distributed: this is broken

This commit is contained in:
Open Toontown 2019-11-10 20:50:13 -05:00
parent 1f8044c25e
commit 155e40564f
2 changed files with 198 additions and 43 deletions

View file

@ -423,6 +423,9 @@ class OTPClientRepository(ClientRepositoryBase):
self.uberZoneInterest = None
self.wantSwitchboard = config.GetBool('want-switchboard', 0)
self.wantSwitchboardHacks = base.config.GetBool('want-switchboard-hacks', 0)
self.__pendingGenerates = {}
self.__pendingMessages = {}
self.__doId2pendingInterest = {}
self.centralLogger = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_CENTRAL_LOGGER, 'CentralLogger')
if self.astronSupport:
self.astronLoginManager = self.generateGlobalObject(OtpDoGlobals.OTP_DO_ID_ASTRON_LOGIN_MANAGER, 'AstronLoginManager')
@ -1934,6 +1937,8 @@ class OTPClientRepository(ClientRepositoryBase):
def handleMessageType(self, msgType, di):
if self.astronSupport:
if self.__recordObjectMessage(msgType, di):
return
if msgType == CLIENT_EJECT:
self.handleGoGetLost(di)
elif msgType == CLIENT_HEARTBEAT:
@ -1941,7 +1946,7 @@ class OTPClientRepository(ClientRepositoryBase):
elif msgType == CLIENT_ENTER_OBJECT_REQUIRED:
self.handleGenerateWithRequired(di)
elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER:
self.handleGenerateWithRequiredOther(di)
self.handleGenerateWithRequired(di, other=True)
elif msgType == CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER:
self.handleGenerateWithRequiredOtherOwner(di)
elif msgType == CLIENT_OBJECT_SET_FIELD:
@ -2014,6 +2019,19 @@ class OTPClientRepository(ClientRepositoryBase):
di = DatagramIterator(dg, di.getCurrentIndex())
self.deferredGenerates.append((CLIENT_DONE_INTEREST_RESP, (dg, di)))
else:
if self.astronSupport:
# Play back generates, if necessary.
# First, create a new DatagramIterator using
# the Datagram from DatagramIterator di, and
# the current index of DatagramIterator di:
di2 = DatagramIterator(di.getDatagram(), di.getCurrentIndex())
# Now, get the handle:
handle = di2.getUint16()
# Finally, play back the generates:
self.__playBackGenerates(handle)
self.handleInterestDoneMessage(di)
def gotObjectLocationMessage(self, di):
@ -2151,51 +2169,180 @@ class OTPClientRepository(ClientRepositoryBase):
return True
return False
def handleGenerateWithRequired(self, di):
parentId = di.getUint32()
zoneId = di.getUint32()
classId = di.getUint16()
doId = di.getUint32()
dclass = self.dclassesByNumber[classId]
if self._isInvalidPlayerAvatarGenerate(doId, dclass, parentId, zoneId):
return
dclass.startGenerate()
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate()
if not config.GetBool('astron-support', True):
def handleGenerateWithRequired(self, di):
parentId = di.getUint32()
zoneId = di.getUint32()
classId = di.getUint16()
doId = di.getUint32()
dclass = self.dclassesByNumber[classId]
if self._isInvalidPlayerAvatarGenerate(doId, dclass, parentId, zoneId):
return
dclass.startGenerate()
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate()
def handleGenerateWithRequiredOther(self, di):
parentId = di.getUint32()
zoneId = di.getUint32()
classId = di.getUint16()
doId = di.getUint32()
dclass = self.dclassesByNumber[classId]
if self._isInvalidPlayerAvatarGenerate(doId, dclass, parentId, zoneId):
return
deferrable = getattr(dclass.getClassDef(), 'deferrable', False)
if not self.deferInterval or self.noDefer:
deferrable = False
now = globalClock.getFrameTime()
if self.deferredGenerates or deferrable:
if self.deferredGenerates or now - self.lastGenerate < self.deferInterval:
self.deferredGenerates.append((CLIENT_CREATE_OBJECT_REQUIRED_OTHER, doId))
dg = Datagram(di.getDatagram())
di = DatagramIterator(dg, di.getCurrentIndex())
self.deferredDoIds[doId] = ((parentId,
zoneId,
classId,
doId,
di),
deferrable,
dg,
[])
if len(self.deferredGenerates) == 1:
taskMgr.remove('deferredGenerate')
taskMgr.doMethodLater(self.deferInterval, self.doDeferredGenerate, 'deferredGenerate')
def handleGenerateWithRequiredOther(self, di):
parentId = di.getUint32()
zoneId = di.getUint32()
classId = di.getUint16()
doId = di.getUint32()
dclass = self.dclassesByNumber[classId]
if self._isInvalidPlayerAvatarGenerate(doId, dclass, parentId, zoneId):
return
deferrable = getattr(dclass.getClassDef(), 'deferrable', False)
if not self.deferInterval or self.noDefer:
deferrable = False
now = globalClock.getFrameTime()
if self.deferredGenerates or deferrable:
if self.deferredGenerates or now - self.lastGenerate < self.deferInterval:
self.deferredGenerates.append((CLIENT_CREATE_OBJECT_REQUIRED_OTHER, doId))
dg = Datagram(di.getDatagram())
di = DatagramIterator(dg, di.getCurrentIndex())
self.deferredDoIds[doId] = ((parentId,
zoneId,
classId,
doId,
di),
deferrable,
dg,
[])
if len(self.deferredGenerates) == 1:
taskMgr.remove('deferredGenerate')
taskMgr.doMethodLater(self.deferInterval, self.doDeferredGenerate, 'deferredGenerate')
else:
self.lastGenerate = now
self.doGenerate(parentId, zoneId, classId, doId, di)
else:
self.lastGenerate = now
self.doGenerate(parentId, zoneId, classId, doId, di)
else:
self.doGenerate(parentId, zoneId, classId, doId, di)
else:
def handleGenerateWithRequired(self, di, other=False):
doId = di.getUint32()
parentId = di.getUint32()
zoneId = di.getUint32()
classId = di.getUint16()
# Determine whether or not we should add this generate
# to the pending generates, or just generate it right away.
for handle, interest in self._interests.items():
if parentId != interest.parentId:
continue
if isinstance(interest.zoneIdList, list):
if zoneId not in interest.zoneIdList:
continue
else:
if zoneId != interest.zoneIdList:
continue
break
else:
interest = None
if not interest or not interest.events:
# Generate this object right away.
return self.__generateObject(doId, parentId, zoneId, classId, di, other)
# Wait on the interest events to complete before generating.
pending = self.__pendingGenerates.setdefault(handle, [])
pending.append((doId, parentId, zoneId, classId, Datagram(di.getDatagram()), other))
self.__doId2pendingInterest[doId] = handle
def __playBackGenerates(self, handle):
if handle not in self.__pendingGenerates:
# Nothing to play back!
return
# We will now play back this interest's pending generates.
# First, get a copy of the pending generates, and remove
# them from self.__pendingGenerates:
generates = self.__pendingGenerates[handle]
del self.__pendingGenerates[handle]
# Sort generates by classId:
generates.sort(key=lambda x: x[3])
# Generate the objects:
for doId, parentId, zoneId, classId, dg, other in generates:
# Set up a DatagramIterator using Datagram dg:
di = DatagramIterator(dg)
# Skip 16 bytes to move past the header.
# For the record: MsgType(2), zoneId, doId, parentId (3x4), classId (2)
di.skipBytes(16)
# Generate the object:
self.__generateObject(doId, parentId, zoneId, classId, di, other)
# Delete this object's doId from
# __doId2pendingInterest if it exists:
if doId in self.__doId2pendingInterest:
del self.__doId2pendingInterest[doId]
# Now that we have generated the object, if there
# are any messages to play back, do so now:
self.__playBackMessages(handle)
def __playBackMessages(self, handle):
if handle not in self.__pendingMessages:
# Nothing to play back!
return
# We will now play back any pending messages.
# First, loop through all the Datagram instances
# in __pendingMessages:
for dg in self.__pendingMessages[handle]:
# Set up a DatagramIterator using Datagram dg:
di = DatagramIterator(dg)
# Get the msgType:
msgType = di.getUint16()
# If self.handler is set, use that. Otherwise,
# use self.handleMessageType:
if self.handler:
self.handler(msgType, di)
else:
self.handleMessageType(msgType, di)
# We can now remove the handle from __pendingMessages:
del self.__pendingMessages[handle]
def __recordObjectMessage(self, msgType, di):
if msgType not in (CLIENT_OBJECT_SET_FIELD, CLIENT_OBJECT_LEAVING, CLIENT_OBJECT_LOCATION):
return False
di2 = DatagramIterator(di.getDatagram(), di.getCurrentIndex())
doId = di2.getUint32()
if doId not in self.__doId2pendingInterest:
return False
pending = self.__pendingMessages.setdefault(self.__doId2pendingInterest[doId], [])
pending.append(Datagram(di.getDatagram()))
return True
def __generateObject(self, doId, parentId, zoneId, classId, di, other):
# Get our dclass:
dclass = self.dclassesByNumber[classId]
# Is this an invalid player avatar generate?
if self._isInvalidPlayerAvatarGenerate(doId, dclass, parentId, zoneId):
# Yup, ignore this.
return
# Start the generation process:
dclass.startGenerate()
# Is this an other generate?
if other:
# Yup. In this case, we'll use generateWithRequiredOtherFields.
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
else:
# Nah. In this case, we'll use generateWithRequiredFields.
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
# We're done.
dclass.stopGenerate()
def handleGenerateWithRequiredOtherOwner(self, di):
classId = di.getUint16()

View file

@ -1,4 +1,5 @@
from direct.directnotify import DirectNotifyGlobal
from direct.distributed.PyDatagram import *
from toontown.distributed.ToontownInternalRepository import ToontownInternalRepository
from toontown.distributed.ToontownDistrictAI import ToontownDistrictAI
from otp.distributed.OtpDoGlobals import *
@ -20,3 +21,10 @@ class ToontownAIRepository(ToontownInternalRepository):
self.district = ToontownDistrictAI(self)
self.district.setName(self.districtName)
self.district.generateWithRequiredAndId(self.districtId, self.getGameDoId(), OTP_ZONE_ID_DISTRICTS)
# Claim ownership of that district...
self.district.setAI(self.ourChannel)
# Make our district available, and we're done.
self.district.b_setAvailable(True)
self.notify.info('Done.')