Passer au contenu principal
Version: latest - a1.169.2 ⚖️

Chargement des Packages et environnement Lua

Dans quel ordre les Packages et leurs scripts sont chargés, comment ils partagent du code entre eux, et ce qui est disponible dans l'environnement Lua.

Ordre de chargement​

Au démarrage, le serveur charge les Packages listés dans la section [game] du Config.toml dans cet ordre :

  1. Le Package game-mode (game_mode)
  2. Les Packages script (packages), dans l'ordre de la liste
  3. Le Package map (map)

Pour chaque Package, avant d'exécuter ses scripts, le serveur charge d'abord ses assets_requirements et ses packages_requirements (et leurs propres dépendances, de façon récursive). Les scripts s'exécutent ensuite dans cet ordre :

  1. Shared/Index.lua
  2. Server/Index.lua (sur le serveur) ou Client/Index.lua (sur les clients)
  3. L'événement Load du Package est déclenché

Les clients chargent les mêmes Packages, dans le même ordre, après avoir téléchargé leurs fichiers Client/ et Shared/.

tip

Consultez la page Cycle de vie du serveur et du client pour un schéma complet de tout ce qui se passe au démarrage du serveur et à la connexion d'un client.

Dépendances des Packages​

Si votre Package utilise quelque chose défini par un autre Package (par ex. les classes d'armes de default-weapons, ou une fonction exportée par une bibliothèque), ajoutez-le aux packages_requirements de votre Package.toml. Il sera ainsi chargé avant l'exécution de vos scripts :

Package.toml
[script]
# ...
packages_requirements = [
"default-weapons",
]
info

Seuls les Packages script (et c-module) peuvent être des dépendances. Si le Package requis n'est pas installé, le serveur peut le télécharger automatiquement depuis le Vault s'il est lancé avec --auto_download.

Évitez de charger des dépendances en cours d'exécution avec Server.LoadPackage(), car votre code risque de s'exécuter avant qu'elles soient prêtes.

Les événements Load et Unload​

Server/Index.lua
-- Triggered after all the Index.lua files of this Package ran
Package.Subscribe("Load", function()
Console.Log("My Package loaded!")
end)

-- Triggered when this Package is unloaded (server stopping, map change or package reload)
Package.Subscribe("Unload", function()
-- Save your data here, e.g. with Package.SetPersistentData
end)

Si auto_cleanup est activé dans le Package.toml (c'est le cas par défaut), toutes les entités créées par le Package sont détruites quand il se décharge.

Découper votre code en plusieurs fichiers​

Seul le Index.lua de chaque dossier s'exécute automatiquement. Pour charger d'autres fichiers, utilisez Package.Require() :

Server/Index.lua
Package.Require("Weapons.lua") -- my-package/Server/Weapons.lua
Package.Require("Utils/Math.lua") -- my-package/Server/Utils/Math.lua

Les fichiers sont recherchés dans cet ordre, donc le nom du fichier suffit en général :

  1. Relatif au fichier actuel
  2. Relatif à my-package/Server/ ou my-package/Client/ (selon le côté)
  3. Relatif à my-package/Shared/
  4. Relatif à my-package/
  5. Relatif à Packages/

Un fichier n'est exécuté qu'une seule fois : le requérir à nouveau renvoie le résultat mis en cache.

Partager du code entre Packages​

Chaque Package s'exécute dans son propre environnement : les variables et fonctions globales définies dans un Package ne sont pas visibles des autres Packages. Cela évite les conflits entre Packages qui utilisent les mêmes noms.

Pour rendre quelque chose accessible à tous les Packages, exportez-le avec Package.Export() :

my-library/Server/Index.lua
MyLibrary = {}

function MyLibrary.Greet(player)
Chat.SendMessage(player, "Hello " .. player:GetName())
end

Package.Export("MyLibrary", MyLibrary)
my-game-mode/Server/Index.lua
-- Works as long as my-library is loaded before (e.g. in packages_requirements)
Player.Subscribe("Ready", function(player)
MyLibrary.Greet(player)
end)
note

Les classes créées avec Inherit (par ex. MyProp = Prop.Inherit("MyProp")) sont enregistrées globalement : elles sont donc aussi accessibles depuis n'importe quel Package du même côté.

Les événements sont un autre moyen de communiquer, voir Communication entre Packages.

L'environnement Lua​

nanos world utilise Lua 5.4, avec la plupart de ses bibliothèques standard, plus l'API nanos world (classes, classes statiques, structs et bibliothèques utilitaires).

Pour des raisons de sécurité, certaines fonctions sont désactivées par défaut :

  • Les fonctions qui accèdent au système d'exploitation : os.execute, os.rename, os.remove, os.exit, os.getenv, os.tmpname, os.setlocale, dofile, loadfile et toute la bibliothèque io.
  • La bibliothèque debug, sauf debug.traceback, debug.getinfo, debug.sethook et debug.gethook, car les autres fonctions peuvent lire et modifier les upvalues et variables locales d'autres fonctions, le registre et les métatables.
  • Le chargement de bytecode Lua précompilé, avec load ou comme fichiers de Package. Seuls les morceaux de code texte peuvent être chargés.

Sur le serveur, on peut les activer avec le paramètre --enable_unsafe_libs, mais faites-le seulement si vous avez confiance en tous les Packages de votre serveur. Côté client, elles sont toujours désactivées, car les joueurs rejoignent des serveurs auxquels ils ne peuvent pas faire confiance.

Pour vous aider à déboguer vos propres scripts, la bibliothèque debug complète peut être activée sur le client dans Settings > Debug. Ce réglage n'est jamais sauvegardé : il ne dure que jusqu'à la fermeture du jeu et s'applique quand vous rejoignez un serveur (ou quand les Packages se rechargent). Les autres fonctions ci-dessus restent désactivées sur le client. Ne l'activez que sur vos propres serveurs, car il permet aux scripts du serveur de lire et de modifier le fonctionnement interne de n'importe quel autre script.

Pour lire et écrire des fichiers, utilisez plutôt la classe File, qui fonctionne dans le dossier du serveur. Pour stocker des données, préférez les données persistantes ou une Database.