ai: Some fixes
This commit is contained in:
parent
70602f7231
commit
a5c5ecbf47
|
|
@ -708,7 +708,7 @@ class AIRepository(ConnectionRepository):
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
dclass = self.dclassesByNumber[classId]
|
dclass = self.dclassesByNumber[classId]
|
||||||
# Is it in our dictionary?
|
# Is it in our dictionary?
|
||||||
if self.doId2do.has_key(doId):
|
if doId in self.doId2do:
|
||||||
self.notify.warning("Object Entered " + str(doId) +
|
self.notify.warning("Object Entered " + str(doId) +
|
||||||
" re-entered without exiting")
|
" re-entered without exiting")
|
||||||
# Create a new distributed object
|
# Create a new distributed object
|
||||||
|
|
@ -720,7 +720,7 @@ class AIRepository(ConnectionRepository):
|
||||||
# sure why or how this happens, but it does come up from time to
|
# sure why or how this happens, but it does come up from time to
|
||||||
# time in production
|
# time in production
|
||||||
# Asad Todo take out this security check for now don't publish to toontown!!!
|
# Asad Todo take out this security check for now don't publish to toontown!!!
|
||||||
## if self.doId2do.has_key(doId):
|
## if doId in self.doId2do:
|
||||||
## self.writeServerEvent('suspicious', doId, 'Avatar re-entered without exiting')
|
## self.writeServerEvent('suspicious', doId, 'Avatar re-entered without exiting')
|
||||||
## # Note: until we figure out what is causing this bug, it will be an error
|
## # Note: until we figure out what is causing this bug, it will be an error
|
||||||
## # This is listed as bug 50608 in the production remarks db
|
## # This is listed as bug 50608 in the production remarks db
|
||||||
|
|
@ -736,7 +736,7 @@ class AIRepository(ConnectionRepository):
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
dclass = self.dclassesByNumber[classId]
|
dclass = self.dclassesByNumber[classId]
|
||||||
# Is it in our dictionary?
|
# Is it in our dictionary?
|
||||||
if self.doId2do.has_key(doId):
|
if doId in self.doId2do:
|
||||||
self.notify.warning("Object Entered " + str(doId) +
|
self.notify.warning("Object Entered " + str(doId) +
|
||||||
" re-entered without exiting")
|
" re-entered without exiting")
|
||||||
# Create a new distributed object
|
# Create a new distributed object
|
||||||
|
|
@ -748,7 +748,7 @@ class AIRepository(ConnectionRepository):
|
||||||
# sure why or how this happens, but it does come up from time to
|
# sure why or how this happens, but it does come up from time to
|
||||||
# time in production
|
# time in production
|
||||||
# Asad Todo take out this security check for now don't publish to toontown!!!
|
# Asad Todo take out this security check for now don't publish to toontown!!!
|
||||||
## if self.doId2do.has_key(doId):
|
## if doId in self.doId2do:
|
||||||
## self.writeServerEvent('suspicious', doId, 'Avatar re-entered without exiting')
|
## self.writeServerEvent('suspicious', doId, 'Avatar re-entered without exiting')
|
||||||
## # Note: until we figure out what is causing this bug, it will be an error
|
## # Note: until we figure out what is causing this bug, it will be an error
|
||||||
## # This is listed as bug 50608 in the production remarks db
|
## # This is listed as bug 50608 in the production remarks db
|
||||||
|
|
@ -817,7 +817,7 @@ class AIRepository(ConnectionRepository):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _generateFromDatagram(self, parentId, zoneId, dclass, doId, di, addToTables=True):
|
def _generateFromDatagram(self, parentId, zoneId, dclass, doId, di, addToTables=True):
|
||||||
if (self.doId2do.has_key(doId)):
|
if (doId in self.doId2do):
|
||||||
# added to prevent objects already generated from being generated again (was
|
# added to prevent objects already generated from being generated again (was
|
||||||
# happening with some traded inventory objects, quests specfically)
|
# happening with some traded inventory objects, quests specfically)
|
||||||
return self.doId2do[doId]
|
return self.doId2do[doId]
|
||||||
|
|
@ -1225,7 +1225,7 @@ class AIRepository(ConnectionRepository):
|
||||||
__builtins__["debug_dictionary"] = self.debug_dictionary
|
__builtins__["debug_dictionary"] = self.debug_dictionary
|
||||||
|
|
||||||
for id in self.debug_dictionary.keys():
|
for id in self.debug_dictionary.keys():
|
||||||
if not self.doId2do.has_key(id):
|
if id not in self.doId2do:
|
||||||
print("--------------------- Not In DOID table")
|
print("--------------------- Not In DOID table")
|
||||||
print(id)
|
print(id)
|
||||||
#traceback.print_list(self.debug_dictionary[id])
|
#traceback.print_list(self.debug_dictionary[id])
|
||||||
|
|
@ -1408,14 +1408,14 @@ class AIRepository(ConnectionRepository):
|
||||||
# (classId, context))
|
# (classId, context))
|
||||||
if ownerChannel == 0 and ownerAvId is not None:
|
if ownerChannel == 0 and ownerAvId is not None:
|
||||||
ownerChannel = (1<<32) + ownerAvId
|
ownerChannel = (1<<32) + ownerAvId
|
||||||
if self.dclassesByNumber.has_key(classId):
|
if classId in self.dclassesByNumber:
|
||||||
dclass = self.dclassesByNumber[classId]
|
dclass = self.dclassesByNumber[classId]
|
||||||
else:
|
else:
|
||||||
if self.dclassesByName.has_key(classId):
|
if classId in self.dclassesByName:
|
||||||
dclass = self.dclassesByName[classId]
|
dclass = self.dclassesByName[classId]
|
||||||
elif self.dclassesByName.has_key(classId+self.dcSuffix):
|
elif classId+self.dcSuffix in self.dclassesByName:
|
||||||
dclass = self.dclassesByName[classId+self.dcSuffix]
|
dclass = self.dclassesByName[classId+self.dcSuffix]
|
||||||
elif self.dclassesByName.has_key(classId+'AI'):
|
elif classId+'AI' in self.dclassesByName:
|
||||||
dclass = self.dclassesByName[classId+'AI']
|
dclass = self.dclassesByName[classId+'AI']
|
||||||
else:
|
else:
|
||||||
self.notify.warning("dclass not found %s"%(classId,))
|
self.notify.warning("dclass not found %s"%(classId,))
|
||||||
|
|
@ -1499,7 +1499,7 @@ class AIRepository(ConnectionRepository):
|
||||||
def handleDatagram(self, di):
|
def handleDatagram(self, di):
|
||||||
if self.notify.getDebug():
|
if self.notify.getDebug():
|
||||||
print("AIRepository received datagram:")
|
print("AIRepository received datagram:")
|
||||||
di.getDatagram().dumpHex(ostream)
|
di.getDatagram().dumpHex(Notify.out())
|
||||||
|
|
||||||
channel=self.getMsgChannel()
|
channel=self.getMsgChannel()
|
||||||
if channel in self.netMessenger.channels:
|
if channel in self.netMessenger.channels:
|
||||||
|
|
@ -1911,3 +1911,6 @@ class AIRepository(ConnectionRepository):
|
||||||
print('########## startReaderPollTask New ')
|
print('########## startReaderPollTask New ')
|
||||||
self.stopReaderPollTask()
|
self.stopReaderPollTask()
|
||||||
self.accept(CConnectionRepository.getOverflowEventName(),self.handleReaderOverflow)
|
self.accept(CConnectionRepository.getOverflowEventName(),self.handleReaderOverflow)
|
||||||
|
|
||||||
|
def getTrackClsends(self):
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,151 @@
|
||||||
|
from .AIBaseGlobal import *
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
from direct.distributed.ClockDelta import *
|
||||||
|
from direct.task import Task
|
||||||
|
from direct.distributed import DistributedObjectAI
|
||||||
|
from direct.directnotify import DirectNotifyGlobal
|
||||||
|
from direct.showbase import GarbageReport
|
||||||
|
from otp.otpbase import OTPGlobals
|
||||||
|
from otp.ai.GarbageLeakServerEventAggregatorAI import GarbageLeakServerEventAggregatorAI
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from direct.directnotify import DirectNotifyGlobal
|
class TimeManagerAI(DistributedObjectAI.DistributedObjectAI):
|
||||||
from direct.distributed.ClockDelta import globalClockDelta
|
notify = DirectNotifyGlobal.directNotify.newCategory("TimeManagerAI")
|
||||||
from direct.distributed.DistributedObjectAI import DistributedObjectAI
|
|
||||||
|
|
||||||
from otp.otpbase import OTPGlobals
|
|
||||||
|
|
||||||
|
|
||||||
class TimeManagerAI(DistributedObjectAI):
|
|
||||||
notify = DirectNotifyGlobal.directNotify.newCategory('TimeManagerAI')
|
|
||||||
|
|
||||||
def __init__(self, air):
|
def __init__(self, air):
|
||||||
DistributedObjectAI.__init__(self, air)
|
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||||
self.avId2disconnectcode = {}
|
if not __dev__:
|
||||||
|
# double-check that we're not implementing a client-sendable debug DC method in production
|
||||||
|
if hasattr(self, 'checkForGarbageLeaks'):
|
||||||
|
self.notify.error('checkForGarbageLeaks should not be defined outside of __dev__')
|
||||||
|
|
||||||
def requestServerTime(self, context):
|
def requestServerTime(self, context):
|
||||||
avId = self.air.getAvatarIdFromSender()
|
"""requestServerTime(self, int8 context)
|
||||||
if not avId:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.sendUpdateToAvatarId(avId, 'serverTime',
|
This message is sent from the client to the AI to initiate a
|
||||||
[context, globalClockDelta.getRealNetworkTime(bits=32), int(time.time())])
|
synchronization phase. The AI should immediately report back
|
||||||
|
with its current time. The client will then measure the round
|
||||||
|
trip.
|
||||||
|
"""
|
||||||
|
timestamp = globalClockDelta.getRealNetworkTime(bits=32)
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
timeOfDay = int(time.time())
|
||||||
|
self.sendUpdateToAvatarId(requesterId, "serverTime",
|
||||||
|
[context, timestamp, timeOfDay])
|
||||||
|
|
||||||
def setDisconnectReason(self, disconnectCode):
|
def setDisconnectReason(self, disconnectCode):
|
||||||
avId = self.air.getAvatarIdFromSender()
|
"""setDisconnectReason(self, uint8 disconnectCode)
|
||||||
if not avId:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.avId2disconnectcode[avId] = disconnectCode
|
This method is called by the client just before it leaves a
|
||||||
self.air.writeServerEvent('disconnect-reason', avId=avId,
|
shard to alert the AI as to the reason it's going. If the AI
|
||||||
reason=OTPGlobals.DisconnectReasons.get(disconnectCode, 'unknown'))
|
doesn't get this message, it can assume the client aborted
|
||||||
|
messily or its internet connection was dropped.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("Client %s leaving for reason %s (%s)." % (
|
||||||
|
requesterId, disconnectCode,
|
||||||
|
OTPGlobals.DisconnectReasons.get(disconnectCode,
|
||||||
|
'invalid reason')))
|
||||||
|
|
||||||
|
if disconnectCode in OTPGlobals.DisconnectReasons:
|
||||||
|
self.air.setAvatarDisconnectReason(requesterId, disconnectCode)
|
||||||
|
else:
|
||||||
|
self.air.writeServerEvent(
|
||||||
|
'suspicious', requesterId, 'invalid disconnect reason: %s' % disconnectCode)
|
||||||
|
|
||||||
|
def setExceptionInfo(self, info):
|
||||||
|
"""setExceptionInfo(self, string info)
|
||||||
|
|
||||||
|
In the case of the client leaving for a Python exception, we
|
||||||
|
also follow up the above message with this one, which just
|
||||||
|
sends a text string describing the exception for the AI log.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("Client %s exception: %s" % (requesterId, info))
|
||||||
|
serverVersion = simbase.config.GetString('server-version','')
|
||||||
|
self.air.writeServerEvent('client-exception', requesterId, '%s|%s' % (serverVersion,info))
|
||||||
|
|
||||||
|
def setSignature(self, signature, hash, pyc):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the xrc signature and the prc hash to the AI for logging in
|
||||||
|
case the client does anything suspicious.
|
||||||
|
"""
|
||||||
|
if signature:
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
prcHash = HashVal()
|
||||||
|
prcHash.setFromBin(hash)
|
||||||
|
info = '%s|%s' % (signature, prcHash.asHex())
|
||||||
|
self.notify.info('Client %s signature: %s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-signature', requesterId, info)
|
||||||
|
|
||||||
|
pycHash = HashVal()
|
||||||
|
pycHash.setFromBin(pyc)
|
||||||
|
if pycHash != HashVal():
|
||||||
|
info = pycHash.asHex()
|
||||||
|
self.notify.info('Client %s py signature: %s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-py-signature', requesterId, info)
|
||||||
|
|
||||||
|
def setCpuInfo(self, info, cacheStatus):
|
||||||
|
"""
|
||||||
|
This method is called by the client at startup time, to send
|
||||||
|
the detailed CPU information to the server for logging.
|
||||||
|
"""
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
|
||||||
|
self.notify.info('client-cpu %s|%s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-cpu', requesterId, info)
|
||||||
|
# We call this cacheStatus, but really it's the mac address or
|
||||||
|
# other client fingerprint information, in a simple
|
||||||
|
# obfuscating cipher. Decode it.
|
||||||
|
key = 'outrageous'
|
||||||
|
p = 0
|
||||||
|
fingerprint = ''
|
||||||
|
for ch in cacheStatus:
|
||||||
|
ic = ord(ch) ^ ord(key[p])
|
||||||
|
p += 1
|
||||||
|
if p >= len(key):
|
||||||
|
p = 0
|
||||||
|
fingerprint += chr(ic)
|
||||||
|
|
||||||
|
self.notify.info('client-fingerprint %s|%s' % (requesterId, fingerprint))
|
||||||
|
self.air.writeServerEvent('client-fingerprint', requesterId, fingerprint)
|
||||||
|
if hasattr(self.air, 'cpuInfoMgr'):
|
||||||
|
self.air.cpuInfoMgr.sendCpuInfoToUd(info, fingerprint)
|
||||||
|
|
||||||
|
|
||||||
|
def setFrameRate(self, fps, deviation, numAvs,
|
||||||
|
locationCode, timeInLocation, timeInGame,
|
||||||
|
gameOptionsCode, vendorId, deviceId,
|
||||||
|
processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, osInfo, cpuSpeed,
|
||||||
|
numCpuCores, numLogicalCpus, apiName):
|
||||||
|
""" This method is called by the client at the interval
|
||||||
|
specified by getFrameRateInterval(), to report its current
|
||||||
|
frame rate. """
|
||||||
|
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
info = '%0.1f fps|%0.3fd|%s avs|%s|%d|%d|%s|0x%04x|0x%04x|%0.1fMB|%0.1fMB|%0.1fMB|%d|%s|%s|%s cpus|%s' % (
|
||||||
|
fps, deviation, numAvs, locationCode, timeInLocation,
|
||||||
|
timeInGame, gameOptionsCode,
|
||||||
|
vendorId, deviceId, processMemory, pageFileUsage, physicalMemory,
|
||||||
|
pageFaultCount, '%s.%d.%d.%d' % osInfo, '%0.03f,%0.03f' % cpuSpeed,
|
||||||
|
'%d,%d' % (numCpuCores, numLogicalCpus),
|
||||||
|
apiName)
|
||||||
|
self.notify.info('client-fps %s|%s' % (requesterId, info))
|
||||||
|
self.air.writeServerEvent('client-fps', requesterId, info)
|
||||||
|
|
||||||
|
if __dev__:
|
||||||
|
def checkForGarbageLeaks(self, wantReply):
|
||||||
|
senderId = self.air.getAvatarIdFromSender()
|
||||||
|
self.notify.info("checking for garbage leaks requested by %s" % senderId)
|
||||||
|
# okay checking for garbage leaks should only be done by devs, it's rare enough i'll flag it
|
||||||
|
# as suspicious
|
||||||
|
self.air.writeServerEvent('suspicious', senderId, 'checkForGarbageLeaks')
|
||||||
|
numLeaks = GarbageReport.checkForGarbageLeaks()
|
||||||
|
if wantReply:
|
||||||
|
requesterId = self.air.getAvatarIdFromSender()
|
||||||
|
self.sendUpdateToAvatarId(requesterId, 'setNumAIGarbageLeaks', [numLeaks])
|
||||||
|
|
||||||
|
def setClientGarbageLeak(self, num, description):
|
||||||
|
messenger.send(GarbageLeakServerEventAggregatorAI.ClientLeakEvent, [num, description])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue