forked from SpockBotMC/SpockBot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimers.py
145 lines (111 loc) · 3.98 KB
/
timers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
Provides clock-time and **SERVER** tick-timers and a convenient API for
registering them. Clock-time timers are as precise as the underlying OS
makes them, server tick-timers are based on time updates from the server
"""
import time
from spockbot.plugins.base import PluginBase, pl_announce
class BaseTimer(object):
def __init__(self, callback, runs=-1):
self.callback = callback
self.runs = runs
def countdown(self):
return -1
def check(self):
return True
def get_runs(self):
return self.runs
def update(self):
if self.check():
self.fire()
def fire(self):
self.callback()
if self.runs > 0 and not self.runs < 0:
self.runs -= 1
if self.runs:
self.reset()
def stop(self):
self.runs = 0
def reset(self):
pass
# Time based timer
class EventTimer(BaseTimer):
def __init__(self, wait_time, callback, runs=1):
super(EventTimer, self).__init__(callback, runs)
self.wait_time = wait_time
self.end_time = time.time() + self.wait_time
def countdown(self):
count = self.end_time - time.time()
return count if count > 0 else 0
def check(self):
if self.runs == 0:
return False
return self.end_time <= time.time()
def reset(self):
self.end_time = time.time() + self.wait_time
# World tick based timer
class TickTimer(BaseTimer):
def __init__(self, world, wait_ticks, callback, runs=1):
super(TickTimer, self).__init__(callback, runs)
self.world = world
self.wait_ticks = wait_ticks
self.end_tick = self.world.age + self.wait_ticks
def check(self):
if self.runs == 0:
return False
return self.end_tick <= self.world.age
def reset(self):
self.end_tick = self.world.age + self.wait_ticks
class TimersCore(object):
def __init__(self, world):
self.timers = []
self.persist_timers = []
self.world = world
def reg_timer(self, timer, persist=False):
if not persist:
self.timers.append(timer)
else:
self.persist_timers.append(timer)
def get_timeout(self):
timeout = -1
for timer in self.timers + self.persist_timers:
if timeout > timer.countdown() or timeout == -1:
timeout = timer.countdown()
return timeout
def reg_event_timer(self, wait_time, callback, runs=-1, persist=False):
self.reg_timer(EventTimer(wait_time, callback, runs), persist)
def reg_tick_timer(self, wait_ticks, callback, runs=-1, persist=False):
self.reg_timer(TickTimer(self.world, wait_ticks, callback, runs),
persist)
class WorldTick(object):
def __init__(self):
self.age = 0
@pl_announce('Timers')
class TimersPlugin(PluginBase):
requires = 'World'
events = {
'event_tick': 'tick',
'net_disconnect': 'handle_disconnect',
}
def __init__(self, ploader, settings):
super(TimersPlugin, self).__init__(ploader, settings)
if not self.world:
self.world = WorldTick()
ploader.reg_event_handler('PLAY<Time Update',
self.handle_time_update)
self.timer_core = TimersCore(self.world)
ploader.provides('Timers', self.timer_core)
def tick(self, name, data):
for timer in self.timer_core.timers:
timer.update()
if not timer.get_runs():
self.timer_core.timers.remove(timer)
for timer in self.timer_core.persist_timers:
timer.update()
if not timer.get_runs():
self.timer_core.persist_timers.remove(timer)
# Time Update - We grab world age if the world plugin isn't available
def handle_time_update(self, name, packet):
self.world.age = packet.data['world_age']
def handle_disconnect(self, name, data):
self.timer_core.timers = []