project screenshot 1
project screenshot 2
project screenshot 3

Garnet

Eternal Legends, a blockchain-based turn-based tactical game, combines MUD2, Solidity, and GoLang. Players select 3 heroes to protect their castles in battles fought on an ASCII graphical interface. Powered by Garnet, a custom MUD2 indexer, transaction builder and backend.

Garnet

Created At

Autonomous Worlds

Winner of

trophy

🏆 Autonomous Worlds Finalist

Project Description

Summary: it's a full-on blockchain game that uses MUDv2 utils to create and upload contracts to the blockchain. The difference with the MUD's templates is that I use a backend to handle all the crypto-related functionality and the client just gets the board status and send actions to the backend without knowing that there is a blockchain storing all the information.

This is to keep the autonomous world idea where any other dev can use the world data and expand it as much as it wants, but without requiring all the game users to keep track of their wallets and keeping their mnemonics safe (we delegate the responsibility to the backend). Also removing all the crypto complexity from the client, makes it easier to have multiple implementations of the client connecting to the same backend.

The project has two binaries:

  • Garnet (server)
  • Eternal Legends (client)

Game logic:

  • The game logic was written using Mud's v2 lib.
  • The solidity contracts get deployed using mud-cli

Garnet (the server) has 4 parts:

  • Indexer: It reads the information from the blockchain using each block's events.
  • Database: It stores all the world's information in an in-memory structure.
  • WebSocket: It allows any client to get the already processed information and allows the creation, signing, and broadcasting of transactions.
  • TxBuilder: It handles wallet creation, contract interactions, transaction creation, signatures, and broadcasting. It also provides a faucet to get coins.

Eternal Legends (the client):

  • It connects to the backend using WebSockets
  • It allows the user to create new games.
  • It displays all the games to the user, so the user can join a game.
  • It displays the board status and allows users to interact with the game.

Eternal Legends rules

  • The board is 10x10 square.
  • Each player has a base with 10 health points.
  • At the start of the game, the player has 5 Mana available. After each turn the total mana available increases by one, up to 15. (The mana leftovers are not carried to the next turn)
  • Each player has 6 different types of units.
  • Each player can summon up to 3 units, each summon has a cost of 3 Mana. The unit can only be placed in the same rows as the player's base.
  • Moving a unit has a cost of 2 Mana, the distance that you can move a unit is determined by the Movement speed of that unit.
  • Each unit can attack once every turn, after striking the unit can no longer move or attack until the next turn.
  • When a base health point reaches 0, the game ends.

For a more detailed explanation, you can check the repo's readme, it has a diagram included at the end of the file.

How it's Made

This project started as a fun way to fully understand how MUD works, because after reading some of the documentation I wanted to move all the players' actions predictions to the backend and share that prediction between all the clients in order to reduce the latency imposed by the block times.

MUD is a gaming web3 tooling so I decided to create an example game to try my code. I realized that there were no CLI games/libs available that integrate with MUD, so I imported a GoLang lib called gocui and started working on the game template.

The first step to creating the backend was to code an indexer that parsed and stored all the transactions events, reading and reusing some of the MODE code functions was useful to start coding.

To populate the blockchain with events, I created the first version of the game contracts and deployed them using the MUD's templates, this allowed me to send transactions using the react client.

After storing all the information in a in-memory database I needed a way to read the values to be sure that everything was correctly stored. I used this opportunity to keep playing with the gocui lib and created the Garnet cli that just displayed the database values in the terminal, auto-updating it's contents every time a MUD transaction was included in a block.

With the index data being displayed with Garnet, I needed a way to send transactions without using the MUD react's templates, so I created a transaction builder inside my Go codebase. The transaction builder uses the local blockchain validator wallet to send coins like a faucet to any user wallet, and it uses the information from the IWorld.abi.json file (autogenerated by the mud-cli) to interact with my deployed contracts.

Having all the pieces that were needed ready, I added a WebSocket server to Garnet to provide a way to get the blockchain information and to create/sign/send transactions.

I finally added a WebSocket client to the terminal game that I created in the first step and started to integrate with the backend, broadcasting the updated database status to the client and the client asking the backend to send the transactions.

I run out of time, so I didn't have time to start playing with the Mempool and try to make the optimizations with transactions predictions, but at least I'm at the point where I can start working on that.

background image mobile

Join the mailing list

Get the latest news and updates