### Install @infernus/gps and @infernus/core Source: https://github.com/dockfries/infernus/blob/main/packages/gps/README.md Install the necessary packages using pnpm. Ensure you have @infernus/core installed as well. ```sh pnpm add @infernus/core @infernus/gps ``` -------------------------------- ### Enable and Handle Drift Events Source: https://github.com/dockfries/infernus/blob/main/packages/drift-detection/README.md This example demonstrates how to enable drift detection for all players, create a vehicle, and then listen for and log player start, update, and end drift events. ```ts import { GameMode, Vehicle } from "@infernus/core"; import { Drift, DriftEvent } from "@infernus/drift-detection"; GameMode.onInit(({ next }) => { const veh = new Vehicle({ modelId: 562, x: 3, y: 3, z: 3, color: [-1, -1], zAngle: 0, }); veh.create(); veh.addComponent(1010); Drift.enableDetection(-1); return next(); }); DriftEvent.onPlayerStart(({ player, next }) => { console.log(player.id); return next(); }); DriftEvent.onPlayerUpdate(({ player, driftAngle, speed, time, next }) => { console.log(player.id, driftAngle, speed, time); return next(); }); DriftEvent.onPlayerEnd(({ player, reason, distance, time, next }) => { console.log(player.id, reason, distance, time); return next(); }); ``` -------------------------------- ### Install @infernus/query Source: https://github.com/dockfries/infernus/blob/main/packages/query/README.md Install the @infernus/query package using pnpm. ```sh pnpm add @infernus/query ``` -------------------------------- ### Install @infernus/qrcode Source: https://github.com/dockfries/infernus/blob/main/packages/qrcode/README.md Install the @infernus/core and @infernus/qrcode packages using pnpm. ```sh pnpm add @infernus/core @infernus/qrcode ``` -------------------------------- ### Initialize and Spawn FCNPC Source: https://github.com/dockfries/infernus/blob/main/packages/fcnpc/README.md Initialize an FCNPC instance and spawn it at a specific location. This example demonstrates basic FCNPC setup within the samp-node event system. ```ts import { FCNPC, FCNPCEvent } from "@infernus/fcnpc"; FCNPCEvent.onInit(({ next }) => { const fcnpc = new FCNPC("npc_name").create(); fcnpc.spawn(0, 1697.7418, -1600.1525, 13.5469); return next(); }); ``` -------------------------------- ### Install @infernus/samp-voice Source: https://github.com/dockfries/infernus/blob/main/packages/samp-voice/README.md Install the package and its core dependency using pnpm. ```sh pnpm add @infernus/core @infernus/samp-voice ``` -------------------------------- ### Install Dependencies Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Run this command to install all project dependencies using pnpm. ```sh pnpm install ``` -------------------------------- ### Install @infernus/rec Source: https://github.com/dockfries/infernus/blob/main/packages/rec/README.md Install the @infernus/rec package using pnpm. ```sh pnpm add @infernus/rec ``` -------------------------------- ### Serve the Application Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Starts the server after the production build is complete. ```sh pnpm serve ``` -------------------------------- ### Initial Full Build with pnpm Source: https://github.com/dockfries/infernus/blob/main/CONTRIBUTING.md Execute this command for the initial setup to build all project packages. ```bash pnpm -w build-all ``` -------------------------------- ### Install @infernus/progress Source: https://github.com/dockfries/infernus/blob/main/packages/progress/README.md Install the progress bar package along with its core dependency. ```sh pnpm add @infernus/core @infernus/progress ``` -------------------------------- ### Install and Use Official Filterscript Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/use.md Install the `@infernus/fs` package to use pre-built filterscripts. This example demonstrates how to use the `A51Base` filterscript with custom options. ```bash pnpm install @infernus/fs ``` -------------------------------- ### Install @infernus/raknet Source: https://github.com/dockfries/infernus/blob/main/packages/raknet/README.md Install the @infernus/core and @infernus/raknet packages using pnpm. ```sh pnpm add @infernus/core @infernus/raknet ``` -------------------------------- ### Install @infernus/e-selection Source: https://github.com/dockfries/infernus/blob/main/packages/e-selection/README.md Install the e-selection package along with its core dependency. ```sh pnpm add @infernus/core @infernus/e-selection ``` -------------------------------- ### SA-MP Voice Example with @infernus/samp-voice Source: https://github.com/dockfries/infernus/blob/main/packages/samp-voice/README.md This example demonstrates how to set up global and local voice streams, handle player connections and disconnections, and manage voice activation keys. It includes attaching players to streams and checking for plugin and microphone availability. ```ts import { GameMode, Player, PlayerEvent, } from "@infernus/core"; import { DynamicLocalPlayerStream, SampVoice, SampVoiceEvent, SampVoiceGlobalStream, SampVoiceLocalStream, SV_INFINITY, SV_NULL, } from "@infernus/samp-voice"; let global_stream: SampVoiceGlobalStream | null = null; const local_stream = new Map(); /* The public OnPlayerActivationKeyPress and OnPlayerActivationKeyRelease are needed in order to redirect the player's audio traffic to the corresponding streams when the corresponding keys are pressed. */ SampVoiceEvent.onPlayerActivationKeyPress(({ player, keyId, next }) => { // Attach player to local stream as speaker if 'B' key is pressed if (keyId === 0x42 && local_stream.has(player)) { local_stream.get(player)!.attachSpeaker(player); } // Attach the player to the global stream as a speaker if the 'Z' key is pressed if (keyId === 0x5a && global_stream) { global_stream.attachSpeaker(player); } return next(); }); SampVoiceEvent.onPlayerActivationKeyRelease(({ player, keyId, next }) => { // Detach the player from the local stream if the 'B' key is released if (keyId === 0x42 && local_stream.has(player)) { local_stream.get(player)!.detachSpeaker(player); } // Detach the player from the global stream if the 'Z' key is released if (keyId === 0x5a && global_stream) { global_stream.detachSpeaker(player); } return next(); }); PlayerEvent.onConnect(({ player, next }) => { // Checking for plugin availability if (SampVoice.getVersion(player) === SV_NULL) { player.sendClientMessage(-1, "Could not find plugin sampvoice."); } // Checking for a microphone else if (SampVoice.hasMicro(player) === false) { player.sendClientMessage(-1, "The microphone could not be found."); } // Create a local stream with an audibility distance of 40.0, an unlimited number of listeners // and the name 'Local' (the name 'Local' will be displayed in red in the players' speakerlist) else { const stream = new DynamicLocalPlayerStream( 40.0, SV_INFINITY, player, 0xff0000ff, "Local", ); if (stream.ptr === SV_NULL) { return next(); } local_stream.set(player, stream); player.sendClientMessage( -1, "Press Z to talk to global chat and B to talk to local chat.", ); // Attach the player to the global stream as a listener if (global_stream) { global_stream.attachListener(player); } // Assign microphone activation keys to the player SampVoice.addKey(player, 0x42); SampVoice.addKey(player, 0x5a); } return next(); }); PlayerEvent.onDisconnect(({ player, next }) => { // Removing the player's local stream after disconnecting if (local_stream.has(player)) { local_stream.get(player)!.detachListener(player); local_stream.get(player)!.detachSpeaker(player); local_stream.get(player)!.delete(); local_stream.delete(player); } return next(); }); GameMode.onInit(({ next }) => { // Uncomment the line to enable debug mode // SampVoice.debug(true); local_stream.clear(); global_stream = new SampVoiceGlobalStream(0xffff0000, "Global"); return next(); }); GameMode.onExit(({ next }) => { if (global_stream) { global_stream.detachAllListeners(); global_stream.detachAllSpeakers(); global_stream.delete(); global_stream = null; } local_stream.clear(); return next(); }); ``` -------------------------------- ### Install @infernus/core and @infernus/fs Source: https://github.com/dockfries/infernus/blob/main/packages/filterscript/README.md Install the necessary packages using pnpm. These packages are required to use the filterscripts. ```sh pnpm add @infernus/core @infernus/fs ``` -------------------------------- ### Install @infernus/mapandreas Source: https://github.com/dockfries/infernus/blob/main/packages/mapandreas/README.md Install the package and its core dependency using pnpm. ```sh pnpm add @infernus/core @infernus/mapandreas ``` -------------------------------- ### Install @infernus/nex-ac Source: https://github.com/dockfries/infernus/blob/main/packages/nex-ac/README.md Install the necessary packages for @infernus/nex-ac, including core, raknet, and nex-ac itself. ```sh pnpm add @infernus/core @infernus/raknet @infernus/nex-ac ``` -------------------------------- ### Install @infernus/weapon-config Source: https://github.com/dockfries/infernus/blob/main/packages/weapon-config/README.md Install the necessary packages for @infernus/weapon-config, including core and raknet. ```sh pnpm add @infernus/core @infernus/raknet @infernus/weapon-config ``` -------------------------------- ### Create and Get Dynamic Object Position with @infernus/streamer Source: https://github.com/dockfries/infernus/blob/main/packages/streamer/README.md Example of creating a dynamic object and retrieving its position within an OnGameModeInit callback. Ensure you have the necessary imports from @infernus/streamer. ```ts import { CreateDynamicObject, GetDynamicObjectPos } from "@infernus/streamer"; // In a callback event, such as OnGameModeInit samp.on("OnGameModeInit", () => { const exampleObj = CreateDynamicObject( 2587, 2001.195679, 1547.113892, 14.2834, 0.0, 0.0, 96.0 ); const { x, y, z } = GetDynamicObjectPos(exampleObj); console.log(x, y, z); }); ``` -------------------------------- ### Install @infernus/map-loader Source: https://github.com/dockfries/infernus/blob/main/packages/map-loader/README.md Install the necessary packages for map loading functionality. ```sh pnpm add @infernus/core @infernus/map-loader ``` -------------------------------- ### Install @infernus/streamer Source: https://github.com/dockfries/infernus/blob/main/packages/streamer/README.md Install the streamer package using pnpm. If you are using @infernus/core, you do not need to install this package separately. ```sh pnpm add @infernus/streamer ``` -------------------------------- ### Create Infernus Project via CLI Source: https://context7.com/dockfries/infernus/llms.txt Use the `@infernus/create-app` CLI to scaffold a new Infernus project. Dependencies can be added and installed using specific commands. ```sh # Create a project interactively via CLI pnpm dlx @infernus/create-app@latest create # Or install globally and use directly pnpm add @infernus/create-app -g infernus create my-gamemode # Add open.mp and streamer plugin dependencies infernus add openmultiplayer/open.mp samp-incognito/samp-streamer-plugin@^2.9.6 # Add a component dependency (e.g., RakNet) infernus add katursis/Pawn.RakNet@^1.6.0-omp --component # Install all declared dependencies (like sampctl ensure) infernus install # Configure a GitHub token to avoid API rate limits infernus config gh_token ``` -------------------------------- ### Install @infernus/fcnpc Source: https://github.com/dockfries/infernus/blob/main/packages/fcnpc/README.md Install the necessary packages for using @infernus/fcnpc with samp-node. ```sh pnpm add @infernus/core @infernus/fcnpc ``` -------------------------------- ### Install @infernus/colandreas Source: https://github.com/dockfries/infernus/blob/main/packages/colandreas/README.md Install the @infernus/core and @infernus/colandreas packages using pnpm. ```sh pnpm add @infernus/core @infernus/colandreas ``` -------------------------------- ### Add @infernus/core and @infernus/cef to Project Source: https://github.com/dockfries/infernus/blob/main/packages/cef/README.md Install the necessary packages for @infernus/core and @infernus/cef using pnpm. ```sh pnpm add @infernus/core @infernus/cef ``` -------------------------------- ### Install @infernus/distance Source: https://github.com/dockfries/infernus/blob/main/packages/distance/README.md Install the @infernus/distance package along with @infernus/core using pnpm. ```sh pnpm add @infernus/core @infernus/distance ``` -------------------------------- ### Create Infernus App with CLI Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Use this command to create a new Infernus project via the command line prompts. Ensure you have pnpm installed. ```sh pnpm dlx @infernus/create-app@latest create ``` -------------------------------- ### Install Dependencies Source: https://github.com/dockfries/infernus/blob/main/packages/drift-detection/README.md Install the necessary packages for drift detection. This includes the core infernus package and the drift-detection package itself. ```sh pnpm add @infernus/core @infernus/drift-detection ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/dockfries/infernus/blob/main/CONTRIBUTING.md Use this command to install project dependencies managed by pnpm. ```bash pnpm -w install ``` -------------------------------- ### Run Development Mode Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Starts the compilation process, monitors for changes, and automatically restarts the server in development mode. ```sh pnpm dev ``` -------------------------------- ### Create and Manage QR Code Objects Source: https://github.com/dockfries/infernus/blob/main/packages/qrcode/README.md This example demonstrates how to create a QR code object at the player's location, send a message with its ID, update its material after a delay, and destroy it after another delay. It utilizes functions from @infernus/qrcode and @infernus/core. ```ts import { generateQRText, createQRObject, setObjectQRMaterial, } from "@infernus/qrcode"; import { PlayerEvent } from "@infernus/core"; PlayerEvent.onCommandText("qr", ({ player, subcommand, next }) => { const { x, y, z } = player.getPos(); const qrText = generateQRText("lmao"); const obj = createQRObject( qrText, { x: x + 1, y: y + 1, z: z + 1, rx: 0, ry: 0, rz: 0, playerId: player.id, drawDistance: 300, }, { backColor: 0xff000000, }, ); Streamer.update(player, StreamerItemTypes.OBJECT); player.sendClientMessage(-1, `qrcode: created id: ${obj.id}`); console.log(qrText); setTimeout(() => { const qrText2 = generateQRText("oaml"); setObjectQRMaterial(obj, qrText2, { backColor: 0xffffff00, }); player.sendClientMessage(-1, `qrcode: updated id: ${obj.id}`); }, 10 * 1000); setTimeout(() => { player.sendClientMessage(-1, `qrcode: destroyed id: ${obj.id}`); obj.destroy(); }, 20 * 1000); return next(); }); ``` -------------------------------- ### Manage Infernus Dependencies with CLI Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Commands for managing project dependencies, including adding, installing, removing, and updating packages. Use the '-p' flag for production mode installs. ```sh # Install the CLI tool globally pnpm add @infernus/create-app -g # If installed globally pnpm update @infernus/create-app -g # Create a project infernus create # Install one or more dependencies, # all operations' dependencies can be followed by a version number, # it is similar to the syntax of npm packages. infernus add openmultiplayer/open.mp samp-incognito/samp-streamer-plugin@^2.9.6 # install a component dependency infernus add katursis/Pawn.RakNet@^1.6.0-omp --component # production mode install deps (not copy inc files) infernus add samp-incognito/samp-streamer-plugin@^2.9.6 -p # Install all existing dependencies, similar to sampctl ensure infernus install # same as above, production mode install deps (not copy inc files) infernus install -p # Uninstall one or more dependencies infernus remove openmultiplayer/open.mp samp-incognito/samp-streamer-plugin infernus remove katursis/Pawn.RakNet # Update a dependency (update global cache and apply to current directory) infernus update openmultiplayer/open.mp # Update a dependency to a specific version infernus update openmultiplayer/open.mp@^1.2.0.2670 ``` -------------------------------- ### Promise-based Command Text Event Handling Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Handle player command text events using Promises. This example also delays sending a message by 1 second, but the `async/await` syntax is recommended. ```typescript import { Player, PlayerEvent } from "@infernus/core"; // In order to demonstrate the false async const fakePromise = () => { return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); }; // Promise is OK, but it is not recommended PlayerEvent.onCommandText("promise", ({ player, next }) => { return new Promise((resolve) => { fakePromise().then(() => { player.sendClientMessage( "#fff", "Send a message after a delay of 1 second.", ); resolve(); return next(); }); }); }); ``` -------------------------------- ### Async Command Text Event Handling Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Handle player command text events asynchronously using `async/await`. This example delays sending a message by 1 second. ```typescript import { Player, PlayerEvent } from "@infernus/core"; // In order to demonstrate the false async const fakePromise = () => { return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); }; // You can use async grammar sugar, which is also the recommended grammar PlayerEvent.onCommandText("async", async ({ player, next }) => { await fakePromise(); player.sendClientMessage("#fff", "Send a message after a delay of 1 second."); return next(); }); ``` -------------------------------- ### Configure and Handle Cheats with nex-ac Source: https://github.com/dockfries/infernus/blob/main/packages/nex-ac/README.md Configure nex-ac settings and define a callback to handle detected cheats. This example shows how to block IPs, send custom messages based on cheat codes, and kick players with desync. ```ts import { GameMode } from '@infernus/core' import { $t, antiCheatKickWithDesync, defineNexACConfig, onCheatDetected } from '@infernus/nex-ac' // other imports and code defineNexACConfig(() => { return { LOCALE: 'en_US', DEBUG: true, } }) onCheatDetected(({ player, ipAddress, type, code, next }) => { if (type) { GameMode.blockIpAddress(ipAddress, 0) return next() } switch (code) { case 5: case 6: case 11: case 14: case 22: case 32: { return next() } case 40: { player.sendClientMessage(-1, $t('MAX_CONNECTS_MSG', null, player.locale)) break } case 41: { player.sendClientMessage(-1, $t('UNKNOWN_CLIENT_MSG', null, player.locale)) break } default: { player.sendClientMessage(-1, $t('KICK_MSG', [code], player.locale)) break } } antiCheatKickWithDesync(player, code) return next() }) ``` -------------------------------- ### Set Player GPS and Handle Map Clicks Source: https://github.com/dockfries/infernus/blob/main/packages/gps/README.md This example demonstrates how to set a player's GPS destination when they click on the map. It uses PlayerEvent.onClickMap to capture the click coordinates and set the Waze GPS destination. Ensure the Waze GPS polyfill is active. ```ts import { WazeEvent, isValidWazeGPS, setPlayerWaze, stopWazeGPS } from "@infernus/gps"; import { PlayerEvent } from "@infernus/core"; PlayerEvent.onClickMap(({ player, fX, fY, fZ, next }) => { player.sendClientMessage(-1, "GPS set!"); setPlayerWaze(player, fX, fY, fZ); return next(); }); ``` -------------------------------- ### Get and Manage Player Instances Source: https://context7.com/dockfries/infernus/llms.txt Retrieve all connected players using `Player.getInstances()` or a specific player by their ID using `Player.getInstance(id)`. Check connection status before interacting with a player instance. ```typescript // Get all online players const players = Player.getInstances(); console.log(`Online: ${players.length}`); // Retrieve specific player by ID const player0 = Player.getInstance(0); if (player0?.isConnected()) { player0.kick(); } ``` -------------------------------- ### Clone Infernus Starter Project Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Instructions for cloning the infernus-starter project using Git, with options for HTTPS or SSH protocols and a specific branch for RakNet. ```sh # Clone the repository through https protocol. git clone https://github.com/dockfries/infernus-starter.git # or use ssh protocol. git clone git@github.com:dockfries/infernus-starter.git # If you need raknet, clone the raknet branch # git clone https://github.com/dockfries/infernus-starter.git -b raknet # or use ssh protocol. # git clone git@github.com:dockfries/infernus-starter.git -b raknet # you can also download the repository directly from the github page. # enter the project root directory. cd infernus-starter # modify the rcon password in config.json. vim config.json # you don't necessarily need to use vim, any editor is fine. # "rcon": { ``` -------------------------------- ### Registering Player Commands Source: https://context7.com/dockfries/infernus/llms.txt Demonstrates how to register simple commands, commands with subcommands, multi-alias commands, and control case sensitivity. ```APIDOC ## Player Commands (`onCommandText`) Register slash commands with built-in subcommand support, aliases, case-sensitivity control, and before/after/error guards. ```ts import { Player, PlayerEvent, GameMode } from "@infernus/core"; // Simple command PlayerEvent.onCommandText("help", ({ player, next }) => { player.sendClientMessage("#fff", "Commands: /help, /pos, /heal"); return next(); }); // Command with subcommands PlayerEvent.onCommandText("help teleport", ({ player, next }) => { player.sendClientMessage("#fff", "Use /tp to teleport."); return next(); }); // Multi-alias command with subcommand args PlayerEvent.onCommandText(["msg", "message"], ({ player, subcommand, next }) => { if (subcommand[0] === "global") { Player.sendClientMessageToAll("#ff0", `[GLOBAL] ${player.getName()}: ${subcommand.slice(1).join(" ")}`); return next(); } next(); return false; // triggers error guard }); // Case-sensitive command registration GameMode.enableCmdCaseSensitive(); PlayerEvent.onCommandText("Admin", ({ player, next }) => { if (!player.isAdmin()) { player.sendClientMessage("#f00", "Access denied."); return next(); } player.sendClientMessage("#0f0", "Admin menu opened."); return next(); }); GameMode.disableCmdCaseSensitive(); // Per-command case sensitivity override PlayerEvent.onCommandText({ caseSensitive: true, command: "SUDO", run({ player, next }) { player.sendClientMessage("#ff0", "SUDO executed."); return next(); }}); // Before guard — runs before onCommandText PlayerEvent.onCommandReceived(({ player, command, next }) => { console.log(`${player.getName()} issued command: ${command}`); return next(); }); // Error guard — fires when command is unknown or guard returns false PlayerEvent.onCommandError(({ player, command, error, next }) => { player.sendClientMessage("#f00", `Unknown command: ${command} (${error.msg})`); next(); return true; // suppress default behavior }); ``` ``` -------------------------------- ### Build Packages with pnpm Source: https://github.com/dockfries/infernus/blob/main/CONTRIBUTING.md Run this command to build the project packages using pnpm. ```bash pnpm -w build ``` -------------------------------- ### Build for Production Source: https://github.com/dockfries/infernus/blob/main/docs/quick-start.md Compiles the project for a production environment. ```sh pnpm build ``` -------------------------------- ### Handle Incoming Connections Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Listen for new player connections and log their details. The `next()` function should be called to allow the connection to proceed. ```typescript import { GameMode } from "@infernus/core"; GameMode.onIncomingConnection(({ next, playerId, ipAddress, port }) => { console.log( `player id:${playerId},ip:${ipAddress},port:${port} try to connect`, ); return next(); }); ``` -------------------------------- ### Add @infernus/types to Development Dependencies Source: https://github.com/dockfries/infernus/blob/main/packages/types/README.md Install the @infernus/types package as a development dependency using pnpm. ```sh pnpm add -D @infernus/types ``` -------------------------------- ### Initialize GameMode Lifecycle Events Source: https://context7.com/dockfries/infernus/llms.txt Set up initial game server configurations like weather, time, gravity, and game mode text within the `GameMode.onInit` event. `GameMode.onExit` handles shutdown logic, and `GameMode.onIncomingConnection` logs connection attempts. ```typescript import { GameMode } from "@infernus/core"; GameMode.onInit(({ next }) => { GameMode.setWeather(10); // sunny weather GameMode.setWorldTime(12); // noon GameMode.setGravity(0.008); // default gravity GameMode.setGameModeText("My Server"); GameMode.supportAllNickname(); // allow all Unicode nicknames console.log("GameMode initialized."); return next(); }); GameMode.onExit(({ next }) => { console.log("GameMode exiting."); return next(); }); GameMode.onIncomingConnection(({ playerId, ipAddress, port, next }) => { console.log(`Incoming connection: player ${playerId} from ${ipAddress}:${port}`); return next(); }); ``` -------------------------------- ### Get Player Instances Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Retrieve all player instances or a specific player instance by ID. This is useful for iterating over players or accessing a single player's object. ```typescript import { Player, PlayerEvent } from "@infernus/core"; PlayerEvent.onConnect(({ player, next }) => { const players = Player.getInstances(); // Get an array of all player instances players.forEach((p) => { p.sendClientMessage("#fff", `player ${player.getName()} connected`); }); const player = Player.getInstance(0); // Get the instance of a player whose id is 0 console.log(player); return next(); }); ``` -------------------------------- ### Configure Weapon Settings Source: https://github.com/dockfries/infernus/blob/main/packages/weapon-config/README.md Define weapon configuration settings and initialize game mode event handlers. Ensure nex-ac is imported before weapon-config if used. ```ts // if you using nex-ac, import it before weapon-config import { GameMode } from "@infernus/core"; import { defineWeaponConfig, setVehiclePassengerDamage, setKnifeSync, } from "@infernus/weapon-config"; // other imports and code defineWeaponConfig(() => { return { DEBUG: true, }; }); GameMode.onInit(({ next }) => { setVehiclePassengerDamage(true); setKnifeSync(true); return next(); }); ``` -------------------------------- ### Defining and Using a Custom Event Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Define a custom event using `defineEvent` to extend Infernus functionality. This example shows how to trigger a custom 'OnPlayerDanger' event and handle it. ```typescript import type { Player } from "@infernus/core"; import { defineEvent, PlayerEvent } from "@infernus/core"; const healthDangerSet = new Set(); const [onPlayerDanger, trigger] = defineEvent({ // Only the commonly used parts are listed isNative: false, // It is not a native event, that is, our custom event. // If it is true, it means the native event in pwn or the native event of the plugin. name: "OnPlayerDanger", // Please raise a unique, do not conflict with the existing event name, usually in this format defaultValue: true, // Define the default return value of middleware as true // If your custom event has callback parameters, be sure to write beforeEach to enhance the ts type prompt // BeforeEach is executed before all the middleware is executed to enhance the parameters beforeEach(player: Player, health: number) { // You are required to return an object return { player, health }; }, // AfterEach is used to execute after all middleware is executed (waiting for all async ones to finish) afterEach({ player, health }) {} }); PlayerEvent.onUpdate(({ player, next }) => { const isDanger = healthDangerSet.has(player); const health = player.getHealth(); if (!isDanger && health <= 10) { healthDangerSet.add(player); const ret = trigger(player, health); if (!ret) return false; } if (isDanger && health > 10) { healthDangerSet.delete(player); } return next(); }); onPlayerDanger(({ player, health, next }) => { player.sendClientMessage( "#ff0", `DANGER! Your health is only ${health}, and the system will automatically return blood for you after 3 seconds.`, ); setTimeout(() => { player.setHealth(100); }, 3000); return next(); }); ``` -------------------------------- ### Registering Commands with Case Sensitivity Option Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Demonstrates how to register a command using `onCommandText` and specify its case sensitivity. ```APIDOC ## PlayerEvent.onCommandText ### Description Registers a callback to be executed when a specific command is entered by a player. Allows for case-sensitive or case-insensitive command matching. ### Method `PlayerEvent.onCommandText(options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **caseSensitive** (boolean) - Optional - Specify if the command is case sensitive. Defaults to global setting. - **command** (string) - Required - The command text to register. - **run** (function) - Required - The callback function to execute when the command is triggered. It receives an object with `player`, `subcommand`, and `next`. ### Request Example ```ts PlayerEvent.onCommandText({ caseSensitive: false, command: "foo", run({ player, subcommand, next }) { return next(); }, }); ``` ### Response None directly returned by the registration function. ``` -------------------------------- ### Define and Use Custom Event Source: https://github.com/dockfries/infernus/blob/main/docs/zh-Hans/essentials/events.md Create a custom event using `defineEvent` for extending functionality. This example shows how to define a custom event `onPlayerDanger` and trigger it based on player health. ```typescript import type { Player } from "@infernus/core"; import { defineEvent, PlayerEvent } from "@infernus/core"; const healthDangerSet = new Set(); const [onPlayerDanger, trigger] = defineEvent({ // 只列了常用部分 isNative: false, // 不是原生事件,即我们的自定义事件,如果为true则意味着在pwn中的native事件或是插件的native事件 name: "OnPlayerDanger", // name请起一个唯一的,不要与现有的事件名冲突,通常为这种格式 defaultValue: true, // 定义中间件默认返回值为true // 如果您的自定义事件会有回调参数,请一定要写beforeEach来增强ts类型提示 // beforeEach会在所有该中间件执行前执行,用于增强参数 beforeEach(player: Player, health: number) { // 要求您一定要返回一个对象 return { player, health }; }, // afterEach用于在所有中间件执行后执行(会等待所有异步的也执行完毕) afterEach({ player, health }) {} }); PlayerEvent.onUpdate(({ player, next }) => { const isDanger = healthDangerSet.has(player); const health = player.getHealth(); if (!isDanger && health <= 10) { healthDangerSet.add(player); const ret = trigger(player, health); if (!ret) return false; } if (isDanger && health > 10) { healthDangerSet.delete(player); } return next(); }); onPlayerDanger(({ player, health, next }) => { player.sendClientMessage( "#ff0", `危险! 您生命值仅为${health}, 3秒后系统将自动为您回血`, ); setTimeout(() => { player.setHealth(100); }, 3000); return next(); }); ``` -------------------------------- ### Register and Show Dialog - TypeScript Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/dialogs.md Demonstrates how to register a command that opens a password-style dialog. It shows how to reuse a dialog instance by modifying its properties and displaying it again for confirmation. ```typescript import { PlayerEvent, Dialog, DialogStylesEnum } from "@infernus/core"; PlayerEvent.onCommandText("register", async ({ player, next }) => { const dialog = new Dialog({ style: DialogStylesEnum.PASSWORD, caption: "Register", info: "Please enter your password", button1: "ok", }); const { inputText: password } = await dialog.show(player); // You can reuse an existing dialog instance, modify its information, and then use it again later. // There are many setter besides info. dialog.info = "Please enter your password again"; const { inputText: againPassword } = await dialog.show(player); if (password !== againPassword) { player.sendClientMessage( "#f00", "The password you entered twice is not the same, please try again!" ); } return next(); }); ``` -------------------------------- ### Handle Player Route Finish Event Source: https://github.com/dockfries/infernus/blob/main/packages/gps/README.md This example demonstrates how to react when a player finishes their Waze GPS route. It uses WazeEvent.onPlayerRouteFinish to log a message indicating the route completion and displays the tick position. ```ts WazeEvent.onPlayerRouteFinish(({ player, finishedRoute, next }) => { player.sendClientMessage( -1, "Route finished!" + finishedRoute.tickPosition.toString(), ); return next(); }); ``` -------------------------------- ### Show Skin Model Menu with @infernus/e-selection Source: https://github.com/dockfries/infernus/blob/main/packages/e-selection/README.md Demonstrates how to display a skin model selection menu to a player upon spawning. It includes creating a list of models with custom text and rotation, and handling the player's selection or cancellation. ```ts import { type Player, PlayerEvent } from "@infernus/core"; import { type IModelData, ModelSelectionMenu } from "@infernus/e-selection"; PlayerEvent.onSpawn(({ player, next }) => { showSkinModelMenu(player) return next() }) async function showSkinModelMenu(player: Player) { // create a list to populate with models. // add skin IDs 0, 1, 29 and 60 with "cool people only" text above skin ID 29. const skins: IModelData[] = [ { modelId: 0 }, { modelId: 1 }, { modelId: 29, modelText: 'Cool people only' }, { modelId: 60 }, ].concat(Array.from({ length: 15 }).map((_, id): IModelData => { return { modelId: id, rotX: Math.random() * 5 } })) try { // use await_arr and set the response array to the model selection menu result const skin = await new ModelSelectionMenu({ player, models: skins, headerText: 'Skins', }).show() // make sure the player actually clicked on a model and not the close button if (skin) { // assign the player the skin of their choosing player.setSkin(skin.modelId) } } catch (err) { player.sendClientMessage(-1, JSON.stringify(err)) } } ``` -------------------------------- ### Close Player Dialog - TypeScript Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/dialogs.md Provides an example of how to close a dialog for a specific player using a command. It includes input validation to ensure a player ID is provided and checks if the target player is online. ```typescript import { PlayerEvent, Player, Dialog } from "@infernus/core"; PlayerEvent.onCommandText("closeDialog", ({ player, subcommand, next }) => { const [playerId] = subcommand; if (!playerId) { player.sendClientMessage( "#f00", "Please enter the dialog for which player you want to close" ); return next(); } // The commands entered by the player are all strings, so you need to convert the type to a numeric type. const closePlayer = Player.getInstance(+playerId); if (!closePlayer) { player.sendClientMessage("#f00", "The player is not online."); } else { // Dialog static method Dialog.close(closePlayer); player.sendClientMessage("#ff0", "You closed the player's dialog."); } return next(); }); ``` -------------------------------- ### Initialize and Manage CEF Browser Instance Source: https://github.com/dockfries/infernus/blob/main/packages/cef/README.md Handles the initialization of the CEF browser for a player, including success and error scenarios. It also subscribes to events from the browser. ```ts import { defineEvent } from "@infernus/core"; import { Cef, CefEvent } from "@infernus/cef"; CefEvent.onInitialize(({ player, success, next }) => { if (!player) return next(); if (success) { new Cef({ player, browserId: 1, url: "http://your-hosting.com", hidden: false, focused: false, }); } else { player.sendClientMessage( -1, "Ahh to bad you cannot see our new cool interface ...", ); } return next(); }); CefEvent.onBrowserCreated(({ cef, statusCode }) => { if (cef.browserId === 1) { if (statusCode !== 200) { // fallback to dialogs ... return; } Cef.subscribe("loginpage:login", "OnLogin"); } }); ``` -------------------------------- ### Inject Vehicle Class Creation Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/hooks.md For certain encapsulated entity classes like Vehicle, use the `__inject__` static method for injection. This example shows how to hook the `create` method of the Vehicle class to log when a new vehicle is created. ```typescript import { Vehicle, type LimitsEnum } from "@infernus/core"; export const orig_CreateVehicle = Vehicle.__inject__.create; export function my_CreateVehicle( ...args: Parameters ) { const id = orig_CreateVehicle(...args); if (id > 0 && id < LimitsEnum.MAX_VEHICLES) { console.log(`hook: vehicle ${id} created`); } return id; } Vehicle.__inject__.create = my_CreateVehicle; ``` -------------------------------- ### Load and Convert Map Data Source: https://github.com/dockfries/infernus/blob/main/packages/map-loader/README.md Converts a .pwn map file to .txt format and then loads it into the game. It logs the conversion time, the number of objects and removed buildings, and information about the loaded map. ```ts import { GameMode } from "@infernus/core"; import { getMapCount, getMapInfoFromID, loadMap, mapConverter, } from "@infernus/map-loader"; import path from "node:path"; GameMode.onInit(async ({ next }) => { const start = Date.now(); await mapConverter({ input: path.resolve("./scriptfiles/us_mapas.pwn"), output: path.resolve("./scriptfiles/us_mapas.txt"), removeOutput: true, }); const end = Date.now(); console.log((end - start) / 1000 + "s"); const mapId = await loadMap({ source: path.resolve("./scriptfiles/us_mapas.txt"), onLoaded(objects, removedBuilding) { console.log(objects.length, removedBuilding.length); }, }); console.log(mapId); const info = getMapInfoFromID(mapId); console.log(info); console.log(getMapCount()); return next(); }); ``` -------------------------------- ### Defining and Using Custom Events Source: https://github.com/dockfries/infernus/blob/main/docs/essentials/events.md Details how to define a new custom event using `defineEvent` and how to trigger and listen to it. ```APIDOC ## Custom Event Definition with `defineEvent` ### Description Allows developers to define their own custom events using `defineEvent`, extending the framework's event system. These custom events can be triggered and listened to like built-in events. ### Method `defineEvent(options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **isNative** (boolean) - Required - Set to `false` for custom events. - **name** (string) - Required - A unique name for the custom event (e.g., `OnPlayerDanger`). - **defaultValue** (any) - Optional - The default return value for middleware (defaults to `true`). - **beforeEach** (function) - Optional - A function executed before all middleware to enhance or validate parameters. Must return an object. - **afterEach** (function) - Optional - A function executed after all middleware have finished. ### Request Example (Definition and Usage) ```ts import type { Player } from "@infernus/core"; import { defineEvent, PlayerEvent } from "@infernus/core"; const healthDangerSet = new Set(); // Define the custom event const [onPlayerDanger, trigger] = defineEvent({ isNative: false, name: "OnPlayerDanger", defaultValue: true, beforeEach(player: Player, health: number) { return { player, health }; }, afterEach({ player, health }) { /* ... */ }, }); // Example of triggering the custom event PlayerEvent.onUpdate(({ player, next }) => { const isDanger = healthDangerSet.has(player); const health = player.getHealth(); if (!isDanger && health <= 10) { healthDangerSet.add(player); const ret = trigger(player, health); if (!ret) return false; } if (isDanger && health > 10) { healthDangerSet.delete(player); } return next(); }); // Example of listening to the custom event onPlayerDanger(({ player, health, next }) => { player.sendClientMessage( "#ff0", `DANGER! Your health is only ${health}, and the system will automatically return blood for you after 3 seconds.`, ); setTimeout(() => { player.setHealth(100); }, 3000); return next(); }); ``` ### Response - **onPlayerDanger** (function) - The listener function for the custom event. - **trigger** (function) - The function to call to trigger the custom event. ``` -------------------------------- ### Ejecutar servidor OMP con codificación UTF-8 en cmd Source: https://github.com/dockfries/infernus/blob/main/docs/es-ES/essentials/i18n.md Este comando cambia la codificación de la consola a UTF-8 (código 65001) antes de ejecutar el servidor OMP. Esto asegura que los caracteres se muestren correctamente en la terminal. ```cmd cmd /c "chcp 65001 > nul & omp-server" ```