Fix at_server_reload_start not firing. Resolve #3477. Add Server-Lifecycle.md docpage
This commit is contained in:
parent
50d8ae2f54
commit
387533d1f0
15 changed files with 222 additions and 80 deletions
|
|
@ -16,13 +16,14 @@ import time
|
|||
import typing
|
||||
from random import getrandbits
|
||||
|
||||
import evennia
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate, password_validation
|
||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||
from django.utils import timezone
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
import evennia
|
||||
from evennia.accounts.manager import AccountManager
|
||||
from evennia.accounts.models import AccountDB
|
||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||
|
|
@ -30,17 +31,24 @@ from evennia.comms.models import ChannelDB
|
|||
from evennia.objects.models import ObjectDB
|
||||
from evennia.scripts.scripthandler import ScriptHandler
|
||||
from evennia.server.models import ServerConfig
|
||||
from evennia.server.signals import (SIGNAL_ACCOUNT_POST_CREATE,
|
||||
SIGNAL_ACCOUNT_POST_LOGIN_FAIL,
|
||||
SIGNAL_OBJECT_POST_PUPPET,
|
||||
SIGNAL_OBJECT_POST_UNPUPPET)
|
||||
from evennia.server.signals import (
|
||||
SIGNAL_ACCOUNT_POST_CREATE,
|
||||
SIGNAL_ACCOUNT_POST_LOGIN_FAIL,
|
||||
SIGNAL_OBJECT_POST_PUPPET,
|
||||
SIGNAL_OBJECT_POST_UNPUPPET,
|
||||
)
|
||||
from evennia.server.throttle import Throttle
|
||||
from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler
|
||||
from evennia.typeclasses.models import TypeclassBase
|
||||
from evennia.utils import class_from_module, create, logger
|
||||
from evennia.utils.optionhandler import OptionHandler
|
||||
from evennia.utils.utils import (is_iter, lazy_property, make_iter, to_str,
|
||||
variable_from_module)
|
||||
from evennia.utils.utils import (
|
||||
is_iter,
|
||||
lazy_property,
|
||||
make_iter,
|
||||
to_str,
|
||||
variable_from_module,
|
||||
)
|
||||
|
||||
__all__ = ("DefaultAccount", "DefaultGuest")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ Building and world design commands
|
|||
import re
|
||||
import typing
|
||||
|
||||
import evennia
|
||||
from django.conf import settings
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Max, Min, Q
|
||||
|
||||
import evennia
|
||||
from evennia import InterruptCommand
|
||||
from evennia.commands.cmdhandler import (generate_cmdset_providers,
|
||||
get_and_merge_cmdsets)
|
||||
from evennia.commands.cmdhandler import generate_cmdset_providers, get_and_merge_cmdsets
|
||||
from evennia.locks.lockhandler import LockException
|
||||
from evennia.objects.models import ObjectDB
|
||||
from evennia.prototypes import menus as olc_menus
|
||||
|
|
@ -24,10 +24,18 @@ from evennia.utils.dbserialize import deserialize
|
|||
from evennia.utils.eveditor import EvEditor
|
||||
from evennia.utils.evmore import EvMore
|
||||
from evennia.utils.evtable import EvTable
|
||||
from evennia.utils.utils import (class_from_module, crop, dbref, display_len,
|
||||
format_grid, get_all_typeclasses,
|
||||
inherits_from, interactive, list_to_string,
|
||||
variable_from_module)
|
||||
from evennia.utils.utils import (
|
||||
class_from_module,
|
||||
crop,
|
||||
dbref,
|
||||
display_len,
|
||||
format_grid,
|
||||
get_all_typeclasses,
|
||||
inherits_from,
|
||||
interactive,
|
||||
list_to_string,
|
||||
variable_from_module,
|
||||
)
|
||||
|
||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||
|
||||
|
|
@ -3274,11 +3282,15 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
|
|||
string += f"\n |RNo match found for '{searchstring}' in #dbref interval.|n"
|
||||
else:
|
||||
result = result[0]
|
||||
string += (f"\n|g {result.get_display_name(caller)}"
|
||||
f"{result.get_extra_display_name_info(caller)} - {result.path}|n")
|
||||
string += (
|
||||
f"\n|g {result.get_display_name(caller)}"
|
||||
f"{result.get_extra_display_name_info(caller)} - {result.path}|n"
|
||||
)
|
||||
if "loc" in self.switches and not is_account and result.location:
|
||||
string += (f" (|wlocation|n: |g{result.location.get_display_name(caller)}"
|
||||
f"{result.get_extra_display_name_info(caller)}|n)")
|
||||
string += (
|
||||
f" (|wlocation|n: |g{result.location.get_display_name(caller)}"
|
||||
f"{result.get_extra_display_name_info(caller)}|n)"
|
||||
)
|
||||
else:
|
||||
# Not an account/dbref search but a wider search; build a queryset.
|
||||
# Searches for key and aliases
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ General Character commands usually available to all characters
|
|||
|
||||
import re
|
||||
|
||||
import evennia
|
||||
from django.conf import settings
|
||||
|
||||
import evennia
|
||||
from evennia.typeclasses.attributes import NickTemplateInvalid
|
||||
from evennia.utils import utils
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ import uuid
|
|||
from collections import defaultdict
|
||||
|
||||
from django.core import exceptions as django_exceptions
|
||||
|
||||
from evennia.prototypes import spawner
|
||||
from evennia.utils.utils import class_from_module
|
||||
|
||||
from .utils import (BIGVAL, MAPSCAN, REVERSE_DIRECTIONS, MapError,
|
||||
MapParserError)
|
||||
from .utils import BIGVAL, MAPSCAN, REVERSE_DIRECTIONS, MapError, MapParserError
|
||||
|
||||
NodeTypeclass = None
|
||||
ExitTypeclass = None
|
||||
|
|
@ -331,7 +331,8 @@ class MapNode:
|
|||
raise MapError(
|
||||
f"Multiple objects found: {NodeTypeclass.objects.filter_xyz(xyz=xyz)}. "
|
||||
"This may be due to manual creation of XYZRooms at this position. "
|
||||
"Delete duplicates.", self
|
||||
"Delete duplicates.",
|
||||
self,
|
||||
)
|
||||
else:
|
||||
self.log(f" updating existing room (if changed) at xyz={xyz}")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ used as stand-alone XYZ-coordinate-aware rooms.
|
|||
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
|
||||
from evennia.objects.manager import ObjectManager
|
||||
from evennia.objects.objects import DefaultExit, DefaultRoom
|
||||
|
||||
|
|
@ -307,8 +308,7 @@ class XYZRoom(DefaultRoom):
|
|||
def xyzgrid(self):
|
||||
global GET_XYZGRID
|
||||
if not GET_XYZGRID:
|
||||
from evennia.contrib.grid.xyzgrid.xyzgrid import \
|
||||
get_xyzgrid as GET_XYZGRID
|
||||
from evennia.contrib.grid.xyzgrid.xyzgrid import get_xyzgrid as GET_XYZGRID
|
||||
return GET_XYZGRID()
|
||||
|
||||
@property
|
||||
|
|
@ -532,8 +532,7 @@ class XYZExit(DefaultExit):
|
|||
def xyzgrid(self):
|
||||
global GET_XYZGRID
|
||||
if not GET_XYZGRID:
|
||||
from evennia.contrib.grid.xyzgrid.xyzgrid import \
|
||||
get_xyzgrid as GET_XYZGRID
|
||||
from evennia.contrib.grid.xyzgrid.xyzgrid import get_xyzgrid as GET_XYZGRID
|
||||
return GET_XYZGRID()
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ EvAdventure character generation.
|
|||
"""
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from evennia.objects.models import ObjectDB
|
||||
from evennia.prototypes.spawner import spawn
|
||||
from evennia.utils.create import create_object
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ import time
|
|||
import typing
|
||||
from collections import defaultdict
|
||||
|
||||
import evennia
|
||||
import inflect
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
import evennia
|
||||
from evennia.commands import cmdset
|
||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||
from evennia.objects.manager import ObjectManager
|
||||
|
|
@ -23,9 +24,17 @@ from evennia.server.signals import SIGNAL_EXIT_TRAVERSED
|
|||
from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler
|
||||
from evennia.typeclasses.models import TypeclassBase
|
||||
from evennia.utils import ansi, create, funcparser, logger, search
|
||||
from evennia.utils.utils import (class_from_module, compress_whitespace, dbref,
|
||||
is_iter, iter_to_str, lazy_property,
|
||||
make_iter, to_str, variable_from_module)
|
||||
from evennia.utils.utils import (
|
||||
class_from_module,
|
||||
compress_whitespace,
|
||||
dbref,
|
||||
is_iter,
|
||||
iter_to_str,
|
||||
lazy_property,
|
||||
make_iter,
|
||||
to_str,
|
||||
variable_from_module,
|
||||
)
|
||||
|
||||
_INFLECT = inflect.engine()
|
||||
_MULTISESSION_MODE = settings.MULTISESSION_MODE
|
||||
|
|
@ -1425,7 +1434,8 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
|||
return [
|
||||
obj
|
||||
for obj in obj_list
|
||||
if obj != looker and (obj.access(looker, "view") and obj.access(looker, "search", default=True))
|
||||
if obj != looker
|
||||
and (obj.access(looker, "view") and obj.access(looker, "search", default=True))
|
||||
]
|
||||
|
||||
# name and return_appearance hooks
|
||||
|
|
|
|||
|
|
@ -642,6 +642,8 @@ def send_instruction(operation, arguments, callback=None, errback=None):
|
|||
"""
|
||||
global AMP_CONNECTION, REACTOR_RUN
|
||||
|
||||
# print("launcher: Sending to portal: {} + {}".format(ord(operation), arguments))
|
||||
|
||||
if None in (AMP_HOST, AMP_PORT, AMP_INTERFACE):
|
||||
print(ERROR_AMP_UNCONFIGURED)
|
||||
sys.exit()
|
||||
|
|
|
|||
|
|
@ -197,8 +197,6 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
if process and not _is_windows():
|
||||
# avoid zombie-process on Unix/BSD
|
||||
process.wait()
|
||||
# unset the reset-mode flag on the portal
|
||||
self.factory.portal.server_restart_mode = None
|
||||
return
|
||||
|
||||
def wait_for_disconnect(self, callback, *args, **kwargs):
|
||||
|
|
@ -232,11 +230,18 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
|
||||
"""
|
||||
if mode == "reload":
|
||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRELOAD)
|
||||
self.send_AdminPortal2Server(
|
||||
amp.DUMMYSESSION, operation=amp.SRELOAD, server_restart_mode=mode
|
||||
)
|
||||
elif mode == "reset":
|
||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SRESET)
|
||||
self.send_AdminPortal2Server(
|
||||
amp.DUMMYSESSION, operation=amp.SRESET, server_restart_mode=mode
|
||||
)
|
||||
elif mode == "shutdown":
|
||||
self.send_AdminPortal2Server(amp.DUMMYSESSION, operation=amp.SSHUTD)
|
||||
self.send_AdminPortal2Server(
|
||||
amp.DUMMYSESSION, operation=amp.SSHUTD, server_restart_mode=mode
|
||||
)
|
||||
# store the mode for use once server comes back up again
|
||||
self.factory.portal.server_restart_mode = mode
|
||||
|
||||
# sending amp data
|
||||
|
|
@ -326,7 +331,6 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
_, server_connected, _, _, _, _ = self.get_status()
|
||||
|
||||
# logger.log_msg("Evennia Launcher->Portal operation %s:%s received" % (ord(operation), arguments))
|
||||
|
||||
# logger.log_msg("operation == amp.SSTART: {}: {}".format(operation == amp.SSTART, amp.loads(arguments)))
|
||||
|
||||
if operation == amp.SSTART: # portal start #15
|
||||
|
|
@ -405,11 +409,11 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
|
||||
sessid, kwargs = self.data_in(packed_data)
|
||||
|
||||
# logger.log_msg("Evennia Server->Portal admin data %s:%s received" % (sessid, kwargs))
|
||||
|
||||
operation = kwargs.pop("operation")
|
||||
portal_sessionhandler = evennia.PORTAL_SESSION_HANDLER
|
||||
|
||||
# logger.log_msg(f"Evennia Server->Portal admin data operation {ord(operation)}")
|
||||
|
||||
if operation == amp.SLOGIN: # server_session_login
|
||||
# a session has authenticated; sync it.
|
||||
session = portal_sessionhandler.get(sessid)
|
||||
|
|
@ -427,22 +431,28 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
portal_sessionhandler.server_disconnect_all(reason=kwargs.get("reason"))
|
||||
|
||||
elif operation == amp.SRELOAD: # server reload
|
||||
# set up callback to restart server once it has disconnected
|
||||
self.factory.server_connection.wait_for_disconnect(
|
||||
self.start_server, self.factory.portal.server_twistd_cmd
|
||||
)
|
||||
# tell server to reload
|
||||
self.stop_server(mode="reload")
|
||||
|
||||
elif operation == amp.SRESET: # server reset
|
||||
# set up callback to restart server once it has disconnected
|
||||
self.factory.server_connection.wait_for_disconnect(
|
||||
self.start_server, self.factory.portal.server_twistd_cmd
|
||||
)
|
||||
# tell server to reset
|
||||
self.stop_server(mode="reset")
|
||||
|
||||
elif operation == amp.SSHUTD: # server-only shutdown
|
||||
self.stop_server(mode="shutdown")
|
||||
|
||||
elif operation == amp.PSHUTD: # full server+server shutdown
|
||||
# set up callback to shut down portal once server has disconnected
|
||||
self.factory.server_connection.wait_for_disconnect(self.factory.portal.shutdown)
|
||||
# tell server to shut down
|
||||
self.stop_server(mode="shutdown")
|
||||
|
||||
elif operation == amp.PSYNC: # portal sync
|
||||
|
|
@ -451,6 +461,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
self.factory.portal.server_process_id = kwargs.get("spid", None)
|
||||
# this defaults to 'shutdown' or whatever value set in server_stop
|
||||
server_restart_mode = self.factory.portal.server_restart_mode
|
||||
# print("Server has connected. Sending session data to Server ... mode: {}".format(server_restart_mode))
|
||||
|
||||
sessdata = evennia.PORTAL_SESSION_HANDLER.get_all_sync_data()
|
||||
self.send_AdminPortal2Server(
|
||||
|
|
@ -461,6 +472,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
portal_start_time=self.factory.portal.start_time,
|
||||
)
|
||||
evennia.PORTAL_SESSION_HANDLER.at_server_connection()
|
||||
self.factory.portal.server_restart_mode = None
|
||||
|
||||
if self.factory.server_connection:
|
||||
# this is an indication the server has successfully connected, so
|
||||
|
|
@ -480,7 +492,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol):
|
|||
)
|
||||
|
||||
# set a flag in case we are about to shut down soon
|
||||
self.factory.server_restart_mode = True
|
||||
self.factory.server_restart_mode = "shutdown"
|
||||
|
||||
elif operation == amp.SCONN: # server_force_connection (for irc/etc)
|
||||
portal_sessionhandler.server_connect(**kwargs)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import re
|
|||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from evennia import CmdSet
|
||||
from evennia.commands import cmdhandler
|
||||
from evennia.utils import dedent, fill, is_iter, justify, logger, to_str, utils
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue