mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 15:06:02 +01:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac9625d33a | ||
|
|
2ab9114d2f | ||
|
|
88c68c7068 | ||
|
|
1e178180bb | ||
|
|
fef441c456 | ||
|
|
85a3879a03 | ||
|
|
65813e75e6 | ||
|
|
a9648fb45f | ||
|
|
dec6caa63b | ||
|
|
967682c449 | ||
|
|
301ff2daf8 | ||
|
|
fd8d65166b | ||
|
|
581640c07a | ||
|
|
9fbf0222ad | ||
|
|
753d3eb025 | ||
|
|
815caddb02 | ||
|
|
3c5d5faa9f | ||
|
|
ae640729ca |
@@ -6,7 +6,7 @@ rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aw
|
||||
|
||||
name 'ox_lib'
|
||||
author 'Overextended'
|
||||
version '3.30.9'
|
||||
version '3.31.3'
|
||||
license 'LGPL-3.0-or-later'
|
||||
repository 'https://github.com/communityox/ox_lib'
|
||||
description 'A library of shared functions to utilise in other resources.'
|
||||
|
||||
@@ -39,10 +39,14 @@ local function removePoint(self)
|
||||
points[self.id] = nil
|
||||
end
|
||||
|
||||
local function hasRemovePoint(entry)
|
||||
return entry.remove == removePoint
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local coords = GetEntityCoords(cache.ped)
|
||||
local newPoints = lib.grid.getNearbyEntries(coords, function(entry) return entry.remove == removePoint end) --[[@as CPoint[] ]]
|
||||
local newPoints = lib.grid.getNearbyEntries(coords, hasRemovePoint) --[[@as CPoint[] ]]
|
||||
local cellX, cellY = lib.grid.getCellPosition(coords)
|
||||
cache.coords = coords
|
||||
closestPoint = nil
|
||||
@@ -89,9 +93,11 @@ CreateThread(function()
|
||||
nearbyCount += 1
|
||||
nearbyPoints[nearbyCount] = point
|
||||
|
||||
if point.onEnter and not point.inside then
|
||||
if not point.inside then
|
||||
point.inside = true
|
||||
point:onEnter()
|
||||
if point.onEnter then
|
||||
point:onEnter()
|
||||
end
|
||||
end
|
||||
elseif point.currentDistance then
|
||||
if point.onExit then point:onExit() end
|
||||
|
||||
@@ -123,11 +123,24 @@ local function shuffle(tbl)
|
||||
return tbl
|
||||
end
|
||||
|
||||
|
||||
---@param tbl table
|
||||
---@param fn function(value: any, key: any): any
|
||||
---@return table
|
||||
local function map(tbl, fn)
|
||||
local result = {}
|
||||
for k, v in pairs(tbl) do
|
||||
result[k] = fn(v, k)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
table.contains = contains
|
||||
table.matches = table_matches
|
||||
table.deepclone = table_deepclone
|
||||
table.merge = table_merge
|
||||
table.shuffle = shuffle
|
||||
table.map = map
|
||||
|
||||
local frozenNewIndex = function(self) error(('cannot set values on a frozen table (%s)'):format(self), 2) end
|
||||
local _rawset = rawset
|
||||
|
||||
@@ -7,27 +7,27 @@
|
||||
"confirm": "Confirmer",
|
||||
"more": "Plus...",
|
||||
"settings": {
|
||||
"locale": "Change locale",
|
||||
"locale_description": "Current language: ${language} (%s)",
|
||||
"notification_audio": "Notification audio",
|
||||
"notification_position": "Notification position"
|
||||
"locale": "Changer la langue",
|
||||
"locale_description": "Langue actuelle : ${language} (%s)",
|
||||
"notification_audio": "Audio des notifications",
|
||||
"notification_position": "Position des notifications"
|
||||
},
|
||||
"position": {
|
||||
"bottom": "Bottom",
|
||||
"bottom-left": "Bottom-left",
|
||||
"bottom-right": "Bottom-right",
|
||||
"center-left": "Center-left",
|
||||
"center-right": "Center-right",
|
||||
"top": "Top",
|
||||
"top-left": "Top-left",
|
||||
"top-right": "Top-right"
|
||||
"bottom": "Bas",
|
||||
"bottom-left": "Bas-gauche",
|
||||
"bottom-right": "Bas-droite",
|
||||
"center-left": "Centre-gauche",
|
||||
"center-right": "Centre-droite",
|
||||
"top": "Haut",
|
||||
"top-left": "Haut-gauche",
|
||||
"top-right": "Haut-droite"
|
||||
}
|
||||
},
|
||||
"open_radial_menu": "Open radial menu",
|
||||
"cancel_progress": "Cancel current progress bar",
|
||||
"txadmin_announcement": "Server announcement by %s",
|
||||
"txadmin_dm": "Direct Message from %s",
|
||||
"txadmin_warn": "You have been warned by %s",
|
||||
"txadmin_warn_content": "%s \nAction ID: %s",
|
||||
"txadmin_scheduledrestart": "Scheduled Restart"
|
||||
"open_radial_menu": "Ouvrir le menu radial",
|
||||
"cancel_progress": "Annuler la barre de progression actuelle",
|
||||
"txadmin_announcement": "Annonce serveur par %s",
|
||||
"txadmin_dm": "Message privé de %s",
|
||||
"txadmin_warn": "Vous avez été averti par %s",
|
||||
"txadmin_warn_content": "%s\nID de l'action : %s",
|
||||
"txadmin_scheduledrestart": "Redémarrage programmé"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"": {
|
||||
"name": "@communityox/ox_lib",
|
||||
"dependencies": {
|
||||
"@nativewrappers/client": "^1.7.33",
|
||||
"@nativewrappers/fivem": "^0.0.103",
|
||||
"csstype": "^3.1.3",
|
||||
"fast-printf": "^1.6.9",
|
||||
"typescript": "^5.4.2",
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
"@mantine/utils": ["@mantine/utils@6.0.22", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-RSKlNZvxhMCkOFZ6slbYvZYbWjHUM+PxDQnupIOxIdsTZQQjx/BFfrfJ7kQFOP+g7MtpOds8weAetEs5obwMOQ=="],
|
||||
|
||||
"@nativewrappers/client": ["@nativewrappers/client@1.7.33", "", {}, "sha512-phuBBGdDPxZiZyw5CaFs1XWfvllnEtwATMdLaNucwMofVg/O/FjlP1bTUq4SOm4qhSZ4Zdo351ijHzBSIbZs6g=="],
|
||||
"@nativewrappers/fivem": ["@nativewrappers/fivem@0.0.103", "", {}, "sha512-x0W00Mx9ZN/rTS9XZc5Kf1hjahqRmlo9sPiuJP4kCYeQG4LDJyglXCsHcfNfygGq6WEblG1W2FLgm4MGDn/wHA=="],
|
||||
|
||||
"@radix-ui/number": ["@radix-ui/number@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10" } }, "sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA=="],
|
||||
|
||||
|
||||
120
package/client/resource/addKeybind/index.ts
Normal file
120
package/client/resource/addKeybind/index.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
interface CKeybind extends KeybindProps {
|
||||
currentKey: string;
|
||||
disabled: boolean;
|
||||
isPressed: boolean;
|
||||
hash: number;
|
||||
getCurrentKey(): string;
|
||||
isControlPressed(): boolean;
|
||||
}
|
||||
|
||||
interface KeybindProps {
|
||||
name: string;
|
||||
description: string;
|
||||
defaultMapper?: string;
|
||||
defaultKey?: string;
|
||||
disabled?: boolean;
|
||||
disable?(this: CKeybind, toggle: boolean): void;
|
||||
onPressed?(this: CKeybind): void;
|
||||
onReleased?(this: CKeybind): void;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const keybinds: Record<string, CKeybind> = {};
|
||||
|
||||
class Keybind implements CKeybind {
|
||||
name: string;
|
||||
description: string;
|
||||
defaultMapper?: string;
|
||||
defaultKey?: string;
|
||||
onPressed?: (this: CKeybind) => void;
|
||||
onReleased?: (this: CKeybind) => void;
|
||||
secondaryKey?: string;
|
||||
secondaryMapper?: string;
|
||||
[key: string]: any;
|
||||
|
||||
disabled: boolean = false;
|
||||
isPressed: boolean = false;
|
||||
hash: number;
|
||||
|
||||
constructor(data: KeybindProps) {
|
||||
this.name = data.name;
|
||||
this.description = data.description;
|
||||
this.defaultMapper = data.defaultMapper ?? "keyboard";
|
||||
this.defaultKey = data.defaultKey ?? "";
|
||||
this.secondaryKey = data.secondaryKey;
|
||||
this.secondaryMapper = data.secondaryMapper;
|
||||
|
||||
if (typeof data.disabled === "boolean") this.disabled = data.disabled;
|
||||
this.onPressed = data.onPressed;
|
||||
this.onReleased = data.onReleased;
|
||||
|
||||
this.hash = GetHashKey("+" + this.name) | 0x80000000;
|
||||
}
|
||||
|
||||
get currentKey(): string {
|
||||
return this.getCurrentKey();
|
||||
}
|
||||
|
||||
getCurrentKey(): string {
|
||||
const label = GetControlInstructionalButton(0, this.hash, true);
|
||||
return label.substring(2);
|
||||
}
|
||||
|
||||
isControlPressed(): boolean {
|
||||
return this.isPressed;
|
||||
}
|
||||
|
||||
disable(toggle: boolean): void {
|
||||
this.disabled = toggle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function addKeybind(data: KeybindProps): CKeybind {
|
||||
const kb = new Keybind(data);
|
||||
|
||||
keybinds[kb.name] = kb;
|
||||
|
||||
RegisterCommand("+" + kb.name, () => {
|
||||
if (kb.disabled || IsPauseMenuActive()) return;
|
||||
kb.isPressed = true;
|
||||
kb.onPressed?.call(kb);
|
||||
}, false);
|
||||
|
||||
RegisterCommand("-" + kb.name, () => {
|
||||
if (kb.disabled || IsPauseMenuActive()) return;
|
||||
kb.isPressed = false;
|
||||
kb.onReleased?.call(kb);
|
||||
}, false);
|
||||
|
||||
RegisterKeyMapping(
|
||||
"+" + kb.name,
|
||||
kb.description,
|
||||
kb.defaultMapper ?? "keyboard",
|
||||
kb.defaultKey ?? ""
|
||||
);
|
||||
|
||||
if (kb.secondaryKey) {
|
||||
RegisterKeyMapping(
|
||||
"~!+" + kb.name,
|
||||
kb.description,
|
||||
kb.secondaryMapper ?? kb.defaultMapper ?? "keyboard",
|
||||
kb.secondaryKey
|
||||
);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
emit("chat:removeSuggestion", `/+${kb.name}`);
|
||||
emit("chat:removeSuggestion", `/-${kb.name}`);
|
||||
}, 500);
|
||||
|
||||
return kb;
|
||||
}
|
||||
|
||||
export function getKeybind(name: string): CKeybind | undefined {
|
||||
return keybinds[name];
|
||||
}
|
||||
|
||||
export function getAllKeybinds(): Readonly<Record<string, CKeybind>> {
|
||||
return keybinds;
|
||||
}
|
||||
@@ -14,3 +14,4 @@ export * from './vehicleProperties';
|
||||
export * from './callback';
|
||||
export * from './points';
|
||||
export * from './dui';
|
||||
export * from './addKeybind';
|
||||
|
||||
@@ -10,7 +10,7 @@ type NotificationPosition =
|
||||
| 'bottom-left'
|
||||
| 'center-right'
|
||||
| 'center-left';
|
||||
type NotificationType = 'inform' | 'error' | 'success';
|
||||
type NotificationType = 'inform' | 'error' | 'success' | 'warning';
|
||||
type IconAnimation = 'spin' | 'spinPulse' | 'spinReverse' | 'pulse' | 'beat' | 'fade' | 'beatFade' | 'bounce' | 'shake';
|
||||
|
||||
interface NotifyProps {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Vector3 } from '@nativewrappers/client';
|
||||
import { Vector3 } from '@nativewrappers/fivem';
|
||||
import { cache } from '../cache';
|
||||
|
||||
let points: Point[] = [];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@communityox/ox_lib",
|
||||
"author": "Overextended",
|
||||
"version": "3.30.9",
|
||||
"version": "3.31.3",
|
||||
"description": "JS/TS wrapper for ox_lib exports",
|
||||
"main": "./shared/index.js",
|
||||
"types": "./shared/index.d.ts",
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"license": "LGPL-3.0",
|
||||
"dependencies": {
|
||||
"@nativewrappers/client": "^1.7.33",
|
||||
"@nativewrappers/fivem": "^0.0.103",
|
||||
"csstype": "^3.1.3",
|
||||
"fast-printf": "^1.6.9",
|
||||
"typescript": "^5.4.2"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { cache } from '../cache/index';
|
||||
import { context } from 'shared';
|
||||
import { Vector3 } from "@nativewrappers/client";
|
||||
import { context } from '../../index';
|
||||
import { Vector3 } from "@nativewrappers/fivem";
|
||||
|
||||
interface NearbyVehicle {
|
||||
vehicle: number;
|
||||
|
||||
55
resource/cache/client.lua
vendored
55
resource/cache/client.lua
vendored
@@ -29,40 +29,43 @@ local GetCurrentPedWeapon = GetCurrentPedWeapon
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local ped = PlayerPedId()
|
||||
cache:set('ped', ped)
|
||||
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
-- If the player's ped is changed, the ped value may return 0 during the transition. If the value is 0, skip all checks.
|
||||
if ped ~= 0 then
|
||||
cache:set('ped', ped)
|
||||
|
||||
if vehicle > 0 then
|
||||
if vehicle ~= cache.vehicle then
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
|
||||
if vehicle > 0 then
|
||||
if vehicle ~= cache.vehicle then
|
||||
cache:set('seat', false)
|
||||
end
|
||||
|
||||
cache:set('vehicle', vehicle)
|
||||
|
||||
if not cache.seat or GetPedInVehicleSeat(vehicle, cache.seat) ~= ped then
|
||||
for i = -1, GetVehicleMaxNumberOfPassengers(vehicle) - 1 do
|
||||
if GetPedInVehicleSeat(vehicle, i) == ped then
|
||||
cache:set('seat', i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
cache:set('vehicle', false)
|
||||
cache:set('seat', false)
|
||||
end
|
||||
|
||||
cache:set('vehicle', vehicle)
|
||||
|
||||
if not cache.seat or GetPedInVehicleSeat(vehicle, cache.seat) ~= ped then
|
||||
for i = -1, GetVehicleMaxNumberOfPassengers(vehicle) - 1 do
|
||||
if GetPedInVehicleSeat(vehicle, i) == ped then
|
||||
cache:set('seat', i)
|
||||
break
|
||||
end
|
||||
end
|
||||
if cache.game == 'redm' then
|
||||
local mount = GetMount(ped)
|
||||
local onMount = IsPedOnMount(ped)
|
||||
cache:set('mount', onMount and mount or false)
|
||||
end
|
||||
else
|
||||
cache:set('vehicle', false)
|
||||
cache:set('seat', false)
|
||||
|
||||
local hasWeapon, currentWeapon = GetCurrentPedWeapon(ped, true)
|
||||
cache:set('weapon', (hasWeapon and currentWeapon ~= 0) and currentWeapon or false)
|
||||
end
|
||||
|
||||
if cache.game == 'redm' then
|
||||
local mount = GetMount(ped)
|
||||
local onMount = IsPedOnMount(ped)
|
||||
cache:set('mount', onMount and mount or false)
|
||||
end
|
||||
|
||||
local hasWeapon, currentWeapon = GetCurrentPedWeapon(ped, true)
|
||||
|
||||
cache:set('weapon', hasWeapon and currentWeapon or false)
|
||||
|
||||
Wait(100)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -30,9 +30,12 @@ local input
|
||||
---@field searchable? boolean
|
||||
---@field description? string
|
||||
---@field maxSelectedValues? number
|
||||
---@field minLength? number
|
||||
---@field maxLength? number
|
||||
|
||||
---@class InputDialogOptionsProps
|
||||
---@field allowCancel? boolean
|
||||
---@field size? 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
|
||||
---@param heading string
|
||||
---@param rows string[] | InputDialogRowProps[]
|
||||
|
||||
@@ -26,6 +26,7 @@ export const debugCustomNotification = () => {
|
||||
title: 'Error',
|
||||
description: 'Notification description',
|
||||
type: 'error',
|
||||
position: "bottom"
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -103,7 +103,7 @@ const InputDialog: React.FC = () => {
|
||||
centered
|
||||
closeOnEscape={fields.options?.allowCancel !== false}
|
||||
closeOnClickOutside={false}
|
||||
size="xs"
|
||||
size={fields.options?.size || 'xs'}
|
||||
styles={{ title: { textAlign: 'center', width: '100%', fontSize: 18 } }}
|
||||
title={fields.heading}
|
||||
withCloseButton={false}
|
||||
|
||||
@@ -24,6 +24,8 @@ const TextareaField: React.FC<Props> = (props) => {
|
||||
autosize={props.row.autosize}
|
||||
minRows={props.row.min}
|
||||
maxRows={props.row.max}
|
||||
minLength={props.row.minLength}
|
||||
maxLength={props.row.maxLength}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ const getAnimation = (visible: boolean, position: string) => {
|
||||
animation = { from: 'X(0px)', to: 'X(-100%)' };
|
||||
} else if (position === 'top-center') {
|
||||
animation = { from: 'Y(0px)', to: 'Y(-100%)' };
|
||||
} else if (position === 'bottom') {
|
||||
} else if (position === 'bottom-center') {
|
||||
animation = { from: 'Y(0px)', to: 'Y(100%)' };
|
||||
} else {
|
||||
animation = { from: 'X(0px)', to: 'X(100%)' };
|
||||
|
||||
@@ -5,6 +5,7 @@ export interface InputProps {
|
||||
rows: Array<IInput | ICheckbox | ISelect | INumber | ISlider | IColorInput | IDateInput | ITextarea | ITimeInput>;
|
||||
options?: {
|
||||
allowCancel?: boolean;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,4 +77,6 @@ export interface ITextarea extends BaseField<'textarea', string> {
|
||||
autosize?: boolean;
|
||||
min?: number;
|
||||
max?: number;
|
||||
minLength?: number;
|
||||
maxLength?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user