Fixed a repeat error in Scripts (resolves #890). Added separation between calling script.pause() deliberately and it being called automatically by the reset/reload, in order to preserve manual pauses across server reloads (resolves #891).

This commit is contained in:
Griatch 2015-12-17 00:12:07 +01:00
parent f56500df9a
commit 161383f9ae
3 changed files with 36 additions and 8 deletions

View file

@ -96,7 +96,9 @@ class ExtendedLoopingCall(LoopingCall):
""" """
self.callcount += 1 self.callcount += 1
if self.start_delay:
self.start_delay = None self.start_delay = None
self.starttime = self.clock.seconds()
super(ExtendedLoopingCall, self).__call__() super(ExtendedLoopingCall, self).__call__()
def force_repeat(self): def force_repeat(self):
@ -130,6 +132,7 @@ class ExtendedLoopingCall(LoopingCall):
if self.running: if self.running:
total_runtime = self.clock.seconds() - self.starttime total_runtime = self.clock.seconds() - self.starttime
interval = self.start_delay or self.interval interval = self.start_delay or self.interval
print "next_call_time:", interval, total_runtime, self.interval, interval - (total_runtime % self.interval)
return interval - (total_runtime % self.interval) return interval - (total_runtime % self.interval)
return None return None
@ -169,6 +172,10 @@ class DefaultScript(ScriptBase):
""" """
from evennia.utils.utils import calledby
print calledby(2)
print "_start_task:", self.db_interval, self.db._paused_time
self.ndb._task = ExtendedLoopingCall(self._step_task) self.ndb._task = ExtendedLoopingCall(self._step_task)
if self.db._paused_time: if self.db._paused_time:
@ -308,8 +315,12 @@ class DefaultScript(ScriptBase):
return 0 return 0
# try to restart a paused script # try to restart a paused script
if self.unpause(): try:
if self.unpause(manual_unpause=False):
return 1 return 1
except RuntimeError:
# manually paused.
return 0
# start the script from scratch # start the script from scratch
self.is_active = True self.is_active = True
@ -349,12 +360,13 @@ class DefaultScript(ScriptBase):
return 0 return 0
return 1 return 1
def pause(self): def pause(self, manual_pause=True):
""" """
This stops a running script and stores its active state. This stops a running script and stores its active state.
It WILL NOT call the `at_stop()` hook. It WILL NOT call the `at_stop()` hook.
""" """
self.db._manual_pause = manual_pause
if not self.db._paused_time: if not self.db._paused_time:
# only allow pause if not already paused # only allow pause if not already paused
task = self.ndb._task task = self.ndb._task
@ -364,10 +376,26 @@ class DefaultScript(ScriptBase):
self._stop_task() self._stop_task()
self.is_active = False self.is_active = False
def unpause(self): def unpause(self, manual_unpause=True):
""" """
Restart a paused script. This WILL call the `at_start()` hook. Restart a paused script. This WILL call the `at_start()` hook.
Args:
manual_unpause (bool, optional): This is False if unpause is
called by the server reload/reset mechanism.
Returns:
result (bool): True if unpause was triggered, False otherwise.
Raises:
RuntimeError: If trying to automatically resart this script
(usually after a reset/reload), but it was manually paused,
and so should not the auto-unpaused.
""" """
if not manual_unpause and self.db._manual_pause:
# if this script was paused manually (by a direct call of pause),
# it cannot be automatically unpaused (e.g. by a @reload)
raise RuntimeError
if self.db._paused_time: if self.db._paused_time:
# only unpause if previously paused # only unpause if previously paused
self.is_active = True self.is_active = True

View file

@ -349,7 +349,7 @@ class Evennia(object):
ServerConfig.objects.conf("server_restart_mode", "reload") ServerConfig.objects.conf("server_restart_mode", "reload")
yield [o.at_server_reload() for o in ObjectDB.get_all_cached_instances()] yield [o.at_server_reload() for o in ObjectDB.get_all_cached_instances()]
yield [p.at_server_reload() for p in PlayerDB.get_all_cached_instances()] yield [p.at_server_reload() for p in PlayerDB.get_all_cached_instances()]
yield [(s.pause(), s.at_server_reload()) for s in ScriptDB.get_all_cached_instances()] yield [(s.pause(manual_pause=False), s.at_server_reload()) for s in ScriptDB.get_all_cached_instances() if s.is_active]
yield self.sessions.all_sessions_portal_sync() yield self.sessions.all_sessions_portal_sync()
self.at_server_reload_stop() self.at_server_reload_stop()
# only save OOB state on reload, not on shutdown/reset # only save OOB state on reload, not on shutdown/reset
@ -368,7 +368,7 @@ class Evennia(object):
yield [(p.unpuppet_all(), p.at_server_shutdown()) yield [(p.unpuppet_all(), p.at_server_shutdown())
for p in PlayerDB.get_all_cached_instances()] for p in PlayerDB.get_all_cached_instances()]
yield ObjectDB.objects.clear_all_sessids() yield ObjectDB.objects.clear_all_sessids()
yield [(s.pause(), s.at_server_shutdown()) for s in ScriptDB.get_all_cached_instances()] yield [(s.pause(manual_pause=False), s.at_server_shutdown()) for s in ScriptDB.get_all_cached_instances()]
ServerConfig.objects.conf("server_restart_mode", "reset") ServerConfig.objects.conf("server_restart_mode", "reset")
self.at_server_cold_stop() self.at_server_cold_stop()

View file

@ -207,7 +207,7 @@ class ServerSession(Session):
obj.player = self.player obj.player = self.player
self.puid = obj.id self.puid = obj.id
self.puppet = obj self.puppet = obj
obj.scripts.validate() #obj.scripts.validate()
obj.locks.cache_lock_bypass(obj) obj.locks.cache_lock_bypass(obj)
def at_login(self, player): def at_login(self, player):