Setonix Server
This is the standalone server part of the Setonix game. Read the setup guide, configuration reference, console commands, and roles and permissions.
The executable binds to 127.0.0.1:28006 by default. Saved worlds are under
worlds/, content packs under packs/, and local users in setonix.db.
See the configuration reference for current CLI autosave behavior and TLS setup.
To run behind nginx on the same machine, set publicAddress to your public
wss:// URL and trustedProxies to ["127.0.0.1"], or pass
--public-address wss://play.example.com:443 --trusted-proxy 127.0.0.1.
Forwarded client IPs are accepted only from configured proxy IPs or CIDR networks.
See the nginx configuration example.
Use as a library
You can use the server as a library in your own project.
Put the following in your pubspec.yaml:
dependencies:
setonix_server:
git:
url: https://github.com/LinwoodDev/Setonix.git
ref: <last commit or tag>
path: server
And then you can use the server in your code:
import 'package:setonix_server/setonix_server.dart';
Future<void> main(List<String> arguments) {
return runServer(arguments);
}
Configure
You can configure the server by providing an onLoad function that will be called before the server starts.
import 'package:setonix_server/setonix_server.dart';
Future<void> main(List<String> arguments) {
return runServer(arguments, onLoad);
}
Future<void> onLoad(SetonixServer server) async {
print("on load was called");
// Add your custom code here
bool toggleCancel = false;
// Put the event you want to listen to in the brackets
server.eventSystem.on<ObjectsMoved>().listen((e) {
print("Listener was called, cancel: $toggleCancel");
// Cancel the event every second time and duplicate the objects instead
if (toggleCancel) {
final event = e.clientEvent;
final table = e.getTableOrDefault(event.table);
final cell = table.getCell(event.from);
final objects = List<GameObject>.from(table.getCell(event.to).objects);
for (final index in event.objects) {
final object = cell.objects[index];
objects.add(object);
}
// Send the event to all clients
e.sendEvent(ObjectsSpawned(e.clientEvent.table, {event.to: objects}));
// Cancel the event
e.cancel();
}
toggleCancel = !toggleCancel;
});
}
Custom roles and permissions
Role and permission identifiers are open strings. Use namespace:key for
values owned by a custom server or pack. Built-in identifiers remain
unqualified for compatibility and resolve against the core pack.
{
"serverRoles": {
"blackjack:dealer": {
"name": "Dealer",
"priority": 25,
"permissions": ["play", "blackjack:deal", "blackjack:shuffle"]
}
}
}
Custom server code can check effective user permissions with
rolesAllowPermission(user.roles, 'blackjack:deal', roles).
Users may have multiple roles. Their effective permissions are the union of
all assigned roles, and their highest role priority is used for moderation
hierarchy checks. The player role is always retained.
Role assignments can be managed from the server console:
role list <user>
role add <user> <role>
role remove <user> <role>
role set <user> <role...>
Role definitions are managed persistently with roles:
roles list
roles show <role>
roles create <role> <priority> <display name...>
roles delete <role> [replacement]
roles rename <role> <display name...>
roles priority <role> <priority>
roles permission add <role> <namespace:key>
roles permission remove <role> <namespace:key>
Deleting a role replaces it with player unless another replacement is
provided. The default player role cannot be deleted.
Role and permission labels use the regular pack translation files. For the
example above, add this to translations/en.json in the blackjack pack:
{
"roles": {
"dealer": { "name": "Dealer" }
},
"permissions": {
"deal": { "name": "Deal cards" },
"shuffle": { "name": "Shuffle cards" }
}
}
Console commands
Command and subcommand names ignore case; argument values keep their original spelling.
Use help, ?, help roles permission add, or players --help for generated
help, examples and options. ANSI terminals support history, cursor editing and
Tab completion; incoming logs preserve the current input. Pipes receive plain
text without prompts or terminal escape sequences.
The server console exposes the following runtime management commands:
status [--json]
players [world] [--world <world>]
name <user> <name...>
bans
ban <user> [minutes] [reason...]
unban <user>
kick <user> [reason] [link]
worlds
modes
reset [world] [game-mode|sandbox]
save [world]
scripts [world]
packs
say <message...>
whitelist <add|remove> <user>
role <list|add|remove|set> <user> [roles...]
roles <list|show|create|delete|rename|priority|permission> ...
stop
User references may use a channel (#2), name (@Player), fingerprint
(*fingerprint), or the unprefixed forms accepted by the individual command.
Console modules
Commands are organized into ServerModule, WorldModule, ModerationModule,
RolesModule and ContentModule. Embedded servers can install custom ConsoleModule
instances through server.consoler.install(module) and execute commands with
await server.consoler.execute(line).
players, save and scripts accept --world / -w as an alternative to
the positional world argument. status --json uses stable field names for
automation. Console output is English for now.
The new Consoler offers colors through server.consoler.colors and customizable
built-in text through server.consoler.messages. No translation integration is
configured by Setonix.
Libraries
- events
- Official setonix server library
- setonix_server
- Official setonix server library