{"id":21187573,"url":"https://github.com/pb82/servus","last_synced_at":"2025-07-21T04:07:05.480Z","repository":{"id":146898224,"uuid":"42173508","full_name":"pb82/Servus","owner":"pb82","description":"Minimalistic game server in elixir","archived":false,"fork":false,"pushed_at":"2020-04-20T15:37:58.000Z","size":50,"stargazers_count":55,"open_issues_count":2,"forks_count":6,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-05T09:41:51.286Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pb82.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2015-09-09T11:03:36.000Z","updated_at":"2024-04-02T16:29:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"5f916ac7-cf39-4668-a487-08a7f0a4d434","html_url":"https://github.com/pb82/Servus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pb82/Servus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pb82%2FServus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pb82%2FServus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pb82%2FServus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pb82%2FServus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pb82","download_url":"https://codeload.github.com/pb82/Servus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pb82%2FServus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266236844,"owners_count":23897268,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-11-20T18:38:11.901Z","updated_at":"2025-07-21T04:07:05.474Z","avatar_url":"https://github.com/pb82.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Servus [![Build Status](https://travis-ci.org/pb82/Servus.png?branch=master)](https://travis-ci.org/pb82/Servus)\n\nA simple, modular backend for multiplayer games. Simple, because it just handles the (socket) communication between a number\nof players and provides hooks for the game logic. Modular, because game logic is written as a state machine and loaded into\nthe server at runtime. The server can host multiple game logic modules simultaneously (on different ports)..\n\nThis is the result of a two day game-jam with two colleagues and should definitely not be used in production!\n\n### Installation\n\n1. Clone this repository\n2. Get all dependencies with `mix deps.get`\n3. Run the tests with `mix test`\n4. Start a server session with `iex -S mix`\n5. Or create a release with `MIX_ENV=prod mix release`\n\n### Usage\n\nServus sends and receives messages over socket connections. Messages must be encoded in JSON format. The format of\na message is\n\n```javascript\n{\n    \"type\":     \u003cREQUIRED\u003e,\n    \"value\":    \u003cREQUIRED\u003e,\n    \"target\":   \u003cOPTIONAL\u003e\u003e\n}\n```\n\nThe `type` of a message can be used in the game logic to implement different commands. The type `join` is special and is used\nto join the waiting queue for a game. The `value` can be any kind of data and will be passed to the receiver of the message\n(a game logic or server plugin). If a `target` is given, the message will be routed to the server plugin that that is \nregistered under that name.\n\nWhen players connect to the server by sending a `join` message, the player is first put into a waiting queue. Every game logic has\nto specify the number of players. When that number is reached a new game session is started and all the players in the queue are in\ngame mode now. This approach is a bit unflexible since it only allows a fixed number of players per game. There is also no matching\nalgorithm at all. Only the order in which the players join determines the opponents in a game.\n\n### Configuration\n\nThe config file is `config/config.exs`. There are two sections: basic configuration and game specific configuration. In the base config\nyou define which game modules and server plugins to start.\n\n#### Base configuration (using the included examples)\n\n```elixir\nconfig :servus, \n  # Start the `connect_four` backend\n  backends: [:connect_four],\n\n  # Start the Echo module (accessible to all backends)\n  modules: [Echo]\n```\n\n#### Game specific configuration\n\n```elixir\nconfig :servus,\n  # Configuration for the `connect_four` backend\n  # TCP and WebSocket adapters are supported\n  connect_four: %{\n    adapters: [\n      tcp: 3334,\n      web: 3335\n    ],\n    players_per_game: 2,\n    implementation: ConnectFour\n  }\n```\n\nThe `implementation` is expected to be a `gen_fsm` statemachine that uses `Servus.Game`. You should override the `init/1` function and return\nthe initial state and the data that will be passed to the fsm actions. For further information you can have a look at the example game under\nlib/connect_four\n\n### Server plugins (or modules)\n\nYou can write your own server plugins for various porupses, like for example, saving hiscores. A server plugin is an elixir module that uses `Servus.Module`.\nEvery plugin will be started as a `gen_server` internally. A module has to be registered by calling the `register` macro as soon as possible in the module\ndefinition. There are two overridables: `startup/0` and `shutdown/1`. `startup/0` allows you to return the plugin state.\n\nTo handle messages to the plugin you use the `handle` macros. In it's simplest form it looks like\n\n```elixir\nhandle \"echo\", args, state do\n  Logger.debug \"Echo module called\"\n  args\nend\n```\n\nThere's also a `handlep` macro. Use this if you don't want the module to be callable via network. `handlep` handlers can only be called from within\nthe server (usually from a game backend).\n\nThis will simply echo all input. Have a look at the example plugin under lib/echo_module.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpb82%2Fservus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpb82%2Fservus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpb82%2Fservus/lists"}