Adjust some function names in the script parents to be at_ instead of a_. Also re-designed the scheduling system to be a lot more pythonic and easy to use. Utilizes classes to represent events. Much easier to plug in events from within the game directory now as well.

This commit is contained in:
Greg Taylor 2009-04-06 16:19:07 +00:00
parent b3c386a2c3
commit 5a465746c5
8 changed files with 159 additions and 145 deletions

View file

@ -136,10 +136,10 @@ def cmd_look(command):
target_obj = source_object.get_location()
# SCRIPT: Get the item's appearance from the scriptlink.
source_object.emit_to(target_obj.scriptlink.return_appearance(source_object))
source_object.emit_to(target_obj.scriptlink.return_appearance(pobject=source_object))
# SCRIPT: Call the object's script's a_desc() method.
target_obj.scriptlink.a_desc(source_object)
target_obj.scriptlink.at_desc(pobject=source_object)
GLOBAL_CMD_TABLE.add_command("look", cmd_look)
def cmd_get(command):
@ -179,7 +179,7 @@ def cmd_get(command):
exclude=source_object)
# SCRIPT: Call the object's script's a_get() method.
target_obj.scriptlink.a_get(source_object)
target_obj.scriptlink.at_get(source_object)
GLOBAL_CMD_TABLE.add_command("get", cmd_get)
def cmd_drop(command):
@ -211,7 +211,7 @@ def cmd_drop(command):
exclude=source_object)
# SCRIPT: Call the object's script's a_drop() method.
target_obj.scriptlink.a_drop(source_object)
target_obj.scriptlink.at_drop(source_object)
GLOBAL_CMD_TABLE.add_command("drop", cmd_drop),
def cmd_examine(command):

View file

@ -110,9 +110,9 @@ def cmd_ps(command):
source_object.emit_to("-- Interval Events --")
for event in scheduler.schedule:
source_object.emit_to(" [%d/%d] %s" % (
scheduler.get_event_nextfire(event),
scheduler.get_event_interval(event),
scheduler.get_event_description(event)))
event.get_nextfire(),
event.interval,
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")),

View file

@ -741,6 +741,10 @@ def cmd_destroy(command):
source_object.emit_to("That object is already destroyed.")
return
# Run any scripted things that happen before destruction.
target_obj.scriptlink.at_pre_destroy(pobject=source_object)
# Notify destroyer and do the deed.
source_object.emit_to("You destroy %s." % target_obj.get_name())
target_obj.destroy()
GLOBAL_CMD_TABLE.add_command("@destroy", cmd_destroy,

View file

@ -1,11 +1,89 @@
"""
Holds the global events scheduled in scheduler.py.
Events are sub-classed from IntervalEvent (which is not to be used directly).
Create your sub-class, call src.scheduler.add_event(YourEventClass()) to add
it to the global scheduler.
"""
import time
from twisted.internet import task
import session_mgr
from src import scheduler
"""
Holds the events scheduled in scheduler.py.
"""
class IntervalEvent(object):
"""
Represents an event that is triggered periodically. Sub-class this and
fill in the stub function.
"""
# This is what shows up on @ps in-game.
name = None
# An interval (in seconds) for execution.
interval = None
# A timestamp (int) for the last time the event was fired.
time_last_executed = None
# A reference to the task.LoopingCall object.
looped_task = None
def __unicode__(self):
"""
String representation of the event.
"""
return self.name
def start_event_loop(self):
"""
Called to start up the event loop when the event is added to the
scheduler.
"""
# Set the call-back function for the task to trigger_event, but pass
# a reference to the event function.
self.looped_task = task.LoopingCall(self.fire_event)
# Start the task up with the specified interval.
self.looped_task.start(self.interval, now=False)
def event_function(self):
"""
### Over-ride this in your sub-class. ###
"""
pass
def get_nextfire(self):
"""
Returns a value in seconds when the event is going to fire off next.
"""
return (self.time_last_executed + self.interval) - time.time()
def set_lastfired(self):
"""
Sets the timestamp (int) that the event was last fired.
"""
self.time_last_executed = time.time()
def fire_event(self):
"""
Set the last ran stamp and fire off the event.
"""
self.set_lastfired()
self.event_function()
def evt_check_sessions():
class IEvt_Check_Sessions(IntervalEvent):
"""
Event: Check all of the connected sessions.
"""
session_mgr.check_all_sessions()
name = 'IEvt_Check_Sessions'
interval = 60
description = "Session consistency checks."
def event_function(self):
"""
This is the function that is fired every self.interval seconds.
"""
session_mgr.check_all_sessions()
def add_global_events():
"""
When the server is started up, this is triggered to add all of the
events in this file to the scheduler.
"""
# Create an instance and add it to the scheduler.
scheduler.add_event(IEvt_Check_Sessions())

View file

@ -1,112 +1,28 @@
import time
from twisted.internet import task
from src import events
"""
This file contains the event scheduler system.
ADDING AN EVENT:
* Create an event function to call.
* Add an entry to the 'schedule' dictionary here.
* Create an event sub-class in events.py.
* Add it to the add_global_events() function at the end of the module.
* Profit.
"""
# Dictionary of events with a list in the form of:
# [<function>, <interval>, <lastrantime>, <taskobject>, <description>]
schedule = {
'evt_check_sessions': [events.evt_check_sessions, # Function
60, # Interval (seconds)
time.time(), # Last time executed (now)
None, # Task object
"Session consistency checks."] # Description
}
# List of IntervalEvent sub-classed objects.
schedule = []
def start_events():
"""
Start the event system, which is built on Twisted's framework.
"""
for event in schedule:
event_func = get_event_function(event)
if callable(event_func):
# Set the call-back function for the task to trigger_event, but pass
# a reference to the event function.
event_task = task.LoopingCall(trigger_event, event_func, event)
# Start the task up with the specified interval.
event_task.start(get_event_interval(event), now=False)
# Set a reference to the event's task object in the dictionary so we
# can re-schedule, start, and stop events from elsewhere.
set_event_taskobj(event, event_task)
def get_event(event_name):
event.start_event_loop()
def add_event(event):
"""
Return the relevant entry in the schedule dictionary for the named event.
event_name: (string) The key of the event in the schedule dictionary.
Adds an event instance to the scheduled event list.
Args:
* event: (IntervalEvent) The event to add to the scheduler.
"""
return schedule.get(event_name, None)
def get_event_function(event_name):
"""
Return a reference to the event's function.
event_name: (string) The key of the event in the schedule dictionary.
"""
return get_event(event_name)[0]
def get_event_interval(event_name):
"""
Return the event's execution interval.
event_name: (string) The key of the event in the schedule dictionary.
"""
return get_event(event_name)[1]
def get_event_nextfire(event_name):
"""
Returns a value in seconds when the event is going to fire off next.
event_name: (string) The key of the event in the schedule dictionary.
"""
return (get_event(event_name)[2]+get_event_interval(event_name))-time.time()
def get_event_taskobj(event_name):
"""
Returns an event's task object.
event_name: (string) The key of the event in the schedule dictionary.
"""
return get_event(event_name)[3]
def get_event_description(event_name):
"""
Returns an event's description.
event_name: (string) The key of the event in the schedule dictionary.
"""
return get_event(event_name)[4]
def set_event_taskobj(event_name, taskobj):
"""
Sets an event's task object.
event_name: (string) The key of the event in the schedule dictionary.
"""
get_event(event_name)[3] = taskobj
def set_event_lastfired(event_name):
"""
Sets an event's last fired time.
event_name: (string) The key of the event in the schedule dictionary.
"""
get_event(event_name)[2] = time.time()
def trigger_event(event_func, event_name):
"""
Update the last ran time and fire off the event.
event_func: (func_reference) Reference to the event function to fire.
eventname: (string) The name of the event (as per schedule dict).
"""
event_func()
set_event_lastfired(event_name)
schedule.append(event)
event.start_event_loop()

View file

@ -10,15 +10,15 @@ SCRIPT_DEFAULT_OBJECT variable in settings.py to point to the new class.
from src import ansi
class EvenniaBasicObject(object):
def __init__(self, source_obj, *args, **kwargs):
def __init__(self, scripted_obj, *args, **kwargs):
"""
Get our ducks in a row.
source_obj: (Object) A reference to the object being scripted (the child).
scripted_obj: (Object) A reference to the object being scripted (the child).
"""
self.source_obj = source_obj
self.scripted_obj = scripted_obj
def a_desc(self, pobject):
def at_desc(self, pobject=None):
"""
Perform this action when someone uses the LOOK command on the object.
@ -26,10 +26,43 @@ class EvenniaBasicObject(object):
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s looked at %s." % (pobject, self.source_obj)
#print "SCRIPT TEST: %s looked at %s." % (pobject, self.scripted_obj)
pass
def at_pre_destroy(self, pobject=None):
"""
Performed right before an object is destroyed.
values:
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s looked at %s." % (pobject, self.scripted_obj)
pass
def return_appearance(self, pobject):
def at_get(self, pobject):
"""
Perform this action when someone uses the GET command on the object.
values:
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s got %s." % (pobject, self.scripted_obj)
pass
def at_drop(self, pobject):
"""
Perform this action when someone uses the DROP command on the object.
values:
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s dropped %s." % (pobject, self.scripted_obj)
pass
def return_appearance(self, pobject=None):
"""
Returns a string representation of an object's appearance when LOOKed at.
@ -37,9 +70,12 @@ class EvenniaBasicObject(object):
* pobject: (Object) The object requesting the action.
"""
# This is the object being looked at.
target_obj = self.source_obj
# See if the envoker sees dbref numbers.
show_dbrefs = pobject.sees_dbrefs()
target_obj = self.scripted_obj
# See if the envoker sees dbref numbers.
if pobject:
show_dbrefs = pobject.sees_dbrefs()
else:
show_dbrefs = False
description = target_obj.get_description()
if description is not None:
@ -52,13 +88,14 @@ class EvenniaBasicObject(object):
target_obj.get_name(show_dbref=show_dbrefs),
)
# Storage for the different object types.
con_players = []
con_things = []
con_exits = []
for obj in target_obj.get_contents():
if obj.is_player():
if obj != pobject and obj.is_connected_plr():
if (obj != pobject and obj.is_connected_plr()) or pobject == None:
con_players.append(obj)
elif obj.is_exit():
con_exits.append(obj)
@ -80,28 +117,6 @@ class EvenniaBasicObject(object):
return retval
def a_get(self, pobject):
"""
Perform this action when someone uses the GET command on the object.
values:
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s got %s." % (pobject, self.source_obj)
pass
def a_drop(self, pobject):
"""
Perform this action when someone uses the GET command on the object.
values:
* pobject: (Object) The object requesting the action.
"""
# Un-comment the line below for an example
#print "SCRIPT TEST: %s dropped %s." % (pobject, self.source_obj)
pass
def default_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether

View file

@ -23,7 +23,7 @@ class EvenniaBasicPlayer(object):
'logged in', in a sense that they're not ready to send logged in
commands or receive communication.
"""
pobject = self.source_obj
pobject = self.scripted_obj
# Load the player's channels from their JSON __CHANLIST attribute.
comsys.load_object_channels(pobject)
@ -36,7 +36,7 @@ class EvenniaBasicPlayer(object):
The user is now logged in. This is what happens right after the moment
they are 'connected'.
"""
pobject = self.source_obj
pobject = self.scripted_obj
pobject.emit_to("You are now logged in as %s." % (pobject.name,))
pobject.get_location().emit_to_contents("%s has connected." %

View file

@ -7,7 +7,7 @@ from django.db import connection
from django.conf import settings
from src.config.models import ConfigValue
from src.session import SessionProtocol
from src import scheduler
from src import events
from src import logger
from src import session_mgr
from src import alias_mgr
@ -50,7 +50,8 @@ class EvenniaService(service.Service):
alias_mgr.load_cmd_aliases()
print '-'*50
scheduler.start_events()
# Fire up the event scheduler.
events.add_global_events()
"""
BEGIN SERVER STARTUP METHODS