mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-06 13:33:55 -07:00
Wire command zone menu, harden counter command handling, and expand tests
- Connect aMoveToCommandZone to cmMoveToCommandZone; the menu item was
added, shown, and shortcut-bound but never wired, so it did nothing
- Extract evaluateModifyCounter() and route cmdIncCounter/cmdSetCounter
through it, replacing isCommandZoneCounterBlocked; reject inc/set on
an inactive tax counter so a hidden counter cannot accumulate value
- Reject reserved tax counter names in cmdCreateCounter to prevent a
client from spoofing a system tax counter via a user-created counter
- Route AbstractCounter::valueChanged through the virtual setValue() so
CommanderTaxCounter clamps and refreshes its tooltip on value changes
- Deduplicate actPlayAndIncreaseTax/actPlayAndIncreasePartnerTax into a
single playAndIncreaseTax(counterId) helper
- Move MINIMUM_STACKING_HEIGHT from CommandZone to the PlayerGraphicsItem
layout code, its only consumer
- Remove unused AbstractCounter forward declaration from player_logic.h
- Add EvaluateModifyCounter tests and PartnerTax cases for
evaluateSetCounterActive
- Pin the FirstUserId floor in new_counter_id_test using ids 3 and 5 so
a naive "highest id + 1" regression fails the test
This commit is contained in:
parent
0bfb0f4131
commit
bc09a19b50
11 changed files with 172 additions and 47 deletions
|
|
@ -441,10 +441,33 @@ Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer &
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool Server_Player::isCommandZoneCounterBlocked(int counterId) const
|
||||
Response::ResponseCode Server_Player::evaluateModifyCounter(bool gameStarted,
|
||||
bool playerConceded,
|
||||
bool commandZoneEnabled,
|
||||
int counterId,
|
||||
const Server_Counter *counter)
|
||||
{
|
||||
return (counterId == CounterIds::CommanderTax || counterId == CounterIds::PartnerTax) &&
|
||||
!game->getEnableCommandZone();
|
||||
if (!gameStarted) {
|
||||
return Response::RespGameNotStarted;
|
||||
}
|
||||
if (playerConceded) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
if (CounterIds::isTaxCounter(counterId)) {
|
||||
// Tax counters are server-managed: they only exist in Commander games, and an
|
||||
// inactive (hidden) tax counter must stay at zero. Block modification in either
|
||||
// case so the value can never diverge from what players can see.
|
||||
if (!commandZoneEnabled) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
if (counter && !counter->isActive()) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
}
|
||||
if (!counter) {
|
||||
return Response::RespNameNotFound;
|
||||
}
|
||||
return Response::RespOk;
|
||||
}
|
||||
|
||||
Response::ResponseCode
|
||||
|
|
@ -458,14 +481,12 @@ Server_Player::cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &
|
|||
}
|
||||
|
||||
const int counterId = cmd.counter_id();
|
||||
|
||||
if (isCommandZoneCounterBlocked(counterId)) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
Server_Counter *c = counters.value(counterId, nullptr);
|
||||
if (!c) {
|
||||
return Response::RespNameNotFound;
|
||||
|
||||
const Response::ResponseCode authResult =
|
||||
evaluateModifyCounter(game->getGameStarted(), conceded, game->getEnableCommandZone(), counterId, c);
|
||||
if (authResult != Response::RespOk) {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
bool didChange = c->incrementCount(cmd.delta());
|
||||
|
|
@ -489,8 +510,15 @@ Server_Player::cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContai
|
|||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
auto *c = new Server_Counter(newCounterId(), nameFromStdString(cmd.counter_name()), cmd.counter_color(),
|
||||
cmd.radius(), cmd.value());
|
||||
const QString counterName = nameFromStdString(cmd.counter_name());
|
||||
// Reserved system counter names (commander/partner tax) are how clients identify
|
||||
// server-managed tax counters for rendering and logging; a client must not be able
|
||||
// to spoof one via a user-created counter.
|
||||
if (CounterNames::isTaxCounter(counterName)) {
|
||||
return Response::RespFunctionNotAllowed;
|
||||
}
|
||||
|
||||
auto *c = new Server_Counter(newCounterId(), counterName, cmd.counter_color(), cmd.radius(), cmd.value());
|
||||
addCounter(c);
|
||||
|
||||
Event_CreateCounter event;
|
||||
|
|
@ -516,14 +544,12 @@ Server_Player::cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &
|
|||
}
|
||||
|
||||
const int counterId = cmd.counter_id();
|
||||
|
||||
if (isCommandZoneCounterBlocked(counterId)) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
Server_Counter *c = counters.value(counterId, nullptr);
|
||||
if (!c) {
|
||||
return Response::RespNameNotFound;
|
||||
|
||||
const Response::ResponseCode authResult =
|
||||
evaluateModifyCounter(game->getGameStarted(), conceded, game->getEnableCommandZone(), counterId, c);
|
||||
if (authResult != Response::RespOk) {
|
||||
return authResult;
|
||||
}
|
||||
|
||||
bool didChange = c->setCount(cmd.value());
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ class Server_Player : public Server_AbstractPlayer
|
|||
private:
|
||||
QMap<int, Server_Counter *> counters;
|
||||
QList<int> lastDrawList;
|
||||
bool isCommandZoneCounterBlocked(int counterId) const;
|
||||
|
||||
public:
|
||||
Server_Player(Server_Game *_game,
|
||||
|
|
@ -37,6 +36,14 @@ public:
|
|||
int counterId,
|
||||
const Server_Counter *counter,
|
||||
bool requestedActive);
|
||||
// Authorization shared by cmdIncCounter and cmdSetCounter. Reserved tax counters
|
||||
// may only be modified inside a Commander game and only while active, so that an
|
||||
// inactive (hidden) tax counter can never accumulate a value behind the scenes.
|
||||
static Response::ResponseCode evaluateModifyCounter(bool gameStarted,
|
||||
bool playerConceded,
|
||||
bool commandZoneEnabled,
|
||||
int counterId,
|
||||
const Server_Counter *counter);
|
||||
|
||||
void setupZones() override;
|
||||
void clearZones() override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue