Replacing projects

I didn't like what I was working with in the Old WLUS, so I'm working on a rewrite. This is the initial upload of the rewrite.
This commit is contained in:
Wesley
2020-03-08 15:43:14 -04:00
parent 7f9b99dcf9
commit a9c5b26d38
979 changed files with 8362 additions and 10123 deletions

69
.gitignore vendored
View File

@@ -1,69 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Temporary databases
*.tmp
# Custom config
config.yml
# DB
cms/db.sqlite3
# Pyaknet packet logs
logs/

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 Wesley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,8 +0,0 @@
# WLUS
This is a LEGO Universe Emulator written in Python 3.6</br>
# Installation
This is the development version of WLUS and is currently not recommended to run if you are not familiar with how to do it in previous. A tutorial for an older version of WLUS can be found here https://lusprojects.github.io/
# Disclaimer
The LEGO Group has not endorsed or authorized the operation of this game and is not liable for any safety issues in relation to its operation

View File

@@ -1,67 +1,36 @@
# -*- coding: utf-8 -*-
import game
import services
import session_service
import os
import asyncio
import configparser
import player_service
import threading
"""
This is the file that is used to start various servers.
Command Line Arguments: <mode> <port> <zone> <name>
mode - This determines what will run. There are technically infinite options.
What actually determines what happens are the plugins that are of that same type.
"Master" is a special type though -- it starts the master server. There are no plugins for the master server.
To use a combination of server types like a Char and World server use a '-' between the types
Example: char-world
port - Port for the server
zone - If there's no zone just put 'None' otherwise use the zone id of the world file you want to load
name - The name of the instance (don't use spaces)
"""
import sys
import replica_service
import game_message_service
import chat_command_service
import chat_server_service
import configparser
from core import generic_game_server, master_server
import asyncio
sys.path.append("./plugins")
if __name__ == "__main__":
game = game.Game()
config = configparser.ConfigParser()
config.read("config.ini")
game_config = config["GAME_CONFIG"]
for config_option in game_config:
game.set_config(config_option, eval(game_config[config_option]))
#Append all game scripts to Game
for file in os.listdir("./game_scripts"):
if file.endswith(".py"):
mod = __import__(f'game_scripts.{file[:-3]}', fromlist=["Main"])
if(hasattr(mod, 'Main')):
game.add_script(getattr(mod, 'Main')(game))
database = services.DatabaseService(game)
game.register_service(database)
player = player_service.PlayerService(game)
game.register_service(player)
session = session_service.SessionService(game)
game.register_service(session)
auth_server = services.AuthServerService(game)
game.register_service(auth_server)
world_server = services.WorldServerService(game)
game.register_service(world_server)
game_message = game_message_service.GameMessageService(game)
game.register_service(game_message)
replica = replica_service.ReplicaService(game)
game.register_service(replica)
world = services.WorldService(game)
game.register_service(world)
chat_server = chat_server_service.ChatServerService(game)
game.register_service(chat_server)
chat_command = chat_command_service.ChatCommandService(game)
game.register_service(chat_command)
game.start()
loop = asyncio.get_event_loop()
loop.run_forever()
loop.close()
if len(sys.argv) == 5 and str(sys.argv[1]).lower() != "master":
config = configparser.ConfigParser()
config.read("config.ini")
generic_game_server.GameServer((config["GENERAL"]["bind_address"], int(sys.argv[2])), max_connections=5,
incoming_password=b"3.25 ND1", server_type=str(sys.argv[1]).lower(),
zone=eval(sys.argv[3]), name=sys.argv[4])
print(f"Started WLUS Instance '{sys.argv[4]}'\n Type: [{sys.argv[1].lower()}]\n Port: [{sys.argv[2]}]\n"
f" Zone: [{eval(sys.argv[3])}]")
loop = asyncio.get_event_loop()
loop.run_forever()
loop.close()
elif len(sys.argv) == 3:
server = master_server.MasterServer(('0.0.0.0', int(sys.argv[2])))
else:
print("Missing arguments")

1
auth.bat Normal file
View File

@@ -0,0 +1 @@
python __main__.py auth 1001 None AUTH_1

View File

@@ -1,88 +0,0 @@
import pyraknet.server
import pyraknet.messages
import uuid
import game_types
from pyraknet.bitstream import *
import game_enums
import os
class AuthServer(pyraknet.server.Server):
def __init__(self, address: pyraknet.messages.Address, max_connections: int, incoming_password: bytes, auth_server_service):
super().__init__(address, max_connections, incoming_password)
self.auth_server_service = auth_server_service
self.add_handler(pyraknet.server.Event.UserPacket, self.handle_packet)
global game
game = self.auth_server_service.get_parent()
self.default_handlers = {"auth_handshake":["OnPacket_Auth_{}".format(game_enums.PacketHeaderEnum.HANDSHAKE.value), self.handle_handshake],
"auth_login":["OnPacket_Auth_{}".format(game_enums.PacketHeaderEnum.CLIENT_LOGIN_INFO.value), self.handle_login]}
def handle_handshake(self, data: bytes, address):
stream = ReadStream(data)
client_version = stream.read(c_ulong)
packet = WriteStream()
packet.write(game_enums.PacketHeaderEnum.HANDSHAKE.value)
packet.write(c_ulong(client_version))
packet.write(c_ulong(0x93))
packet.write(c_ulong(1)) # Connection Type (1 For Auth, 4 For Everything Else)
packet.write(c_ulong(os.getpid()))
packet.write(c_short(0xff)) # Local port
packet.write(game.get_config("redirect_address"), allocated_length=33)
self.send(packet, address)
def handle_login(self, data: bytes, address):
stream = ReadStream(data)
username = stream.read(str, allocated_length=33)
password = stream.read(str, allocated_length=41)
packet = WriteStream()
print("Attempted Login With Username '{}' And Password '{}'".format(username, password))
login, user_info = self.auth_server_service.validate_login(username, password)
if (login):
response = game_enums.LoginResponseEnum.SUCCESS.value
print("Login Accepted!")
else:
response = game_enums.LoginResponseEnum.INVALID_LOGIN_INFO.value
print("Login Rejected!")
packet.write(game_enums.PacketHeaderEnum.LOGIN_RESPONSE.value)
packet.write(c_uint8(response))
packet.write(game_types.String("Talk_Like_A_Pirate", allocated_length=33))
packet.write(game_types.String("", allocated_length=33 * 7))
packet.write(c_ushort(1))
packet.write(c_ushort(10)) # Version Major, Current and Minor
packet.write(c_ushort(64))
user_key = (str(uuid.uuid4()))[0:20]
packet.write(user_key, allocated_length=33)
packet.write(game_types.String(game.get_config("redirect_address"), allocated_length=33)) # World Instance IP
packet.write(game_types.String(game.get_config("redirect_address"), allocated_length=33)) # Chat Instance IP
packet.write(c_uint16(2002)) # World Port
packet.write(c_ushort(3003)) # Chat Port
packet.write(game_types.String('0', allocated_length=33)) # Some other IP
packet.write(game_types.String('00000000-0000-0000-0000-000000000000', allocated_length=37))
packet.write(c_ulong(0))
packet.write(game_types.String('US', allocated_length=3)) # US Localization
packet.write(c_bool(False))
packet.write(c_bool(False))
packet.write(c_ulonglong(0))
packet.write("Hello there ;D", length_type=c_uint16) # Custom error message
packet.write(c_uint16(0))
packet.write(c_ulong(4))
self.send(packet, address)
if (login):
session_service = game.get_service("Session")
player_service = game.get_service("Player")
player_service.add_account(account_id=user_info["account_id"])
session_service.add_session(address=address, user_key=user_key, account_id=user_info["account_id"], username=username)
def handle_packet(self, data : bytes, address : pyraknet.messages.Address):
game.trigger_event("OnPacket_Auth_{}".format(str(data[0:8])), args=[data[8:], address], debug=True)

1
char.bat Normal file
View File

@@ -0,0 +1 @@
python __main__.py char 2003 None CHAR_1

View File

@@ -1,91 +0,0 @@
import services
from pyraknet.bitstream import *
import copy
import game_enums
import components
import json
class ChatCommandService(services.GameService):
def __init__(self, parent):
super().__init__(parent)
self._name = "Chat Command"
self._commands = {}
global game
game = self.get_parent()
def initialize(self):
self.register_command("/testmap", self.testmap)
self.register_command("/fly", self.toggle_jetpack)
self.register_command("/togglepvp", self.toggle_pvp)
self.register_command("/gmadditem", self.get_item)
self.register_command("/spawn", self.spawn_lot)
self.register_command("/togglegm", self.toggle_gm, True)
game.register_event_handler("GM_{}".format(game_enums.GameMessages.PARSE_CHAT_MSG.value))(self.handle_command)
super().initialize()
def toggle_gm(self, object_id, address, args, client_state):
player = game.get_service("Player").get_player_object_by_id(object_id)
if(player.gm_level != 2):
player.gm_level = 2
else:
player.gm_level = 2
def toggle_pvp(self, object_id, address, args, client_state):
player = game.get_service("Player").get_player_object_by_id(object_id)
player.zone.pvp_enabled = not player.zone.pvp_enabled
def spawn_lot(self, object_id, address, args, client_state):
player = game.get_service("Player").get_player_object_by_id(object_id)
try:
lot = int(args[0])
except:
return
object_config = {"lot":lot, "object_id":game.generate_object_id(), "position":player.get_component(components.Transform).position}
player.zone.create_object(player.zone, object_config)
database_service = game.get_service("Database")
server_db = database_service.server_db
c = server_db.connection.cursor()
adjusted_config = copy.deepcopy(object_config)
adjusted_config["position"] = str(object_config["position"])
c.execute("INSERT INTO ZoneObjects (zone_id, replica_config) VALUES (?, ?)", (player.zone.get_zone_id(), json.dumps(adjusted_config)))
def handle_command(self, object_id, stream, address):
client_state = stream.read(c_int)
command = stream.read(str, length_type=c_ulong)
args = command.split(" ")
if(args[0] in self._commands):
if (self._commands[args[0]][1] == False or game.get_config("allow_commands") == True or bool(game.get_service("Player").get_account_by_player_id(object_id)["is_admin"]) == True):
copy_args = copy.deepcopy(args)
del copy_args[0]
self._commands[args[0]][0](object_id, address, copy_args, client_state)
def register_command(self, command_name, handler, requires_admin = True):
self._commands[command_name] = [handler, requires_admin]
def get_item(self, object_id, address, args, client_state):
lot = int(args[0])
player_service = game.get_service("Player")
item = player_service.add_item_to_inventory(object_id, lot, json_data={"from":"command"})
if(item is not None):
game.get_service("Game Message").add_item_to_inventory_client_sync(object_id, [address], item["lot"], item["item_id"], item["slot"])
def toggle_jetpack(self, object_id, address, args, client_state):
player = game.get_service("Player").get_player_object_by_id(object_id)
zone = player.zone
if(player is not None):
game.get_service("Game Message").set_jetpack_mode(object_id, zone.get_connections(), bypass_checks=True, use=not player.get_component(components.Character).jetpack_enabled, air_speed=20,
max_air_speed=30, vert_vel=2, effect_id=36)
player.get_component(components.Character).jetpack_enabled = not player.get_component(components.Character).jetpack_enabled
def testmap(self, object_id, address, args, client_state):
if(game.get_service("World").get_zone_by_id(int(args[0])) is not None):
world_server = game.get_service("World Server").server
world_server.load_world(object_id, int(args[0]), address, True)

View File

@@ -1,75 +0,0 @@
import services
import pyraknet.server
import pyraknet.messages
from pyraknet.bitstream import *
import game_enums
import copy
import game_types
class ChatServerService(services.GameService):
def __init__(self, parent):
super().__init__(parent)
self._name = "Chat Server"
self.blacklist = []
if (parent.get_config("chat_port") is not None):
self._port = parent.get_config("chat_port")
else:
self._port = 3003
if (parent.get_config("bind_address") is not None):
self._address = parent.get_config("bind_address")
else:
self._address = "127.0.0.1"
if (parent.get_config("world_max_connections") is not None):#Since you would only be connected to the Chat Server if you were also connected to the World Server why not make them the same
self._max_connections = parent.get_config("world_max_connections")
else:
self._max_connections = 10
self.server = ChatServer((self._address, self._port), max_connections=self._max_connections, incoming_password=b"3.25 ND1", chat_server_service=self)
global game
game = self.get_parent()
def initialize(self):
for handler in self.server.default_handlers:
self.get_parent().register_event_handler(self.server.default_handlers[handler][0])(self.server.default_handlers[handler][1])
super().initialize()
class ChatServer(pyraknet.server.Server):
def __init__(self, address: pyraknet.messages.Address, max_connections: int, incoming_password: bytes, chat_server_service):
super().__init__(address, max_connections, incoming_password)
self.chat_server_service = chat_server_service
self.add_handler(pyraknet.server.Event.UserPacket, self.handle_packet)
self.default_handlers = {"chat_whitelist_request":["OnPacket_World_{}".format(game_enums.PacketHeaderEnum.CLIENT_WHITELIST_REQUEST.value), self.handle_whitelist_request]}
global game
game = self.chat_server_service.get_parent()
def handle_whitelist_request(self, data : bytes, address):#Just make the whole "accepted" and filter out any bad words when we send the actual message
request_packet = ReadStream(data)
super_chat_level = request_packet.read(c_uint8)
request_id = request_packet.read(c_uint8)
stream = WriteStream()
stream.write(game_enums.PacketHeaderEnum.CHAT_MODERATION_RESPONSE.value)
stream.write(c_bit(True))
stream.write(c_uint16(0))
stream.write(c_uint8(request_id))
stream.write(c_uint8(0))
stream.write(game_types.String("", allocated_length=66))
length = int(len(copy.deepcopy(stream).__bytes__()))
stream.write(game_types.String("", allocated_length=99-length))
stream.write(c_uint8(0))
stream.write(c_uint8(0))
ws = game.get_service("World Server")
ws.server.send(stream, address)#Doesn't work for some reason, i'll have to check it out
def handle_packet(self, data : bytes, address : pyraknet.messages.Address):
game.trigger_event("OnPacket_Chat_{}".format(str(data[0:8])), args=[data[8:], address], debug=True)

View File

@@ -1,274 +0,0 @@
import game_types
import typing
import time
import copy
'''
Components are used to attach specific values to game objects
'''
class Component():
def __init__(self, parent):
self._parent = parent
self._name = "Base Component"
def get_name(self):
return self._name
def get_parent(self):
return self._parent
def __setattr__(self, key, value):
super().__setattr__(key, value)
self.get_parent().update()
class Transform(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Transform"
self.scale : int = 1
self.position : game_types.Vector3 = game_types.Vector3()
self.rotation : game_types.Vector4 = game_types.Vector4()
self.velocity : game_types.Vector3 = game_types.Vector3()
self.on_ground : bool = True
self.angular_velocity : game_types.Vector3 = game_types.Vector3()
if(self.get_parent().lot == 1):
self.player_sync_thread = game_types.GameThread(target=self.player_sync)
self.player_sync_thread.start()
def player_sync(self):
player_id = self.get_parent().get_object_id()
game = self.get_parent().zone.get_parent().get_parent()
player_service = game.get_service("Player")
while self.get_parent().player_sync == True:
player = player_service.get_player_by_id(player_id)
player["Data"]["position"] = self.position
player["Data"]["rotation"] = self.rotation
time.sleep(.1)
class Collectible(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Collectible"
self.collectible_id : int = 0
class Bouncer(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Bouncer"
self.pet_required : bool = False
#TODO: Implement This Component, It Doesn't Do Anything Now
class Component107(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Component107"
class Character(Component):
def __init__(self, parent, player_id : int = 0):
super().__init__(parent)
self._name = "Character"
self.player_id : int = player_id
self.vehicle_id : int = 0
self.head_glow : int = 0
self.gm_level : int = 0
self.jetpack_enabled : bool = False
def get_player_info(self):
game = self.get_parent().zone.get_parent().get_parent()
player = game.get_service("Player").get_player_by_id(self.player_id)
account = game.get_service("Player").get_account_by_player_id(self.player_id)
return copy.deepcopy(player), copy.deepcopy(account)
class Minifig(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Minfig"
self.head : int = 0
self.chest : int = 0
self.legs : int = 0
self.hair_style : int = 0
self.hair_color : int = 0
self.chest_decal : int = 0
self.head_color : int = 0
self.left_hand : int = 0
self.right_hand : int = 0
self.eyebrows : int = 0
self.eyes : int = 0
self.mouth : int = 0
class Possessable(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Possessable"
self.driver_object_id : int = 0
#TODO: Implement This Component, It Doesn't Do Anything Now
class Vendor(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Vendor"
class PhysicsEffect(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "PhysicsEffect"
self.effect_type : int = 0
self.effect_amount : float = 0.0
self.effect_direction : game_types.Vector3 = game_types.Vector3()
class VehiclePhysics(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "VehiclePhysics"
self.data_1 : int = 0
self.flag_1 : bool = False
self.flag_2 : bool = False
self.flag_2_1 : bool = False
#TODO: Implement This Component, It Doesn't Do Anything Now
class RacingControl(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "RacingControl"
# TODO: Implement This Component, It Doesn't Do Anything Now
class ScriptedActivity(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "ScriptedActivity"
#TODO: Implement This Component, It Doesn't Do Anything Now
class Skill(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Skill"
class Switch(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Switch"
self.state : bool = False
class Trigger(Component):
def __init__(self, parent):
super().__init__(parent)
self.tigger_id : int = 0
class ModelData(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "ModelData"
self.ldf : game_types.LDF = game_types.LDF()
class Render(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Render"
self.render_disabled : bool = False
self.fx_effects : list = []
def add_fx_effect(self, name, effect_id, effect_type, scale, secondary):
self.fx_effects.append(({"name":name, "effect_id":effect_id, "effect_type":effect_type, "scale":scale, "secondary":secondary}))
#TODO: Implement This Component, It Doesn't Do Anything Now
class ModuleAssembly(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "ModuleAssembly"
class LUPExhibit(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "LUPExhibit"
self.exhibited_lot : int = 10781
#TODO: Implement This Component, It Doesn't Do Anything Now
class ScriptComponent(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "ScriptComponent"
class Pet(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Pet"
self.owner_id : int= 0
self.pet_name : str = "Petty The Pet"
class Stats(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Stats"
self.health : int = 0
self.max_health : int = 0
self.armor : int = 0
self.max_armor : int = 0
self.imagination : int = 0
self.max_imagination : int = 0
self.faction : int = 0
self.is_smashable : bool = False
self.level : int = 1
if(self.get_parent().lot == 1):
self.player_sync_thread = game_types.GameThread(target=self.player_sync)
self.player_sync_thread.start()
def player_sync(self):
player_id = self.get_parent().get_object_id()
game = self.get_parent().zone.get_parent().get_parent()
player_service = game.get_service("Player")
while self.get_parent().player_sync == True:
player = player_service.get_player_by_id(player_id)
player["Data"]["health"] = self.health
player["Data"]["max_health"] = self.max_health
player["Data"]["armor"] = self.armor
player["Data"]["max_armor"] = self.max_armor
player["Data"]["imagination"] = self.imagination
player["Data"]["max_imagination"] = self.max_imagination
time.sleep(.1)
#TODO: Implement This Component, It Doesn't Do Anything Now
class Destructible(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Destructible"
#THIS COMPONENT DOES NOT APPLY TO PLAYERS
class Inventory(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Inventory"
self.items : list = []
def add_item(self, item):
self.items.append(item)
class BaseCombatAI(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "BaseCombatAI"
self.action : int = 0
self.target_id : int = 0
class Rebuild(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "Rebuild"
self.rebuild_state : int = 0
self.success : bool = False
self.enabled : bool = True
self.time_since_start :float = 0.0
self.reset_time : float = 0.0
self.build_activator_pos : game_types.Vector3 = game_types.Vector3()
#TODO: Implement this component
class MovingPlatform(Component):
def __init__(self, parent):
super().__init__(parent)
self._name = "MovingPLatform"

View File

@@ -1,11 +1,11 @@
[GAME_CONFIG]
bind_address="0.0.0.0"
redirect_address="127.0.0.1"
auth_port=1001
world_port=2002
allow_commands=True
auth_max_connections=10
world_max_connections=10
accept_custom_names=False
jonnys_dumb_effect=False
cache_structs=True
[GENERAL]
bind_address=0.0.0.0
master_server_address=127.0.0.1
master_server_port=4211
master_server_password=1124 WLUS2.0
[MYSQL]
user=root
password=1088043
host=127.0.0.1
database=wlus

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,74 @@
"""
This file contains the game server class.
"""
import pyraknet.server
import pyraknet.messages
import threading
from core.plugin_manager import PluginManager
import importlib
from mysql.connector import connection
import configparser
import socket
import sys
class GameServer(pyraknet.server.Server):
def __init__(self, address: pyraknet.messages.Address, max_connections: int, incoming_password: bytes,
server_type: str, zone: int, name: str):
super().__init__(address, max_connections, incoming_password)
self.add_handler(pyraknet.server.Event.UserPacket, self.handle_packet)
self.name = name
self.zone = zone
self.config = configparser.ConfigParser()
self.config.read("config.ini")
self.master_server = socket.socket()
self.master_server.connect((str(self.config["GENERAL"]["master_server_address"]),
int(self.config["GENERAL"]["master_server_port"])))
self.master_server.send(str(self.config["GENERAL"]["master_server_password"]).encode("UTF-8"))
if self.master_server.recv(1024) == b"Accepted":
print("Successfully Logged Into Master Server")
self.master_server.send((str(server_type) + "$" + str(address[1]) + "$" + str(zone) + "$" + str(self.name))
.encode("UTF-8"))
if self.master_server.recv(1024) == b"Registered":
print("Successfully Registered Server")
else:
print("Server Failed Registration")
sys.exit()
else:
print("Server Failed To Login")
sys.exit()
self.packet_handlers = {}
self.db_connection = connection.MySQLConnection(user=self.config["MYSQL"]["user"],
password=self.config["MYSQL"]["password"],
host=self.config["MYSQL"]["host"],
database=self.config["MYSQL"]["database"])
plugins_to_load = PluginManager.get_valid_plugins(server_type)
for p in plugins_to_load:
config = PluginManager.get_config(p)
plugin_module = importlib.import_module(f"plugins.{p}.{config['main_file']}")
plugin_module.Plugin(self)
def redirect_request(self, method: str, identifier: str):
self.master_server.send(b"r")
if self.master_server.recv(1024) == b"Redirect Acknowledged":
self.master_server.send((method + "$" + identifier).encode("UTF-8"))
data = self.master_server.recv(1024).decode("UTF-8")
data = data.split("$")
return str(data[0]), int(data[1])
def register_handler(self, function, packet_header):
if packet_header in self.packet_handlers:
self.packet_handlers[packet_header].append(function)
else:
self.packet_handlers[packet_header] = [function]
def handle_packet(self, data: bytes, address: pyraknet.messages.Address):
if data[0:8] in self.packet_handlers:
for f in self.packet_handlers[data[0:8]]:
handler = threading.Thread(target=f, args=(data[8:], address, self))
handler.start()

73
core/master_server.py Normal file
View File

@@ -0,0 +1,73 @@
import socket
import threading
class MasterServer:
def __init__(self, address: tuple, max_connections: int = 10, password: bytes = b"1124 WLUS2.0"):
self.address = address
self.max_connections = max_connections
self.password = password
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._s.bind(address)
self._s.listen(max_connections)
self._connections = {}
main_thread = threading.Thread(target=self._run)
main_thread.start()
def _run(self):
print("Starting Master Server")
while True:
client_socket, address = self._s.accept()
password = client_socket.recv(1024)
print(f"Attempted Login From Address [{address}] With Password [{password.decode('UTF-8')}]")
if password == self.password:
client_socket.send(b"Accepted")
server_info = client_socket.recv(1024)
data = server_info.decode("UTF-8").split("$")
if data[2].lower() == 'none':
data[2] = None
print(f"Registered Server With Data: {data}")
self._connections[data[3]] = {"instance_type": data[0], "port": data[1], "zone": data[2],
"address": address}
client_socket.send(b"Registered")
threading.Thread(target=self._client_thread, args=(client_socket, address)).start()
else:
client_socket.send(b"Bad Login")
client_socket.close()
def _client_thread(self, client_socket: socket, address: tuple):
while True:
data = client_socket.recv(1024)
if len(data.decode("UTF-8")) > 0:
if data.decode("UTF-8")[0] == "r":
client_socket.send(b"Redirect Acknowledged")
# Format: <selector_type>$<selector>
redirect_data = client_socket.recv(1024).decode("UTF-8").split("$")
if len(redirect_data) == 2:
print(f"Redirecting by type [{redirect_data[0]}] with selector [{redirect_data[1]}]")
if redirect_data[0] == "instance":
response = b"None"
for conn in self._connections:
if self._connections[conn]["instance_type"] == redirect_data[1]:
response = (str(self._connections[conn]["address"][0]) + "$" +
str(self._connections[conn]["port"])).encode("UTF-8")
break
client_socket.send(response)
elif redirect_data[0] == "name":
if redirect_data[1] in self._connections:
client_socket.send((str(self._connections[redirect_data[1]]["address"][0]) + "$" +
str(self._connections[redirect_data[1]]["port"])).encode("UTF-8"))
else:
client_socket.send(b"None")
elif redirect_data[0] == "zone":
response = b"None"
for conn in self._connections:
if self._connections[conn]["zone"] == redirect_data[1]:
response = (str(self._connections[conn]["address"][0]) + "$" +
str(self._connections[conn]["port"])).encode("UTF-8")
break
client_socket.send(response)
else:
client_socket.send(b"None")

62
core/plugin_manager.py Normal file
View File

@@ -0,0 +1,62 @@
"""
This contains the PluginManager class.
THIS AINT WORKIN. What should be implemented is a recursive function that goes through each
plugin and makes sure they all have their dependencies. STOP BEING LAZY AND FIX THIS WESLEY
NOTE: Plugin ids should be the same name as their folder.
"""
from typing import List, Dict
import os
import json
class PluginManager:
"""
Makes sure that all dependencies are needed for the plugins that will be loaded.
"""
@classmethod
def get_config(cls, plugin_id: str) -> Dict:
with open(f"./plugins/{plugin_id}/plugin.json") as json_file:
config = json.load(json_file)
return config
@classmethod
def get_valid_plugins(cls, plugin_type: str, debug: bool = True) -> List[str]:
"""
This gets all the plugins which have their dependencies fulfilled.
:param plugin_type: The type of plugin the function will look for. (ie. an auth server will only want to load auth types)
:param debug: Determines whether or not the function will output the plugins which aren't valid
:return: Returns a list of all the plugin directories which should be loaded
"""
plugins = {} # Dict of lists of various plugin types
for folder in next(os.walk('./plugins'))[1]:
config = PluginManager.get_config(folder)
if config["type"] in plugins:
plugins[config["type"]].append((f"./plugins/{folder}/plugin.json", config))
else:
plugins[config["type"]] = [(f"./plugins/{folder}/plugin.json", config)]
valid_plugins = []
for t in plugin_type.split("-"):
if t in plugins:
for plugin, config in plugins[t]:
load = [True]
for d in config["dependencies"]:
has_plugin = False
for p_type in plugins:
for p in plugins[p_type]:
if p[1]["id"] == d:
has_plugin = True
break
if has_plugin:
break
if not has_plugin:
load = False
if debug:
print(f"{config['name']} will not be loaded. Missing dependency: {d}")
break
if load[0]:
valid_plugins.append(config["id"])
return valid_plugins

View File

@@ -0,0 +1,9 @@
class Terminal:
"""
This is what is created when the user starts a terminal instance.
Not Implemented - Obviously
"""
def __init__(self):
pass

View File

@@ -1,143 +0,0 @@
'''
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import *
'''
import sqlite3
#This is all for sqlalchemy orm implementation. I'm not 100% sure what Im doing so Im just gonna comment it out until I understand it better
'''
Base = declarative_base()
class Account(Base):
__tablename__ = "Accounts"
account_id = Column('account_id', INTEGER, primary_key=True, autoincrement=True)
username = Column('username', TEXT)
password = Column('password', TEXT)
banned = Column('banned', INTEGER)
is_admin = Column('is_admin', INTEGER)
class CharacterData(Base):
__tablename__ = "CharacterData"
universe_score = Column('universe_score', INTEGER)
level = Column('level', INTEGER)
health = Column('health', INTEGER)
max_health = Column('max_health', INTEGER)
armor = Column('armor', INTEGER)
max_armor = Column('max_armor', INTEGER)
imagination = Column('imagination', INTEGER)
max_imagination = Column('max_imagination', INTEGER)
currency = Column('currency', INTEGER)
player_id = Column('player_id', INTEGER)
backpack_space = Column('backpack_space', INTEGER)
position = Column('position', TEXT)
rotation = Column('rotation', TEXT)
class CharacterStats(Base):
__tablename__ = "CharacterStats"
currency_collected = Column('currency_collected', INTEGER)
bricks_collected = Column('bricks_collected', INTEGER)
smashables_smashed = Column('smashables_smashed', INTEGER)
level = Column('level', INTEGER)
quick_builds_done = Column('quick_builds_done', INTEGER)
enemies_smashed = Column('enemies_smashed', INTEGER)
rockets_used = Column('rockets_used', INTEGER)
pets_tamed = Column('pets_tamed', INTEGER)
imagination_collected = Column('imagination_collected', INTEGER)
health_collected = Column('health_collected', INTEGER)
armor_collected = Column('armor_collected', INTEGER)
distance_traveled = Column('distance_traveled', INTEGER)
times_died = Column('times_died', INTEGER)
damage_taken = Column('damage_taken', INTEGER)
damage_healed = Column('damage_healed', INTEGER)
armor_repaired = Column('armor_repaired', INTEGER)
imagination_restored = Column('imagination_restored', INTEGER)
imagination_used = Column('imagination_used', INTEGER)
distance_driven = Column('distance_driven', INTEGER)
time_airborne_in_car = Column('time_airborne_in_car', INTEGER)
racing_imagination_collected = Column('racing_imagination_collected', INTEGER)
racing_imagination_crates_smashed = Column('racing_imagination_crates_smashed', INTEGER)
race_car_boosts = Column('race_car_boosts', INTEGER)
car_wrecks = Column('car_wrecks', INTEGER)
racing_smashables_smashed = Column('racing_smashables_smashed', INTEGER)
races_finished = Column('races_finished', INTEGER)
races_won = Column('races_won', INTEGER)
player_id = Column('player_id', INTEGER)
class Character(Base):
__tablename__ = "Characters"
player_id = Column('player_id', INTEGER)
name = Column('name', TEXT)
zone = Column('zone', INTEGER)
shirt_color = Column('shirt_color', INTEGER)
shirt_style = Column('shirt_style', INTEGER)
pants_color = Column('pants_color', INTEGER)
hair_color = Column('hair_color', INTEGER)
hair_style = Column('hair_style', INTEGER)
lh = Column('lh', INTEGER)
rh = Column('rh', INTEGER)
eyebrows = Column('eyebrows', INTEGER)
eyes = Column('eyes', INTEGER)
mouth = Column('mouth', INTEGER)
account_id = Column('account_id', INTEGER)
custom_name = Column('custom_name', TEXT)
class CompletedMission(Base):
__tablename__ = "CompletedMissions"
player_id = Column('player_id', INTEGER)
mission_id = Column('mission_id', INTEGER)
class CurrentMission(Base):
__tablename__ = "CurrentMissions"
player_id = Column('player_id', INTEGER)
mission_id = Column('mission_id', INTEGER)
progress = Column('progress', INTEGER)
class Inventory(Base):
__tablename__ = "Inventory"
lot = Column('lot', INTEGER)
slot = Column('slot', INTEGER)
equipped = Column('equipped', INTEGER)
linked = Column('linked', INTEGER)
quantity = Column('quantity', INTEGER)
item_id = Column('item_id', INTEGER)
player_id = Column('player_id', INTEGER)
JSON = Column('JSON', TEXT)
class ZoneObject(Base):
__tablename__ = "ZoneObjects"
zone_id = Column('zone_id', INTEGER)
replica_config = Column('replica_config', TEXT)
class ServerDB():
def __init__(self, database_path : str):
engine = create_engine(f"sqlite:///{database_path}")
metadata = MetaData()
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind=engine)
Session.configure(bind=engine)
self.session = Session()
self.conn = engine.connect()
self.accounts = Table('accounts', metadata, )
'''
class GameDB():
def __init__(self, database_path : str):
self.connection = sqlite3.connect(database_path, check_same_thread=False)
self.connection.isolation_level = None
def row_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
self.connection.row_factory = row_factory

55
db/wlus_account.sql Normal file
View File

@@ -0,0 +1,55 @@
-- MySQL dump 10.13 Distrib 8.0.16, for Win64 (x86_64)
--
-- Host: localhost Database: wlus
-- ------------------------------------------------------
-- Server version 8.0.16
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
SET NAMES utf8 ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `account`
--
DROP TABLE IF EXISTS `account`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `account` (
`account_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) DEFAULT NULL,
`password` varchar(200) DEFAULT NULL,
`banned` tinyint(4) DEFAULT NULL,
`is_admin` tinyint(4) DEFAULT NULL,
`last_login` bigint(20) DEFAULT NULL,
PRIMARY KEY (`account_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `account`
--
LOCK TABLES `account` WRITE;
/*!40000 ALTER TABLE `account` DISABLE KEYS */;
INSERT INTO `account` VALUES (1,'wesley','$2b$12$dUzSrCFmGJt2WuR2zvDzj.9b3BTjdfIJWGt.hiQ1zskmG2Sjfks2i',0,1,NULL);
/*!40000 ALTER TABLE `account` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-03-08 15:39:55

65
db/wlus_character.sql Normal file
View File

@@ -0,0 +1,65 @@
-- MySQL dump 10.13 Distrib 8.0.16, for Win64 (x86_64)
--
-- Host: localhost Database: wlus
-- ------------------------------------------------------
-- Server version 8.0.16
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
SET NAMES utf8 ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `character`
--
DROP TABLE IF EXISTS `character`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `character` (
`character_id` bigint(20) NOT NULL,
`current_name` varchar(45) DEFAULT NULL,
`requested_name` varchar(45) DEFAULT NULL,
`head_color` int(11) DEFAULT NULL,
`head` int(11) DEFAULT NULL,
`chest_color` int(11) DEFAULT NULL,
`chest` int(11) DEFAULT NULL,
`legs` int(11) DEFAULT NULL,
`hair_style` int(11) DEFAULT NULL,
`hair_color` int(11) DEFAULT NULL,
`left_hand` int(11) DEFAULT NULL,
`right_hand` int(11) DEFAULT NULL,
`eyebrow_style` int(11) DEFAULT NULL,
`eye_style` int(11) DEFAULT NULL,
`mouth_style` int(11) DEFAULT NULL,
`account_id` int(11) DEFAULT NULL,
PRIMARY KEY (`character_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `character`
--
LOCK TABLES `character` WRITE;
/*!40000 ALTER TABLE `character` DISABLE KEYS */;
INSERT INTO `character` VALUES (1152921512385983723,'CrustyRedTortilla','Wesley',0,0,0,9,1,0,96,28552208,28104900,33,1,5,1);
/*!40000 ALTER TABLE `character` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-03-08 15:39:55

57
db/wlus_inventory.sql Normal file
View File

@@ -0,0 +1,57 @@
-- MySQL dump 10.13 Distrib 8.0.16, for Win64 (x86_64)
--
-- Host: localhost Database: wlus
-- ------------------------------------------------------
-- Server version 8.0.16
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
SET NAMES utf8 ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `inventory`
--
DROP TABLE IF EXISTS `inventory`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `inventory` (
`object_id` bigint(20) NOT NULL,
`lot` int(11) DEFAULT NULL,
`slot` int(11) DEFAULT NULL,
`equipped` tinyint(4) DEFAULT NULL,
`linked` tinyint(4) DEFAULT NULL,
`quantity` int(11) DEFAULT NULL,
`player_id` bigint(20) DEFAULT NULL,
`proxy_items` varchar(500) DEFAULT NULL,
PRIMARY KEY (`object_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `inventory`
--
LOCK TABLES `inventory` WRITE;
/*!40000 ALTER TABLE `inventory` DISABLE KEYS */;
INSERT INTO `inventory` VALUES (537010342,2519,0,1,1,1,1152921512385983723,NULL),(625381859,4057,1,1,1,1,1152921512385983723,NULL);
/*!40000 ALTER TABLE `inventory` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-03-08 15:39:55

57
db/wlus_session.sql Normal file
View File

@@ -0,0 +1,57 @@
-- MySQL dump 10.13 Distrib 8.0.16, for Win64 (x86_64)
--
-- Host: localhost Database: wlus
-- ------------------------------------------------------
-- Server version 8.0.16
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
SET NAMES utf8 ;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `session`
--
DROP TABLE IF EXISTS `session`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
SET character_set_client = utf8mb4 ;
CREATE TABLE `session` (
`session_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) DEFAULT NULL,
`current_player` bigint(20) DEFAULT NULL,
`current_zone` int(11) DEFAULT NULL,
`current_instance` int(11) DEFAULT NULL,
`user_key` varchar(45) DEFAULT NULL,
`ip_address` varchar(45) DEFAULT NULL,
`login_timestamp` bigint(20) DEFAULT NULL,
PRIMARY KEY (`session_id`)
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `session`
--
LOCK TABLES `session` WRITE;
/*!40000 ALTER TABLE `session` DISABLE KEYS */;
INSERT INTO `session` VALUES (57,'wesley',NULL,NULL,NULL,'1cea7c36-fd8a-4792-a','(\'127.0.0.1\', 57170)',1581811925);
/*!40000 ALTER TABLE `session` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2020-03-08 15:39:55

99
game.py
View File

@@ -1,99 +0,0 @@
import typing
import game_types
import ctypes
import threading
import random
import time
'''
The Game class is the parent of all other objects in the game.
Things should ALWAYS be implmented through either a service or a script
'''
class Game(game_types.BaseObject):
def __init__(self):
super().__init__(None)
self._name = "Game"
self._services = []
self._config : dict = {}
self._event_handlers = {}
self._event_wait_list = {}
self._console_command_handlers = {}
def wait_for_event(self, event_id : str, condition : str):
if(event_id not in self._event_wait_list):
self._event_wait_list[event_id] = {"condition":condition, "state":False}
while self._event_wait_list[event_id]["state"] == False:
time.sleep(.0001)
def start(self):
for service in self._services:
service.initialize()
self.trigger_event("GameStarted")
console_thread = threading.Thread(target =self._console_loop)
console_thread.start()
def register_console_command(self, command, handler):
self._console_command_handlers[command.upper()] = handler
def _console_loop(self):
while True:
input_str = input()
args = input_str.rstrip().split(" ")
if(args[0].upper() in self._console_command_handlers):
self._console_command_handlers[args[0].upper()](args[1:])
else:
print("Unknown Console Command")
def generate_object_id(self):
#TODO: You need to figure out the correct way to generate object ids you dumb dumb
id = random.randint(100000000000000000, 999999999999999999)
return id
def register_service(self, service):
self._services.append(service)
self.trigger_event("ServiceRegistered", args=(service,), debug=False)
def register_event_handler(self, event_id : str, threaded : bool = True):
def register_handler(handler):
self._event_handlers[handler] = [event_id, threaded]
return register_handler
def trigger_event(self, event_id, args : typing.Tuple =(), debug : bool = False):
if(event_id in self._event_wait_list):
if(eval(self._event_wait_list[event_id]["condition"]) == True):
self._event_wait_list[event_id]["state"] = True
handler_activated = False
for handler in self._event_handlers:
if(self._event_handlers[handler][0] == event_id):
if(self._event_handlers[handler][1] == True):
handler_thread = threading.Thread(target=handler, args=args)
handler_thread.start()
else:
handler(*args)
handler_activated = True
if(handler_activated != True and debug):
print("{} Had No Handler!".format(event_id))
def get_service(self, service_name : str):
for service in self._services:
if(service.get_name() == service_name):
return service
return None
def set_config(self, key : str, value : typing.Any):
self._config[key.upper()] = value
def remove_config(self, key : str):
del self._config[key.upper()]
def get_pyobject(self, id):
return ctypes.cast(id, ctypes.py_object).value
def get_config(self, key : str):
if(key.upper() in self._config):
return self._config[key.upper()]
else:
return None

View File

@@ -1,154 +0,0 @@
from enum import *
import game_types
class PacketHeaderEnum(Enum):
HANDSHAKE = b'S\x00\x00\x00\x00\x00\x00\x00'
DISCONNECT_NOTIFY = b"S\x00\x00\x01\x00\x00\x00\x00"
CLIENT_LOGIN_INFO = b'S\x01\x00\x00\x00\x00\x00\x00'
LOGIN_RESPONSE = b'S\x05\x00\x00\x00\x00\x00\x00'
CLIENT_USER_SESSION_INFO = b"S\x04\x00\x01\x00\x00\x00\x00"
CLIENT_MINIFIGURE_LIST_REQUEST = b"S\x04\x00\x02\x00\x00\x00\x00"
MINIFIGURE_LIST = b"S\x05\x00\x06\x00\x00\x00\x00"
CLIENT_MINIFIGURE_CREATE_REQUEST = b"S\x04\x00\x03\x00\x00\x00\x00"
MINIFIGURE_CREATION_RESPONSE = b"S\x05\x00\x08\x00\x00\x00\x00"
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'
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'
SERVER_GAME_MESSAGE = b'S\x05\x00\x0c\x00\x00\x00\x00'
CLIENT_POSITION_UPDATES = b'S\x04\x00\x16\x00\x00\x00\x00'
CLIENT_CHAT_MESSAGE = b'S\x04\x00\x0e\x00\x00\x00\x00'
CLIENT_WHITELIST_REQUEST = b'S\x04\x00\x19\x00\x00\x00\x00'
CHAT_MODERATION_RESPONSE = b'S\x05\x00\x3b\x00\x00\x00\x00'
class ReplicaTypes(IntEnum):
CONSTRUCTION = 0
SERIALIZATION = 1
class LoginResponseEnum(IntEnum):
SUCCESS = 0x01
BANNED = 0x02
INVALID_PERM = 0x03
INVALID_LOGIN_INFO = 0x06
ACCOUNT_LOCKED = 0x07
class DisconnectionReasonEnum(IntEnum):
UNKNOWN_ERROR = 0x00
DUPLICATE_LOGIN = 0x04
SERVER_SHUTDOWN = 0x05
SERVER_CANNOT_LOAD_MAP = 0x06
INVALID_SESSION_KEY = 0x07
CHARACTER_NOT_FOUND = 0x09
CHARACTER_CORRUPTION = 0x0a
KICKED = 0x0b
class ObjectTypes(IntEnum):
UNDEFINED = 0
SPAWNED = 1
LOCAL = 2
GLOBAL = 3
STATIC = 4
class ItemLOTs(IntEnum):
SHIRT_BRIGHT_RED = 4049
SHIRT_BRIGHT_BLUE = 4083
SHIRT_BRIGHT_YELLOW = 4117
SHIRT_DARK_GREEN = 4151
SHIRT_BRIGHT_ORANGE = 4185
SHIRT_BLACK = 4219
SHIRT_DARK_STONE_GRAY = 4253
SHIRT_MEDIUM_STONE_GRAY = 4287
SHIRT_REDDISH_BROWN = 4321
SHIRT_WHITE = 4355
SHIRT_MEDIUM_BLUE = 4389
SHIRT_DARK_RED = 4423
SHIRT_EARTH_BLUE = 4457
SHIRT_EARTH_GREEN = 4491
SHIRT_BRICK_YELLOW = 4525
SHIRT_SAND_BLUE = 4559
SHIRT_SAND_GREEN = 4593
PANTS_BRIGHT_RED = 2508
PANTS_BRIGHT_ORANGE = 2509
PANTS_BRICK_YELLOW = 2511
PANTS_MEDIUM_BLUE = 2513
PANTS_SAND_GREEN = 2514
PANTS_DARK_GREEN = 2515
PANTS_EARTH_GREEN = 2516
PANTS_EARTH_BLUE = 2517
PANTS_BRIGHT_BLUE = 2519
PANTS_SAND_BLUE = 2520
PANTS_DARK_STONE_GRAY = 2521
PANTS_MEDIUM_STONE_GRAY = 2522
PANTS_WHITE = 2523
PANTS_BLACK = 2524
PANTS_REDDISH_BROWN = 2526
PANTS_DARK_RED = 2527
class DeathType(Enum):
DEATH_WATER = "death_water"
SHARK = "shark-death"
BIG_SHARK = "big-shark-death"
ELECTRO_SHOCK = "electro-shock-death"
class GameMessages(IntEnum):
SERVER_DONE_LOADING_OBJECTS = 1642
PLAYER_READY = 509
READY_FOR_UPDATES = 888
PLAY_FX_EFFECT = 154
STOP_FX_EFFECT = 155
PARSE_CHAT_MSG = 850
SET_JETPACK_MODE = 561
ADD_SKILL = 127
REMOVE_SKILL = 128
PLAYER_LOADED = 505
ADD_ITEM_TO_INVENTORY_CLIENT_SYNC = 227
EQUIP_INVENTORY = 231
UNEQUIP_INVENTORY = 233
RESYNC_EQUIPMENT = 1238
START_SKILL = 119
ECHO_START_SKILL = 118
ECHO_SYNC_SKILL = 1144
SYNC_SKILL = 1145
DIE = 37
REQUEST_DIE = 38
PLAYER_REQUEST_SMASH = 1202
RESSURECT_REQUEST = 159
RESSURECT = 160
class ItemTypes(IntEnum):
INVALID = 0
BRICK = 1
HAT = 2
HAIR = 3
NECK = 4
LEFT_HAND = 5
RIGHT_HAND = 6
LEGS = 7
LEFT_TRINKET = 8
RIGHT_TRINKET = 9
BEHAVIOR = 10
PROPERTY = 11
MODEL = 12
COLLECTABLE = 13
CONSUMABLE = 14
CHEST = 15
EGG = 16
PET_FOOD = 17
QUEST_OBJECT = 18
PET_INVENTORY_ITEM = 19
t20_PACKAGE = 20
LOOT_MODEL = 21
VEHICLE = 22
class MinifigureCreationResponseEnum(IntEnum):
SUCCESS = 0x00
ID_NOT_WORKING = 0x01
NAME_NOT_ALLOWED = 0x02
PREDEFINED_NAME_IN_USE = 0x03
NAME_IN_USE = 0x04

View File

@@ -1,42 +0,0 @@
import math
import game_types
'''import gem, supposedly this library is good for 3D math but I have no idea how to work it'''
def quat_to_euler(quaternion : game_types.Vector4) -> game_types.Vector3:
x = quaternion.X
y = quaternion.Y
z = quaternion.Z
w = quaternion.W
y_sqr = y * y
t0 = +2.0 * (w * x + y * z)
t1 = +1.0 - 2.0 * (x * x + y_sqr)
X = math.degrees(math.atan2(t0, t1))
t2 = +2.0 * (w * y - z * x)
t2 = +1.0 if t2 > +1.0 else t2
t2 = -1.0 if t2 < -1.0 else t2
Y = math.degrees(math.asin(t2))
t3 = +2.0 * (w * z + x * y)
t4 = +1.0 - 2.0 * (y_sqr + z * z)
Z = math.degrees(math.atan2(t3, t4))
return game_types.Vector3(float(X), float(Y), float(Z))
#TODO: Fix
def front_vector(rotation : game_types.Vector4, position : game_types.Vector3, magnitude : float = 1.0) -> game_types.Vector3:
direction = game_types.Vector3(2 * (rotation.X * rotation.Z - rotation.W * rotation.Y),
2 * (rotation.Y * rotation.Z - rotation.W * rotation.X),
1 - 2 * (rotation.X * rotation.X + rotation.Y * rotation.Y))
return (position + direction * magnitude)

View File

@@ -1,268 +0,0 @@
import services
from pyraknet.bitstream import *
import game_enums
import game_types
import copy
class GameMessageService(services.GameService):
def __init__(self, parent):
super().__init__(parent)
self._name = "Game Message"
global game
game = self.get_parent()
def initialize(self):
self.world_server = game.get_service("World Server").server
super().initialize()
def init_game_msg(self, stream: WriteStream, object_id: int, message_id: int):
stream.write(game_enums.PacketHeaderEnum.SERVER_GAME_MESSAGE.value)
stream.write(c_longlong(object_id))
stream.write(c_ushort(message_id))
def send_game_msg(self, object_id, msg_id, recipients: list):
msg = WriteStream()
msg.write(game_enums.PacketHeaderEnum.SERVER_GAME_MESSAGE.value)
msg.write(c_longlong(object_id))
msg.write(c_ushort(msg_id))
self.world_server.send(msg, recipients)
def play_fx_effect(self, object_id : int, recipients : list, effect_id : int, effect_type : str, scale : float, name : str, priority : float = 1.0, secondary : int = -1, serialize : bool = True):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.PLAY_FX_EFFECT.value)
msg.write(c_bit(effect_id != -1))
if(effect_id != -1):
msg.write(c_long(effect_id))
msg.write(effect_type, length_type=c_ulong)
msg.write(c_bit(scale != 1.0))
if(scale != 1.0):
msg.write(c_float(scale))
msg.write(game_types.String(name, length_type=c_ulong))
msg.write(c_bit(priority != 1.0))
if(priority != 1.0):
msg.write(c_float(priority))
msg.write(c_bit(secondary > -1))
if(secondary > -1):
msg.write(c_longlong(secondary))
msg.write(c_bit(serialize))
self.world_server.send(msg, recipients)
def stop_fx_effect(self, object_id : int, recipients : list, kill_immediately : bool, name : str):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.STOP_FX_EFFECT.value)
msg.write(c_bit(kill_immediately))
msg.write(game_types.String(name, length_type=c_ulong))
self.world_server.send(msg, recipients)
def add_item_to_inventory_client_sync(self, object_id : int, recipients : list, lot : int, item_id : int, slot_id : int, bound: bool = False, bound_on_equip : bool = False, bound_on_pickup : bool = False, loot_type_source : int = 0, extra_info : str = "", sub_key : int = 0, inventory_type : int = 0, item_count : int = 1, items_total : int = 0, flying_loot_pos : game_types.Vector3 = game_types.Vector3(), show_flying_loot : bool = True):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.ADD_ITEM_TO_INVENTORY_CLIENT_SYNC.value)
msg.write(c_bit(bound))
msg.write(c_bit(bound_on_equip))
msg.write(c_bit(bound_on_pickup))
msg.write(c_bit(loot_type_source != 0))
if(loot_type_source != 0):
msg.write(c_int(loot_type_source))
msg.write(extra_info, length_type=c_ulong)
msg.write(c_ulong(lot))
msg.write(c_bit(sub_key != 0))
if(sub_key != 0):
msg.write(c_longlong(sub_key))
msg.write(c_bit(inventory_type != 0))
if(inventory_type != 0):
msg.write(c_int(inventory_type))
msg.write(c_bit(item_count != 1))
if(item_count != 1):
msg.write(c_ulong(item_count))
msg.write(c_bit(items_total != 0))
if(items_total != 0):
msg.write(c_ulong(items_total))
msg.write(c_longlong(item_id))
msg.write(c_float(flying_loot_pos.X))
msg.write(c_float(flying_loot_pos.Y))
msg.write(c_float(flying_loot_pos.Z))
msg.write(c_bit(show_flying_loot))
msg.write(c_int(slot_id))
self.world_server.send(msg, recipients)
def remove_skill(self, object_id : int, recipients : list, skill_id : int, from_skill_set : bool = False):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.REMOVE_SKILL.value)
msg.write(c_bit(from_skill_set))
msg.write(c_int(skill_id))
self.world_server.send(msg, recipients)
def ressurect(self, object_id : int, recipients : list, rez_immediately : bool = False):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.RESSURECT.value)
msg.write(c_bit(rez_immediately))
self.world_server.send(msg, recipients)
def die(self, object_id : int, recipients : list, killer_id : int = 0, client_death : bool = True, spawn_loot : bool = False, death_type : str = game_enums.DeathType.ELECTRO_SHOCK.value, dir_rel_xz : float = 0, dir_rel_y : float = 0, dir_rel_force = 0, loot_owner_id : int = 0):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.DIE.value)
msg.write(c_bit(client_death))
msg.write(c_bit(spawn_loot))
msg.write(death_type, length_type=c_ulong)
msg.write(c_float(dir_rel_xz))
msg.write(c_float(dir_rel_y))
msg.write(c_float(dir_rel_force))
msg.write(c_bit(False))
if(killer_id > 0):
msg.write(c_longlong(killer_id))
else:
msg.write(c_longlong(object_id))
msg.write(c_bit(loot_owner_id != 0 and spawn_loot))
if(loot_owner_id != 0 and spawn_loot):
msg.write(c_longlong(loot_owner_id))
self.world_server.send(msg, recipients)
def echo_start_skill(self, object_id : int, recipients : list, skill_id : int, bit_stream:str, optional_originator : int, used_mouse : bool = False, caster_latency : float = 0.0, cast_type : int = 0, last_clicked_pos : game_types.Vector3 = game_types.Vector3(), optional_target_id : int = 0, originator_rot : game_types.Vector4 = game_types.Vector4(), ui_skill_handle : int = 0):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.ECHO_START_SKILL.value)
msg.write(c_bit(used_mouse))
msg.write(c_bit(caster_latency != 0.0))
if(caster_latency != 0.0):
msg.write(c_float(caster_latency))
msg.write(c_bit(cast_type != 0))
if(cast_type != 0):
msg.write(c_int(cast_type))
msg.write(c_bit(last_clicked_pos != game_types.Vector3()))
if(last_clicked_pos != game_types.Vector3()):
msg.write(c_float(last_clicked_pos.X))
msg.write(c_float(last_clicked_pos.Y))
msg.write(c_float(last_clicked_pos.Z))
msg.write(c_longlong(optional_originator))
msg.write(c_bit(optional_target_id != 0))
if(optional_target_id != 0):
msg.write(c_longlong(optional_target_id))
msg.write(c_bit(originator_rot != game_types.Vector4()))
if(originator_rot != game_types.Vector4()):
msg.write(c_float(originator_rot.X))
msg.write(c_float(originator_rot.Y))
msg.write(c_float(originator_rot.Z))
msg.write(c_float(originator_rot.W))
msg.write(game_types.String(bit_stream, length_type=c_ulong))
msg.write(c_ulong(skill_id))
msg.write(c_bit(ui_skill_handle != 0))
if(ui_skill_handle != 0):
msg.write(c_ulong(0))
self.world_server.send(msg, recipients)
def add_skill(self, object_id : int, recipients : list, skill_id : int, ai_combat_weight : int = 0, from_skill_set : bool = False, cast_type : int = 0, time_secs : float = -1.0, times_can_cast : int = -1, slot_id : int = -1, temporary : bool = True):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.ADD_SKILL.value)
msg.write(c_bit(ai_combat_weight != 0 and ai_combat_weight is not None))
if(ai_combat_weight != 0 and ai_combat_weight is not None):
msg.write(c_int(ai_combat_weight))
msg.write(c_bit(from_skill_set))
msg.write(c_bit(cast_type != 0))
if(cast_type != 0):
msg.write(c_int(cast_type))
msg.write(c_bit(time_secs > -1.0))
if(time_secs > -1.0):
msg.write(c_float(time_secs))
msg.write(c_bit(times_can_cast > -1))
if(times_can_cast > -1):
msg.write(c_int(times_can_cast))
msg.write(c_ulong(skill_id))
msg.write(c_bit(slot_id > -1))
if(slot_id > -1):
msg.write(c_int(slot_id))
msg.write(c_bit(temporary))
self.world_server.send(msg, recipients)
def set_jetpack_mode(self, object_id : int, recipients : list, bypass_checks : bool = True, hover : bool = False, use : bool = False, effect_id : int = -1, air_speed : int = 10, max_air_speed : int = 15, vert_vel : int = 1, warning_effect_id : int = -1):
msg = WriteStream()
self.init_game_msg(msg, object_id, game_enums.GameMessages.SET_JETPACK_MODE.value)
msg.write(c_bit(bypass_checks))
msg.write(c_bit(hover))
msg.write(c_bit(use))
msg.write(c_bit(effect_id != -1))
if(effect_id != -1):
msg.write(c_int(effect_id))
msg.write(c_bit(air_speed != 10))
if(air_speed != 10):
msg.write(c_float(air_speed))
msg.write(c_bit(max_air_speed != 15))
if(max_air_speed != 15):
msg.write(c_float(max_air_speed))
msg.write(c_bit(vert_vel != 1))
if(vert_vel != 1):
msg.write(c_float(vert_vel))
msg.write(c_bit(warning_effect_id != -1))
if(warning_effect_id != -1):
msg.write(c_int(0))
self.world_server.send(msg, recipients)

View File

@@ -1,87 +0,0 @@
import game_types
import components
import game_enums
'''
GameObjects are objects placed inside scenes
'''
class GameObject(game_types.BaseObject):
def __init__(self, parent, zone, object_id : int = None, name : str = "GameObject"):
super().__init__(parent)
self._name = name
self._components = []
self.zone = zone
global game
game = zone.get_parent().get_parent().get_parent()
if(object_id is None):
raise Exception("Need Object ID!")
self._object_id = object_id
def add_component(self, component):
self._components.append(component)
def get_component(self, component):
for object_component in self._components:
if(isinstance(object_component, component)):
return object_component
return None
def get_object_id(self):
return self._object_id
def update(self):
self.zone.update(self)
def get_name(self):
return self._name
def has_component(self, component):
for object_component in self._components:
if(isinstance(object_component, component)):
return True
return False
class ReplicaObject(GameObject):
def __init__(self, parent, zone, config : dict):
object_id = None
name = ""
if("object_id" in config):
object_id = config["object_id"]
else:
object_id = zone.get_parent().get_parent().generate_object_id()
if ("name" in config):
name = config["name"]
super().__init__(parent, zone, object_id, name)
self.object_type = game_enums.ObjectTypes.UNDEFINED.value
self.lot = 0
self.spawner_id = None
self.spawner_node_id = None
self.world_state = None
self.gm_level = None
self.json = {}
if("object_type" in config):
self.object_type = int(config["object_type"])
if("json" in config):
self.json = config["json"]
if("gm_level" in config):
self.gm_level = config["gm_level"]
if("world_state" in config):
self.world_state = config["world_state"]
if("lot" in config):
self.lot = config["lot"]
if(self.lot == 1):
self.player_sync = True
if("spawner_id" in config):
self.spawner_id = config["spawner_id"]
if("spawner_node_id" in config):
self.spawner_node_id = config["spawner_node_id"]
transform = components.Transform(self)
self.add_component(transform)
def on_destruction(self):
for component in self._components:
if (hasattr(component, "player_sync_thread")):
if(self.lot == 1):
self.player_sync = False
component.player_sync_thread.stop()

View File

@@ -1,61 +0,0 @@
import sys
sys.path.append("..")
import scripts
import json
import game_types
import random
class Main(scripts.Script):
def __init__(self, parent):
super().__init__(parent, "Console Commands")
global game
game = self.get_parent()
def run(self):
game.register_console_command("Register", self.register_handler)
game.register_console_command("ImportLUZ", self.import_handler)
def import_handler(self, args):
if(len(args) == 1):
zone = int(args[0])
file_path = input("JSON Directory: ")
if(file_path == ''):
return
lvl_files = []
luz = open(file_path, "r")
luz_json = json.loads(luz.read())
folder = '\\'.join(file_path.split('\\')[0:-1])
for scene in luz_json["scenes"]:
lvl_files.append({"scene_id":scene["id"], "path":folder+"/"+scene["filename"]+".json"})
for lvl in lvl_files:
file = open(lvl["path"], "r")
json_obj = json.loads(file.read())
database = game.get_service("Database")
server_db = database.server_db
c = server_db.connection.cursor()
for chunk in json_obj["chunks"]:
if(chunk["_type"] == 2001):
object_id = random.randint(100000000000000000, 999999999999900000)
for game_object in chunk["objects"]:
if("spawntemplate" in game_object["settings"]):
object_id += 1
config = {'lot':game_object["settings"]["spawntemplate"], 'spawner_id':game_object["id"],
'position': str(game_types.Vector3(game_object['pos']['pos']['x'], game_object['pos']['pos']['y'], game_object['pos']['pos']['z'])),
'rotation': str(game_types.Vector4(game_object['pos']['rot']['x'], game_object['pos']['rot']['y'], game_object['pos']['rot']['z'], game_object['pos']['rot']['w'])),
'scale':game_object["scale"], 'spawner_node_id':0, 'object_id':object_id, 'scene':lvl["scene_id"], 'object_type':1}
c.execute("INSERT INTO ZoneObjects (zone_id, replica_config) VALUES (?, ?)", (zone, json.dumps(config)))
print("Imported Object {} To DB".format(config["object_id"]))
def register_handler(self, args):
username = args[0]
password = args[1]
auth_service = game.get_service("Auth Server")
auth_service.register_account(username, password)

View File

@@ -1,29 +0,0 @@
import sys
sys.path.append("..")
import scripts
import time
'''Big thanks to Tracer (the other Wesley), for providing me with the function from JALUS that does this thing'''
class Main(scripts.Script):
def __init__(self, parent):
super().__init__(parent, "Jonny's Dumb Effect")
global game
game = self.get_parent()
def run(self):
game.wait_for_event("ServiceInitialized", '''args[0].get_name() == "World"''')
game_message_service = game.get_service("Game Message")
while True:
if (game.get_config("jonnys_dumb_effect") is not None and game.get_config("jonnys_dumb_effect") == True):
zones = game.get_service("World").get_zones()
for zone in zones:
players = zone.get_players()
for player_id in players:
game_message_service.stop_fx_effect(player_id, zone.get_connections(), False, "wisp_hands")
game_message_service.play_fx_effect(player_id, zone.get_connections(), 1573, "on-anim", 1.0, "wisp_hands")
game_message_service.stop_fx_effect(player_id, zone.get_connections(), False, "wisp_hands_left")
game_message_service.play_fx_effect(player_id, zone.get_connections(), 1579, "on-anim", 1.0, "wisp_hands_left")
time.sleep(.5)

View File

@@ -1,90 +0,0 @@
import sys
sys.path.append("..")
import scripts
import game_types
from pyraknet.bitstream import ReadStream
import random
#Zones should be in order of loading priority?
zone_checksums = {1200: 0xda1e6b30,
1000: 0x20b8087c,
1001: 0x26680a3c,
1100: 0x49525511,
#1101: 0x538214e2,
1102: 0x0fd403da,
1150: 0x0fd403da,
1151: 0x0a890303,
1201: 0x476e1330,
#1203: 0x10fc0502,
1204: 0x07d40258,
1250: 0x058d0191,
1251: 0x094f045d,
1300: 0x12eac290,
1302: 0x0b7702ef,
#9999: 0x13600646 #Frostburgh
#1303: 0x152e078a,
1350: 0x04b6015c,
1400: 0x8519760d,
1402: 0x02f50187,
#1403: 0x81850f4e,
1450: 0x03f00126,
1600: 0x07c202ee,
1601: 0x02320106,
1602: 0x0793037f,
1603: 0x043b01ad,
1604: 0x181507dd,
1700: 0x02040138,
1800: 0x4b17a399,
1900: 0x9e4af43c,
2000: 0x4d692c74,
2001: 0x09eb00ef}
class Main(scripts.Script):
def __init__(self, parent):
super().__init__(parent, "on_boot")
global game
game = self.get_parent()
def run(self):
@game.register_event_handler("GameStarted", threaded=True)
def register_zones():
world_service = game.get_service("World")
cdclient = game.get_service("Database").cdclient_db
c = cdclient.connection.cursor()
for zone in zone_checksums:
json = {}
c.execute("SELECT * FROM ZoneTable WHERE zoneID = ?", (zone,))
zone_data = c.fetchone()
luz_path = f"resources/{zone_data['zoneName']}"
name = zone_data["DisplayDescription"]
luz_file = open(luz_path, "rb")
stream = ReadStream(luz_file.read())
luz = game_types.LUZ().deserialize(stream)
luz_file.close()
spawn_loc = luz.config["spawnpoint_pos"]
spawn_rot = luz.config["spawnpoint_rot"]
folder = ""
path_folders = luz_path.split("/")
path_folders = path_folders[:-1]
for path_folder in path_folders:
folder += path_folder + "/"
json["zone_path"] = folder
json["scenes"] = luz.config["scenes"]
world_service.register_zone(zone_id=zone, load_id=zone, checksum=zone_checksums[zone], spawn_loc=spawn_loc, spawn_rot=spawn_rot, name=name, json = json)
zone = world_service.get_zone_by_id(zone)
start_id = random.randint(100000000000000000, 999999999999900000)
for scene in luz.config["scenes"]:
folders = "/".join(zone_data['zoneName'].split('/')[:-1])
scene_path = f"resources/{folders}/{scene['filename']}"
lvl_file = open(scene_path, "rb")
lvl_stream = ReadStream(lvl_file.read())
lvl = game_types.LVL().deserialize(lvl_stream)
for object_to_spawn in lvl.config["objects"]:
object_to_spawn["object_id"] = start_id
zone.create_object(zone, object_to_spawn)
start_id+=1
print(f"Registered {name}!")
game.trigger_event("BootUp_WorldsRegistered")

View File

@@ -1,434 +0,0 @@
import threading
import typing
from pyraknet.bitstream import *
import pyraknet.replicamanager
from pyraknet.messages import *
from xml.etree import ElementTree
import game_enums
class BaseObject():
def __init__(self, parent):
self._name = "Name"
self._parent = parent
self._children = []
self._scripts = {}
if(isinstance(self._parent, BaseObject)):
self._parent._children.append(self)
def get_name(self):
return self._name
def get_py_id(self):
return id(self)
def set_name(self, name : str):
self._name = name
def add_script(self, script):
script_thread = GameThread(target=script.run)
script_thread.start()
self._scripts[script.get_name()] = script_thread
def remove_script(self, script_name : str):
thread_list = threading.enumerate()
for thread in thread_list:
if(thread == self._scripts[script_name]):
thread.stop()
del self._scripts[script_name]
return
def get_parent(self):
return self._parent
def get_children(self):
return self._children
class GameThread(threading.Thread):
def stop(self):
self._tstate_lock = None
self._stop()
class String(Serializable):
def __init__(self, data='', allocated_length=None, length_type=None):
self.data = data
self.allocated_length = allocated_length
self.length_type = length_type
def serialize(self, stream):
stream.write(self.data if isinstance(self.data, bytes) else bytes(self.data, 'latin1'),
allocated_length=self.allocated_length, length_type=self.length_type)
def deserialize(self, stream):
return stream.read(bytes, allocated_length=self.allocated_length, length_type=self.length_type).decode('latin1')
class LwoObjectID(Serializable):
def __init__(self, value : int, type : int = 0):
self._val = value
self._type = type
def serialize(self, stream: "WriteStream"):
if(self._type == game_enums.ObjectTypes.SPAWNED.value):
stream.write(c_longlong(self._val + (1>>57)))
else:
stream.write(c_longlong(self._val))
def deserialize(cls, stream: "ReadStream"):
return stream.read(c_longlong)
class Vector3(Serializable):
def __init__(self, X : float = 0.0, Y : float = 0.0, Z : float = 0.0, str_val:str = None):
self.X : float = X
self.Y : float = Y
self.Z : float = Z
if(str_val is not None):
vector_list = str_val.split(",")
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)
def __sub__(self, other):
return Vector3(self.X - other.X, self.Y - other.Y, self.Z - other.Z)
def set(self, X : float, Y : float, Z : float):
self.X = X
self.Y = Y
self.Z = Z
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
def serialize(self, stream):
stream.write(c_float(self.X))
stream.write(c_float(self.Y))
stream.write(c_float(self.Z))
def deserialize(self, stream):
return Vector3(stream.read(c_float), stream.read(c_float), stream.read(c_float))
def __mul__(self, other):
if(isinstance(other, Vector3)):
return Vector3(self.X * other.X, self.Y * other.Y, self.Z * other.Z)
elif(isinstance(other, float)):
return Vector3(self.X * other, self.Y * other, self.Z * other)
elif(isinstance(other, int)):
return Vector3(float(self.X * other), float(self.Y * other), float(self.Z * other))
else:
raise Exception(f"Vector3 cannot be multiplied with type {other.__class__}")
class LDF(Serializable):
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 __str__(self):
return str(self._keys)
def serialize(self, stream):
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)
def deserialize(self, stream):
return "Not Implemented"
class Vector4(Serializable):
def __init__(self, X : float = 0.0, Y : float = 0.0, Z : float = 0.0, W : float = 0.0, str_val: str = None):
self.X : float = X
self.Y : float = Y
self.Z : float = Z
self.W : float = W
if(str_val is not None):
vector_list = str_val.split(",")
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)
def __sub__(self, other):
return Vector4(self.X - other.X, self.Y - other.Y, self.Z - other.Z, self.W - other.W)
def set(self, X : float, Y : float, Z : float, W : float):
self.X = X
self.Y = Y
self.Z = Z
self.W = W
def __str__(self):
return "{},{},{},{}".format(self.X, self.Y, self.Z, self.W)
def __eq__(self, other):
if(self.X == other.X and self.Y == other.Y and self.Z == other.Z, self.W == other.W):
return True
else:
return False
def __mul__(self, other):
if(isinstance(other, Vector4)):
return Vector4(self.X * other.X, self.Y * other.Y, self.Z * other.Z, self.W * other.W)
elif(isinstance(other, float)):
return Vector4(self.X * other, self.Y * other, self.Z * other, self.W * other)
elif(isinstance(other, int)):
return Vector4(float(self.X * other), float(self.Y * other), float(self.Z * other), float(self.W * other))
else:
raise Exception(f"Vector4 cannot be multiplied with type {other.__class__}")
def serialize(self, stream):
stream.write(c_float(self.X))
stream.write(c_float(self.Y))
stream.write(c_float(self.Z))
stream.write(c_float(self.W))
def deserialize(self, stream):
return Vector4(stream.read(c_float), stream.read(c_float), stream.read(c_float), stream.read(c_float))
class LVL(Serializable):
def __init__(self, config : dict = None):
self.config = config
def serialize(self, stream):
raise NotImplementedError
def deserialize(self, stream):
#Most of this is shamelessly ripped off from PyLUS because I'm very lazy (Sorry Knight d:)
config = {}
config["objects"] = []
header = stream.read(bytes, length=4)
stream._read_offset = 0
if header == b'CHNK':
while not stream.all_read():
assert stream._read_offset // 8 % 16 == 0
start_pos = stream._read_offset // 8
assert stream.read(bytes, length=4) == b'CHNK'
chunk_type = stream.read(c_uint)
assert stream.read(c_ushort) == 1
assert stream.read(c_ushort) in (1, 2)
chunk_len = stream.read(c_uint)
data_pos = stream.read(c_uint)
stream._read_offset = data_pos * 8
assert stream._read_offset // 8 % 16 == 0
if chunk_type == 1000:
pass
elif chunk_type == 2000:
pass
elif chunk_type == 2001:
for _ in range(stream.read(c_uint)):
objid = stream.read(c_int64)
lot = stream.read(c_uint)
unknown1 = stream.read(c_uint)
unknown2 = stream.read(c_uint)
position = Vector3().deserialize(stream)
rot_w = stream.read(c_float)
rot_x = stream.read(c_float)
rot_y = stream.read(c_float)
rot_z = stream.read(c_float)
rotation = Vector4(rot_x, rot_y, rot_z, rot_w)
scale = stream.read(c_float)
object_config = self._read_ldf(stream.read(str, length_type=c_uint))
assert stream.read(c_uint) == 0
if('renderDisabled' in object_config):
continue
if lot == 176:
lot = int(object_config['spawntemplate'])
config["objects"].append({"lot":lot, "spawner_id":objid, "position":position, "rotation": rotation, "scale":scale, "object_type":game_enums.ObjectTypes.SPAWNED.value, "spawner_config":object_config})
elif chunk_type == 2002:
pass
stream._read_offset = (start_pos + chunk_len) * 8
return LVL(config)
def _read_ldf(self, ldf):
ldf_dict = {}
key_sets = ldf.split("\n")
for x in key_sets:
key = x.split("=")[0]
value = x.split(":")[1]
ldf_dict[key] = value
return ldf_dict
class LUZ(Serializable):
def __init__(self, config : dict = None):
self.config = config
def serialize(self, stream):
raise NotImplementedError
def deserialize(self, stream):
config = {}
config["version"] = stream.read(c_ulong)
if(config["version"] >= 0x24):
config["ulong_01"] = stream.read(c_ulong)
config["world_id"] = stream.read(c_ulong)
if(config["version"] >= 0x26):
config["spawnpoint_pos"] = Vector3().deserialize(stream)
config["spawnpoint_rot"] = Vector4().deserialize(stream)
if(config["version"] < 0x25):
scene_count = stream.read(c_uint8)
else:
scene_count = stream.read(c_ulong)
config["scenes"] = []
for _ in range(scene_count):
scene = {}
scene["filename"] = String(length_type=c_uint8).deserialize(stream)
scene["id"] = stream.read(c_uint8)
scene["scene_3bytes_01"] = stream.read(bytes, length=3)
scene["is_audio_scene"] = stream.read(c_uint8)
scene["scene_3bytes_02"] = stream.read(bytes, length=3)
scene["name"] = String(length_type=c_uint8).deserialize(stream)
scene["scene_3bytes_03"] = stream.read(bytes, length=3)
config["scenes"].append(scene)
config["u8_01"] = stream.read(c_uint8)
config["terrain_map_filename"] = String(length_type=c_uint8).deserialize(stream)
config["terrain_map_name"] = String(length_type=c_uint8).deserialize(stream)
config["terrain_map_desc"] = String(length_type=c_uint8).deserialize(stream)
if(config["version"] >= 0x20):
scene_transition_count = stream.read(c_ulong)
config["scene_transitions"] = []
for _ in range(scene_transition_count):
scene_transition = {}
if(config["version"] < 0x25):
scene_transition["name"] = (String(length_type=c_uint8).deserialize(stream))
if(config["version"] <= 0x21 or config["version"] >= 0x27):
loop_times = 2
else:
loop_times = 5
scene_transition["scene_transition_types"] = []
for _ in range(loop_times):
scene_transition_type = {}
scene_transition_type["scene_id"] = stream.read(c_ulonglong)
scene_transition_type["transition_point"] = Vector3().deserialize(stream)
scene_transition["scene_transition_types"].append(scene_transition_type)
config["scene_transitions"].append(scene_transition)
config["length_of_rest_of_file"] = stream.read(c_ulong)
config["ulong_02"] = stream.read(c_ulong)
path_count = stream.read(c_ulong)
#TODO: Fix Paths
# config["paths"] = []
# for _ in range(path_count):
# path = {}
# path["path_version"] = stream.read(c_ulong)
# path["path_name"] = String(length_type=c_uint8).deserialize(stream)
# path["path_type"] = stream.read(c_ulong)
# path["ulong_01"] = stream.read(c_ulong)
# path["path_behavior"] = stream.read(c_ulong)
# if(path["path_type"] == 1):
# if(path["path_version"] >= 18):
# path["u8_01"] = stream.read(c_uint8)
# elif(path["path_version"] >= 13):
# path["moving_platform_sound"] = stream.read(str, length_type=c_uint8)
# elif(path["path_type"] == 2):
# path["long_01"] = stream.read(c_long)
# path["price"] = stream.read(c_long)
# path["rental_time"] = stream.read(c_long)
# path["accociated_zone"] = stream.read(c_ulonglong)
# path["display_name"] = String(length_type=c_uint8).deserialize(stream)
# path["display_description"] = String(length_type=c_uint8).deserialize(stream)
# path["long_02"] = stream.read(c_long)
# path["clone_limit"] = stream.read(c_long)
# path["reputation_multiplier"] = stream.read(c_float)
# path["rental_time_unit"] = stream.read(c_long)
# path["achievement_required"] = stream.read(c_long)
# path["player_zone_pos"] = Vector3().deserialize(stream)
# path["max_building_height"] = stream.read(c_float)
# elif(path["path_type"] == 3):
# path["next_path"] = String(length_type=c_uint8).deserialize(stream)
# if(path["path_version"] >= 14):
# path["u8_01"] = stream.read(c_uint8)
# elif(path["path_type"] == 4):
# path["spawned_lot"] = stream.read(c_ulong)
# path["respawn_time"] = stream.read(c_ulong)
# path["max_to_spawn"] = stream.read(c_long)
# path["number_to_maintain"] = stream.read(c_ulong)
# path["spawner_object_id"] = stream.read(c_longlong)
# path["activate_spawner_network_on_load"] = stream.read(c_bit)
# waypoint_count = stream.read(c_ulong)
# path["waypoints"] = []
# for _ in range(waypoint_count):
# waypoint = {}
# waypoint["position"] = Vector3().deserialize(stream)
# if(path["path_type"] == 1):
# waypoint["rotation"] = Vector4().deserialize(stream)
# waypoint["lock_player_until_next_waypoint"] = stream.read(c_bit)
# waypoint["speed"] = stream.read(c_float)
# waypoint["wait"] = stream.read(c_float)
# if(path["path_version"] >= 13):
# waypoint["depart_sound"] = stream.read(str, length_type=c_uint8)
# waypoint["arrive_sound"] = stream.read(str, length_type=c_uint8)
# elif(path["path_type"] == 3):
# waypoint["float_01"] = stream.read(c_float)
# waypoint["float_02"] = stream.read(c_float)
# waypoint["float_03"] = stream.read(c_float)
# waypoint["float_04"] = stream.read(c_float)
# waypoint["time"] = stream.read(c_float)
# waypoint["float_05"] = stream.read(c_float)
# waypoint["continuity"] = stream.read(c_float)
# waypoint["bias"] = stream.read(c_float)
# elif(path["path_type"] == 4):
# waypoint["rotation"] = Vector4().deserialize(stream)
# elif(path["path_type"] == 6):
# waypoint["rotation"] = Vector4().deserialize(stream)
# waypoint["u8_01"] = stream.read(c_uint8)
# waypoint["u8_02"] = stream.read(c_uint8)
# waypoint["float_01"] = stream.read(c_float)
# waypoint["float_02"] = stream.read(c_float)
# waypoint["float_03"] = stream.read(c_float)
# elif(path["path_type"] == 7):
# waypoint["float_01"] = stream.read(c_float)
# waypoint["float_02"] = stream.read(c_float)
# waypoint["float_03"] = stream.read(c_float)
# waypoint["float_04"] = stream.read(c_float)
# if(path["path_version"] >= 17):
# waypoint["float_05"] = stream.read(c_float)
# if(path["path_type"] in [0,4,7]):
# waypoint["config"] = {}
# for _ in range(stream.read(c_ulong)):
# waypoint["config"][stream.read(str, length_type=c_uint8)] = stream.read(str, length_type=c_uint8)
# path["waypoints"].append(waypoint)
# config["paths"].append(path)
return LUZ(config)

1
master.bat Normal file
View File

@@ -0,0 +1 @@
python __main__.py master 4211

View File

@@ -1,429 +0,0 @@
import services
import json
import database
import copy
import game_enums
import typing
import time
import threading
import game_types
class PlayerService(services.GameService):
def __init__(self, parent):
super().__init__(parent)
self._name = "Player"
self._accounts = []
global game
game = self.get_parent()
def initialize(self):
super().initialize()
def sync_thread():
while True:
self.sync_database()
time.sleep(1)
sync = threading.Thread(target=sync_thread)
sync.start()
def add_account(self, account_id : int):
server_db = self.get_parent().get_service("Database").server_db
c = server_db.connection.cursor()
c.execute("SELECT * FROM Accounts WHERE account_id = ?", (account_id,))
account = c.fetchone()
c.execute("SELECT * FROM Characters WHERE account_id = ?", (account_id,))
characters = c.fetchall()
for character in characters:
c.execute("SELECT * FROM CharacterData WHERE player_id = ?", (character["player_id"],))
data = c.fetchone()
data["position"] = game_types.Vector3(str_val=data["position"])
data["rotation"] = game_types.Vector4(str_val=data["rotation"])
character["Data"] = data
c.execute("SELECT * FROM CharacterStats WHERE player_id = ?", (character["player_id"],))
character["Stats"] = c.fetchone()
c.execute("SELECT * FROM CompletedMissions WHERE player_id = ?", (character["player_id"],))
character["CompletedMissions"] = c.fetchall()
c.execute("SELECT * FROM CurrentMissions WHERE player_id = ?", (character["player_id"],))
character["CurrentMissions"] = c.fetchall()
c.execute("SELECT * FROM Inventory WHERE player_id = ?", (character["player_id"],))
inventory = c.fetchall()
for item in inventory:
if(item["json"] is not None):
item["json"] = json.loads(item["json"])
else:
item["json"] = {}
character["Inventory"] = inventory
account["Characters"] = characters
self._accounts.append(account)
self.get_parent().trigger_event("AccountAdded", args=(account,))
def remove_account(self, account_id : int):
for account in self._accounts:
if(account["account_id"] == account_id):
self._accounts.remove(account)
def sync_database(self, accounts : typing.Iterable = None):
if(accounts is None):
accounts = self._accounts
server_db = self.get_parent().get_service("Database").server_db
c = server_db.connection.cursor()
for account in accounts:
account_copy = copy.deepcopy(account)
for character in account_copy["Characters"]:
inventory = copy.deepcopy(character["Inventory"])
del character["Inventory"]
stats = copy.deepcopy(character["Stats"])
del character["Stats"]
data = copy.deepcopy(character["Data"])
data["position"] = str(data["position"])
data["rotation"] = str(data["rotation"])
del character["Data"]
completed_missions = character["CompletedMissions"]
del character["CompletedMissions"]
current_missions = character["CurrentMissions"]
del character["CurrentMissions"]
c.execute("UPDATE Characters SET name = ?, zone = ?, shirt_color = ?, shirt_style = ?, pants_color = ?, hair_color = ?, hair_style = ?, lh = ?, rh = ?, eyebrows = ?, eyes = ?, mouth = ? WHERE player_id = ?",
(character["name"], character["zone"], character["shirt_color"], character["shirt_style"], character["pants_color"], character["hair_color"], character["hair_style"], character["lh"], character["rh"],
character["eyebrows"], character["eyes"], character["mouth"], character["player_id"]))
c.execute('''UPDATE CharacterStats SET currency_collected = ?, bricks_collected = ?, smashables_smashed = ?, quick_builds_done = ?, enemies_smashed = ?, rockets_used = ?, pets_tamed = ?, imagination_collected = ?, health_collected = ?, armor_collected = ?, distance_traveled = ?, times_died = ?,
damage_taken = ?, damage_healed = ?, armor_repaired = ?, imagination_restored = ?, imagination_used = ?, distance_driven = ?, time_airborne_in_car = ?, racing_imagination_collected = ?, racing_imagination_crates_smashed = ?, race_car_boosts = ?, car_wrecks = ?, racing_smashables_smashed = ?,
races_finished = ?, races_won = ? WHERE player_id = ?''', (stats["currency_collected"], stats["bricks_collected"], stats["smashables_smashed"], stats["quick_builds_done"], stats["enemies_smashed"], stats["rockets_used"], stats["pets_tamed"], stats["imagination_collected"], stats["health_collected"], stats["armor_collected"], stats["distance_traveled"], stats["times_died"],
stats["damage_taken"], stats["damage_healed"], stats["armor_repaired"], stats["imagination_restored"], stats["imagination_used"], stats["distance_driven"], stats["time_airborne_in_car"], stats["racing_imagination_collected"], stats["racing_imagination_crates_smashed"], stats["race_car_boosts"], stats["car_wrecks"], stats["racing_smashables_smashed"],
stats["races_finished"], stats["races_won"], character["player_id"]))
c.execute('''UPDATE CharacterData SET universe_score = ?, level = ?, health = ?, max_health = ?, armor = ?, max_armor = ?, imagination = ?, max_imagination = ?, currency = ?, position = ?, rotation = ?, backpack_space = ? WHERE player_id = ?''',
(data["universe_score"], data["level"], data["health"], data["max_health"], data["armor"], data["max_armor"], data["imagination"], data["max_imagination"], data["currency"], data["position"], data["rotation"], data["backpack_space"], character["player_id"]))
for mission in completed_missions:
c.execute("SELECT * FROM CompletedMissions WHERE player_id = ? and mission_id = ?", (mission["player_id"], mission["mission_id"]))
check = c.fetchall()
if(check == []):
c.execute("INSERT INTO CompletedMissions (player_id, mission_id) VALUES (?, ?)", (mission["player_id"], mission["mission_id"]))
for mission in current_missions:
c.execute("SELECT * FROM CurrentMissions WHERE player_id = ? and mission_id = ?", (mission["player_id"], mission["mission_id"]))
check = c.fetchall()
if(check == []):
c.execute("INSERT INTO CurrentMissions (player_id, mission_id, progress) VALUES (?, ?, ?)", (mission["player_id"], mission["mission_id"], mission["progress"]))
else:
c.execute("UPDATE CurrentMissions SET progress = ? WHERE player_id = ? AND mission_id = ?", (mission["progress"], mission["player_id"], mission["mission_id"]))
c.execute("SELECT * FROM CurrentMissions WHERE player_id = ?", (character["player_id"],))
db_missions = c.fetchall()
for mission in db_missions:
keep = False
for server_mission in current_missions:
if(server_mission["mission_id"] == mission["mission_id"]):
keep = True
if(keep == False):
c.execute("DELETE FROM CurrentMissions WHERE player_id = ? AND mission_id = ?", (mission["player_id"], mission["mission_id"]))
for item in inventory:
item["json"] = json.dumps(item["json"])
c.execute("SELECT * FROM Inventory WHERE item_id = ?", (item["item_id"],))
check = c.fetchall()
if(check == []):
c.execute("INSERT INTO Inventory (lot, slot, equipped, linked, quantity, item_id, player_id, json) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(item["lot"], item["slot"], item["equipped"], item["linked"], item["quantity"], item["item_id"], item["player_id"], item["json"]))
else:
c.execute("UPDATE Inventory SET slot = ?, equipped = ?, linked = ?, quantity = ?, json = ? WHERE item_id = ?",
(item["slot"], item["equipped"], item["linked"], item["quantity"], item["json"], item["item_id"]))
c.execute("SELECT * FROM Inventory WHERE player_id = ?", (character["player_id"],))
db_inventory = c.fetchall()
for item in db_inventory:
keep = False
for server_item in inventory:
if(server_item["item_id"] == item["item_id"]):
keep = True
if(keep == False):
c.execute("DELETE FROM Inventory WHERE item_id = ?", (item["item_id"],))
def delete_player(self, player_id):
account = self.get_account_by_player_id(player_id)
self.sync_database(accounts=[account])
player = copy.deepcopy(self.get_player_by_id(player_id))
for character in account["Characters"]:
if(character["player_id"] == player_id):
account["Characters"].remove(character)
db = self.get_parent().get_service("Database").server_db
c = db.connection.cursor()
c.execute("DELETE FROM Characters WHERE player_id = ?", (player_id,))
c.execute("DELETE FROM CharacterData WHERE player_id = ?", (player_id,))
c.execute("DELETE FROM CharacterStats WHERE player_id = ?", (player_id,))
c.execute("DELETE FROM CompletedMissions WHERE player_id = ?", (player_id,))
c.execute("DELETE FROM CurrentMissions WHERE player_id = ?", (player_id,))
c.execute("DELETE FROM Inventory WHERE player_id = ?", (player_id,))
self.get_parent().trigger_event("PlayerDeleted", args=(player,))
def create_player(self, account_id : int, name: str, shirt_color: int, shirt_style: int, pants_color: int, hair_color: int,
hair_style: int, lh: int, rh: int, eyebrows: int, eyes: int, mouth: int, custom_name: str):
db = self.get_parent().get_service("Database").server_db
c = db.connection.cursor()
player_id = self.get_parent().generate_object_id()
c.execute('''INSERT INTO CharacterStats (currency_collected, bricks_collected, smashables_smashed, quick_builds_done, enemies_smashed, rockets_used, pets_tamed, imagination_collected, health_collected, armor_collected, distance_traveled, times_died,
damage_taken, damage_healed, armor_repaired, imagination_restored , imagination_used, distance_driven, time_airborne_in_car, racing_imagination_collected, racing_imagination_crates_smashed, race_car_boosts, car_wrecks, racing_smashables_smashed,
races_finished, races_won, player_id) VALUES (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,?)''', (player_id,))
c.execute('''INSERT INTO Characters (account_id, name, shirt_color, shirt_style, pants_color, hair_color, hair_style, lh, rh, eyebrows, eyes, mouth, zone, player_id, custom_name) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (account_id, name, shirt_color, shirt_style, pants_color, hair_color, hair_style, lh, rh, eyebrows, eyes, mouth, 1000, player_id, custom_name))
c.execute('''INSERT INTO CharacterData (universe_score, level, health, max_health, armor, max_armor, imagination, max_imagination, currency, position, rotation, player_id, backpack_space) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (0, 0, 4, 4, 0, 0, 0, 0, 0, "0,0,0", "0,0,0", player_id, 20))
account = self.get_account_by_id(account_id)
self.sync_database([account])
player_copy = copy.deepcopy({"account_id":account_id, "name":name, "shirt_color":shirt_color, "shirt_style":shirt_style, "pants_color":pants_color, "hair_color":hair_color, "hair_style":hair_style,
"lh":lh, "rh":rh, "eyebrows":eyebrows, "eyes":eyes, "mouth":mouth, "zone":1000, "player_id":player_id, "custom_name":custom_name})
player_copy["Data"] = {"universe_score":0, "level":0, "health":4, "max_health":4, "armor":0, "max_armor":0, "imagination":0, "max_imagination":0, "currency":0, "position":"0,0,0",
"rotation":"0,0,0,0", "player_id":player_id, "backpack_space":20}
player_copy["Data"]["position"] = game_types.Vector3(str_val = player_copy["Data"]["position"])
player_copy["Data"]["rotation"] = game_types.Vector4(str_val = player_copy["Data"]["rotation"])
player_copy["Stats"] = {"currency_collected":0, "bricks_collected":0, "smashables_smashed":0, "quick_builds_done":0, "enemies_smashed":0, "rockets_used":0, "pets_tamed":0,
"imagination_collected":0, "health_collected":0, "armor_collected":0, "distance_traveled":0, "times_died":0, "damage_taken":0, "damage_healed":0,
"armor_repaired":0, "imagination_restored":0, "imagination_used":0, "distance_driven":0, "time_airborne_in_car":0, "racing_imagination_collected":0,
"racing_imagination_crates_smashed":0, "race_car_boosts":0, "car_wrecks":0, "racing_smashables_smashed":0, "races_finished":0, "races_won":0, "player_id":player_id}
player_copy["CompletedMissions"] = []
player_copy["CurrentMissions"] = []
player_copy["Inventory"] = []
account["Characters"].append(player_copy)
self.get_parent().trigger_event("PlayerCreated", args=[player_id,])
shirt_id = 0
if (shirt_color == 0):
if (shirt_style >= 35):
shirt_id = 5730
else:
shirt_id = game_enums.ItemLOTs.SHIRT_BRIGHT_RED.value
elif (shirt_color == 1):
if (shirt_style >= 35):
shirt_id = 5736
else:
shirt_id = game_enums.ItemLOTs.SHIRT_BRIGHT_BLUE.value
elif (shirt_color == 3):
if (shirt_style >= 35):
shirt_id = 5808
else:
shirt_id = game_enums.ItemLOTs.SHIRT_DARK_GREEN.value
elif (shirt_color == 5):
if (shirt_style >= 35):
shirt_id = 5754
else:
shirt_id = game_enums.ItemLOTs.SHIRT_BRIGHT_ORANGE.value
elif (shirt_color == 6):
if (shirt_style >= 35):
shirt_id = 5760
else:
shirt_id = game_enums.ItemLOTs.SHIRT_BLACK.value
elif (shirt_color == 7):
if (shirt_style >= 35):
shirt_id = 5766
else:
shirt_id = game_enums.ItemLOTs.SHIRT_DARK_STONE_GRAY.value
elif (shirt_color == 8):
if (shirt_style >= 35):
shirt_id = 5772
else:
shirt_id = game_enums.ItemLOTs.SHIRT_MEDIUM_STONE_GRAY.value
elif (shirt_color == 9):
if (shirt_style >= 35):
shirt_id = 5778
else:
shirt_id = game_enums.ItemLOTs.SHIRT_REDDISH_BROWN.value
elif (shirt_color == 10):
if (shirt_style >= 35):
shirt_id = 5784
else:
shirt_id = game_enums.ItemLOTs.SHIRT_WHITE.value
elif (shirt_color == 11):
if (shirt_style >= 35):
shirt_id = 5802
else:
shirt_id = game_enums.ItemLOTs.SHIRT_MEDIUM_BLUE.value
elif (shirt_color == 13):
if (shirt_style >= 35):
shirt_id = 5796
else:
shirt_id = game_enums.ItemLOTs.SHIRT_DARK_RED.value
elif (shirt_color == 14):
if (shirt_style >= 35):
shirt_id = 5802
else:
shirt_id = game_enums.ItemLOTs.SHIRT_EARTH_BLUE.value
elif (shirt_color == 15):
if (shirt_style >= 35):
shirt_id = 5808
else:
shirt_id = game_enums.ItemLOTs.SHIRT_EARTH_GREEN.value
elif (shirt_color == 16):
if (shirt_style >= 35):
shirt_id = 5814
else:
shirt_id = game_enums.ItemLOTs.SHIRT_BRICK_YELLOW.value
elif (shirt_color == 84):
if (shirt_style >= 35):
shirt_id = 5820
else:
shirt_id = game_enums.ItemLOTs.SHIRT_SAND_BLUE.value
elif (shirt_color == 96):
if (shirt_style >= 35):
shirt_id = 5826
else:
shirt_id = game_enums.ItemLOTs.SHIRT_SAND_GREEN.value
if (shirt_style >= 35):
final_shirt_id = shirt_id + (shirt_style - 35)
else:
final_shirt_id = shirt_id + (shirt_style - 1)
if (pants_color == 0):
pants_id = game_enums.ItemLOTs.PANTS_BRIGHT_RED.value
elif (pants_color == 1):
pants_id = game_enums.ItemLOTs.PANTS_BRIGHT_BLUE.value
elif (pants_color == 3):
pants_id = game_enums.ItemLOTs.PANTS_DARK_GREEN.value
elif (pants_color == 5):
pants_id = game_enums.ItemLOTs.PANTS_BRIGHT_ORANGE.value
elif (pants_color == 6):
pants_id = game_enums.ItemLOTs.PANTS_BLACK.value
elif (pants_color == 7):
pants_id = game_enums.ItemLOTs.PANTS_DARK_STONE_GRAY.value
elif (pants_color == 8):
pants_id = game_enums.ItemLOTs.PANTS_MEDIUM_STONE_GRAY.value
elif (pants_color == 9):
pants_id = game_enums.ItemLOTs.PANTS_REDDISH_BROWN.value
elif (pants_color == 10):
pants_id = game_enums.ItemLOTs.PANTS_WHITE.value
elif (pants_color == 11):
pants_id = game_enums.ItemLOTs.PANTS_MEDIUM_BLUE.value
elif (pants_color == 13):
pants_id = game_enums.ItemLOTs.PANTS_DARK_RED.value
elif (pants_color == 14):
pants_id = game_enums.ItemLOTs.PANTS_EARTH_BLUE.value
elif (pants_color == 15):
pants_id = game_enums.ItemLOTs.PANTS_EARTH_GREEN.value
elif (pants_color == 16):
pants_id = game_enums.ItemLOTs.PANTS_BRICK_YELLOW.value
elif (pants_color == 84):
pants_id = game_enums.ItemLOTs.PANTS_SAND_BLUE.value
elif (pants_color == 96):
pants_id = game_enums.ItemLOTs.PANTS_SAND_GREEN.value
else:
pants_id = 2508
self.add_item_to_inventory(player_id, final_shirt_id, equipped=True, linked=True, json_data={"from":"character_creation"})
self.add_item_to_inventory(player_id, pants_id, equipped=True, linked=True,json_data={"from":"character_creation"})
def get_account_by_id(self, account_id : int):
for account in self._accounts:
if(account["account_id"] == account_id):
return account
return None
def get_player_object_by_id(self, player_id : int):
session = self.get_parent().get_service("Session").get_session_by_player_id(player_id)
zone = self.get_parent().get_service("World").get_zone_by_id(session.zone_id)
return zone.get_object_by_id(player_id)
def get_account_by_player_id(self, player_id : int):
for account in self._accounts:
for character in account["Characters"]:
if(character["player_id"] == player_id):
return account
return None
def get_player_by_id(self, player_id : int):
for account in self._accounts:
for character in account["Characters"]:
if(character["player_id"] == player_id):
return character
return None
def add_item_to_inventory(self, player_id : int, lot : int, slot : int = None, equipped : bool = False, linked : bool = False, quantity : int = 1, json_data : dict = None):
if(json_data is None):
json_data = {}
player = self.get_player_by_id(player_id)
if(slot is None):
availible_slots = []
for i in range(player["Data"]["backpack_space"]):
availible_slots.append(i)
for item in player["Inventory"]:
availible_slots.remove(item["slot"])
if(availible_slots != []):
slot = availible_slots[0]
else:
print("No Inventory Space Availible!")
return None
database_service = game.get_service("Database")
cdclient = database_service.cdclient_db
c = cdclient.connection.cursor()
c.execute("SELECT component_id FROM ComponentsRegistry WHERE id = ? and component_type = 11", (lot,))
item_component_id = c.fetchone()
c.execute("SELECT * FROM ItemComponent WHERE id = ?", (item_component_id["component_id"],))
item_data = c.fetchone()
new_item_id = game.generate_object_id()
json_data["proxy_items"] = []
if(item_data["subItems"] is not None):
json_data["proxy_items"].append({"player_id":player_id, "lot":int(item_data["subItems"]), "slot":-1, "equipped":1, "linked":1, "quantity":1, "item_id":game.generate_object_id(), "json":{"is_proxy":1, "parent_item":new_item_id}})
item = {"player_id":player_id, "lot":lot, "slot":slot, "equipped":int(equipped), "linked":int(linked), "quantity":quantity, "json":json_data, "item_id":new_item_id}
db = self.get_parent().get_service("Database").server_db
c2 = db.connection.cursor()
db_item = copy.deepcopy(item)
db_item["json"] = json.dumps(db_item["json"])
c2.execute("INSERT INTO Inventory (lot, slot, equipped, linked, quantity, item_id, player_id, json) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(db_item["lot"], db_item["slot"], db_item["equipped"], db_item["linked"], db_item["quantity"], db_item["item_id"], db_item["player_id"], db_item["json"]))
player["Inventory"].append(item)
self.get_parent().trigger_event("ItemAdded", args=[player_id, item])
return item
def get_item_by_id(self, player_id : int, item_id : int):
player = self.get_player_by_id(player_id)
if(player is not None):
for item in player["Inventory"]:
if(item["item_id"] == item_id):
return item
return None
def get_equipped_items(self, player_id : int):
player = self.get_player_by_id(player_id)
items = []
def parse_item(item):
if (int(item["equipped"]) == 1):
items.append(item)
if ("proxy_items" in item["json"] and item["json"]["proxy_items"] != []):
for proxy_item in item["json"]["proxy_items"]:
parse_item(proxy_item)
for item in player["Inventory"]:
parse_item(item)
self.get_parent().trigger_event("EquipListRequest", args=[player_id, items])
return items

View File

@@ -0,0 +1,75 @@
"""
This plugin will handle all of the auth packet handlers
"""
from ..serializables import packet_enum, auth_to_client, client_to_auth, global_packets
from pyraknet.bitstream import *
import os
import uuid
import bcrypt
from datetime import datetime
class Plugin:
def __init__(self, parent):
print("Auth Handler Initiated")
parent.register_handler(Plugin.handle_handshake, packet_enum.PacketHeader.HANDSHAKE.value)
parent.register_handler(Plugin.handle_login, packet_enum.PacketHeader.CLIENT_LOGIN_INFO.value)
@classmethod
def handle_login(cls, data: bytes, address, server):
stream = ReadStream(data)
login_info = stream.read(client_to_auth.LoginInfoPacket)
print(f"Player logging in with Username [{login_info.username}] and Password [{login_info.password}]")
packet = WriteStream()
response = auth_to_client.LoginInfoPacket()
c = server.db_connection.cursor()
c.execute("SELECT * FROM account WHERE username = %s", (login_info.username,))
results = c.fetchone()
if results is not None:
user_info = dict(zip(c.column_names, results))
if (not bool(user_info["banned"]) and
bcrypt.checkpw(login_info.password.encode("utf-8"), user_info["password"].encode("utf-8"))):
response.login_return_code = packet_enum.LoginReturnCode.SUCCESS.value
response.user_key = (str(uuid.uuid4()))[0:20]
timestamp = datetime.timestamp(datetime.now())
c.execute("DELETE FROM session WHERE username = %s", (login_info.username,))
server.db_connection.commit()
c.execute("INSERT INTO session (username, user_key, ip_address, login_timestamp)"
"VALUES (%s, %s, %s, %s);",
(login_info.username, response.user_key, str(address), timestamp))
server.db_connection.commit()
print(f"Login Succeeded - Created Session with User-key [{response.user_key}] "
f"and Timestamp [{timestamp}]")
else:
response.login_return_code = packet_enum.LoginReturnCode.INVALID_LOGIN_INFO.value
print("Login Failed")
else:
response.login_return_code = packet_enum.LoginReturnCode.INVALID_LOGIN_INFO.value
print("Login Failed")
char_address, char_port = server.redirect_request("instance", "char")
response.char_port = char_address
response.char_ip = char_port
packet.write(packet_enum.PacketHeader.LOGIN_RESPONSE.value)
packet.write(response)
server.send(packet, address)
@classmethod
def handle_handshake(cls, data: bytes, address, server):
"""
Handles initial connection between server and client.
"""
stream = ReadStream(data)
client_handshake = stream.read(global_packets.HandshakePacket)
print(f"{address[0]} has initiated handshake - Client has version {client_handshake.game_version}")
server_handshake = global_packets.HandshakePacket()
server_handshake.remote_connection_type = 1
server_handshake.process_id = os.getpid()
packet = WriteStream()
packet.write(packet_enum.PacketHeader.HANDSHAKE.value)
packet.write(server_handshake)
server.send(packet, address)

View File

@@ -0,0 +1,8 @@
{
"name": "Auth Handler",
"id": "auth_handler",
"description": "This plugin handles auth packets.",
"main_file": "auth_handlers",
"type": "auth",
"dependencies": ["serializables"]
}

View File

@@ -0,0 +1,157 @@
"""
This will handle all of the character related packets.
"""
from ..serializables import packet_enum, world_to_client, client_to_world, global_packets, misc_serializables
from pyraknet.bitstream import *
import os
class Plugin:
def __init__(self, parent):
print("Character Handler Initiated")
parent.register_handler(Plugin.handle_handshake, packet_enum.PacketHeader.HANDSHAKE.value)
parent.register_handler(Plugin.handle_minifigure_list_request,
packet_enum.PacketHeader.CLIENT_USER_SESSION_INFO.value)
parent.register_handler(Plugin.handle_minifigure_creation,
packet_enum.PacketHeader.CLIENT_MINIFIGURE_CREATE_REQUEST.value)
@classmethod
def handle_handshake(cls, data: bytes, address, server):
"""
Handles initial connection between server and client.
"""
stream = ReadStream(data)
client_handshake = stream.read(global_packets.HandshakePacket)
print(f"{address[0]} has initiated handshake - Client has version {client_handshake.game_version}")
server_handshake = global_packets.HandshakePacket()
server_handshake.remote_connection_type = 4
server_handshake.process_id = os.getpid()
packet = WriteStream()
packet.write(packet_enum.PacketHeader.HANDSHAKE.value)
packet.write(server_handshake)
server.send(packet, address)
@classmethod
def handle_minifigure_creation(cls, data: bytes, address, server):
c = server.db_connection.cursor()
c.execute("SELECT * FROM wlus.session WHERE ip_address = %s", (str(address),))
session = c.fetchone()
c.execute("SELECT account_id FROM wlus.account WHERE username = %s", (session[1],))
account_id = c.fetchone()[0]
stream = ReadStream(data)
minfig = stream.read(client_to_world.MinifigureCreateRequestPacket).to_login_character()
minfig.save_to_db(account_id, server.db_connection)
response = world_to_client.MinifigureCreationResponsePacket()
response.response = 0x00
packet = WriteStream()
packet.write(packet_enum.PacketHeader.MINIFIGURE_CREATION_RESPONSE.value)
packet.write(response)
server.send(packet, address)
characters = []
c.execute("SELECT * FROM wlus.character WHERE account_id = %s", (account_id,))
minifig_results = c.fetchall()
for minifig in minifig_results:
char = misc_serializables.LoginCharacter()
char.object_id = minifig[0]
char.current_name = minifig[1]
char.unapproved_name = minifig[2]
char.head_color = minifig[3]
char.head = minifig[4]
char.chest_color = minifig[5]
char.chest = minifig[6]
char.legs = minifig[7]
char.hair_style = minifig[8]
char.hair_color = minifig[9]
char.left_hand = minifig[10]
char.right_hand = minifig[11]
char.eyebrows_style = minifig[12]
char.eyes_style = minifig[13]
char.mouth_style = minifig[14]
c.execute("SELECT * FROM wlus.inventory WHERE player_id = %s AND equipped = 1", (char.object_id,))
equipped_items = c.fetchall()
for i in equipped_items:
char.equipped_items.append(i[1])
characters.append(char)
char_list = world_to_client.MinfigureListPacket()
for c in characters:
char_list.minifigs.append(c)
packet = WriteStream()
packet.write(packet_enum.PacketHeader.MINIFIGURE_LIST.value)
packet.write(char_list)
server.send(packet, address)
@classmethod
def handle_minifigure_list_request(cls, data: bytes, address, server):
stream = ReadStream(data)
session_info = stream.read(client_to_world.UserSessionInfoPacket)
c = server.db_connection.cursor()
c.execute("SELECT * FROM wlus.session WHERE username = %s", (session_info.username,))
results = c.fetchall()
if results is not None:
sessions = [dict(zip(c.column_names, result)) for result in results]
if sessions[0]["user_key"] == session_info.user_key:
packet = WriteStream()
c.execute("SELECT account_id FROM account WHERE username = %s", (session_info.username,))
account_id = c.fetchone()[0]
characters = []
c.execute("SELECT * FROM wlus.character WHERE account_id = %s", (account_id,))
minifig_results = c.fetchall()
for minifig in minifig_results:
char = misc_serializables.LoginCharacter()
char.object_id = minifig[0]
char.current_name = minifig[1]
char.unapproved_name = minifig[2]
char.head_color = minifig[3]
char.head = minifig[4]
char.chest_color = minifig[5]
char.chest = minifig[6]
char.legs = minifig[7]
char.hair_style = minifig[8]
char.hair_color = minifig[9]
char.left_hand = minifig[10]
char.right_hand = minifig[11]
char.eyebrows_style = minifig[12]
char.eyes_style = minifig[13]
char.mouth_style = minifig[14]
c.execute("SELECT * FROM wlus.inventory WHERE player_id = %s AND equipped = 1", (char.object_id,))
equipped_items = c.fetchall()
for i in equipped_items:
char.equipped_items.append(i[1])
characters.append(char)
char_list = world_to_client.MinfigureListPacket()
for c in characters:
char_list.minifigs.append(c)
"""
# Add Duke Exeter (For Testing)
exeter = misc_serializables.LoginCharacter.from_cdclient(12261)
exeter.equipped_items.append(7369)
exeter.equipped_items.append(7381)
char_list.minifigs.append(exeter)
"""
packet.write(packet_enum.PacketHeader.MINIFIGURE_LIST.value)
packet.write(char_list)
server.send(packet, address)
else:
disconnect = global_packets.DisconnectNotifyPacket()
disconnect.disconnect_id = packet_enum.DisconnectionNotify.INVALID_SESSION_KEY.value
disconnect_packet = WriteStream()
disconnect_packet.write(packet_enum.PacketHeader.DISCONNECT_NOTIFY.value)
disconnect_packet.write(disconnect)
server.send(disconnect_packet, address)
else:
disconnect = global_packets.DisconnectNotifyPacket()
disconnect.disconnect_id = packet_enum.DisconnectionNotify.INVALID_SESSION_KEY.value
disconnect_packet = WriteStream()
disconnect_packet.write(packet_enum.PacketHeader.DISCONNECT_NOTIFY.value)
disconnect_packet.write(disconnect)
server.send(disconnect_packet, address)

View File

@@ -0,0 +1,8 @@
{
"name": "Char Handler",
"id": "char_handler",
"description": "This plugin handles all the character packets.",
"main_file": "char_handlers",
"type": "char",
"dependencies": ["serializables"]
}

View File

@@ -0,0 +1,84 @@
"""
Contains various enum for the cdclient
"""
from enum import IntEnum
class COMPONENTS(IntEnum):
CONTROLLABLE_PHYSICS = 1
RENDER = 2
SIMPLE_PHYSICS = 3
CHARACTER = 4
SCRIPT = 5
BOUNCER = 6
DESTROYABLE = 7
SKILL = 9
SPAWNER = 10
ITEM = 11
REBUILD = 12
REBUILD_START = 13
VENDOR = 16
INVENTORY = 17
PROJECTILE_PHYSICS = 18
SHOOTING_GALLERY = 19
RIGID_BODY_PHANTOM_PHYSICS = 20
CHEST = 22
COLLECTIBLE = 23
BLUEPRINT = 24
MOVING_PLATFORM = 25
PET = 26
PLATFORM_BOUNDARY = 27
MODULE = 28
ARCADE = 29
VEHICLE_PHYSICS_0 = 30
MOVEMENT_AI = 31
EXHIBIT = 32
MINIFIG = 35
PROPERTY = 36
PET_CREATOR = 37
MODEL_BUILDER = 38
SCRIPTED_ACTIVITY = 39
PHANTOM_PHYSICS = 40
SPRINGPAD = 41
B3_BEHAVIORS = 42
PROPERTY_ENTRANCE = 43
PROPERTY_MANAGEMENT = 45
VEHICLE_PHYSICS_1 = 46
PHYSICS_SYSTEM = 47
QUICK_BUILD = 48
SWITCH = 49
MINIGAME = 50
CHANGLING = 51
CHOICE_BUILD = 52
PACKAGE = 53
SOUND_REPEATER = 54
SOUND_AMBIENT_2D = 55
SOUND_AMBIENT_3D = 56
PRECONDITION = 57
CUSTOM_BUILD_ASSEMBLY = 59
BASE_COMBAT_AI = 60
MODULE_ASSEMBLY = 61
SHOWCASE_MODEL_HANDLER = 62
RACING_MODULE = 63
GENERIC_ACTIVATOR = 64
PROPERTY_VENDOR = 65
HF_LIGHT_DIRECTION_GADGET = 66
ROCKET_LAUNCH = 67
ROCKET_LANDING = 68
RACING_CONTROL = 71
FACTION_TRIGGER = 72
MISSION_OFFER = 73
RACING_STATS = 74
LUP_EXHIBIT = 75
SOUND_TRIGGER = 77
PROXIMITY_MONITOR = 79
USER_CONTROL = 95
LUP_LAUNCHPAD = 97
BRICK_DONATION = 100
COMMENDATION_VENDOR = 102
RAIL_ACTIVATOR = 104
ROLLER = 105
POSSESSABLE = 108
PROPERTY_PLAQUE = 113
BUILD_BORDER = 114
CULLING_PLANE = 116

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"name": "Easy CDClient Module",
"id": "easy_cdclient",
"description": "This module makes searching through the cdclient a lot easier. Something is currently wrong with it, sooo probably best not to use it for now.",
"type": "module",
"dependencies": []
}

View File

@@ -0,0 +1,53 @@
"""
Contains all the packets that auth would send to the client
"""
from pyraknet import bitstream
from .misc_serializables import CString
class LoginInfoPacket(bitstream.Serializable):
"""
[53-05-00-00]
This packet is sent in response to the character logging in.
"""
def __init__(self):
self.login_return_code = 0x06
self.client_version_major = 1
self.client_version_current = 10
self.client_version_minor = 64
self.user_key = ""
self.char_ip = "127.0.0.1"
self.chat_ip = "127.0.0.1"
self.char_port = 2002
self.chat_port = 3003
self.localization = "US"
self.custom_error = ""
self.display_first_time = False
self.is_ftp = False
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint8(self.login_return_code))
stream.write(CString("Talk_Like_A_Pirate", allocated_length=33))
stream.write(CString("", allocated_length=33 * 7))
stream.write(bitstream.c_uint16(self.client_version_major))
stream.write(bitstream.c_uint16(self.client_version_current))
stream.write(bitstream.c_uint16(self.client_version_minor))
stream.write(self.user_key, allocated_length=33)
stream.write(CString(self.char_ip, allocated_length=33))
stream.write(CString(self.chat_ip, allocated_length=33))
stream.write(bitstream.c_uint16(self.char_port))
stream.write(bitstream.c_uint16(self.chat_port))
stream.write(CString('0', allocated_length=33))
stream.write(CString('00000000-0000-0000-0000-000000000000', allocated_length=37))
stream.write(bitstream.c_uint32(0))
stream.write(CString(self.localization, allocated_length=3)) # US Localization
stream.write(bitstream.c_bool(self.display_first_time))
stream.write(bitstream.c_bool(self.is_ftp))
stream.write(bitstream.c_uint64(0))
stream.write(self.custom_error, length_type=bitstream.c_uint16) # Custom error message
stream.write(bitstream.c_uint16(0))
stream.write(bitstream.c_uint32(4))
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This packet cannot be deserialized.")

View File

@@ -0,0 +1,30 @@
"""
Contains all the packets that are sent from the client to the auth server.
"""
from pyraknet import bitstream
class LoginInfoPacket(bitstream.Serializable):
"""
[53-01-00-00]
This packet contains the username and password of a player logging in.
Even though there is more information in the Login Info Packet,
the only ones that this Serializable will read is the Username and Password
"""
def __init__(self):
self.username = ""
self.password = ""
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = LoginInfoPacket()
packet.username = stream.read(str, allocated_length=33)
packet.password = stream.read(str, allocated_length=41)
return packet

View File

@@ -0,0 +1,326 @@
"""
Contains all the packets sent from the client to the world/char server
"""
from pyraknet import bitstream
from ..serializables import misc_serializables, packet_enum
class UserSessionInfoPacket(bitstream.Serializable):
"""
[53-04-00-01]
This packet contains the username and session key of a user who went through
the auth server.
"""
def __init__(self):
self.username = ""
self.user_key = ""
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = UserSessionInfoPacket()
packet.username = stream.read(str, allocated_length=33)
packet.user_key = stream.read(str, allocated_length=33)
return packet
class MinifigureListRequestPacket(bitstream.Serializable):
"""
[53-04-00-02]
This packet actually doesn't have any info. It's just here because it exists.
This is sent to let the server know that it's ready for the minifgure list
"""
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = UserSessionInfoPacket()
return packet
class MinifigureCreateRequestPacket(bitstream.Serializable):
"""
[53-04-00-03]
This packet is sent when a character clicks the create minfigure button.
It contains all of the selection choices he/she made.
"""
def __init__(self):
self.name = ""
self.predef_name_1 = 0
self.predef_name_2 = 0
self.predef_name_3 = 0
self.unknown_0 = 0
self.head_color = 0
self.head = 0
self.chest_color = 0
self.chest = 0
self.legs = 0
self.hair_style = 0
self.hair_color = 0
self.left_hand = 0
self.right_hand = 0
self.eyebrow_style = 0
self.eyes_style = 0
self.mouth_style = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = MinifigureCreateRequestPacket()
packet.name = stream.read(str, allocated_length=33)
packet.predef_name_1 = stream.read(bitstream.c_uint32)
packet.predef_name_2 = stream.read(bitstream.c_uint32)
packet.predef_name_3 = stream.read(bitstream.c_uint32)
packet.unknown_0 = stream.read(bitstream.c_uint8)
packet.head_color = stream.read(bitstream.c_uint32)
packet.head = stream.read(bitstream.c_uint32)
packet.chest_color = stream.read(bitstream.c_uint32)
packet.chest = stream.read(bitstream.c_uint32)
packet.legs = stream.read(bitstream.c_uint32)
packet.hair_style = stream.read(bitstream.c_uint32)
packet.hair_color = stream.read(bitstream.c_uint32)
packet.left_hand = stream.read(bitstream.c_uint32)
packet.right_hand = stream.read(bitstream.c_uint32)
packet.eyebrow_style = stream.read(bitstream.c_uint32)
packet.eyes_style = stream.read(bitstream.c_uint32)
packet.mouth_style = stream.read(bitstream.c_uint32)
return packet
def to_login_character(self):
char = misc_serializables.LoginCharacter()
first = open('./res/minifigname_first.txt', 'r')
safe_name = first.readlines()[self.predef_name_1].rstrip()
first.close()
middle = open('./res/minifigname_middle.txt', 'r')
safe_name += middle.readlines()[self.predef_name_2].rstrip()
middle.close()
last = open('./res/minifigname_last.txt', 'r')
safe_name += last.readlines()[self.predef_name_3].rstrip()
last.close()
char.object_id = misc_serializables.LwoObjID.gen_lwoobjid(persistent=True, character=True)
char.current_name = safe_name
char.unapproved_name = self.name
char.head_color = self.head_color
char.head = self.head
char.chest_color = self.chest_color
char.chest = self.chest
char.legs = self.legs
char.hair_style = self.hair_style
char.hair_color = self.hair_color
char.left_hand = self.left_hand
char.right_hand = self.right_hand
char.eyebrows_style = self.eyebrow_style
char.eyes_style = self.eyes_style
char.mouth_style = self.mouth_style
shirt_id = 0
if self.chest_color == 0:
if self.chest >= 35:
shirt_id = 5730
else:
shirt_id = packet_enum.CreationLOT.SHIRT_BRIGHT_RED.value
elif self.chest_color == 1:
if self.chest >= 35:
shirt_id = 5736
else:
shirt_id = packet_enum.CreationLOT.SHIRT_BRIGHT_BLUE.value
elif self.chest_color == 3:
if self.chest >= 35:
shirt_id = 5808
else:
shirt_id = packet_enum.CreationLOT.SHIRT_DARK_GREEN.value
elif self.chest_color == 5:
if self.chest >= 35:
shirt_id = 5754
else:
shirt_id = packet_enum.CreationLOT.SHIRT_BRIGHT_ORANGE.value
elif self.chest_color == 6:
if self.chest >= 35:
shirt_id = 5760
else:
shirt_id = packet_enum.CreationLOT.SHIRT_BLACK.value
elif self.chest_color == 7:
if self.chest >= 35:
shirt_id = 5766
else:
shirt_id = packet_enum.CreationLOT.SHIRT_DARK_STONE_GRAY.value
elif self.chest_color == 8:
if self.chest >= 35:
shirt_id = 5772
else:
shirt_id = packet_enum.CreationLOT.SHIRT_MEDIUM_STONE_GRAY.value
elif self.chest_color == 9:
if self.chest >= 35:
shirt_id = 5778
else:
shirt_id = packet_enum.CreationLOT.SHIRT_REDDISH_BROWN.value
elif self.chest_color == 10:
if self.chest >= 35:
shirt_id = 5784
else:
shirt_id = packet_enum.CreationLOT.SHIRT_WHITE.value
elif self.chest_color == 11:
if self.chest >= 35:
shirt_id = 5802
else:
shirt_id = packet_enum.CreationLOT.SHIRT_MEDIUM_BLUE.value
elif self.chest_color == 13:
if self.chest >= 35:
shirt_id = 5796
else:
shirt_id = packet_enum.CreationLOT.SHIRT_DARK_RED.value
elif self.chest_color == 14:
if self.chest >= 35:
shirt_id = 5802
else:
shirt_id = packet_enum.CreationLOT.SHIRT_EARTH_BLUE.value
elif self.chest_color == 15:
if self.chest >= 35:
shirt_id = 5808
else:
shirt_id = packet_enum.CreationLOT.SHIRT_EARTH_GREEN.value
elif self.chest_color == 16:
if self.chest >= 35:
shirt_id = 5814
else:
shirt_id = packet_enum.CreationLOT.SHIRT_BRICK_YELLOW.value
elif self.chest_color == 84:
if self.chest >= 35:
shirt_id = 5820
else:
shirt_id = packet_enum.CreationLOT.SHIRT_SAND_BLUE.value
elif self.chest_color == 96:
if self.chest >= 35:
shirt_id = 5826
else:
shirt_id = packet_enum.CreationLOT.SHIRT_SAND_GREEN.value
if self.chest >= 35:
final_shirt_id = shirt_id + (self.chest - 35)
else:
final_shirt_id = shirt_id + (self.chest - 1)
if self.legs == 0:
pants_id = packet_enum.CreationLOT.PANTS_BRIGHT_RED.value
elif self.legs == 1:
pants_id = packet_enum.CreationLOT.PANTS_BRIGHT_BLUE.value
elif self.legs == 3:
pants_id = packet_enum.CreationLOT.PANTS_DARK_GREEN.value
elif self.legs == 5:
pants_id = packet_enum.CreationLOT.PANTS_BRIGHT_ORANGE.value
elif self.legs == 6:
pants_id = packet_enum.CreationLOT.PANTS_BLACK.value
elif self.legs == 7:
pants_id = packet_enum.CreationLOT.PANTS_DARK_STONE_GRAY.value
elif self.legs == 8:
pants_id = packet_enum.CreationLOT.PANTS_MEDIUM_STONE_GRAY.value
elif self.legs == 9:
pants_id = packet_enum.CreationLOT.PANTS_REDDISH_BROWN.value
elif self.legs == 10:
pants_id = packet_enum.CreationLOT.PANTS_WHITE.value
elif self.legs == 11:
pants_id = packet_enum.CreationLOT.PANTS_MEDIUM_BLUE.value
elif self.legs == 13:
pants_id = packet_enum.CreationLOT.PANTS_DARK_RED.value
elif self.legs == 14:
pants_id = packet_enum.CreationLOT.PANTS_EARTH_BLUE.value
elif self.legs == 15:
pants_id = packet_enum.CreationLOT.PANTS_EARTH_GREEN.value
elif self.legs == 16:
pants_id = packet_enum.CreationLOT.PANTS_BRICK_YELLOW.value
elif self.legs == 84:
pants_id = packet_enum.CreationLOT.PANTS_SAND_BLUE.value
elif self.legs == 96:
pants_id = packet_enum.CreationLOT.PANTS_SAND_GREEN.value
else:
pants_id = 2508
char.equipped_items.append(pants_id)
char.equipped_items.append(final_shirt_id)
return char
class JoinWorldPacket(bitstream.Serializable):
"""
[53-04-00-04]
This packet is sent when a user clicks play.
"""
def __init__(self):
self.object_id = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = JoinWorldPacket()
packet.object_id = stream.read(bitstream.c_int64)
return packet
class CharacterDeleteRequestPacket(bitstream.Serializable):
"""
[53-04-00-06]
This packet is sent when a user deletes a character.
"""
def __init__(self):
self.object_id = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = CharacterDeleteRequestPacket()
packet.object_id = stream.read(bitstream.c_int64)
return packet
class CharacterRenameRequestPacket(bitstream.Serializable):
"""
[53-04-00-07]
This packet is sent when a user attempts to rename their character.
"""
def __init__(self):
self.object_id = 0
self.new_name = ""
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = CharacterRenameRequestPacket()
packet.object_id = stream.read(bitstream.c_int64)
packet.new_name = stream.read(str, allocated_length=33)
return packet
class ClientLoadCompletePacket(bitstream.Serializable):
"""
[53-04-00-13]
This packet is sent when the client is finished loading.
"""
def __init__(self):
self.zone_id = 0
self.map_instance = 0
self.map_clone = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
raise Exception("This Serializable can only deserialize")
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = ClientLoadCompletePacket()
packet.zone_id = stream.read(bitstream.c_uint16)
packet.map_instance = stream.read(bitstream.c_uint16)
packet.map_clone = stream.read(bitstream.c_uint32)
return packet

View File

@@ -0,0 +1,72 @@
"""
Contains all the packets which are sent by either the client or server
"""
from pyraknet import bitstream
class HandshakePacket(bitstream.Serializable):
"""
[53-00-00-00]
Global handshake packet serializable.
This packet is sent to establish a connection.
"""
def __init__(self):
self.game_version = 171022
self.unknown_0 = 0x93
self.remote_connection_type = 0 # For auth this is 1, otherwise it is 4
self.process_id = 1124
self.local_port = 0xff
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint32(self.game_version))
stream.write(bitstream.c_uint32(self.unknown_0))
stream.write(bitstream.c_uint32(self.remote_connection_type))
stream.write(bitstream.c_uint32(self.process_id))
stream.write(bitstream.c_uint16(self.local_port))
stream.write("127.0.0.1", allocated_length=33)
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = HandshakePacket()
packet.game_version = stream.read(bitstream.c_uint32)
packet.unknown_0 = stream.read(bitstream.c_uint32)
packet.remote_connection_type = stream.read(bitstream.c_uint32)
packet.process_id = stream.read(bitstream.c_uint32)
packet.local_port = stream.read(bitstream.c_uint16)
return packet
class DisconnectNotifyPacket(bitstream.Serializable):
"""
[53-00-00-01]
This packet is sent when the server and client disconnect from each other
"""
def __init__(self):
self.disconnect_id = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint32(self.disconnect_id))
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = DisconnectNotifyPacket()
packet.disconnect_id = stream.read(bitstream.c_uint32)
return packet
class GeneralNotifyPacket(bitstream.Serializable):
"""
[53-00-00-02]
This packet is sent to notify the player?
"""
def __init__(self):
self.notify_id = 0
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint32(self.notify_id))
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
packet = GeneralNotifyPacket()
packet.notify_id = stream.read(bitstream.c_uint32)
return packet

View File

@@ -0,0 +1,192 @@
from pyraknet import bitstream
import random
import sqlite3
from xml.etree import ElementTree
class CString(bitstream.Serializable):
def __init__(self, data='', allocated_length=None, length_type=None):
self.data = data
self.allocated_length = allocated_length
self.length_type = length_type
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(self.data if isinstance(self.data, bytes) else bytes(self.data, 'latin1'),
allocated_length=self.allocated_length, length_type=self.length_type)
def deserialize(self, stream: bitstream.ReadStream):
return stream.read(bytes, allocated_length=self.allocated_length, length_type=self.length_type).decode('latin1')
class LwoObjID:
"""
This is the data type that object ids are made out of.
They are different from normal 64 bit ints because they have flags that must be set.
"""
@classmethod
def gen_lwoobjid(cls, persistent: bool = False, client: bool = False, spawned: bool = False,
character: bool = False):
number = random.randrange(0, (2**32) - 1)
number = number | (int(persistent) << 32)
number = number | (int(client) << 46)
number = number | (int(spawned) << 58)
number = number | (int(character) << 60)
return number
class LDF(bitstream.Serializable):
"""
Lego Data Format
"""
def __init__(self):
self._keys: list = []
def register_key(self, key_name: str, value: any, value_type: int):
self._keys.append([key_name, value, value_type])
def serialize(self, stream: bitstream.WriteStream) -> None:
key_num = len(self._keys)
stream.write(bitstream.c_uint(key_num))
for key in self._keys:
name = key[0]
value = key[1]
value_type = key[2]
stream.write(bitstream.c_uint8(len(name) * 2))
for char in name:
stream.write(char.encode('latin1'))
stream.write(b'\0')
stream.write(bitstream.c_ubyte(value_type))
if value_type == 0:
stream.write(value, length_type=bitstream.c_uint)
elif value_type == 1:
stream.write(bitstream.c_int(value))
elif value_type == 3:
stream.write(bitstream.c_float(value))
elif value_type == 5:
stream.write(bitstream.c_uint(value))
elif value_type == 7:
stream.write(bitstream.c_bool(value))
elif value_type == 8 or value_type == 9:
stream.write(bitstream.c_int64(value))
elif value_type == 13:
xml_str = bytes(ElementTree.tostring(value))
xml_str = b'<?xml version="1.0">' + xml_str
stream.write(bitstream.c_ulong(xml_str.__len__()))
stream.write(xml_str)
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This struct cannot be deserialized")
class LoginCharacter(bitstream.Serializable):
"""
This is a serializable that creates the struct which is repeated in the minfigure list packet
"""
def __init__(self):
self.object_id = 1124
self.current_name = ""
self.unapproved_name = ""
self.name_rejected = False
self.is_ftp = False
self.head_color = 0
self.head = 0
self.chest_color = 0
self.chest = 0
self.legs = 0
self.hair_style = 0
self.hair_color = 0
self.left_hand = 0
self.right_hand = 0
self.eyebrows_style = 0
self.eyes_style = 0
self.mouth_style = 0
self.last_zone = 0
self.last_map_instance = 0
self.last_map_clone = 0
self.equipped_items = []
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This struct cannot be deserialized")
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint64(self.object_id))
stream.write(bitstream.c_uint32(0))
stream.write(self.current_name, allocated_length=33)
stream.write(self.unapproved_name, allocated_length=33)
stream.write(bitstream.c_bool(self.name_rejected))
stream.write(bitstream.c_bool(self.is_ftp))
stream.write(bitstream.c_uint32(self.head_color))
stream.write(bitstream.c_uint16(0))
stream.write(bitstream.c_uint32(self.head))
stream.write(bitstream.c_uint32(self.chest_color))
stream.write(bitstream.c_uint32(self.chest))
stream.write(bitstream.c_uint32(self.legs))
stream.write(bitstream.c_uint32(self.hair_style))
stream.write(bitstream.c_uint32(self.hair_color))
stream.write(bitstream.c_uint32(self.left_hand))
stream.write(bitstream.c_uint32(self.right_hand))
stream.write(bitstream.c_uint32(self.eyebrows_style))
stream.write(bitstream.c_uint32(self.eyes_style))
stream.write(bitstream.c_uint32(self.mouth_style))
stream.write(bitstream.c_uint32(0))
stream.write(bitstream.c_uint16(self.last_zone))
stream.write(bitstream.c_uint16(self.last_map_instance))
stream.write(bitstream.c_uint32(self.last_map_clone))
stream.write(bitstream.c_uint64(0))
stream.write(bitstream.c_uint16(len(self.equipped_items)))
for item in self.equipped_items:
stream.write(bitstream.c_uint32(item))
# For testing just use lot 6010
@classmethod
def from_cdclient(cls, lot: int):
char = LoginCharacter()
conn = sqlite3.connect("./res/cdclient.sqlite")
c = conn.cursor()
c.execute("SELECT displayName FROM Objects WHERE id = ?", (lot,))
char.current_name = c.fetchone()[0].split("-")[0]
c.execute("SELECT component_type, component_id FROM ComponentsRegistry WHERE id = ?", (lot,))
components = c.fetchall()
for comp in components:
if comp[0] == 17:
c.execute("SELECT itemid FROM InventoryComponent WHERE id = ?", (comp[1],))
items = c.fetchall()
equipped = []
for i in items:
equipped.append(i[0])
char.equipped_items = equipped
elif comp[0] == 35:
c.execute("SELECT * FROM MinifigComponent WHERE id = ?", (comp[1],))
minifig_comp = c.fetchone()
char.head = minifig_comp[1]
char.chest_color = minifig_comp[6]
char.legs = minifig_comp[3]
char.hair_style = minifig_comp[4]
char.hair_color = minifig_comp[5]
char.chest = minifig_comp[2]
char.head_color = minifig_comp[7]
char.left_hand = minifig_comp[8]
char.right_hand = minifig_comp[9]
char.eyebrows_style = minifig_comp[10]
char.eyes_style = minifig_comp[11]
char.mouth_style = minifig_comp[12]
conn.close()
return char
def save_to_db(self, account_id, connection):
c = connection.cursor()
c.execute("INSERT INTO wlus.character (character_id, current_name, requested_name, head_color,"
" head, chest_color, chest, legs, hair_style, hair_color, left_hand, right_hand,"
" eyebrow_style, eye_style, mouth_style, account_id) VALUES (%s, %s, %s, %s, %s, %s, %s, "
"%s, %s, %s, %s, %s, %s, %s, %s, %s)", (self.object_id, self.current_name, self.unapproved_name,
self.head_color, self.head, self.chest_color, self.chest,
self.legs, self.hair_style, self.hair_color, self.left_hand,
self.right_hand, self.eyebrows_style, self.eyes_style,
self.mouth_style, account_id))
for i in range(len(self.equipped_items)):
item_id = LwoObjID.gen_lwoobjid()
c.execute("INSERT INTO wlus.inventory (object_id, lot, slot, equipped, linked, quantity, player_id)"
"VALUES (%s, %s, %s, 1, 1, 1, %s)", (item_id, self.equipped_items[i], i, self.object_id))
connection.commit()

View File

@@ -0,0 +1,97 @@
"""
Contains all enums related to packets.
"""
from enum import Enum, IntEnum
class PacketHeader(Enum):
"""
Contains the headers for packets.
"""
HANDSHAKE = b'S\x00\x00\x00\x00\x00\x00\x00'
DISCONNECT_NOTIFY = b"S\x00\x00\x01\x00\x00\x00\x00"
CLIENT_LOGIN_INFO = b'S\x01\x00\x00\x00\x00\x00\x00'
LOGIN_RESPONSE = b'S\x05\x00\x00\x00\x00\x00\x00'
CLIENT_USER_SESSION_INFO = b"S\x04\x00\x01\x00\x00\x00\x00"
CLIENT_MINIFIGURE_LIST_REQUEST = b"S\x04\x00\x02\x00\x00\x00\x00"
MINIFIGURE_LIST = b"S\x05\x00\x06\x00\x00\x00\x00"
CLIENT_MINIFIGURE_CREATE_REQUEST = b"S\x04\x00\x03\x00\x00\x00\x00"
MINIFIGURE_CREATION_RESPONSE = b"S\x05\x00\x08\x00\x00\x00\x00"
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'
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'
SERVER_GAME_MESSAGE = b'S\x05\x00\x0c\x00\x00\x00\x00'
CLIENT_POSITION_UPDATES = b'S\x04\x00\x16\x00\x00\x00\x00'
CLIENT_CHAT_MESSAGE = b'S\x04\x00\x0e\x00\x00\x00\x00'
CLIENT_WHITELIST_REQUEST = b'S\x04\x00\x19\x00\x00\x00\x00'
CHAT_MODERATION_RESPONSE = b'S\x05\x00\x3b\x00\x00\x00\x00'
class DisconnectionNotify(IntEnum):
"""
Contains various reasons for disconnect notify.
"""
UNKNOWN_ERROR = 0x00
DUPLICATE_LOGIN = 0x04
SERVER_SHUTDOWN = 0x05
SERVER_CANNOT_LOAD_MAP = 0x06
INVALID_SESSION_KEY = 0x07
CHARACTER_NOT_FOUND = 0x09
CHARACTER_CORRUPTION = 0x0a
KICKED = 0x0b
class LoginReturnCode(IntEnum):
SUCCESS = 0x01
BANNED = 0x02
INVALID_PERM = 0x03
INVALID_LOGIN_INFO = 0x06
ACCOUNT_LOCKED = 0x07
class ObjectFlag(IntEnum):
OBJECT_BIT_PERSISTENT = 32
OBJECT_BIT_CLIENT = 46
OBJECT_BIT_SPAWNED = 58
OBJECT_BIT_CHARACTER = 60
class CreationLOT(IntEnum):
SHIRT_BRIGHT_RED = 4049
SHIRT_BRIGHT_BLUE = 4083
SHIRT_BRIGHT_YELLOW = 4117
SHIRT_DARK_GREEN = 4151
SHIRT_BRIGHT_ORANGE = 4185
SHIRT_BLACK = 4219
SHIRT_DARK_STONE_GRAY = 4253
SHIRT_MEDIUM_STONE_GRAY = 4287
SHIRT_REDDISH_BROWN = 4321
SHIRT_WHITE = 4355
SHIRT_MEDIUM_BLUE = 4389
SHIRT_DARK_RED = 4423
SHIRT_EARTH_BLUE = 4457
SHIRT_EARTH_GREEN = 4491
SHIRT_BRICK_YELLOW = 4525
SHIRT_SAND_BLUE = 4559
SHIRT_SAND_GREEN = 4593
PANTS_BRIGHT_RED = 2508
PANTS_BRIGHT_ORANGE = 2509
PANTS_BRICK_YELLOW = 2511
PANTS_MEDIUM_BLUE = 2513
PANTS_SAND_GREEN = 2514
PANTS_DARK_GREEN = 2515
PANTS_EARTH_GREEN = 2516
PANTS_EARTH_BLUE = 2517
PANTS_BRIGHT_BLUE = 2519
PANTS_SAND_BLUE = 2520
PANTS_DARK_STONE_GRAY = 2521
PANTS_MEDIUM_STONE_GRAY = 2522
PANTS_WHITE = 2523
PANTS_BLACK = 2524
PANTS_REDDISH_BROWN = 2526
PANTS_DARK_RED = 2527

View File

@@ -0,0 +1,7 @@
{
"name": "Serializables Module",
"id": "serializables",
"description": "Module for various serializable types.",
"type": "module",
"dependencies": []
}

View File

@@ -0,0 +1,26 @@
"""
This file contains all of the replica components and the structs withing them
"""
from pyraknet import bitstream
class BaseDataComponent(bitstream.Serializable):
"""
Base Data should be supplied with every replica.
replica_mode refers to whether or not it is construction, serialization or destruction.
Construction - 0
Serialization - 1
Destruction - 2
"""
def __init__(self, replica_mode: int = 0):
self.replica_mode = replica_mode
self.object_id = 0
self.lot = 0
self.name = ""
self.time_since_created = 0
self.has_trigger = False
self.spawner_id = 0
self.spawner_node_id = 0
self.scale = 1
self.object_world_state = 0
self.gm_level = 0

View File

@@ -0,0 +1,65 @@
"""
Contains all the packets that the world/char server would send to the client
"""
from pyraknet import bitstream
class MinfigureListPacket(bitstream.Serializable):
"""
[53-05-00-06]
This sends all of the characters to the client.
"""
def __init__(self):
self.current_index = 0
self.minifigs = []
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This packet cannot be deserialized")
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint8(len(self.minifigs)))
stream.write(bitstream.c_uint8(self.current_index))
for m in self.minifigs:
stream.write(m)
class MinifigureCreationResponsePacket(bitstream.Serializable):
"""
[53-05-00-07]
Lets the client know how the creation process was handled.
"""
def __init__(self):
self.response = 0x00
@classmethod
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This packet cannot be deserialized")
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(bitstream.c_uint8(self.response))
class RedirectiontoNewServerPacket(bitstream.Serializable):
"""
[53-05-00-0e]
This packet redirects the client to connect to a new server.
If worlds are hosted on separate servers, send this packet and
let the other server handle the load world packet. It would
probably be best if the other server sent the load world on
handshake - because when would there be a connection which wasn't
trying to load in the world.
"""
def __init__(self):
self.redirect_ip = "127.0.0.1"
self.redirect_port = 1124
self.is_mythran_dimension_shift = False
def deserialize(cls, stream: bitstream.ReadStream) -> bitstream.Serializable:
raise Exception("This packet cannot be deserialized")
def serialize(self, stream: bitstream.WriteStream) -> None:
stream.write(self.redirect_ip, allocated_length=33)
stream.write(bitstream.c_uint16(self.redirect_port))
stream.write(bitstream.c_bool(self.is_mythran_dimension_shift))

View File

@@ -1,6 +0,0 @@
<60>
[bit] - {replica.has_component(components.BaseCombatAI)}
{%if previous == True%}
[u32] - {replica.get_component(components.BaseCombatAI).action}
[s64] - {replica.get_component(components.BaseCombatAI).target_id}
{%end%}

View File

@@ -1,5 +0,0 @@
<6>
[bit] - {False}
{%if previous == True%}
[bit] - {True}#This is apparently "PetNotRequired" but I don't really care about pet bouncers right now
{%end%}

View File

@@ -1,99 +0,0 @@
<4>
{character = replica.get_component(components.Character)}
{player, account = character.get_player_info()}
{minifig_comp = replica.get_component(components.Minifig)}
{stats = player["Stats"]}
[bit] - {character.vehicle_id != 0}
{%if previous == True%}
[bit] - {True}
[s64] - {character.vehicle_id}
[u8] - {0}
{%end%}
[bit] - {True}
[u32] - {player["Data"]["level"]}
[bit] - {False}
#[bit] - ???
#[bit] - ???
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[u64] - ???, could be "co" from xml data
[bit] - {False}
#[u64] - ???
[bit] - {False}
#[u64] - ???
[bit] - {False}
#[u64] - ???
{%if minifig_comp is not None%}
[u32] - {minifig_comp.hair_color}
[u32] - {minifig_comp.hair_style}
[u32] - {0}
[u32] - {minifig_comp.chest}
[u32] - {minifig_comp.legs}
[u32] - {0}
[u32] - {0}
[u32] - {minifig_comp.eyebrows}
[u32] - {minifig_comp.eyes}
[u32] - {minifig_comp.mouth}
{%end%}
{%else%}
[u32] - {player["hair_color"]}
[u32] - {player["hair_style"]}
[u32] - {0}
[u32] - {player["shirt_color"]}
[u32] - {player["pants_color"]}
[u32] - {0}
[u32] - {0}
[u32] - {player["eyebrows"]}
[u32] - {player["eyes"]}
[u32] - {player["mouth"]}
{%end%}
[u64] - {player["account_id"]}
[u64] - {0}
[u64] - {0}
[u64] - {player["Data"]["universe_score"]}
[bit] - {False}
[u64] - {stats["currency_collected"]}
[u64] - {stats["bricks_collected"]}
[u64] - {stats["smashables_smashed"]}
[u64] - {stats["quick_builds_done"]}
[u64] - {stats["enemies_smashed"]}
[u64] - {stats["rockets_used"]}
[u64] - {len(player["CompletedMissions"])}
[u64] - {stats["pets_tamed"]}
[u64] - {stats["imagination_collected"]}
[u64] - {stats["health_collected"]}
[u64] - {stats["armor_collected"]}
[u64] - {stats["distance_traveled"]}
[u64] - {stats["times_died"]}
[u64] - {stats["damage_taken"]}
[u64] - {stats["damage_healed"]}
[u64] - {stats["armor_repaired"]}
[u64] - {stats["imagination_restored"]}
[u64] - {stats["imagination_used"]}
[u64] - {stats["distance_driven"]}
[u64] - {stats["time_airborne_in_car"]}
[u64] - {stats["racing_imagination_collected"]}
[u64] - {stats["racing_imagination_crates_smashed"]}
[u64] - {stats["race_car_boosts"]}
[u64] - {stats["car_wrecks"]}
[u64] - {stats["racing_smashables_smashed"]}
[u64] - {stats["races_finished"]}
[u64] - {stats["races_won"]}
[bit] - {False}
[bit] - {False}#This needs to be implemented for rockets
#[u16-wstring] - LDF info of rocket modules
{%end%}
[bit] - {True}
[bit] - {replica.zone.pvp_enabled}
[bit] - {False}
[u8] - {character.gm_level}
[bit] - {False}
[u8] - {0}
[bit] - {True}
[u32] - {character.head_glow}
[bit] - {False}
#TODO: Implement Guilds
#[s64] - guild (leader?) id, assert == 0
#[u8-wstring] - guild name, assert == ""
#[bit] - ???
#[s32] - ???

View File

@@ -1 +0,0 @@
[u16] - {replica.get_component(components.Collectible).collectible_id}

View File

@@ -1,3 +0,0 @@
<107>
[bit] - {False}
#[s64] - ???

View File

@@ -1,8 +0,0 @@
<108>
[bit] - {False}
#[bit] - flag
#[s64] - driver object id
#[bit] - flag
#[u32] - possessable component id?
#[bit] - ???
#I should Implement this eventually

View File

@@ -1,60 +0,0 @@
<1>
{transform = replica.get_component(components.Transform)}
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[u32] - jetpack effect id
#[bit] - ???
#[bit] - ???
[bit] - {False}
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - ???
{%end%}
[bit] - {False}
#[float] - ???
#[float] - ???
[bit] - {False}
#[float] - ???
#[bit] - ???
[bit] - {False}
#[bit] - flag
#[u32] - ???
#[bit] - ???
[bit] - {True}
[float] - {transform.position.X}
[float] - {transform.position.Y}
[float] - {transform.position.Z}
[float] - {transform.rotation.X}
[float] - {transform.rotation.Y}
[float] - {transform.rotation.Z}
[float] - {transform.rotation.W}
[bit] - {transform.on_ground}
[bit] - {False}#On Rail
[bit] - {transform.velocity != game_types.Vector3(0.0, 0.0, 0.0)}
{%if previous == True%}
[float] - {transform.velocity.X}
[float] - {transform.velocity.Y}
[float] - {transform.velocity.Z}
{%end%}
[bit] - {transform.angular_velocity != game_types.Vector3(0.0, 0.0, 0.0)}
{%if previous == True%}
[float] - {transform.angular_velocity.X}
[float] - {transform.angular_velocity.Y}
[float] - {transform.angular_velocity.Z}
{%end%}
[bit] - {False}
#[s64] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[bit] - flag
#[float] - ???
#[float] - ???
#[float] - ???
{%if replica_type != game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
{%end%}

View File

@@ -1,39 +0,0 @@
<7>
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[u32] - count for following structs
#[u32] - ???
#[bit] - flag
#[u32] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#trigger=[bit] - ???, seems to trigger [s64] below?
#[bit] - ???
#if trigger:
#[s64] - ???
#[u32] - ???
[bit] - {False}
#[u32] - count for following structs
#[u32] - ???
#[bit] - flag
#[u32] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#[bit] - ???
#trigger=[bit] - ???, seems to trigger [s64] below?
#[bit] - ???
#if trigger:
#[s64] - ???
#[u32] - ???
{%end%}

View File

@@ -1,4 +0,0 @@
Exhibit ($+863790):
[bit] - {False}
#[s32] - exhibited LOT
#Should be in replica.get_component(components.LUPExhibit) but I won't implement that right now

View File

@@ -1,47 +0,0 @@
<17>
{inventory = replica.get_component(components.Inventory)}
{%if game.get_service("Player").get_player_by_id(int(replica.get_object_id())) is None%}
[bit] - {True}
[u32] - {len(inventory.items)}
{%for item in inventory.items%}
[s64] - {item["item_id"]}
[lot] - {item["lot"]}
[bit] - {False}
#[s64] - ???
[bit] - {True}
[u32] - {item["quantity"]}
[bit] - {True}
[u16] - {item["slot"]}
[bit] - {False}
#[u32] - inventory type?, expect == 4
[bit] - {False}
#[compressed_ldf] - extra data
#Should Probably Implement this
[bit] - {True}
{%end%}
[bit] - {False}
#[u32] - ???, assert == 0
{%end%}
{%else%}
{player_items = game.get_service("Player").get_equipped_items(int(replica.get_object_id()))}
[bit] - {True}
[u32] - {len(player_items)}
{%for item in player_items%}
[s64] - {item["item_id"]}
[lot] - {item["lot"]}
[bit] - {False}
#[s64] - ???
[bit] - {True}
[u32] - {item["quantity"]}
[bit] - {True}
[u16] - {item["slot"]}
[bit] - {False}
#[u32] - inventory type?, expect == 4
[bit] - {False}
#[compressed_ldf] - extra data
#Should Probably Implement this
[bit] - {True}
{%end%}
[bit] - {False}
#[u32] - ???, assert == 0
{%end%}

View File

@@ -1,9 +0,0 @@
<61>
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[bit] - flag
#[s64] - ???
#[bit] - ???
#[u16-wstring] - ???
{%end%}
#Need to implement

View File

@@ -1,41 +0,0 @@
<25>
[bit] - {False}
[bit] - {False}
#[bit] - ???
#[u16-wstring] - path name
#[u32] - ???
#[bit] - ???
#if flag:#(First Flag)
#[bit] - ???
#subcomponent_type=[u32] - subcomponent type, 4 - mover, 5 - simple mover?, expect in (4, 5)
#if subcomponent_type == 4:
#[bit] - ???
#[u32] - state
#[s32] - ???
#[bit] - ???
#[bit] - based on this and some other criteria some other things are also included?
#[float] - ???
#[float] - unexpected position x
#[float] - unexpected position y
#[float] - unexpected position z
#[u32] - current waypoint index
#[u32] - next waypoint index
#[float] - idle time elapsed
#[u32] - ???
#if subcomponent_type == 5:
#[bit] - flag
#[bit] - flag
#[float] - position x?
#[float] - position y?
#[float] - position z?
#[float] - rotation x?
#[float] - rotation y?
#[float] - rotation z?
#[float] - rotation w?
#[bit] - flag
#[u32] - ???
#[u32] - ???
#[bit] - ???

View File

@@ -1,13 +0,0 @@
<26>
[bit] - {False}
#[u32] - ???
#[u32] - ???
#[bit] - flag, expect == False
#[s64] - ???
#[bit] - flag, expect == False
#[s64] - ???
#[bit] - flag, expect == False
#[u32] - ???
#[u8-wstring] - pet name
#[u8-wstring] - pet owner name
#Need to implement

View File

@@ -1,22 +0,0 @@
<40>
{transform = replica.get_component(components.Transform)}
[bit] - {True}
[float] - {transform.position.X}
[float] - {transform.position.Y}
[float] - {transform.position.Z}
[float] - {transform.rotation.X}
[float] - {transform.rotation.Y}
[float] - {transform.rotation.Z}
[float] - {transform.rotation.W}
[bit] - {False}
#[bit] - is physics effect active
#[u32] - effect type, 0 = push, 1 = attract, 2 = repulse, 3 = gravity, 4 = friction
#[float] - effect amount
#[bit] - flag
#[u32] - ???
#[u32] - ???
#[bit] - flag
#[float] - effect direction x
#[float] - effect direction y
#[float] - effect direction z
#I do already have the physics effect component but this is just a quick implementation for now

View File

@@ -1,41 +0,0 @@
<71>
[bit] - {False}
#[u32] - count
#[u64] - player object id
#constant size 10 loop
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
[bit] - {False}
#[u16] - ???
[bit] - {False}
#while True:
#not_break=[bit] - flag
#if not not_break:
#break
#[s64] - player object id
#[s64] - car object id
#[u32] - ???
#[bit] - ???
[bit] - {False}
#while True:
#not_break=[bit] - flag
#if not not_break:
#break
#[s64] - player object id
#[u32] - ???
[bit] - {False}
#[u16] - remaining laps?
#[u16-wstring] - path name
[bit] - {False}
#[bit] - flag
#[s64] - ???
#[float] - ???
#[float] - ???

View File

@@ -1,28 +0,0 @@
[bit] - {False}
#[u32] - count
#[u64] - player object id
#constant size 10 loop
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#end of ScriptedActivity
[bit] - {False}
#[u32] - rebuild state
#[bit] - success
#[bit] - enabled
#[float] - rebuild time
#[float] - a time related to paused rebuilds, expect == 0
#if creation:
#[bit] - ???
#[u32] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[bit] - ???

View File

@@ -1,10 +0,0 @@
<2>
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[s32] - {0}
#[u8-string] - effect name
#[s32] - effectID
#[u8-wstring] - effectType
#[float] - scale or priority?
#[s64] - secondary?
{%end%}
#Should probably implement this soon

View File

@@ -1,10 +0,0 @@
<20>
{transform = replica.get_component(components.Transform)}
[bit] - {True}
[float] - {transform.position.X}
[float] - {transform.position.Y}
[float] - {transform.position.Z}
[float] - {transform.rotation.X}
[float] - {transform.rotation.Y}
[float] - {transform.rotation.Z}
[float] - {transform.rotation.W}

View File

@@ -1,5 +0,0 @@
<5>
{transform = replica.get_component(components.Transform)}
[bit] - {False}
#[compressed_ldf] - script variables
{%end%}

View File

@@ -1,15 +0,0 @@
<39>
[bit] - {False}
#[u32] - count
#[s64] - player object id
#constant size 10 loop
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???

View File

@@ -1,37 +0,0 @@
<19>
[bit] - {False}
#[u32] - count
#[s64] - player object id
#constant size 10 loop
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[float] - {0}
[float] - {0}
[float] - {0}
[float] - {0}
[float] - {0}
[float] - {0}
{%end%}
[bit] - {False}
#[double] - Cannon Velocity
#[double] - Cannon Refire Rate
#[double] - Cannon Min Distance
#[float] - Cannon Barrel Offset X
#[float] - Cannon Barrel Offset Y
#[float] - Cannon Barrel Offset Z
#[float] - Cannon Angle
#[float] - Facing X
#[float] - Facing Y
#[float] - Facing Z
#[u64] - ???
#[float] - ???, expect == -1
#[float] - Cannon FOV

View File

@@ -1,23 +0,0 @@
<3>
{transform = replica.get_component(components.Transform)}
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
[float] - {0}
{%end%}
[bit] - {False}
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[float] - ???
[bit] - {False}
#[u32] - ???, expect == 5
[bit] - {True}
[float] - {transform.position.X}
[float] - {transform.position.Y}
[float] - {transform.position.Z}
[float] - {transform.rotation.X}
[float] - {transform.rotation.Y}
[float] - {transform.rotation.Z}
[float] - {transform.rotation.W}

View File

@@ -1,21 +0,0 @@
<9>
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[u32] - count for following structs
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - ???
#[u32] - count for following structs
#[u32] - ???
#[u32] - ???, seems to be something in BehaviorTemplate?
#[u32] - ???
#[u32] - ???, expect == 18
#[s64] - ???
#[s64] - ???
#[s64] - ???, expect == 0
#[bit] - ???, assert == False
#[float] - ???, expect == 0
#[u32] - ???, expect == 0
#[u32] - ???, expect == 0
{%end%}

View File

@@ -1,42 +0,0 @@
{stats = replica.get_component(components.Stats)}
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
#[u32] - ???
#[u32] - is boss?, expect == 0
#Should Implement the boss thing soon
#[u32] - ???
#[u32] - ???
#[u32] - ???, expect == 0
#[u32] - ???, assert == 0
#[u32] - ???, assert == 0
#[u32] - ???
#[u32] - ???
{%end%}
[bit] - {True}
[u32] - {stats.health}
[float] - {stats.max_health}
[u32] - {stats.armor}
[float] - {stats.max_armor}
[u32] - {stats.imagination}
[float] - {stats.max_imagination}
[u32] - {0}
[bit] - {False}
[bit] - {False}
[bit] - {False}
[float] - {stats.max_health}
[float] - {stats.max_armor}
[float] - {stats.max_imagination}
[u32] - {1}
[s32] - {stats.faction}
[bit] - {stats.is_smashable}
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[bit] - {False}
[bit] - {False}
{%if stats.is_smashable == True%}
[bit] - {False}
[bit] - {False}
#[float] - ???
{%end%}
{%end%}
[bit] - {False}
#[bit] - ???

View File

@@ -1,2 +0,0 @@
<49>
[bit] - {replica.get_component(components.Switch).state}

View File

@@ -1,5 +0,0 @@
#Trigger Component
#Seems like this component is append when there is a trigger_id entry in the luz
#See also .lutriggers files in the client
[bit] - {False}
#[s32] - ???, expect == -1

View File

@@ -1,42 +0,0 @@
<30>
[bit] - {False}
#[float] - position x
#[float] - position y
#[float] - position z
#[float] - rotation x
#[float] - rotation y
#[float] - rotation z
#[float] - rotation w
#[bit] - is on ground
#[bit] - ???
#[bit] - flag
#[float] - velocity x
#[float] - velocity y
#[float] - velocity z
#[bit] - flag
#[float] - angular velocity x
#[float] - angular velocity y
#[float] - angular velocity z
#[bit] - flag
#[s64] - ???
#[float] - ???
#[float] - ???
#[float] - ???
#[bit] - flag
#[float] - ???
#[float] - ???
#[float] - ???
#[bit] - flag
#[float] - ???
#[float] - ???
#[bit] - ???
#[bit] - ???
#[float] - ???
#if not creation:
#[bit] - flag?
#if creation:
#[u8] - ???
#[bit] - ???
#[bit] - flag
#[bit] - ???

View File

@@ -1,4 +0,0 @@
<16>
[bit] - {False}
#[bit] - ???
#[bit] - ???

View File

@@ -1,31 +0,0 @@
{%if replica_type == game_enums.ReplicaTypes.CONSTRUCTION%}
[s64]-{replica.get_object_id()}
[s32]-{replica.lot}
[u8-wstring]-{replica.get_name()}
[u32]-{0}
[bit]-{replica.has_component(components.ModelData)}
{%if previous == True%}
[ldf]-{replica.get_component(components.ModelData).ldf}
{%end%}
[bit]-{replica.has_component(components.Trigger)}
[bit]-{replica.spawner_id is not None}
{%if previous == True%}
[s64]-{replica.spawner_id}
{%end%}
[bit]-{replica.spawner_node_id is not None}
{%if previous == True%}
[u32]-{replica.spawner_node_id}
{%end%}
[bit]-{replica.get_component(components.Transform).scale != 1}
{%if previous == True%}
[float]-{replica.get_component(components.Transform).scale}
{%end%}
[bit]-{False}
{%if previous == True%}
[u8]-{0}#ObjectWorldState
{%end%}
[bit]-{False}
{%if previous == True%}
[u8]-{0}#GMLevel
{%end%}
{%end%}

View File

@@ -1,8 +0,0 @@
[bit]-{False}
#[bit]-flag
#[object_id]-parent object id
#[bit]-???
#[bit]-flag
#[u16]-count
#[u64]-child object id
#I need to implement this but I'm just gonna be lazy for now

View File

@@ -1,343 +0,0 @@
import services
import game_objects
import game_types
import components
import game_enums
import re
from pyraknet.bitstream import *
class ReplicaService(services.GameService):
def __init__(self, parent):
super().__init__(parent)
self._name = "Replica"
global game
game = self.get_parent()
#Cached structs should give a boost to performance, the only reason it should really be disabled is if you are working on a replica component
self._cached_structs = {}
def initialize(self):
if(game.get_config("cache_structs") is not None and game.get_config("cache_structs") == True):
'''Theres probably a much better way to do this but I'm too lazy'''
self._cached_structs["replica/creation_header.structs"] = compile(self.parse_struct("replica/creation_header.structs"), '<string>', 'exec')
self._cached_structs["replica/serialization_header.structs"] = compile(self.parse_struct("replica/serialization_header.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Component 108.structs"] = compile(self.parse_struct("replica/components/Component 108.structs"), '<string>', 'exec')
self._cached_structs["replica/components/ModuleAssembly.structs"] = compile(self.parse_struct("replica/components/ModuleAssembly.structs"), '<string>', 'exec')
self._cached_structs["replica/components/ControllablePhysics.structs"] = compile(self.parse_struct("replica/components/ControllablePhysics.structs"), '<string>', 'exec')
self._cached_structs["replica/components/SimplePhysics.structs"] = compile(self.parse_struct("replica/components/SimplePhysics.structs"), '<string>', 'exec')
self._cached_structs["replica/components/RigidBodyPhantomPhysics.structs"] = compile(self.parse_struct("replica/components/RigidBodyPhantomPhysics.structs"), '<string>', 'exec')
self._cached_structs["replica/components/VehiclePhysics.structs"] = compile(self.parse_struct("replica/components/VehiclePhysics.structs"), '<string>', 'exec')
self._cached_structs["replica/components/PhantomPhysics.structs"] = compile(self.parse_struct("replica/components/PhantomPhysics.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Destructible.structs"] = compile(self.parse_struct("replica/components/Destructible.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Stats.structs"] = compile(self.parse_struct("replica/components/Stats.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Collectible.structs"] = compile(self.parse_struct("replica/components/Collectible.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Pet.structs"] = compile(self.parse_struct("replica/components/Pet.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Character.structs"] = compile(self.parse_struct("replica/components/Character.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Shooting Gallery.structs"] = compile(self.parse_struct("replica/components/Shooting Gallery.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Inventory.structs"] = compile(self.parse_struct("replica/components/Inventory.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Script.structs"] = compile(self.parse_struct("replica/components/Script.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Skill.structs"] = compile(self.parse_struct("replica/components/Skill.structs"), '<string>', 'exec')
self._cached_structs["replica/components/BaseCombatAI.structs"] = compile(self.parse_struct("replica/components/BaseCombatAI.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Rebuild.structs"] = compile(self.parse_struct("replica/components/Rebuild.structs"), '<string>', 'exec')
self._cached_structs["replica/components/MovingPlatform.structs"] = compile(self.parse_struct("replica/components/MovingPlatform.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Switch.structs"] = compile(self.parse_struct("replica/components/Switch.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Vendor.structs"] = compile(self.parse_struct("replica/components/Vendor.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Bouncer.structs"] = compile(self.parse_struct("replica/components/Bouncer.structs"), '<string>', 'exec')
self._cached_structs["replica/components/ScriptedActivity.structs"] = compile(self.parse_struct("replica/components/ScriptedActivity.structs"), '<string>', 'exec')
self._cached_structs["replica/components/RacingControl.structs"] = compile(self.parse_struct("replica/components/RacingControl.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Exhibit.structs"] = compile(self.parse_struct("replica/components/Exhibit.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Render.structs"] = compile(self.parse_struct("replica/components/Render.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Component 107.structs"] = compile(self.parse_struct("replica/components/Component 107.structs"), '<string>', 'exec')
self._cached_structs["replica/components/Trigger.structs"] = compile(self.parse_struct("replica/components/Trigger.structs"), '<string>', 'exec')
super().initialize()
def create_replica_object(self, parent, zone, config : dict):
if("lot" not in config):
raise Exception("'create_replica_object' Requires A LOT In The Conifg!")
replica = game_objects.ReplicaObject(parent, zone, config)
transform : components.Transform = replica.get_component(components.Transform)
if("position" in config):
if(not isinstance(config["position"], str)):
transform.position = config["position"]
else:
transform.position = game_types.Vector3(str_val=config["position"])
if("rotation" in config):
if (not isinstance(config["rotation"], str)):
transform.rotation = config["rotation"]
else:
transform.rotation = game_types.Vector4(str_val=config["rotation"])
if("scale" in config):
transform.scale = config["scale"]
cdclient_db = game.get_service("Database").cdclient_db
c = cdclient_db.connection.cursor()
c.execute("SELECT component_type, component_id FROM ComponentsRegistry WHERE id = ?", (config["lot"],))
component_list = c.fetchall()
object_components = {}
for component in component_list:
object_components[int(component["component_type"])] = int(component["component_id"])
if(108 in object_components):
possesable = components.Possessable(replica)
if("driver_object_id" in config):
possesable.driver_object_id = config["driver_object_id"]
replica.add_component(possesable)
if(61 in object_components):
module_assembly = components.ModuleAssembly(replica)
replica.add_component(module_assembly)
if(30 in object_components):
vehicle_physics = components.VehiclePhysics(replica)
replica.add_component(vehicle_physics)
if(7 in object_components):
destructible = components.Destructible(replica)
replica.add_component(destructible)
c.execute("SELECT * FROM DestructibleComponent WHERE id = ?", (object_components[7],))
destructible_data = c.fetchone()
stats = components.Stats(replica)
if(destructible_data["life"] is not None):
stats.health = int(destructible_data["life"])
stats.max_health = int(destructible_data["life"])
if(destructible_data["armor"] is not None):
stats.armor = int(destructible_data["armor"])
stats.max_armor = int(destructible_data["armor"])
if (destructible_data["imagination"] is not None):
stats.imagination = int(destructible_data["imagination"])
stats.max_imagination = int(destructible_data["imagination"])
if (destructible_data["faction"] is not None):
stats.faction = int(destructible_data["faction"])
if (destructible_data["isSmashable"] is not None):
stats.is_smashable = destructible_data["isSmashable"]
if("health" in config):
stats.health = config["health"]
if("max_health" in config):
stats.max_health = config["max_health"]
if("armor" in config):
stats.armor = config["armor"]
if("max_armor" in config):
stats.max_armor = config["max_armor"]
if("imagination" in config):
stats.imagination = config["imagination"]
if("max_imagination" in config):
stats.max_imagination = config["max_imagination"]
if("faction" in config):
stats.faction = config["faction"]
if("is_smashable" in config):
stats.is_smashable = config["is_smashable"]
replica.add_component(stats)
if(23 in object_components):
if(replica.get_component(components.Stats) is None):
stats = components.Stats(replica)
replica.add_component(stats)
collectible = components.Collectible(replica)
if("collectible_id" in config):
collectible.collectible_id = config["collectible_id"]
replica.add_component(collectible)
if(26 in object_components):
#TODO: Actually Implement The Config
pet = components.Pet(replica)
replica.add_component(pet)
if(4 in object_components):
character = components.Character(replica, replica.get_object_id())
replica.add_component(character)
if(17 in object_components):
if(game.get_service("Player").get_player_by_id(int(replica.get_object_id())) is None):
inventory = components.Inventory(replica)
c.execute("SELECT * FROM InventoryComponent WHERE id = ?", (object_components[17],))
db_items = c.fetchall()
for item in db_items:
new_item = {}
new_item["item_id"] = game.generate_object_id()
new_item["lot"] = item["itemid"]
new_item["quantity"] = item["count"]
new_item["equipped"] = item["equip"]
new_item["linked"] = 0
new_item["slot"] = 0
new_item["json"] = {"from_db":1}
inventory.add_item(new_item)
replica.add_component(inventory)
if(5 in object_components):
script_comp = components.ScriptComponent(replica)
replica.add_component(script_comp)
if(9 in object_components):
skill = components.Skill(replica)
replica.add_component(skill)
if(60 in object_components):
base_comabt_ai = components.BaseCombatAI(replica)
replica.add_component(base_comabt_ai)
if(48 in object_components):
rebuild = components.Rebuild(replica)
c.execute("SELECT * FROM RebuildComponent WHERE id = ?", (object_components[48],))
db_rebuild = c.fetchone()
rebuild.reset_time = float(db_rebuild["reset_time"])
if("build_activator_pos" in config):
rebuild.build_activator_pos = config["build_activator_pos"]
if("build_enabled" in config):
rebuild.enabled = config["build_enabled"]
replica.add_component(rebuild)
if(replica.get_component(components.Stats) is None):
stats = components.Stats(replica)
stats.imagination = int(db_rebuild["take_imagination"])
stats.max_imagination = int(db_rebuild["take_imagination"])
replica.add_component(stats)
if(25 in object_components):
moving_platform = components.MovingPlatform(replica)
replica.add_component(moving_platform)
if(49 in object_components):
switch = components.Switch(replica)
replica.add_component(switch)
if(16 in object_components):
vendor = components.Vendor(replica)
replica.add_component(vendor)
if(6 in object_components):
bouncer = components.Bouncer(replica)
replica.add_component(bouncer)
if(39 in object_components):
scripted_activity = components.ScriptedActivity(replica)
replica.add_component(scripted_activity)
if(71 in object_components):
racing_control = components.RacingControl(replica)
replica.add_component(racing_control)
if(75 in object_components):
exhibit = components.LUPExhibit(replica)
replica.add_component(exhibit)
if(2 in object_components):
render = components.Render(replica)
replica.add_component(render)
if(107 in object_components):
comp107 = components.Component107(replica)
replica.add_component(comp107)
if(69 in object_components):
trigger = components.Trigger(replica)
replica.add_component(trigger)
game.trigger_event("GeneratedReplica", args=[replica])
return replica
def parse_struct(self, file_path):
write_methods = {"bit":"c_bit", "float":"c_float", "double":"c_double", "s8":"c_int8", "u8":"c_uint8", "s16":"c_int16", "u16":"c_uint16", "s32":"c_int32", "u32":"c_uint32", "s64":"c_int64", "u64":"c_uint64",
"lot":"c_long"}
execute_string = ""
indent_level = 0
def format_line(string, indentation_level):
indent_string = ""
for i in range(indentation_level):
indent_string += " "
return indent_string + string + "\n"
with open(file_path, "r") as file:
for line in file:
line = line.split("#")[0]#Filter out comments
line = line.strip()
if(line[:1] == "["):#Line is trying to write something to the stream
data_type = line[line.find("[")+1:line.find("]")]
write_value = line[line.find("{")+1:line.find("}")]
write_str = ""
if(data_type in write_methods):
write_str = "stream.write({}({}))".format(write_methods[data_type], write_value)
else:
if(len(data_type.split("-")) == 2 and data_type.split("-")[1] == "string"):#If it says string at the start then write it via the String data type in game_types
write_str = "stream.write(game_types.String({}, length_type={}))".format(write_value, write_methods[data_type.split("-")[0]])
elif(len(data_type.split("-")) == 2 and data_type.split("-")[1] == "wstring"):
write_str = "stream.write({}, length_type={})".format(write_value, write_methods[data_type.split("-")[0]])
elif(len(data_type.split("-")) == 2 and data_type.split("-")[0] == "lwoobjectid"):
write_str = "stream.write(game_types.LwoObjectID({}, {}))".format(write_value, data_type.split("-")[1])
elif(data_type == "ldf"):
write_str = "stream.write({})".format(write_value)
execute_string += format_line(write_str, indent_level)
execute_string += format_line("previous = {}".format(write_value), indent_level)
elif(line[:2] == "{%"):#Line is setting a condition or ending one
conditional = line[line.find("{%")+2:line.find("%}")]
if(conditional == "end"):
indent_level -= 1
else:
execute_string += format_line(conditional+":", indent_level)
indent_level += 1
elif(line[:1] == "{"):
write_value = line[line.find("{")+1:line.find("}")]
execute_string += format_line(write_value, indent_level)
return execute_string
def _get_real_time(self, file_name):
return self.parse_struct(file_name)
def _get_from_cache(self, file_name):
return self._cached_structs[file_name]
def write_to_stream(self, replica : game_objects.ReplicaObject, stream, replica_type):
struct_method = self._get_real_time
if(game.get_config("cache_structs") is not None and game.get_config("cache_structs") == True):
struct_method = self._get_from_cache
exec(struct_method("replica/creation_header.structs"))
exec(struct_method("replica/serialization_header.structs"))
cdclient_db = game.get_service("Database").cdclient_db
c = cdclient_db.connection.cursor()
c.execute("SELECT component_type, component_id FROM ComponentsRegistry WHERE id = ?", (replica.lot,))
component_list = c.fetchall()
object_components = []
for component in component_list:
object_components.append(int(component["component_type"]))
if(108 in object_components):
exec(struct_method("replica/components/Component 108.structs"))
if(61 in object_components):
exec(struct_method("replica/components/ModuleAssembly.structs"))
if(1 in object_components):
exec(struct_method("replica/components/ControllablePhysics.structs"))
if(3 in object_components):
exec(struct_method("replica/components/SimplePhysics.structs"))
if(20 in object_components):
exec(struct_method("replica/components/RigidBodyPhantomPhysics.structs"))
if(30 in object_components):
exec(struct_method("replica/components/VehiclePhysics.structs"))
if(40 in object_components):
exec(struct_method("replica/components/PhantomPhysics.structs"))
if(7 in object_components):
exec(struct_method("replica/components/Destructible.structs"))
exec(struct_method("replica/components/Stats.structs"))
if(23 in object_components):
exec(struct_method("replica/components/Stats.structs"))
exec(struct_method("replica/components/Collectible.structs"))
if(26 in object_components):
exec(struct_method("replica/components/Pet.structs"))
if(4 in object_components):
exec(struct_method("replica/components/Character.structs"))
if(19 in object_components):
exec(struct_method("replica/components/Shooting Gallery.structs"))
if(17 in object_components):
exec(struct_method("replica/components/Inventory.structs"))
if(5 in object_components):
exec(struct_method("replica/components/Script.structs"))
if(9 in object_components):
exec(struct_method("replica/components/Skill.structs"))
if(60 in object_components):
exec(struct_method("replica/components/BaseCombatAI.structs"))
if(48 in object_components):
exec(struct_method("replica/components/Stats.structs"))
exec(struct_method("replica/components/Rebuild.structs"))
if(25 in object_components):
exec(struct_method("replica/components/MovingPlatform.structs"))
if(49 in object_components):
exec(struct_method("replica/components/Switch.structs"))
if(16 in object_components):
exec(struct_method("replica/components/Vendor.structs"))
if(6 in object_components):
exec(struct_method("replica/components/Bouncer.structs"))
if(39 in object_components):
exec(struct_method("replica/components/ScriptedActivity.structs"))
if(71 in object_components):
exec(struct_method("replica/components/RacingControl.structs"))
if(75 in object_components):
exec(struct_method("replica/components/Exhibit.structs"))
if(2 in object_components):
exec(struct_method("replica/components/Render.structs"))
if(107 in object_components):
exec(struct_method("replica/components/Component 107.structs"))
if(69 in object_components):
exec(struct_method("replica/components/Trigger.structs"))

View File

@@ -1 +1,3 @@
bcrypt
bcrypt
mysql-connector-python
hg+https://bitbucket.org/lcdr/pyraknet@4251284791e1476f29e51bbda44986e38a448aed

View File

@@ -1,7 +0,0 @@
#asset list
A:res\audio\NDAudio\Ambience\Ambience_Avant_Gardens\Ambience_Avant_Gardens_Streaming.fsb
A:res\audio\NDAudio\Ambience\Ambience_Avant_Gardens\Ambience_Avant_Gardens_Non-Streaming.fsb
A:res\audio\NDAudio\Ambience\Ambience_Avant_Gardens\Ambience_Avant_Gardens_2_Non-Streaming.fsb
A:res\audio\NDAudio\Music\Music_Global\Music_Global_Avant_Gardens_Streaming.fsb
A:res\audio\NDAudio\Music\Music_Global\Music_Global_Day1-Patch.fsb

View File

@@ -1,208 +0,0 @@
<?xml version="1.0" ?>
<!-- DO NOT EDIT THIS FILE -->
<envData>
<bindings>
<binding sceneID="1" configuration="Launch" />
<binding sceneID="2" configuration="Battlefield" />
<binding sceneID="3" configuration="Monument" />
<binding sceneID="4" configuration="Launch" />
<binding sceneID="5" configuration="Cave_To_Mon" />
<binding sceneID="6" configuration="Battlefield" />
<binding sceneID="7" configuration="Battlefield" />
<binding sceneID="8" configuration="Battlefield" />
<binding sceneID="9" configuration="Battlefield" />
<binding sceneID="10" configuration="Spider_Cave" />
<binding sceneID="11" configuration="Spider_Cave_Rear" />
<binding sceneID="12" configuration="SEN_Camp" />
<binding sceneID="13" configuration="Spider_Cave" />
<binding sceneID="14" configuration="Spider_Cave" />
<binding sceneID="15" configuration="Spider_Cave_Rear" />
<binding sceneID="16" configuration="Cave_To_Mon" />
<binding sceneID="17" configuration="Cave_To_Mon" />
<binding sceneID="18" configuration="Monument" />
<binding sceneID="19" configuration="Monument" />
<binding sceneID="20" configuration="Monument" />
<binding sceneID="21" configuration="Monument" />
<binding sceneID="22" configuration="Monument" />
<binding sceneID="23" configuration="Monument" />
<binding sceneID="24" configuration="Monument" />
<binding sceneID="25" configuration="Monument" />
<binding sceneID="26" configuration="Monument" />
<binding sceneID="27" configuration="Launch" />
<binding sceneID="28" configuration="Launch" />
<binding sceneID="29" configuration="Launch" />
<binding sceneID="30" configuration="Launch" />
<binding sceneID="35" configuration="Monument" />
<binding sceneID="37" configuration="Launch" />
<binding sceneID="38" configuration="Monument" />
<binding sceneID="40" configuration="Spider_Cave" />
</bindings>
<configuration name="Battlefield">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>0.788235,0.749020,0.698039</fogColor>
<maxDrawDistance fogFar="700" fogNear="100" postFogFade="100" postFogSolid="100" />
<minDrawDistance fogFar="300" fogNear="100" postFogFade="100" postFogSolid="80" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\env_sky_won_nim_landing.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="Cave_To_Mon">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>1.000000,1.000000,1.000000</fogColor>
<maxDrawDistance fogFar="300" fogNear="200" postFogFade="100" postFogSolid="100" />
<minDrawDistance fogFar="250" fogNear="100" postFogFade="50" postFogSolid="50" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\env_sky_won_nim_hills.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="Launch">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>0.564706,0.819608,0.901961</fogColor>
<maxDrawDistance fogFar="800" fogNear="300" postFogFade="100" postFogSolid="160" />
<minDrawDistance fogFar="750" fogNear="300" postFogFade="10" postFogSolid="10" />
<position>-0.48,209.00,230.00</position>
<skydomeFilename>mesh\env\env_sky_won_nim_landing.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="Monument">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>0.564706,0.819608,0.901961</fogColor>
<maxDrawDistance fogFar="400" fogNear="150" postFogFade="800" postFogSolid="160" />
<minDrawDistance fogFar="300" fogNear="150" postFogFade="700" postFogSolid="80" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\env_sky_won_nim_hills.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="SEN_Camp">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>0.784314,0.749020,0.694118</fogColor>
<maxDrawDistance fogFar="700" fogNear="100" postFogFade="100" postFogSolid="100" />
<minDrawDistance fogFar="250" fogNear="100" postFogFade="170" postFogSolid="70" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\env_sky_won_nim_landing.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="Spider_Cave">
<ambientLightColor>0.419608,0.619608,0.749020</ambientLightColor>
<directionalLightColor>1.000000,1.000000,1.000000</directionalLightColor>
<fogColor>0.788235,0.749020,0.698039</fogColor>
<maxDrawDistance fogFar="700" fogNear="100" postFogFade="100" postFogSolid="100" />
<minDrawDistance fogFar="250" fogNear="100" postFogFade="50" postFogSolid="50" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\env_sky_won_nim_hills.nif</skydomeFilename>
<specularLightColor>1.000000,1.000000,1.000000</specularLightColor>
<upperHemiColor>1.000000,1.000000,1.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
<configuration name="Spider_Cave_Rear">
<ambientLightColor>0.686275,0.686275,0.686275</ambientLightColor>
<directionalLightColor>0.000000,0.000000,0.000000</directionalLightColor>
<fogColor>0.000000,0.000000,0.000000</fogColor>
<maxDrawDistance fogFar="10000" fogNear="10000" postFogFade="10000" postFogSolid="1000" />
<minDrawDistance fogFar="10000" fogNear="100" postFogFade="50" postFogSolid="50" />
<position>-0.48,-0.86,-0.19</position>
<skydomeFilename>mesh\env\nexustower\env_sky_nx_towerblack.nif</skydomeFilename>
<specularLightColor>0.247059,0.474510,0.619608</specularLightColor>
<upperHemiColor>0.000000,0.000000,0.000000</upperHemiColor>
<cullSettings>
<cullData cullGroupID="0" cullMax="0" cullMin="0" />
<cullData cullGroupID="1" cullMax="150" cullMin="100" />
<cullData cullGroupID="2" cullMax="200" cullMin="150" />
<cullData cullGroupID="3" cullMax="250" cullMin="200" />
<cullData cullGroupID="4" cullMax="450" cullMin="350" />
<cullData cullGroupID="5" cullMax="100" cullMin="50" />
<cullData cullGroupID="6" cullMax="40" cullMin="40" />
<cullData cullGroupID="7" cullMax="600" cullMin="400" />
<cullData cullGroupID="8" cullMax="100" cullMin="60" />
<cullData cullGroupID="9" cullMax="100" cullMin="50" />
<cullData cullGroupID="10" cullMax="400" cullMin="300" />
</cullSettings>
</configuration>
</envData>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" ?>
<!-- DO NOT EDIT THIS FILE -->
<triggers nextID="157">
<trigger id="1" enabled="1">
<event id="OnEnter">
<command id="zonePlayer" target="target" args="312" />
</event>
</trigger>
<trigger id="44" enabled="1">
<event id="OnCreate">
<command id="SetPhysicsVolumeEffect" target="self" args="push,75,0.9,2,-0.41" />
</event>
</trigger>
<trigger id="46" enabled="1">
<event id="OnCreate">
<command id="SetPhysicsVolumeEffect" target="self" args="push,75,0.9,3,-0.41" />
</event>
</trigger>
</triggers>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" ?>
<!-- DO NOT EDIT THIS FILE -->
<triggers nextID="5">
<trigger id="4" enabled="1">
<event id="OnEnter">
<command id="updateMission" target="target" args="exploretask,1,1,1,AG_POI_RESEARCH" />
</event>
</trigger>
</triggers>

Some files were not shown because too many files have changed in this diff Show More