Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created June 29, 2026 15:59
Show Gist options
  • Select an option

  • Save EncodeTheCode/0d73e061520e00d7d2d010be8ffcb7a7 to your computer and use it in GitHub Desktop.

Select an option

Save EncodeTheCode/0d73e061520e00d7d2d010be8ffcb7a7 to your computer and use it in GitHub Desktop.
import asyncio
import json
import time
# =========================
# CONFIG
# =========================
HOST = "0.0.0.0"
PORT = 4445
TICK_RATE = 20
PING_INTERVAL = 1.0
MAX_PACKET_SIZE = 1200
MAX_PLAYERS = 2000
# =========================
# PLAYER STORAGE
# =========================
players = {}
# =========================
# CREATE NEW PLAYER
# =========================
def create_player(addr):
return {
# identity
"addr": str(addr),
# position (3D)
"x": 0.0,
"y": 0.0,
"z": 0.0,
# previous position (for smoothing/interpolation)
"px": 0.0,
"py": 0.0,
"pz": 0.0,
# stats
"health": 100,
"armor": 0,
# weapon system
"weapon_id": 0,
"primary_ammo": 30,
"secondary_ammo": 90,
# movement state
"walking": False,
"running": False,
# networking
"last_seen": time.time(),
"ping": 0.0
}
# =========================
# SAFE PARSE
# =========================
def parse(data):
if len(data) > MAX_PACKET_SIZE:
return None
try:
return json.loads(data)
except:
return None
# =========================
# APPLY CLIENT DATA
# =========================
def update_player(addr, msg):
if addr not in players:
players[addr] = create_player(addr)
p = players[addr]
p["last_seen"] = time.time()
msg_type = msg.get("type")
# ---------------------
# POSITION UPDATE
# ---------------------
if msg_type == "update":
# store previous position (for interpolation)
p["px"], p["py"], p["pz"] = p["x"], p["y"], p["z"]
# apply movement
p["x"] += float(msg.get("dx", 0))
p["y"] += float(msg.get("dy", 0))
p["z"] += float(msg.get("dz", 0))
# movement states
p["walking"] = bool(msg.get("walking", False))
p["running"] = bool(msg.get("running", False))
# ---------------------
# COMBAT UPDATE
# ---------------------
elif msg_type == "combat":
p["weapon_id"] = int(msg.get("weapon_id", p["weapon_id"]))
p["primary_ammo"] = int(msg.get("primary_ammo", p["primary_ammo"]))
p["secondary_ammo"] = int(msg.get("secondary_ammo", p["secondary_ammo"]))
# ---------------------
# DAMAGE SYSTEM
# ---------------------
elif msg_type == "damage":
dmg = int(msg.get("amount", 0))
# armor absorbs first
absorbed = min(p["armor"], dmg)
p["armor"] -= absorbed
dmg -= absorbed
p["health"] -= dmg
if p["health"] < 0:
p["health"] = 0
# ---------------------
# PING SYSTEM
# ---------------------
elif msg_type == "ping":
client_time = float(msg.get("t", time.time()))
p["ping"] = time.time() - client_time
# =========================
# BUILD WORLD SNAPSHOT
# =========================
def build_world():
world = {}
for addr, p in players.items():
world[str(addr)] = {
# position
"x": p["x"],
"y": p["y"],
"z": p["z"],
# interpolation helper
"px": p["px"],
"py": p["py"],
"pz": p["pz"],
# stats
"health": p["health"],
"armor": p["armor"],
# weapons
"weapon_id": p["weapon_id"],
"primary_ammo": p["primary_ammo"],
"secondary_ammo": p["secondary_ammo"],
# movement
"walking": p["walking"],
"running": p["running"],
# ping (updated every second)
"ping": round(p["ping"], 3)
}
return {
"type": "world",
"players": world
}
# =========================
# UDP SERVER
# =========================
class GameServer(asyncio.DatagramProtocol):
def connection_made(self, transport):
self.transport = transport
def datagram_received(self, data, addr):
msg = parse(data)
if not msg:
return
if len(players) < MAX_PLAYERS:
update_player(addr, msg)
# =========================
# BROADCAST LOOP
# =========================
async def broadcast(server):
interval = 1.0 / TICK_RATE
while True:
start = time.time()
world = build_world()
packet = json.dumps(world).encode()
dead = []
for addr in players:
try:
server.transport.sendto(packet, addr)
except:
dead.append(addr)
for d in dead:
players.pop(d, None)
elapsed = time.time() - start
await asyncio.sleep(max(0, interval - elapsed))
# =========================
# PING UPDATE LOOP (every 1 second)
# =========================
async def ping_loop():
while True:
now = time.time()
for p in players.values():
# simple timeout detection
if now - p["last_seen"] > 5:
p["health"] = max(0, p["health"] - 1)
await asyncio.sleep(PING_INTERVAL)
# =========================
# START SERVER
# =========================
async def main():
loop = asyncio.get_running_loop()
transport, server = await loop.create_datagram_endpoint(
GameServer,
local_addr=(HOST, PORT)
)
print(f"Game server running on {HOST}:{PORT}")
await asyncio.gather(
broadcast(server),
ping_loop()
)
asyncio.run(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment