forked from hipstercat/giantsd
Added more commands
This commit is contained in:
parent
556c9dcc69
commit
d962495e48
@ -123,13 +123,12 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
appdata.putShort(self.server.points_per_kill)
|
appdata.putShort(self.server.points_per_kill)
|
||||||
appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client
|
appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client
|
||||||
appdata.putShort(self.server.detente_time)
|
appdata.putShort(self.server.detente_time)
|
||||||
appdata.write(
|
appdata.write(self.server.currentmap.checksum) # Seems to be a checksum of current map OR linked to the number of chars in the map name
|
||||||
b'\x9f\xb2\x42\xec') # Seems to be a checksum of current map OR linked to the number of chars in the map name
|
|
||||||
appdata.write(self.server.currentmap.mapname.encode("ascii"))
|
appdata.write(self.server.currentmap.mapname.encode("ascii"))
|
||||||
appdata.write(b'\x00' * (32 - len(self.server.currentmap.mapname)))
|
appdata.write(b'\x00' * (32 - len(self.server.currentmap.mapname)))
|
||||||
er.ApplicationReservedData = appdata.getvalue()
|
er.ApplicationReservedData = appdata.getvalue()
|
||||||
|
|
||||||
logger.debug("Current map: %s", self.server.currentmap.mapname)
|
logger.debug("Current map: %s, checksum: %s", self.server.currentmap.mapname, self.server.currentmap.checksum)
|
||||||
er.ApplicationReservedData += b'\x00' * (32 - len(self.server.currentmap.mapname))
|
er.ApplicationReservedData += b'\x00' * (32 - len(self.server.currentmap.mapname))
|
||||||
self.send_packet(addr, er.to_packet())
|
self.send_packet(addr, er.to_packet())
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -220,7 +219,8 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
sack_sent = True
|
sack_sent = True
|
||||||
|
|
||||||
# release lock for new packet to be sent
|
# release lock for new packet to be sent
|
||||||
session.lock.release()
|
if session.lock.locked():
|
||||||
|
session.lock.release()
|
||||||
|
|
||||||
# WIP: The bNSeq, bNRcv, optional selective acknowledgment (SACK), and optional send mask fields are then processed by using the standard rules in sections 3.1.5.2.1 through 3.1.5.2.4
|
# WIP: The bNSeq, bNRcv, optional selective acknowledgment (SACK), and optional send mask fields are then processed by using the standard rules in sections 3.1.5.2.1 through 3.1.5.2.4
|
||||||
# TODO: A successfully validated SACK packet SHOULD count as a valid receive and thus restart the KeepAlive timer
|
# TODO: A successfully validated SACK packet SHOULD count as a valid receive and thus restart the KeepAlive timer
|
||||||
@ -274,10 +274,13 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
|
|
||||||
if dframe.Command & DFrame.PACKET_COMMAND_POLL:
|
if dframe.Command & DFrame.PACKET_COMMAND_POLL:
|
||||||
#logger.debug("Sending SACK")
|
#logger.debug("Sending SACK")
|
||||||
#session.send_cframe_sack()
|
session.send_cframe_sack()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
session.next_expected_seq += 1
|
if session.next_expected_seq == 255:
|
||||||
|
session.next_expected_seq = 0
|
||||||
|
else:
|
||||||
|
session.next_expected_seq += 1
|
||||||
if dframe.Payload:
|
if dframe.Payload:
|
||||||
await self.handle_game_packet(session, dframe.Payload)
|
await self.handle_game_packet(session, dframe.Payload)
|
||||||
else:
|
else:
|
||||||
@ -336,11 +339,12 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
appdata.putShort(self.server.points_per_kill)
|
appdata.putShort(self.server.points_per_kill)
|
||||||
appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client
|
appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client
|
||||||
appdata.putShort(self.server.detente_time)
|
appdata.putShort(self.server.detente_time)
|
||||||
appdata.write(b'\x9f\xb2\x42\xec') # Seems to be a checksum of current map OR linked to the number of chars in the map name
|
appdata.write(self.server.currentmap.checksum) # Seems to be a checksum of current map OR linked to the number of chars in the map name
|
||||||
appdata.write(self.server.currentmap.mapname.encode("ascii"))
|
appdata.write(self.server.currentmap.mapname.encode("ascii"))
|
||||||
appdata.write(b'\x00' * (32 - len(self.server.currentmap.mapname)))
|
appdata.write(b'\x00' * (32 - len(self.server.currentmap.mapname)))
|
||||||
d.ApplicationReservedData = appdata.getvalue()
|
d.ApplicationReservedData = appdata.getvalue()
|
||||||
session.send(d)
|
session.send(d)
|
||||||
|
logger.debug("%s:%s > %s (GAMEDATA)", session.ip, session.port, appdata.getvalue().hex())
|
||||||
player.phase = PlayerPhases.DN_SEND_CONNECT_INFO
|
player.phase = PlayerPhases.DN_SEND_CONNECT_INFO
|
||||||
|
|
||||||
elif payload[0] == 0xc3:
|
elif payload[0] == 0xc3:
|
||||||
@ -371,27 +375,6 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
await player.session.send_gamedata(p1, acknow=False)
|
await player.session.send_gamedata(p1, acknow=False)
|
||||||
await player.session.send_gamedata(b'\x3d\x00\x5b\x53\x65\x72\x76\x65\x72\x5d'+b"\x00"*25, acknow=True) # [SERVER]
|
await player.session.send_gamedata(b'\x3d\x00\x5b\x53\x65\x72\x76\x65\x72\x5d'+b"\x00"*25, acknow=True) # [SERVER]
|
||||||
await player.session.send_gamedata(b'\x3d\x01'+player.name.encode("ascii")+b"\x00"*(33-len(player.name.encode("ascii"))), acknow=True) # playername
|
await player.session.send_gamedata(b'\x3d\x01'+player.name.encode("ascii")+b"\x00"*(33-len(player.name.encode("ascii"))), acknow=True) # playername
|
||||||
"""
|
|
||||||
player.session.send_gamedata(b'\x0f\x56\xab\x31\x96\x06\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
player.session.send_gamedata(b'\x10\x02\x56\xab\x31\x96\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
player.session.send_gamedata(b'\x29\x28\x00\x00\x80\x32\x00\x00\x80\x05\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
player.session.send_gamedata(b'\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
player.session.send_gamedata(b'\x39\x01\x02\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
player.session.send_gamedata(b'\x0f\x56\xab\x31\x96\x07\x00\x00\x00\x00\x00\x00\x00\x00') # unknown
|
|
||||||
|
|
||||||
player.session.send_gamedata(b'\x0a\x12\x00\x00\x00\x00\x28\x10\x03\x10\x12\x00\x00\x00\xc1\xff\x41\xff\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0f\x56\xab\x31\x96\x08\x00\x00\x00\x00\x00\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x12\x00\x00\x00\x00\x2c\x10\x03\x10\x12\x00\x00\x00\x08\x00\xb6\x01\x0a\x14\x00\x00\x00\x00\x2d\x10\x03\x01\x12\x00\x00\x00\xd4\xfc\x9b\xfd\x00\x00\x00', acknow=True) # unknown
|
|
||||||
#\x00
|
|
||||||
player.session.send_gamedata(b'\x2f\x02\x00\x00\xbe\x00\x00\x00\x00\x00\x00\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x12\x00\x00\x00\x00\x2e\x10\x03\x10\x12\x00\x00\x00\xa8\xfd\x2d\x03\x0a\x14\x00\x00\x00\x00\x2e\x10\x03\x01\x12\x00\x00\x00\x60\xfd\x14\x03\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x14\x00\x00\x00\x00\x28\x10\x03\x01\x12\x00\x00\x00\xbf\xff\x3f\xff\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x12\x00\x00\x00\x00\x2a\x10\x03\x10\x12\x00\x00\x00\x73\x01\x42\x02\x0a\x14\x00\x00\x00\x00\x2a\x10\x03\x01\x12\x00\x00\x00\xbe\x01\x8c\x02\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x2f\x02\x00\x00\xc2\x00\x00\x00\x00\x00\x00\x00\x00\x00',acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x14\x00\x00\x00\x00\x2c\x10\x03\x01\x12\x00\x00\x00\x06\x00\xb5\x01\x00\x00\x00', acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x0a\x12\x00\x00\x00\x00\x2e\x10\x03\x10\x12\x00\x00\x00\xa4\xfd\x2c\x03\x00',acknow=True) # unknown
|
|
||||||
player.session.send_gamedata(b'\x2f\x02\x00\x00\xc2\x00\x00\x00\x00\x00\x00\x00\x00\x00', acknow=True) # unknown
|
|
||||||
"""
|
|
||||||
elif payload[0] == 0x0f:
|
elif payload[0] == 0x0f:
|
||||||
player = self.get_player(session)
|
player = self.get_player(session)
|
||||||
if not player:
|
if not player:
|
||||||
@ -410,14 +393,34 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
out.putULong(playerid)
|
out.putULong(playerid)
|
||||||
out.putByte(status)
|
out.putByte(status)
|
||||||
await player.session.send_gamedata(out.getvalue(), acknow=False)
|
await player.session.send_gamedata(out.getvalue(), acknow=False)
|
||||||
elif payload[0] == 0x2c:
|
|
||||||
|
elif payload[0] == 0x2c: # CMSG_CHANGE_TEAM: team (byte), player id (int), unknown (byte)
|
||||||
player = self.get_player(session)
|
player = self.get_player(session)
|
||||||
if not player:
|
if not player:
|
||||||
logger.debug("Fuck that no player wtf man")
|
logger.debug("Fuck that no player wtf man")
|
||||||
return
|
return
|
||||||
|
|
||||||
# assign team?
|
p = Packet(payload)
|
||||||
await player.session.send_gamedata(b"\x10"+struct.pack("<B", player.team)+struct.pack("<L", player.id)+b"\x00\x00", acknow=False)
|
opcode = p.getByte()
|
||||||
|
team = p.getByte()
|
||||||
|
playerid = p.getULong()
|
||||||
|
unknown = p.getByte()
|
||||||
|
|
||||||
|
await player.change_team(team-128)
|
||||||
|
await self.server.broadcast_event("on_player_change_team", player, player.team)
|
||||||
|
elif payload[0] == 0x35: # CMSG_SEND_CHAT_MESSAGE: messagetype? (byte), team? (byte), message (string)
|
||||||
|
player = self.get_player(session)
|
||||||
|
if not player:
|
||||||
|
logger.debug("Fuck that no player wtf man")
|
||||||
|
return
|
||||||
|
|
||||||
|
p = Packet(payload)
|
||||||
|
opcode = p.getByte()
|
||||||
|
type = p.getByte()
|
||||||
|
team = p.getByte()
|
||||||
|
message = p.read().decode("utf8").replace("\x00", "")
|
||||||
|
await self.server.broadcast_event("on_player_chat", player, type, team, message)
|
||||||
|
|
||||||
elif payload[0] == 0x2a:
|
elif payload[0] == 0x2a:
|
||||||
player = self.get_player(session)
|
player = self.get_player(session)
|
||||||
if not player:
|
if not player:
|
||||||
@ -435,10 +438,12 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
logger.debug("Fuck that no player wtf man")
|
logger.debug("Fuck that no player wtf man")
|
||||||
return
|
return
|
||||||
playerping = 1
|
playerping = 1
|
||||||
await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", playerping) + b"\x00",acknow=False) # acknow=True
|
await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", playerping) + b"\x00", acknow=False) # acknow=True
|
||||||
for i in range(0x06):
|
for i in range(0x06):
|
||||||
ack = (i % 2 == 0)
|
ack = (i % 2 == 0)
|
||||||
await player.session.send_gamedata(b"\x04" + struct.pack("<B", i) + b"\x00\x00\x00\x00" + struct.pack("<B", i+0x07) + b"\x00\x00\x00",acknow=ack)
|
await player.session.send_gamedata(b"\x04" + struct.pack("<B", i) + b"\x00\x00\x00\x00" + struct.pack("<B", i+0x07) + b"\x00\x00\x00",acknow=ack)
|
||||||
|
|
||||||
|
# spawn position is sent by client wtf
|
||||||
await player.session.send_gamedata(b"\x1a\xee\x02\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x83\x5f\xa4\x44\x00\xf9\xa3\xc2\x00\x00\x00\x00\xff\xff\x33\x43\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x9e\xdc\x07\x00", acknow=True)
|
await player.session.send_gamedata(b"\x1a\xee\x02\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x83\x5f\xa4\x44\x00\xf9\xa3\xc2\x00\x00\x00\x00\xff\xff\x33\x43\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x9e\xdc\x07\x00", acknow=True)
|
||||||
await player.session.send_gamedata(b"\x19\x96\x03\x00\x10\x00\x00\x04\x00\x0d\x00\x00\x83\x5f\xa4\x44\x00\xf9\xa3\xc2\x00\x00\x00\x00\xff\xff\x33\x43\x00\x00\x7a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00", acknow=False)
|
await player.session.send_gamedata(b"\x19\x96\x03\x00\x10\x00\x00\x04\x00\x0d\x00\x00\x83\x5f\xa4\x44\x00\xf9\xa3\xc2\x00\x00\x00\x00\xff\xff\x33\x43\x00\x00\x7a\x44\x00\x00\x00\x00\x00\x00\x00\x00\x00", acknow=False)
|
||||||
await player.session.send_gamedata(b"\x39"+b"\x00"*21, acknow=True)
|
await player.session.send_gamedata(b"\x39"+b"\x00"*21, acknow=True)
|
||||||
@ -448,122 +453,34 @@ class Netserver(asyncio.DatagramProtocol):
|
|||||||
await player.session.send_gamedata(b"\x3e\x00\x00\x00\x00\x00", acknow=True)
|
await player.session.send_gamedata(b"\x3e\x00\x00\x00\x00\x00", acknow=True)
|
||||||
await player.session.send_gamedata(b"\x3f\x00\x00", acknow=False)
|
await player.session.send_gamedata(b"\x3f\x00\x00", acknow=False)
|
||||||
await player.session.send_gamedata(b"\x0e\x00", acknow=True)
|
await player.session.send_gamedata(b"\x0e\x00", acknow=True)
|
||||||
|
|
||||||
await player.session.send_gamedata(b"\x10" + struct.pack("<B", player.team) + struct.pack("<L", player.id) + b"\x00\x00", acknow=False)
|
await player.session.send_gamedata(b"\x10" + struct.pack("<B", player.team) + struct.pack("<L", player.id) + b"\x00\x00", acknow=False)
|
||||||
|
elif payload[0] == 0x0a and payload[1] == 0x32:
|
||||||
|
player = self.get_player(session)
|
||||||
|
if not player:
|
||||||
|
logger.debug("Fuck that no player wtf man")
|
||||||
|
return
|
||||||
|
p = Packet(payload)
|
||||||
|
opcode = p.getShort()
|
||||||
|
unknown1 = p.getULong()
|
||||||
|
unknown2 = p.getULong()
|
||||||
|
unknown3 = p.getULong()
|
||||||
|
playerx = p.getFloat()
|
||||||
|
playery = p.getFloat()
|
||||||
|
playerz = p.getFloat()
|
||||||
|
unknown4 = p.getULong()
|
||||||
|
unknown5 = p.getULong()
|
||||||
|
unknown6 = p.getULong()
|
||||||
|
unknown7 = p.getULong()
|
||||||
|
unknown8 = p.getULong()
|
||||||
|
unknown9 = p.getULong()
|
||||||
|
|
||||||
|
player.x = playerx
|
||||||
|
player.y = playery
|
||||||
|
player.z = playerz
|
||||||
|
|
||||||
|
logger.info("%s is now at coords (%s,%s,%s)", player.name, player.x, player.y, player.z)
|
||||||
return
|
await self.server.broadcast_message("%s is now at coords (%s,%s,%s)" % (player.name, player.x, player.y, player.z))
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\x71\xa6\x08\x10\x12\x00\x00\x00\xde\xfe\x83\xfd\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\x68\xa6\x08\x10\x12\x00\x00\x00\x50\xff\x5a\xfd\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(b"\x4b\xe0\xe8\x0c\x00\x00\x8a\x14\x00\x00", acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\xa9\xa5\x08\x01\x2d\x00\x00\x00\x25\x54\x05\x46\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x16\x00\x00\x00\x00\x53\xa6\x08\x04\x15\x00\x00\x00\xc2\xfd\x6d\x01\x40\x00\xf4\xff\x0a\x14\x00\x00\x00\x00\x71\xa6\x08\x01\x12\x00\x00\x00\xde\xfe\x81\xfd\x00\x00\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x14\x00\x00\x00\x00\x68\xa6\x08\x01\x12\x00\x00\x00\x51\xff\x5c\xfd\x00\x00\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
playerping = 1
|
|
||||||
await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", playerping) + b"\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\x57\xa6\x08\x10\x12\x00\x00\x00\x2e\xff\xa7\xfd\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x14\x00\x00\x00\x00\x57\xa6\x08\x01\x12\x00\x00\x00\x5b\xff\x75\xfd\x00\x00\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x16\x00\x00\x00\x00\x50\xa6\x08\x04\x15\x00\x00\x00\xe2\xfd\x51\x01\x3d\x00\xed\xff\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x16\x00\x00\x00\x00\x55\xa6\x08\x04\x15\x00\x00\x00\xe5\xfd\x40\x01\xe5\xff\xf8\xff\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\x72\xa6\x08\x10\x12\x00\x00\x00\xf2\xfe\x79\xfd\x0a\x14\x00\x00\x00\x00\x72\xa6\x08\x01\x12\x00\x00\x00\x28\xff\x48\xfd\x00\x00\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x16\x00\x00\x00\x00\x4e\xa6\x08\x04\x15\x00\x00\x00\xc8\xfd\x2f\x01\xa1\xff\x06\x00\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
b"\x0a\x12\x00\x00\x00\x00\xa9\xa5\x08\x01\x2d\x00\x00\x00\x19\x3d\x09\x46\x00",
|
|
||||||
acknow=False) # acknow=True
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000057a608101200000031ffa4fd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000057a608101200000031ffa4fd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000056a6080415000000b1fd4001c8ff120000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000056a6080415000000b1fd4001c8ff120000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a12000000005ca608101200000077ff03fe00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a14000000005ca608011200000050ffd6fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000047a6080415000000bafd1001d0ff0a0000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000072a6081012000000f5fe75fd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000052a6080415000000c9fd45011800080000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a16000000004ca6080415000000c1fdab01e7ff0d0000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a140000000057a608011200000030ffa6fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("2b00000000fa5e5b4500"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex(
|
|
||||||
"0a12000000005ca608101200000074fffffd0a12000000005da608101200000092ff6afd0a140000000072a6080112000000f4fe77fd00000a14000000005da6080112000000a7ff80fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a1200000000a9a508012d000000fe280d4600"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("091200000000c9a50802260000000073a60800"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a140000000073a608011200000009ff97fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("2e070700000000000000"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000054a6080415000000befd88010d00e4ff00"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a16000000004aa6080415000000b0fd5301b4ffb4ff00"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(
|
|
||||||
bytes.fromhex("0a120000000068a608101200000075ff7dfd0a140000000068a608011200000051ff5cfd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a12000000005da608101200000095ff6dfd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex(
|
|
||||||
"0a16000000004ba6080415000000e7fd3f01e0ffa6ff0a160000000049a6080415000000b5fd6101c0ffe5ff00"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a14000000005ca608011200000076ff00fe000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000068a608101200000071ff79fd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("090e00000000c9a508012600000000"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a1200000000a9a508012d000000c016114600"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a16000000004fa6080415000000b2fd8801c9ffceff00"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a14000000005da608011200000094ff6cfd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a160000000048a608041500000011fe5201e2ff2c0000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000073a6081012000000c0fe5efd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a140000000073a608011200000009ff83fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a120000000071a6081012000000fbfec2fd00"), acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a140000000071a6080112000000defe81fd000000"),
|
|
||||||
acknow=False)
|
|
||||||
await player.session.send_gamedata(bytes.fromhex("0a140000000068a608011200000072ff7afd000000"),
|
|
||||||
acknow=False)
|
|
||||||
for i in range(0x7f):
|
|
||||||
if i >= 0x5c:
|
|
||||||
await player.session.send_gamedata(bytes.fromhex(
|
|
||||||
"04" + struct.pack("<B", i).hex() + "00000000" + struct.pack("<B", (
|
|
||||||
0xa4 + i) % 0xff).hex() + "a60800"), acknow=False)
|
|
||||||
else:
|
|
||||||
await player.session.send_gamedata(bytes.fromhex(
|
|
||||||
"04" + struct.pack("<B", i).hex() + "00000000" + struct.pack("<B", 0xa4 + i).hex() + "a50800"),
|
|
||||||
acknow=False)
|
|
||||||
|
|
||||||
await player.session.send_gamedata(b"\x05\x01\x7b\x02\x00\x03\x00\x00\x00\x00", acknow=False) # acknow=True
|
|
||||||
# 0f packet
|
|
||||||
# final packet
|
|
||||||
await player.session.send_gamedata(b"\x2b\x00\x00\x00\x00\xa0\xe8\x5a\x45\x00", acknow=False) # acknow=True
|
|
||||||
|
|
||||||
|
|
||||||
def send_packet(self, addr, packet):
|
def send_packet(self, addr, packet):
|
||||||
|
@ -59,4 +59,21 @@ class GameTypes:
|
|||||||
GTypeStone = 0x08
|
GTypeStone = 0x08
|
||||||
GTypeWood = 0x09
|
GTypeWood = 0x09
|
||||||
Crash = 0x0a
|
Crash = 0x0a
|
||||||
GTypeNull = 0x0c
|
GTypeNull = 0x0c
|
||||||
|
|
||||||
|
|
||||||
|
class ChatColor:
|
||||||
|
Black = 0x00
|
||||||
|
Cyan = 0x01 # or 0x06
|
||||||
|
Yellow = 0x02
|
||||||
|
LightBlue = 0x03
|
||||||
|
Orange = 0x04
|
||||||
|
DarkBlue = 0x05
|
||||||
|
White = 0x07
|
||||||
|
Blue = 0x0c
|
||||||
|
|
||||||
|
|
||||||
|
class ChatType:
|
||||||
|
All = 0x00
|
||||||
|
AllFromPlayer = 0xc0
|
||||||
|
TeamFromPlayer = 0xf0
|
||||||
|
@ -19,6 +19,18 @@ class Map:
|
|||||||
self.checksum = Map.checksum(mappath)
|
self.checksum = Map.checksum(mappath)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def checksum(mapname):
|
def checksum(mappath):
|
||||||
# TODO
|
# TODO
|
||||||
return 1
|
if mappath == "Three Way Island - Canyons.gck":
|
||||||
|
return b"\x9c\x53\xf4\xdd"
|
||||||
|
if mappath == "test1.gck":
|
||||||
|
return b"\x9f\xb2\x42\xec"
|
||||||
|
if mappath == "test.gck":
|
||||||
|
return b"\x48\x52\x33\x23"
|
||||||
|
# \x00\x00\x00\x00: [None]
|
||||||
|
# \x00\x00\x00\x01: <custom map>
|
||||||
|
# \x9c\x53\xf4\xdd: Three Way Island - Canyons
|
||||||
|
# \x1e\xe9\x39\xe1: Still Winter
|
||||||
|
# \x9f\xb2\x42\xec: testv1
|
||||||
|
# \x48\x52\x33\x23: testv2
|
||||||
|
return b"\x00\x00\x00\x00"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
from .entity import Entity
|
from .entity import Entity
|
||||||
import random
|
import random
|
||||||
|
import struct
|
||||||
|
from . import ChatColor, ChatType
|
||||||
|
|
||||||
|
|
||||||
class PlayerPhases:
|
class PlayerPhases:
|
||||||
@ -16,7 +18,20 @@ class Player(Entity):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.session = session
|
self.session = session
|
||||||
self.team = 1
|
self.team = 4
|
||||||
self.score = 0
|
self.score = 0
|
||||||
self.id = random.getrandbits(32)
|
self.id = random.getrandbits(32)
|
||||||
self.phase = PlayerPhases.NONE
|
self.phase = PlayerPhases.NONE
|
||||||
|
self.ping = 1
|
||||||
|
|
||||||
|
async def change_team(self, newteam):
|
||||||
|
self.team = newteam
|
||||||
|
await self.session.send_gamedata(b"\x10"+struct.pack("<B", self.team)+struct.pack("<L", self.id)+b"\x00\x00", acknow=False)
|
||||||
|
|
||||||
|
async def send_ping(self, ping):
|
||||||
|
await self.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", ping) + b"\x00", acknow=False)
|
||||||
|
|
||||||
|
async def send_message(self, message, type=ChatType.All, playerindex=0, color=ChatColor.Orange):
|
||||||
|
options = type | color
|
||||||
|
playeri = 0x80 + playerindex
|
||||||
|
await self.session.send_gamedata(b"\x35" + struct.pack("<B", playeri)+ struct.pack("<B", options) + message.encode("utf8") + b"\x00\x00", acknow=False)
|
64
plugins/commands.py
Normal file
64
plugins/commands.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from giants import ChatColor
|
||||||
|
import asyncio
|
||||||
|
import struct
|
||||||
|
|
||||||
|
|
||||||
|
class Commands:
|
||||||
|
def __init__(self, server):
|
||||||
|
self.server = server
|
||||||
|
|
||||||
|
async def on_player_chat(self, player, type, team, message):
|
||||||
|
await self.server.broadcast_message("%s (%s,%s): %s" % (player.name, type, team, message), color=ChatColor.Yellow)
|
||||||
|
print(message)
|
||||||
|
command = message.split(" ")
|
||||||
|
|
||||||
|
if len(command) > 1 and command[0] == "team":
|
||||||
|
newteam = command[1].replace("\x00", "")
|
||||||
|
print("Changing team of %s to %s" % (player.name, newteam))
|
||||||
|
await self.server.broadcast_message("%s switched to team %s" % (player.name, newteam))
|
||||||
|
await player.change_team(int(newteam))
|
||||||
|
|
||||||
|
if len(command) > 1 and command[0] == "ping":
|
||||||
|
newping = command[1].replace("\x00", "")
|
||||||
|
print("Changing ping of %s to %s" % (player.name, newping))
|
||||||
|
await self.server.broadcast_message("%s set his ping to %s" % (player.name, newping))
|
||||||
|
await player.send_ping(int(newping))
|
||||||
|
|
||||||
|
if command[0] == "ping":
|
||||||
|
print("ping function")
|
||||||
|
await self.server.broadcast_message("pong")
|
||||||
|
|
||||||
|
if command[0] == "colors":
|
||||||
|
# color codes seem to go from 01 to 0F, loop and show each value:
|
||||||
|
for i in range(1, 0xf + 1):
|
||||||
|
print("Trying value %s" % i)
|
||||||
|
await player.send_message("Color %s" % i, color=i)
|
||||||
|
await asyncio.sleep(2) # sleep between each value to see what value makes the client crash
|
||||||
|
|
||||||
|
if command[0] == "chattypes":
|
||||||
|
# type codes seem to go from 00 to 0F, loop and show each value: CRASH
|
||||||
|
for i in range(0, 0xf+1):
|
||||||
|
print("Trying value %s" % i)
|
||||||
|
await self.server.broadcast_message("Type %s" % i, type=i)
|
||||||
|
await asyncio.sleep(2) # sleep between each value to see what value makes the client crash
|
||||||
|
|
||||||
|
if command[0] == "doomchat":
|
||||||
|
# tries every value of first byte and second byte
|
||||||
|
for i in range(3,0xff+1):
|
||||||
|
for j in range(0, 0x81):
|
||||||
|
if i == 0 and j == 2:
|
||||||
|
break # ;)
|
||||||
|
message = "(%s, %s)" % (i, j)
|
||||||
|
print(message)
|
||||||
|
await player.session.send_gamedata(b"\x35" + struct.pack("<B", i)+ struct.pack("<B", j) + message.encode("utf8") + b"\x00\x00", acknow=False)
|
||||||
|
await asyncio.sleep(0.1) # sleep between each value to see what value makes the client crash
|
||||||
|
|
||||||
|
if command[0] == "die" and len(command) > 1:
|
||||||
|
diemethod = int(command[1])
|
||||||
|
await player.send_message("Death by id: %s" % diemethod)
|
||||||
|
await player.session.send_gamedata(bytes.fromhex("0b1a0000000002070000a5b0d4c35d9714c450abef354a68fb410914000000020700000402000000")+struct.pack("<L",diemethod)+bytes.fromhex("0000"))
|
||||||
|
|
||||||
|
|
||||||
|
def setup(server):
|
||||||
|
plugin = Commands(server)
|
||||||
|
server.add_plugin(plugin)
|
@ -1,6 +1,4 @@
|
|||||||
import random
|
import random
|
||||||
import asyncio
|
|
||||||
import struct
|
|
||||||
|
|
||||||
class Greetings:
|
class Greetings:
|
||||||
def __init__(self, server):
|
def __init__(self, server):
|
||||||
@ -9,20 +7,14 @@ class Greetings:
|
|||||||
|
|
||||||
async def on_player_join(self, player):
|
async def on_player_join(self, player):
|
||||||
await self.server.broadcast_message(random.choice(self.messages) % player.name)
|
await self.server.broadcast_message(random.choice(self.messages) % player.name)
|
||||||
#await Greetings.send_ping(player)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
async def send_ping(player):
|
|
||||||
while 1:
|
|
||||||
for ping in range(0, 999):
|
|
||||||
await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", ping) + b"\x00",acknow=True) # acknow=True
|
|
||||||
for ping in range(999, 0, -1):
|
|
||||||
await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("<H", ping) + b"\x00",acknow=True) # acknow=True
|
|
||||||
|
|
||||||
async def on_map_change(self, newmap):
|
async def on_map_change(self, newmap):
|
||||||
await self.server.broadcast_message("You are now playing on "+newmap.mapname)
|
await self.server.broadcast_message("You are now playing on "+newmap.mapname)
|
||||||
|
|
||||||
|
async def on_player_change_team(self, player, newteam):
|
||||||
|
await self.server.broadcast_message("%s switched to team %s" % (player.name, newteam))
|
||||||
|
|
||||||
|
|
||||||
def setup(server):
|
def setup(server):
|
||||||
plugin = Greetings(server)
|
plugin = Greetings(server)
|
||||||
server.add_plugin(plugin)
|
server.add_plugin(plugin)
|
||||||
|
38
server.py
38
server.py
@ -5,10 +5,11 @@ from dpnet.session import Session
|
|||||||
import socket
|
import socket
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
from giants import Teams, GameTypes
|
from giants import Teams, GameTypes, ChatColor, ChatType
|
||||||
from utils.logger import setup_logger
|
from utils.logger import setup_logger
|
||||||
import traceback
|
import traceback
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from aioconsole import ainput
|
||||||
|
|
||||||
logger = setup_logger(__name__)
|
logger = setup_logger(__name__)
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ class Server:
|
|||||||
self.register_with_ms = kwargs.get("register", False)
|
self.register_with_ms = kwargs.get("register", False)
|
||||||
self.teams = kwargs.get("teams", Teams.MvM)
|
self.teams = kwargs.get("teams", Teams.MvM)
|
||||||
self.game_type = kwargs.get("gametype", GameTypes.TeamDeathmatchWithFullBase)
|
self.game_type = kwargs.get("gametype", GameTypes.TeamDeathmatchWithFullBase)
|
||||||
self.currentmap = kwargs.get("map", Map("Three Way Island - Canyons.gck"))
|
self.currentmap = kwargs.get("map", Map("test.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")
|
||||||
|
|
||||||
@ -29,6 +30,11 @@ class Server:
|
|||||||
fake_session.port = 3333
|
fake_session.port = 3333
|
||||||
self.players = [Player("[Server]", fake_session)]
|
self.players = [Player("[Server]", fake_session)]
|
||||||
|
|
||||||
|
fake_player = Session(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
|
||||||
|
fake_player.ip = "127.0.0.1"
|
||||||
|
fake_player.port = 3334
|
||||||
|
self.players.append(Player("Bot 1", fake_player))
|
||||||
|
|
||||||
self.accept_new_players = True
|
self.accept_new_players = True
|
||||||
self.version = 1.497
|
self.version = 1.497
|
||||||
self.points_per_kill = 1
|
self.points_per_kill = 1
|
||||||
@ -46,7 +52,7 @@ class Server:
|
|||||||
async def add_player(self, player):
|
async def add_player(self, player):
|
||||||
self.tempplayers.remove(player)
|
self.tempplayers.remove(player)
|
||||||
self.players.append(player)
|
self.players.append(player)
|
||||||
await self._broadcast_event("on_player_join", player)
|
await self.broadcast_event("on_player_join", player)
|
||||||
|
|
||||||
# todo: remove
|
# todo: remove
|
||||||
def create_temp_player(self, player):
|
def create_temp_player(self, player):
|
||||||
@ -54,7 +60,7 @@ class Server:
|
|||||||
|
|
||||||
async def remove_player(self, player):
|
async def remove_player(self, player):
|
||||||
self.players.remove(player)
|
self.players.remove(player)
|
||||||
await self._broadcast_event("on_player_left", player)
|
await self.broadcast_event("on_player_left", player)
|
||||||
|
|
||||||
def add_plugin(self, plugin):
|
def add_plugin(self, plugin):
|
||||||
self._plugins.append(plugin)
|
self._plugins.append(plugin)
|
||||||
@ -62,11 +68,11 @@ class Server:
|
|||||||
async def change_map(self, mappath):
|
async def change_map(self, mappath):
|
||||||
try:
|
try:
|
||||||
self.currentmap = Map(mappath)
|
self.currentmap = Map(mappath)
|
||||||
await self._broadcast_event("on_map_change", self.currentmap)
|
await self.broadcast_event("on_map_change", self.currentmap)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error("Could not change map")
|
logger.error("Could not change map")
|
||||||
|
|
||||||
async def _broadcast_event(self, event, *args):
|
async def broadcast_event(self, event, *args):
|
||||||
logger.debug("Broadcasting event "+event)
|
logger.debug("Broadcasting event "+event)
|
||||||
for plugin in self._plugins:
|
for plugin in self._plugins:
|
||||||
if hasattr(plugin, event):
|
if hasattr(plugin, event):
|
||||||
@ -97,19 +103,33 @@ class Server:
|
|||||||
logger.warning("Could not load plugin "+plugin)
|
logger.warning("Could not load plugin "+plugin)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
async def broadcast_message(self, text):
|
async def broadcast_message(self, text, color=ChatColor.Orange, type=ChatType.All):
|
||||||
for player in self.players:
|
for player in self.players:
|
||||||
if player.name == "[Server]":
|
if player.name == "[Server]":
|
||||||
continue
|
continue
|
||||||
await player.session.send_gamedata(b'\x35\x80\x81'+text.encode("ascii")+b'\x00\x00', acknow=False)
|
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()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
server = Server(name="giantsd", maxplayers=20, register=False)
|
server = Server(name="giantsd", maxplayers=20, register=False) #, map=Map("Three Way Island - Canyons.gck"))
|
||||||
server.load_plugins()
|
server.load_plugins()
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
listen = loop.create_datagram_endpoint(lambda: Netserver(server), local_addr=(server.listen_ip, server.listen_port))
|
listen = loop.create_datagram_endpoint(lambda: Netserver(server), local_addr=(server.listen_ip, server.listen_port))
|
||||||
transport, protocol = loop.run_until_complete(listen)
|
transport, protocol = loop.run_until_complete(listen)
|
||||||
|
loop.create_task(server.ask_command())
|
||||||
try:
|
try:
|
||||||
loop.run_forever()
|
loop.run_forever()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
Loading…
Reference in New Issue
Block a user