/warx

Silly multiplayer game. Play here:

Primary LanguageJavaScriptGNU General Public License v3.0GPL-3.0

warx

CircleCI

Background

I wanted to see if I could create a multi-player game with React and Redux, using some stuff I wanted to try out for a while, like RxJS and Flow.

Contributions and usage

Any issues or ideas are welcome in the Github issues. I have no clear goal for this, so any improvements are welcome in PRs, also game-play. Feel free to fork and run your own instances, but please note this project is under the GNU General Public License v3.0.

Build and deploy

This is still a bit awkward with some .sh files, because we need to copy some client files into the server, etc.

If you run your own server, you can choose to let this server register itself with a www.warx.io. Your server will then appear on all other servers that registered themselves with this 'hub'.

Build

Running ./build.sh will create a production ready version in the ./dist folder. This will build both the server and client. To run it, run yarn start from the ./dist folder.

Environment vars

When running the server you can set these env vars:

ENV Variable Description
HUB The central hub to register your server with, your server will appear on all other servers registered this this hun. Default: http://www.warx.io
ADDRESS Your server's http(s) address, this is where players will be redirected to if they choose to join your server
SERVER_NAME The name of your game server that will appear on all server lists
LOCATION Geographical location, so players can join a server close to them.
NUM_BOTS Number of bots to start the server with.
MAX_PLAYERS Maximum number of players that can join your server. More than 10 doesn't run smoothly at the moment.

More env vars will be added related to rules

Deploy to Heroku

  1. Create a heroku app and add the needed env vars to your app
  2. Build using ./build.sh from the root project folder
  3. Run ./heroku.sh from the root project folder
  4. Fill in your app name in the prompt

Deploy to Now.sh

  1. Build using ./build.sh to build to ./dist
  2. Create an .env.production file and fill in the needed env vars
  3. From the dist folder now --dotenv=./.env.production
  4. Set your now alias to the server name you chose in the env vars

Tests

Jest is used for unit tests. Run yarn test in the root dir to run the server tests or in the client dir to run the client tests.

CI

CircleCI is configured to run the tests in this repository on every branch and master. Tests must pass on PRs before merging.

Server and client

This project is split up in a Node Express server and a React.js client. The server lives in the root dir, with the source in the server dir. The client lives in the client subdirectory. Shared code can be placed in the client directory where the server can access it. Note: at the moment this does not work correctly because of different babel configurations.

Architecture

Each of these should be replacable with out touching other layers much. Ideally each layer should only touch the one below:

  1. client (see client architecture in client/README.md)
  2. www (http server)
  3. app (express)
  4. network messages (send and get messages, now socket.io, possibly plain websockets)
  5. messages-actions (network-state-glue: translates network messages to redux actions vice versa)
  6. game state (redux + redux-observable, possibly mobx or redux + sagas)
  7. data sources (not yet implemented)

Modules in state

The state folder is where the business logic lives. This is the largest layer and is split up in several modules. Each module can export initial state, actions, reducers, selectors and epics. These modules can be generated by using plop module.

Network messages

This application shares redux actions between server and client, actions can be marked as any of these:

  • client-to-client actions (i.e. opening a panel)
  • client-to-server actions (i.e. connect request, move request)
  • server-to-client actions (i.e. new connection, player moved)
  • server-to-server actions: update server state without directly sending to client(s)

Actions which are client-to-server or server-to-client will also be dispatched at its origin. This means actions must be unique between client and server. This should be tested somehow, possibly at runtime (todo).

Option 1 (used now): set this type on the action

  • pro: the type is defined where the action is defined
  • con: the types of actions are scattered across modules, it's not easy to see which actions will be sent to the client in one spot

Option 2: keep a list of these types in a single file

  • pro: it's easy to see which client-actions will be sent to the server and which server actions will be sent to the client in one spot
  • con: needs a separate list of actions

Option 3: ditch shared actions, for special messages

  • pro: separate client and server actions
  • con: extra translation between messages and actions needed