Added World Loading (Replica Components Not Implemented)

This commit is contained in:
Wesley
2018-06-28 23:41:50 -04:00
parent ec1798346a
commit ecb3bd492e
10 changed files with 240 additions and 70 deletions
+3 -3
View File
@@ -38,12 +38,12 @@ if __name__ == "__main__":
auth_server = services.AuthServerService(game)
game.register_service(auth_server)
world = services.WorldService(game)
game.register_service(world)
world_server = services.WorldServerService(game)
game.register_service(world_server)
world = services.WorldService(game)
game.register_service(world)
game.start()
loop = asyncio.get_event_loop()
+1
View File
@@ -22,6 +22,7 @@ class Game(game_types.BaseObject):
for service in self._services:
service_thread = game_types.GameThread(target=service.initialize)
service_thread.start()
self.trigger_event("GameStarted")
def generate_object_id(self):
id = random.randint(100000000000000000, 999999999999999999)
+65 -33
View File
@@ -14,7 +14,7 @@ class PacketHeaderEnum(Enum):
CLIENT_DELETE_MINIFIGURE_REQUEST = b'S\x04\x00\x06\x00\x00\x00\x00'
WORLD_INFO = b'S\x05\x00\x02\x00\x00\x00\x00'
CLINET_ENTER_WORLD = b'S\x04\x00\x04\x00\x00\x00\x00'
CLINET_LOAD_COMPLETE = b'S\x04\x00\x13\x00\x00\x00\x00'
CLIENT_LOAD_COMPLETE = b'S\x04\x00\x13\x00\x00\x00\x00'
DETAILED_USER_INFO = b'S\x05\x00\x04\x00\x00\x00\x00'
ROUTED_PACKET = b'S\x04\x00\x15\x00\x00\x00\x00'
CLIENT_GAME_MESSAGE = b'S\x04\x00\x05\x00\x00\x00\x00'
@@ -74,7 +74,7 @@ class ItemLOTs(IntEnum):
PANTS_REDDISH_BROWN = 2526
PANTS_DARK_RED = 2527
ZoneChecksums = {
zone_checksums = {
1000: 0x20b8087c,
1001: 0x26680a3c,
1100: 0x49525511,
@@ -108,37 +108,69 @@ ZoneChecksums = {
2001: 0x09eb00ef
}
DefaultZoneSpawns = {1000 : [-624.13, 613.326233, -30.974],
1001 : [-187.2391, 608.2743, 54.5554352],
1100 : [522.9949, 406.040375, 129.992722],
1101 : [35.0297, 365.780426, -201.578369],
1102 : [-18.7062054, 440.20932, 37.5326424],
1150 : [-18.7062054, 440.20932, 37.5326424],
1151 : [25.0526543, 472.215027, -24.318882],
1200 : [-40.0, 293.047, -16.0],
1201 : [111.670906, 229.282776, 179.87793],
1203 : [0.0, 0.0, 0.0],
1204 : [-12.1019106, 212.900024, 191.147964],
1250 : [-17.8299046, 440.509674, 30.0326862],
1251 : [31.55009, 470.885254, 193.457321],
1300 : [-329.965881, 302.470184, -470.232758],
1302 : [-293.072571, 233.0, -4.16148],
1303 : [0.0, 0.0, 0.0],
1350 : [-19.713892, 440.20932, 26.935009],
1400 : [390.284363, 229.452881, -511.350983],
1402 : [-264.426575, 290.3452, 308.619049],
1403 : [-1457.71826, 794.0, -332.2917],
1450 : [-26.8431015, 425.11496, 53.7349777],
1600 : [34.6352119, 1571.29309, 48.0321465],
1601 : [-90.30964, 211.087067, -126.3196],
1602 : [-163.2, 217.254913, 172.0],
1603 : [9.18036652, 48.79997, 109.610374],
1604 : [-99.80103, 231.916946, -162.67955],
1700 : [-359.979156, 1066.328, -369.287781],
1800 : [-241.965515, 92.78052, 557.327942],
1900 : [165.355682, 1164.17822, -543.9093],
2000 : [-446.79715, 171.158859, 1122.83545],
2001 : [11.26009, 211.05188, 40.6721039]}
default_zone_spawns = {1000 : [-624.13, 613.326233, -30.974],
1001 : [-187.2391, 608.2743, 54.5554352],
1100 : [522.9949, 406.040375, 129.992722],
1101 : [35.0297, 365.780426, -201.578369],
1102 : [-18.7062054, 440.20932, 37.5326424],
1150 : [-18.7062054, 440.20932, 37.5326424],
1151 : [25.0526543, 472.215027, -24.318882],
1200 : [-40.0, 293.047, -16.0],
1201 : [111.670906, 229.282776, 179.87793],
1203 : [0.0, 0.0, 0.0],
1204 : [-12.1019106, 212.900024, 191.147964],
1250 : [-17.8299046, 440.509674, 30.0326862],
1251 : [31.55009, 470.885254, 193.457321],
1300 : [-329.965881, 302.470184, -470.232758],
1302 : [-293.072571, 233.0, -4.16148],
1303 : [0.0, 0.0, 0.0],
1350 : [-19.713892, 440.20932, 26.935009],
1400 : [390.284363, 229.452881, -511.350983],
1402 : [-264.426575, 290.3452, 308.619049],
1403 : [-1457.71826, 794.0, -332.2917],
1450 : [-26.8431015, 425.11496, 53.7349777],
1600 : [34.6352119, 1571.29309, 48.0321465],
1601 : [-90.30964, 211.087067, -126.3196],
1602 : [-163.2, 217.254913, 172.0],
1603 : [9.18036652, 48.79997, 109.610374],
1604 : [-99.80103, 231.916946, -162.67955],
1700 : [-359.979156, 1066.328, -369.287781],
1800 : [-241.965515, 92.78052, 557.327942],
1900 : [165.355682, 1164.17822, -543.9093],
2000 : [-446.79715, 171.158859, 1122.83545],
2001 : [11.26009, 211.05188, 40.6721039]}
zone_names = {1000 : "Venture Explorer",
1001 : "Return To The Venture Explorer",
1100 : "Avant Gardens",
1101 : "Avant Gardens Survival",
1102 : "Spider Queen Battle",
1150 : "Block Yard",
1151 : "Avant Grove",
1200 : "Nimbus Station",
1201 : "Pet Cove",
1203 : "Vertigo Loop",
1204 : "Battle of Nimbus Station",
1250 : "Nimbus Rock",
1251 : "Nimbus Isle",
1300 : "Gnarled Forest",
1302 : "Canyon Cove",
1303 : "Keelhaul Canyon",
1350 : "Chantey Shantey",
1400 : "Forbidden Valley",
1402 : "Forbidden Valley Dragon",
1403 : "Dragonmaw Chasm",
1450 : "Raven Bluff",
1600 : "Starbase 3001",
1601 : "Deep Freeze",
1602 : "Robot City",
1603 : "Moon Base",
1604 : "Portabello",
1700 : "LEGO Club",
1800 : "Crux Prime",
1900 : "Nexus Tower",
2000 : "Ninjago Monastery",
2001 : "Frakjaw Battle"}
class MinifigureCreationResponseEnum(IntEnum):
SUCCESS = 0x00
+13
View File
@@ -0,0 +1,13 @@
'''
This script will do things that are supposed to happen on bootup
'''
game = self._parent
@game.register_event_handler("ServiceRegistered")
def register_zones(service):
from game_enums import zone_names
if(service.get_name() == "World"):
for zone in zone_names:
service.register_scene(level=zone, name=zone_names[zone])
print("Registered {}!".format(zone_names[zone]))
-10
View File
@@ -1,10 +0,0 @@
'''
This is a test script.
'''
print("'{}' Has Been Started (This Is A Test Message)".format(self._name))
+47 -7
View File
@@ -3,6 +3,7 @@ import typing
from pyraknet.bitstream import *
import pyraknet.replicamanager
from pyraknet.messages import *
from xml.etree import ElementTree
class BaseObject():
def __init__(self, parent):
@@ -67,9 +68,9 @@ class Vector3():
self.Z : float = Z
if(str_val is not None):
vector_list = str_val.split(",")
self.X = vector_list[0]
self.Y = vector_list[1]
self.Z = vector_list[2]
self.X = float(vector_list[0])
self.Y = float(vector_list[1])
self.Z = float(vector_list[2])
def __add__(self, other):
return Vector3(self.X + other.X,self.Y + other.Y,self.Z + other.Z)
@@ -85,7 +86,46 @@ class Vector3():
def __str__(self):
return "{},{},{}".format(self.X, self.Y, self.Z)
def __eq__(self, other):
if(self.X == other.X and self.Y == other.Y and self.Z == other.Z):
return True
else:
return False
class LDF():
def __init__(self):
self._keys : list = []
def register_key(self, key_name : str, value : any, type : int):
self._keys.append([key_name, value, type])
def write_to_stream(self, stream : WriteStream):
key_num = len(self._keys)
stream.write(c_uint(key_num))
for key in self._keys:
name = key[0]
value = key[1]
type = key[2]
stream.write(c_uint8(len(name) * 2))
for char in name:
stream.write(char.encode('latin1'))
stream.write(b'\0')
stream.write(c_ubyte(type))
if(type == 0):
stream.write(value, length_type=c_uint)
elif(type == 1):
stream.write(c_int(value))
elif(type == 3):
stream.write(c_float(value))
elif(type == 5):
stream.write(c_uint(value))
elif(type == 7):
stream.write(c_bool(value))
elif(type == 8 or type == 9):
stream.write(c_int64(value))
elif(type == 13):
xml_str = bytes(ElementTree.tostring(value))
xml_str = b'<?xml version="1.0">' + xml_str
stream.write(c_ulong(xml_str.__len__()))
stream.write(xml_str)
class Vector4():
def __init__(self, X : float = 0.0, Y : float = 0.0, Z : float = 0.0, W : float = 0.0, str_val: str = None):
@@ -95,10 +135,10 @@ class Vector4():
self.W : float = W
if(str_val is not None):
vector_list = str_val.split(",")
self.X = vector_list[0]
self.Y = vector_list[1]
self.Z = vector_list[2]
self.W = vector_list[3]
self.X = float(vector_list[0])
self.Y = float(vector_list[1])
self.Z = float(vector_list[2])
self.W = float(vector_list[3])
def __add__(self, other):
return Vector4(self.X + other.X, self.Y + other.Y, self.Z + other.Z, self.W + other.W)
+4 -3
View File
@@ -39,9 +39,10 @@ class PlayerService(services.GameService):
account = account_table.select(["account_id", "username", "banned", "is_admin"], "account_id = {}".format(account_id))[0]
characters = character_table.select_all("account_id = {}".format(account_id))
for character in characters:
character["Data"] = character_data_table.select_all("player_id = {}".format(character["player_id"]))[0]
character["Data"]["position"] = game_types.Vector3(str_val=character["Data"]["position"])
character["Data"]["rotation"] = game_types.Vector4(str_val=character["Data"]["rotation"])
data = character_data_table.select_all("player_id = {}".format(character["player_id"]))[0]
data["position"] = game_types.Vector3(str_val=data["position"])
data["rotation"] = game_types.Vector4(str_val=data["rotation"])
character["Data"] = data
character["Stats"] = character_stats_table.select_all("player_id = {}".format(character["player_id"]))[0]
character["CompletedMissions"] = completed_missions_table.select_all("player_id = {}".format(character["player_id"]))
character["CurrentMissions"] = current_missions_table.select_all("player_id = {}".format(character["player_id"]))
BIN
View File
Binary file not shown.
+9 -5
View File
@@ -29,8 +29,11 @@ class WorldService(GameService):
self._name = "World"
self._scenes : typing.List[scene.Scene] = []
def add_scene(self, level : int, name : str = "Scene"):
self._scenes.append(scene.Scene(self, level, name))
def register_scene(self, level : int, name : str = "Scene"):
new_scene = scene.Scene(self, level, name)
self._scenes.append(new_scene)
self.get_parent().trigger_event("SceneRegistered", args=(new_scene,))
def get_scene_by_id(self, id : int):
for scene in self._scenes:
@@ -45,11 +48,12 @@ class WorldService(GameService):
scenes.append(scene)
return scenes
def get_scene_by_name(self, name: str):
def get_scenes_by_name(self, name: str):
scenes = []
for scene in self._scenes:
if(scene.get_name() == name):
return scene
return None
scenes.append(scene)
return scene
def get_scenes(self):
return self._scenes
+98 -9
View File
@@ -5,6 +5,8 @@ import game_enums
import os
import game_types
from pyraknet.bitstream import *
import zlib
from xml.etree import ElementTree
class WorldServer(pyraknet.server.Server):
@@ -19,7 +21,9 @@ class WorldServer(pyraknet.server.Server):
"world_session_info":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_USER_SESSION_INFO.value), self.handle_session_info],
"world_minifigure_list":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_MINIFIGURE_LIST_REQUEST.value), self.handle_minifig_list_request],
"world_minifig_creation":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_MINIFIGURE_CREATE_REQUEST.value), self.handle_minifig_creation],
"world_minifig_deletion:":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_DELETE_MINIFIGURE_REQUEST.value), self.handle_minifig_deletion]}
"world_minifig_deletion:":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_DELETE_MINIFIGURE_REQUEST.value), self.handle_minifig_deletion],
"world_join_world":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLINET_ENTER_WORLD.value), self.handle_join_world],
"world_detailed_user_info":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_LOAD_COMPLETE.value), self.handle_detailed_user_info]}
def handle_handshake(self, data: bytes, address):
stream = ReadStream(data)
@@ -85,24 +89,25 @@ class WorldServer(pyraknet.server.Server):
time.sleep(.5)
self.handle_minifig_list_request(data, address)
def load_world(self, player_id: int, level_id: int, spawn_at_default: bool = False):
def load_world(self, player_id: int, level_id: int, address, spawn_at_default: bool = False):
packet = WriteStream()
player = game.get_service("Player").get_player_by_id(player_id)
world = game.get_service("World")
session = game.get_service("Session").get_session_by_player_id(player_id)
session = game.get_service("Session").get_session_by_address(address)
session.player_id = player_id
scene = world.get_scenes_by_level(level_id)[0]
print("Sending Player {} to {}".format(player_id, scene.get_name()))
packet.write(game_enums.PacketHeaderEnum.WORLD_INFO)
packet.write(game_enums.PacketHeaderEnum.WORLD_INFO.value)
packet.write(c_uint16(level_id))
packet.write(c_uint16(0)) # Map Instance
packet.write(c_ulong(0)) # Map Clone
packet.write(c_ulong(game_enums.ZoneChecksums[level_id]))
packet.write(c_ulong(game_enums.zone_checksums[level_id]))
if (spawn_at_default):
packet.write(c_float(game_enums.DefaultZoneSpawns[level_id][0]))
packet.write(c_float(game_enums.DefaultZoneSpawns[level_id][1]))
packet.write(c_float(game_enums.DefaultZoneSpawns[level_id][2]))
player["position"] = game_types.Vector3(game_enums.DefaultZoneSpawns[level_id][0], game_enums.DefaultZoneSpawns[level_id][1], game_enums.DefaultZoneSpawns[level_id][2])
packet.write(c_float(game_enums.default_zone_spawns[level_id][0]))
packet.write(c_float(game_enums.default_zone_spawns[level_id][1]))
packet.write(c_float(game_enums.default_zone_spawns[level_id][2]))
player["position"] = game_types.Vector3(game_enums.default_zone_spawns[level_id][0], game_enums.default_zone_spawns[level_id][1], game_enums.default_zone_spawns[level_id][2])
else:
packet.write(c_float(player["position"].X))
packet.write(c_float(player["position"].Y))
@@ -116,8 +121,92 @@ class WorldServer(pyraknet.server.Server):
else:
game.get_pyobject(session.scene_id).remove_player(player_id)
scene.add_player(player_id)
session.scene_id = scene.get_py_id()
self.send(packet, session.address)
def handle_detailed_user_info(self, data: bytes, address):
session = game.get_service("Session").get_session_by_address(address)
player = game.get_service("Player").get_player_by_id(session.player_id)
ldf = game_types.LDF()
ldf.register_key("levelid", player["zone"], 1)
ldf.register_key("objid", player["player_id"], 9)
ldf.register_key("template", 1, 1)
ldf.register_key("name", player["name"], 0)
root = ElementTree.Element("obj")
root.set("v", "1")
buff = ElementTree.SubElement(root, "buff")
skill = ElementTree.SubElement(root, "skill")
inv = ElementTree.SubElement(root, "inv")
bag = ElementTree.SubElement(inv, "bag")
bag_info = ElementTree.SubElement(bag, "b")
bag_info.set("t", "0")
bag_info.set("m", str(player["Data"]["backpack_space"]))
items = ElementTree.SubElement(inv, "items")
item_in = ElementTree.SubElement(items, "in")
for item in player["Inventory"]:
i = ElementTree.SubElement(item_in, "i")
i.set("l", str(item["lot"]))
i.set("id", str(item["item_id"]))
i.set("s", str(item["lot"]))
i.set("c", str(item["quantity"]))
i.set("b", str(int(item["linked"])))
i.set("eq", str(int(item["equipped"])))
mf = ElementTree.SubElement(root, "mf")
char = ElementTree.SubElement(root, "char")
char.set("cc", str(player["currency"]))
char.set("ls", str(player["universe_score"]))
lvl = ElementTree.SubElement(root, "lvl")
lvl.set("l", str(player["level"]))
pets = ElementTree.SubElement(root, "pet")
mis = ElementTree.SubElement(root, "mis")
done = ElementTree.SubElement(mis, "done")
for mission in player["CompletedMissions"]:
m = ElementTree.SubElement(done, "m")
m.set("id", str(mission["mission_id"]))
m.set("cct", "1")
m.set("cts", "0")
cur = ElementTree.SubElement(mis, "cur")
for mission in player["CurrentMissions"]:
m = ElementTree.SubElement(cur, "m")
m.set("id", str(mission["mission_id"]))
sv = ElementTree.SubElement(m, "sv")
sv.set("v", str(mission["progress"]))
ldf.register_key("xmlData", root, 13)
lego_data = WriteStream()
ldf.write_to_stream(lego_data)
ldf_bytes = bytes(lego_data)
compressed = zlib.compress(ldf_bytes)
packet = WriteStream()
packet.write(game_enums.PacketHeaderEnum.DETAILED_USER_INFO)
packet.write(c_ulong(len(compressed) + 9))
packet.write(c_bool(True))
packet.write(c_ulong(len(ldf_bytes)))
packet.write(c_ulong(len(compressed)))
packet.write(compressed)
self.send(packet, address)
print("Sent Detailed User Info To {}".format(player["name"]))
def handle_join_world(self, data: bytes, address):
stream = ReadStream(data)
player_id = stream.read(c_longlong)
player = game.get_service("Player").get_player_by_id(player_id)
if (player["zone"] == 0):
player["zone"] = 1000
spawn_at_default = False
if (player["Data"]["position"].X < 2 and player["Data"]["position"].Y < 2 and player["Data"]["position"].Z < 2):
spawn_at_default = True
self.load_world(player_id, player["zone"], address, spawn_at_default=spawn_at_default)
def handle_session_info(self, data: bytes, address):
stream = ReadStream(data)
username = stream.read(str, allocated_length=33)