An API-based multiplayer game where you purchase mining equipment and various resources to become rich.
Run the service:
./scripts/run.sh
To build for Windows, Mac, and Linux:
./scripts/build.sh
To create release binaries (includes build.sh):
./scripts/release.sh
Releases are versioned with the latest git tag under the release folder (ex: release/v1.1.0-17-gfdba3eb).
Build the latest Docker container image:
make docker
Run a container:
docker run --rm -p 9090:9090 miningpost
This is a fun hobby project that is not intended for actual production use. This server cannot, in its current state, scale out horizontally, only vertically. Since everything is stored in memory while running and no complex calculations are being made, it is very lightweight and very performant. As such, this project uses a simple embedded key-value database for storing player data.
The database chosen for this project is bbolt, which is a fork of the no longer maintained boltdb. Bolt is simple, fast, and written in pure Go. There might be scaling/performance concerns for very large amounts of data, but for the data being stored for this project, Bolt should be more than sufficient.
Here are some other options that were considered and are most likely just as viable:
- BadgerDB: Fast key-value storage written in Go.
- RocksDB: Fast key-value storage written in C++.
- LevelDB: Fast key-value storage created by Google and written in C++.
- SQLite: Small, fast, self-contained, SQL database. Cannot have more than one concurrent writer.
If this project was going to be deployed and made available to the public, a more commercial option would be used. Most likely one of the following:
- AWS DynamoDB: Fast, robust, and easy-to-use key-value storage.
- AWS Aurora PostgreSQL: Managed PostgreSQL that is highly available and performant, but expensive.
- CockroachDB: Distributed SQL database that is designed to scale.
- Redis: Fast in-memory cache that can also persist data.
- Need a way to calculate net worth outside of current money (use net worth for promotions). Net worth would be value of resources, equipment, employees, land, etc.
- Add type to listings and filter capability for name and type
- More ranks? Like amatuer and apprentice and mining engineer?
- Related to ranks, adjust salaries. Should start with a very low salary.
- Add equipment (like pickaxes and mine carts) and buildings (like a mine)
- Add a mine/dig option? Use pickaxes to get minerals?
- Maybe a prospect option to find more land? Call the land claims and they are non-producing unless you dig? Land can be built into mines?
- Add high score table that lists the top ten players by net worth
- Put instructions in a markdown file and use embed to add to handler
- Should not be able to buy or sell quantity 0 or negative
- List market should show time remaining.
- Should round values before returning to player. I saw this happen again with money somehow... Would be nice if money was formatted as a string like
"$12.30"
- Better locking system.
- Need a way to save player data. Postgres or maybe just hack JSON file for now? There are some decent free embedded databases, like maybe bolt or sqlite? Keep everything in memory and just save at the end of every update. Works for now, but won't allow scaling horizontally.
- Need something to autogenerate developer docs. Swagger? OpenAPI?
- Host developer docs on public endpoint
- Need to perf test updates with a large number of users, like 1 million users
- Need to separate data models and contract models. I tried it both ways and keeping them combined, as expected, is turning into more of a pain than mapping
- Add retries to client. Use Rican7 package.
- Add middleware to limit request size. Is there pre-existing middleware in the chi library? Write it myself?
- Add middleware for request id. Add request id to all logs for a transaction. Maybe add a helper function like I have for errors, requestIDAttr?
- Create dummy auth endpoint that generates a JWT regardless of password. (/game/signup to create an account in the accounts db bucket. /game/token to get an access token.)
- Create authorizer middleware to properly validate JWT. Client ID should be passed in headers and/or context. Is there anything out there I can use? Or just write it myself?
- All /game endpoints need to be public, no auth. Everything else should be protected by auth.
- Add rate limiting for requests. Is there pre-existing middleware in the chi library? (chi library only has throttling for total number of requests, not per user) Write it myself with semaphore? (need client id in headers/context from authorizer first)
- Should I add middleware to allowlist certain content types and encodings? (go-chi has AllowContentType and AllowContentEncoding)
- Enforce TLS 1.2 or greater on the server (already enforced)
- Run locally using TLS with test certs (generated new test certs good for 100 years that work with 127.0.0.1. Had to do some weird stuff to add the IP SAN for 127.0.0.1 and insecureskipverify needs to be true since certs are self-signed)
Potential options for rate limiting (besides writing it myself) that can limit per user per unit of time (like no more than 60 requests per minute for player "tstark"):