Files
ReSkate/Engine/Game/Multiplayer/object_placement.h
T
AyeZeeBB 07fef3820d Limit how many objects each player can place (protocol 43)
Limit how many objects each player can place (protocol 43)

- Servers and lobby hosts set how many objects each player may have
  placed: object_limit in ReSkateServer.json and the "objects" command,
  "Objects per player" in the host options. Default 100; 0 is no limit
- The host and a server's admins are not limited
- At the limit a player's game refuses another object, from the native
  object tool and the park editor, and the menu shows how many they have
  placed
- Enforced by the host or server, which shows everyone no more than the
  limit of each player's layout; objects already shown keep their place
- The limit travels in the roster, which takes the protocol to version
  43: builds before this cannot join sessions with builds after it
- The protocol tests link again (the server browser needs the identity
  lists since the official servers change)
2026-10-07 10:03:54 -05:00

49 lines
2.8 KiB
C++

#pragma once
#include <charconv>
#include <cstdint>
#include <optional>
#include <string_view>
namespace dingosdk {
// Host policy for who may place, move or delete objects in a session. Wire
// values 0/1 match the older on/off editor byte (off = host only).
enum class ObjectPlacement : std::uint8_t { host_only = 0, everyone = 1, nobody = 2 };
inline constexpr bool valid_object_placement(std::uint64_t value) noexcept { return value <= 2; }
inline constexpr bool object_placement_allowed(ObjectPlacement policy, bool hosting) noexcept {
return policy == ObjectPlacement::everyone || (policy == ObjectPlacement::host_only && hosting);
}
inline constexpr std::string_view object_placement_name(ObjectPlacement policy) noexcept {
return policy == ObjectPlacement::everyone ? "Everyone" : policy == ObjectPlacement::host_only ? "Host only" : "Nobody";
}
// Accepts everyone|host|nobody, on/off as everyone/host, and next to cycle.
// Native widgets retain their activation callback, so `next` resolves against
// live state, never a value captured when the widget opened.
inline std::optional<ObjectPlacement> parse_object_placement(std::string_view argument,
ObjectPlacement current) noexcept {
if (argument == "everyone" || argument == "on") return ObjectPlacement::everyone;
if (argument == "host" || argument == "off") return ObjectPlacement::host_only;
if (argument == "nobody") return ObjectPlacement::nobody;
if (argument == "next")
return current == ObjectPlacement::everyone ? ObjectPlacement::host_only
: current == ObjectPlacement::host_only ? ObjectPlacement::nobody : ObjectPlacement::everyone;
return {};
}
// How many objects each player may have placed in a session, set by the host or the server:
// 0 is no limit beyond the protocol's own (max_object_limit). The host and a server's admins
// are not held to it. A player over it keeps what everyone already sees of theirs; only the
// objects past the limit are left out.
inline constexpr unsigned max_object_limit = 1024;
// What a server or a host starts with, until they choose otherwise.
inline constexpr unsigned default_object_limit = 100;
inline constexpr bool valid_object_limit(std::uint64_t value) noexcept { return value <= max_object_limit; }
// Accepts a number from 1 to max_object_limit, and off|none|0 for no limit.
inline std::optional<unsigned> parse_object_limit(std::string_view argument) noexcept {
if (argument == "off" || argument == "none") return 0U;
unsigned value{};
const auto parsed = std::from_chars(argument.data(), argument.data() + argument.size(), value);
if (argument.empty() || parsed.ec != std::errc{} || parsed.ptr != argument.data() + argument.size() || !valid_object_limit(value))
return {};
return value;
}
} // namespace dingosdk