From e957878fc6042b191b1ee9014587c67063bf86ce Mon Sep 17 00:00:00 2001 From: Open Toontown <57279094+opentoontown@users.noreply.github.com> Date: Tue, 4 Jan 2022 14:35:16 -0500 Subject: [PATCH] OTP support for NetMessenger --- direct/src/distributed/AstronNetMessenger.py | 113 ++++++++++++++++++ direct/src/distributed/NetMessenger.py | 116 +------------------ direct/src/distributed/OTPNetMessenger.py | 92 +++++++++++++++ 3 files changed, 210 insertions(+), 111 deletions(-) create mode 100755 direct/src/distributed/AstronNetMessenger.py create mode 100755 direct/src/distributed/OTPNetMessenger.py diff --git a/direct/src/distributed/AstronNetMessenger.py b/direct/src/distributed/AstronNetMessenger.py new file mode 100755 index 0000000000..758a3b0e6d --- /dev/null +++ b/direct/src/distributed/AstronNetMessenger.py @@ -0,0 +1,113 @@ + +from direct.directnotify import DirectNotifyGlobal +from direct.distributed.PyDatagram import PyDatagram +from direct.showbase.Messenger import Messenger +from pickle import dumps, loads + + +class AstronNetMessenger(Messenger): + """ + This works very much like the Messenger class except that messages + are sent over the network and (possibly) handled (accepted) on a + remote machine (server). + """ + notify = DirectNotifyGlobal.directNotify.newCategory('AstronNetMessenger') + + def __init__(self, air, baseChannel=20000, baseMsgType=20000): + """ + air is the AI Repository. + baseChannel is the channel that the first message is sent on. + baseMsgType is the MsgType of the same. + """ + assert self.notify.debugCall() + Messenger.__init__(self) + self.air=air + self.baseChannel = baseChannel + self.baseMsgType = baseMsgType + + self.__message2type = {} + self.__type2message = {} + self.__message2channel = {} + + def clear(self): + assert self.notify.debugCall() + Messenger.clear(self) + + def register(self, code, message): + assert self.notify.debugCall() + channel = self.baseChannel + code + msgType = self.baseMsgType + code + + if message in self.__message2type: + self.notify.error('Tried to register message %s twice!' % message) + return + + self.__message2type[message] = msgType + self.__type2message[msgType] = message + self.__message2channel[message] = channel + + def prepare(self, message, sentArgs=[]): + """ + Prepare the datagram that would get sent in order to send this message + to its designated channel. + """ + assert self.notify.debugCall() + + # Make sure the message is registered: + if message not in self.__message2type: + self.notify.error('Tried to send unregistered message %s!' % message) + return + + datagram = PyDatagram() + # To: + datagram.addUint8(1) + datagram.addChannel(self.__message2channel[message]) + # From: + datagram.addChannel(self.air.ourChannel) + + messageType=self.__message2type[message] + datagram.addUint16(messageType) + datagram.addString(str(dumps(sentArgs))) + + return datagram + + def accept(self, message, *args): + if message not in self.__message2channel: + self.notify.error('Tried to accept unregistered message %s!' % message) + return + + anyAccepting = bool(self.whoAccepts(message)) + if not anyAccepting: + self.air.registerForChannel(self.__message2channel[message]) + + Messenger.accept(self, message, *args) + + def send(self, message, sentArgs=[]): + """ + Send message to anything that's listening for it. + """ + assert self.notify.debugCall() + + datagram = self.prepare(message, sentArgs) + self.air.send(datagram) + Messenger.send(self, message, sentArgs=sentArgs) + + def handle(self, msgType, di): + """ + Send data from the net on the local netMessenger. + """ + assert self.notify.debugCall() + + if msgType not in self.__type2message: + self.notify.warning('Received unknown message: %d' % msgType) + return + + message = self.__type2message[msgType] + sentArgs=loads(di.getBlob()) + + if type(sentArgs) != list: + self.notify.warning('Received non-list item in %s message: %r' % + (message, sentArgs)) + return + + Messenger.send(self, message, sentArgs=sentArgs) diff --git a/direct/src/distributed/NetMessenger.py b/direct/src/distributed/NetMessenger.py index 4669da13a1..44e688242c 100755 --- a/direct/src/distributed/NetMessenger.py +++ b/direct/src/distributed/NetMessenger.py @@ -1,113 +1,7 @@ -from direct.directnotify import DirectNotifyGlobal -from direct.distributed.PyDatagram import PyDatagram -from direct.showbase.Messenger import Messenger -from pickle import dumps, loads +from panda3d.core import ConfigVariableBool - -class NetMessenger(Messenger): - """ - This works very much like the Messenger class except that messages - are sent over the network and (possibly) handled (accepted) on a - remote machine (server). - """ - notify = DirectNotifyGlobal.directNotify.newCategory('NetMessenger') - - def __init__(self, air, baseChannel=20000, baseMsgType=20000): - """ - air is the AI Repository. - baseChannel is the channel that the first message is sent on. - baseMsgType is the MsgType of the same. - """ - assert self.notify.debugCall() - Messenger.__init__(self) - self.air=air - self.baseChannel = baseChannel - self.baseMsgType = baseMsgType - - self.__message2type = {} - self.__type2message = {} - self.__message2channel = {} - - def clear(self): - assert self.notify.debugCall() - Messenger.clear(self) - - def register(self, code, message): - assert self.notify.debugCall() - channel = self.baseChannel + code - msgType = self.baseMsgType + code - - if message in self.__message2type: - self.notify.error('Tried to register message %s twice!' % message) - return - - self.__message2type[message] = msgType - self.__type2message[msgType] = message - self.__message2channel[message] = channel - - def prepare(self, message, sentArgs=[]): - """ - Prepare the datagram that would get sent in order to send this message - to its designated channel. - """ - assert self.notify.debugCall() - - # Make sure the message is registered: - if message not in self.__message2type: - self.notify.error('Tried to send unregistered message %s!' % message) - return - - datagram = PyDatagram() - # To: - datagram.addUint8(1) - datagram.addChannel(self.__message2channel[message]) - # From: - datagram.addChannel(self.air.ourChannel) - - messageType=self.__message2type[message] - datagram.addUint16(messageType) - datagram.addString(str(dumps(sentArgs))) - - return datagram - - def accept(self, message, *args): - if message not in self.__message2channel: - self.notify.error('Tried to accept unregistered message %s!' % message) - return - - anyAccepting = bool(self.whoAccepts(message)) - if not anyAccepting: - self.air.registerForChannel(self.__message2channel[message]) - - Messenger.accept(self, message, *args) - - def send(self, message, sentArgs=[]): - """ - Send message to anything that's listening for it. - """ - assert self.notify.debugCall() - - datagram = self.prepare(message, sentArgs) - self.air.send(datagram) - Messenger.send(self, message, sentArgs=sentArgs) - - def handle(self, msgType, di): - """ - Send data from the net on the local netMessenger. - """ - assert self.notify.debugCall() - - if msgType not in self.__type2message: - self.notify.warning('Received unknown message: %d' % msgType) - return - - message = self.__type2message[msgType] - sentArgs=loads(di.getBlob()) - - if type(sentArgs) != list: - self.notify.warning('Received non-list item in %s message: %r' % - (message, sentArgs)) - return - - Messenger.send(self, message, sentArgs=sentArgs) +if ConfigVariableBool('astron-support', True): + from direct.distributed.AstronNetMessenger import AstronNetMessenger as NetMessenger +else: + from direct.distributed.OTPNetMessenger import OTPNetMessenger as NetMessenger diff --git a/direct/src/distributed/OTPNetMessenger.py b/direct/src/distributed/OTPNetMessenger.py new file mode 100755 index 0000000000..62e5bd6866 --- /dev/null +++ b/direct/src/distributed/OTPNetMessenger.py @@ -0,0 +1,92 @@ + +from direct.directnotify import DirectNotifyGlobal +from direct.distributed.PyDatagram import PyDatagram +from direct.showbase.Messenger import Messenger +from pickle import dumps, loads + + +# Messages do not need to be in the MESSAGE_TYPES list. +# This is just an optimization. If the message is found +# in this list, it is reduced to an integer index and +# the message string is not sent. Otherwise, the message +# string is sent in the datagram. +MESSAGE_TYPES=( + "avatarOnline", + "avatarOffline", + "create", + "needUberdogCreates", + "transferDo", +) + +# This is the reverse look up for the recipient of the +# datagram: +MESSAGE_STRINGS={} +for i in zip(MESSAGE_TYPES, range(1, len(MESSAGE_TYPES)+1)): + MESSAGE_STRINGS[i[0]]=i[1] + + +class OTPNetMessenger(Messenger): + """ + This works very much like the Messenger class except that messages + are sent over the network and (possibly) handled (accepted) on a + remote machine (server). + """ + notify = DirectNotifyGlobal.directNotify.newCategory('OTPNetMessenger') + + def __init__(self, air, channels): + """ + air is the AI Repository. + channels is a list of channel IDs (uint32 values) + """ + assert self.notify.debugCall() + Messenger.__init__(self) + self.air=air + self.channels=channels + for i in self.channels: + self.air.registerForChannel(i) + + def clear(self): + assert self.notify.debugCall() + for i in self.channels: + self.air.unRegisterChannel(i) + del self.air + del self.channels + Messenger.clear(self) + + def send(self, message, sentArgs=[]): + """ + Send message to All AI and Uber Dog servers. + """ + assert self.notify.debugCall() + datagram = PyDatagram() + # To: + datagram.addUint8(1) + datagram.addChannel(self.channels[0]) + # From: + datagram.addChannel(self.air.ourChannel) + #if 1: # We send this just because the air expects it: + # # Add an 'A' for AI + # datagram.addUint8(ord('A')) + + messageType=MESSAGE_STRINGS.get(message, 0) + datagram.addUint16(messageType) + if messageType: + datagram.addString(str(dumps(sentArgs))) + else: + datagram.addString(str(dumps((message, sentArgs)))) + self.air.send(datagram) + + def handle(self, pickleData): + """ + Send pickleData from the net on the local netMessenger. + The internal data in pickleData should have a tuple of + (messageString, sendArgsList). + """ + assert self.notify.debugCall() + messageType=self.air.getMsgType() + if messageType: + message=MESSAGE_TYPES[messageType-1] + sentArgs=loads(pickleData) + else: + (message, sentArgs) = loads(pickleData) + Messenger.send(self, message, sentArgs=sentArgs)