diff --git a/client/js/compatibility/utils.js b/client/js/compatibility/utils.js index bc8a4454c..9b69a2132 100644 --- a/client/js/compatibility/utils.js +++ b/client/js/compatibility/utils.js @@ -5,6 +5,8 @@ /** @type {typeof import("./../../../shared/js/utils.js")} */ const { assert, waitFor, assertRGBA, assertVector2, assertVector3 } = requireBinding("shared/utils.js"); +const { SharedUtils } = requireBinding("shared/compatibility/utils.js"); + requireBinding("shared/timers.js"); requireBinding("shared/classes/rgba.js"); requireBinding("shared/classes/vector.js"); @@ -198,7 +200,7 @@ class Marker { } } -class Utils { +class Utils extends SharedUtils { static async requestModel(model, timeout = 5000) { assert(typeof model === "string" || typeof model === "number", "Expected a string or number as first argument"); assert(typeof timeout === "number", "Expected a number as second argument"); diff --git a/shared/js/compatibility/classes/resource.js b/shared/js/compatibility/classes/resource.js new file mode 100644 index 000000000..a9bc596b4 --- /dev/null +++ b/shared/js/compatibility/classes/resource.js @@ -0,0 +1,18 @@ +/// +/// +/// +// import * as alt from "@altv/server"; + +// requireBinding("shared/entity.js"); + +class Resource extends alt.Resource { + get valid() { + return !!alt.Resource.get(super.name); + } + + static getByName(name) { + return alt.Resource.get(name); + } +} + +cppBindings.registerCompatibilityExport("Resource", Resource); diff --git a/shared/js/compatibility/utils.js b/shared/js/compatibility/utils.js new file mode 100644 index 000000000..4cca6c1c0 --- /dev/null +++ b/shared/js/compatibility/utils.js @@ -0,0 +1,84 @@ +/// +/// +/// +// import * as alt from "@altv/server"; + +/** @type {typeof import("./../../../shared/js/utils.js")} */ +const { assertIsType } = requireBinding("shared/utils.js"); + +requireBinding("shared/events/console.js"); + +class Timer { + constructor(callback, ms, once) { + assertIsType(callback, "function"); + assertIsType(ms, "number"); + + if (once) return new alt.Timers.setTimeout(callback, ms); + return new alt.Timers.setInterval(callback, ms); + } +} + +class ConsoleCommand { + static registeredCommands = new Map(); + + #commandName; + #callback; + + constructor(name, callback) { + assertIsType(name, "string"); + assertIsType(callback, "function"); + + name = name.toLowerCase(); + + this.#commandName = name; + this.#callback = callback; + + const handlers = ConsoleCommand.registeredCommands.get(name) ?? []; + handlers.push(callback); + ConsoleCommand.registeredCommands.set(name, handlers); + } + + get callback() { + return this.#callback; + } + + destroy() { + const registeredCommands = (ConsoleCommand.registeredCommands.get(this.#commandName) ?? []).filter((command) => command != this); + + if (registeredCommands.length) ConsoleCommand.registeredCommands.set(this.#commandName, registeredCommands); + else Keybind.registeredHandlers.delete(this.keyCode); + } +} + +alt.Events.onConsoleCommand(({ command, args }) => { + command = command.toLowerCase(); + + if (!ConsoleCommand.registeredCommands.has(command)) return; + + const handlers = ConsoleCommand.registeredCommands.get(command); + + for (const handler of handlers) { + handler?.(...args); + } +}); + +export class SharedUtils { + static wait = alt.Utils.wait; + static waitFor = alt.Utils.waitFor; + + static inspect = alt.Utils.inspect; + static assert = alt.Utils.assert; + + static ConsoleCommand = ConsoleCommand; + + static Timer = Timer; + static Timeout = alt.Timers.Timeout; + static Interval = alt.Timers.Interval; + static NextTick = alt.Timers.NextTick; + static EveryTick = alt.Timers.EveryTick; +} + +if (alt.isServer) { + // NOTE (xLuxy): Server has no Utilities + cppBindings.registerCompatibilityExport("Utils", SharedUtils); +}