Repository navigation
Game State
Communication between server and clients is handled using XML payloads containing information about the current verified game state.
Card structure
<Card>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Frontface>svg</Frontface>
<Backface>svg</Backface>
<Attributes>
<StringAttribute>
<Name>attribute1</Name>
<Value>string</Value>
<StringAttribute>
<IntAttribute>
<Name>attribute2</Name>
<Value>3</Value>
</IntAttribute>
<BoolAttribute>
<Name>attribute3</Name>
<Value>false</Value>
</BoolAttribute>
<Attributes>
<Geometry>
<PositionX>120</PositionX>
<PositionY>120</PositionY>
<Rotation>0</Rotation>
<Scaling>1</Scaling>
<FrontFacing>true</FrontFacing>
<ZIndex>1</ZIndex>
</Geometry>
</Card>
Actor structure
<Actor>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Name>John Doe</Name>
<ProfilePicture>svg</ProfilePicture>
<Visible>true<Visible>
<Statistics>
<Public>
<StatisticsEntry>
<Visible>true</Visible>
<Icon>svg</Icon>
<StringAttribute>
<Name>attribute1</Name>
<Value>string</Value>
<StringAttribute>
</StatisticsEntry>
</Public>
<Private>
<StatisticsEntry>
<Visible>true</Visible>
<Icon>svg</Icon>
<BoolAttribute>
<Name>attribute</Name>
<Value>true</Value>
<BoolAttribute>
</StatisticsEntry>
</Private>
</Statistics>
</Actor>
Slot structure
<Slot>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Hidden>true</Hidden>
<Cards>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
</Cards>
<Actors>
<ActorEntry>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Permission>Read</Permission>
<Owner>true</Owner>
</ActorEntry>
<ActorEntry>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Permission>ReadWrite</Permission>
<Owner>false</Owner>
</ActorEntry>
<ActorEntry>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<Permission>Read</Permission>
<Owner>false</Owner>
</ActorEntry>
</Actors>
</Slot>
GameState
<GameState>
<Metadata>...</Metadata>
<Deck>
<Card>...</Card>
<Card>...</Card>
</Deck>
<Board>
<Slot>...</Slot>
<Slot>...</Slot>
</Board>
<Actors>
<Actor></Actor>
<Actor></Actor>
</Actors>
</GameState>
At the beginning, all clients receive game state (cut off from any information about other users); in the process of the game, each client receives just partial game state based on the delta update principle: missing properties signal no change.
In ordinary delta update architecture, we could have supported properties marked as <Property xsi:nil="true"> signalling removal of the entry. To allow the server to distinguish between "omitted" and "explicitly null", every nullable property must be paired with an ignored boolean tracking property:
[XmlElement(IsNullable = true)]
public string? Name { get; set; }
[XmlIgnore]
public bool NameSpecified { get; set; } // Auto-set by .NET.
However, we decided not to support removal of individual properties, meaning at the beginning, XML is fully constructed, and from this point, missing properties mean no change only.
We support delete (update) of items in a list, though. Any item that goes into a list (Cards, Actors, Attributes) should inherit from a base class (ListItem) containing a Guid (actually, our classes contain Guid themselves) and a _Tombstone _flag. To completely remove an object from a list, send its Guid and set the deletion flag to true:
<Attributes>
<IntAttribute>
<Guid>123e4567-e89b-12d3-a456-426614174000</Guid>
<IsDeleted>true</IsDeleted>
</IntAttribute>
</Attributes>
GameState.prepareXml(IActor actor) -> XmlDataGameState.update(XmlData xmlData) -> void