Daikombat Server is the server code repository for a simple Doom-like online shooter game with a non-stop death-match mode. It is built using Maven, Netty, Spring, and Java 14. Client/desktop code is also publicly available on GitHub.
- Java 14
- Maven 3.6.3
The server opens a network connection and pushes in-game events as protobuf messages(find .proto
schema in schema module).
The client publishes game commands and then subscribes to server events by collecting them in an
in-memory queue that is meant to be polled during game rendering.
All communications (server-to-client and client-to-server) are totally non-blocking.
- All configuration defaults should be prod-ready
- The code should be simple, so I can understand it at 2 AM after taking a two-month break
- Add as many tests as possible even if it looks non-practical at a moment(you will appreciate it later)
- All time related values(configs too) are stored in the millisecond format
- No AI
- The server is not scalable
- The server is not fully authoritative
- Basic anti-cheat
Game server can be configured using the following environment variables:
GAME_SERVER_PORTTCP server port at which client connections are going to be accepted. For simplicity, UDP port isGAME_SERVER_PORT+1. Default -7777.GAME_SERVER_BLACKLISTED_WORDSBlacklisted words. Affects chat messages and player names. Words should be separated by a comma (,) symbol. Case-insensitive. Example:ABC,XYZ,QWE. Not set by default.GAME_SERVER_BIG_UDP_WARNINGPushes a warning to logs if a big UDP datagram was sent over a network. Default -false.GAME_SERVER_GAMES_TO_CREATEGames to create. Default -1.GAME_SERVER_MAX_PLAYERS_PER_GAMEMaximum number of players to join a game. Default -25. Total number of players on the server isGAME_SERVER_GAMES_TO_CREATE*GAME_SERVER_MAX_PLAYERS_PER_GAME.GAME_SERVER_MOVES_UPDATE_FREQUENCY_MLSFrequency(in milliseconds) at which server notifies players about other players' positioning on the map. Default -25.GAME_SERVER_ACK_RESEND_FREQUENCY_MLSFrequency(in milliseconds) at which server resends UDP messages that require an ack but haven't received one. Default -100.GAME_SERVER_MAX_IDLE_TIME_MLSMaximum idle time(in milliseconds) for a player. "Idle" - no network activity, which includes in-game events + ping responds. For example, if player connects to a game and doesn't move but responds to PING requests, then it's NOT considered idle. This check is mostly needed when a TCP connection was closed abruptly(no FIN). Default -10_000.GAME_SERVER_MAX_VISIBILITYMaximum visibility on the map. Default -14. Events outside of this radius won't be transmitted over the network to save traffic.GAME_SERVER_DEFAULT_SHOTGUN_DAMAGEGunshot damage. Default -20.GAME_SERVER_DEFAULT_RAILGUN_DAMAGERailgun damage. Default -75.GAME_SERVER_DEFAULT_PUNCH_DAMAGEPunch damage. Default -50.GAME_SERVER_DEFAULT_ROCKET_DAMAGERocket damage. Default -75.GAME_SERVER_DEFAULT_MINIGUN_DAMAGEMinigun damage. Default -15.GAME_SERVER_DEFAULT_PLASMA_DAMAGEPlasma damage. Default -15.GAME_SERVER_FAST_TCPEnables fast TCP configurations(used mostly for testing, not recommended to be set tofalsein prod). Default -true.GAME_SERVER_FRAGS_PER_GAMEFrags to win a game. Default -25.GAME_SERVER_SPAWN_IMMORTAL_MLSTime (in millisecond) players are immortal after spawn/respawn. Default -2000GAME_SERVER_QUAD_DAMAGE_SPAWN_MLSTime (in millisecond) it takes to spawn a quad damage power-up orb. Default -45_000.GAME_SERVER_QUAD_DAMAGE_LASTS_FOR_MLSTime (in millisecond) quad damage lasts for. Default -15_000.GAME_SERVER_DEFENCE_SPAWN_MLSTime (in millisecond) it takes to spawn a defence power-up orb. Default -35_000.GAME_SERVER_DEFENCE_LASTS_FOR_MLSTime (in millisecond) defence lasts for. Default -10_000.GAME_SERVER_INVISIBILITY_SPAWN_MLSTime (in millisecond) it takes to spawn an invisibility power-up orb. Default -30_000.GAME_SERVER_MAP_NAMEMap name. Must be one of built-in maps ( see/server/main/resources/mapsfolder). Default -classic.GAME_SERVER_AMMO_SPAWN_MLSTime (in millisecond) it takes to spawn ammo. Default -30_000.GAME_SERVER_HEALTH_SPAWN_MLSTime (in millisecond) it takes to spawn a health power-up orb. Default -35_000.GAME_SERVER_INVISIBILITY_LASTS_FOR_MLSTime (in millisecond) invisibility lasts for. Default -15_000.GAME_SERVER_POWER_UPS_ENABLEDTurns power-ups on and off. Default -true.GAME_SERVER_TELEPORTS_ENABLEDTurns teleports on and off. Default -true.GAME_SERVER_PLAYER_SPEEDBase player speed. Changes depending on class. Default -7.GAME_SERVER_PLAYER_STATS_TIMEOUT_MLSTime (in milliseconds) to store player's stats for connection recovery. Default -120000.GAME_SERVER_PUNCH_DELAY_MLSPunch attack delay(in milliseconds). Default -300GAME_SERVER_ROCKET_LAUNCHER_DELAY_MLSRocket launcher delay(in milliseconds). Default -1_500.GAME_SERVER_PLASMAGUN_DELAY_MLSPlasma gun delay(in milliseconds). Default -155.GAME_SERVER_SHOTGUN_DELAY_MLSShotgun attack delay(in milliseconds). Default -450GAME_SERVER_RAILGUN_DELAY_MLSRailgun attack delay(in milliseconds). Default -1_700GAME_SERVER_MINIGUN_DELAY_MLSMinigun attack delay(in milliseconds). Default -155GAME_SERVER_SHOTGUN_MAX_AMMOShotgun max ammo. Default -20GAME_SERVER_RAILGUN_MAX_AMMORailgun max ammo. Default -15GAME_SERVER_MINIGUN_MAX_AMMOMinigun max ammo. Default -100GAME_SERVER_PLASMAGUN_MAX_AMMOPlasmagun max ammo. Default -50GAME_SERVER_ROCKET_LAUNCHER_MAX_AMMORocket launcher max ammo. Default -10GAME_SERVER_BEAST_SPAWN_MLSTime (in millisecond) it takes to spawn a beast power-up orb. Default -60_000.GAME_SERVER_BEAST_LASTS_FOR_MLSTime (in millisecond) defence lasts for. Default -25_000.SENTRY_DSNSentry DSN. Not specified by default.
Some environment variables can be overridden for a specific game room. The format
is <ROOM_ID>_<ENV_VAR_NAME>. For example 0_GAME_SERVER_DEFAULT_SHOTGUN_DAMAGE=99 overrides
GAME_SERVER_DEFAULT_SHOTGUN_DAMAGE variable for game room 0. Here is the list of all room-specific
configs:
GAME_SERVER_ROOM_TITLEGAME_SERVER_ROOM_DESCRIPTIONGAME_SERVER_DEFAULT_SHOTGUN_DAMAGEGAME_SERVER_DEFAULT_RAILGUN_DAMAGEGAME_SERVER_DEFAULT_MINIGUN_DAMAGEGAME_SERVER_DEFAULT_PLASMA_DAMAGEGAME_SERVER_DEFAULT_ROCKET_DAMAGEGAME_SERVER_DEFAULT_PUNCH_DAMAGEGAME_SERVER_PUNCH_DELAY_MLSGAME_SERVER_SHOTGUN_DELAY_MLSGAME_SERVER_RAILGUN_DELAY_MLSGAME_SERVER_ROCKET_LAUNCHER_DELAY_MLSGAME_SERVER_PLASMAGUN_DELAY_MLSGAME_SERVER_MINIGUN_DELAY_MLSGAME_SERVER_PLAYER_SPEEDGAME_SERVER_MAX_VISIBILITYGAME_SERVER_SHOTGUN_MAX_AMMOGAME_SERVER_RAILGUN_MAX_AMMOGAME_SERVER_MINIGUN_MAX_AMMOGAME_SERVER_PLASMAGUN_MAX_AMMOGAME_SERVER_ROCKET_LAUNCHER_MAX_AMMOGAME_SERVER_MAP_NAME
Game client is also configurable through environments variables:
CLIENT_MAX_SERVER_INACTIVE_MLSMaximum server inactivity time(in milliseconds). Default -10_000.CLIENT_FAST_TCPEnables fast TCP configurations(used mostly for testing, not recommended to be set tofalsein prod). Default -true.CLIENT_UDP_GLITCHY_INBOUND_DROP_MESSAGE_PROBABILITYProbability to drop a UDP message while reading. Ranges from0(0%) to1(100%). Default -0.CLIENT_UDP_GLITCHY_OUTBOUND_DROP_MESSAGE_PROBABILITYProbability to drop a UDP message while writing. Ranges from0(0%) to1(100%). Default -0.
Note: all default (both client and server) configurations are production-ready.
All submodules, including network client, can be used as maven/gradle dependencies using jitpack.
Server image is deployed on every release to Github container registry. A sample docker-compose file can be found in the root folder.
Server JVM metrics can be monitored through JMX remotely. See docker-compose file. In the sample, JMX agent is running on port 9999 listening to incoming connections initiated by 127.0.0.1. If server is running in the cloud, then it's possible to port-forward JMX using the following command:
ssh -L 9999:127.0.0.1:9999 <user>@<remote_host>
Apart from JMX metrics, the server is configured to drop a heap dump file on out-of-memory.
All command handlers publish Micrometer timer metrics through JMX. See "metrics" in Jconsole " MBeans" tab.
All errors are automatically published to Sentry. See SENTRY_DSN env var.
Here are some commands that might be useful while coding.
mvn versions:set -DnewVersion=<version>
mvn spotbugs:check
rm .\schema\src\main\java\com\beverly\hills\money\gang\proto\*
protoc --java_out=./schema/src/main/java/ .\schema\src\main\resources\server-common.proto
protoc --java_out=./schema/src/main/java/ .\schema\src\main\resources\server-response.proto
protoc --java_out=./schema/src/main/java/ .\schema\src\main\resources\server-command.proto