1
1
import json
2
2
import os
3
+ import threading
3
4
import time
4
5
from enum import Enum
5
6
from io import StringIO
7
+ from time import sleep
6
8
from typing import List , Union
7
9
8
10
from mcdreforged .api .all import *
@@ -44,7 +46,13 @@ class TaskType(Enum):
44
46
python_code = 'python_code'
45
47
46
48
47
- class Task (Serializable ):
49
+ class Task :
50
+ def __init__ (self , name , task_type , created_by , command ):
51
+ self .name = name
52
+ self .task_type = task_type
53
+ self .created_by = created_by
54
+ self .command = command
55
+
48
56
name : str = 'undefined'
49
57
50
58
task_type : TaskType = TaskType .undefined
@@ -113,12 +121,55 @@ def execute_task(self, server: PluginServerInterface, hook: str, var_dict: dict
113
121
if obj_dict is not None :
114
122
exec (self .command , obj_dict , {})
115
123
else :
116
- exec (self .command , var_dict , locals ())
117
-
124
+ if var_dict is not None :
125
+ exec (self .command , var_dict , locals ())
126
+ else :
127
+ exec (self .command , globals (), locals ())
128
+
118
129
server .logger .debug (f'Task finished, name: { self .name } , task_type: { self .task_type } , command: { self .command } , '
119
130
f'costs { time .time () - start_time } seconds.' )
120
131
121
132
133
+ def stop_all_schedule_daemon_threads ():
134
+ if len (temp_config .schedule_daemon_threads ) == 0 :
135
+ return
136
+
137
+ for thr in temp_config .schedule_daemon_threads :
138
+ thr .break_thread ()
139
+ temp_config .schedule_daemon_threads .remove (thr )
140
+
141
+
142
+ class AThread (threading .Thread ):
143
+ def init_thread (self ):
144
+ super ().__init__ (daemon = True )
145
+
146
+
147
+ class ScheduleTask (Task , AThread ):
148
+ def __init__ (self , name , task_type , created_by , command , server_inst , exec_interval ):
149
+ super ().__init__ (name , task_type , created_by , command )
150
+ self .server_inst = server_inst
151
+ self .exec_interval = exec_interval
152
+ self .stop_event = threading .Event ()
153
+ super ().init_thread ()
154
+ temp_config .schedule_daemon_threads .append (self )
155
+
156
+ def break_thread (self ):
157
+ self .stop_event .set ()
158
+
159
+ def run (self ):
160
+ if self .exec_interval <= 0 :
161
+ self .server_inst .logger .warning (
162
+ f'Schedule task { self .name } has illegal exec_interval: { self .exec_interval } ' )
163
+ return
164
+
165
+ while True :
166
+ for _ in range (self .exec_interval ):
167
+ if self .stop_event .is_set ():
168
+ return
169
+ sleep (1.0 )
170
+ self .execute_task (self .server_inst , 'schedule' )
171
+
172
+
122
173
class Configuration (Serializable ):
123
174
def __init__ (self , ** kwargs ):
124
175
super ().__init__ (** kwargs )
@@ -156,6 +207,8 @@ def __init__(self):
156
207
task : dict [str , Task ]
157
208
158
209
scripts_list : dict [str , str ]
210
+
211
+ schedule_daemon_threads : list = list ()
159
212
160
213
161
214
temp_config : TempConfig
@@ -249,7 +302,7 @@ def unmount_task(hook: str, task: str, src: CommandSource, server: PluginServerI
249
302
250
303
251
304
def create_task (task_type : str , command : str , name : str , src : CommandSource , server : PluginServerInterface ,
252
- created_by = None ):
305
+ is_schedule = False , exec_interval = 0 , created_by = None ):
253
306
if name in temp_config .task :
254
307
src .reply (RTextMCDRTranslation ('hooks.create.already_exist' ))
255
308
return
@@ -266,7 +319,14 @@ def create_task(task_type: str, command: str, name: str, src: CommandSource, ser
266
319
if created_by is None :
267
320
created_by = str (src )
268
321
269
- temp_config .task [name ] = Task (name = name , task_type = tsk_type , command = command , created_by = created_by )
322
+ if not is_schedule :
323
+ temp_config .task [name ] = Task (name = name , task_type = tsk_type , command = command , created_by = created_by )
324
+ else :
325
+ var1 = ScheduleTask (name = name , task_type = tsk_type , command = command , created_by = created_by ,
326
+ server_inst = server , exec_interval = exec_interval )
327
+ temp_config .task [name ] = var1
328
+ var1 .start ()
329
+ var1 .name = f'hooks - schedule_task_daemon({ name } )'
270
330
271
331
server .logger .info (f'Successfully created task { name } ' )
272
332
src .reply (RTextMCDRTranslation ('hooks.create.success' , name ))
@@ -282,6 +342,11 @@ def delete_task(name: str, src: CommandSource, server: PluginServerInterface):
282
342
if tasks_in_hook == name :
283
343
unmount_task (hook , name , src , server )
284
344
345
+ var1 = temp_config .task .get (name )
346
+ if isinstance (var1 , ScheduleTask ):
347
+ var1 .break_thread ()
348
+ temp_config .schedule_daemon_threads .remove (var1 )
349
+
285
350
temp_config .task .pop (name )
286
351
287
352
server .logger .info (f'Successfully deleted task { name } ' )
@@ -314,7 +379,7 @@ def list_mount(src: CommandSource):
314
379
list_hooks .append (str (temp_config .hooks .get (str (hk ))))
315
380
316
381
src .reply (RTextMCDRTranslation ('hooks.list.mount' , * list_hooks ))
317
-
382
+
318
383
319
384
@new_thread ('hooks - list' )
320
385
def list_scripts (src : CommandSource ):
@@ -332,6 +397,8 @@ def list_scripts(src: CommandSource):
332
397
def reload_config (src : CommandSource , server : PluginServerInterface ):
333
398
global config , temp_config
334
399
400
+ stop_all_schedule_daemon_threads ()
401
+
335
402
temp_config = TempConfig ()
336
403
config = server .load_config_simple (target_class = Configuration )
337
404
@@ -394,7 +461,7 @@ def parse_and_apply_scripts(script: str, server: PluginServerInterface):
394
461
create_task (task .get ('task_type' ), task .get ('command' ), task .get ('name' ),
395
462
server .get_plugin_command_source (),
396
463
server , created_by = script )
397
-
464
+
398
465
for hook in task .get ('hooks' ):
399
466
# 挂载
400
467
mount_task (hook , task .get ('name' ), server .get_plugin_command_source (), server )
@@ -464,6 +531,25 @@ def on_load(server: PluginServerInterface, old_module):
464
531
)
465
532
)
466
533
)
534
+ .then (
535
+ Literal ('schedule' )
536
+ .then (
537
+ Text ('name' )
538
+ .then (
539
+ Integer ('exec_interval' )
540
+ .then (
541
+ Text ('task_type' )
542
+ .then (
543
+ GreedyText ('command' )
544
+ .requires (lambda src : src .has_permission (3 ))
545
+ .runs (lambda src , ctx : create_task (ctx ['task_type' ], ctx ['command' ], ctx ['name' ], src ,
546
+ server , is_schedule = True ,
547
+ exec_interval = ctx ['exec_interval' ]))
548
+ )
549
+ )
550
+ )
551
+ )
552
+ )
467
553
.then (
468
554
Literal ('mount' )
469
555
.then (
@@ -535,6 +621,9 @@ def on_load(server: PluginServerInterface, old_module):
535
621
536
622
def on_unload (server : PluginServerInterface ):
537
623
global temp_config
624
+
625
+ stop_all_schedule_daemon_threads ()
626
+
538
627
trigger_hooks (Hooks .on_plugin_unloaded , server , {'server' : process_arg_server (server )})
539
628
540
629
server .save_config_simple (config )
0 commit comments