mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 19:56:00 +02:00
Server config: - Written in sections, in reading order: server, access, maps, players, anti_cheat, network, votes. A config from an older version, flat and under older names, is read as it is and written back this way on first start; only settings that are really new are reported as new. - Renamed: no_bail, noclip, boosts, parties, voice_chat to allow_*; global_bans to use_global_bans; welcome to welcome_message; speed_check to speed_hack; score_check to modified_scoring; score_allow to allowed_scoring_mods; map_pool and map_rotation_minutes to maps.pool and maps.rotation_minutes. Console and admin commands are unchanged. - Bans are kept in data/bans.json beside the config. A config that holds them has them moved there; a bans file that cannot be read stops the server from starting. - Reserved slots are one list, "reserved_players_slots": a slot is kept for each listed player who is not on. "reserved_slots" and the "reserved slots <n>" command are gone; admins may take a kept slot but none is kept for them. - "tps" is no longer in the file: dedicated servers run at 20. - "bone_scale_limit" is 1 by default: resized body parts are off unless a server allows them. - New: "pack_ms" (10), how long Steam may hold a message to pack it with others; "finger_distance" (25); "steam_debug", which logs what Steam's networking says, for connection faults.
161 lines
9.3 KiB
C++
161 lines
9.3 KiB
C++
#pragma once
|
|
#include "Engine/Game/Multiplayer/distance_settings.h"
|
|
#include "Engine/Game/Multiplayer/object_placement.h"
|
|
#include "Engine/Game/Multiplayer/session_model.h"
|
|
#include "Engine/Game/Multiplayer/tick_settings.h"
|
|
#include "Engine/Game/Multiplayer/voice_settings.h"
|
|
#include "Engine/Game/World/park_rotation.h"
|
|
#include <cstdint>
|
|
#include <filesystem>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace dingosdk::server {
|
|
// One kind of player vote: whether players may start it, and the share of connected players
|
|
// (percent, 1-100) whose yes passes it.
|
|
struct VoteSetting {
|
|
bool enabled{};
|
|
unsigned percent = 60;
|
|
};
|
|
struct VoteSettings {
|
|
VoteSetting map, kick, time{false, 50};
|
|
unsigned seconds = 30; // how long a vote runs
|
|
unsigned cooldown = 60; // seconds before the same player may start another
|
|
};
|
|
// ReSkateServer.json. Every setting an admin or the console changes is saved
|
|
// back, so a restart keeps it.
|
|
inline constexpr unsigned dedicated_tps = 20;
|
|
struct ServerConfig {
|
|
std::filesystem::path file;
|
|
std::string name = "ReSkate server";
|
|
// The map everyone skates, named like the game's `load` command: "San Vansterdam",
|
|
// "Isle of Grom", or a custom map in Mods\ such as "bbcity".
|
|
std::string map = "San Vansterdam";
|
|
std::vector<std::string> map_pool; // maps for votes and the rotation, in order; empty: every map
|
|
unsigned map_rotation = 0; // minutes per map before the next pool map (0: off)
|
|
unsigned max_players = 16; // players; the server itself is not one
|
|
// The most poses a second one player is sent (crowd_limits); 0: no limit.
|
|
unsigned crowd_budget = crowd_pose_budget;
|
|
// The most a mod may resize part of a skater for the other players, as a factor (and its
|
|
// inverse the least): 1, the default, shows every skater at the game's own proportions;
|
|
// 0 is no limit.
|
|
float bone_scale_limit = 1;
|
|
// How players reach the server: true, through Steam's relay network only; false, straight
|
|
// to `port` (UDP). A direct server still answers through the relays, for a player the port
|
|
// does not reach, one who has turned direct connections off, or an older game.
|
|
bool use_steam_relay = true;
|
|
// Logs what Steam's networking says it is doing, to find out why connections fail.
|
|
bool steam_debug = false;
|
|
// How long a message to a player may wait to share a packet with the next ones, in
|
|
// milliseconds (0: each goes at once in a packet of its own). Fewer, fuller packets:
|
|
// less sent for the same updates, and less work sending it.
|
|
unsigned pack_ms = 10;
|
|
// Past this many metres a player's fingers are not sent moving (0: always). A skater's
|
|
// forty finger bones turn in nearly every pose and are half of what a pose carries.
|
|
unsigned finger_distance = 25;
|
|
// What the server may send each player, in KB/s (128-16384).
|
|
unsigned send_rate = 900;
|
|
// The players with a reserved slot: one is kept free for each of them who is not on.
|
|
std::vector<std::uint64_t> reserved;
|
|
std::string password; // empty: anyone may join
|
|
std::string welcome; // sent to each player as they join
|
|
bool listed = true; // shown in the in-game server browser
|
|
// A Steam game server login token (steamcommunity.com/dev/managegameservers, app 3354750).
|
|
// With one the server signs in to its own account and keeps the same Steam ID every start,
|
|
// which is how the ReSkate team's list of official servers knows it. Empty: anonymous.
|
|
std::string steam_token;
|
|
bool auto_update = true; // install new releases when nobody is on
|
|
bool global_bans = true; // turn away players the ReSkate team has banned (global_bans.h)
|
|
bool activity_log = true; // console lines for throwdowns, objects and loading
|
|
bool announce_throwdowns = true; // tell everyone in chat when a throwdown drop is placed
|
|
// Players form parties (/party, the game's Social menu): 2-8 players each (the game's Party
|
|
// panel has eight rows). Off, nobody can be in one.
|
|
bool parties = true;
|
|
unsigned party_size = 8;
|
|
// Players whose game runs fast (a speedhack; Server/speed_check.h): "warn" takes them out of
|
|
// throwdowns and coop challenges and tells the admins, "kick" also removes them, "off" does not check.
|
|
std::string speed_check = "warn";
|
|
// Players whose mods change how tricks score (Engine/Vfs/mod_scoring.h): "warn" takes them out
|
|
// of throwdowns and coop challenges (the server stops relaying theirs) and tells everyone,
|
|
// "kick" removes them, "off" does not check.
|
|
std::string score_check = "warn";
|
|
// Scoring fingerprints accepted besides the game's own (a server that runs on a scoring mod
|
|
// everyone installs). Each player's fingerprint is in the console when they are flagged.
|
|
std::vector<std::uint64_t> score_allow;
|
|
std::uint16_t port = 27015, query_port = 27016;
|
|
// Fixed for dedicated servers for now (dedicated_tps): a busy one's traffic, in and out,
|
|
// is its players' poses, and at 20 a second that is a third less than at 30. Whatever
|
|
// the file says is read as this; lobbies keep their own choice.
|
|
unsigned tps = dedicated_tps;
|
|
bool voice_chat = true;
|
|
float voice_range = default_voice_range;
|
|
MultiplayerDistances distances;
|
|
// everyone, admins (only the admins below may build) or nobody.
|
|
ObjectPlacement object_placement = ObjectPlacement::everyone;
|
|
// Objects each player may have placed (object_placement.h); 0: no limit. Admins are not held to it.
|
|
unsigned object_limit = default_object_limit;
|
|
// Whether players may use noclip (and teleport) / No Bail / the boosts (admins always may).
|
|
bool noclip = true, no_bail = true, boosts = true;
|
|
// Players skate with the game's own physics tuning, not copies they edited.
|
|
bool enforce_tuning = true;
|
|
VoteSettings votes; // all off until the owner turns them on
|
|
ParkChoices parks{"skatepark_01", "megapark_05", "flumppark_08"};
|
|
// Forced on every player while world_layer_sync is on: layer key -> mode.
|
|
// Needs world-layers.json (the players' catalog) next to the server.
|
|
bool world_layer_sync{};
|
|
std::map<std::string, std::string> layers;
|
|
std::vector<std::uint64_t> admins;
|
|
std::vector<MultiplayerBan> bans;
|
|
};
|
|
// Reads `file`, writing a default one first when it does not exist. Settings this version
|
|
// has that the file lacks (added by an update) are written back with their defaults, and
|
|
// their names go to `added` ("votes.seconds" for a nested one).
|
|
ServerConfig load_config(const std::filesystem::path &file, std::vector<std::string> *added = nullptr);
|
|
void save_config(const ServerConfig &config);
|
|
// Where the bans are kept: data/bans.json, beside the config.
|
|
std::filesystem::path bans_file(const ServerConfig &config);
|
|
// Whether a player who is not yet on may join a server with `on` players on it, `reserved_on`
|
|
// of them players with a reserved slot. A slot is kept for each reserved player who is not on:
|
|
// anyone joins while a slot beyond those is free, then only the reserved players and the admins
|
|
// until the server is full.
|
|
bool may_join(const ServerConfig &config, std::uint64_t id, std::size_t on, std::size_t reserved_on) noexcept;
|
|
// Why `config` cannot run, or empty.
|
|
std::string config_error(const ServerConfig &config);
|
|
// A scoring fingerprint as the config and console write it (16 hex digits), and read back
|
|
// (nothing for text that is not one, or for 0: the game's own scoring needs no entry).
|
|
std::string scoring_text(std::uint64_t fingerprint);
|
|
std::optional<std::uint64_t> parse_scoring(std::string_view text);
|
|
|
|
// Maps. The game always has its root level (DingoLevel_Root) loaded, and a map
|
|
// is the level loaded into it, named as the game's own `load` command names it:
|
|
// "San Vansterdam", "Isle of Grom", a custom map's "bbcity"...
|
|
struct ServerLevel {
|
|
std::string asset, name;
|
|
};
|
|
// The retail maps, and the custom maps in `mods`\<mod>\reskate-levels.json
|
|
// (players' map mods, copied next to the server). Returns why a mod was skipped.
|
|
std::vector<std::string> load_levels(const std::filesystem::path &mods);
|
|
const std::vector<ServerLevel> &levels();
|
|
// Like the game's `load`: a level path, a name or short name, or the unique start of one.
|
|
const ServerLevel *find_level(std::string_view map);
|
|
// Whether the server has this map (a name, level path or destination): one of the game's own,
|
|
// or one a mod folder in its Mods lists. It only moves players to a map it has itself.
|
|
bool installed_map(std::string_view map);
|
|
// "a.b.c.d" as a number (a the highest byte), or 0 when it is not an IPv4 address.
|
|
std::uint32_t direct_ipv4(std::string_view text) noexcept;
|
|
// What players load for a map, as the protocol carries it ("<root>|<level>").
|
|
// Empty when the map is unknown (a full level path is always accepted).
|
|
std::string map_destination(std::string_view map);
|
|
// The name to store for a map, a level path or a destination (an in-game admin
|
|
// sends destinations).
|
|
std::string map_setting(std::string_view map);
|
|
// A map's name for people: "San Vansterdam".
|
|
std::string map_label(std::string_view map);
|
|
std::vector<const ServerLevel *> pool_levels(const ServerConfig &config); // known pool maps once each; all when empty
|
|
bool in_map_pool(const ServerConfig &config, std::string_view map);
|
|
const ServerLevel *next_pool_map(const ServerConfig &config, std::string_view map); // after `map`; null if no other
|
|
} // namespace dingosdk::server
|