71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
import asyncio
|
|
import datetime
|
|
import logging
|
|
import time
|
|
from threading import Thread
|
|
from typing import Optional
|
|
|
|
from hopper.models.player import PlayerList
|
|
from hopper.ws_server import WSServer
|
|
from settings import settings
|
|
|
|
|
|
class InactivityWatchdog(Thread):
|
|
def __init__(
|
|
self, players: PlayerList, ws_server: Optional[WSServer] = None, *args, **kwargs
|
|
) -> None:
|
|
self.players = players
|
|
self.ws_server = ws_server
|
|
self.stopped = False
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def run(self) -> None:
|
|
logging.info("Starting inactivity watchdog")
|
|
while not self.stopped:
|
|
self.cleanup_players()
|
|
time.sleep(settings.inacivity_watchdog.TICK_INTERVAL)
|
|
|
|
def cleanup_players(self) -> None:
|
|
now = datetime.datetime.now()
|
|
inactivity_threshold = now - datetime.timedelta(
|
|
seconds=settings.inacivity_watchdog.INACIVITY_TIMEOUT
|
|
)
|
|
kick_threshold = now - datetime.timedelta(
|
|
seconds=settings.inacivity_watchdog.KICK_TIMEOUT
|
|
)
|
|
|
|
send_game_state = False
|
|
|
|
for player in self.players:
|
|
if (
|
|
player.can_be_deactivated
|
|
and player.active
|
|
and player.last_seen < inactivity_threshold
|
|
):
|
|
player.active = False
|
|
logging.info(f"Player {player} set as inactive")
|
|
send_game_state = True
|
|
|
|
# safe remove from list
|
|
n = 0
|
|
while n < len(self.players):
|
|
player = self.players[n]
|
|
if player.can_be_deactivated and player.last_seen < kick_threshold:
|
|
self.players.pop(n)
|
|
logging.info(f"Player {player} kicked out")
|
|
send_game_state = True
|
|
else:
|
|
n += 1
|
|
|
|
if send_game_state:
|
|
self.send_game_state()
|
|
|
|
def send_game_state(self):
|
|
if not self.ws_server:
|
|
return
|
|
logging.info("Sending WS game state")
|
|
asyncio.run(self.ws_server.send_game_state())
|
|
|
|
def stop(self) -> None:
|
|
self.stopped = True
|