Monks and Mages is a TCG-game built on React and socket.io

Overview

Monks and Mages

Monks and Mages is a trading card-style game inspired by Heroes of Might and Magic / Magic the Gathering. The gameplay is similar to Magic, but with vastly simplified rules. Players build decks, then pit these decks against 1-3 other players. Cards are inspired from a mix of medieval and Chinese settings

To play, visit: https://www.monksandmages.com/

This game is a work in progress. If you find bugs, feel free to let me know on the issues section of this project

Installation and Running

This game can be run locally if you have node v16.x and yarn installed globally

To get started:

yarn install
yarn dev

Go to http://localhost:3000/ to see the game (and open it in multiple browser windows to simulate multiple players)

To see sockets.io debug screen:

open https://admin.socket.io/#/sockets while running the app

This project also strives for extensive TDD and unit testing. To run tests in watch mode:

yarn test

To run tests for a particular file:

yarn test src/server/gameEngine/gameEngine.spec.ts

To run tests once through:

yarn ci

Core technologies

This project runs on a few core technologies:

Linting on this project is done via a combination of typescript, prettier, and eslint

Unit testing is covered via Jest and React Testing Library

Game rules

  • Players come with a deck of at least 50 cards
  • 2-4 players can play against each other
  • 7 cards to start, 1 card drawn per turn (unless starting player)
  • Players start with 15 life
  • Players lose when they either reach 0 or less life or attempt to draw from an empty deck
  • Cards come in 3 flavors: Resources, Units, and Spells
    • Resources are the basis for paying for the other two types of cards. When a player deploys a resource card (one per turn can be deployed), they add that resource to their casting pool. This casting pool refills every turn.
      • Casting costs are represented similarly to MtG. For instance, a lancer costs ( 🛠️ ), meaning a single iron can pay for one to be deployed onto the field
    • Units have a cost, an attack, and a health pool. The health of a unit ticks down whenever it is attacked. The attack determines
      • On a given turn, you can deploy as many units as you have space (max 6 units per player) and resources
      • Units can attack once per turn (some have > 1 attack / turn), and cannot attack the turn they are deployed
      • Units have 3 overarching types:
        • Soldiers: Non-magical units must attack soldiers, if any are present on the board. Soldiers are the 'tanks' of the game
        • Ranged: ranged units (including most magic units) can attack without getting 'hit back'
        • Magical: magical units can attack any target, including the opponent directly, even if there are soldiers present
    • Spells have an effect that is deployed immediately upon casting, such as:
      • Ember Spear ( 🔥 ) deal 3 damage to any target
      • A gentle gust ( 🔥 )( 🌊 ) buffs the team's stats by 1

Game philosophy

  • the game has 5 resources with separate identities:

    • Bamboo 🎋 : resource generation, minor healing effects, buffing hp, ranged units and ranged damage spells
    • Iron 🛠 : soldiers, sturdy units, minor damage spells, buffing attack and hp
    • Fire 🔥 : direct damage, conjuration, curses (e.g. cursing an opponents' hand), buffing attack
    • Water 🌊 : drawing cards, conjuration, returning units to hands (bounce)
    • Crystal 🔮 : drawing cards (minor), resurrection, augmenting other forms of magic
  • Within the resources, we have 2 color combos that form unique sub-identities:

    • Crystal + Water: Water (more water spells accessible)
    • Crystal + Fire: Fire (more fire spells accessible)
    • Crystal + Iron: Saharan - Drawing / discarding
    • Crystal + Bamboo: Earth magic / primal / witchcraft (e.g. polymorph into frog)
    • Water + Fire: Wind
    • Water + Iron: Seafaring / pirates
    • Water + Bamboo: Coral Magic
    • Fire + Iron: Might and machinery (e.g. cannons, buff cards, damage-based boardwipes)
    • Fire + Bamboo: Dragon raising / Phoenixes
    • Bamboo + Iron: Ninjas / assassins

Scripts

Normally, downloading images from pexels / unsplash, processing them to be 520px in width, converting them to avif is a very manual process that we do through tools like https://squoosh.app/

Luckily, we've written some scripts to help with this process.

For all the cards in cardDb, imgSrc is not used in the components, but rather in these scripts as part of the 'download -> compress' chain. The img src's for each card are actually calculated via @/transformers/getImgSrcForCard

To run these scripts:

yarn scrapeImages
yarn compressImages

To get an image into assets/images:

  1. Make sure to brew install imagemagick
  2. add a new unit / spell / token card to src/cardDb
  3. set that imgSrc to be a jpg image off the internet (starting with http)
  4. run the scripts above ^
  5. prosper!

Note: on occassion, some imageMagick conversions will rotate the image b/c of orientation. The camera may have originally recorded the picture in a different rotation, and imageMagick is trying to re-orient it:

https://legacy.imagemagick.org/discourse-server/viewtopic.php?t=33900

To fix this, I recommend taking a screenshot of the image and pushing it through https://squoosh.app - it's hacky, but it gets the job done.

Also in terms of dev tooling on Macs, the easiest way to inspect the generated avif's is actually through Github Desktop client.

Comments
  • Rolling restarts causing issues with connection drops

    Rolling restarts causing issues with connection drops

    Because the app is using socket.io and Heroku for hosting it ran into issues during the daily restart of Heroku where players would lose connection to the server.

    After digging online, I found this: https://devcenter.heroku.com/articles/node-websockets#option-2-socket-io-start-the-app

    A combination of enabling http-session-affinity and preboot and upgrading to a 25$ a month professional dyno allowed the server to retain its stateful game memory in node.JS even after a restart of dynos: Screen Shot 2022-03-26 at 1 01 56 AM

    https://devcenter.heroku.com/articles/private-spaces#rolling-deploys-with-zero-downtime

    bug 
    opened by lijim 3
  • Add auth0 integration

    Add auth0 integration

    Closes: #365

    Basic implementation of auth0 on both the server and client side of the game. This was a challenging endeavor that required 5 separate NPM packages just to get everything working. None of the existing auth0 socket.io integrations considered the fact that you might want to have authentication be optional (guest mode), which presented a challenge in writing this for the backend.

    Client side:

    • implemented the Auth0Provider and useAuth0 hooks to let components drive the state of log in / sign up / log out. When the player logs in, the WebSocket manager fires a 'login' clientToServer event to the socket.io client.

    Server side

    • said login event authenticates by using a Machine to Machine set of keys on a separate webserver-specific auth0 application. The server handles verification of a user and confirming their usernames
    • B/c none of the auth0 specific npm packages for socket.io were configured to handle optional login, I modified some existing middleware to account for this scenario.
    • We're still staying in a monolithic structure due to low # of players. The webserver will handle authentication requests 🙏🏻

    Player impact:

    • Players will now have to be 'guests' if they don't sign up
    • Players will get engagement stats, titles / awards, and possibly profile pictures / saved decks / etc. once they register in the future

    New sign-in screen: Screen Shot 2022-05-20 at 11 14 45 PM

    opened by lijim 1
  • Modal system

    Modal system

    We need a modal system to display:

    • open source credits (#237 )
    • game instructions (#249)

    This ticket will encompass the creation of a modal system to display those things

    • use React.Portal to create the modal on a separate layer
    • lazy load the modals
    • make the modals actionable in redux, e.g. closeModal, openModal(ModalTypes.INSTRUCTIONS)
    opened by lijim 1
  • Anti-magical cards

    Anti-magical cards

    Magic units are OP.

    They can shoot past soldiers, they have great effects stapled to them.

    Beside their normally low attack values, if they remain on board, they are super hard to stop unless the opponent already has a board.

    We need more ways for physical decks (e.g. monks) to beat magic ones.

    Ideas: A unit that costs 1 and an Iron that is a 2/1 that destroys an opposing unit if it is magical (Gargoyle?)

    A unit that costs 2 and an iron that deals 1 damage to all magical units

    • [ ] introduce restrictions to effects:
    Screen Shot 2022-04-05 at 10 32 46 PM
    • [ ] introduce a 'destroy' effect
    • [ ] make the auto-resolver respect restrictions (if no valid targets that match a restriction, bail out early)
    • [ ] make resolveEffects for destroy + deal damage respect restrictions
    enhancement 
    opened by lijim 1
  • Nerf Bamboo Farmer

    Nerf Bamboo Farmer

    The bamboo farmer unit is one of the most powerful units currently in the game and seems to have almost no drawback

    It is basically a 1-resource version of this 3-mana card in MtG: https://scryfall.com/card/khc/80/wood-elves

    This leads to some powerful starts for the divers / farmers decks that make those decks unfair against other archetypes.

    A potential drawback that Bamboo farmer could incur could be: "on death: destroy 1 bamboo resource of your own"

    • [ ] #253
    • [ ] #254
    • [ ] #255
    • [ ] #256
    enhancement 
    opened by lijim 1
  • Make deck list selection redux-based

    Make deck list selection redux-based

    Puts the decklist selection into a new slice called decklist. In the future, this will include custom decklists, but for now, it just has the premade decklist

    Part of #197 - we need this so that we have a sense of what decklist to display for the top-level router component that displays the decklist

    opened by lijim 1
  • Reduce time to first paint by 25% (SEO improvements)

    Reduce time to first paint by 25% (SEO improvements)

    I recently added CloudFlare as a CDN provider for the app and tackling the Google Lighthouse issues highlighted in #157 .

    The biggest problem highlighted by the report was the client-side Javascript resources, resulting in a 4.8s First Contentful Paint + time to interactive. On 3G this becomes even worse, with a 10.5second first contentful paint. (Source: lighthouse report, see #158 )

    Added code splitting + bundle minimization to reduce the overall size of client.bundle.js.

    Every piece of the app besides the router was put into bundles that load when actually called.

    Bundle Size

    This reduced the size of the initially loaded code (excluding node_modules) from 264kb to 14kb. Before: Screen Shot 2022-03-14 at 6 23 21 AM

    After: Screen Shot 2022-03-14 at 7 24 16 AM

    Speed / loading

    The impact on speed was also significant (tested using no-cache, Fast 3g simulator with chrome dev tools locally)

    Before (3.0 seconds time to first paint): Screen Shot 2022-03-14 at 6 55 25 AM

    After: (2.4 seconds time to first paint): Screen Shot 2022-03-14 at 6 57 49 AM

    Avoiding Flash of Unstyled Content

    B/c file splitting / lazy-load causes the app to paint in a jarring manner (flashing into the screen), I introduced an animation for the appearance of the NameChanger component to reduce strain on the eyes:

    https://user-images.githubusercontent.com/1839462/158162840-94fca1c5-28c9-4ae5-9f7a-75c57f5f6fb9.mov

    Borrowed inspiration from: https://nextjs.org/docs/advanced-features/dynamic-import#with-named-exports

    dev experience 
    opened by lijim 1
  • Add animations to cards

    Add animations to cards

    https://www.youtube.com/watch?v=kT6yYSwK1oA < using react-spring, some of the animations like a unit bouncing from board to hand, or a unit fading away after dying could stand to be animated to better convey what is happening to the players. investigate react-spring as a potential solution for this nice-to-have feature

    future epics 
    opened by lijim 1
  • Make cemetery visible and interactable

    Make cemetery visible and interactable

    Right now, the players' cemeteries are not visible (a la Hearthstone), but are shown on the UI

    Screen Shot 2022-03-09 at 12 51 45 AM

    This is a stretch epic to make players able to cast spells that revive a particular unit from a cemetery, or return a particular card from the cemetery back to the hand

    • [ ] Make a spell card that revives a particular unit
    • [ ] Make a unit card that on entering, returns a target spell card to the hand
    future epics 
    opened by lijim 1
  • Add effect resolution system

    Add effect resolution system

    Effects happen when spells are cast or units enter the board. Effects require resolution (either automatic or player-controlled) in order to advance the game state along. Effects are processed from the top to the bottom of the card

    • [x] #78
    • [x] #77
    • [x] #79
    • [x] #80
    • [x] #81
    • [x] #82
    • [x] #83
    • [x] #88
    • [x] #84
    • [x] #85
    • [x] #86
    • [x] #87
    • [x] #89
    • [x] #90
    • [x] #91
    • [x] #96
    • [x] #97
    • [x] #99
    • [x] #100
    • [x] #109
    opened by lijim 1
  • Make name changing server-side

    Make name changing server-side

    In most games, you have the option to pick a name.

    This commit adds:

    • a WebSocket provider that provides down all descendant components (such as IntroScreen) a way to access methods (e.g. chooseName) associated with the socket connection

    • we changed the intro screen to involve picking a name before seeing anything else.

    demo:

    https://user-images.githubusercontent.com/1839462/155854794-6f90f4fd-ba16-4382-a73f-59403c3e2090.mov

    opened by lijim 1
  • Alert when a guest name has already been taken

    Alert when a guest name has already been taken

    We don't let users pick an already taken guest name, but we don't alert them about it today. It fails silently right now and it's confusing.

    • Push an event to the client that their name is taken via websockets
    • Upon receiving this event, the form field turns red and shows an error
    • Upon typing, this error goes away
    opened by lijim 0
  • Allow players to change nicknames

    Allow players to change nicknames

    out of the box, auth0 provides the social sign-in email as the nickname. There should be a clear button that indicates that you can change your name that makes a socket.io clientToServer call, which in turn makes a PATCH API request for the given user

    opened by lijim 0
Owner
Jimmy Li
Front-end oriented software engineer for @UrbanCompass
Jimmy Li
A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router.

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router. It also includes a theme switcher from light to dark mode.

Franklin Okolie 4 Jun 5, 2022
Simple React Social Network, built with React,Node,Express,MongoDB and Tailwind

Full stack react social network application A mini social network application built with React,Typescript, Redux, Node, Express, MongoDB, and Tailwind

Albenis Kërqeli 31 Dec 19, 2022
Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.

Recoil · Recoil is an experimental set of utilities for state management with React. Please see the website: https://recoiljs.org Installation The Rec

Facebook Experimental 18.2k Jan 8, 2023
This simple tic-tac-toe game is created by following the react documentation. and there's some modifications on it.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Kesara Karannagoda 1 Dec 29, 2022
Chat Loop is a highly scalable, low-cost, and high performant chat application built on AWS and React leveraging GraphQL subscriptions for real-time communication.

Chat Loop Chat Loop is a highly scalable, low cost and high performant chat application built on AWS and React leveraging GraphQL subscriptions for re

Smile Gupta 24 Jun 20, 2022
A portfolio built in React and NextJS. Simple, clean, and fast.

Personal Portfolio A portfolio built in React and NextJS. Simple, clean and fast. Note: The logo and banner used in the project are my intellectual pr

Vipul Jha 98 Jan 2, 2023
USA Covid-19 Tracker is a mobile-first application built with React and Redux to give precise information about the virus behavior in the United States. Great transitions and user feedback made with plain CSS.

React.js USA Covid-19 Tracker This application allows the public to keep track of the stadistics of the Covid-19 Pandemic in the United Stated. You wi

Rafael Echart 14 Oct 25, 2022
A website built with React, Redux, and Tailwind for styling. The project is displaying a list of books, adding, and removing books.

Bookstore "Bookstore" is a website built with React, Redux, and Tailwind for styling. The project is displaying a list of books, adding, and removing

Shady Shawkat 5 Dec 19, 2022
Redefined chart library built with React and D3

Recharts Introduction Recharts is a Redefined chart library built with React and D3. The main purpose of this library is to help you to write charts i

recharts 19.4k Jan 5, 2023
React + Redux starter kit / boilerplate with Babel, hot reloading, testing, linting and a working example app built in

A comprehensive starter kit for rapid application development using React. Why Slingshot? One command to get started - Type npm start to start develop

Cory House 9.8k Dec 22, 2022
A collection of sample apps built using GetStream and React Native

React Native samples [ Built with ♥ at Stream ] This repo contains projects and samples developed by the team and Stream community, using React Native

Stream 93 Jan 8, 2023
Single Page Application built using React, Context API and OMDb API.

Movie Search App This project is a React application with functions to search for movies and add movies to favorites using OMDb API. Home Page Favorit

Efecan Pınar 24 Sep 6, 2022
A lightweight Apple Music client for Windows, built with MusicKit JS, Edge WebView2 and React.

Lito Music English | 中文 Lito (/laɪto/) Music is a lightweight Apple Music client for Windows, built with MusicKit JS, Edge WebView2 and React. System

Jiahao Lu 113 Dec 30, 2022
A text editor built with react , firebase and quill

Welcome to Text-Editor ?? A simple text editor built with react,firebase v8 & quill ✨ Demo Install npm install Usage npm run start Run tests npm run t

Whirl 4 Aug 30, 2022
Built a covid-19 trcaker app using React.js implementing hooks and materail UI

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Aditya Dond 1 Dec 21, 2021
👉 Built my first React JS project "ToDo" webapp using some Features and Icons from Material UI.

# Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Avai

Vansh Chitlangia 2 Dec 15, 2021
Twitter-Clone-Nextjs - Twitter Clone Built With React JS, Next JS, Recoil for State Management and Firebase as Backend

Twitter Clone This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn de

Basudev 0 Feb 7, 2022
Math Magicians is a website for performing basic maths calculations, This website is built using REACT and JavaScript libraries.

Math Magicians Math Magicians is a website for performing basic maths calculations, This website is built using REACT and JavaScript libraries. Screen

Ranjeet Singh 12 Oct 20, 2022
Bootstrap components built with React

React-Bootstrap Bootstrap 4 components built with React. Docs See the documentation with live editable examples and API documentation. To find the doc

react-bootstrap 21.4k Jan 5, 2023