events.tricks, overlay, session.read, net.session, server and console permissions.
How a game mode is split
A plugin whose manifest says"side": "both" runs twice in a session:
- The player’s copy runs on every player’s game.
reskate.sideis"client". It sees the local skater, draws, and sends what happened to the server copy. - The server copy runs on the session’s authority.
reskate.sideis"server". It hears the players’ copies, keeps the state, and answers everyone. Only it may callreskate.server.
- A lobby: on the lobby’s host, beside the host’s own player copy. The server copies start when the game starts hosting a lobby and stop when it stops. They draw nothing and show no panels. Each has its own id,
<folder>@server(reskate.idsays so), for its log lines, its storage, its console commands and anything it holds in the game, so it never shares state with the player copy: a server copy stopping leaves the player copy as it was. - A dedicated server: on
ReSkateServer.exe, from aPluginsfolder beside it (see On a dedicated server). The server has no world: there is no skater, camera or HUD there, so game functions say they are unavailable. What a server copy does there is messages, the session’s players,reskate.serverand its storage.
"side": "client" (the default) runs only as the player’s copy, and "side": "server" only as the server copy.
Nothing a player’s copy says is trusted by the server copy just because it came from the same plugin. Players can change their copy. Check every message in the server copy before you act on it.
1. The package
Make a mod folder in the game’sMods folder:
reskate-plugin.json asks for both sides and every permission either copy uses:
manifest.json gives the mod its name. Messages between copies go under this name, so every game and the server must have the same one. Without a manifest.json (or without a name in it), the folder’s name is used instead.
2. Pick the copy
Both copies run the same entry file. Readreskate.side and load the code for this copy:
require("server") loads plugin/server.luau or plugin/server.lua: modules are looked up beside the entry. See require.
3. The player’s copy
The player’s copy does three things: it says hello when it joins, reports each landed trick, and shows the scores the server copy sends back.Talk to the server copy
reskate.net.send("server", message) sends a message to the server copy only. Other players’ copies never see it. A message is a string (here JSON from reskate.json) of at most 4082 bytes, and a plugin sends at most 16 KB a second. send returns false when there is no session.
player_joined event names every player that joins, the local player too (player.me). When the local player joins a session, send a hello so the server copy answers with the scores so far. A plugin loaded while the session is already on says hello from its load handler instead.
Report tricks
Thetrick_landed event (events.tricks) gives the trick’s points. See events for its other fields.
Hear the server copy
Themessage handler gets who sent the message and its text. from.server is true only for what the server copy said: a player’s copy cannot send a message that arrives with it set. Ignore score messages from anyone else.
Show the scores
The draw handler (overlay) draws the table in the top left each tick. The drawing guide covers it in depth.
4. The server copy
The server copy keeps one score for each player and sends the standings to everyone whenever they change.Keep the state
id (the SteamID64 as a string), name, me, host and server. See session.
Answer everyone, or one player
reskate.net.send("all", message) from the server copy reaches every player’s copy, and each of them sees from.server set. To answer one player, pass the player (or their id) instead of "all". The server copy cannot send to "server": it raises an error, since it is the server.
Check what the players say
The server copy hears messages sent to"server" and those sent to "all". Check the kind and the values before using them. A score no trick can make is a player who changed their copy: reskate.server.kick drops them from the session.
reskate.server.say writes a line in everyone’s chat under the plugin’s name, at most one a second. reskate.server.kick, say, tell and move all return ok, why. They need the server permission and raise an error in a player’s copy, and a plugin makes at most 20 server calls a second. See server.
Follow who leaves
The server copy hearsplayer_joined and player_left too (session.read). Drop a player’s score when they leave:
A command for whoever runs the server
A server copy can add console commands like any plugin (console). On a dedicated server they are typed in the server’s console, and on a lobby’s host in the game’s console.
The whole plugin
Try it in a lobby
Host a lobby with the mod in yourMods folder: your game runs both copies. The game’s log says Plugins: hosting a lobby, so server copies run here. when the server copies start. Each player who joins needs the mod too.
On the lobby’s host, your own player copy’s messages to "server" stay on your game and reach the server copy there, and what the server copy sends to "all" reaches your player copy as well as everyone else’s.
The server copy’s log lines read [Trick_Race@server] ..., and the player copy’s [Trick_Race] ....
The game’s
plugin console commands reach the server copies too while your game hosts. plugin list shows them as <folder>@server, and plugin reload Trick_Race@server, plugin off Trick_Race@server and plugin on Trick_Race@server act on the server copy; the plain folder name acts on your player copy. The server copies also reload with their files on their own. A server copy’s console command runs only when no player copy has a command of that name.On a dedicated server
A dedicated server runs the server copies of the plugins in aPlugins folder beside ReSkateServer.exe (beside its Mods folder). Each plugin is a folder there with its reskate-plugin.json, and its "side" must be "server" or "both":
manifest.json included, so the server’s messages go under the same name as the players’ copies. The server checks the folder every 2 s: a new plugin loads, a changed one reloads, and a removed one unloads. Like the game, it refuses a package that holds a program or a script Windows runs. Server copies keep their storage in data/plugins beside the server’s config file.
On a dedicated server, reskate.session.active() and reskate.session.is_dedicated() are true, and reskate.session.players() lists the players on the server. None of them is me: the server is not a player. Lines the plugins log and print go to the server’s log.
Console commands on the server
Type these in the server’s console:
A plugin’s own command, such as
trickrace reset, runs from the server’s console only for a line the server does not know, so a plugin can never hide one of the server’s commands. The server answers Ran by a plugin. when one ran.
Where to go next
- Session and messages:
reskate.sessionandreskate.net.sendin full. - Server:
kick,say,tellandmove. - Limits: message sizes and rates.
- Examples: reskate-test’s server copy answers
ptest server.