ToonTownRewritten/otp/distributed/TelemetryLimiter.py

118 lines
3.2 KiB
Python

from direct.showbase.DirectObject import DirectObject
from otp.avatar.DistributedPlayer import DistributedPlayer
from direct.task.Task import Task
class TelemetryLimiter(DirectObject):
TaskName = 'TelemetryLimiterEnforce'
LeakDetectEventName = 'telemetryLimiter'
def __init__(self):
self._objs = {}
self._task = taskMgr.add(self._enforceLimits, self.TaskName, priority=40)
def destroy(self):
taskMgr.remove(self._task)
del self._objs
def getNumObjs(self):
return len(self._objs)
def addObj(self, obj):
id = obj.getTelemetryLimiterId()
self._objs[id] = obj
self.accept(self._getDummyEventName(obj), self._dummyEventHandler)
def hasObj(self, obj):
id = obj.getTelemetryLimiterId()
return id in self._objs
def _getDummyEventName(self, obj):
return '%s-%s-%s-%s' % (self.LeakDetectEventName,
obj.getTelemetryLimiterId(),
id(obj),
obj.__class__.__name__)
def _dummyEventHandler(self, *args, **kargs):
pass
def removeObj(self, obj):
id = obj.getTelemetryLimiterId()
self._objs.pop(id)
self.ignore(self._getDummyEventName(obj))
def _enforceLimits(self, task = None):
for obj in self._objs.itervalues():
obj.enforceTelemetryLimits()
return Task.cont
class TelemetryLimit:
def __call__(self, obj):
pass
class RotationLimitToH(TelemetryLimit):
def __init__(self, pConst = 0.0, rConst = 0.0):
self._pConst = pConst
self._rConst = rConst
def __call__(self, obj):
obj.setHpr(obj.getH(), self._pConst, self._rConst)
class TLNull:
def __init__(self, *limits):
pass
def destroy(self):
pass
class TLGatherAllAvs(DirectObject):
def __init__(self, name, *limits):
self._name = name
self._avs = {}
self._limits = makeList(limits)
self._avId2limits = {}
avs = base.cr.doFindAllInstances(DistributedPlayer)
for av in avs:
self._handlePlayerArrive(av)
self.accept(DistributedPlayer.GetPlayerGenerateEvent(), self._handlePlayerArrive)
self.accept(DistributedPlayer.GetPlayerDeleteEvent(), self._handlePlayerLeave)
def _handlePlayerArrive(self, av):
if av is not localAvatar:
self._avs[av.doId] = av
limitList = []
for limit in self._limits:
l = limit()
limitList.append(l)
av.addTelemetryLimit(l)
self._avId2limits[av.doId] = limitList
base.cr.telemetryLimiter.addObj(av)
def _handlePlayerLeave(self, av):
if av is not localAvatar and base.cr.telemetryLimiter.hasObj(av) and av.doId in self._avId2limits:
base.cr.telemetryLimiter.removeObj(av)
for limit in self._avId2limits[av.doId]:
av.removeTelemetryLimit(limit)
del self._avId2limits[av.doId]
if av.doId in self._avs:
del self._avs[av.doId]
def destroy(self):
self.ignoreAll()
while len(self._avs):
self._handlePlayerLeave(self._avs.values()[0])
del self._avs
del self._limits
del self._avId2limits