mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-09 15:54:47 -07:00
implement gameboard v1
This commit is contained in:
parent
b103db681b
commit
0d7336edc2
177 changed files with 16995 additions and 139 deletions
|
|
@ -0,0 +1,73 @@
|
|||
// Byte-level verification that Command_AttachCard's proto2 optional target
|
||||
// fields stay UNSET when we build an "Unattach" — i.e. the client omits
|
||||
// them entirely rather than sending sentinel values. Desktop's server-side
|
||||
// `has_target_player_id()` / `has_target_zone()` / `has_target_card_id()`
|
||||
// drives the unattach branch; if any target field gets serialized, the
|
||||
// server treats it as a re-attach instead of an unattach.
|
||||
//
|
||||
// See the M6 Unattach deferrable in webclient/plans/gameboard-deferrables.md.
|
||||
|
||||
import { create, isFieldSet, toBinary, fromBinary } from '@bufbuild/protobuf';
|
||||
import { Command_AttachCardSchema } from '@app/generated';
|
||||
|
||||
describe('Command_AttachCard proto2 presence (Unattach invariant)', () => {
|
||||
it('omitting target fields leaves them unset on the in-memory message', () => {
|
||||
const msg = create(Command_AttachCardSchema, {
|
||||
startZone: 'table',
|
||||
cardId: 10,
|
||||
});
|
||||
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.startZone)).toBe(true);
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.cardId)).toBe(true);
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.targetPlayerId)).toBe(false);
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.targetZone)).toBe(false);
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.targetCardId)).toBe(false);
|
||||
});
|
||||
|
||||
it('omitting target fields omits them from the serialized bytes', () => {
|
||||
const msg = create(Command_AttachCardSchema, {
|
||||
startZone: 'table',
|
||||
cardId: 10,
|
||||
});
|
||||
|
||||
const bytes = toBinary(Command_AttachCardSchema, msg);
|
||||
// Round-trip to confirm the wire format also reports the fields unset.
|
||||
const parsed = fromBinary(Command_AttachCardSchema, bytes);
|
||||
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetPlayerId)).toBe(false);
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetZone)).toBe(false);
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetCardId)).toBe(false);
|
||||
});
|
||||
|
||||
it('passing an explicit targetPlayerId DOES set presence (so "attach" paths still work)', () => {
|
||||
const msg = create(Command_AttachCardSchema, {
|
||||
startZone: 'table',
|
||||
cardId: 10,
|
||||
targetPlayerId: 5,
|
||||
targetZone: 'table',
|
||||
targetCardId: 99,
|
||||
});
|
||||
|
||||
const bytes = toBinary(Command_AttachCardSchema, msg);
|
||||
const parsed = fromBinary(Command_AttachCardSchema, bytes);
|
||||
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetPlayerId)).toBe(true);
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetZone)).toBe(true);
|
||||
expect(isFieldSet(parsed, Command_AttachCardSchema.field.targetCardId)).toBe(true);
|
||||
expect(parsed.targetPlayerId).toBe(5);
|
||||
});
|
||||
|
||||
it('setting a target field to its default -1 still records presence (presence != default)', () => {
|
||||
// This is the trap the deferrable warned about: proto2 `optional` with a
|
||||
// default of -1 treats an explicit `-1` as "field set with value -1",
|
||||
// which the server interprets as "attach to slot -1" rather than unattach.
|
||||
// Clients must OMIT the field entirely to unattach.
|
||||
const msg = create(Command_AttachCardSchema, {
|
||||
startZone: 'table',
|
||||
cardId: 10,
|
||||
targetPlayerId: -1,
|
||||
});
|
||||
|
||||
expect(isFieldSet(msg, Command_AttachCardSchema.field.targetPlayerId)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -34,6 +34,8 @@ import type {
|
|||
MulliganParams,
|
||||
RollDieParams,
|
||||
GameCommand,
|
||||
CreateGameParams,
|
||||
JoinGameParams,
|
||||
} from '@app/generated';
|
||||
|
||||
import type { ConnectTarget } from './WebClientConfig';
|
||||
|
|
@ -84,6 +86,8 @@ export interface IRoomsRequest {
|
|||
joinRoom(roomId: number): void;
|
||||
leaveRoom(roomId: number): void;
|
||||
roomSay(roomId: number, message: string): void;
|
||||
createGame(roomId: number, params: CreateGameParams): void;
|
||||
joinGame(roomId: number, params: JoinGameParams): void;
|
||||
}
|
||||
|
||||
export interface IAdminRequest {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue