Server
Namespace:
DeadworksManaged.Api
Server controls things that affect the whole server: the map, console commands, kicking players and adding bots.
Find out which map is running
string map = Server.MapName; // "dl_midtown"
Change the map
if (!Server.ChangeMap(mapName))
throw new CommandException($"There's no map called {mapName}.");
Everyone stays connected and loads into the new map. ChangeMap checks the name with Server.IsMapValid first. It returns false if the map doesn't exist, so it's safe to pass a name a player typed. Server.ChangeLevel(map) changes map without checking.
Server.GetMapList() returns the maps you can change to: the game's own maps, plus any listed under serverbrowser.extra_maps in configs/deadworks.jsonc, sorted by name.
While the map is changing, Server.IsChangingLevel is true.
Changes you make to players while the map is changing are lost. Check Server.IsChangingLevel first and return early.
if (Server.IsChangingLevel) return;
Run code when a map starts
Override OnStartupServer. It runs every time a map starts, including the first.
public override void OnStartupServer()
{
Console.WriteLine($"Now playing on {Server.MapName}");
}
Run a console command
Server.ExecuteCommand("sv_cheats 1");
ExecuteCommand runs the command as if it were typed in the server console.
To change a setting, set a cvar instead.
To read the command's output, pass a callback. The callback runs on a later frame, because console commands run on the next frame.
Server.ExecuteCommand("status", output => caller.Reply(output));
Setting a cvar prints nothing, so its output is empty.
Run a command on a player's game
Server.ClientCommand(controller.Slot, "echo Hello from the server!");
ClientCommand runs the command in that player's game console.
Kick a player
controller.Kick("You were kicked for being idle.");
Kick prints the message in the player's chat and game console. It then passes the message to the engine as the disconnect reason.
Deadlock doesn't show the disconnect reason on the main menu. The player only sees the message if they read it before the disconnect. To give them time, warn them first.
Chat.PrintToChat(controller, "You'll be kicked in 3 seconds for being idle.");
Timer.Once(3.Seconds(), () => controller.Kick("You were kicked for being idle."));
Server.Kick(slot, message) does the same for a slot. controller.Kick() with no message kicks the player without a message.
To turn a player away while they're connecting, see ClientConnectEvent. To ban them, see Penalties.
Add a bot
int slot = Server.CreateFakeClient("Bot");
if (slot == -1)
Console.WriteLine("There was no free slot for a bot.");
CreateFakeClient returns the bot's slot, or -1 when the server has no slot free.
To tell bots from real players, check IsBot:
foreach (var controller in Players.GetAll())
{
if (controller.IsBot) continue;
// Real players only
}
Run code every tick
Override OnGameFrame. Check simulating first, so your code only runs while the game is running.
public override void OnGameFrame(bool simulating, bool firstTick, bool lastTick)
{
if (!simulating) return;
// ...
}
OnGameFrame runs every tick, so keep it fast. For anything slower than every tick, use a timer.
Find out what time it is in the game
GlobalVars.CurTime is the game's clock, in seconds. Use it to measure how long something took.
float started = GlobalVars.CurTime;
// Later
float seconds = GlobalVars.CurTime - started;
GlobalVars.TickCount is how many ticks the game has run. GlobalVars.IntervalPerTick is how long one tick lasts.
Read what the server logs
public override void OnLoad(bool isReload)
{
Server.AddEngineLogListener(OnLog);
}
public override void OnUnload()
{
Server.RemoveEngineLogListener(OnLog);
}
private void OnLog(string message)
{
if (message.Contains("error"))
{
// ...
}
}
The game engine calls your method with every line it logs.