Moved the register to MS function to a variable, added Giants enums, implemented plugin system

This commit is contained in:
Amazed 2019-01-23 10:28:23 +01:00
parent 3fd1ea47b3
commit d594e38be5
8 changed files with 129 additions and 45 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
maps/*.gck

View File

@ -30,9 +30,10 @@ class Netserver:
gameserverthread = threading.Thread(target=self.handle_packets) gameserverthread = threading.Thread(target=self.handle_packets)
gameserverthread.start() gameserverthread.start()
#ms = MasterServer(self.server) if self.server.register_with_ms:
#statsserverthread = threading.Thread(target=ms.register_and_run) ms = MasterServer(self.server)
#statsserverthread.start() ms.register()
gameserverthread.join() gameserverthread.join()
#statsserverthread.join() #statsserverthread.join()
@ -74,7 +75,7 @@ class Netserver:
er.ApplicationInstanceGUID = self.guid er.ApplicationInstanceGUID = self.guid
er.ApplicationGUID = eq.ApplicationGUID er.ApplicationGUID = eq.ApplicationGUID
er.ApplicationReservedData = b'\xff' # Map ID er.ApplicationReservedData = b'\xff' # Map ID
er.ApplicationReservedData += b'\x00\x04\x00' er.ApplicationReservedData += b'\x00\x04\x00' # game type and teams
er.ApplicationReservedData += b'\xd9\x05' # game version er.ApplicationReservedData += b'\xd9\x05' # game version
er.ApplicationReservedData += b'\x02\x92\x05\x00\x01\x00\x00\x00\x00\x00' # Unknown er.ApplicationReservedData += b'\x02\x92\x05\x00\x01\x00\x00\x00\x00\x00' # Unknown
er.ApplicationReservedData += b'\x9c\x53\xf4\xde' # Seems to be a checksum of current map er.ApplicationReservedData += b'\x9c\x53\xf4\xde' # Seems to be a checksum of current map

View File

@ -0,0 +1,25 @@
class Teams:
MvM = 0x00
MvMvM = 0x01
RvR = 0x02
MvR = 0x03
MvRvK = 0x04
MvK = 0x05
RvK = 0x06
TeamB = 0x07
Crash = 0x5a
class GameTypes:
TeamDeathmatch = 0x00
TeamDeathmatchWithFullBase = 0x01
CaptureSmartie = 0x02
CaptureSmartieWithFullBase = 0x03
BaseBuildDeathmatch = 0x04
BaseBuildCaptureSmartie = 0x05
DefendBase = 0x06
DefendBaseCaptureSmartie = 0x07
GTypeStone = 0x08
GTypeWood = 0x09
Crash = 0x0a
GTypeNull = 0x0c

View File

@ -1,11 +1,24 @@
class Map: import os
def __init__(self, mapname="Unknown mapname"):
self.mapname = mapname
self.checksum = None
def load_map(self, mapname):
self.checksum = Map.checksum(mapname) class Map:
def __init__(self, mappath):
self.mappath = mappath
self.checksum = None
self.mapname = "Unknown map"
self.load_map(mappath)
def load_map(self, mappath):
if not os.path.exists("maps/"+mappath):
raise Exception("Map not found: "+mappath)
if not mappath.endswith(".gck"):
raise Exception("Server only supports GCK maps")
self.mapname = mappath.split(".gck")[0]
self.checksum = Map.checksum(mappath)
@staticmethod @staticmethod
def checksum(mapname): def checksum(mapname):
# TODO
return 1 return 1

View File

@ -1,5 +1,6 @@
import socket import socket
from dpnet.packet import Packet from dpnet.packet import Packet
import threading
class MasterServer: class MasterServer:
@ -9,22 +10,27 @@ class MasterServer:
self.masterserverip = "gckms.no-ip.org" self.masterserverip = "gckms.no-ip.org"
self.masterserverport = 27900 self.masterserverport = 27900
def register(self):
statsserverthread = threading.Thread(target=self.register_and_run)
statsserverthread.start()
statsserverthread.join()
def register_and_run(self): def register_and_run(self):
self.socket.bind((self.server.listen_ip, 8911)) self.socket.bind((self.server.listen_ip, 8911))
print("Listening to " + self.server.listen_ip + ":" + str(8911)) print("Listening to " + self.server.listen_ip + ":" + str(8911))
print("Registering to Master Server") print("Registering to Master Server")
self.register() self._register()
self.keepalive() self.keepalive()
self.handle_packets() self.handle_packets()
def register(self): def _register(self):
packet = Packet() packet = Packet()
packet.write("019711".encode("ascii")) packet.write(("0"+str(self.server.listen_port)).encode("ascii"))
self.socket.sendto(packet.getvalue(), (self.masterserverip, self.masterserverport)) self.socket.sendto(packet.getvalue(), (self.masterserverip, self.masterserverport))
def keepalive(self): def keepalive(self):
packet = Packet() packet = Packet()
packet.write("119711".encode("ascii")) packet.write(("1"+str(self.server.listen_port)).encode("ascii"))
self.socket.sendto(packet.getvalue(), (self.masterserverip, self.masterserverport)) self.socket.sendto(packet.getvalue(), (self.masterserverip, self.masterserverport))
def handle_packets(self): def handle_packets(self):

0
plugins/__init__.py Normal file
View File

14
plugins/greetings.py Normal file
View File

@ -0,0 +1,14 @@
class Greetings:
def __init__(self, server):
self.server = server
def on_player_join(self, player):
self.server.broadcast_message("Welcome "+player.name+"!")
def on_map_change(self, newmap):
self.server.broadcast_message("You are now playing on "+newmap.mapname)
def setup(server):
plugin = Greetings(server)
server.add_plugin(plugin)

View File

@ -2,8 +2,14 @@ from giants.map import Map
from giants.player import Player from giants.player import Player
from dpnet.netserver import Netserver from dpnet.netserver import Netserver
from dpnet.session import Session from dpnet.session import Session
from dpnet.DFrame import DFrame
import socket import socket
import importlib
import os
from giants import Teams, GameTypes
from utils.logger import setup_logger
import traceback
logger = setup_logger(__name__)
class Server: class Server:
@ -14,51 +20,69 @@ class Server:
fake_session.ip = "127.0.0.1" fake_session.ip = "127.0.0.1"
fake_session.port = 3333 fake_session.port = 3333
self.players = [Player("Amazed4", fake_session)] self.players = [Player("Amazed4", fake_session)]
self.currentmap = kwargs.get("map", Map("wow rly")) self.currentmap = kwargs.get("map", Map("Three Way Island - Canyons.gck"))
self.maxplayers = kwargs.get("maxplayers", 20) self.maxplayers = kwargs.get("maxplayers", 20)
self.name = kwargs.get("name", "Default Server Name") self.name = kwargs.get("name", "Default Server Name")
self.accept_new_players = True self.accept_new_players = True
self.register_with_ms = False self.register_with_ms = kwargs.get("register", False)
self.teams = kwargs.get("teams", Teams.MvM)
self.game_type = kwargs.get("gametype", GameTypes.TeamDeathmatchWithFullBase)
self._plugins = []
# events def add_player(self, player):
self._on_new_player = []
self._on_new_map = []
def new_player(self, player):
self.players.append(player) self.players.append(player)
for func in self._on_new_player: self._broadcast_event("on_player_join", player)
func(player)
def change_map(self, mapname): def add_plugin(self, plugin):
for func in self._on_new_map: self._plugins.append(plugin)
func(mapname)
def on_new_player(self, func): def change_map(self, mappath):
self._on_new_player.append(func) try:
return func self.currentmap = Map(mappath)
self._broadcast_event("on_map_change", self.currentmap)
except Exception:
logger.error("Could not change map")
def _broadcast_event(self, event, *args):
logger.debug("Broadcasting event "+event)
for plugin in self._plugins:
if hasattr(plugin, event):
func = getattr(plugin, event)
if callable(func):
try:
func(args)
except Exception:
logger.error("Could not call plugin function: "+plugin.__name__+"."+event)
traceback.print_exc()
def load_plugins(self):
plugins = os.listdir("plugins")
for plugin in plugins:
if os.path.isdir("plugins/"+plugin) or plugin == "__init__.py":
continue
if not plugin.endswith(".py"):
continue
pluginname = plugin.split(".py")[0]
try:
module = importlib.import_module("plugins."+pluginname)
if hasattr(module, "setup"):
setup = getattr(module, "setup")
if callable(setup):
logger.info("Loading plugin "+module.__name__)
module.setup(self)
except Exception:
logger.warn("Could not load plugin "+plugin)
traceback.print_exc()
def broadcast_message(self, text): def broadcast_message(self, text):
for player in self.players: for player in self.players:
player.session.send_gamedata(b'\x35\x80\x81'+text.encode("ascii")+b'\x00\x00') player.session.send_gamedata(b'\x35\x80\x81'+text.encode("ascii")+b'\x00\x00')
def on_new_map(self, func):
self._on_new_map.append(func)
return func
def run(self): def run(self):
self.load_plugins()
return Netserver(self).run() return Netserver(self).run()
if __name__ == '__main__': if __name__ == '__main__':
server = Server(name="giantsd", map=Map("expect crashes"), maxplayers=10) server = Server(name="giantsd", maxplayers=10, register=False)
@server.on_new_player
def new_player(player):
#print("A NEW PLAYER HAS JOINED: %s" % player)
pass
@server.on_new_map
def new_map(mapname):
pass
server.run() # blocking server.run() # blocking