Skip to content

Instantly share code, notes, and snippets.

@rdeioris
Created February 8, 2019 18:53
Show Gist options
  • Save rdeioris/2f992db1014bfb26534c177f625f432c to your computer and use it in GitHub Desktop.
Save rdeioris/2f992db1014bfb26534c177f625f432c to your computer and use it in GitHub Desktop.
import socket
import sys
import time
import select
import numpy
import struct
HZ = 1.0 / 10
COMMAND_JOIN = 0
SET_VELOCITY = 1
UPDATE_POSITION = 2
class GamePlayer:
def __init__(self, server, address):
self.server = server
self.address = address
self.last_packet_timestamp = time.perf_counter()
self.location = numpy.array((0.0, 0.0, 0.0))
self.velocity = numpy.array((0.0, 0.0, 0.0))
def tick(self):
self.location += self.velocity * HZ
packet = struct.pack('=Bfff', UPDATE_POSITION, self.location[0], self.location[1], self.location[2])
self.server.packets_to_send.append(packet)
class GameServer:
def __init__(self, address, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.setblocking(False)
self.socket.bind((address, port))
self.commands_table = {}
self.commands_table[COMMAND_JOIN] = self.join
self.commands_table[SET_VELOCITY] = self.set_velocity
self.players = {}
self.time_to_wait = HZ
self.packets_to_send = []
def tick(self):
if self.time_to_wait < 0:
self.time_to_wait = 0
before = time.perf_counter()
# check if self.socket is ready
rlist, wlist, xlist = select.select([self.socket], [], [], self.time_to_wait)
after = time.perf_counter()
# check how much time passed into select
self.time_to_wait -= (after - before)
has_received_packet = False
# is self.socket ready ?
if self.socket in rlist:
try:
self.packet, self.sender = self.socket.recvfrom(64)
has_received_packet = True
except socket.error:
print('non-blocking exception!')
else:
self.time_to_wait = 0
if has_received_packet:
# check the size of the packet (zero packet would require a KICK)
if len(self.packet) < 1:
return
# check command availability
if self.packet[0] not in self.commands_table:
return
# dispatch request
self.commands_table[self.packet[0]]()
for packet in self.packets_to_send:
for player in self.players.values():
self.socket.sendto(packet, player.address)
self.packets_to_send = []
if self.time_to_wait > 0:
return
#print('HZ elapsed')
now = time.perf_counter()
dead_players = []
for player in self.players.values():
# check last received packed
if now - player.last_packet_timestamp >= 5:
print('player {} is dead'.format(player.address))
dead_players.append(player.address)
else:
player.tick()
# remove dead players
for player_address in dead_players:
del(self.players[player_address])
self.time_to_wait = HZ
def join(self):
if self.sender in self.players:
return
self.players[self.sender] = GamePlayer(self, self.sender)
print('received join from {}'.format(self.sender))
def set_velocity(self):
#print('set_velocity for {}'.format(self.sender))
# check if the player is known
if self.sender not in self.players:
return
# check packet size
if len(self.packet) != 13:
return
_, x, y, z = struct.unpack('=Bfff', self.packet)
player = self.players[self.sender]
player.last_packet_timestamp = time.perf_counter()
player.velocity = numpy.array((x, y, z))
game_server = GameServer(sys.argv[1], int(sys.argv[2]))
while True:
game_server.tick()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment