mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-29 03:46:50 +01:00
Server: tools can be locked for single players, and for a throwdown's players
The server can take noclip (with teleporting), No Bail, the boosts and the player's own physics tuning from one player while everyone else keeps what the server allows: for fair throwdowns on a server that allows them for free skating. Server only: a locked player gets a roster of their own with the tool off (players with the same locks share one) and permissions without "movement", so their role cannot give it back. Players without locks get exactly the roster they got before. - lock <player|SteamID64> <tool[,tool...]|all>, unlock <player|SteamID64> [<tools>|all], locks: from the console, or an admin in chat. In memory only; locks end when the player leaves. Logged as "[lock] <name> (<SteamID64>): nobail, boosts locked by <who>". - players.throwdown_locks (default []): tools locked for the players of a throwdown from its start until they quit, it ends or they leave (console: throwdown-locks <tools>|off). - Tests: Server/Test/server_lock_tests.cpp, and the key in the config tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PreNfxwh21xyPp8EA72cUN
This commit is contained in:
1 parent
0f8af62710
commit
3bfabed705
13 files changed
+720
-18
No files matched your search
@@ -128,6 +128,10 @@ Layout layout(const ServerConfig &c) {
|
||||
players.set("allow_object_scaling", c.object_scaling);
|
||||
players.set("sync_effects", c.sync_effects);
|
||||
players.set("announce_throwdowns", c.announce_throwdowns);
|
||||
auto locks = Json::array();
|
||||
for (const auto bit : {lock_noclip, lock_nobail, lock_boosts, lock_tuning})
|
||||
if (c.throwdown_locks & bit) locks.push_back(lock_tools_text(bit));
|
||||
players.set("throwdown_locks", std::move(locks));
|
||||
|
||||
auto &anti_cheat = root.section("anti_cheat");
|
||||
anti_cheat.set("speed_hack", c.speed_check);
|
||||
@@ -373,6 +377,10 @@ ServerConfig load_config(const std::filesystem::path &file, std::vector<std::str
|
||||
c.object_scaling = get("players", "allow_object_scaling", c.object_scaling);
|
||||
c.sync_effects = get("players", "sync_effects", c.sync_effects);
|
||||
c.announce_throwdowns = get("players", "announce_throwdowns", c.announce_throwdowns);
|
||||
if (const auto *locks = find("players", "throwdown_locks", {}); locks && locks->is_array())
|
||||
for (const auto &value : *locks)
|
||||
if (value.is_string())
|
||||
if (const auto tools = parse_lock_tools(value.string())) c.throwdown_locks |= *tools;
|
||||
|
||||
c.speed_check = get("anti_cheat", "speed_hack", c.speed_check, {"speed_check"});
|
||||
if (c.speed_check != "off" && c.speed_check != "warn" && c.speed_check != "kick") c.speed_check = "warn";
|
||||
@@ -685,6 +693,34 @@ std::optional<std::uint64_t> parse_scoring(std::string_view text) {
|
||||
if (!value) return std::nullopt;
|
||||
return value;
|
||||
}
|
||||
std::optional<std::uint8_t> parse_lock_tools(std::string_view text) {
|
||||
std::uint8_t tools{};
|
||||
for (bool more = true; more;) {
|
||||
const auto comma = text.find(',');
|
||||
more = comma != std::string_view::npos;
|
||||
auto name = text.substr(0, comma);
|
||||
text = more ? text.substr(comma + 1) : std::string_view{};
|
||||
while (!name.empty() && std::isspace(static_cast<unsigned char>(name.front()))) name.remove_prefix(1);
|
||||
while (!name.empty() && std::isspace(static_cast<unsigned char>(name.back()))) name.remove_suffix(1);
|
||||
std::string lower(name);
|
||||
for (auto &c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
if (lower == "noclip" || lower == "teleport") tools |= lock_noclip;
|
||||
else if (lower == "nobail") tools |= lock_nobail;
|
||||
else if (lower == "boosts") tools |= lock_boosts;
|
||||
else if (lower == "tuning") tools |= lock_tuning;
|
||||
else if (lower == "all") tools |= lock_all;
|
||||
else return std::nullopt;
|
||||
}
|
||||
if (!tools) return std::nullopt;
|
||||
return tools;
|
||||
}
|
||||
std::string lock_tools_text(std::uint8_t tools) {
|
||||
std::string text;
|
||||
for (const auto &[bit, name] : {std::pair{lock_noclip, "noclip"}, std::pair{lock_nobail, "nobail"},
|
||||
std::pair{lock_boosts, "boosts"}, std::pair{lock_tuning, "tuning"}})
|
||||
if (tools & bit) text += (text.empty() ? "" : ", ") + std::string(name);
|
||||
return text.empty() ? "none" : text;
|
||||
}
|
||||
std::size_t extra_slots(const ServerConfig &config) noexcept {
|
||||
// (A player with such a role who is also listed has one slot, not two.)
|
||||
std::size_t slots = config.reserved.size();
|
||||
|
||||
Reference in new issue
Block a user