Skip to content

Commit e544775

Browse files
committed
feat: add stats record for slot
1 parent 9432d49 commit e544775

File tree

3 files changed

+126
-8
lines changed

3 files changed

+126
-8
lines changed

mount/MountSlot.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import os
2-
from threading import Lock
2+
from threading import Lock, Thread
3+
import time
4+
from typing import Callable, Optional
5+
from anyio import Event
36

47
from jproperties import Properties
58

@@ -8,12 +11,39 @@
811
from .utils import logger, psi, rtr
912

1013

14+
class StatsChecker(Thread):
15+
def __init__(self, interval: int, cb: Callable[[], None]):
16+
super().__init__()
17+
self.setDaemon(True)
18+
self.setName(self.__class__.__name__)
19+
self._report_time = time.time()
20+
self.stop_event = Event()
21+
self.interval = interval
22+
self._callback = cb
23+
24+
def run(self):
25+
while True: # loop until stop
26+
while True: # # loop for report
27+
if self.stop_event.wait(1):
28+
return
29+
if time.time() - self._report_time > self.interval:
30+
break
31+
self._report_time = time.time()
32+
self._callback()
33+
34+
def stop(self):
35+
self.stop_event.set()
36+
1137
class MountSlot:
1238
def __init__(self, path):
1339
self.path = path
1440
self.load_config()
1541
self.properties = Properties()
1642
self.slot_lock = Lock()
43+
self.__players = []
44+
self.__players_lock = Lock()
45+
self.__stats_lock = Lock()
46+
self.__stats_checker = StatsChecker(60, self.update_stats)
1747

1848
@property
1949
def name(self):
@@ -88,3 +118,48 @@ def edit_config(self, key: str, value: str):
88118
self._config.__setattr__(key, value)
89119
self.save_config()
90120
return rtr('config.set_value', key=rtr(f'config.slot.{key}'), value=self._config.__getattribute__(key))
121+
122+
def on_player_join(self, player: str):
123+
with self.__players_lock:
124+
self.update_stats()
125+
self._config.stats.total_players = self._config.stats.total_players + 1
126+
self.__players.append(player)
127+
self.update_stats()
128+
129+
def on_player_left(self, player: str):
130+
try:
131+
with self.__players_lock:
132+
self.update_stats()
133+
self.__players.remove(player)
134+
except ValueError:
135+
pass
136+
137+
def on_mount(self):
138+
if not self.__stats_checker.is_alive:
139+
with self.__stats_lock:
140+
current = time.time_ns
141+
self._config.stats.last_mount_ns = current
142+
self.save_config()
143+
self.__stats_checker.start()
144+
145+
def on_unmount(self):
146+
if self.__stats_checker.is_alive:
147+
self.update_stats()
148+
self.__stats_checker.stop()
149+
self.__stats_checker.join()
150+
151+
152+
def update_stats(self):
153+
if not self.__stats_checker.is_alive:
154+
return
155+
with self.__stats_lock:
156+
current = time.time_ns
157+
prev = self._config.stats.last_mount_ns
158+
p = len(self.__players)
159+
t = current - prev
160+
stats = self._config.stats
161+
stats.last_mount_ns = current
162+
stats.total_use_time = stats.total_use_time + t
163+
stats.total_player_time = stats.total_player_time + t * p
164+
self._config.stats = stats
165+
self.save_config()

mount/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import time
12
from typing import List
23

34
from mcdreforged.api.rtext import *
@@ -30,6 +31,12 @@ def load() -> 'MountConfig':
3031
return psi.load_config_simple(file_name=CONFIG_NAME, target_class=MountConfig, in_data_folder=False)
3132

3233

34+
class SlotStats(Serializable):
35+
last_mount_ns: int = time.time_ns
36+
total_use_time: int = 0
37+
total_player_time: int = 0
38+
total_players: int = 0
39+
3340
class SlotConfig(Serializable):
3441
checked: bool = False
3542
desc: str = "Demo server"
@@ -45,6 +52,9 @@ class SlotConfig(Serializable):
4552
# mcdr plugin path for specific plugin, empty for disable, should be relative to mc server path
4653
plugin_dir: str = ""
4754

55+
# slot stats, used for rank
56+
stats: SlotStats = SlotStats()
57+
4858
def display(self, server_path: str):
4959
conf_list = self.get_annotations_fields()
5060

mount/entry.py

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,49 @@
1111
manager: Optional[MountManager] = None
1212

1313

14-
def welcome(server: PluginServerInterface, player: str, info: Info):
15-
server.tell(player, rtr('help_msg.welcome'))
16-
17-
1814
def on_load(server: PluginServerInterface, prev_module):
1915
global manager
2016
config: MountConfig = server.load_config_simple(
2117
file_name=CONFIG_NAME, in_data_folder=False, target_class=MountConfig)
2218
manager = MountManager(config=config)
2319
register_commands(server, manager)
24-
if config.welcome_player:
25-
server.register_event_listener(
26-
event='mcdr.player_joined', callback=welcome)
20+
21+
if manager.current_slot and server.is_server_running():
22+
manager.current_slot.on_mount()
23+
24+
25+
def on_unload(server: PluginServerInterface):
26+
if not manager:
27+
return
28+
if manager.current_slot and server.is_server_running():
29+
manager.current_slot.on_unmount()
30+
31+
32+
def on_server_startup(server: PluginServerInterface):
33+
if not manager:
34+
return
35+
if manager.current_slot:
36+
manager.current_slot.on_mount()
37+
38+
39+
def on_server_stop(server: PluginServerInterface, code: int):
40+
if not manager:
41+
return
42+
if manager.current_slot:
43+
manager.current_slot.on_unmount()
44+
45+
46+
def on_player_joined(server: PluginServerInterface, player: str, info: Info):
47+
if not manager:
48+
return
49+
if manager._config.welcome_player:
50+
server.tell(player, rtr('help_msg.welcome'))
51+
if manager.current_slot:
52+
manager.current_slot.on_player_join(player)
53+
54+
55+
def on_player_left(server: PluginServerInterface, player: str):
56+
if not manager:
57+
return
58+
if manager.current_slot:
59+
manager.current_slot.on_player_left(player)

0 commit comments

Comments
 (0)