mirror of
https://github.com/Wesley-DeMontigny/WLUS.git
synced 2026-02-09 11:38:36 -06:00
1103 lines
46 KiB
Python
1103 lines
46 KiB
Python
import os
|
|
import threading
|
|
from threading import Thread
|
|
import asyncio
|
|
from messages import Message
|
|
import server
|
|
from bitstream import *
|
|
from socket import *
|
|
from Packet import *
|
|
from reliability import PacketReliability
|
|
import uuid
|
|
from struct import *
|
|
from replicamanager import *
|
|
from DBHandlers import *
|
|
from time import sleep
|
|
from GameMessage import *
|
|
from LDFReader import *
|
|
from difflib import SequenceMatcher
|
|
from ReplicaPacket import *
|
|
from LDFReader import *
|
|
import atexit
|
|
import copy
|
|
from LVLParser import *
|
|
from ScriptedEvents import *
|
|
|
|
|
|
|
|
class WorldServer(server.Server):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.register_handler(Message.LegoPacket, self.handleLegoPacket)
|
|
self.register_handler(Message.NewIncomingConnection, self.addToParticipants)#Adds participant to replica manager
|
|
self.Local = True
|
|
self.SavedObjects = {}
|
|
self.unhandledGMs = []
|
|
self.RM = ReplicaManager(self)
|
|
self.GM = GameMessages(self)
|
|
self.EM = EventManager()
|
|
|
|
self.EM.registerEvent("Unlock Imagination Pickup", "GM_486", self.UnlockImaginationHandler)
|
|
|
|
updateLoop = Thread(target=self.updateLoop)
|
|
updateLoop.start()
|
|
|
|
initGameObjects = Thread(target=self.spawnInitWorldObjects)
|
|
initGameObjects.start()
|
|
|
|
def UnlockImaginationHandler(self, Arguments):
|
|
objectID = Arguments[0]
|
|
player = Arguments[1].read(c_longlong)
|
|
if(664 in self.SavedObjects[player].CurrentMissions and objectID not in self.SavedObjects):
|
|
task = self.DB.getMissionTaskType(664)[0][0]
|
|
|
|
NotifyMissionTask = self.GM.InitGameMessage(255, player)
|
|
NotifyMissionTask.write(c_int(664))
|
|
NotifyMissionTask.write(c_int(1 << (task + 1)))
|
|
update = BitStream()
|
|
update.write(c_float(2210+(objectID<<8)))
|
|
NotifyMissionTask.write(c_uint8(update.__len__()))
|
|
NotifyMissionTask.write(update)
|
|
|
|
session = self.DB.getSessionByCharacter(player)
|
|
self.send(NotifyMissionTask, (str(session[2]), int(session[7])))
|
|
|
|
|
|
def addSkill(self, objectID, skillID, AICombatWeight=0, fromSkillSet=False, castType=0, timeSecs=-1, timesCanCast=-1, slotID=-1, temporary=True):
|
|
packet = self.GM.InitGameMessage(124, objectID)
|
|
packet.write(c_int(AICombatWeight))
|
|
packet.write(c_bit(fromSkillSet))
|
|
packet.write(c_int(castType))
|
|
packet.write(c_float(timeSecs))
|
|
packet.write(c_int(timesCanCast))
|
|
packet.write(c_ulong(skillID))
|
|
packet.write(c_int(slotID))
|
|
packet.write(c_bit(temporary))
|
|
|
|
def getSavedObjectsInZone(self, zoneID):
|
|
Objects = []
|
|
for id in self.SavedObjects:
|
|
if(self.SavedObjects[id].Zone == zoneID):
|
|
Objects.append(self.SavedObjects[id])
|
|
return Objects
|
|
|
|
def handleInteraction(self, multiInteractionUse, multiInteractionID, multiInteractionType, object, secondary, player):
|
|
LOT = int(self.SavedObjects[object].getLOT())
|
|
mission = self.DB.getApplicableMission(LOT, self.SavedObjects[player].CurrentMissions, self.SavedObjects[player].CompletedMissions)
|
|
if(mission is not None):
|
|
self.offerMission(player, mission, object)
|
|
elif(self.SavedObjects[object].onInteraction != None):
|
|
tokens = self.SavedObjects[object].onInteraction.split(" ")
|
|
if(tokens[0] == "zoneTransfer"):
|
|
session = self.DB.getSessionByCharacter(player)
|
|
self.loadWorld(player, int(tokens[1]), (str(session[2]), int(session[7])), loadAtDefaultSpawn=True)
|
|
|
|
def resurrect(self, playerID, rezImmediately=False):
|
|
zone = self.DB.getZoneOfObject(playerID)[0]
|
|
packet = self.GM.InitGameMessage(160, playerID)
|
|
packet.write(c_bit(rezImmediately))
|
|
self.SavedObjects[playerID].components[3].currentHealth = c_ulong(int(unpack("f", self.SavedObjects[playerID].components[3].maxHealth)[0]))
|
|
self.brodcastPacket(packet, zone)
|
|
|
|
def killPlayer(self, playerID):
|
|
self.SavedObjects[playerID].components[3].currentHealth = c_ulong(0)
|
|
zone = self.DB.getZoneOfObject(playerID)[0]
|
|
packet = self.GM.InitGameMessage(37, playerID)
|
|
self.log("Killing player with ID: " + str(playerID))
|
|
self.brodcastPacket(packet, zone)
|
|
|
|
def updateLoop(self):
|
|
while True:
|
|
try:
|
|
for id in self.SavedObjects:
|
|
|
|
try:
|
|
obj = self.SavedObjects[id]
|
|
except Exception as e:
|
|
print("Error while serializing: ", e)
|
|
if("Drop" not in obj.tag.split(" ") and "Static" not in obj.tag.split(" ")):
|
|
self.RM.serialize(obj)
|
|
if(unpack("l", obj.components[0].LOT)[0] == 1):#If obj is a player
|
|
try:
|
|
self.killZoneCheck(id, unpack("f", obj.components[1].yPos)[0])
|
|
except:
|
|
pass
|
|
if(obj.components[3].currentHealth == c_ulong(0)):
|
|
self.killPlayer(id)
|
|
except Exception as e:
|
|
pass
|
|
sleep(.3)
|
|
|
|
def smash(self, objectID, force, ghostOpacity, killerID, ignoreObjectVisibility = False):
|
|
zone = self.DB.getZoneOfObject(objectID)[0]
|
|
packet = self.GM.InitGameMessage(537, objectID)
|
|
packet.write(c_bit(ignoreObjectVisibility))
|
|
packet.write(c_float(force))
|
|
packet.write(c_float(ghostOpacity))
|
|
packet.write(c_longlong(killerID))
|
|
self.brodcastPacket(packet, zone)
|
|
|
|
def spawnInitWorldObjects(self):
|
|
Objects = []
|
|
ventureExplorer = lvlFile(os.getcwd() + "\\LegoUniverse\\nd_space_ship.lvl", 1000)
|
|
for gameObject in ventureExplorer.Objects:
|
|
Objects.append(gameObject)
|
|
for Object in Objects:
|
|
objectID = randint(100000000000000000, 999999999999999999)
|
|
smashable = False
|
|
respawn = None
|
|
custom_server_script = None
|
|
LOT = Object["LOT"]
|
|
zoneTransferInteraction = None
|
|
Tag = ""
|
|
SpawnIn = False#This is just until I can figure out how to disable rendering
|
|
|
|
if("is_smashable" in Object["LDF"]):
|
|
smashable = bool(int(Object["LDF"]["is_smashable"]))
|
|
if("renderDisabled" in Object["LDF"] and Object["LDF"]["renderDisabled"] == '1'):
|
|
Tag = Tag + "RenderDisabled "
|
|
if("respawn" in Object["LDF"]):
|
|
respawn = Object["LDF"]["respawn"]
|
|
SpawnIn = True
|
|
if("transferZoneID" in Object["LDF"]):
|
|
zoneTransferInteraction = int(Object["LDF"]["transferZoneID"])
|
|
SpawnIn = True
|
|
if("custom_server_script" in Object["LDF"]):
|
|
custom_server_script = Object["LDF"]["custom_script_server"]
|
|
if("spawntemplate" in Object["LDF"]):
|
|
LOT = int(Object["LDF"]["spawntemplate"])
|
|
SpawnIn = True
|
|
if(SpawnIn):
|
|
self.log("Initialized Object With LOT " + str(LOT) + " In Zone " + str(Object["Zone"]))
|
|
self.createObject("", LOT, objectID, Object["Zone"], Object["XPos"], Object["YPos"], Object["ZPos"], Object["XRot"], Object["YRot"], Object["ZRot"], Object["WRot"], Register=False, Init=True,
|
|
smashable=smashable, Respawn=respawn, serverScript=custom_server_script, Scale=Object["Scale"], zoneTrasnferInteraction=zoneTransferInteraction, Tag=Tag,
|
|
spawnerObjectID=Object["ObjectID"])
|
|
self.log("Finished Initializing Objects")
|
|
|
|
def updatePlayerLoc(self, objectID, xPos, yPos, zPos, xRot, yRot, zRot, wRot):
|
|
try:
|
|
obj = self.SavedObjects[objectID]
|
|
obj.components[1].xPos = c_float(xPos)
|
|
obj.components[1].yPos = c_float(yPos)
|
|
obj.components[1].zPos = c_float(zPos)
|
|
obj.components[1].xRot = c_float(xRot)
|
|
obj.components[1].yRot = c_float(yRot)
|
|
obj.components[1].zRot = c_float(zRot)
|
|
obj.components[1].wRot = c_float(wRot)
|
|
#self.DB.setCharacterLoc(objectID, xPos, yPos, zPos, xRot, yRot, zRot, wRot)
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
def getZoneRecipients(self, zone):
|
|
connections = self.DB.getConnectionsInZone(zone)
|
|
recipients = []
|
|
for conn in connections:
|
|
recipients.append((str(conn[0]), int(conn[1])))
|
|
return recipients
|
|
|
|
def killZoneCheck(self, objectID, yPos):
|
|
zone = self.DB.getZoneOfObject(objectID)[0]
|
|
if((zone == Zones.VENTURE_EXPLORER or zone == Zones.VENTURE_EXPLORER_RETURN) and yPos < 575):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.AVANT_GARDENS and yPos < 255):
|
|
self.killPlayer(objectID)
|
|
if((zone == Zones.BLOCK_YARD or zone == Zones.AVANT_GROVE or zone == Zones.NIMBUS_ROCK or zone == Zones.CHANTEY_SHANTEY or zone == Zones.RAVEN_BLUFF) and yPos < 375):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.NIMBUS_ISLE and yPos < 445):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.GNARLED_FOREST and yPos < 165):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.CANYON_COVE and yPos < 210):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.FORBIDDEN_VALLEY and yPos < 60):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.STARBASE_3001 and yPos < 900):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.LEGO_CLUB and yPos < 800):
|
|
self.killPlayer(objectID)
|
|
if(zone == Zones.CRUX_PRIME and yPos < -20):
|
|
self.killPlayer(objectID)
|
|
|
|
def offerMission(self, objectID, missionID, offererID):
|
|
packet = self.GM.InitGameMessage(248, objectID)
|
|
packet.write(c_int(missionID))
|
|
packet.write(c_longlong(offererID))
|
|
session = self.DB.getSessionByCharacter(objectID)
|
|
self.send(packet, (str(session[2]), int(session[7])))
|
|
|
|
def orientToPosition(self, objectID, xPos, yPos, zPos):
|
|
zone = self.DB.getZoneOfObject(objectID)[0]
|
|
packet = self.GM.InitGameMessage(906, objectID)
|
|
packet.write(c_float(xPos))
|
|
packet.write(c_float(yPos))
|
|
packet.write(c_float(zPos))
|
|
self.brodcastPacket(packet, int(zone))
|
|
|
|
def orientToAngle(self, objectID, relativeToCurrent, angle):
|
|
zone = self.DB.getZoneOfObject(objectID)[0]
|
|
packet = self.GM.InitGameMessage(906, objectID)
|
|
packet.write(c_bit(relativeToCurrent))
|
|
packet.write(c_float(angle))
|
|
self.brodcastPacket(packet, int(zone))
|
|
|
|
def brodcastPacket(self, packet, zoneID):
|
|
connections = self.DB.getConnectionsInZone(zoneID)
|
|
for connection in connections:
|
|
self.send(packet, (str(connection[0]), int(connection[1])))
|
|
|
|
def SetJetPackMode(self, objectID, bypassChecks=False, doHover=False, Use=True, effectID=-1, airSpeed=10, maxAirSpeed=15, vertVel=1, warningEffectID=-1):
|
|
zone = self.DB.getZoneOfObject(objectID)[0]
|
|
packet = self.GM.InitGameMessage(561, objectID)
|
|
packet.write(c_bit(bypassChecks))
|
|
packet.write(c_bit(doHover))
|
|
packet.write(c_bit(Use))
|
|
packet.write(c_int(effectID))
|
|
packet.write(c_float(airSpeed))
|
|
packet.write(c_float(maxAirSpeed))
|
|
packet.write(c_float(vertVel))
|
|
packet.write(c_int(warningEffectID))
|
|
self.brodcastPacket(packet, int(zone))
|
|
|
|
def dropLoot(self, recipients, usePosition, finalPosition, currency, LOT, owner, sourceObj, spawnPosition):
|
|
packet = BitStream()
|
|
lootID = randint(100000000000000000, 999999999999999999)
|
|
packet.write(c_bit(usePosition))
|
|
packet.write(c_float(finalPosition[0]))
|
|
packet.write(c_float(finalPosition[1]))
|
|
packet.write(c_float(finalPosition[2]))
|
|
packet.write(c_int(currency))
|
|
packet.write(c_long(LOT))
|
|
packet.write(c_longlong(lootID))
|
|
packet.write(c_longlong(owner))
|
|
packet.write(c_longlong(sourceObj))
|
|
packet.write(c_float(spawnPosition[0]))
|
|
packet.write(c_float(spawnPosition[1]))
|
|
packet.write(c_float(spawnPosition[2]))
|
|
Object = GameObject()
|
|
Object.tag = "Drop"
|
|
Object.dropLOT = LOT
|
|
Object.dropOwner = owner
|
|
self.SavedObjects[lootID] = Object
|
|
for recipient in recipients:
|
|
self.send(packet, recipient)
|
|
|
|
def createObjectsForWorld(self, zoneID, address):
|
|
objects = self.getSavedObjectsInZone(zoneID)
|
|
for obj in objects:
|
|
self.createObject(0, 0, 0, zoneID, 0, 0, 0, 0, 0, 0, 0, RO=obj, Register=False, Address=address)
|
|
|
|
def createObject(self, Name, LOT, ObjectID, zone, xPos, yPos, zPos, xRot, yRot, zRot, wRot, RO=None, Init=False, message=None, Register=True, Scale=1, currentHealth=1, maxHealth=1, currentArmor=0, maxArmor=0, currentImagination=0, maxImagination=0, smashable=False, level=1,
|
|
collectibleID=2210, Tag="", Address=None, Respawn=None, serverScript=None, triggerID=None, zoneTrasnferInteraction=None, spawnerObjectID=None):
|
|
if(RO != None):
|
|
if(Register == True):
|
|
self.DB.registerWorldObject(Name, LOT, ObjectID, zone, xPos,yPos, zPos, xRot, yRot, zRot, wRot, self.RM._current_network_id)
|
|
RO.Zone = zone
|
|
RO.tag = Tag
|
|
RO.respawn = Respawn
|
|
RO.customServerScript = serverScript
|
|
if(zoneTrasnferInteraction != None):
|
|
RO.onInteraction = "zoneTransfer " + str(zoneTrasnferInteraction)
|
|
self.SavedObjects[ObjectID] = RO
|
|
if(Init == False):
|
|
if(message == None):
|
|
if(Address == None):
|
|
self.RM.construct(RO, recipients=self.getZoneRecipients(zone))
|
|
else:
|
|
self.RM.construct(RO, recipients=[Address])
|
|
else:
|
|
if(Address == None):
|
|
self.RM.construct(RO, constructMsg=message, recipients=self.getZoneRecipients(zone))
|
|
else:
|
|
self.RM.construct(RO, constructMsg=message, recipients=[Address])
|
|
else:
|
|
Components = []
|
|
|
|
compList = self.DB.getComponentsForLOT(LOT)
|
|
|
|
obj = BaseData()
|
|
obj.objectID = c_longlong(ObjectID)
|
|
obj.LOT = c_long(LOT)
|
|
obj.Name = Name
|
|
if(triggerID != None):
|
|
obj.trigger = True
|
|
if(spawnerObjectID != None):
|
|
obj.SpawnerObjID = c_longlong(spawnerObjectID)
|
|
obj.flag3 = True
|
|
obj.NameLength = Name.__len__()
|
|
obj.Scale = c_float(Scale)
|
|
adjCompList = []
|
|
Components.append(obj)
|
|
for comp in compList:
|
|
adjCompList.append(comp[0])
|
|
|
|
if(108 in adjCompList):
|
|
Comp108 = Component108()
|
|
Components.append(Comp108)
|
|
if(61 in adjCompList):
|
|
self.log("ModuleAssembly is not implemented")
|
|
return
|
|
if (1 in adjCompList):
|
|
ControllablePhysics = ControllablePhysicsComponent()
|
|
ControllablePhysics.vectorFlag = True
|
|
ControllablePhysics.xPos = c_float(xPos)
|
|
ControllablePhysics.yPos = c_float(yPos)
|
|
ControllablePhysics.zPos = c_float(zPos)
|
|
ControllablePhysics.xRot = c_float(xRot)
|
|
ControllablePhysics.yRot = c_float(yRot)
|
|
ControllablePhysics.zRot = c_float(zRot)
|
|
ControllablePhysics.wRot = c_float(wRot)
|
|
ControllablePhysics.onGround = True
|
|
Components.append(ControllablePhysics)
|
|
if(3 in adjCompList):
|
|
Physics = SimplePhysicsComponent()
|
|
Physics.vectorFlag = True
|
|
Physics.xPos = c_float(xPos)
|
|
Physics.yPos = c_float(yPos)
|
|
Physics.zPos = c_float(zPos)
|
|
Physics.xRot = c_float(xRot)
|
|
Physics.yRot = c_float(yRot)
|
|
Physics.zRot = c_float(zRot)
|
|
Physics.wRot = c_float(wRot)
|
|
Components.append(Physics)
|
|
if(20 in adjCompList):
|
|
self.log("RigidBodyPhantomPhysics is not implemented")
|
|
return
|
|
if(30 in adjCompList):
|
|
VPhysics = VehiclePhysics()
|
|
Components.append(VPhysics)
|
|
if(40 in adjCompList):
|
|
Physics = PhantomPhysics()
|
|
Physics.vectorFlag = True
|
|
Physics.xPos = c_float(xPos)
|
|
Physics.yPos = c_float(yPos)
|
|
Physics.zPos = c_float(zPos)
|
|
Physics.xRot = c_float(xRot)
|
|
Physics.yRot = c_float(yRot)
|
|
Physics.zRot = c_float(zRot)
|
|
Physics.wRot = c_float(wRot)
|
|
Components.append(Physics)
|
|
if(7 in adjCompList):
|
|
Destructible = DestructibleIndex()
|
|
Destructible.flag1 = False
|
|
|
|
Stats = StatsIndex()
|
|
Stats.currentHealth = c_ulong(currentHealth)
|
|
Stats.maxHealth = c_float(maxHealth)
|
|
Stats.currentArmor = c_ulong(currentArmor)
|
|
Stats.maxArmor = c_float(maxArmor)
|
|
Stats.currentImagination = c_ulong(currentImagination)
|
|
Stats.maxImagination = c_float(maxImagination)
|
|
Stats.flag2 = True
|
|
if(str(self.DB.getObjectType(LOT)[0]) == "Smashables"):
|
|
Stats.isSmashable = True
|
|
Stats.flag3 = True
|
|
Stats.factionID = c_long(6)
|
|
else:
|
|
Stats.isSmashable = smashable
|
|
if (23 in adjCompList):
|
|
Stats.factionID = c_long(25)
|
|
Components.append(Destructible)
|
|
Components.append(Stats)
|
|
if(23 in adjCompList):
|
|
Stats = StatsIndex()
|
|
Stats.currentHealth = c_ulong(currentHealth)
|
|
Stats.maxHealth = c_float(maxHealth)
|
|
Stats.currentArmor = c_ulong(currentArmor)
|
|
Stats.maxArmor = c_float(maxArmor)
|
|
Stats.factionID = c_long(25)
|
|
Stats.currentImagination = c_ulong(currentImagination)
|
|
Stats.maxImagination = c_float(maxImagination)
|
|
Stats.flag2 = True
|
|
|
|
Collectible = CollectibleComponent()
|
|
Collectible.CollectibleID = c_ushort(collectibleID)
|
|
|
|
Components.append(Stats)
|
|
Components.append(Collectible)
|
|
if(26 in adjCompList):
|
|
self.log("Pet is not implemented")
|
|
return
|
|
if(4 in adjCompList):
|
|
Character = CharacterComponent()
|
|
Character.hasLevel = True
|
|
Character.level = c_ulong(level)
|
|
info = PlayerInfo()
|
|
info.setInfo(self.DB, ObjectID)
|
|
Character.info = info
|
|
style = PlayerStyle()
|
|
style.setStyle(self.DB, ObjectID)
|
|
Character.style = style
|
|
data9 = Component4_Data9()
|
|
Character.data9 = data9
|
|
data11 = Component4_Data11()
|
|
Character.data11 = data11
|
|
Components.append(Character)
|
|
if(17 in adjCompList):
|
|
Inventory = InventoryComponent(self.DB)
|
|
Inventory.flag1 = True
|
|
Inventory.characterObjID = ObjectID
|
|
Components.append(Inventory)
|
|
if (5 in adjCompList):
|
|
Script = ScriptComponent()
|
|
self.log("WARNING: Script component is not fully implemented")
|
|
Components.append(Script)
|
|
if (9 in adjCompList):
|
|
Skill = SkillComponent()
|
|
self.log("WARNING: Skill component is not fully implemented")
|
|
Components.append(Skill)
|
|
if(60 in adjCompList):
|
|
AI = BaseCombatAI()
|
|
Components.append(AI)
|
|
if(48 in adjCompList):
|
|
self.log("Rebuild is not implemented")
|
|
return
|
|
if(25 in adjCompList):
|
|
self.log("MovingPlatform is not implemented")
|
|
return
|
|
if(49 in adjCompList):
|
|
self.log("Switch is not implemented")
|
|
return
|
|
if(16 in adjCompList):
|
|
Vendor = VendorComponent()
|
|
Components.append(Vendor)
|
|
if(6 in adjCompList):
|
|
Bouncer = BouncerComponent()
|
|
Components.append(Bouncer)
|
|
if(39 in adjCompList):
|
|
SA = ScriptedActivity()
|
|
self.log("WARNING: ScriptedActivity component is not fully implemented")
|
|
Components.append(SA)
|
|
if(71 in adjCompList):
|
|
self.log("RacingControl is not implemented")
|
|
return
|
|
if(75 in adjCompList):
|
|
self.log("Exhibit is not implemented")
|
|
return
|
|
# if(42 in adjCompList):
|
|
# self.log("Model is not implemented")
|
|
# return
|
|
if(2 in adjCompList):
|
|
if("RenderDisabled" not in Tag.split(" ")):#Don't give it a render component if disabled
|
|
Render = RenderComponent()
|
|
Components.append(Render)
|
|
if(107 in adjCompList):
|
|
Comp107 = Component107()
|
|
Components.append(Comp107)
|
|
if(69 in adjCompList):
|
|
trigger = Trigger()
|
|
trigger.triggerID = triggerID
|
|
Components.append(trigger)
|
|
|
|
Object = GameObject()
|
|
Object.Zone = zone
|
|
Object.tag = Tag
|
|
Object.components = Components
|
|
Object.respawn = Respawn
|
|
Object.customServerScript = serverScript
|
|
if(zoneTrasnferInteraction != None):
|
|
Object.onInteraction = "zoneTransfer " + str(zoneTrasnferInteraction)
|
|
if (Register == True):
|
|
self.DB.registerWorldObject(Name, LOT, ObjectID, zone, xPos, yPos, zPos, xRot, yRot, zRot, wRot, self.RM._current_network_id)
|
|
self.SavedObjects[ObjectID] = Object
|
|
if (Init == False):
|
|
if(message == None):
|
|
if(Address == None):
|
|
self.RM.construct(Object, recipients=self.getZoneRecipients(zone))
|
|
else:
|
|
self.RM.construct(Object, recipients=[Address])
|
|
else:
|
|
if(Address == None):
|
|
self.RM.construct(Object, constructMsg=message, recipients=self.getZoneRecipients(zone))
|
|
else:
|
|
self.RM.construct(Object, constructMsg=message, recipients=[Address])
|
|
|
|
def loadWorld(self, objectID, worldID, address, loadAtDefaultSpawn=False):
|
|
self.DB.deleteWorldObject(objectID)
|
|
self.DB.updateCharacterZone(worldID, objectID) # Update session if needed
|
|
characterData = self.DB.getCharacterDataByID(objectID) # Reload character data
|
|
self.DB.registerOrJoinWorld(worldID)
|
|
# Register the world if there isn't one
|
|
worldLoad = BitStream()
|
|
# START OF HEADER
|
|
worldLoad.write(c_ubyte(Message.LegoPacket)) # MSG ID ()
|
|
worldLoad.write(c_ushort(0x05)) # Connection Type (UShort)
|
|
worldLoad.write(c_ulong(0x02)) # Internal Packet ID (ULong)
|
|
worldLoad.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
###END OF HEADER
|
|
if(worldID == 0):
|
|
worldID = 1000
|
|
worldLoad.write(c_ushort(int(worldID))) # Write the last zone ID of the character
|
|
worldLoad.write(c_ushort(0x00)) # Map instance
|
|
worldLoad.write(c_ulong(0x00)) # Map clone
|
|
checksum = Zones.zoneChecksums[(int(worldID))]
|
|
for i in range(len(checksum)):
|
|
worldLoad.write(c_ubyte(checksum[i])) # Write special world checksum
|
|
worldLoad.write(c_ushort(0x00)) # Unknown
|
|
if (characterData[17] == None or characterData[18] == None or characterData[19] == None or loadAtDefaultSpawn == True):
|
|
defaultSpawn = Zones.defaultZoneSpawns[(int(characterData[14]))]
|
|
worldLoad.write(c_float(int(defaultSpawn[0]))) # Posx
|
|
worldLoad.write(c_float(int(defaultSpawn[1]))) # Posy
|
|
worldLoad.write(c_float(int(defaultSpawn[2]))) # Posz
|
|
self.DB.setCharacterPos(objectID, defaultSpawn[0], defaultSpawn[1], defaultSpawn[2])
|
|
else:
|
|
worldLoad.write(c_float(int(characterData[17]))) # Posx
|
|
worldLoad.write(c_float(int(characterData[18]))) # Posy
|
|
worldLoad.write(c_float(int(characterData[19]))) # Posz
|
|
worldLoad.write(c_ulong(0x00)) # 0 if normal world. 4 if activity
|
|
self.send(worldLoad, address, reliability=PacketReliability.ReliableOrdered)
|
|
|
|
def addToParticipants(self, data, address):
|
|
self.log("Just added new participant to replica manager")
|
|
self.RM.add_participant(address)
|
|
|
|
def handleLegoPacket(self, data, address):
|
|
if(data[0:3] == bytearray(b'\x00\x00\x00')):#Handshake
|
|
self.log("Lego Packet was Connection Init")
|
|
handshake = BitStream()
|
|
# START OF HEADER
|
|
handshake.write(c_ubyte(Message.LegoPacket)) # MSG ID ()
|
|
handshake.write(c_ushort(0x00)) # Connection Type (UShort)
|
|
handshake.write(c_ulong(0x00)) # Internal Packet ID (ULong)
|
|
handshake.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
###END OF HEADER
|
|
handshake.write(c_ulong(171022)) # Client version number
|
|
handshake.write(c_ulong(0x93)) # Unknown, don't mess with it
|
|
handshake.write(c_ulong(4)) # Remote Connection Type (1 for Auth, 4 for everything else)
|
|
handshake.write(c_ulong(getpid())) # Current PID
|
|
handshake.write(c_short(-1)) # Unknown, speculated to be client port (0xff)
|
|
handshake.write(str(socket.gethostbyname(socket.gethostname()))) # Local IP addr of server
|
|
self.send(handshake, address, reliability=PacketReliability.ReliableOrdered)
|
|
elif(data[0:3] == b"\x04\x00\x01"):
|
|
self.log("Lego Packet was User Session Info")
|
|
sessionInfo = self.DB.getSessionByAddress(address[0])
|
|
userRead = BitStream(data[7:])
|
|
userIDRead = BitStream(data[73:])
|
|
username = userRead.read(str)
|
|
userID = userIDRead.read(str)
|
|
self.log("Session Info - Username : " + str(username) + " UserKey : " + str(userID))
|
|
if(sessionInfo[1] == self.DB.getAccountByUsername(username)[0]):
|
|
self.DB.updateSessionByUserKey(userID, 1, "NULL", "NULL")
|
|
elif(data[0:3] == b"\x04\x00\x02"):
|
|
sleep(.5)
|
|
session = self.DB.getSessionByAddress(address[0])
|
|
self.log("Lego Packet was Minifigure List Request")
|
|
if(session[6] == 1):
|
|
self.log("Client's Session is valid")
|
|
rows, characterData = self.DB.getCharacterData(session[1])
|
|
if(rows > 4):
|
|
rows = 4
|
|
self.log("Account " + str(session[1]) + " has " + str(rows) + " character(s)")
|
|
characterList = BitStream()
|
|
# START OF HEADER
|
|
characterList.write(c_ubyte(Message.LegoPacket)) # MSG ID ()
|
|
characterList.write(c_ushort(0x05)) # Connection Type (UShort)
|
|
characterList.write(c_ulong(0x06)) # Internal Packet ID (ULong)
|
|
characterList.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
###END OF HEADER
|
|
characterList.write(c_ubyte(rows))#Number of characters
|
|
characterList.write(c_ubyte(0x00))#Character to show up front
|
|
for row in characterData:
|
|
characterList.write(c_longlong(row[3]))#Object ID
|
|
characterList.write(c_ulong(0x00))#Unknown, must be 0
|
|
characterList.write(str(row[2]), allocated_length=66)#Name
|
|
characterList.write("", allocated_length=66)
|
|
characterList.write(c_byte(False))#Has custom name rejected
|
|
characterList.write(c_byte(False))#Is free to play
|
|
for _ in range(10):#Don't know what this stuff is for
|
|
characterList.write_bits(b"\x00")
|
|
characterList.write(c_ulong(row[4]))#Shirt color
|
|
characterList.write(c_ulong(row[5]))#Shirt style
|
|
characterList.write(c_ulong(row[6]))#Pants color
|
|
characterList.write(c_ulong(row[8]))#Hair style
|
|
characterList.write(c_ulong(row[7]))#Hair color
|
|
characterList.write(c_ulong(row[9]))#lh??
|
|
characterList.write(c_ulong(row[10]))#rh??
|
|
characterList.write(c_ulong(row[11]))#Eyebrows
|
|
characterList.write(c_ulong(row[12])) # Eyes
|
|
characterList.write(c_ulong(row[13])) # Mouth
|
|
characterList.write(c_ulong(0x00))#Unknown
|
|
characterList.write(c_ushort(row[14])) # Last Zone ID
|
|
characterList.write(c_ushort(row[15])) # map instance
|
|
characterList.write(c_ulong(row[16])) # map clone
|
|
characterList.write(c_ulonglong(0x00)) # Last logout?
|
|
items = self.DB.getEquippedItems(str(row[3]))
|
|
characterList.write(c_ushort(len(items)))#Equipped Item Lots
|
|
for item in items:
|
|
LOT = self.DB.getLOTFromObject(str(item[0]))
|
|
self.log("Found item in inventory with LOT " + str(LOT[0]))
|
|
characterList.write_bits(c_ulong(int(LOT[0])))
|
|
self.send(characterList, address, reliability=PacketReliability.ReliableOrdered)
|
|
else:
|
|
self.log("Client's Session is Invalid. Disconnecting...")
|
|
DisconnectionNotify = BitStream()
|
|
# START OF HEADER
|
|
DisconnectionNotify.write(bytes(Message.LegoPacket)) # MSG ID
|
|
DisconnectionNotify.write(bytes(0x00)) # Connection Type
|
|
DisconnectionNotify.write(bytes(0x00)) # Internal Packet ID
|
|
DisconnectionNotify.write(bytes(0x00)) # Unknown
|
|
###END OF HEADER
|
|
DisconnectionNotify.write(c_ulong(0x00)) # Unknown Server Error
|
|
self.send(DisconnectionNotify, address)
|
|
self.DB.destroySessionWithAddress(address[0])
|
|
elif(data[0:3] == b"\x04\x00\x03"):#When you create a minifigure you have to add a minfigure list packet
|
|
self.log("Lego Packet was Minifigure Creation Request")
|
|
session = self.DB.getSessionByAddress(address[0])
|
|
self.log("Lego Packet was Minifigure List Request")
|
|
if(session[6] == 1):
|
|
nameData = BitStream(data[7:])
|
|
name = nameData.read(str)
|
|
shirtColorData = BitStream(data[94:])
|
|
shirtStyleData = BitStream(data[98:])
|
|
pantsColorData = BitStream(data[102:])
|
|
hairStyleData = BitStream(data[106:])
|
|
hairColorData = BitStream(data[110:])
|
|
lhData = BitStream(data[114:])
|
|
rhData = BitStream(data[118:])
|
|
eyebrowsData = BitStream(data[122:])
|
|
eyesData = BitStream(data[126:])
|
|
mouthData = BitStream(data[130:])
|
|
shirtColor = shirtColorData.read(c_ulong)
|
|
shirtStyle = shirtStyleData.read(c_ulong)
|
|
pantsColor = pantsColorData.read(c_ulong)
|
|
hairStyle = hairStyleData.read(c_ulong)
|
|
hairColor = hairColorData.read(c_ulong)
|
|
lh = lhData.read(c_ulong)
|
|
rh = rhData.read(c_ulong)
|
|
eyebrows = eyebrowsData.read(c_ulong)
|
|
eyes = eyesData.read(c_ulong)
|
|
mouth = mouthData.read(c_ulong)
|
|
self.DB.createMinifigure(session[1], name, shirtColor, shirtStyle, pantsColor,
|
|
hairStyle, hairColor, lh, rh, eyebrows, eyes, mouth)
|
|
response = BitStream()
|
|
# START OF HEADER
|
|
response.write(c_ubyte(Message.LegoPacket)) # MSG ID ()
|
|
response.write(c_ushort(0x05)) # Connection Type (UShort)
|
|
response.write(c_ulong(0x07)) # Internal Packet ID (ULong)
|
|
response.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
###END OF HEADER
|
|
response.write(c_ubyte(0x00)) # 0x00 is success
|
|
self.send(response, address,reliability=PacketReliability.ReliableOrdered) # Inform client character was created
|
|
self.log("Client's Session is valid")
|
|
rows, characterData = self.DB.getCharacterData(session[1])
|
|
if(rows > 4):
|
|
rows = 4
|
|
self.log("Account " + str(session[1]) + " now has " + str(rows) + " characters")
|
|
characterList = BitStream()
|
|
# START OF HEADER
|
|
characterList.write(c_ubyte(Message.LegoPacket)) # MSG ID ()
|
|
characterList.write(c_ushort(0x05)) # Connection Type (UShort)
|
|
characterList.write(c_ulong(0x06)) # Internal Packet ID (ULong)
|
|
characterList.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
###END OF HEADER
|
|
characterList.write(c_ubyte(rows))#Number of characters
|
|
characterList.write(c_ubyte(0x00))#Character to show up front
|
|
for row in characterData:
|
|
characterList.write(c_longlong(row[3]))#Object ID
|
|
characterList.write(c_ulong(0x00))#Unknown, must be 0
|
|
characterList.write(str(row[2]), allocated_length=66)#Name
|
|
characterList.write("", allocated_length=66)
|
|
characterList.write(c_byte(False))#Has custom name rejected
|
|
characterList.write(c_byte(False))#Is free to play
|
|
for _ in range(10):#Don't know what this stuff is for
|
|
characterList.write_bits(b"\x00")
|
|
characterList.write(c_ulong(row[4]))#Shirt color
|
|
characterList.write(c_ulong(row[5]))#Shirt style
|
|
characterList.write(c_ulong(row[6]))#Pants color
|
|
characterList.write(c_ulong(row[8]))#Hair style
|
|
characterList.write(c_ulong(row[7]))#Hair color
|
|
characterList.write(c_ulong(row[9]))#lh??
|
|
characterList.write(c_ulong(row[10]))#rh??
|
|
characterList.write(c_ulong(row[11]))#Eyebrows
|
|
characterList.write(c_ulong(row[12])) # Eyes
|
|
characterList.write(c_ulong(row[13])) # Mouth
|
|
characterList.write(c_ulong(0x00))#Unknown
|
|
characterList.write(c_ushort(row[14])) # Last Zone ID
|
|
characterList.write(c_ushort(row[15])) # map instance
|
|
characterList.write(c_ulong(row[16])) # map clone
|
|
characterList.write(c_ulonglong(0x00)) # Last logout?
|
|
items = self.DB.getEquippedItems(str(row[3]))
|
|
characterList.write(c_ushort(len(items)))#Equipped Item Lots
|
|
for item in items:
|
|
LOT = self.DB.getLOTFromObject(str(item[0]))
|
|
self.log("Found item in inventory with LOT " + str(LOT[0]))
|
|
characterList.write_bits(c_ulong(int(LOT[0])))
|
|
self.send(characterList, address, reliability=PacketReliability.ReliableOrdered)
|
|
elif(data[0:3] == b"\x04\x00\x06"):#Delete minifigure
|
|
self.log("Lego Packet was Minifigure Deletion")
|
|
objIdData = BitStream(data[7:])
|
|
objId = objIdData.read(c_longlong)#Get objectID
|
|
self.log("Deleting Minifigure with ID : " + str(objId))
|
|
self.DB.deleteCharacter(objId)#Delete It with the objID
|
|
elif(data[0:3] == b"\x04\x00\x04"):#Character wants to enter world
|
|
self.log("Lego Packet was World Enter Request")
|
|
objectIDData = BitStream(data[7:])
|
|
objectID = objectIDData.read(c_longlong)
|
|
characterData = self.DB.getCharacterDataByID(objectID)#Get character data
|
|
if(characterData[14] == Zones.NO_ZONE):#If the character has no zone place him in venture explorer
|
|
self.DB.updateCharacterZone(Zones.VENTURE_EXPLORER, objectID)
|
|
characterData = self.DB.getCharacterDataByID(objectID)
|
|
self.loadWorld(objectID, int(characterData[14]), address)
|
|
elif(data[0:3] == b"\x04\x00\x13"):#Load character
|
|
self.log("Lego Packet was Client Loading Complete")
|
|
session = self.DB.getSessionByAddress(address[0])
|
|
characterData = self.DB.getCharacterDataByID(session[4])
|
|
zoneData = BitStream(data[7:])
|
|
zoneID = zoneData.read(c_ushort)
|
|
accountData = self.DB.getAccountByAccountID(characterData[1])
|
|
#START OF HEADER
|
|
charHeader = BitStream()
|
|
charHeader.write(c_ubyte(Message.LegoPacket)) # MSG ID
|
|
charHeader.write(c_ushort(0x05)) # Connection Type (UShort)
|
|
charHeader.write(c_ulong(0x04)) # Internal Packet ID (ULong)
|
|
charHeader.write(c_ubyte(0x00)) # Internal Packet ID (Uchar)
|
|
##END OF HEADER
|
|
#Start of LDF
|
|
LDF = BitStream()
|
|
|
|
keyNumber = 0
|
|
|
|
accountIDKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"accountID".__len__()*2)))
|
|
accountIDKeyAdj.write("accountID", allocated_length=(b"accountID".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(accountIDKeyAdj[:-2])
|
|
LDF.write(c_ubyte(8)) # Write data format 8
|
|
LDF.write(c_int64(int(accountData[0])))#s64#Write int(characterData[1])
|
|
keyNumber = keyNumber + 1
|
|
|
|
chatmodeKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"chatmode".__len__() * 2)))
|
|
chatmodeKeyAdj.write("chatmode", allocated_length=(b"chatmode".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(chatmodeKeyAdj[:-2])
|
|
LDF.write(c_ubyte(1)) # Write data format 1
|
|
LDF.write(c_int(int(accountData[4])))#Write int(accountData[4])
|
|
keyNumber = keyNumber + 1
|
|
|
|
editor_enabledKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"editor_enabled".__len__() * 2)))
|
|
editor_enabledKeyAdj.write("editor_enabled", allocated_length=(b"editor_enabled".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(editor_enabledKeyAdj[:-2])
|
|
LDF.write(c_ubyte(7)) # Write data format 7
|
|
LDF.write(c_bool(False))#Write False?
|
|
keyNumber = keyNumber + 1
|
|
|
|
editor_levelKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"editor_level".__len__() * 2)))
|
|
editor_levelKeyAdj.write("editor_level", allocated_length=(b"editor_level".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(editor_levelKeyAdj[:-2])
|
|
LDF.write(c_ubyte(1)) # Write data format 1
|
|
LDF.write(c_int(0))#Write 0?
|
|
keyNumber = keyNumber + 1
|
|
|
|
gmlevelKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"gmlevel".__len__() * 2)))
|
|
gmlevelKeyAdj.write("gmlevel", allocated_length=(b"gmlevel".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(gmlevelKeyAdj[:-2])
|
|
LDF.write(c_ubyte(1)) # Write data format 1
|
|
LDF.write(c_int(int(0)))#Write int(accountData[4])
|
|
keyNumber = keyNumber + 1
|
|
|
|
levelidKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"levelid".__len__() * 2)))
|
|
levelidKeyAdj.write("levelid", allocated_length=(b"levelid".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(levelidKeyAdj[:-2])
|
|
LDF.write(c_ubyte(8)) # Write data format 8
|
|
LDF.write(c_int64(zoneID))#s64#Write int(zoneID)
|
|
keyNumber = keyNumber + 1
|
|
|
|
objidKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"objid".__len__() * 2)))
|
|
objidKeyAdj.write("objid", allocated_length=(b"objid".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(objidKeyAdj[:-2])#Remove 2 unnecessary bits
|
|
LDF.write(c_ubyte(9)) # Write data format 9
|
|
LDF.write(c_int64(int(characterData[3])))#Write int(characterData[3])
|
|
keyNumber = keyNumber + 1
|
|
|
|
reputationKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"reputation".__len__() * 2)))
|
|
reputationKeyAdj.write("reputation", allocated_length=(b"reputation".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(reputationKeyAdj[:-2])
|
|
LDF.write(c_ubyte(8)) # Write data format 8
|
|
LDF.write(c_int64(100))#s64#Write 100
|
|
keyNumber = keyNumber + 1
|
|
|
|
templateKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"template".__len__() * 2)))
|
|
templateKeyAdj.write("template", allocated_length=(b"template".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(templateKeyAdj[:-2])#Remove 2 unnecessary bits
|
|
LDF.write(c_ubyte(1)) # Write data format 1
|
|
LDF.write(c_int(1))#Write 1
|
|
keyNumber = keyNumber + 1 #Update key number
|
|
|
|
|
|
xml = '<?xml version="1.0"?><obj v="1"><buff/><skill/>'#Basic start of xml
|
|
xml = xml + '<inv><bag><b t="0" m="'+str(characterData[24])+'"/></bag>'#Inventory bag space
|
|
xml = xml + '<items><in>'#Items in inventory setup
|
|
LOT, OBJECT, QUANTITY, LINKED, SPAWNERID, SLOT = self.DB.getInventoryInfo(characterData[3])
|
|
for i in range(len(LOT)):#Add all the items in inventory
|
|
baseItem = '<i l="'+str(LOT[i][0])+'" id ="'+str(OBJECT[i])+'" s="'+str(SLOT[i])+'"'
|
|
if(QUANTITY[i] > 1):
|
|
baseItem = baseItem + ' c="'+str(QUANTITY[i])+'"'
|
|
if(SPAWNERID[i] != None):
|
|
if(SPAWNERID > -1):
|
|
baseItem = baseItem + ' sk="'+str(SPAWNERID[i])+'"'
|
|
if(LINKED[i] == 1):
|
|
baseItem = baseItem + ' b="1"'
|
|
if(SPAWNERID[i] != None):
|
|
if(SPAWNERID > -1):
|
|
#Do rocket stuff here
|
|
self.log("Spawner ids are not implemented yet")#A simple implementation can probably be found in the LUNI file WorldConnection.cpp
|
|
baseItem = baseItem + '/>'
|
|
xml = xml + baseItem
|
|
xml = xml + '</in></items></inv>'#Close inventory
|
|
xml = xml + '<mf/><char cc="'+str(characterData[21])+'"></char>'#Currency
|
|
xml = xml + '<lvl l="'+str(characterData[20])+'"/><flag/><pet/>'#Level and flag and pet
|
|
completedMissions = self.DB.getCompletedMissions(characterData[3])
|
|
currentMissions = self.DB.getCurrentMissions(characterData[3])
|
|
if(completedMissions != None or currentMissions != None):#If there are completed missions or current missions write them to the xml
|
|
missionData = '<mis>'
|
|
if(completedMissions != None):
|
|
missionData = missionData + "<done>"
|
|
for mission in completedMissions:
|
|
missionData = missionData + '<m id="'+str(mission[0])+'" cts="0" cct="1"/>'
|
|
missionData = missionData + "</done>"
|
|
if(currentMissions != None):
|
|
missionData = missionData + "<cur>"
|
|
for mission in currentMissions:
|
|
print("mission")
|
|
missionData = missionData + '<m id="'+str(mission[0])+'" />'
|
|
missionData = missionData + "</cur></mis>"
|
|
else:
|
|
missionData = missionData + "</mis>"
|
|
xml = xml + missionData
|
|
else:
|
|
xml = xml + '</mis>'#If there are no missions write nothing
|
|
xml = xml + "<mnt/><dest/></obj>"#Idk what these three are. Should probably find that out
|
|
|
|
xmlKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"xmlData".__len__() * 2)))
|
|
xmlKeyAdj.write("xmlData", allocated_length=(b"xmlData".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(xmlKeyAdj[:-2])
|
|
LDF.write(c_ubyte(13)) # Write data format
|
|
LDF.write(c_ulong((xml.__len__()+1))) # xml length
|
|
LDF.write(xml, allocated_length=(len(xml)+1), char_size=1) # xml data
|
|
keyNumber = keyNumber + 1
|
|
|
|
nameKeyAdj = BitStream()
|
|
LDF.write(c_ubyte((b"name".__len__() * 2)))
|
|
nameKeyAdj.write("name", allocated_length=(b"name".__len__()*2)+2) # Write encoded key as bits
|
|
LDF.write(nameKeyAdj[:-2])
|
|
LDF.write(c_ubyte(0)) # Write data format 0
|
|
LDF.write(c_uint((str(characterData[2]).__len__()*2)+2))#Write String Length
|
|
LDF.write(str(characterData[2]), allocated_length=(str(characterData[2]).__len__()*2)+2) # String
|
|
keyNumber = keyNumber + 1
|
|
|
|
adjLDF = BitStream()#Create Final LDF Stream
|
|
adjLDF.write(c_uint(keyNumber))#Add Key Number
|
|
adjLDF.write(LDF)#Add LDF
|
|
|
|
Bitsize = len(adjLDF) + 5 # Adjust for the ulong and bool
|
|
finalPacket = BitStream() # Create new packet
|
|
finalPacket.write_bits(charHeader) # Write the header
|
|
finalPacket.write(c_ulong(Bitsize)) # The size of the following data including the bool and ulong
|
|
finalPacket.write(c_bool(False)) # Is compressed. LUNI has it set to false so I'll leave it there.
|
|
|
|
finalPacket.write(adjLDF) # Writes all the LDF data
|
|
|
|
self.send(finalPacket, address, reliability=PacketReliability.ReliableOrdered)
|
|
|
|
self.log("Sent Detailed User Info")
|
|
|
|
self.createObjectsForWorld(zoneID, address)
|
|
|
|
#Add Base Data
|
|
Player = BaseData()
|
|
Player.objectID = c_int64(int(characterData[3]))
|
|
Player.LOT = c_long(1)
|
|
Player.flag6 = True
|
|
Player.NameLength = (str(characterData[2]).__len__())
|
|
Player.Name = str(characterData[2])
|
|
|
|
#Add Controllable Physics
|
|
ControllablePhysics = ControllablePhysicsComponent()
|
|
ControllablePhysics.flag2 = True
|
|
ControllablePhysics.flag4 = True
|
|
ControllablePhysics.vectorFlag = True
|
|
ControllablePhysics.xPos = c_float(int(characterData[17]))
|
|
ControllablePhysics.yPos = c_float(int(characterData[18]))
|
|
ControllablePhysics.zPos = c_float(int(characterData[19]))
|
|
ControllablePhysics.xRot = c_float(int(characterData[31]))
|
|
ControllablePhysics.yRot = c_float(int(characterData[32]))
|
|
ControllablePhysics.zRot = c_float(int(characterData[33]))
|
|
ControllablePhysics.wRot = c_float(int(characterData[34]))
|
|
ControllablePhysics.onGround=True
|
|
|
|
|
|
#Add Destructible
|
|
Destructible = DestructibleIndex()
|
|
Destructible.flag1 = False
|
|
|
|
#Add Stats
|
|
Stats = StatsIndex()
|
|
Stats.flag1 = True
|
|
Stats.currentHealth = c_ulong(characterData[26])
|
|
Stats.maxHealth = c_float(characterData[25])
|
|
Stats.currentArmor = c_ulong(characterData[28])
|
|
Stats.maxArmor = c_float(characterData[27])
|
|
Stats.currentImagination = c_ulong(characterData[30])
|
|
Stats.maxImagination = c_float(characterData[29])
|
|
Stats.flag2 = True
|
|
|
|
#Add Character Component
|
|
Character = CharacterComponent()
|
|
Character.hasLevel = True
|
|
Character.level = c_ulong(characterData[20])
|
|
info = PlayerInfo()
|
|
info.setInfo(self.DB, characterData[3])
|
|
Character.info = info
|
|
style = PlayerStyle()
|
|
style.setStyle(self.DB, characterData[3])
|
|
Character.style = style
|
|
data9 = Component4_Data9()
|
|
Character.data9 = data9
|
|
data11 = Component4_Data11()
|
|
Character.data11 = data11
|
|
|
|
#Add Inventory
|
|
Inventory = InventoryComponent(self.DB)
|
|
Inventory.flag1 = True
|
|
Inventory.characterObjID = characterData[3]
|
|
|
|
#Add Script
|
|
Script = ScriptComponent()
|
|
|
|
#Add Skill
|
|
Skill = SkillComponent()
|
|
|
|
#Add Render
|
|
Render = RenderComponent()
|
|
|
|
#Add Component 107
|
|
Comp107 = Component107()
|
|
Comp107.flag1 = True
|
|
|
|
PlayerComponents = [Player, ControllablePhysics, Destructible, Stats, Character, Inventory, Script, Skill, Render, Comp107]
|
|
player = GameObject()
|
|
player.components = PlayerComponents
|
|
player.tag = "Player"
|
|
for mission in completedMissions:
|
|
player.CompletedMissions.append(mission)
|
|
for mission in currentMissions:
|
|
player.CompletedMissions.append(mission)
|
|
self.createObject(characterData[2], 1, int(characterData[3]), zoneID, int(characterData[17]), int(characterData[18]), int(characterData[19]), 0.0, 0.0, 0.0, 0.0, RO=player, message="Sent Player Construction")
|
|
|
|
self.GM.SendGameMessage(1642, int(characterData[3]), address)#Server done loading all objects
|
|
self.GM.SendGameMessage(509, int(characterData[3]), address) # Player ready
|
|
|
|
elif(data[0:3] == b"\x04\x00\x05"):
|
|
message = BitStream(data[7:])
|
|
objID = message.read(c_longlong)
|
|
msgID = message.read(c_ushort)
|
|
self.EM.runEvent("GM_"+str(msgID), [objID, copy.deepcopy(message)])
|
|
if(str(msgID) == "1485"):
|
|
return
|
|
elif(str(msgID) == "41"):
|
|
self.log("Got GM 'Play Emote'")
|
|
emoteID = message.read(c_int)
|
|
targetID = message.read(c_longlong)
|
|
self.log("Emote ID:" + str(emoteID) + ", Target ID: " + str(targetID))
|
|
elif(str(msgID) == "505"):
|
|
playerID = message.read(c_longlong)
|
|
self.log("Player with ID: " + str(playerID) + " has loaded")
|
|
elif(str(msgID) == "888"):#Object needs an update
|
|
return
|
|
elif(str(msgID) == "767"):
|
|
return
|
|
elif(str(msgID) == "1474"):
|
|
return
|
|
elif(str(msgID) == "768"):
|
|
#SetGhostReferencePosition
|
|
xPos = message.read(c_float)
|
|
yPos = message.read(c_float)
|
|
zPos = message.read(c_float)
|
|
elif(str(msgID) == "249"):#Respond to mission
|
|
missionID = message.read(c_int)
|
|
player = message.read(c_longlong)
|
|
receiver = message.read(c_longlong)
|
|
reward = None
|
|
try:
|
|
reward = message.read(c_long)
|
|
except:
|
|
pass
|
|
if(reward != None):
|
|
print("Reward: " + str(reward))#TODO: Give award?
|
|
elif(str(msgID) == "520"):
|
|
complete = message.read(c_bit)
|
|
state = message.read(c_int)
|
|
missionID = message.read(c_int)
|
|
responder = message.read(c_longlong)
|
|
|
|
task = self.DB.getMissionTaskType(missionID)[0][0]
|
|
|
|
NotifyMissionTask = self.GM.InitGameMessage(255, responder)
|
|
NotifyMissionTask.write(c_int(missionID))
|
|
NotifyMissionTask.write(c_int(1 << (task + 1)))
|
|
NotifyMissionTask.write(c_uint8(0))
|
|
self.send(NotifyMissionTask, address)
|
|
|
|
NotifyMission = self.GM.InitGameMessage(254, responder)
|
|
NotifyMission.write(c_int(missionID))
|
|
if(complete == False):
|
|
NotifyMission.write(c_int(2)) # Mission state: Active
|
|
self.SavedObjects[responder].CurrentMissions.append(missionID)
|
|
self.SavedObjects[responder].CurrentMissionStates[missionID] = 0
|
|
else:#Mission was completed
|
|
self.SavedObjects[responder].CurrentMissions.remove(missionID)
|
|
self.SavedObjects[responder].CompletedMissions.append(missionID)
|
|
del self.SavedObjects[responder].CurrentMissionStates[missionID]
|
|
NotifyMission.write(c_int(8)) #Mission state: Completed
|
|
NotifyMission.write(c_bit(False)) # Sending rewards
|
|
self.send(NotifyMission, address)
|
|
elif(str(msgID) == "124"):
|
|
#SelectSkill
|
|
fromSkillSet = message.read(c_bit)
|
|
skillID = message.read(c_long)
|
|
self.log("Select Skill " + str(skillID))
|
|
elif(str(msgID) == "1202"):#Player requested to be smashed
|
|
self.killPlayer(objID)
|
|
elif(str(msgID) == "159"):#Resurect
|
|
self.resurrect(objID)
|
|
elif(str(msgID) == "364"):#Interaction
|
|
multiInteractUse = message.read(c_bit)
|
|
multiInteractID = message.read(c_ulong)
|
|
multiInteractType = message.read(c_int)
|
|
object = message.read(c_longlong)
|
|
secondary = message.read(c_bit)
|
|
self.handleInteraction(multiInteractUse, multiInteractID, multiInteractType, object, secondary, objID)
|
|
elif(str(msgID) == "486"):#Something was collected
|
|
player = message.read(c_longlong)#TODO: Add stats to player's current stats
|
|
else:
|
|
self.log("Message id of "+ str(msgID) +" currently has no handler and is not defined!")
|
|
self.unhandledGMs.append((msgID, objID))
|
|
elif(data[0:3] == b"\x04\x00\x15"):
|
|
#This needs to be figured out how to implement
|
|
self.log("Lego Packet was 'Some Kind of Indicator This Packet Should Be Routed'????")
|
|
#self.log(data[11:])
|
|
elif(data[0:3] == b"\x04\x00\x16"):
|
|
#self.log("[" + self.role + "]" + "Lego Packet was Position/Rotation Update")
|
|
session = self.DB.getSessionByAddress(address[0])
|
|
info = BitStream(data[7:])
|
|
xPos = info.read(c_float)
|
|
yPos = info.read(c_float)
|
|
zPos = info.read(c_float)
|
|
xRot = info.read(c_float)
|
|
yRot = info.read(c_float)
|
|
zRot = info.read(c_float)
|
|
wRot = info.read(c_float)
|
|
try:
|
|
self.updatePlayerLoc(session[4], xPos, yPos, zPos, xRot, yRot, zRot, wRot)
|
|
except:
|
|
pass
|
|
|
|
else:
|
|
self.log("Received Unknown Packet:")
|
|
self.log(data) |