mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 01:14:34 +02:00
Votes on a dedicated server show as a card above chat instead of being followed through chat lines. - The card has what is voted on, the Yes and No counts, how many are needed, a bar of how far Yes has got, and the seconds left. When the vote ends it shows Passed, Failed or Cancelled for four seconds. - Yes and No are two buttons, labelled with the player's binds. The answer given is highlighted and can be changed. They can be clicked whenever the cursor is free (chat, menu or console open). - Two new binds, "Vote yes" and "Vote no", in the binds list: F1 and F2 unless changed, to keys or controller combos like the others. They are read only while a vote is running, and not while typing. - /yes and /no still work and show on the card. The player a kick vote is about sees the card and has no vote in it. - Console: "mp vote yes|no", "bind voteyes <n>", "bind voteno <n>". Server: - The roster carries the running vote (id, kind, tally, seconds left, starter, target, label) and the one just finished with how it ended. - A chat line is no longer sent for each change of the tally; the lines for a vote starting and ending stay. Fix: a dedicated server's roster may list more players than its limit. The extra slots for reserved players and admins (33 of 32) made a roster the protocol refused to encode, so with one in use the server logged "Server error" every pass and stopped part-way through each one until somebody left. Lobbies hosted by a player are still held to their size.
128 lines
6.9 KiB
C++
128 lines
6.9 KiB
C++
#include "Extension/Profile/profile_internal.h"
|
|
#include <cmath>
|
|
#include <set>
|
|
#include <type_traits>
|
|
|
|
namespace dingosdk::profile {
|
|
using namespace detail;
|
|
std::uint32_t freecam_controller_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("freecam_controller");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Freecam Controller binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Freecam Controller binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
bool freecam_controller(const Snapshot& s) {
|
|
const auto options = s.settings.find("options");
|
|
if (options == s.settings.end()) return false;
|
|
require(options->is_object(), "Options must be an object");
|
|
const auto value = options->find("freecam_controller");
|
|
if (value == options->end()) return false;
|
|
require(value->is_boolean(), "freecam_controller must be a boolean");
|
|
return value->get<bool>();
|
|
}
|
|
std::uint32_t freecam_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("freecam");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Freecam binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Freecam binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
std::uint32_t tp_to_freecam_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("tp_to_freecam");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"TP to Freecam binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in TP to Freecam binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
std::uint32_t noclip_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("noclip");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Noclip binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Noclip binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
|
|
std::uint32_t forward_velocity_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("forward_velocity");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Forward velocity binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Forward Boost binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
|
|
// Yes or No in a server's vote. Never set: the default key. Cleared by the player: 0, none.
|
|
static std::uint32_t vote_binding(const Snapshot& s, const char* key, std::uint32_t fallback) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return fallback;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find(key);
|
|
if (value == bindings->end()) return fallback;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Vote binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in a vote binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
std::uint32_t vote_yes_binding(const Snapshot& s) { return vote_binding(s, "vote_yes", default_vote_yes_binding); }
|
|
std::uint32_t vote_no_binding(const Snapshot& s) { return vote_binding(s, "vote_no", default_vote_no_binding); }
|
|
std::uint32_t offboard_up_velocity_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("offboard_up_velocity");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Off-board Up Boost binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Off-board Up Boost binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
std::uint32_t up_velocity_binding(const Snapshot& s) {
|
|
const auto bindings = s.settings.find("bindings");
|
|
if (bindings == s.settings.end()) return 0;
|
|
require(bindings->is_object(), "Bindings must be an object");
|
|
const auto value = bindings->find("up_velocity");
|
|
if (value == bindings->end()) return 0;
|
|
require(value->is_number_unsigned() || (value->is_number_integer() && value->get<std::int64_t>() >= 0),
|
|
"Up velocity binding must be a nonnegative integer");
|
|
const auto mask = value->get<std::uint64_t>();
|
|
require(mask <= UINT32_MAX && valid_action_binding(static_cast<std::uint32_t>(mask)),
|
|
"Unsupported controller or keyboard key in Up Boost binding");
|
|
return static_cast<std::uint32_t>(mask);
|
|
}
|
|
|
|
}
|