Add the script/functions to schedule events with a standard calendar
This commit is contained in:
parent
c18bfe7388
commit
7cd7d68a5a
1 changed files with 126 additions and 0 deletions
|
|
@ -7,7 +7,11 @@ total runtime of the server and the current uptime.
|
||||||
"""
|
"""
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import time
|
import time
|
||||||
|
from calendar import monthrange
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from evennia import DefaultScript
|
||||||
from evennia.server.models import ServerConfig
|
from evennia.server.models import ServerConfig
|
||||||
|
|
||||||
# Speed-up factor of the in-game time compared
|
# Speed-up factor of the in-game time compared
|
||||||
|
|
@ -107,6 +111,106 @@ def gametime(absolute=False):
|
||||||
gtime = epoch + (runtime() - GAME_TIME_OFFSET) * TIMEFACTOR
|
gtime = epoch + (runtime() - GAME_TIME_OFFSET) * TIMEFACTOR
|
||||||
return gtime
|
return gtime
|
||||||
|
|
||||||
|
def real_seconds_until(sec=None, min=None, hour=None, day=None,
|
||||||
|
month=None, year=None):
|
||||||
|
"""
|
||||||
|
Return the real seconds until game time.
|
||||||
|
|
||||||
|
If the game time is 5:00, TIME_FACTOR is set to 2 and you ask
|
||||||
|
the number of seconds until it's 5:10, then this function should
|
||||||
|
return 300 (5 minutes).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sec (int or None): number of absolute seconds.
|
||||||
|
min (int or None): number of absolute minutes.
|
||||||
|
hour (int or None): number of absolute hours.
|
||||||
|
day (int or None): number of absolute days.
|
||||||
|
month (int or None): number of absolute months.
|
||||||
|
year (int or None): number of absolute years.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
real_seconds_until(hour=5, min=10, sec=0)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The number of real seconds before the given game time is up.
|
||||||
|
|
||||||
|
"""
|
||||||
|
current = datetime.frmtimestamp(gametime(absolute=True))
|
||||||
|
s_sec = year if year is not None else current.second
|
||||||
|
s_min = min if min is not None else current.minute
|
||||||
|
s_hour = hour if hour is not None else current.hour
|
||||||
|
s_day = day if day is not None else current.day
|
||||||
|
s_month = month if month is not None else current.month
|
||||||
|
s_year = year if year is not None else current.year
|
||||||
|
projected = datetime(s_year, s_month, s_day, s_hour, s_min, s_sec)
|
||||||
|
|
||||||
|
if projected <= current:
|
||||||
|
# We increase one unit of time depending on parameters
|
||||||
|
days_in_month = monthrange(s_year, s_month)[1]
|
||||||
|
days_in_year = sum(monthrange(s_year, m + 1)[1] for m in range(12))
|
||||||
|
if month is not None:
|
||||||
|
projected += timedelta(days=days_in_year)
|
||||||
|
elif day is not None:
|
||||||
|
projected += timedelta(days=days_in_month)
|
||||||
|
elif hour is not None:
|
||||||
|
projected += timedelta(days=1)
|
||||||
|
elif min is not None:
|
||||||
|
projected += timedelta(seconds=3600)
|
||||||
|
else:
|
||||||
|
projected += timedelta(seconds=60)
|
||||||
|
|
||||||
|
# Get the number of gametime seconds between these two dates
|
||||||
|
print "Asked", current, projected
|
||||||
|
seconds = (projected - current).total_seconds()
|
||||||
|
print "Found", seconds
|
||||||
|
return seconds / TIMEFACTOR
|
||||||
|
|
||||||
|
def schedule(callback, repeat=False, sec=None, min=None, hour=None,
|
||||||
|
day=None, month=None, year=None):
|
||||||
|
"""
|
||||||
|
Call the callback when the game time is up.
|
||||||
|
|
||||||
|
This function will setup a script that will be called when the
|
||||||
|
time corresponds to the game time. If `repeat` is set to True,
|
||||||
|
the callback will be called again next time the game time matches
|
||||||
|
the given time. The time is given in units as keyword arguments.
|
||||||
|
For instance:
|
||||||
|
>>> schedule(func, min=5, sec=0) # Will call next hour at :05.
|
||||||
|
>>> schedule(func, hour=2, min=30, sec=0) # Will call the next day at 02:30.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (function): the callback function that will be called [1].
|
||||||
|
repeat (bool, optional): should the callback be called regularly?
|
||||||
|
sec (int or None): number of absolute seconds.
|
||||||
|
min (int or None): number of absolute minutes.
|
||||||
|
hour (int or None): number of absolute hours.
|
||||||
|
day (int or None): number of absolute days.
|
||||||
|
month (int or None): number of absolute months.
|
||||||
|
year (int or None): number of absolute years.
|
||||||
|
|
||||||
|
[1] The callback must be a top-level function, since the script will
|
||||||
|
be persistent.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The created script (Script).
|
||||||
|
|
||||||
|
"""
|
||||||
|
seconds = real_seconds_until(sec=sec, min=min, hour=hour, day=day,
|
||||||
|
month=month, year=year)
|
||||||
|
script = create_script("evennia.utils.gametime.GametimeScript",
|
||||||
|
key="GametimeScript", desc="A gametime-sensitive script",
|
||||||
|
interval=seconds, start_delay=True,
|
||||||
|
repeats=-1 if repeat else 1)
|
||||||
|
script.db.callback = callback
|
||||||
|
script.db.gametime = {
|
||||||
|
"sec": sec,
|
||||||
|
"min": min,
|
||||||
|
"hour": hour,
|
||||||
|
"day": day,
|
||||||
|
"month": month,
|
||||||
|
"year": year,
|
||||||
|
}
|
||||||
|
return script
|
||||||
|
|
||||||
def reset_gametime():
|
def reset_gametime():
|
||||||
"""
|
"""
|
||||||
|
|
@ -117,3 +221,25 @@ def reset_gametime():
|
||||||
global GAME_TIME_OFFSET
|
global GAME_TIME_OFFSET
|
||||||
GAME_TIME_OFFSET = runtime()
|
GAME_TIME_OFFSET = runtime()
|
||||||
ServerConfig.objects.conf("gametime_offset", GAME_TIME_OFFSET)
|
ServerConfig.objects.conf("gametime_offset", GAME_TIME_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
|
# Scripts dealing in gametime (use `schedule` to create it)
|
||||||
|
class GametimeScript(DefaultScript):
|
||||||
|
|
||||||
|
"""Gametime-sensitive script."""
|
||||||
|
|
||||||
|
def at_script_creation(self):
|
||||||
|
"""The script is created."""
|
||||||
|
self.key = "unknown scr"
|
||||||
|
self.interval = 100
|
||||||
|
self.start_delay = True
|
||||||
|
self.persistent = True
|
||||||
|
|
||||||
|
def at_repeat(self):
|
||||||
|
"""Call the callback and reset interval."""
|
||||||
|
callback = self.db.callback
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
|
||||||
|
seconds = real_seconds_until(**self.db.gametime)
|
||||||
|
self.restart(interval=seconds)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue