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
Exemple #3
0
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