Poodletooth-iLand/otp/ai/Barrier.py

83 lines
3.1 KiB
Python

from otp.ai.AIBase import *
from direct.task import Task
from direct.showbase import DirectObject
import random
class Barrier(DirectObject.DirectObject):
notify = directNotify.newCategory('Barrier')
def __init__(self, name, uniqueName, avIdList, timeout, clearedFunc = None, timeoutFunc = None, doneFunc = None):
self.name = name
self.uniqueName = uniqueName + '-Barrier'
self.avIdList = avIdList[:]
self.pendingAvatars = self.avIdList[:]
self.timeout = timeout
self.clearedFunc = clearedFunc
self.timeoutFunc = timeoutFunc
self.doneFunc = doneFunc
if len(self.pendingAvatars) == 0:
self.notify.debug('%s: barrier with empty list' % self.uniqueName)
self.active = 0
if self.clearedFunc:
self.clearedFunc()
if self.doneFunc:
self.doneFunc(self.avIdList)
return
self.taskName = self.uniqueName + '-Timeout'
origTaskName = self.taskName
while taskMgr.hasTaskNamed(self.taskName):
self.taskName = origTaskName + '-' + str(random.randint(0, 10000))
taskMgr.doMethodLater(self.timeout, self.__timerExpired, self.taskName)
for avId in self.avIdList:
event = simbase.air.getAvatarExitEvent(avId)
self.acceptOnce(event, self.__handleUnexpectedExit, extraArgs=[avId])
self.notify.debug('%s: expecting responses from %s within %s seconds' % (self.uniqueName, self.avIdList, self.timeout))
self.active = 1
def cleanup(self):
if self.active:
taskMgr.remove(self.taskName)
self.active = 0
self.ignoreAll()
def clear(self, avId):
if avId not in self.pendingAvatars:
self.notify.warning('%s: tried to clear %s, who was not listed.' % (self.uniqueName, avId))
return
self.notify.debug('%s: clearing avatar %s' % (self.uniqueName, avId))
self.pendingAvatars.remove(avId)
if len(self.pendingAvatars) == 0:
self.notify.debug('%s: barrier cleared by %s' % (self.uniqueName, self.avIdList))
self.cleanup()
if self.clearedFunc:
self.clearedFunc()
if self.doneFunc:
self.doneFunc(self.avIdList)
def isActive(self):
return self.active
def getPendingAvatars(self):
return self.pendingAvatars[:]
def __timerExpired(self, task):
self.notify.warning('%s: timeout expired; responses not received from %s' % (self.uniqueName, self.pendingAvatars))
self.cleanup()
if self.timeoutFunc:
self.timeoutFunc(self.pendingAvatars[:])
if self.doneFunc:
clearedAvIds = self.avIdList[:]
for avId in self.pendingAvatars:
clearedAvIds.remove(avId)
self.doneFunc(clearedAvIds)
return Task.done
def __handleUnexpectedExit(self, avId):
if avId not in self.avIdList:
return
self.avIdList.remove(avId)
if avId in self.pendingAvatars:
self.clear(avId)