Écrire une ressource sur bs_core
Construisons-en une toute petite : une « tour radio » utilisable une fois toutes les 10 minutes pour 50 $ en liquide et un peu d’XP. Elle est inventée, les éléments qu’elle utilise sont réels.
resources/[beyond]/bs_radiotower/├── fxmanifest.lua├── config/config.lua├── client/cl_main.lua└── server/sv_main.luaPréfixez-la avec bs_. Les noms de ressources FiveM forment un seul espace de noms global ; une ressource appelée radio finira par entrer en collision avec le script de quelqu’un.
fxmanifest.lua
Section intitulée « fxmanifest.lua »fx_version 'cerulean'game 'gta5'lua54 'yes'
name 'bs_radiotower'description 'BeyondSurvival - radio tower example'
shared_scripts { '@bs_core/shared/sh_bridge.lua', -- BSB callbacks + BSB.RegisterCommand 'config/config.lua',}client_scripts { 'client/cl_main.lua' }server_scripts { 'server/sv_main.lua' }
dependencies { 'bs_core' }
-- live overrides from the F1 console, AFTER your config filesshared_script '@bs_config/shared/apply.lua'-- crash breadcrumbsclient_script '@bs_core/shared/sh_crumbs.lua'Ajoutez ensuite ensure bs_radiotower à server.cfg, après bs_core et après tout ce que vous appelez.
config/config.lua
Section intitulée « config/config.lua »RadioTower = {}RadioTower.Settings = { reward = 50, xp = 20, cooldown = 600, -- seconds pos = vector3(0.0, 0.0, 0.0), range = 3.0,}Une table globale au nom de votre ressource. C’est ce que le helper apply de F1 modifie (voir Helper config apply).
server/sv_main.lua
Section intitulée « server/sv_main.lua »local last = {} -- [charId] = os.time()
BSB.RegisterCallback('radiotower:use', function(src) local p = exports.bs_core:GetPlayerSummary(src) if not p then return { ok = false, error = 'Not loaded.' } end
-- never trust the client: check distance here too local pos = GetEntityCoords(GetPlayerPed(src)) if #(pos - RadioTower.Settings.pos) > RadioTower.Settings.range + 2.0 then return { ok = false, error = 'Too far.' } end
local now = os.time() if last[p.charId] and now - last[p.charId] < RadioTower.Settings.cooldown then return { ok = false, error = 'Nothing on the air yet.' } end last[p.charId] = now
exports.bs_core:AddMoney(src, 'cash', RadioTower.Settings.reward, 'radiotower') exports.bs_core:AddXP(src, RadioTower.Settings.xp, 'radiotower') return { ok = true }end)Argent et XP uniquement via les exports de bs_core. N’écrivez jamais vous-même dans les colonnes de la BD.
client/cl_main.lua
Section intitulée « client/cl_main.lua »local function use() if not exports.bs_core:IsLoaded() then return end Crumb('radiotower', 'use') local res = BSB.Await('radiotower:use', 5000) if not res then return end -- timed out, server side not running TriggerEvent('bs:ui:notify', { type = res.ok and 'success' or 'error', message = res.ok and 'You picked up a signal.' or res.error, })end
RegisterCommand('radiotower', use, false)Pour une vraie interaction, vous enregistreriez une option dans bs_interactions (le point ALT) plutôt qu’une commande ; regardez comment bs_recycler ou bs_mining le font.
Si vous téléportez des joueurs
Section intitulée « Si vous téléportez des joueurs »Appelez exports.bs_guard:Allow(src, 'teleport', 3000) avant de les déplacer côté serveur, sinon bs_guard signale chaque usage.
Pièges (tous sont arrivés)
Section intitulée « Pièges (tous sont arrivés) »- Les globales d’une autre ressource sont invisibles.
Items.Definitionsdans bs_admin est une table vide, pas celle de bs_inventory. Utilisez les exports. - Les fonctions ne traversent pas les exports. Passer une fonction callback à l’export d’une autre ressource ne marche pas. C’est pourquoi BSB est un fichier que vous incluez, pas un export.
- Ne faites pas de
Waitdans un export appelé par quelqu’un d’autre. Il s’exécute sur le thread de l’appelant dans votre runtime et lève une erreur. bs_radial avait ce bug, c’est pourquoiBSB.Radialexiste. local a, b = x and f() or y- Lua ne garde que le premier retour def()ici. Écrivez-le avec un if.- Un local utilisé avant sa déclaration est une globale nil.
luac5.4 -l file.lua | grep _ENVles trouve. - Protégez
GetEntityModelavecDoesEntityExist. Sur un handle mort, ça fait planter violemment le client du jeu. - Pas de messages NUI à chaque frame au repos. Envoyez au changement.
- Chaque
bs:ui:openeda besoin d’unbs:ui:closedsur chaque chemin de sortie, voir Conventions UI/NUI.
bs19.org · Privacy · Terms · Cookie settings
Cookies and outside content
The site only needs two essential cookies to keep you logged in and protect forms. Videos and streams from YouTube and Twitch load from their servers, which can set their own cookies, so they stay off until you say yes. Nothing is pre-ticked and you can change your mind any time with "Cookie settings" at the bottom of every page. Details.
Questions about the server, the framework or the site? A real person reads this, usually within a day.