From e4a83aaa6ef344f3315ebf84c8ec8e1fd526b2fc Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 05:43:27 +0100 Subject: [PATCH 01/14] Message types. Skeleton of AstronClientRepository.py. --- .../src/distributed/AstronClientRepository.py | 192 ++++++++++++++++++ direct/src/distributed/MsgTypesAstron.py | 32 +++ 2 files changed, 224 insertions(+) create mode 100644 direct/src/distributed/AstronClientRepository.py create mode 100644 direct/src/distributed/MsgTypesAstron.py diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py new file mode 100644 index 0000000000..85a5938ae9 --- /dev/null +++ b/direct/src/distributed/AstronClientRepository.py @@ -0,0 +1,192 @@ +"""AstronClientRepository module: contains the AstronClientRepository class""" + +from ClientRepositoryBase import ClientRepositoryBase +from MsgTypesAstron import * + +class AstronClientRepository(ClientRepositoryBase): + """ + The Astron implementation of a clients repository for + communication with an Astron ClientAgent. + """ + + def __init__(self, *args, **kwargs): + ClientRepositoryBase.__init__(self, *args, **kwargs) + base.finalExitCallbacks.append(self.shutdown) + # FIXME: Partial code from ClientRepository.py may be required here. + + # + # Message Handling + # + + def handleDatagram(self, di): + + msgType = self.getMsgType() + + # These are the messages to a client that Astron specifies. + + if msgType == CLIENT_HELLO_RESP: + messenger.send("CLIENT_HELLO_RESP", []) + elif msgType == CLIENT_EJECT: + error_code = di.get_uint16() + reason = di.get_string() + messenger.send("CLIENT_EJECT", [error_code, reason]) + elif msgType == CLIENT_ENTER_OBJECT_REQUIRED: + self.handleEnterObjectRequired(di) + elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OWNER: + self.handleEnterObjectRequiredOwner(di) + # FIXME: These are supposedly handled in cConnectionRepository + #elif msgType == CLIENT_OBJECT_SET_FIELD: + # self.handleObjectSetField(di) + #elif msgType == CLIENT_OBJECT_SET_FIELDS: + # self.handleObjectSetFields(di) + elif msgType == CLIENT_OBJECT_LEAVING: + self.handleObjectLeaving(di) + elif msgType == CLIENT_OBJECT_LOCATION: + self.handleObjectLocation(di) + elif msgType == CLIENT_ADD_INTEREST: + self.handleAddInterest(di) + elif msgType == CLIENT_ADD_INTEREST_MULTIPLE: + self.handleAddInterestMultiple(di) + elif msgType == CLIENT_REMOVE_INTEREST: + self.handleRemoveInterest(di) + else: + self.handleMessageType(msgType, di) + + self.considerHeartbeat() + + def handleEnterObjectRequired(di) + do_id = di.getArg(STUint32) + parent_id = di.getArg(STUint32) + zone_id = di.getArg(STUint32) + dclass_id = di.getArg(STUint16) + dclass = self.dclassesByNumber[dclass_id] + self.generateWithRequiredFields(dclass, do_id, di, parent_id, zone_id) + + def handleEnterObjectRequiredOwner(di) + avatar_doId = di.getArg(STUint32) + parentId = di.getArg(STUint32) + zoneId = di.getArg(STUint32) + dclass_id = di.getArg(STUint16) + dclass = self.dclassesByNumber[dclass_id] + self.generateWithRequiredFieldsOwner(dclass, avatar_doId, di) + + def generateWithRequiredFieldsOwner(self, dclass, doId, di): + if doId in self.doId2ownerView: + # ...it is in our dictionary. + # Just update it. + self.notify.error('duplicate owner generate for %s (%s)' % ( + doId, dclass.getName())) + distObj = self.doId2ownerView[doId] + assert distObj.dclass == dclass + distObj.generate() + distObj.updateRequiredFields(dclass, di) + # updateRequiredFields calls announceGenerate + elif self.cacheOwner.contains(doId): + # ...it is in the cache. + # Pull it out of the cache: + distObj = self.cacheOwner.retrieve(doId) + assert distObj.dclass == dclass + # put it in the dictionary: + self.doId2ownerView[doId] = distObj + # and update it. + distObj.generate() + distObj.updateRequiredFields(dclass, di) + # updateRequiredFields calls announceGenerate + else: + # ...it is not in the dictionary or the cache. + # Construct a new one + classDef = dclass.getOwnerClassDef() + if classDef == None: + self.notify.error("Could not create an undefined %s object. Have you created an owner view?" % (dclass.getName())) + distObj = classDef(self) + distObj.dclass = dclass + # Assign it an Id + distObj.doId = doId + # Put the new do in the dictionary + self.doId2ownerView[doId] = distObj + # Update the required fields + distObj.generateInit() # Only called when constructed + distObj.generate() + distObj.updateRequiredFields(dclass, di) + # updateRequiredFields calls announceGenerate + return distObj + + def handleObjectSetField(di): + do_id = di.getArg(STUint32) + field_id = di.getArg(STUint16) + # FIXME: Is this really the best way? + do = self.doId2do[do_id] + # FIXME: Figure out field types and unpack them, or use + # some code that auto-unpacks them. + field_name = self.get_dc_file().get_field_by_index(field_id).get_name() + # FIXME: You actually need to figure out the fields types and unpack them! + self.sendUpdate(field_name, [fieldArguments]) + + def handleObjectSetFields(di): + # FIXME: Implement this! + pass + + def handleObjectLeaving(di): + # FIXME: Implement this! + pass + + def handleObjectLocation(di): + # FIXME: Implement this! + pass + + def handleAddInterest(di): + # FIXME: Implement this! + pass + + def handleAddInterestMultiple(di): + # FIXME: Implement this! + pass + + def handleRemoveInterest(di): + # FIXME: Implement this! + pass + + # + # Sending messages + # + + # FIXME: The version string should default to a .prc variable. + def sendHello(self, version_string): + dg = PyDatagram() + dg.add_uint16(MsgTypes.CLIENT_HELLO) + dg.add_uint32(self.get_dc_file().get_hash()) + dg.add_string(version_string) + self.send(dg) + + def sendHeartbeat(self): + datagram = PyDatagram() + datagram.addUint16(CLIENT_HEARTBEAT) + self.send(datagram) + + def sendAddInterest(self, context, interest_id, parent_id, zone_id): + dg = PyDatagram() + dg.add_uint16(MsgTypes.CLIENT_ADD_INTEREST) + dg.add_uint32(context) + dg.add_uint16(interest_id) + dg.add_uint32(parent_id) + dg.add_uint32(zone_id) + self.send(dg) + + def sendAddInterestMultiple(self, context, interest_id, parent_id, zone_ids): + dg = PyDatagram() + dg.add_uint16(MsgTypes.CLIENT_ADD_INTEREST_MULTIPLE) + dg.add_uint32(context) + dg.add_uint16(interest_id) + dg.add_uint32(parent_id) + dg.add_uint16(len(zone_ids)) + for zone_id in zone_ids: + dg.add_uint32(zone_id) + self.send(dg) + + def sendRemoveInterest(self, context, interest_id): + dg = PyDatagram() + dg.add_uint16(MsgTypes.CLIENT_REMOVE_INTEREST) + dg.add_uint32(context) + dg.add_uint16(interest_id) + self.send(dg) + diff --git a/direct/src/distributed/MsgTypesAstron.py b/direct/src/distributed/MsgTypesAstron.py new file mode 100644 index 0000000000..5e94797361 --- /dev/null +++ b/direct/src/distributed/MsgTypesAstron.py @@ -0,0 +1,32 @@ +"""MsgTypesAstron module: contains distributed object message types""" + +from direct.showbase.PythonUtil import invertDictLossless + +MsgName2Id = { + 'CLIENT_HELLO': 1, + 'CLIENT_HELLO_RESP': 2, + 'CLIENT_DISCONNECT': 3, + 'CLIENT_EJECT': 4, + 'CLIENT_HEARTBEAT': 5, + 'CLIENT_ENTER_OBJECT_REQUIRED': 142, + 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER': 143, + 'CLIENT_ENTER_OBJECT_REQUIRED_OWNER': 172, + 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER': 173, + 'CLIENT_OBJECT_SET_FIELD': 120, + 'CLIENT_OBJECT_SET_FIELDS': 121, + 'CLIENT_OBJECT_LEAVING': 132, + 'CLIENT_OBJECT_LOCATION': 140, + 'CLIENT_ADD_INTEREST': 200, + 'CLIENT_ADD_INTEREST_MULTIPLE': 201, + 'CLIENT_REMOVE_INTEREST': 203, + 'CLIENT_DONE_INTEREST_RESP': 204, + } + +# create id->name table for debugging +MsgId2Names = invertDictLossless(MsgName2Id) + +# put msg names in module scope, assigned to msg value +for name, value in MsgName2Id.items(): + exec '%s = %s' % (name, value) +del name, value + From 743f6cc55c9911904ee4bedc2b053b080ea567ad Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 08:54:44 +0100 Subject: [PATCH 02/14] First bugfixes during testing. --- .../src/distributed/AstronClientRepository.py | 84 +++++++++++-------- direct/src/distributed/DistributedNode.py | 1 + 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 85a5938ae9..bbc872408f 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -1,14 +1,23 @@ """AstronClientRepository module: contains the AstronClientRepository class""" +from direct.directnotify import DirectNotifyGlobal from ClientRepositoryBase import ClientRepositoryBase from MsgTypesAstron import * +from direct.distributed.PyDatagram import PyDatagram +from pandac.PandaModules import STUint16, STUint32 class AstronClientRepository(ClientRepositoryBase): """ The Astron implementation of a clients repository for communication with an Astron ClientAgent. """ - + + notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository") + + # This is required by DoCollectionManager, even though it's not + # used by this implementation. + GameGlobalsId = 0 + def __init__(self, *args, **kwargs): ClientRepositoryBase.__init__(self, *args, **kwargs) base.finalExitCallbacks.append(self.shutdown) @@ -18,9 +27,10 @@ class AstronClientRepository(ClientRepositoryBase): # Message Handling # - def handleDatagram(self, di): + #def handleDatagram(self, di): + #msgType = self.getMsgType() - msgType = self.getMsgType() + def handleMessageType(self, msgType, di): # These are the messages to a client that Astron specifies. @@ -54,7 +64,7 @@ class AstronClientRepository(ClientRepositoryBase): self.considerHeartbeat() - def handleEnterObjectRequired(di) + def handleEnterObjectRequired(self, di): do_id = di.getArg(STUint32) parent_id = di.getArg(STUint32) zone_id = di.getArg(STUint32) @@ -62,7 +72,7 @@ class AstronClientRepository(ClientRepositoryBase): dclass = self.dclassesByNumber[dclass_id] self.generateWithRequiredFields(dclass, do_id, di, parent_id, zone_id) - def handleEnterObjectRequiredOwner(di) + def handleEnterObjectRequiredOwner(self, di): avatar_doId = di.getArg(STUint32) parentId = di.getArg(STUint32) zoneId = di.getArg(STUint32) @@ -111,40 +121,40 @@ class AstronClientRepository(ClientRepositoryBase): # updateRequiredFields calls announceGenerate return distObj - def handleObjectSetField(di): - do_id = di.getArg(STUint32) - field_id = di.getArg(STUint16) - # FIXME: Is this really the best way? - do = self.doId2do[do_id] - # FIXME: Figure out field types and unpack them, or use - # some code that auto-unpacks them. - field_name = self.get_dc_file().get_field_by_index(field_id).get_name() - # FIXME: You actually need to figure out the fields types and unpack them! - self.sendUpdate(field_name, [fieldArguments]) + def handleObjectSetField(self, di): + do_id = di.getArg(STUint32) + field_id = di.getArg(STUint16) + # FIXME: Is this really the best way? + do = self.doId2do[do_id] + # FIXME: Figure out field types and unpack them, or use + # some code that auto-unpacks them. + field_name = self.get_dc_file().get_field_by_index(field_id).get_name() + # FIXME: You actually need to figure out the fields types and unpack them! + self.sendUpdate(field_name, [fieldArguments]) - def handleObjectSetFields(di): - # FIXME: Implement this! - pass + def handleObjectSetFields(self, di): + # FIXME: Implement this! + pass - def handleObjectLeaving(di): - # FIXME: Implement this! - pass + def handleObjectLeaving(self, di): + # FIXME: Implement this! + pass - def handleObjectLocation(di): - # FIXME: Implement this! - pass + def handleObjectLocation(self, di): + # FIXME: Implement this! + pass - def handleAddInterest(di): - # FIXME: Implement this! - pass + def handleAddInterest(self, di): + # FIXME: Implement this! + pass - def handleAddInterestMultiple(di): - # FIXME: Implement this! - pass + def handleAddInterestMultiple(self, di): + # FIXME: Implement this! + pass - def handleRemoveInterest(di): - # FIXME: Implement this! - pass + def handleRemoveInterest(self, di): + # FIXME: Implement this! + pass # # Sending messages @@ -153,7 +163,7 @@ class AstronClientRepository(ClientRepositoryBase): # FIXME: The version string should default to a .prc variable. def sendHello(self, version_string): dg = PyDatagram() - dg.add_uint16(MsgTypes.CLIENT_HELLO) + dg.add_uint16(CLIENT_HELLO) dg.add_uint32(self.get_dc_file().get_hash()) dg.add_string(version_string) self.send(dg) @@ -165,7 +175,7 @@ class AstronClientRepository(ClientRepositoryBase): def sendAddInterest(self, context, interest_id, parent_id, zone_id): dg = PyDatagram() - dg.add_uint16(MsgTypes.CLIENT_ADD_INTEREST) + dg.add_uint16(CLIENT_ADD_INTEREST) dg.add_uint32(context) dg.add_uint16(interest_id) dg.add_uint32(parent_id) @@ -174,7 +184,7 @@ class AstronClientRepository(ClientRepositoryBase): def sendAddInterestMultiple(self, context, interest_id, parent_id, zone_ids): dg = PyDatagram() - dg.add_uint16(MsgTypes.CLIENT_ADD_INTEREST_MULTIPLE) + dg.add_uint16(CLIENT_ADD_INTEREST_MULTIPLE) dg.add_uint32(context) dg.add_uint16(interest_id) dg.add_uint32(parent_id) @@ -185,7 +195,7 @@ class AstronClientRepository(ClientRepositoryBase): def sendRemoveInterest(self, context, interest_id): dg = PyDatagram() - dg.add_uint16(MsgTypes.CLIENT_REMOVE_INTEREST) + dg.add_uint16(CLIENT_REMOVE_INTEREST) dg.add_uint32(context) dg.add_uint16(interest_id) self.send(dg) diff --git a/direct/src/distributed/DistributedNode.py b/direct/src/distributed/DistributedNode.py index 353b001cc2..af4aa10e82 100644 --- a/direct/src/distributed/DistributedNode.py +++ b/direct/src/distributed/DistributedNode.py @@ -17,6 +17,7 @@ class DistributedNode(DistributedObject.DistributedObject, NodePath): self.DistributedNode_initialized = 1 self.gotStringParentToken = 0 DistributedObject.DistributedObject.__init__(self, cr) + NodePath.__init__(self, "DistributedNode") # initialize gridParent self.gridParent = None From 9752736dbcee98b3ba102a945976f895b15f33f9 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 09:46:41 +0100 Subject: [PATCH 03/14] Prevented infinite loop on handleMessageType. Added debug prints. --- direct/src/distributed/AstronClientRepository.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index bbc872408f..3c1e95b0e2 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -35,6 +35,7 @@ class AstronClientRepository(ClientRepositoryBase): # These are the messages to a client that Astron specifies. if msgType == CLIENT_HELLO_RESP: + print("Hello back!") messenger.send("CLIENT_HELLO_RESP", []) elif msgType == CLIENT_EJECT: error_code = di.get_uint16() @@ -60,7 +61,8 @@ class AstronClientRepository(ClientRepositoryBase): elif msgType == CLIENT_REMOVE_INTEREST: self.handleRemoveInterest(di) else: - self.handleMessageType(msgType, di) + print("Passing unknown message type "+str(msgType)) + ClientRepositoryBase.handleMessageType(self, msgType, di) self.considerHeartbeat() @@ -167,6 +169,8 @@ class AstronClientRepository(ClientRepositoryBase): dg.add_uint32(self.get_dc_file().get_hash()) dg.add_string(version_string) self.send(dg) + # FIXME: Remove debug print + print("Hello!") def sendHeartbeat(self): datagram = PyDatagram() From 659d7f4073fee7e032d6ed62ff736fd0c985c554 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 10:08:06 +0100 Subject: [PATCH 04/14] Overwrite handleDatagram to get CLIENT_HELLO_RESP, which otherwise gets swallowed. Cleanup. --- direct/src/distributed/AstronClientRepository.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 3c1e95b0e2..663752c77b 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -27,15 +27,15 @@ class AstronClientRepository(ClientRepositoryBase): # Message Handling # - #def handleDatagram(self, di): - #msgType = self.getMsgType() + def handleDatagram(self, di): + msgType = self.getMsgType() + self.handleMessageType(msgType, di) def handleMessageType(self, msgType, di): # These are the messages to a client that Astron specifies. if msgType == CLIENT_HELLO_RESP: - print("Hello back!") messenger.send("CLIENT_HELLO_RESP", []) elif msgType == CLIENT_EJECT: error_code = di.get_uint16() @@ -60,9 +60,11 @@ class AstronClientRepository(ClientRepositoryBase): self.handleAddInterestMultiple(di) elif msgType == CLIENT_REMOVE_INTEREST: self.handleRemoveInterest(di) + elif msgType == CLIENT_DONE_INTEREST_RESP: + # FIXME: Unpack and send event + pass else: - print("Passing unknown message type "+str(msgType)) - ClientRepositoryBase.handleMessageType(self, msgType, di) + self.notify.error("Got unknown message type %d!" % (msgType,)) self.considerHeartbeat() @@ -169,8 +171,6 @@ class AstronClientRepository(ClientRepositoryBase): dg.add_uint32(self.get_dc_file().get_hash()) dg.add_string(version_string) self.send(dg) - # FIXME: Remove debug print - print("Hello!") def sendHeartbeat(self): datagram = PyDatagram() From cd5bb84890a3d6705af538ff38585355dbd5a307 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 12:11:58 +0100 Subject: [PATCH 05/14] Re-internalized CLIENTOBJECT_SET_FIELD. --- direct/src/distributed/AstronClientRepository.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 663752c77b..2245d6eed9 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -45,9 +45,9 @@ class AstronClientRepository(ClientRepositoryBase): self.handleEnterObjectRequired(di) elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OWNER: self.handleEnterObjectRequiredOwner(di) + elif msgType == CLIENT_OBJECT_SET_FIELD: + self.handleUpdateField(di) # FIXME: These are supposedly handled in cConnectionRepository - #elif msgType == CLIENT_OBJECT_SET_FIELD: - # self.handleObjectSetField(di) #elif msgType == CLIENT_OBJECT_SET_FIELDS: # self.handleObjectSetFields(di) elif msgType == CLIENT_OBJECT_LEAVING: @@ -134,6 +134,10 @@ class AstronClientRepository(ClientRepositoryBase): # some code that auto-unpacks them. field_name = self.get_dc_file().get_field_by_index(field_id).get_name() # FIXME: You actually need to figure out the fields types and unpack them! + print("do_id: %d" % (do_id,)) + print("do : %s" % (str(do),)) + print("do_t : %s" % (type(do),)) + print("field: %s" % (field_name,)) self.sendUpdate(field_name, [fieldArguments]) def handleObjectSetFields(self, di): @@ -164,6 +168,12 @@ class AstronClientRepository(ClientRepositoryBase): # Sending messages # + def sendUpdate(self, distObj, fieldName, args): + """ Sends a normal update for a single field. """ + dg = distObj.dclass.clientFormatUpdate( + fieldName, distObj.doId, args) + self.send(dg) + # FIXME: The version string should default to a .prc variable. def sendHello(self, version_string): dg = PyDatagram() From 53f14161ff9d85bfeafcd08e39c69f0cf05fb409 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Fri, 28 Feb 2014 13:49:55 +0100 Subject: [PATCH 06/14] Added several events. Cleanup. --- .../src/distributed/AstronClientRepository.py | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 2245d6eed9..0e0e593694 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -10,6 +10,15 @@ class AstronClientRepository(ClientRepositoryBase): """ The Astron implementation of a clients repository for communication with an Astron ClientAgent. + + This repo will emit events for: + * CLIENT_HELLO_RESP + * CLIENT_EJECT ( int error_code, string reason ) + * CLIENT_DONE_INTEREST_RESP" ( int context, int interest_id ) + * CLIENT_OBJECT_LEAVING ( int do_id ) + * CLIENT_ADD_INTEREST ( context, interest_id, parent_id, zone_id ) + * CLIENT_REMOVE_INTEREST ( context, interest_id ) + * LOST_CONNECTION () """ notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository") @@ -47,22 +56,35 @@ class AstronClientRepository(ClientRepositoryBase): self.handleEnterObjectRequiredOwner(di) elif msgType == CLIENT_OBJECT_SET_FIELD: self.handleUpdateField(di) - # FIXME: These are supposedly handled in cConnectionRepository - #elif msgType == CLIENT_OBJECT_SET_FIELDS: - # self.handleObjectSetFields(di) + # FIXME: This is supposedly handled in cConnectionRepository; see CLIENT_OBJECT_SET_FIELD + # elif msgType == CLIENT_OBJECT_SET_FIELDS: + # self.handleObjectSetFields(di) elif msgType == CLIENT_OBJECT_LEAVING: - self.handleObjectLeaving(di) + # FIXME: Doesn't this need to be handled in the repository? + do_id = di.get_uint32() + messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) elif msgType == CLIENT_OBJECT_LOCATION: + # FIXME: What does this even do??? self.handleObjectLocation(di) elif msgType == CLIENT_ADD_INTEREST: - self.handleAddInterest(di) + # FIXME: Doesn't this need to be handled in the repository? + context = di.get_uint32() + interest_id = di.get_uint16() + parent_id = di.get_uint32() + zone_id = di.get_uint32() + messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id]) elif msgType == CLIENT_ADD_INTEREST_MULTIPLE: - self.handleAddInterestMultiple(di) - elif msgType == CLIENT_REMOVE_INTEREST: - self.handleRemoveInterest(di) - elif msgType == CLIENT_DONE_INTEREST_RESP: - # FIXME: Unpack and send event + # FIXME: Informative event here pass + elif msgType == CLIENT_REMOVE_INTEREST: + # FIXME: Doesn't this need to be handled in the repository? + context = di.get_uint32() + interest_id = di.get_uint16() + messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) + elif msgType == CLIENT_DONE_INTEREST_RESP: + context = di.get_uint32() + interest_id = di.get_uint16 () + messenger.send("CLIENT_DONE_INTEREST_RESP", [context, interest_id]) else: self.notify.error("Got unknown message type %d!" % (msgType,)) @@ -125,45 +147,10 @@ class AstronClientRepository(ClientRepositoryBase): # updateRequiredFields calls announceGenerate return distObj - def handleObjectSetField(self, di): - do_id = di.getArg(STUint32) - field_id = di.getArg(STUint16) - # FIXME: Is this really the best way? - do = self.doId2do[do_id] - # FIXME: Figure out field types and unpack them, or use - # some code that auto-unpacks them. - field_name = self.get_dc_file().get_field_by_index(field_id).get_name() - # FIXME: You actually need to figure out the fields types and unpack them! - print("do_id: %d" % (do_id,)) - print("do : %s" % (str(do),)) - print("do_t : %s" % (type(do),)) - print("field: %s" % (field_name,)) - self.sendUpdate(field_name, [fieldArguments]) - - def handleObjectSetFields(self, di): - # FIXME: Implement this! - pass - - def handleObjectLeaving(self, di): - # FIXME: Implement this! - pass - def handleObjectLocation(self, di): # FIXME: Implement this! pass - def handleAddInterest(self, di): - # FIXME: Implement this! - pass - - def handleAddInterestMultiple(self, di): - # FIXME: Implement this! - pass - - def handleRemoveInterest(self, di): - # FIXME: Implement this! - pass - # # Sending messages # @@ -214,3 +201,10 @@ class AstronClientRepository(ClientRepositoryBase): dg.add_uint16(interest_id) self.send(dg) + # + # Other stuff + # + + def lostConnection(self): + messenger.send("LOST_CONNECTION") + From a6ff9bef01ef85947b3f14a61682960077ac11c3 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Sun, 2 Mar 2014 12:36:19 +0100 Subject: [PATCH 07/14] More message implementations. Better FIXMEs. --- .../src/distributed/AstronClientRepository.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 0e0e593694..d2e026dac9 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -30,7 +30,6 @@ class AstronClientRepository(ClientRepositoryBase): def __init__(self, *args, **kwargs): ClientRepositoryBase.__init__(self, *args, **kwargs) base.finalExitCallbacks.append(self.shutdown) - # FIXME: Partial code from ClientRepository.py may be required here. # # Message Handling @@ -56,28 +55,33 @@ class AstronClientRepository(ClientRepositoryBase): self.handleEnterObjectRequiredOwner(di) elif msgType == CLIENT_OBJECT_SET_FIELD: self.handleUpdateField(di) - # FIXME: This is supposedly handled in cConnectionRepository; see CLIENT_OBJECT_SET_FIELD - # elif msgType == CLIENT_OBJECT_SET_FIELDS: - # self.handleObjectSetFields(di) + elif msgType == CLIENT_OBJECT_SET_FIELDS: + # FIXME: There is no implementation in the repository for + # updating multiple Fields. + self.notify.error("CLIENT_OBJECT_SET_FIELDS not implemented!") elif msgType == CLIENT_OBJECT_LEAVING: - # FIXME: Doesn't this need to be handled in the repository? + # FIXME: Does this need handling by the repository? do_id = di.get_uint32() messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) elif msgType == CLIENT_OBJECT_LOCATION: # FIXME: What does this even do??? self.handleObjectLocation(di) elif msgType == CLIENT_ADD_INTEREST: - # FIXME: Doesn't this need to be handled in the repository? + # FIXME: Does this need handling by the repository? context = di.get_uint32() interest_id = di.get_uint16() parent_id = di.get_uint32() zone_id = di.get_uint32() messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id]) elif msgType == CLIENT_ADD_INTEREST_MULTIPLE: - # FIXME: Informative event here - pass + # FIXME: Does this need handling by the repository? + context = di.get_uint32() + interest_id = di.get_uint16() + parent_id = di.get_uint32() + zone_ids = [di.get_uint32() for i in range(0, di.get_uint16())] + messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids]) elif msgType == CLIENT_REMOVE_INTEREST: - # FIXME: Doesn't this need to be handled in the repository? + # FIXME: Does this need handling by the repository? context = di.get_uint32() interest_id = di.get_uint16() messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) @@ -148,7 +152,7 @@ class AstronClientRepository(ClientRepositoryBase): return distObj def handleObjectLocation(self, di): - # FIXME: Implement this! + # FIXME: What does this do? pass # From 4adc2f6a72f6793139a5db382c973e79a09c3487 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Sun, 2 Mar 2014 13:46:45 +0100 Subject: [PATCH 08/14] self.handleInterestDoneMessage invoked. Cleanup. --- direct/src/distributed/AstronClientRepository.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index d2e026dac9..70431bb86c 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -13,11 +13,12 @@ class AstronClientRepository(ClientRepositoryBase): This repo will emit events for: * CLIENT_HELLO_RESP - * CLIENT_EJECT ( int error_code, string reason ) - * CLIENT_DONE_INTEREST_RESP" ( int context, int interest_id ) - * CLIENT_OBJECT_LEAVING ( int do_id ) + * CLIENT_EJECT ( error_code, reason ) + * CLIENT_OBJECT_LEAVING ( do_id ) * CLIENT_ADD_INTEREST ( context, interest_id, parent_id, zone_id ) + * CLIENT_ADD_INTEREST_MULTIPLE ( icontext, interest_id, parent_id, [zone_ids] ) * CLIENT_REMOVE_INTEREST ( context, interest_id ) + * CLIENT_DONE_INTEREST_RESP ( context, interest_id ) * LOST_CONNECTION () """ @@ -64,28 +65,25 @@ class AstronClientRepository(ClientRepositoryBase): do_id = di.get_uint32() messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) elif msgType == CLIENT_OBJECT_LOCATION: - # FIXME: What does this even do??? self.handleObjectLocation(di) elif msgType == CLIENT_ADD_INTEREST: - # FIXME: Does this need handling by the repository? context = di.get_uint32() interest_id = di.get_uint16() parent_id = di.get_uint32() zone_id = di.get_uint32() messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id]) elif msgType == CLIENT_ADD_INTEREST_MULTIPLE: - # FIXME: Does this need handling by the repository? context = di.get_uint32() interest_id = di.get_uint16() parent_id = di.get_uint32() zone_ids = [di.get_uint32() for i in range(0, di.get_uint16())] messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids]) elif msgType == CLIENT_REMOVE_INTEREST: - # FIXME: Does this need handling by the repository? context = di.get_uint32() interest_id = di.get_uint16() messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) elif msgType == CLIENT_DONE_INTEREST_RESP: + self.handleInterestDoneMessage(di) # Implemented in DoInterestManager.py context = di.get_uint32() interest_id = di.get_uint16 () messenger.send("CLIENT_DONE_INTEREST_RESP", [context, interest_id]) From bf141562d3e97539e3e95705e88376674c056e6e Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Sun, 2 Mar 2014 17:03:24 +0100 Subject: [PATCH 09/14] Added DistributedObjectBase cleanup method. Implemented CLIENT_OBJECT_LEAVING. Bugfixed CLIENT_OBJECT_LOCATION. Some debug code. --- .../src/distributed/AstronClientRepository.py | 58 ++++++++++++++++--- .../src/distributed/DistributedObjectBase.py | 8 +++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 70431bb86c..9f8d848a2f 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -57,12 +57,22 @@ class AstronClientRepository(ClientRepositoryBase): elif msgType == CLIENT_OBJECT_SET_FIELD: self.handleUpdateField(di) elif msgType == CLIENT_OBJECT_SET_FIELDS: - # FIXME: There is no implementation in the repository for - # updating multiple Fields. + do_id = di.getUint32() + field_count = di.getUint16() + for i in range(0, field_count): + field_id = di.getUint16() + field = self.get_dc_file().get_field_by_index(field_id) + print(type(field)) + print(field) + # FIXME: Get field type, unpack value, create and send message. + # value = di.get?() + # Assemble new message self.notify.error("CLIENT_OBJECT_SET_FIELDS not implemented!") elif msgType == CLIENT_OBJECT_LEAVING: - # FIXME: Does this need handling by the repository? do_id = di.get_uint32() + dist_obj = self.doId2do.get(do_id) + dist_obj.delete() + self.deleteObject(do_id) messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) elif msgType == CLIENT_OBJECT_LOCATION: self.handleObjectLocation(di) @@ -84,9 +94,6 @@ class AstronClientRepository(ClientRepositoryBase): messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) elif msgType == CLIENT_DONE_INTEREST_RESP: self.handleInterestDoneMessage(di) # Implemented in DoInterestManager.py - context = di.get_uint32() - interest_id = di.get_uint16 () - messenger.send("CLIENT_DONE_INTEREST_RESP", [context, interest_id]) else: self.notify.error("Got unknown message type %d!" % (msgType,)) @@ -149,9 +156,42 @@ class AstronClientRepository(ClientRepositoryBase): # updateRequiredFields calls announceGenerate return distObj - def handleObjectLocation(self, di): - # FIXME: What does this do? - pass + def deleteObject(self, doId): + """ + implementation copied from ClientRepository.py + + Removes the object from the client's view of the world. This + should normally not be called directly except in the case of + error recovery, since the server will normally be responsible + for deleting and disabling objects as they go out of scope. + + After this is called, future updates by server on this object + will be ignored (with a warning message). The object will + become valid again the next time the server sends a generate + message for this doId. + + This is not a distributed message and does not delete the + object on the server or on any other client. + """ + if doId in self.doId2do: + # If it is in the dictionary, remove it. + obj = self.doId2do[doId] + # Remove it from the dictionary + del self.doId2do[doId] + # Disable, announce, and delete the object itself... + # unless delayDelete is on... + obj.deleteOrDelay() + if self.isLocalId(doId): + self.freeDoId(doId) + elif self.cache.contains(doId): + # If it is in the cache, remove it. + self.cache.delete(doId) + if self.isLocalId(doId): + self.freeDoId(doId) + else: + # Otherwise, ignore it + self.notify.warning( + "Asked to delete non-existent DistObj " + str(doId)) # # Sending messages diff --git a/direct/src/distributed/DistributedObjectBase.py b/direct/src/distributed/DistributedObjectBase.py index ba1d8a21bc..d378141e77 100755 --- a/direct/src/distributed/DistributedObjectBase.py +++ b/direct/src/distributed/DistributedObjectBase.py @@ -95,3 +95,11 @@ class DistributedObjectBase(DirectObject): def hasParentingRules(self): return self.dclass.getFieldByName('setParentingRules') != None + + def delete(self): + """ + Overwrite this to handle cleanup right before this object + gets deleted. + """ + pass + From 8edd5aa4fb7ab0976c33f9be508310324a2e10ac Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Wed, 9 Apr 2014 05:45:26 +0200 Subject: [PATCH 10/14] disconnect() now removes all distributed objects. --- direct/src/distributed/AstronClientRepository.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 9f8d848a2f..7f9585cff4 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -250,3 +250,11 @@ class AstronClientRepository(ClientRepositoryBase): def lostConnection(self): messenger.send("LOST_CONNECTION") + def disconnect(self): + """ + This implicitly deletes all objects from the repository. + """ + for do_id in self.doId2do.keys(): + print("Deleting DO "+str(do_id)) + self.deleteObject(do_id) + ClientRepositoryBase.disconnect(self) From 06a082362d361f4c57169772f8b8e1b6ea8cf3a2 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Wed, 9 Apr 2014 05:45:26 +0200 Subject: [PATCH 11/14] disconnect() now removes all distributed objects. --- direct/src/distributed/AstronClientRepository.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 9f8d848a2f..a1a92bc4de 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -250,3 +250,10 @@ class AstronClientRepository(ClientRepositoryBase): def lostConnection(self): messenger.send("LOST_CONNECTION") + def disconnect(self): + """ + This implicitly deletes all objects from the repository. + """ + for do_id in self.doId2do.keys(): + self.deleteObject(do_id) + ClientRepositoryBase.disconnect(self) From f1e705fc3b89f13e1d8ab6f182d28f1ee013165f Mon Sep 17 00:00:00 2001 From: bobbybee Date: Sun, 29 Jun 2014 15:11:16 -0400 Subject: [PATCH 12/14] CLIENT_OBJECT_SET_FIELDS raises NotImplementedError --- direct/src/distributed/AstronClientRepository.py | 1 + 1 file changed, 1 insertion(+) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index a1a92bc4de..3b0216d4c9 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -68,6 +68,7 @@ class AstronClientRepository(ClientRepositoryBase): # value = di.get?() # Assemble new message self.notify.error("CLIENT_OBJECT_SET_FIELDS not implemented!") + raise NotImplementedError("CLIENT_OBJECT_SET_FIELDS not implemented!") elif msgType == CLIENT_OBJECT_LEAVING: do_id = di.get_uint32() dist_obj = self.doId2do.get(do_id) From d8c265dd7082919e3164c3a4a083dcd4d65aec9a Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Wed, 2 Jul 2014 02:38:08 +0200 Subject: [PATCH 13/14] Commented out speculative implementation of CLIENT_OBJECT_SET_FIELDS. --- .../src/distributed/AstronClientRepository.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 3b0216d4c9..8f0bddaad7 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -57,18 +57,19 @@ class AstronClientRepository(ClientRepositoryBase): elif msgType == CLIENT_OBJECT_SET_FIELD: self.handleUpdateField(di) elif msgType == CLIENT_OBJECT_SET_FIELDS: - do_id = di.getUint32() - field_count = di.getUint16() - for i in range(0, field_count): - field_id = di.getUint16() - field = self.get_dc_file().get_field_by_index(field_id) - print(type(field)) - print(field) - # FIXME: Get field type, unpack value, create and send message. - # value = di.get?() - # Assemble new message - self.notify.error("CLIENT_OBJECT_SET_FIELDS not implemented!") raise NotImplementedError("CLIENT_OBJECT_SET_FIELDS not implemented!") + # Can't test this without the server actually sending it. + # Here's some tentative code and notes: + #do_id = di.getUint32() + #field_count = di.getUint16() + #for i in range(0, field_count): + # field_id = di.getUint16() + # field = self.get_dc_file().get_field_by_index(field_id) + # # print(type(field)) + # # print(field) + # # FIXME: Get field type, unpack value, create and send message. + # # value = di.get?() + # # Assemble new message elif msgType == CLIENT_OBJECT_LEAVING: do_id = di.get_uint32() dist_obj = self.doId2do.get(do_id) From bbf1b4b2a34e25bca91120995dc8318b5827dc18 Mon Sep 17 00:00:00 2001 From: Sebastian Hoffmann Date: Thu, 10 Jul 2014 03:14:42 +0200 Subject: [PATCH 14/14] Split up handleMessageType. Added "forgotten" types to MsgTypes. --- .../src/distributed/AstronClientRepository.py | 131 ++++++++++-------- direct/src/distributed/MsgTypes.py | 2 + direct/src/distributed/MsgTypesAstron.py | 32 ----- 3 files changed, 72 insertions(+), 93 deletions(-) delete mode 100644 direct/src/distributed/MsgTypesAstron.py diff --git a/direct/src/distributed/AstronClientRepository.py b/direct/src/distributed/AstronClientRepository.py index 8f0bddaad7..a665385201 100644 --- a/direct/src/distributed/AstronClientRepository.py +++ b/direct/src/distributed/AstronClientRepository.py @@ -2,7 +2,7 @@ from direct.directnotify import DirectNotifyGlobal from ClientRepositoryBase import ClientRepositoryBase -from MsgTypesAstron import * +from MsgTypes import * from direct.distributed.PyDatagram import PyDatagram from pandac.PandaModules import STUint16, STUint32 @@ -27,80 +27,48 @@ class AstronClientRepository(ClientRepositoryBase): # This is required by DoCollectionManager, even though it's not # used by this implementation. GameGlobalsId = 0 - + def __init__(self, *args, **kwargs): ClientRepositoryBase.__init__(self, *args, **kwargs) base.finalExitCallbacks.append(self.shutdown) - + self.message_handlers = {CLIENT_HELLO_RESP: self.handleHelloResp, + CLIENT_EJECT: self.handleEject, + CLIENT_ENTER_OBJECT_REQUIRED: self.handleEnterObjectRequired, + CLIENT_ENTER_OBJECT_REQUIRED_OWNER: self.handleEnterObjectRequiredOwner, + CLIENT_OBJECT_SET_FIELD: self.handleUpdateField, + CLIENT_OBJECT_SET_FIELDS: self.handleUpdateFields, + CLIENT_OBJECT_LEAVING: self.handleObjectLeaving, + CLIENT_OBJECT_LOCATION: self.handleObjectLocation, + CLIENT_ADD_INTEREST: self.handleAddInterest, + CLIENT_ADD_INTEREST_MULTIPLE: self.handleAddInterestMultiple, + CLIENT_REMOVE_INTEREST: self.handleRemoveInterest, + CLIENT_DONE_INTEREST_RESP: self.handleInterestDoneMessage, + } + # # Message Handling # def handleDatagram(self, di): msgType = self.getMsgType() - self.handleMessageType(msgType, di) - - def handleMessageType(self, msgType, di): - - # These are the messages to a client that Astron specifies. - - if msgType == CLIENT_HELLO_RESP: - messenger.send("CLIENT_HELLO_RESP", []) - elif msgType == CLIENT_EJECT: - error_code = di.get_uint16() - reason = di.get_string() - messenger.send("CLIENT_EJECT", [error_code, reason]) - elif msgType == CLIENT_ENTER_OBJECT_REQUIRED: - self.handleEnterObjectRequired(di) - elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OWNER: - self.handleEnterObjectRequiredOwner(di) - elif msgType == CLIENT_OBJECT_SET_FIELD: - self.handleUpdateField(di) - elif msgType == CLIENT_OBJECT_SET_FIELDS: - raise NotImplementedError("CLIENT_OBJECT_SET_FIELDS not implemented!") - # Can't test this without the server actually sending it. - # Here's some tentative code and notes: - #do_id = di.getUint32() - #field_count = di.getUint16() - #for i in range(0, field_count): - # field_id = di.getUint16() - # field = self.get_dc_file().get_field_by_index(field_id) - # # print(type(field)) - # # print(field) - # # FIXME: Get field type, unpack value, create and send message. - # # value = di.get?() - # # Assemble new message - elif msgType == CLIENT_OBJECT_LEAVING: - do_id = di.get_uint32() - dist_obj = self.doId2do.get(do_id) - dist_obj.delete() - self.deleteObject(do_id) - messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) - elif msgType == CLIENT_OBJECT_LOCATION: - self.handleObjectLocation(di) - elif msgType == CLIENT_ADD_INTEREST: - context = di.get_uint32() - interest_id = di.get_uint16() - parent_id = di.get_uint32() - zone_id = di.get_uint32() - messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id]) - elif msgType == CLIENT_ADD_INTEREST_MULTIPLE: - context = di.get_uint32() - interest_id = di.get_uint16() - parent_id = di.get_uint32() - zone_ids = [di.get_uint32() for i in range(0, di.get_uint16())] - messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids]) - elif msgType == CLIENT_REMOVE_INTEREST: - context = di.get_uint32() - interest_id = di.get_uint16() - messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) - elif msgType == CLIENT_DONE_INTEREST_RESP: - self.handleInterestDoneMessage(di) # Implemented in DoInterestManager.py + # self.handleMessageType(msgType, di) + # + #def handleMessageType(self, msgType, di): + if msgType in self.message_handlers: + self.message_handlers[msgType](di) else: self.notify.error("Got unknown message type %d!" % (msgType,)) self.considerHeartbeat() + def handleHelloResp(self, di): + messenger.send("CLIENT_HELLO_RESP", []) + + def handleEject(self, di): + error_code = di.get_uint16() + reason = di.get_string() + messenger.send("CLIENT_EJECT", [error_code, reason]) + def handleEnterObjectRequired(self, di): do_id = di.getArg(STUint32) parent_id = di.getArg(STUint32) @@ -158,6 +126,47 @@ class AstronClientRepository(ClientRepositoryBase): # updateRequiredFields calls announceGenerate return distObj + def handleUpdateFields(self, di): + # Can't test this without the server actually sending it. + self.notify.error("CLIENT_OBJECT_SET_FIELDS not implemented!") + # # Here's some tentative code and notes: + # do_id = di.getUint32() + # field_count = di.getUint16() + # for i in range(0, field_count): + # field_id = di.getUint16() + # field = self.get_dc_file().get_field_by_index(field_id) + # # print(type(field)) + # # print(field) + # # FIXME: Get field type, unpack value, create and send message. + # # value = di.get?() + # # Assemble new message + + def handleObjectLeaving(self, di): + do_id = di.get_uint32() + dist_obj = self.doId2do.get(do_id) + dist_obj.delete() + self.deleteObject(do_id) + messenger.send("CLIENT_OBJECT_LEAVING", [do_id]) + + def handleAddInterest(self, di): + context = di.get_uint32() + interest_id = di.get_uint16() + parent_id = di.get_uint32() + zone_id = di.get_uint32() + messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id]) + + def handleAddInterestMultiple(self, di): + context = di.get_uint32() + interest_id = di.get_uint16() + parent_id = di.get_uint32() + zone_ids = [di.get_uint32() for i in range(0, di.get_uint16())] + messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids]) + + def handleRemoveInterest(self, di): + context = di.get_uint32() + interest_id = di.get_uint16() + messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id]) + def deleteObject(self, doId): """ implementation copied from ClientRepository.py diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index f839873bcc..b689214d10 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -15,10 +15,12 @@ MsgName2Id = { 'CLIENT_HEARTBEAT': 5, 'CLIENT_OBJECT_SET_FIELD': 120, + 'CLIENT_OBJECT_SET_FIELDS': 121, 'CLIENT_OBJECT_LEAVING': 132, 'CLIENT_OBJECT_LEAVING_OWNER': 161, 'CLIENT_ENTER_OBJECT_REQUIRED': 142, 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER': 143, + 'CLIENT_ENTER_OBJECT_REQUIRED_OWNER': 172, 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER': 173, 'CLIENT_DONE_INTEREST_RESP': 204, diff --git a/direct/src/distributed/MsgTypesAstron.py b/direct/src/distributed/MsgTypesAstron.py deleted file mode 100644 index 5e94797361..0000000000 --- a/direct/src/distributed/MsgTypesAstron.py +++ /dev/null @@ -1,32 +0,0 @@ -"""MsgTypesAstron module: contains distributed object message types""" - -from direct.showbase.PythonUtil import invertDictLossless - -MsgName2Id = { - 'CLIENT_HELLO': 1, - 'CLIENT_HELLO_RESP': 2, - 'CLIENT_DISCONNECT': 3, - 'CLIENT_EJECT': 4, - 'CLIENT_HEARTBEAT': 5, - 'CLIENT_ENTER_OBJECT_REQUIRED': 142, - 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER': 143, - 'CLIENT_ENTER_OBJECT_REQUIRED_OWNER': 172, - 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER': 173, - 'CLIENT_OBJECT_SET_FIELD': 120, - 'CLIENT_OBJECT_SET_FIELDS': 121, - 'CLIENT_OBJECT_LEAVING': 132, - 'CLIENT_OBJECT_LOCATION': 140, - 'CLIENT_ADD_INTEREST': 200, - 'CLIENT_ADD_INTEREST_MULTIPLE': 201, - 'CLIENT_REMOVE_INTEREST': 203, - 'CLIENT_DONE_INTEREST_RESP': 204, - } - -# create id->name table for debugging -MsgId2Names = invertDictLossless(MsgName2Id) - -# put msg names in module scope, assigned to msg value -for name, value in MsgName2Id.items(): - exec '%s = %s' % (name, value) -del name, value -