|
|
5 years ago | |
|---|---|---|
| .vscode | 5 years ago | |
| protobuf | 5 years ago | |
| server | 5 years ago | |
| unity | 5 years ago | |
| .gitattributes | 5 years ago | |
| .gitignore | 5 years ago | |
| README.md | 5 years ago | |
README.md
cards-simulator
Gaem.
The server
When run it creates a properties.json with some configs, output.log with the server output, and the games folder. Inside that folder games can be placed. For now only games coded in Rhai are supported, but myabe later support is added for wasm based games, or shared libraries, although the latter is quite unsafe and its support is quite unprobable.
Making a game
The most important part of the game is the game.json file. It contains the metadata and many attributes for the game.
($json_schema is where the file located in server/schema/game-config.json, in the future a public link will be offered)
{
"$schema": "$json_schema",
"name": "UNO",
"version": "0.0.0",
"authors": ["ThePerkinrex"],
"script": "game.rhai",
"default_back": "cards/uno_back.png",
"available_cards": {
"B0": {
"image": "cards/blue0.png"
},
"+4": {
"image": "cards/plus4.png"
}
},
"piles": {
"deck": {
"cards": [
"B0", "+4", "+4", "+4", "+4"
]
},
"placed": {}
},
"player_piles": {
"deck": {}
}
}
In this file, firstly, the name of the game, the version and the authors are specified. The script (the game logic), is also specified, and the rest is the definition of the structure:
available_cardscontains the cards by id, which can have animageandback_image, this last one is not required when thedefault_backproperty is set.pilescontains the card piles common to all players, these are named, and can have default cards placed in them.player_pilesare the same aspilesbut specific to each player, so when the game is setup, a clone is created for each of the players.- lastly,
default_back, which isn't required as long as all the cards have aback_imageproperty, has the back image which will be used whenback_imageisn't specified.
Then we have the script, in this case game.rhai:
// setup(data) -> data
fn setup(data) { // Required
print("Setting up UNO for " + data.players + " players");
data.piles.deck = shuffle(data.piles.deck);
for i in range(0, 2) {
for player_idx in range(0, data.player_piles.len) {
let drawed_card = data.piles.deck.cards.pop();
data.player_piles[player_idx].deck.cards.push(drawed_card);
}
}
data.fw = true;
// Sets the turn direction used in UNO.
// This is an example of how the data object keeps custom properties, like some kind of global variable
return data;
}
// turn_end(data, player) -> [data, next_player]
fn turn_end(data, player) { // Required
print("Turn for " + player + " ending");
if data.fw {
player.add(1);
}else{
player.sub(1);
}
return [data, player];
}
// turn_start(data, player) -> data
fn turn_start(data, player) { // Not required
print("Turn for " + player + " starting");
return data;
}
// turn_start(data, card_clicked, action_author, current_player) -> [data, turn_has_ended]
fn on_click(data, card, action_author, current_player) { // Required
if action_author == current_player {
if card.pile_kind == "common" {
if card.pile_name == "deck" {
// Get a card from the deck
let c = data.pop_card(card);
data.player_piles[player.val].deck.cards.push(c);
}
}else{
if card.pile_name == "deck" {
let c = data.pop_card(card);
data.piles.placed.cards.push(c);
}
}
return [data, true];
}
return [data, false];
}
See for example the shuffle function, which is provided by the environment.
Go to the rhai book for the language reference.
Common errors:
- When taking more cards than are available from a pile,
()(null or undefined) is returned, that happens for example when too many people try to play a game where a specific number of cards from a deck are given to each player, and there are too many players for the amount of cards in the deck