Skip to content

johnpreed/HousePartyGames

Repository files navigation

house-party-games

Contributing

As we add more games, we want to keep this well organized, sharing react components where it makes sense and keeping each game confined to its own Hub and its own Manager.

Development Environment

This project is set up to easily launch with VSCode. Mainly you should just need the following extensions installed:

  • C#
  • Debugger for Chrome
  • ESLint
  • Prettier

Launching via F5 will just launch Chrome and run both client and server.

Development and CI/CD

This application is containerized, using a Dockerfile and hosted on DockerHub. Each merge/commit to the master kick off an action that will build and deploy the docker image to a Azure web application.

Since we're continuously deploying, All active development should be done on a branch and fully functional before we merge it to master.

UI

The front end is written in React using Typescript. Currently there are no unit tests for react components, but that's something we can add in the future. When we add tests, each component's test should live alongside the component in its own folder.

My general approach to React components for this site has been to use React Hooks as much as possible. While I'm familiar with their use, occasionally they still don't fully make sense to me particularly when coupled with SignalR events and it's easier to just use a class in those cases. But I'd like to strive to use hooks whenever possible.

I usually keep my chrome developer console open while i'm working on the UI and fix all warnings that show up there.

Folder Description
/src/HousePartyGames/ClientApp Front end code root
/src/HousePartyGames/ClientApp/src/Components Folder for all React components
/src/HousePartyGames/ClientApp/src/Components/Common Shared React components for all games
/src/HousePartyGames/ClientApp/src/Components/Common/VectorGraphics Each SVG lives in its own tsx file here and cane be used with the SvgIcon component to render in your React component.
/src/HousePartyGames/ClientApp/src/Components/GameUI Top level folder for all the UI for a game

Third Party Libraries

Library Purpose
Material UI This is the core UI component library for the website for a uniform look. Open to changing to a different library in the future, but this one is pretty standard. Visit https://material-ui.com/ for examples
Axios Though most of the game state communcation is managed with signalr, this library is used for making standard http requests to the back end service when needed.
SignalR Used to maintain websocket connections between the browser and web service. This is used to keep all clients' in sync with the game state on the server.

Web Service

The web service is written in .NET Core and uses SignalR for web socket communication with each connected browser.

Folder Description
/src/HousePartyGames/Hubs Each game should have its own hub in this folder.
/src/HousePartyGames/Managers Each game should have its own Manager in this folder that fully manages its game state. threadsafe.

Hubs

The hub's responsibility is to maintain the collection of connected clients as well as communication to them. It should only be aware of game state in the sense of what to call in the manager.

Note that if a request comes from the client and a response can be returned right away, with SignalR you can call:

await Clients.Client("some-connection-id").SendAsync("some-method", someArgs);

But if the call is originating from another place in code, say from a Timer you need to make that call this way:

await _callbackContext.Clients.Client("some-connection-id").SendAsync("some-method", someArgs);

where _callbackContext is an IHubContext<YourHub> which is injected in the Startup class.

To map a hub to a specific endpoint that's done in the Startup.cs. Map your hub in this section:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ThatsItHub>("/thatsitgame");

    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller}/{action=Index}/{id?}");
});

NOTE: make sure your hub doesn't conflict with a React Route! So if the path to my game in the browser was: housepartygames.com/chess, I would map my hub with something that isn't chess or that will conflict. So maybe append a string to it and call it: /chessgame.

Managers

It should return data to the hub or callback into a method on the hub when it is finished with a process and needs to send state to the connected clients. One important thing to remember with the manager is that each change to the state needs to be threadsafe. I've created a convenience wrapper to handle that. Use it like this:

await ActiveGames.WithLockedInstance(joinCode, async (GameInstance instance) =>
{
    ...
});

Storage

Currently all game state is stored in memory. If deploy the site all active games will get WIPED.

TODO:

  • Use persistent storage

Game Cleanup Service

There is a background service that runs to clean up games that have ended (or have been abandoned). This is implemented as a hosted service because this allows a user to refresh their browser and stay connected to the game.

The original implementation would check if a game had any connected clients (players) and dispose of the game instance if that was the last client to disconnect. This caused problems where joining a game and then refreshing your browser would disconnect and reconnect, but if you were the only player in the game, the game would be gone. Similarly if you just let your phone go to sleep you get disconnected and your game will get disposed.

Now, you can disconnect your game state will remain intact until some time threshold has been reached and then it will get disconnected. Each game's Manager should implement a method that handles the cleanup and then add the call to it in the cleanup service.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors