class PythonTimer(TimerComponent): __slots__ = ('_timeInterval', '__weakref__') def __init__(self, viewObject, typeID, viewID, totalTime, finishTime, startTime=None, interval=1.0, secondInRow=False, **kwargs): super(PythonTimer, self).__init__(viewObject, typeID, viewID, totalTime, finishTime, startTime, secondInRow=secondInRow, **kwargs) self._timeInterval = TimeInterval(interval, self, '_tick') def clear(self): self._timeInterval.stop() super(PythonTimer, self).clear() def _startTick(self): if self._totalTime: timeLeft = max(0, self._finishTime - BigWorld.serverTime()) if timeLeft: self._setViewSnapshot(timeLeft) self._timeInterval.restart() def _stopTick(self): self._timeInterval.stop() def _tick(self): timeLeft = self._finishTime - BigWorld.serverTime() if timeLeft >= 0: self._setViewSnapshot(timeLeft) else: self.hide() def _setViewSnapshot(self, timeLeft): raise NotImplementedError
class PrecisePythonTimer(PythonTimer): __slots__ = ('__short1stPeriodCbId', '__interval', '_timeInterval', '_startTime') def __init__(self, viewObject, typeID, viewID, totalTime, finishTime, startTime=None, interval=1.0, secondInRow=False, **kwargs): super(PrecisePythonTimer, self).__init__(viewObject, typeID, viewID, totalTime, finishTime, startTime, interval, secondInRow, **kwargs) if startTime is not None: self._startTime = startTime self.__interval = interval self.__short1stPeriodCbId = None return def _startTick(self): if self._totalTime: timeLeft = max(0, self._finishTime - BigWorld.serverTime()) if timeLeft: self._setViewSnapshot(timeLeft) self._timeInterval = TimeInterval(self.__interval, self, '_tick') firstShortPeriod = float(self._totalTime) % self.__interval if round(firstShortPeriod, 4) > 0.0: self.__short1stPeriodCbId = BigWorld.callback(firstShortPeriod, self.__onShort1stPeriodFinished) else: self._timeInterval.restart() def clear(self): self.__clearShort1stPeriodCb() super(PrecisePythonTimer, self).clear() def _stopTick(self): self.__clearShort1stPeriodCb() super(PrecisePythonTimer, self)._stopTick() def _setViewSnapshot(self, timeLeft): raise NotImplementedError def __clearShort1stPeriodCb(self): if self.__short1stPeriodCbId is not None: BigWorld.cancelCallback(self.__short1stPeriodCbId) self.__short1stPeriodCbId = None return def __onShort1stPeriodFinished(self): self.__short1stPeriodCbId = None self._tick() timeLeft = self._finishTime - BigWorld.serverTime() if timeLeft > 0: self._timeInterval.restart() else: self.hide() return
class VehicleStateController(IBattleController): def __init__(self): super(VehicleStateController, self).__init__() self.__eManager = Event.EventManager() self.onVehicleStateUpdated = Event.Event(self.__eManager) self.onVehicleControlling = Event.Event(self.__eManager) self.onPostMortemSwitched = Event.Event(self.__eManager) self.onRespawnBaseMoving = Event.Event(self.__eManager) self.__cachedStateValues = {} self.__cachedRepairingCallbackID = None self.__waitingTI = TimeInterval(VEHICLE_WAINING_INTERVAL, self, '_waiting') self.__vehicleID = 0 self.__updater = None self.__isRqToSwitch = False self.__isInPostmortem = False self.__needInvalidate = False return def getControllerID(self): return BATTLE_CTRL_ID.OBSERVED_VEHICLE_STATE def startControl(self, *_): pass def stopControl(self): if self.__waitingTI is not None: self.__waitingTI.stop() self.__waitingTI = None if self.__updater is not None: self.__updater.clear() self.__updater = None self.__vehicleID = 0 self.__isRqToSwitch = False self.__isInPostmortem = False self.__eManager.clear() self.__cachedStateValues.clear() if self.__cachedRepairingCallbackID: BigWorld.cancelCallback(self.__cachedRepairingCallbackID) return @property def isInPostmortem(self): return self.__isInPostmortem def setPlayerVehicle(self, vehicleID): self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, vehicleID) self.__vehicleID = vehicleID self.__updater = _VehicleUpdater(self, self.__vehicleID) self.__waitingTI.restart() def getControllingVehicle(self): vehicle = None if self.__vehicleID: vehicle = BigWorld.entity(self.__vehicleID) return vehicle def getControllingVehicleID(self): return self.__vehicleID def notifyStateChanged(self, stateID, value): if stateID == VEHICLE_VIEW_STATE.DEVICES: self.__cachedStateValues.setdefault(stateID, {}) deviceName = value[0] cachedRepairingDeviceName = first( self.__cachedStateValues.get(VEHICLE_VIEW_STATE.REPAIRING, ())) if cachedRepairingDeviceName == deviceName and value[ 2] == DEVICE_STATE_NORMAL: self.__cachedStateValues.pop(VEHICLE_VIEW_STATE.REPAIRING) self.__cachedStateValues[stateID][deviceName] = value else: if stateID == VEHICLE_VIEW_STATE.REPAIRING: if self.__cachedRepairingCallbackID: BigWorld.cancelCallback(self.__cachedRepairingCallbackID) BigWorld.callback( value[2], partial(self.__cachedRepairingCallback, value)) self.__cachedStateValues[stateID] = value self.onVehicleStateUpdated(stateID, value) def __cachedRepairingCallback(self, value): self.__cachedRepairingCallbackID = None if self.__cachedStateValues.get(VEHICLE_VIEW_STATE.REPAIRING) == value: self.__cachedStateValues.pop(VEHICLE_VIEW_STATE.REPAIRING) return def getStateValue(self, stateID): if stateID in self.__cachedStateValues: if stateID == VEHICLE_VIEW_STATE.DEVICES: value = self.__cachedStateValues[stateID].values() else: value = self.__cachedStateValues[stateID] return value else: return None def refreshVehicleStateValue(self, stateID): if stateID in self.__cachedStateValues: self.onVehicleStateUpdated(stateID, self.__cachedStateValues[stateID]) def invalidate(self, state, value, vehicleID=0): if vehicleID != 0 and vehicleID != self.__vehicleID: return else: isStateChangeHandled = False if self.__isRqToSwitch and self.__waitingTI.isStarted(): self._waiting() if self.__updater is not None: isStateChangeHandled = self.__updater.handleStateChange( state, value) if not isStateChangeHandled: self.notifyStateChanged(state, value) return def switchToPostmortem(self, noRespawnPossible, respawnAvailable): self.__isRqToSwitch = False if avatar_getter.getPlayerVehicleID() == self.__vehicleID: if self.__updater is not None: self.__updater.stop() self.__updater.updateOnce() self.__isInPostmortem = True self.onPostMortemSwitched(noRespawnPossible, respawnAvailable) return def switchToOther(self, vehicleID): if vehicleID is None: self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0) self.__needInvalidate = True return elif self.__vehicleID == vehicleID and not self.__needInvalidate: return else: self.__needInvalidate = False self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, vehicleID) self.__waitingTI.stop() if self.__updater: self.__updater.stop() self.__vehicleID = vehicleID self.__isRqToSwitch = True self.notifyStateChanged(VEHICLE_VIEW_STATE.PLAYER_INFO, self.__vehicleID) self.__cachedStateValues.clear() self.__waitingTI.start() return def refreshObserverVehicleVisual(self): vehicle = self.getControllingVehicle() if vehicle is not None: self.onVehicleControlling(vehicle) return def movingToRespawn(self): self.__isInPostmortem = False self.notifyStateChanged(VEHICLE_VIEW_STATE.SWITCHING, 0) self.onRespawnBaseMoving() self.__cachedStateValues.clear() def _waiting(self): vehicle = BigWorld.entity(self.__vehicleID) if vehicle is not None and vehicle.isStarted: self.__waitingTI.stop() self._setup(vehicle) return def _setup(self, vehicle): if self.__updater is not None: self.__updater = self.__updater.switch(self.__vehicleID) if self.__isRqToSwitch: nationID = vehicle.typeDescriptor.type.id[0] notifications = avatar_getter.getSoundNotifications() if notifications is not None: notifications.clear() SoundGroups.g_instance.soundModes.setCurrentNation( nations.NAMES[nationID]) self.onVehicleControlling(vehicle) if VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED in self.__cachedStateValues.keys( ): self.onVehicleStateUpdated( VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED, self.getStateValue(VEHICLE_VIEW_STATE.DUAL_GUN_STATE_UPDATED)) if self.__updater is not None: self.__updater.start() return