mirror of
https://github.com/evennia/evennia.git
synced 2026-03-25 09:16:32 +01:00
Added more stable events.
- added PIDs to all events, so they can be deleted safely. - scheduler.del_event(pid) cleanly deletes events from the scheduler - added @delevent for deleting events based on PID (@ps shows this now) - Events has a self.repeat property allowing them to only be repeated a certain time (default is infinitely many times). After the set number of repeats, the event deletes itself from the scheduler. Events are currently not persistently stored; this is left for future commits. . Griatch
This commit is contained in:
parent
642932a403
commit
5e866c6b73
5 changed files with 148 additions and 26 deletions
|
|
@ -775,3 +775,21 @@ def cmd_help(command):
|
|||
|
||||
source_object.emit_to(string)
|
||||
GLOBAL_CMD_TABLE.add_command("help", cmd_help)
|
||||
|
||||
## def cmd_testevent(command):
|
||||
## from src import events
|
||||
## from src import scheduler
|
||||
## source_object = command.source_object
|
||||
|
||||
## if not command.command_argument:
|
||||
## #event = events.IntervalEvent()
|
||||
## event = events.IntervalEvent()
|
||||
## event.repeats = 3
|
||||
## event.interval = 5
|
||||
## pid = scheduler.add_event(event)
|
||||
## source_object.emit_to("event with pid %s added." % pid)
|
||||
## else:
|
||||
## pid = command.command_argument
|
||||
## scheduler.del_event(pid)
|
||||
## source_object.emit_to("event with pid %s removed (if it existed)." % pid)
|
||||
## GLOBAL_CMD_TABLE.add_command("testevent", cmd_testevent)
|
||||
|
|
|
|||
|
|
@ -135,13 +135,18 @@ def cmd_ps(command):
|
|||
"""
|
||||
source_object = command.source_object
|
||||
|
||||
source_object.emit_to("-- Interval Events --")
|
||||
for event in scheduler.schedule:
|
||||
source_object.emit_to(" [%d/%d] %s" % (
|
||||
event.get_nextfire(),
|
||||
event.interval,
|
||||
event.description))
|
||||
source_object.emit_to("Totals: %d interval events" % (len(scheduler.schedule),))
|
||||
source_object.emit_to("Processes Scheduled:\n-- PID [time/interval] [repeats] description --")
|
||||
for event in scheduler.SCHEDULE:
|
||||
repeats = "[inf] "
|
||||
if event.repeats != None:
|
||||
repeats = "[%i] " % event.repeats
|
||||
source_object.emit_to(" %i [%d/%d] %s%s" % (
|
||||
event.pid,
|
||||
event.get_nextfire(),
|
||||
event.interval,
|
||||
repeats,
|
||||
event.description))
|
||||
source_object.emit_to("Totals: %d interval events" % (len(scheduler.SCHEDULE),))
|
||||
GLOBAL_CMD_TABLE.add_command("@ps", cmd_ps,
|
||||
priv_tuple=("genperms.process_control",), help_category="Admin")
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ from src.helpsys import helpsystem
|
|||
from src.config.models import CommandAlias
|
||||
from src.config import edit_aliases
|
||||
from src import cache
|
||||
from src import scheduler
|
||||
|
||||
|
||||
def cmd_reload(command):
|
||||
"""
|
||||
@reload - reload game subsystems
|
||||
|
|
@ -761,3 +764,37 @@ def cmd_setcmdalias(command):
|
|||
GLOBAL_CMD_TABLE.add_command("@setcmdalias", cmd_setcmdalias,
|
||||
priv_tuple=("genperms.process_control",),
|
||||
help_category="Admin")
|
||||
|
||||
|
||||
def cmd_delevent(command):
|
||||
"""
|
||||
@delevent - remove events manually
|
||||
|
||||
Usage:
|
||||
@delevent <pid>
|
||||
|
||||
Removes an event with the given pid (process ID) from the event scheduler.
|
||||
To see all active events and their pids, use the @ps command.
|
||||
"""
|
||||
source_object = command.source_object
|
||||
|
||||
if not command.command_argument:
|
||||
source_object.emit_to("Usage: @delevent <pid>")
|
||||
return
|
||||
try:
|
||||
pid = int(command.command_argument)
|
||||
except ValueError:
|
||||
source_object.emit_to("You must supply a valid pid number.")
|
||||
return
|
||||
event = scheduler.get_event(pid)
|
||||
if event:
|
||||
desc = event.description
|
||||
scheduler.del_event(pid)
|
||||
source_object.emit_to("Event %i - '%s' removed." % (pid, desc))
|
||||
else:
|
||||
source_object.emit_to("No event found with a pid of %i. Use @ps to list process IDs." % pid)
|
||||
|
||||
GLOBAL_CMD_TABLE.add_command("@delevent", cmd_delevent,
|
||||
priv_tuple=("genperms.process_control",),
|
||||
help_category="Admin")
|
||||
|
||||
|
|
|
|||
|
|
@ -18,18 +18,28 @@ class IntervalEvent(object):
|
|||
"""
|
||||
Represents an event that is triggered periodically. Sub-class this and
|
||||
fill in the stub function.
|
||||
|
||||
self.repeats decides if this event will fire indefinitely or only a
|
||||
certain number of times.
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, description="IntervalEvent"):
|
||||
"""
|
||||
Executed when the class is instantiated.
|
||||
"""
|
||||
# This is a globally unique ID of this event. If None, a new one will
|
||||
# be allocated when the event is added to the scheduler.
|
||||
self.pid = None
|
||||
# This is set to prevent a Nonetype exception on @ps before the
|
||||
# event is fired for the first time.
|
||||
self.time_last_executed = time.time()
|
||||
# This is what shows up on @ps in-game.
|
||||
self.name = None
|
||||
# This used to describe the event in @ps listings.
|
||||
self.description = description
|
||||
# An interval (in seconds) for execution.
|
||||
self.interval = None
|
||||
# How many times to repeat this event.
|
||||
# None : indefinitely,
|
||||
# positive integer : number of times
|
||||
self.repeats = None
|
||||
# A reference to the task.LoopingCall object.
|
||||
self.looped_task = None
|
||||
|
||||
|
|
@ -39,6 +49,18 @@ class IntervalEvent(object):
|
|||
"""
|
||||
return self.name
|
||||
|
||||
def __eq__(self, event2):
|
||||
"""
|
||||
Handles comparison operations.
|
||||
"""
|
||||
return self.pid == event2.pid
|
||||
|
||||
def __hash__(self):
|
||||
"""
|
||||
Used for dictionary key comparisons.
|
||||
"""
|
||||
return self.pid
|
||||
|
||||
def start_event_loop(self):
|
||||
"""
|
||||
Called to start up the event loop when the event is added to the
|
||||
|
|
@ -78,9 +100,16 @@ class IntervalEvent(object):
|
|||
def fire_event(self):
|
||||
"""
|
||||
Set the last ran stamp and fire off the event.
|
||||
Stop repeating if number of repeats have been achieved.
|
||||
"""
|
||||
self.set_lastfired()
|
||||
self.set_lastfired()
|
||||
self.event_function()
|
||||
if self.repeats != None:
|
||||
self.repeats -= 1
|
||||
if self.repeats <= 0 and self.pid != None:
|
||||
scheduler.del_event(self.pid)
|
||||
|
||||
|
||||
|
||||
class IEvt_Check_Sessions(IntervalEvent):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -9,9 +9,23 @@ ADDING AN EVENT:
|
|||
* Profit.
|
||||
"""
|
||||
|
||||
# List of IntervalEvent sub-classed objects.
|
||||
schedule = []
|
||||
|
||||
# dict of IntervalEvent sub-classed objects, keyed by their
|
||||
# process id:s.
|
||||
SCHEDULE = []
|
||||
|
||||
def next_free_pid():
|
||||
"""
|
||||
Find the next free pid
|
||||
"""
|
||||
pids = [event.pid for event in SCHEDULE]
|
||||
if not pids:
|
||||
return 0
|
||||
maxpid = max(pids)
|
||||
freepids = [pid for pid in xrange(maxpid+1) if pid not in pids]
|
||||
if freepids:
|
||||
return min(freepids)
|
||||
return maxpid + 1
|
||||
|
||||
def add_event(event):
|
||||
"""
|
||||
Adds an event instance to the scheduled event list. Call this any time you
|
||||
|
|
@ -19,21 +33,40 @@ def add_event(event):
|
|||
|
||||
Args:
|
||||
* event: (IntervalEvent) The event to add to the scheduler.
|
||||
"""
|
||||
Returns:
|
||||
* pid : (int) The process ID assigned to this event, for future reference.
|
||||
|
||||
#don't add multiple instances of the same event, instead replace
|
||||
if event in schedule:
|
||||
schedule[schedule.index(event)] = event
|
||||
return
|
||||
"""
|
||||
# Make sure not to add multiple instances of the same event.
|
||||
matches = [i for i, stored_event in enumerate(SCHEDULE) if event == stored_event]
|
||||
if matches:
|
||||
# Before replacing an event, stop its old incarnation.
|
||||
del_event(matches[0])
|
||||
SCHEDULE[matches[0]] = event
|
||||
else:
|
||||
schedule.append(event)
|
||||
# Add a new event with a fresh pid.
|
||||
event.pid = next_free_pid()
|
||||
SCHEDULE.append(event)
|
||||
event.start_event_loop()
|
||||
return event.pid
|
||||
|
||||
def del_event(event):
|
||||
def get_event(pid):
|
||||
"""
|
||||
Remove an event from scheduler.
|
||||
Return an event with the given pid, if it exists,
|
||||
otherwise return None.
|
||||
"""
|
||||
if event in schedule:
|
||||
i = schedule.index(event)
|
||||
schedule[i].stop_event_loop()
|
||||
del schedule[i]
|
||||
pid = int(pid)
|
||||
imatches = [i for i, stored_event in enumerate(SCHEDULE) if stored_event.pid == pid]
|
||||
if imatches:
|
||||
return SCHEDULE[imatches[0]]
|
||||
|
||||
def del_event(pid):
|
||||
"""
|
||||
Remove an event from scheduler. There should never be more than one
|
||||
event with a certain pid, this cleans up in case there are any multiples.
|
||||
"""
|
||||
pid = int(pid)
|
||||
imatches = [i for i, stored_event in enumerate(SCHEDULE) if stored_event.pid == pid]
|
||||
for imatch in imatches:
|
||||
SCHEDULE[imatch].stop_event_loop()
|
||||
del SCHEDULE[imatch]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue