maelstromeous / cards Goto Github PK
View Code? Open in Web Editor NEWA online card game replica of a popular card game (CAH) designed for small groups
A online card game replica of a popular card game (CAH) designed for small groups
Proper thought needs to be applied to the game data / state. This needs to be a highly portable body of data in order to syncronise with clients quickly and efficently.
Data objects can be kept small by ensuring that card data (the text within the cards themeselves) is kept seperate from game data.
A lite version will be made available for the homepage game list. This is the full fat version.
{
"id": "magnum-detroit",
"name": "Pigs DO fly!",
"status": "playing",
"locked": true, // Server still maintains authority on this. It will ignore the client when checking they can join the game.
"validToJoin": true, // Denotes whether the game is accessible from the server itself to render for the client. Note the server has authority, it will ignore the client when joining the game.
"roundCount": 1, // How many rounds this game has played
"people": { // Expanded array of player objects without their sessionIds
"host": {
"id": "UUID4",
"name": "Maelstromeous",
"score": 1,
"ready": true // Denotes if the player has all cards loaded etc, reported from the client
"chosenCard": "UUID4", // Player's card choice, if they have one yet
},
"players": [{
"id": "UUID4",
"name": "SomeAwesomeDude",
"score": 2,
"ready": true,
"chosenCard": "UUID4",
}],
"spectators": [{}]
},
"options": {
"gameType": "tsar", // Denotes game's type, quite important
"scoreToWin": 5,
"maxPlayers": 6, // Impose hard limit?
"maxSpectators": 10, // Impose hard limit?
"packs": [123, 1234, 12345] // Packs enabled for the game
"chatEnabled": true,
"roundTimer": 30, // Seconds to give players to make choices before random selection
"idleTimer": 120 // Seconds before booting players from the session
},
"typeSpecificData": { // Made this mode specific as it depends on game type. Signifies who's the tsar.
"tsar": {
"currentTsar": "Player3 UUID",
"previousTsars": [ // The updating of this has to be done carefully, otherwise a player might have tsar multiple times.
"Player1 UUID",
"Player2 UUID",
"Player3 UUID"
],
"nextTsar": "Player4 UUID"
}
},
"cards": { // Holds state of cards in play, this'll be a bit tricky. Card text etc will be exposed via API calls
"black": {
"id": "UUID4"
},
"white": [{
"player1 UUID": {
"cards": ["UUID4", "UUID4"] // Array of 10 cards
}
}]
},
"serverSide": { // Details not to be exposed to the client to prevent cheating etc, could be done at API level rather than an object like this.
"gamePassword": "foobar", // Stored as a hash obvs
"bannedPlayers": [], // List of player IDs who are banned from the game
"cards": {
"played": { // List of card IDs already played so the server doesn't give players the same cards
"white": ["UUID4"],
"black": ["UUID4"]
}
}
},
}
Bare minimum needed to render the homepage, this will be requested via an API call with a certain flag.
{
id: 'shark-tale',
name: 'A medium game',
status: 'lobby',
locked: true,
validToJoin: true,
people: {
host: {
name: "Warcore"
},
players: [
{name: "SomeAwesomeDude"},
{name: "SomeAnnoyingDude"},
{name: "A lady in red"},
{name: "A dude in blue"},
{name: "A gentlemen in blue"},
]
},
options: {
pointsToWin: 5,
maxPlayers: 7,
},
winConditions: {
type: 'tsar',
}
},
{
"id": "UUID4",
"name": "Maelstromeous",
"sessionId": "somerandomcookiestring",
}
{
"id": 123,
"name": "PAX Prime 2014",
"official": true
}
{
"id": "UUID4",
"type": "white",
"text": "ADVENTURE!",
"pack": 123
},
Note here there's an extra pick
attribute.
{
"id": "UUID4",
"type": "black",
"text": "Aww babe, your burps smell like _!",
"pick": 1, // Max 3?
"pack": 123
}
Tools and technologies we're going to use in the project
Design / outline of the functionality of the project, what the experience is going to be etc.
The purpose of the project is to provide a better online Cards Against Humanity experience. There are a few websites that do this, notably https://pretendyoure.xyz/zy/, which has a number of issues I intend to correct:
Firstly, the design of the site has to be visually appealing in order to achieve popularity. The site should also be themeable, should the user want to use white mode or dark mode etc. This could be easily achieved with a CSS framework and proper application of sensible design.
Thought has to be put into mobile. It's no longer out of the realms of reality that card games are being played on phones over VoIP calls e.g. Discord etc for fun.
So the game itself will heavily match Cards Against Humanity, which is basically the following premise:
There are various card packs out there. For the Alpha, I'll be choosing the classic pack, then implement the other packs at a later date. Thankfully, there is a website with the entire set of CAH packs available as a JSON download: https://crhallberg.com/cah/
To address the issues of say pretendyoure.xyzzy, the experience needs to be butter smooth. Namely the specifics:
In order to properly seperate cards, each card contained within the JSON Against Humanity DB (https://crhallberg.com/cah/) needs to be ingested into a NoSQL database, in the format as determined by #19.
This will require a mechanism to ingest the data.
Full file available in root, cah-cards.json
.
Need to think about how to prevent sending invalid data to the game state with cards that don't exist etc. Perhaps a server centric model is warrented with changes to game state being pushed to users rather than polled from users.
Server should be authority - if a card that has been played isn't recognised by the server, it should be chucked, and a potential warning in the chat displayed.
Create a database of quirky chat lines, such as:
Setting up of the stack required to run the project.
This is likely going to be run on K8s for hosting simplicity for myself, plus it'll be nice to get back into K8s again.
Would be nice to add game variations, e.g.:
Registering appropiate domain name
I believe this should be an opportunity to finally get into automated tests.
So for the connection, Socket.io(Websocket/Http) or a Websocket is used. This means connections use TCP, meaning packet drop is not an issue however this might add some lag. More lag can occur due to the single connection with bidirectional chatter.
Connections will look like the following. The first part is the heartbeats, the client(once connected) will start sending these at a fixed interval, and the server will respond with an acknowledgment of it. Failure to send a heartbeat or receive an acknowledgment means the connection has gone bad and needs to be terminated/disconnected. The server has to account for network lag. Socket.io has this functionality by default, and this information is here for the sake of completion.
The next step is identification. The client before connecting should have already created an identification token using an Http endpoint. The identification is used to start a session. The client will receive a session token in return. Optional a user can send a session id with an event number. These last ones can be used to resume a connection/session. When identified any messages that are sent to the client will have an event counter to keep track of received messages in case of a reconnect. This is only there to continue where a client left on resuming. Note that the server only keeps these events for a certain amount of time, meaning resuming is not always possible.
A new session, will receive information on all games that are public/joinable. From there it can send a command to join a game.
When joining a game. It will receive the game state from the perspective of the client. This includes public elements of the game(e.g. the black card, list of submitted white cards with or without content, player stats, and any additional metadata) and the unique player elements(e.g. list of white cards, and any additional metadata). The information should be sent in such a way that no information is exposed that can be used to cheat(e.g. the content of a card when face down, links between players and cards).
From here the client will receive updates of the game states, and these messages will be used to patch the game state. This will reduce the amount of traffic and be a good fit for Vue, but will however complicate the code as the patch/merge mechanism needs to be solid to avoid incorrect states. Handling the correct order of events will be very important.
The client will have depending on the metadata/game state the ability to send certain commands(e.g. to submit cards, choose a winner). These are done through means of the update messages similar to those received from the server. This means that a permission system needs to be in place on the server to validate the commands and make sure that they are allowed from the perspective of the server. However if possible network lag needs to be a consideration. This can be done by letting the client know in some way or form that it cannot send a command before actually invalidating them(e.g. round state goes from active, to finishing, to ended).
I also would recommend separating the game and chat. Mainly as chat has other considerations than the game in terms of netcode. Also, some hard limits need to be in place when it comes to the game so the games will stay playable. Limits can be static or a more dynamic system can be in place where newer games can be moved to another server. Also, static limits can be loosely defined at first and be tightened later on.
Design of the site template, overall themes, general feel of the product.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.