Updated gametime module to work on-the-fly, based on patches and discussion with user Khandrish. Also made cleanups to @scripts command and some small bug fixes.
This commit is contained in:
parent
48bfc7e54a
commit
ea7e43c746
5 changed files with 87 additions and 141 deletions
|
|
@ -215,7 +215,7 @@ def format_script_list(scripts):
|
||||||
if not scripts:
|
if not scripts:
|
||||||
return "<No scripts>"
|
return "<No scripts>"
|
||||||
|
|
||||||
table = prettytable.PrettyTable(["{wid",
|
table = prettytable.PrettyTable(["{wdbref",
|
||||||
"{wobj",
|
"{wobj",
|
||||||
"{wkey",
|
"{wkey",
|
||||||
"{wintval",
|
"{wintval",
|
||||||
|
|
@ -245,7 +245,7 @@ class CmdScripts(MuxCommand):
|
||||||
Operate and list global scripts, list all scrips.
|
Operate and list global scripts, list all scrips.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@scripts[/switches] [<obj or scriptid or script.path>]
|
@scripts[/switches] [#dbref, key, script.path or <obj>]
|
||||||
|
|
||||||
Switches:
|
Switches:
|
||||||
start - start a script (must supply a script path)
|
start - start a script (must supply a script path)
|
||||||
|
|
@ -256,7 +256,7 @@ class CmdScripts(MuxCommand):
|
||||||
If no switches are given, this command just views all active
|
If no switches are given, this command just views all active
|
||||||
scripts. The argument can be either an object, at which point it
|
scripts. The argument can be either an object, at which point it
|
||||||
will be searched for all scripts defined on it, or an script name
|
will be searched for all scripts defined on it, or an script name
|
||||||
or dbref. For using the /stop switch, a unique script dbref is
|
or #dbref. For using the /stop switch, a unique script #dbref is
|
||||||
required since whole classes of scripts often have the same name.
|
required since whole classes of scripts often have the same name.
|
||||||
|
|
||||||
Use @script for managing commands on objects.
|
Use @script for managing commands on objects.
|
||||||
|
|
@ -287,7 +287,7 @@ class CmdScripts(MuxCommand):
|
||||||
scripts = ScriptDB.objects.get_all_scripts(key=args)
|
scripts = ScriptDB.objects.get_all_scripts(key=args)
|
||||||
if not scripts:
|
if not scripts:
|
||||||
# try to find an object instead.
|
# try to find an object instead.
|
||||||
objects = ObjectDB.objects.object_search(args, caller=caller)
|
objects = ObjectDB.objects.object_search(args)
|
||||||
if objects:
|
if objects:
|
||||||
scripts = []
|
scripts = []
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
|
|
@ -608,9 +608,9 @@ class CmdTime(MuxCommand):
|
||||||
"Show server time data in a table."
|
"Show server time data in a table."
|
||||||
table = prettytable.PrettyTable(["{wserver time statistic","{wtime"])
|
table = prettytable.PrettyTable(["{wserver time statistic","{wtime"])
|
||||||
table.align = 'l'
|
table.align = 'l'
|
||||||
table.add_row(["Current server uptime", utils.time_format(time.time() - SESSIONS.server.start_time, 3)])
|
table.add_row(["Current server uptime", utils.time_format(gametime.uptime(), 3)])
|
||||||
table.add_row(["Total server running time", utils.time_format(gametime.runtime(format=False), 2)])
|
table.add_row(["Total server running time", utils.time_format(gametime.runtime(), 2)])
|
||||||
table.add_row(["Total in-game time (realtime x %g" % (gametime.TIMEFACTOR), utils.time_format(gametime.gametime(format=False), 2)])
|
table.add_row(["Total in-game time (realtime x %g" % (gametime.TIMEFACTOR), utils.time_format(gametime.gametime(), 2)])
|
||||||
table.add_row(["Server time stamp", datetime.datetime.now()])
|
table.add_row(["Server time stamp", datetime.datetime.now()])
|
||||||
self.caller.msg(str(table))
|
self.caller.msg(str(table))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,8 @@ class ScriptManager(TypedObjectManager):
|
||||||
if dbref or dbref == 0:
|
if dbref or dbref == 0:
|
||||||
script = self.dbref_search(dbref)
|
script = self.dbref_search(dbref)
|
||||||
if not script:
|
if not script:
|
||||||
scripts = self.filter(db_key=key)
|
script = self.filter(db_key=key)
|
||||||
return scripts
|
return script
|
||||||
return self.all()
|
return self.all()
|
||||||
|
|
||||||
def delete_script(self, dbref):
|
def delete_script(self, dbref):
|
||||||
|
|
|
||||||
|
|
@ -336,6 +336,10 @@ class Evennia(object):
|
||||||
if SERVER_STARTSTOP_MODULE:
|
if SERVER_STARTSTOP_MODULE:
|
||||||
SERVER_STARTSTOP_MODULE.at_server_cold_stop()
|
SERVER_STARTSTOP_MODULE.at_server_cold_stop()
|
||||||
|
|
||||||
|
# stopping time
|
||||||
|
from src.utils import gametime
|
||||||
|
gametime.save()
|
||||||
|
|
||||||
if SERVER_STARTSTOP_MODULE:
|
if SERVER_STARTSTOP_MODULE:
|
||||||
SERVER_STARTSTOP_MODULE.at_server_stop()
|
SERVER_STARTSTOP_MODULE.at_server_stop()
|
||||||
# if _reactor_stopping is true, reactor does not need to
|
# if _reactor_stopping is true, reactor does not need to
|
||||||
|
|
|
||||||
|
|
@ -293,14 +293,12 @@ BASE_BATCHPROCESS_PATHS = ['game.gamesrc.world', 'contrib']
|
||||||
|
|
||||||
# You don't actually have to use this, but it affects the routines in
|
# You don't actually have to use this, but it affects the routines in
|
||||||
# src.utils.gametime.py and allows for a convenient measure to
|
# src.utils.gametime.py and allows for a convenient measure to
|
||||||
# determine the current in-game time. You can of course read "week",
|
# determine the current in-game time. You can of course interpret
|
||||||
# "month" etc as your own in-game time units as desired.
|
# "week", "month" etc as your own in-game time units as desired.
|
||||||
|
|
||||||
#The time factor dictates if the game world runs faster (timefactor>1)
|
#The time factor dictates if the game world runs faster (timefactor>1)
|
||||||
# or slower (timefactor<1) than the real world.
|
# or slower (timefactor<1) than the real world.
|
||||||
TIME_FACTOR = 2.0
|
TIME_FACTOR = 2.0
|
||||||
# The tick is the smallest unit of time in the game. Smallest value is 1s.
|
|
||||||
TIME_TICK = 1.0
|
|
||||||
# These measures might or might not make sense to your game world.
|
# These measures might or might not make sense to your game world.
|
||||||
TIME_SEC_PER_MIN = 60
|
TIME_SEC_PER_MIN = 60
|
||||||
TIME_MIN_PER_HOUR = 60
|
TIME_MIN_PER_HOUR = 60
|
||||||
|
|
@ -308,8 +306,6 @@ TIME_HOUR_PER_DAY = 24
|
||||||
TIME_DAY_PER_WEEK = 7
|
TIME_DAY_PER_WEEK = 7
|
||||||
TIME_WEEK_PER_MONTH = 4
|
TIME_WEEK_PER_MONTH = 4
|
||||||
TIME_MONTH_PER_YEAR = 12
|
TIME_MONTH_PER_YEAR = 12
|
||||||
# How often the game time is updated
|
|
||||||
TIME_UPDATE_INTERVAL = 60
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Default Player setup and access
|
# Default Player setup and access
|
||||||
|
|
|
||||||
|
|
@ -6,37 +6,28 @@ in-mud time and real-world time as well allows to get the
|
||||||
total runtime of the server and the current uptime.
|
total runtime of the server and the current uptime.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from time import time
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.scripts.scripts import Script
|
from src.scripts.scripts import Script
|
||||||
from src.scripts.models import ScriptDB
|
|
||||||
from src.utils.create import create_script
|
from src.utils.create import create_script
|
||||||
from src.utils import logger
|
|
||||||
|
|
||||||
# name of script that keeps track of the time
|
GAMETIME_SCRIPT_NAME = "sys_game_time"
|
||||||
|
|
||||||
GAME_TIME_SCRIPT = "sys_game_time"
|
|
||||||
|
|
||||||
# Speed-up factor of the in-game time compared
|
# Speed-up factor of the in-game time compared
|
||||||
# to real time.
|
# to real time.
|
||||||
|
|
||||||
TIMEFACTOR = settings.TIME_FACTOR
|
TIMEFACTOR = settings.TIME_FACTOR
|
||||||
|
|
||||||
# How often this script runs and updates the game time
|
# Common real-life time measure, in seconds.
|
||||||
|
# You should not change this.
|
||||||
|
|
||||||
UPDATE_INTERVAL = settings.TIME_UPDATE_INTERVAL
|
|
||||||
|
|
||||||
# Common real-life time measures, in seconds.
|
|
||||||
# You should not change these.
|
|
||||||
|
|
||||||
REAL_TICK = max(1.0, settings.TIME_TICK) # Smallest time unit (min 1s)
|
|
||||||
REAL_MIN = 60.0 # seconds per minute in real world
|
REAL_MIN = 60.0 # seconds per minute in real world
|
||||||
|
|
||||||
# Game-time units, in real-life seconds. These are supplied as
|
# Game-time units, in real-life seconds. These are supplied as
|
||||||
# a convenient measure for determining the current in-game time,
|
# a convenient measure for determining the current in-game time,
|
||||||
# e.g. when defining events. The words month, week and year can
|
# e.g. when defining in-game events. The words month, week and year can
|
||||||
# of course mean whatever units of time are used in the game.
|
# be used to mean whatever units of time are used in the game.
|
||||||
|
|
||||||
TICK = REAL_TICK * TIMEFACTOR
|
|
||||||
MIN = settings.TIME_SEC_PER_MIN
|
MIN = settings.TIME_SEC_PER_MIN
|
||||||
HOUR = MIN * settings.TIME_MIN_PER_HOUR
|
HOUR = MIN * settings.TIME_MIN_PER_HOUR
|
||||||
DAY = HOUR * settings.TIME_HOUR_PER_DAY
|
DAY = HOUR * settings.TIME_HOUR_PER_DAY
|
||||||
|
|
@ -44,22 +35,25 @@ WEEK = DAY * settings.TIME_DAY_PER_WEEK
|
||||||
MONTH = WEEK * settings.TIME_WEEK_PER_MONTH
|
MONTH = WEEK * settings.TIME_WEEK_PER_MONTH
|
||||||
YEAR = MONTH * settings.TIME_MONTH_PER_YEAR
|
YEAR = MONTH * settings.TIME_MONTH_PER_YEAR
|
||||||
|
|
||||||
|
# Cached time stamps
|
||||||
|
SERVER_STARTTIME = time()
|
||||||
|
SERVER_RUNTIME = 0.0
|
||||||
|
|
||||||
|
|
||||||
class GameTime(Script):
|
class GameTime(Script):
|
||||||
"""
|
"""
|
||||||
This sets up an script that keeps track of the
|
This script repeatedly saves server times so
|
||||||
in-game time and some other time units.
|
it can be retrieved after server downtime.
|
||||||
"""
|
"""
|
||||||
def at_script_creation(self):
|
def at_script_creation(self):
|
||||||
"""
|
"""
|
||||||
Setup the script
|
Setup the script
|
||||||
"""
|
"""
|
||||||
self.key = "sys_game_time"
|
self.key = GAMETIME_SCRIPT_NAME
|
||||||
self.desc = "Keeps track of the game time"
|
self.desc = "Keeps track of the game time"
|
||||||
self.interval = UPDATE_INTERVAL
|
self.interval = 60
|
||||||
self.persistent = True
|
self.persistent = True
|
||||||
self.start_delay = True
|
self.start_delay = True
|
||||||
self.attributes.add("game_time", 0.0) # IC time
|
|
||||||
self.attributes.add("run_time", 0.0) # OOC time
|
self.attributes.add("run_time", 0.0) # OOC time
|
||||||
self.attributes.add("up_time", 0.0) # OOC time
|
self.attributes.add("up_time", 0.0) # OOC time
|
||||||
|
|
||||||
|
|
@ -67,130 +61,78 @@ class GameTime(Script):
|
||||||
"""
|
"""
|
||||||
Called every minute to update the timers.
|
Called every minute to update the timers.
|
||||||
"""
|
"""
|
||||||
# We store values as floats to avoid drift over time
|
self.attributes.add("run_time", runtime())
|
||||||
game_time = float(self.attributes.get("game_time"))
|
self.attributes.add("up_time", uptime())
|
||||||
run_time = float(self.attributes.get("run_time"))
|
|
||||||
up_time = float(self.attributes.get("up_time"))
|
|
||||||
self.attributes.add("game_time", game_time + UPDATE_INTERVAL * TIMEFACTOR)
|
|
||||||
self.attributes.add("run_time", run_time + UPDATE_INTERVAL)
|
|
||||||
self.attributes.add("up_time", up_time + UPDATE_INTERVAL)
|
|
||||||
|
|
||||||
def at_start(self):
|
def at_start(self):
|
||||||
"""
|
"""
|
||||||
This is called once every server restart.
|
This is called once every server restart.
|
||||||
We reset the up time.
|
We reset the up time and load the relevant
|
||||||
|
times.
|
||||||
"""
|
"""
|
||||||
self.attributes.add("up_time", 0.0)
|
global SERVER_RUNTIME
|
||||||
self.interval = UPDATE_INTERVAL
|
SERVER_RUNTIME = self.attributes.get("run_time")
|
||||||
|
|
||||||
|
def save():
|
||||||
|
"Force save of time. This is called by server when shutting down/reloading."
|
||||||
|
from src.scripts.models import ScriptDB
|
||||||
|
try:
|
||||||
|
script = ScriptDB.objects.get(db_key=GAMETIME_SCRIPT_NAME)
|
||||||
|
script.at_repeat()
|
||||||
|
except Exception:
|
||||||
|
from src.utils import logger
|
||||||
|
logger.log_trace()
|
||||||
|
|
||||||
# Access routines
|
def _format(seconds, *divisors) :
|
||||||
|
|
||||||
def format(seconds, divisors, modify_seconds=True):
|
|
||||||
"""
|
"""
|
||||||
Takes a list of divisors by which to divide the seconds, also passed
|
Helper function. Creates a tuple of even dividends given
|
||||||
in, by. The result of each division will be returned in the order it
|
a range of divisors.
|
||||||
was performed, starting from the beginning of the divisors list.
|
|
||||||
|
|
||||||
The default behavior is to, after first dividing the number of seconds
|
Inputs
|
||||||
by the divisor, mod the seconds by the divisor and, at the very end,
|
seconds - number of seconds to format
|
||||||
return the left over seconds by appending to the list. When passed a
|
*divisors - a number of integer dividends. The number of seconds will be
|
||||||
list of divisors such as [31536000, 2628000, 604800, 86400, 3600, 60]
|
integer-divided by the first number in this sequence, the remainder
|
||||||
this results in the years, months, weeks, days, hours, minutes, and
|
will be divided with the second and so on.
|
||||||
seconds that have passed, according to ths seconds value passed in,
|
Output:
|
||||||
being returned via tuple.
|
A tuple of length len(*args)+1, with the last element being the last remaining
|
||||||
|
seconds not evenly divided by the supplied dividends.
|
||||||
|
|
||||||
If modify_seconds=False then the order the divisors are passed in
|
|
||||||
have no meaning other than placement in the results set and there is
|
|
||||||
no remainder to append to the end of the results.
|
|
||||||
"""
|
"""
|
||||||
results = []
|
results = []
|
||||||
|
seconds = int(seconds)
|
||||||
for divisor in divisors:
|
for divisor in divisors:
|
||||||
results.append(seconds / divisor)
|
results.append(seconds / divisor)
|
||||||
if modify_seconds:
|
seconds %= divisor
|
||||||
seconds = seconds % divisor
|
results.append(seconds)
|
||||||
if modify_seconds:
|
|
||||||
results.append(seconds)
|
|
||||||
return tuple(results)
|
return tuple(results)
|
||||||
|
|
||||||
|
|
||||||
def gametime_format(seconds):
|
# Access functions
|
||||||
"""
|
|
||||||
Converts the count in seconds into an integer tuple of the form
|
|
||||||
(years, months, weeks, days, hours, minutes, seconds) where
|
|
||||||
several of the entries may be 0.
|
|
||||||
|
|
||||||
We want to keep a separate version of this (rather than just
|
|
||||||
rescale the real time once and use the normal realtime_format
|
|
||||||
below) since the admin might for example decide to change how many
|
|
||||||
hours a 'day' is in their game etc.
|
|
||||||
"""
|
|
||||||
return format(seconds, [YEAR, MONTH, WEEK, DAY, HOUR, MIN])
|
|
||||||
|
|
||||||
|
|
||||||
def realtime_format(seconds):
|
|
||||||
"""
|
|
||||||
As gametime format, but with real time units
|
|
||||||
"""
|
|
||||||
return format(seconds, [31536000, 2628000, 604800, 86400, 3600, 60])
|
|
||||||
|
|
||||||
|
|
||||||
def gametime(format=False):
|
|
||||||
"""
|
|
||||||
Find the current in-game time (in seconds) since the start of the mud.
|
|
||||||
The value returned from this function can be used to track the 'true'
|
|
||||||
in-game time since only the time the game has actually been active will
|
|
||||||
be adding up (ignoring downtimes).
|
|
||||||
|
|
||||||
format - instead of returning result in seconds, format to (game-) time
|
|
||||||
units.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
script = ScriptDB.objects.get_all_scripts(GAME_TIME_SCRIPT)[0]
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
logger.log_trace("GameTime script not found.")
|
|
||||||
return
|
|
||||||
# we return this as an integer (second-precision is good enough)
|
|
||||||
game_time = int(script.attributes.get("game_time"))
|
|
||||||
if format:
|
|
||||||
return gametime_format(game_time)
|
|
||||||
return game_time
|
|
||||||
|
|
||||||
|
|
||||||
def runtime(format=False):
|
def runtime(format=False):
|
||||||
"""
|
"Get the total runtime of the server since first start (minus downtimes)"
|
||||||
Get the total actual time the server has been running (minus downtimes)
|
runtime = SERVER_RUNTIME + (time() - SERVER_STARTTIME)
|
||||||
"""
|
|
||||||
try:
|
|
||||||
script = ScriptDB.objects.get_all_scripts(GAME_TIME_SCRIPT)[0]
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
logger.log_trace("GameTime script not found.")
|
|
||||||
return
|
|
||||||
# we return this as an integer (second-precision is good enough)
|
|
||||||
run_time = int(script.attributes.get("run_time"))
|
|
||||||
if format:
|
if format:
|
||||||
return realtime_format(run_time)
|
return _format(runtime, 31536000, 2628000, 604800, 86400, 3600, 60)
|
||||||
return run_time
|
return runtime
|
||||||
|
|
||||||
|
|
||||||
def uptime(format=False):
|
def uptime(format=False):
|
||||||
"""
|
"Get the current uptime of the server since last reload"
|
||||||
Get the actual time the server has been running since last downtime.
|
uptime = time() - SERVER_STARTTIME
|
||||||
"""
|
|
||||||
try:
|
|
||||||
script = ScriptDB.objects.get_all_scripts(GAME_TIME_SCRIPT)[0]
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
logger.log_trace("GameTime script not found.")
|
|
||||||
return
|
|
||||||
# we return this as an integer (second-precision is good enough)
|
|
||||||
up_time = int(script.attributes.get("up_time"))
|
|
||||||
if format:
|
if format:
|
||||||
return realtime_format(up_time)
|
return _format(uptime, 31536000, 2628000, 604800, 86400, 3600, 60)
|
||||||
return up_time
|
return uptime
|
||||||
|
|
||||||
|
def gametime(format=False):
|
||||||
|
"Get the total gametime of the server since first start (minus downtimes)"
|
||||||
|
gametime = runtime() * TIMEFACTOR
|
||||||
|
if format:
|
||||||
|
return _format(gametime, YEAR, MONTH, WEEK, DAY, HOUR, MIN)
|
||||||
|
return gametime
|
||||||
|
|
||||||
|
|
||||||
def gametime_to_realtime(secs=0, mins=0, hrs=0, days=0,
|
def gametime_to_realtime(secs=0, mins=0, hrs=0, days=0,
|
||||||
weeks=0, months=0, yrs=0):
|
weeks=0, months=0, yrs=0, format=False):
|
||||||
"""
|
"""
|
||||||
This method helps to figure out the real-world time it will take until an
|
This method helps to figure out the real-world time it will take until an
|
||||||
in-game time has passed. E.g. if an event should take place a month later
|
in-game time has passed. E.g. if an event should take place a month later
|
||||||
|
|
@ -201,15 +143,17 @@ def gametime_to_realtime(secs=0, mins=0, hrs=0, days=0,
|
||||||
gametime_to_realtime(days=2) -> number of seconds in real life from
|
gametime_to_realtime(days=2) -> number of seconds in real life from
|
||||||
now after which 2 in-game days will have passed.
|
now after which 2 in-game days will have passed.
|
||||||
"""
|
"""
|
||||||
real_time = (secs + mins * MIN + hrs * HOUR + days * DAY + weeks * WEEK + \
|
realtime = (secs + mins * MIN + hrs * HOUR + days * DAY + weeks * WEEK + \
|
||||||
months * MONTH + yrs * YEAR) / TIMEFACTOR
|
months * MONTH + yrs * YEAR) / TIMEFACTOR
|
||||||
return real_time
|
if format:
|
||||||
|
return _format(realtime, 31536000, 2628000, 604800, 86400, 3600, 60)
|
||||||
|
return realtime
|
||||||
|
|
||||||
|
|
||||||
def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0,
|
def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0,
|
||||||
weeks=0, months=0, yrs=0):
|
weeks=0, months=0, yrs=0, format=False):
|
||||||
"""
|
"""
|
||||||
This method calculates how large an in-game time a real-world time
|
This method calculates how much in-game time a real-world time
|
||||||
interval would correspond to. This is usually a lot less interesting
|
interval would correspond to. This is usually a lot less interesting
|
||||||
than the other way around.
|
than the other way around.
|
||||||
|
|
||||||
|
|
@ -217,9 +161,11 @@ def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0,
|
||||||
realtime_to_gametime(days=2) -> number of game-world seconds
|
realtime_to_gametime(days=2) -> number of game-world seconds
|
||||||
corresponding to 2 real days.
|
corresponding to 2 real days.
|
||||||
"""
|
"""
|
||||||
game_time = TIMEFACTOR * (secs + mins * 60 + hrs * 3600 + days * 86400 +
|
gametime = TIMEFACTOR * (secs + mins * 60 + hrs * 3600 + days * 86400 +
|
||||||
weeks * 604800 + months * 2419200 + yrs * 29030400)
|
weeks * 604800 + months * 2628000 + yrs * 31536000)
|
||||||
return game_time
|
if format:
|
||||||
|
return _format(gametime, YEAR, MONTH, WEEK, DAY, HOUR, MIN)
|
||||||
|
return gametime
|
||||||
|
|
||||||
|
|
||||||
# Time administration routines
|
# Time administration routines
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue