2019-03-05 03:58:01 +01:00
from dpnet . packet import Packet
2019-01-22 01:30:42 +01:00
from giants . map import Map
from giants . player import Player
from dpnet . netserver import Netserver
from dpnet . session import Session
import socket
2019-01-23 10:28:23 +01:00
import importlib
import os
2019-02-19 01:01:31 +01:00
from giants import Teams , GameTypes , ChatColor , ChatType
2019-01-23 10:28:23 +01:00
from utils . logger import setup_logger
import traceback
2019-02-06 01:07:00 +01:00
import asyncio
2019-02-19 01:01:31 +01:00
from aioconsole import ainput
2019-03-05 01:30:20 +01:00
import struct
2019-03-13 01:37:49 +01:00
from curses import wrapper
2019-01-23 10:28:23 +01:00
logger = setup_logger ( __name__ )
2019-01-22 01:30:42 +01:00
class Server :
def __init__ ( self , * * kwargs ) :
self . listen_ip = kwargs . get ( " ip " , " 0.0.0.0 " )
self . listen_port = kwargs . get ( " port " , 19711 )
2019-02-05 01:35:22 +01:00
self . register_with_ms = kwargs . get ( " register " , False )
self . teams = kwargs . get ( " teams " , Teams . MvM )
self . game_type = kwargs . get ( " gametype " , GameTypes . TeamDeathmatchWithFullBase )
2019-03-05 01:49:13 +01:00
self . currentmap = kwargs . get ( " map " , Map ( " Testmap.gck " ) )
2019-01-22 01:30:42 +01:00
self . maxplayers = kwargs . get ( " maxplayers " , 20 )
self . name = kwargs . get ( " name " , " Default Server Name " )
2019-02-05 01:35:22 +01:00
2019-03-07 02:09:50 +01:00
fake_session = Session ( self , socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) )
2019-02-05 01:35:22 +01:00
fake_session . ip = " 127.0.0.1 "
fake_session . port = 3333
self . players = [ Player ( " [Server] " , fake_session ) ]
2019-03-07 02:09:50 +01:00
fake_player = Session ( self , socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) )
2019-02-19 01:01:31 +01:00
fake_player . ip = " 127.0.0.1 "
fake_player . port = 3334
self . players . append ( Player ( " Bot 1 " , fake_player ) )
2019-03-07 02:09:50 +01:00
fake_player = Session ( self , socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) )
2019-02-28 04:01:03 +01:00
fake_player . ip = " 127.0.0.1 "
fake_player . port = 3334
self . players . append ( Player ( " Bot 2 " , fake_player ) )
2019-03-07 02:09:50 +01:00
fake_player = Session ( self , socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) )
2019-02-28 04:01:03 +01:00
fake_player . ip = " 127.0.0.1 "
fake_player . port = 3334
self . players . append ( Player ( " Bot 3 " , fake_player ) )
2019-01-22 01:30:42 +01:00
self . accept_new_players = True
2019-01-23 10:54:51 +01:00
self . version = 1.497
2019-02-05 22:33:25 +01:00
self . points_per_kill = 1
2019-01-23 10:54:51 +01:00
self . points_per_capture = 5
self . detente_time = 0 # minutes
2019-01-23 10:28:23 +01:00
self . _plugins = [ ]
2019-02-05 01:35:22 +01:00
self . tempplayers = [ ]
self . running = True
self . ticks = 60
2019-03-05 03:58:01 +01:00
self . _nextid = 118
2019-02-05 01:35:22 +01:00
def update ( self ) :
#logger.debug("Calling update")
pass
2019-01-22 01:30:42 +01:00
2019-02-06 01:07:00 +01:00
async def add_player ( self , player ) :
2019-02-05 01:35:22 +01:00
self . tempplayers . remove ( player )
2019-01-22 01:30:42 +01:00
self . players . append ( player )
2019-02-19 01:01:31 +01:00
await self . broadcast_event ( " on_player_join " , player )
2019-01-23 10:28:23 +01:00
2019-02-05 01:35:22 +01:00
# todo: remove
def create_temp_player ( self , player ) :
self . tempplayers . append ( player )
2019-02-06 01:07:00 +01:00
async def remove_player ( self , player ) :
2019-02-05 01:35:22 +01:00
self . players . remove ( player )
2019-01-23 10:28:23 +01:00
def add_plugin ( self , plugin ) :
self . _plugins . append ( plugin )
2019-02-06 01:07:00 +01:00
async def change_map ( self , mappath ) :
2019-01-23 10:28:23 +01:00
try :
self . currentmap = Map ( mappath )
2019-02-19 01:01:31 +01:00
await self . broadcast_event ( " on_map_change " , self . currentmap )
2019-01-23 10:28:23 +01:00
except Exception :
logger . error ( " Could not change map " )
2019-01-22 01:30:42 +01:00
2019-02-19 01:01:31 +01:00
async def broadcast_event ( self , event , * args ) :
2019-01-23 10:28:23 +01:00
logger . debug ( " Broadcasting event " + event )
for plugin in self . _plugins :
if hasattr ( plugin , event ) :
func = getattr ( plugin , event )
if callable ( func ) :
try :
2019-02-06 01:07:00 +01:00
await func ( * args )
2019-01-23 10:28:23 +01:00
except Exception :
2019-02-05 01:35:22 +01:00
logger . error ( " Could not call plugin function: " + plugin . __class__ . __name__ + " . " + event )
2019-01-23 10:28:23 +01:00
traceback . print_exc ( )
2019-01-22 01:30:42 +01:00
2019-02-06 01:07:00 +01:00
def load_plugins ( self ) :
2019-01-23 10:28:23 +01:00
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 :
2019-02-06 01:07:00 +01:00
logger . warning ( " Could not load plugin " + plugin )
2019-01-23 10:28:23 +01:00
traceback . print_exc ( )
2019-01-22 01:30:42 +01:00
2019-02-19 01:01:31 +01:00
async def broadcast_message ( self , text , color = ChatColor . Orange , type = ChatType . All ) :
2019-01-22 01:30:42 +01:00
for player in self . players :
2019-02-06 14:09:17 +01:00
if player . name == " [Server] " :
continue
2019-02-19 01:01:31 +01:00
await player . send_message ( text , color = color , type = type )
async def ask_command ( self ) :
while True :
try :
cmd = await ainput ( " > " )
logger . debug ( " Sending game payload %s " , cmd )
for player in self . players :
if player . name == " [Server] " :
continue
await player . session . send_gamedata ( bytes . fromhex ( cmd ) , acknow = False )
except :
traceback . print_exc ( )
2019-02-28 04:01:03 +01:00
async def broadcast_gamedata ( self , payload , * * kwargs ) :
for player in self . players :
if player . name == " [Server] " :
continue
await player . session . send_gamedata ( payload , * * kwargs )
2019-03-07 02:09:50 +01:00
async def broadcast_gamedata_except ( self , player , payload , * * kwargs ) :
for pplayer in self . players :
if pplayer . name == " [Server] " or pplayer == player :
continue
await pplayer . session . send_gamedata ( payload , * * kwargs )
2019-03-05 01:30:20 +01:00
async def broadcast_message_except ( self , player , text , color = ChatColor . Yellow , type = ChatType . All ) :
for pplayer in self . players :
if pplayer . name == " [Server] " or pplayer == player :
continue
await pplayer . send_message ( text , color = color , type = type )
2019-03-13 01:37:49 +01:00
async def new_object ( self , model ) :
oid = self . _nextid
p = Packet ( )
p . putByte ( 0x05 ) # opcode
p . putByte ( 0 )
p . putShort ( self . _nextid )
p . putByte ( 0x00 )
p . putULong ( model )
p . putByte ( 0x00 )
self . _nextid + = 1
await self . broadcast_gamedata ( p . getvalue ( ) )
return oid
2019-03-11 21:18:30 +01:00
async def spawn ( self , player , model ) :
plix = self . get_player_index ( player )
2019-03-05 03:58:01 +01:00
p = Packet ( )
p . putByte ( 0x05 ) # opcode
p . putByte ( plix )
p . putShort ( self . _nextid )
p . putByte ( 0x00 )
p . putULong ( model )
p . putByte ( 0x00 )
await self . broadcast_gamedata ( p . getvalue ( ) , acknow = False )
#await self.broadcast_gamedata(bytes.fromhex("05" + plix + struct.pack("<H", self._nextid).hex() + "00" + model + "00000000"), acknow=False)
p = Packet ( )
p . putByte ( 0x0a ) # opcode
p . putByte ( 0x12 ) # length
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( plix ) # player index
p . putShort ( self . _nextid ) # object id
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x01 ) # unknown
p . putULong ( model ) # model
p . putFloat ( player . x ) # player x
p . putFloat ( player . y ) # player y
p . putFloat ( player . z ) # player z
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # orientation
p . putULong ( 0x00 ) # unknown
await self . broadcast_gamedata ( p . getvalue ( ) , acknow = False )
self . _nextid + = 1
#await self.broadcast_gamedata(bytes.fromhex("0a12000000" + plix + struct.pack("<H", self._nextid).hex() + "0003" + model + "00000000"), acknow=False)
#await self.broadcast_gamedata(bytes.fromhex("0a32000000" + plix + struct.pack("<B", self._nextid).hex() + "000001" + model + "000000ff00000000000000000000000000000000000000000000000000000000000000000000000a12000000" + plix + struct.pack("<B", self._nextid).hex() + "0000" + model + "020000000000000000"), acknow=False)
async def change_model ( self , player , model ) :
plid = self . get_player_index ( player )
# p = Packet()
# p.putByte(0x0a) # opcode
# p.putByte(0x12) # length
# p.putByte(0x00) # unknown
# p.putByte(0x00) # unknown
# p.putByte(0x00) # unknown
# p.putByte(plid) # player index
# p.putShort(player.oid) # object id
# p.putByte(0x00) # unknown
# p.putByte(0x02) # 4 -> death, 3 -> little move
# p.putULong(model) # model
# p.putFloat(player.x) # x
# p.putFloat(player.y) # y
# p.putFloat(player.z) # z
# p.putULong(0x00) # unknown
# p.putULong(0x00) # unknown
# p.putULong(0x00) # unknown
# p.putULong(0x00) # unknown
# p.putULong(player.o + 30) # orientation
# p.putULong(0x00) # unknown
p = Packet ( )
p . putByte ( 0x0a ) # opcode
p . putByte ( 0x32 ) # length
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( plid ) # player index
p . putShort ( player . oid ) # object id
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x01 ) # 1 -> stand still, 4 -> death, 3 -> little move
p . putULong ( model ) # model
p . putFloat ( 0x00 ) # x
p . putFloat ( player . y ) # y
p . putFloat ( player . z ) # z
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( 0x00 ) # unknown
p . putULong ( ( player . o + 30 ) % 360 ) # orientation
p . putULong ( 0x00 ) # unknown
p . putByte ( 0x0a ) # opcode
p . putByte ( 0x12 ) # length
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # unknown
p . putByte ( plid ) # player index
p . putShort ( player . oid ) # object id
p . putByte ( 0x00 ) # unknown
p . putByte ( 0x00 ) # 1 -> stand still, 4 -> death, 3 -> little move
p . putULong ( model ) # model
p . putULong ( 0x00 )
p . putByte ( 0x00 )
p . putByte ( 0x00 )
await self . broadcast_gamedata ( p . getvalue ( ) , acknow = False )
#await self.broadcast_gamedata(bytes.fromhex("0a32000000" + plix + struct.pack("<B", objid).hex() + "000001" + model + "000000ff00000000000000000000000000000000000000000000000000000000000000000000000a12000000" + plix + struct.pack("<B", objid).hex() + "0000" + model + "020000000000000000"), acknow=False)
def get_player_index ( self , player ) :
for iplayer in range ( len ( self . players ) ) :
if self . players [ iplayer ] == player :
return iplayer
return False
2019-03-05 01:30:20 +01:00
2019-03-05 03:58:01 +01:00
def get_player_by_index ( self , playerindex ) :
return self . players [ playerindex ]
2019-01-22 01:30:42 +01:00
if __name__ == ' __main__ ' :
2019-03-13 01:37:49 +01:00
server = Server ( name = " giantsd " , maxplayers = 20 , register = False , teams = Teams . MvM , map = Map ( " Three Way Island - Canyons.gck " ) ) #, map=Map("Three Way Island - Canyons.gck"))
2019-02-06 01:07:00 +01:00
server . load_plugins ( )
loop = asyncio . get_event_loop ( )
listen = loop . create_datagram_endpoint ( lambda : Netserver ( server ) , local_addr = ( server . listen_ip , server . listen_port ) )
transport , protocol = loop . run_until_complete ( listen )
2019-03-13 01:37:49 +01:00
loop . create_task ( server . ask_command ( ) )
2019-02-06 01:07:00 +01:00
try :
loop . run_forever ( )
except KeyboardInterrupt :
pass
transport . close ( )
loop . close ( )