{"id":37056636,"url":"https://github.com/enriko-riba/multiplayer-host","last_synced_at":"2026-01-14T06:24:42.215Z","repository":{"id":44825267,"uuid":"317196967","full_name":"enriko-riba/multiplayer-host","owner":"enriko-riba","description":"Generic .NET 10 based multiplayer game server.","archived":false,"fork":false,"pushed_at":"2025-08-29T04:57:41.000Z","size":2122,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-09T20:44:32.318Z","etag":null,"topics":["csharp","dotnet","dotnet5","game-development","gamedev","server"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enriko-riba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-11-30T11:06:42.000Z","updated_at":"2025-09-25T06:30:41.000Z","dependencies_parsed_at":"2025-08-29T06:16:25.007Z","dependency_job_id":null,"html_url":"https://github.com/enriko-riba/multiplayer-host","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/enriko-riba/multiplayer-host","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enriko-riba%2Fmultiplayer-host","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enriko-riba%2Fmultiplayer-host/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enriko-riba%2Fmultiplayer-host/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enriko-riba%2Fmultiplayer-host/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enriko-riba","download_url":"https://codeload.github.com/enriko-riba/multiplayer-host/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enriko-riba%2Fmultiplayer-host/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28412211,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","dotnet5","game-development","gamedev","server"],"created_at":"2026-01-14T06:24:42.152Z","updated_at":"2026-01-14T06:24:42.209Z","avatar_url":"https://github.com/enriko-riba.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multiplayer Host\n![project logo](host/images/image.png)\n\n[![Build .NET 9 class library](https://github.com/enriko-riba/multiplayer-host/actions/workflows/build.yml/badge.svg)](https://github.com/enriko-riba/multiplayer-host/actions/workflows/build.yml)\n\n## Overview\nThe **Multiplayer Host** is a class library helping game developers implementing multiplayer game servers. It exposes a **Server** component \nthat streamlines message handling, message buffering, user state handling and invoking the game implementation layer.\nThe Server component does not contain any game specific logic. Game developers deal with the game logic by implementing several interfaces \ninvoked by the server component.\n\nThe goal of this project is to create a framework for streamlining the game backend development. \n\n\n## High level architecture\n![project logo](host/images/conceptual-diagram.png)\n\n\n### Multiplayer Host implements\n* abstract User class and user management\n* main game loop\n* message dispatcher loop\n* client message double buffering (accepts new incoming messages simultaneously with turn processing)\n* server message buffering\n* dedicated background threads for the main loop and message dispatcher\n* public IServer api supporting basic server operations, queuing client messages and creating response messages\n\n### Multiplayer Host does not implement\n* a real game - although a minimalistic reference game (server and client) is provided for test purposes\n* any kind of game specific logic\n* any kind of client connectivity\n* any kind of data storage\n* anything related to game clients\n\n# Components\nThe server requires external components providing the following interfaces:\n* **`IConnectionManager`**, providing client connection management and message sending/receiving \n* **`IRepository`**, providing game persistence\n* **`ITurnProcessor`**, providing the game logic\n* in addition the host implements the **`IServer`** to be used by other components to control and communicate with the server\n\n## Turn processing\nThe server uses the `ITurnProcessor` interface to invoke game specific logic. The turn processors methods are invoked in the following order:\n1. `ITurnProcessor.ProcessClientMessage(User user, in ClientMessage message);` invoked once for every received client message \n2. `ITurnProcessor.ProcessUserTurn(User user, int ellapsedMilliseconds);` invoked once per turn for every user (both online and offline)\n3. `ITurnProcessor.OnTurnComplete();` invoked once per turn after all messages and users have been processed\n\n# Quickstart\n1. create a game specific user entity inheriting from `MultiplayerHost.Domain.User`\n```cs\npublic class Player : User\n{\n    public int Diamond { get; internal set; }\n    public int Gold { get; internal set; }\n    public int Reputation { get; internal set; }\n    ...\n}\n```\n2. implement the three mandatory interfaces: `IConnectionManager`, `IRepository` and `ITurnProcessor`. \nNote: for testing purposes a single class could implement all of them. When dealing with users inside your game logic, make sure to cast the provided User instance into your specific user entity class.\nThe server will only use the IRepository interface to save the user state. If you need to persist additional state you must implement it as part of your game logic.\n3. Implement client messages and corresponding parsers/handlers, define server messages and specify their payload format\n4. obtain an IServer reference, grab the context and provide the interface implementations\n```cs\nIServer server;\nvar context = server.Context;\ncontext.Configure(repository, connMngr, turnProcessor);\n// optionally subscribe for initial game setup: context.Server.OnBeforeServerStart += OnServerStart;\n```\n5. start the server\n```cs\nawait server.Start();\n```\n6. The server starts invoking the turn processing logic\n7. You also need a client capable of exchanging messages with your IConnectionManager implementation\n\n**Note**: The multiplayer game server is easiest to be used with a DI container. Consult the reference game server project how to setup DI in a console application.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenriko-riba%2Fmultiplayer-host","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenriko-riba%2Fmultiplayer-host","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenriko-riba%2Fmultiplayer-host/lists"}