diff --git a/docs/latest/.buildinfo b/docs/latest/.buildinfo index fde16c6f64..6c71332602 100644 --- a/docs/latest/.buildinfo +++ b/docs/latest/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: d1717c6951a36f983bb395a91741da4a +config: 6134ec9189a59a5ec6083b15fbd587a1 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/latest/Coding/Changelog.html b/docs/latest/Coding/Changelog.html index 3a62d5ee9c..91d2266caa 100644 --- a/docs/latest/Coding/Changelog.html +++ b/docs/latest/Coding/Changelog.html @@ -204,7 +204,16 @@

Main branch

@@ -221,6 +230,11 @@ existing database caused corruption of db. For empty db, can still change in

Evennia 4.4.0

Sep 29, 2024

+
+

WARNING: Due to a bug in the default Sqlite3 PRAGMA settings, it is +recommended to not upgrade to this version if you are using Sqlite3. +Use 4.4.1 or higher instead.

+

turnbattle

diff --git a/docs/latest/_modules/evennia/contrib/game_systems/storage/storage.html b/docs/latest/_modules/evennia/contrib/game_systems/storage/storage.html new file mode 100644 index 0000000000..6cadfc71ef --- /dev/null +++ b/docs/latest/_modules/evennia/contrib/game_systems/storage/storage.html @@ -0,0 +1,313 @@ + + + + + + + + evennia.contrib.game_systems.storage.storage — Evennia latest documentation + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Source code for evennia.contrib.game_systems.storage.storage

+from evennia import CmdSet
+from evennia.utils import list_to_string
+from evennia.utils.search import search_object_by_tag
+from evennia.commands.default.muxcommand import MuxCommand
+
+SHARED_TAG_PREFIX = "shared"
+
+
+
[docs]class StorageCommand(MuxCommand): + """ + Shared functionality for storage-related commands + """ + +
[docs] def at_pre_cmd(self): + """ + Check if the current location is tagged as a storage location + Every stored object is tagged on storage, and untagged on retrieval + + Returns: + bool: True if the command is to be stopped here + """ + if super().at_pre_cmd(): + return True + + self.storage_location_id = self.caller.location.tags.get(category="storage_location") + if not self.storage_location_id: + self.caller.msg(f"You cannot {self.cmdstring} anything here.") + return True + + self.object_tag = ( + SHARED_TAG_PREFIX + if self.storage_location_id.startswith(SHARED_TAG_PREFIX) + else self.caller.pk + ) + self.currently_stored = search_object_by_tag( + self.object_tag, category=self.storage_location_id + )
+ + +
[docs]class CmdStore(StorageCommand): + """ + Store something in a storage location. + + Usage: + store <obj> + """ + + key = "store" + locks = "cmd:all()" + help_category = "Storage" + +
[docs] def func(self): + """ + Find the item in question to store, then store it + """ + caller = self.caller + if not self.args: + self.caller.msg("Store what?") + return + obj = caller.search(self.args.strip(), candidates=caller.contents) + if not obj: + return + + """ + We first check at_pre_move before setting the location to None, in case + anything should stymie its movement. + """ + if obj.at_pre_move(caller.location): + obj.tags.add(self.object_tag, self.storage_location_id) + obj.location = None + caller.msg(f"You store {obj.get_display_name(caller)} here.") + else: + caller.msg(f"You fail to store {obj.get_display_name(caller)} here.")
+ + +
[docs]class CmdRetrieve(StorageCommand): + """ + Retrieve something from a storage location. + + Usage: + retrieve <obj> + """ + + key = "retrieve" + locks = "cmd:all()" + help_category = "Storage" + +
[docs] def func(self): + """ + Retrieve the item in question if possible + """ + caller = self.caller + + if not self.args: + self.caller.msg("Retrieve what?") + return + + obj = caller.search(self.args.strip(), candidates=self.currently_stored) + if not obj: + return + + if obj.at_pre_move(caller): + obj.tags.remove(self.object_tag, self.storage_location_id) + caller.msg(f"You retrieve {obj.get_display_name(caller)}.") + else: + caller.msg(f"You fail to retrieve {obj.get_display_name(caller)}.")
+ + +
[docs]class CmdList(StorageCommand): + """ + List items in the storage location. + + Usage: + list + """ + + key = "list" + locks = "cmd:all()" + help_category = "Storage" + +
[docs] def func(self): + """ + List items in the storage + """ + caller = self.caller + if not self.currently_stored: + caller.msg("You find nothing stored here.") + return + caller.msg(f"Stored here:\n{list_to_string(self.currently_stored)}")
+ + +
[docs]class CmdStorage(MuxCommand): + """ + Make the current location a storage room, or delete it as a storage and move all stored objects into the room contents. + + Shared storage locations can be used by all interchangeably. + + The default storage identifier will be its primary key in the database, but you can supply a new one in case you want linked storages. + + Usage: + storage [= [storage identifier]] + storage/shared [= [storage identifier]] + storage/delete + """ + + key = "@storage" + locks = "cmd:perm(Builder)" + +
[docs] def func(self): + """Set the storage location.""" + + caller = self.caller + location = caller.location + current_storage_id = location.tags.get(category="storage_location") + storage_id = self.lhs or location.pk + + if "delete" in self.switches: + if not current_storage_id: + caller.msg("This is not tagged as a storage location.") + return + # Move the stored objects, if any, into the room + currently_stored_here = search_object_by_tag(category=current_storage_id) + for obj in currently_stored_here: + obj.tags.remove(category=current_storage_id) + obj.location = location + caller.msg("You remove the storage capabilities of the room.") + location.tags.remove(current_storage_id, category="storage_location") + return + + if current_storage_id: + caller.msg("This is already a storage location: |wstorage/delete|n to remove the tag.") + return + + new_storage_id = ( + f"{SHARED_TAG_PREFIX if SHARED_TAG_PREFIX in self.switches else ''}{storage_id}" + ) + location.tags.add(new_storage_id, category="storage_location") + caller.msg(f"This is now a storage location with id: {new_storage_id}.")
+ + +
[docs]class StorageCmdSet(CmdSet): + """ + CmdSet for all storage-related commands + """ + +
[docs] def at_cmdset_creation(self): + self.add(CmdStore) + self.add(CmdRetrieve) + self.add(CmdList) + self.add(CmdStorage)
+
+ +
+
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/latest/_modules/evennia/contrib/game_systems/storage/tests.html b/docs/latest/_modules/evennia/contrib/game_systems/storage/tests.html new file mode 100644 index 0000000000..b60f855320 --- /dev/null +++ b/docs/latest/_modules/evennia/contrib/game_systems/storage/tests.html @@ -0,0 +1,244 @@ + + + + + + + + evennia.contrib.game_systems.storage.tests — Evennia latest documentation + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Source code for evennia.contrib.game_systems.storage.tests

+from evennia.commands.default.tests import BaseEvenniaCommandTest
+from evennia.utils.create import create_object
+
+from . import storage
+
+
+
[docs]class TestStorage(BaseEvenniaCommandTest): +
[docs] def setUp(self): + super().setUp() + self.obj1.location = self.char1 + self.room1.tags.add("storage_1", "storage_location") + self.room2.tags.add("shared_storage_2", "storage_location")
+ +
[docs] def test_store_and_retrieve(self): + self.call( + storage.CmdStore(), + "", + "Store what?", + caller=self.char1, + ) + self.call( + storage.CmdStore(), + "obj", + f"You store {self.obj1.get_display_name(self.char1)} here.", + caller=self.char1, + ) + self.call( + storage.CmdList(), + "", + f"Stored here:\n{self.obj1.get_display_name(self.char1)}", + caller=self.char1, + ) + self.call( + storage.CmdRetrieve(), + "obj2", + "Could not find 'obj2'.", + caller=self.char1, + ) + self.call( + storage.CmdRetrieve(), + "obj", + f"You retrieve {self.obj1.get_display_name(self.char1)}.", + caller=self.char1, + )
+ +
[docs] def test_store_retrieve_while_not_in_storeroom(self): + self.char2.location = self.char1 + self.call(storage.CmdStore(), "obj", "You cannot store anything here.", caller=self.char2) + self.call( + storage.CmdRetrieve(), "obj", "You cannot retrieve anything here.", caller=self.char2 + )
+ +
[docs] def test_store_retrieve_nonexistent_obj(self): + self.call(storage.CmdStore(), "asdasd", "Could not find 'asdasd'.", caller=self.char1) + self.call(storage.CmdRetrieve(), "asdasd", "Could not find 'asdasd'.", caller=self.char1)
+ +
[docs] def test_list_nothing_stored(self): + self.call( + storage.CmdList(), + "", + "You find nothing stored here.", + caller=self.char1, + )
+ +
[docs] def test_shared_storage(self): + self.char1.location = self.room2 + self.char2.location = self.room2 + + self.call( + storage.CmdStore(), + "obj", + f"You store {self.obj1.get_display_name(self.char1)} here.", + caller=self.char1, + ) + self.call( + storage.CmdRetrieve(), + "obj", + f"You retrieve {self.obj1.get_display_name(self.char1)}.", + caller=self.char2, + )
+ +
[docs] def test_remove_add_storage(self): + self.char1.permissions.add("builder") + self.call( + storage.CmdStorage(), + "", + "This is already a storage location: storage/delete to remove the tag.", + caller=self.char1, + ) + self.call( + storage.CmdStore(), + "obj", + f"You store {self.obj1.get_display_name(self.char1)} here.", + caller=self.char1, + ) + self.assertEqual(self.obj1.location, None) + self.call( + storage.CmdStorage(), + "/delete", + "You remove the storage capabilities of the room.", + caller=self.char1, + ) + self.assertEqual(self.obj1.location, self.room1) + self.call( + storage.CmdStorage(), + "", + f"This is now a storage location with id: {self.room1.id}.", + caller=self.char1, + ) + self.call( + storage.CmdStorage(), + "/delete", + "You remove the storage capabilities of the room.", + caller=self.char1, + ) + self.call( + storage.CmdStorage(), + "/shared", + f"This is now a storage location with id: shared{self.room1.id}.", + caller=self.char1, + )
+
+ +
+
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/latest/_modules/evennia/objects/models.html b/docs/latest/_modules/evennia/objects/models.html index 2ba117e623..3073976998 100644 --- a/docs/latest/_modules/evennia/objects/models.html +++ b/docs/latest/_modules/evennia/objects/models.html @@ -160,6 +160,7 @@ """ objects = self.load() + self._typecache = defaultdict(dict) self._pkcache = {obj.pk: True for obj in objects} for obj in objects: try: diff --git a/docs/latest/_modules/evennia/server/portal/mccp.html b/docs/latest/_modules/evennia/server/portal/mccp.html index 4b543b8b99..0ea7c6fd8e 100644 --- a/docs/latest/_modules/evennia/server/portal/mccp.html +++ b/docs/latest/_modules/evennia/server/portal/mccp.html @@ -107,6 +107,7 @@ mccp_compress and calling it from its write methods. """ +import weakref import zlib # negotiations for v1 and v2 of the protocol @@ -149,10 +150,10 @@ """ - self.protocol = protocol - self.protocol.protocol_flags["MCCP"] = False + self.protocol = weakref.ref(protocol) + self.protocol().protocol_flags["MCCP"] = False # ask if client will mccp, connect callbacks to handle answer - self.protocol.will(MCCP).addCallbacks(self.do_mccp, self.no_mccp) + self.protocol().will(MCCP).addCallbacks(self.do_mccp, self.no_mccp)
[docs] def no_mccp(self, option): """ @@ -162,10 +163,10 @@ option (Option): Option dict (not used). """ - if hasattr(self.protocol, "zlib"): - del self.protocol.zlib - self.protocol.protocol_flags["MCCP"] = False - self.protocol.handshake_done()
+ if hasattr(self.protocol(), "zlib"): + del self.protocol().zlib + self.protocol().protocol_flags["MCCP"] = False + self.protocol().handshake_done()
[docs] def do_mccp(self, option): """ @@ -176,10 +177,10 @@ option (Option): Option dict (not used). """ - self.protocol.protocol_flags["MCCP"] = True - self.protocol.requestNegotiation(MCCP, b"") - self.protocol.zlib = zlib.compressobj(9) - self.protocol.handshake_done()
+ self.protocol().protocol_flags["MCCP"] = True + self.protocol().requestNegotiation(MCCP, b"") + self.protocol().zlib = zlib.compressobj(9) + self.protocol().handshake_done() diff --git a/docs/latest/_modules/evennia/server/portal/mssp.html b/docs/latest/_modules/evennia/server/portal/mssp.html index 9f4fdcda0d..54dd85bd32 100644 --- a/docs/latest/_modules/evennia/server/portal/mssp.html +++ b/docs/latest/_modules/evennia/server/portal/mssp.html @@ -103,6 +103,7 @@ """ +import weakref from django.conf import settings from evennia.utils import utils @@ -131,8 +132,8 @@ protocol (Protocol): The active protocol instance. """ - self.protocol = protocol - self.protocol.will(MSSP).addCallbacks(self.do_mssp, self.no_mssp) + self.protocol = weakref.ref(protocol) + self.protocol().will(MSSP).addCallbacks(self.do_mssp, self.no_mssp)
[docs] def get_player_count(self): """ @@ -142,7 +143,7 @@ count (int): The number of players in the MUD. """ - return str(self.protocol.sessionhandler.count_loggedin())
+ return str(self.protocol().sessionhandler.count_loggedin())
[docs] def get_uptime(self): """ @@ -152,7 +153,7 @@ uptime (int): Number of seconds of uptime. """ - return str(self.protocol.sessionhandler.uptime)
+ return str(self.protocol().sessionhandler.uptime)
[docs] def no_mssp(self, option): """ @@ -163,7 +164,7 @@ option (Option): Not used. """ - self.protocol.handshake_done()
+ self.protocol().handshake_done()
[docs] def do_mssp(self, option): """ @@ -224,8 +225,8 @@ ) # send to crawler by subnegotiation - self.protocol.requestNegotiation(MSSP, varlist) - self.protocol.handshake_done()
+ self.protocol().requestNegotiation(MSSP, varlist) + self.protocol().handshake_done() diff --git a/docs/latest/_modules/evennia/server/portal/mxp.html b/docs/latest/_modules/evennia/server/portal/mxp.html index 80c4e97afb..07079c1773 100644 --- a/docs/latest/_modules/evennia/server/portal/mxp.html +++ b/docs/latest/_modules/evennia/server/portal/mxp.html @@ -107,6 +107,7 @@ """ import re +import weakref from django.conf import settings @@ -153,10 +154,10 @@ protocol (Protocol): The active protocol instance. """ - self.protocol = protocol - self.protocol.protocol_flags["MXP"] = False + self.protocol = weakref.ref(protocol) + self.protocol().protocol_flags["MXP"] = False if settings.MXP_ENABLED: - self.protocol.will(MXP).addCallbacks(self.do_mxp, self.no_mxp) + self.protocol().will(MXP).addCallbacks(self.do_mxp, self.no_mxp)
[docs] def no_mxp(self, option): """ @@ -166,8 +167,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["MXP"] = False - self.protocol.handshake_done()
+ self.protocol().protocol_flags["MXP"] = False + self.protocol().handshake_done()
[docs] def do_mxp(self, option): """ @@ -178,11 +179,11 @@ """ if settings.MXP_ENABLED: - self.protocol.protocol_flags["MXP"] = True - self.protocol.requestNegotiation(MXP, b"") + self.protocol().protocol_flags["MXP"] = True + self.protocol().requestNegotiation(MXP, b"") else: - self.protocol.wont(MXP) - self.protocol.handshake_done()
+ self.protocol().wont(MXP) + self.protocol().handshake_done() diff --git a/docs/latest/_modules/evennia/server/portal/naws.html b/docs/latest/_modules/evennia/server/portal/naws.html index 87b60dfb5d..b97f45dfee 100644 --- a/docs/latest/_modules/evennia/server/portal/naws.html +++ b/docs/latest/_modules/evennia/server/portal/naws.html @@ -103,6 +103,7 @@ """ from codecs import encode as codecs_encode +import weakref from django.conf import settings @@ -133,13 +134,13 @@ """ self.naws_step = 0 - self.protocol = protocol - self.protocol.protocol_flags["SCREENWIDTH"] = { + self.protocol = weakref.ref(protocol) + self.protocol().protocol_flags["SCREENWIDTH"] = { 0: DEFAULT_WIDTH } # windowID (0 is root):width - self.protocol.protocol_flags["SCREENHEIGHT"] = {0: DEFAULT_HEIGHT} # windowID:width - self.protocol.negotiationMap[NAWS] = self.negotiate_sizes - self.protocol.do(NAWS).addCallbacks(self.do_naws, self.no_naws) + self.protocol().protocol_flags["SCREENHEIGHT"] = {0: DEFAULT_HEIGHT} # windowID:width + self.protocol().negotiationMap[NAWS] = self.negotiate_sizes + self.protocol().do(NAWS).addCallbacks(self.do_naws, self.no_naws)
[docs] def no_naws(self, option): """ @@ -150,8 +151,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["AUTORESIZE"] = False - self.protocol.handshake_done()
+ self.protocol().protocol_flags["AUTORESIZE"] = False + self.protocol().handshake_done()
[docs] def do_naws(self, option): """ @@ -161,8 +162,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["AUTORESIZE"] = True - self.protocol.handshake_done()
+ self.protocol().protocol_flags["AUTORESIZE"] = True + self.protocol().handshake_done()
[docs] def negotiate_sizes(self, options): """ @@ -175,9 +176,9 @@ if len(options) == 4: # NAWS is negotiated with 16bit words width = options[0] + options[1] - self.protocol.protocol_flags["SCREENWIDTH"][0] = int(codecs_encode(width, "hex"), 16) + self.protocol().protocol_flags["SCREENWIDTH"][0] = int(codecs_encode(width, "hex"), 16) height = options[2] + options[3] - self.protocol.protocol_flags["SCREENHEIGHT"][0] = int(codecs_encode(height, "hex"), 16)
+ self.protocol().protocol_flags["SCREENHEIGHT"][0] = int(codecs_encode(height, "hex"), 16) diff --git a/docs/latest/_modules/evennia/server/portal/suppress_ga.html b/docs/latest/_modules/evennia/server/portal/suppress_ga.html index c429134c68..64675ac9db 100644 --- a/docs/latest/_modules/evennia/server/portal/suppress_ga.html +++ b/docs/latest/_modules/evennia/server/portal/suppress_ga.html @@ -106,6 +106,8 @@ """ +import weakref + SUPPRESS_GA = bytes([3]) # b"\x03" # default taken from telnet specification @@ -128,14 +130,14 @@ protocol (Protocol): The active protocol instance. """ - self.protocol = protocol + self.protocol = weakref.ref(protocol) - self.protocol.protocol_flags["NOGOAHEAD"] = True - self.protocol.protocol_flags["NOPROMPTGOAHEAD"] = ( + self.protocol().protocol_flags["NOGOAHEAD"] = True + self.protocol().protocol_flags["NOPROMPTGOAHEAD"] = ( True # Used to send a GA after a prompt line only, set in TTYPE (per client) ) # tell the client that we prefer to suppress GA ... - self.protocol.will(SUPPRESS_GA).addCallbacks(self.will_suppress_ga, self.wont_suppress_ga) + self.protocol().will(SUPPRESS_GA).addCallbacks(self.will_suppress_ga, self.wont_suppress_ga)
[docs] def wont_suppress_ga(self, option): """ @@ -145,8 +147,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["NOGOAHEAD"] = False - self.protocol.handshake_done()
+ self.protocol().protocol_flags["NOGOAHEAD"] = False + self.protocol().handshake_done()
[docs] def will_suppress_ga(self, option): """ @@ -156,8 +158,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["NOGOAHEAD"] = True - self.protocol.handshake_done()
+ self.protocol().protocol_flags["NOGOAHEAD"] = True + self.protocol().handshake_done() diff --git a/docs/latest/_modules/evennia/server/portal/telnet.html b/docs/latest/_modules/evennia/server/portal/telnet.html index d70dd1e59a..d591de5bac 100644 --- a/docs/latest/_modules/evennia/server/portal/telnet.html +++ b/docs/latest/_modules/evennia/server/portal/telnet.html @@ -398,6 +398,8 @@ """ self.sessionhandler.disconnect(self) + if self.nop_keep_alive and self.nop_keep_alive.running: + self.toggle_nop_keepalive() self.transport.loseConnection()
[docs] def applicationDataReceived(self, data): diff --git a/docs/latest/_modules/evennia/server/portal/telnet_oob.html b/docs/latest/_modules/evennia/server/portal/telnet_oob.html index 6552fc22e7..151f330b59 100644 --- a/docs/latest/_modules/evennia/server/portal/telnet_oob.html +++ b/docs/latest/_modules/evennia/server/portal/telnet_oob.html @@ -118,6 +118,7 @@ import json import re +import weakref # General Telnet from twisted.conch.telnet import IAC, SB, SE @@ -176,16 +177,16 @@ protocol (Protocol): The active protocol. """ - self.protocol = protocol - self.protocol.protocol_flags["OOB"] = False + self.protocol = weakref.ref(protocol) + self.protocol().protocol_flags["OOB"] = False self.MSDP = False self.GMCP = False # ask for the available protocols and assign decoders # (note that handshake_done() will be called twice!) - self.protocol.negotiationMap[MSDP] = self.decode_msdp - self.protocol.negotiationMap[GMCP] = self.decode_gmcp - self.protocol.will(MSDP).addCallbacks(self.do_msdp, self.no_msdp) - self.protocol.will(GMCP).addCallbacks(self.do_gmcp, self.no_gmcp) + self.protocol().negotiationMap[MSDP] = self.decode_msdp + self.protocol().negotiationMap[GMCP] = self.decode_gmcp + self.protocol().will(MSDP).addCallbacks(self.do_msdp, self.no_msdp) + self.protocol().will(GMCP).addCallbacks(self.do_gmcp, self.no_gmcp) self.oob_reported = {}
[docs] def no_msdp(self, option): @@ -197,7 +198,7 @@ """ # no msdp, check GMCP - self.protocol.handshake_done()
+ self.protocol().handshake_done()
[docs] def do_msdp(self, option): """ @@ -208,8 +209,8 @@ """ self.MSDP = True - self.protocol.protocol_flags["OOB"] = True - self.protocol.handshake_done()
+ self.protocol().protocol_flags["OOB"] = True + self.protocol().handshake_done()
[docs] def no_gmcp(self, option): """ @@ -220,7 +221,7 @@ option (Option): Not used. """ - self.protocol.handshake_done()
+ self.protocol().handshake_done()
[docs] def do_gmcp(self, option): """ @@ -231,8 +232,8 @@ """ self.GMCP = True - self.protocol.protocol_flags["OOB"] = True - self.protocol.handshake_done()
+ self.protocol().protocol_flags["OOB"] = True + self.protocol().handshake_done() # encoders @@ -467,7 +468,7 @@ cmds["msdp_{}".format(remap)] = cmds.pop(lower_case[remap]) # print("msdp data in:", cmds) # DEBUG - self.protocol.data_in(**cmds) + self.protocol().data_in(**cmds)
[docs] def decode_gmcp(self, data): """ @@ -516,7 +517,7 @@ if cmdname.lower().startswith(b"core_"): # if Core.cmdname, then use cmdname cmdname = cmdname[5:] - self.protocol.data_in(**{cmdname.lower().decode(): [args, kwargs]})
+ self.protocol().data_in(**{cmdname.lower().decode(): [args, kwargs]}) # access methods @@ -533,11 +534,11 @@ if self.MSDP: encoded_oob = self.encode_msdp(cmdname, *args, **kwargs) - self.protocol._write(IAC + SB + MSDP + encoded_oob + IAC + SE) + self.protocol()._write(IAC + SB + MSDP + encoded_oob + IAC + SE) if self.GMCP: encoded_oob = self.encode_gmcp(cmdname, *args, **kwargs) - self.protocol._write(IAC + SB + GMCP + encoded_oob + IAC + SE) + self.protocol()._write(IAC + SB + GMCP + encoded_oob + IAC + SE) diff --git a/docs/latest/_modules/evennia/server/portal/ttype.html b/docs/latest/_modules/evennia/server/portal/ttype.html index 5a80c823a6..9cef7a480c 100644 --- a/docs/latest/_modules/evennia/server/portal/ttype.html +++ b/docs/latest/_modules/evennia/server/portal/ttype.html @@ -104,6 +104,8 @@ """ +import weakref + # telnet option codes TTYPE = bytes([24]) # b"\x18" IS = bytes([0]) # b"\x00" @@ -147,16 +149,16 @@ """ self.ttype_step = 0 - self.protocol = protocol + self.protocol = weakref.ref(protocol) # we set FORCEDENDLINE for clients not supporting ttype - self.protocol.protocol_flags["FORCEDENDLINE"] = True - self.protocol.protocol_flags["TTYPE"] = False + self.protocol().protocol_flags["FORCEDENDLINE"] = True + self.protocol().protocol_flags["TTYPE"] = False # is it a safe bet to assume ANSI is always supported? - self.protocol.protocol_flags["ANSI"] = True + self.protocol().protocol_flags["ANSI"] = True # setup protocol to handle ttype initialization and negotiation - self.protocol.negotiationMap[TTYPE] = self.will_ttype + self.protocol().negotiationMap[TTYPE] = self.will_ttype # ask if client will ttype, connect callback if it does. - self.protocol.do(TTYPE).addCallbacks(self.will_ttype, self.wont_ttype) + self.protocol().do(TTYPE).addCallbacks(self.will_ttype, self.wont_ttype)
[docs] def wont_ttype(self, option): """ @@ -166,8 +168,8 @@ option (Option): Not used. """ - self.protocol.protocol_flags["TTYPE"] = False - self.protocol.handshake_done()
+ self.protocol().protocol_flags["TTYPE"] = False + self.protocol().handshake_done()
[docs] def will_ttype(self, option): """ @@ -183,7 +185,7 @@ stored on protocol.protocol_flags under the TTYPE key. """ - options = self.protocol.protocol_flags + options = self.protocol().protocol_flags if options and options.get("TTYPE", False) or self.ttype_step > 3: return @@ -196,7 +198,7 @@ if self.ttype_step == 0: # just start the request chain - self.protocol.requestNegotiation(TTYPE, SEND) + self.protocol().requestNegotiation(TTYPE, SEND) elif self.ttype_step == 1: # this is supposed to be the name of the client/terminal. @@ -217,9 +219,9 @@ xterm256 = clientname.split("MUDLET", 1)[1].strip() >= "1.1" # Mudlet likes GA's on a prompt line for the prompt trigger to # match, if it's not wanting NOGOAHEAD. - if not self.protocol.protocol_flags["NOGOAHEAD"]: - self.protocol.protocol_flags["NOGOAHEAD"] = True - self.protocol.protocol_flags["NOPROMPTGOAHEAD"] = False + if not self.protocol().protocol_flags["NOGOAHEAD"]: + self.protocol().protocol_flags["NOGOAHEAD"] = True + self.protocol().protocol_flags["NOPROMPTGOAHEAD"] = False if ( clientname.startswith("XTERM") @@ -245,11 +247,11 @@ truecolor = True # all clients supporting TTYPE at all seem to support ANSI - self.protocol.protocol_flags["ANSI"] = True - self.protocol.protocol_flags["XTERM256"] = xterm256 - self.protocol.protocol_flags["TRUECOLOR"] = truecolor - self.protocol.protocol_flags["CLIENTNAME"] = clientname - self.protocol.requestNegotiation(TTYPE, SEND) + self.protocol().protocol_flags["ANSI"] = True + self.protocol().protocol_flags["XTERM256"] = xterm256 + self.protocol().protocol_flags["TRUECOLOR"] = truecolor + self.protocol().protocol_flags["CLIENTNAME"] = clientname + self.protocol().requestNegotiation(TTYPE, SEND) elif self.ttype_step == 2: # this is a term capabilities flag @@ -262,11 +264,11 @@ and not tupper.endswith("-COLOR") # old Tintin, Putty ) if xterm256: - self.protocol.protocol_flags["ANSI"] = True - self.protocol.protocol_flags["XTERM256"] = xterm256 - self.protocol.protocol_flags["TERM"] = term + self.protocol().protocol_flags["ANSI"] = True + self.protocol().protocol_flags["XTERM256"] = xterm256 + self.protocol().protocol_flags["TERM"] = term # request next information - self.protocol.requestNegotiation(TTYPE, SEND) + self.protocol().requestNegotiation(TTYPE, SEND) elif self.ttype_step == 3: # the MTTS bitstring identifying term capabilities @@ -278,14 +280,14 @@ support = dict( (capability, True) for bitval, capability in MTTS if option & bitval > 0 ) - self.protocol.protocol_flags.update(support) + self.protocol().protocol_flags.update(support) else: # some clients send erroneous MTTS as a string. Add directly. - self.protocol.protocol_flags[option.upper()] = True + self.protocol().protocol_flags[option.upper()] = True - self.protocol.protocol_flags["TTYPE"] = True + self.protocol().protocol_flags["TTYPE"] = True # we must sync ttype once it'd done - self.protocol.handshake_done() + self.protocol().handshake_done() self.ttype_step += 1
diff --git a/docs/latest/_modules/index.html b/docs/latest/_modules/index.html index a0684e11be..f7ce32313f 100644 --- a/docs/latest/_modules/index.html +++ b/docs/latest/_modules/index.html @@ -182,6 +182,8 @@
  • evennia.contrib.game_systems.multidescer.tests
  • evennia.contrib.game_systems.puzzles.puzzles
  • evennia.contrib.game_systems.puzzles.tests
  • +
  • evennia.contrib.game_systems.storage.storage
  • +
  • evennia.contrib.game_systems.storage.tests
  • evennia.contrib.game_systems.turnbattle.tb_basic
  • evennia.contrib.game_systems.turnbattle.tb_equip
  • evennia.contrib.game_systems.turnbattle.tb_items
  • diff --git a/docs/latest/_sources/Coding/Changelog.md.txt b/docs/latest/_sources/Coding/Changelog.md.txt index 4e48832cdd..92302db559 100644 --- a/docs/latest/_sources/Coding/Changelog.md.txt +++ b/docs/latest/_sources/Coding/Changelog.md.txt @@ -4,13 +4,29 @@ ## Main branch - [Feat][pull3634]: New contrib for in-game `storage` of items in rooms (aMiss-aWry) +- [Feat][pull3636]: Make `cpattr` command also support Attribute categories (aMiss-aWry) +- [Fix][pull3635]: Fix memory leak in Portal Telnet connections, force weak + references to Telnet negotiations, stop LoopingCall on disconnect (a-rodian-jedi) - [Fix][pull3626]: Typo in `defense_type` in evadventure tutorial (feyrkh) +- [Fix][pull3632]: Made fallback permissions on be set correctly (InspectorCaracal) +- [Fix][pull3639]: Fix `system` command when environment uses a language with + commas for decimal points (aMiss-aWry) +- [Fix][pull3645]: Correct `character_creator` contrib's error return (InspectorCaracal) +- [Fix][pull3640]: Typo fixes for conjugate verbs (aMiss-aWry) +- [Fix][pull3647]: Contents cache didn't reset internal typecache on use of `init` hook (InspectorCaracal) - [Docs][pull3576]: Rework doc for [Pycharm howto][doc-pycharm] - Docs updates: feykrh, Griatch [pull3626]: https://github.com/evennia/evennia/pull/3626 [pull3676]: https://github.com/evennia/evennia/pull/3676 [pull3634]: https://github.com/evennia/evennia/pull/3634 +[pull3632]: https://github.com/evennia/evennia/pull/3632 +[pull3636]: https://github.com/evennia/evennia/pull/3636 +[pull3639]: https://github.com/evennia/evennia/pull/3639 +[pull3645]: https://github.com/evennia/evennia/pull/3645 +[pull3640]: https://github.com/evennia/evennia/pull/3640 +[pull3647]: https://github.com/evennia/evennia/pull/3647 +[pull3635]: https://github.com/evennia/evennia/pull/3635 [doc-pycharm]: https://www.evennia.com/docs/latest/Coding/Setting-up-PyCharm.html ## Evennia 4.4.1 @@ -28,6 +44,10 @@ Oct 1, 2024 Sep 29, 2024 +> WARNING: Due to a bug in the default Sqlite3 PRAGMA settings, it is +> recommended to not upgrade to this version if you are using Sqlite3. +> Use `4.4.1` or higher instead. + - Feat: Support `scripts key:typeclass` to create global scripts with dynamic keys (rather than just relying on typeclass' key) (Griatch) - [Feat][pull3595]: Tweak Sqlite3 PRAGMAs for better performance (0xDEADFED5) diff --git a/docs/latest/_sources/api/evennia.contrib.game_systems.md.txt b/docs/latest/_sources/api/evennia.contrib.game_systems.md.txt index 07ddfa33e1..de3da5f352 100644 --- a/docs/latest/_sources/api/evennia.contrib.game_systems.md.txt +++ b/docs/latest/_sources/api/evennia.contrib.game_systems.md.txt @@ -21,6 +21,7 @@ evennia.contrib.game\_systems evennia.contrib.game_systems.mail evennia.contrib.game_systems.multidescer evennia.contrib.game_systems.puzzles + evennia.contrib.game_systems.storage evennia.contrib.game_systems.turnbattle ``` \ No newline at end of file diff --git a/docs/latest/_sources/api/evennia.contrib.game_systems.storage.md.txt b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.md.txt new file mode 100644 index 0000000000..82abd8d66a --- /dev/null +++ b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.md.txt @@ -0,0 +1,18 @@ +```{eval-rst} +evennia.contrib.game\_systems.storage +============================================= + +.. automodule:: evennia.contrib.game_systems.storage + :members: + :undoc-members: + :show-inheritance: + + + +.. toctree:: + :maxdepth: 6 + + evennia.contrib.game_systems.storage.storage + evennia.contrib.game_systems.storage.tests + +``` \ No newline at end of file diff --git a/docs/latest/_sources/api/evennia.contrib.game_systems.storage.storage.md.txt b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.storage.md.txt new file mode 100644 index 0000000000..882eaf6984 --- /dev/null +++ b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.storage.md.txt @@ -0,0 +1,10 @@ +```{eval-rst} +evennia.contrib.game\_systems.storage.storage +==================================================== + +.. automodule:: evennia.contrib.game_systems.storage.storage + :members: + :undoc-members: + :show-inheritance: + +``` \ No newline at end of file diff --git a/docs/latest/_sources/api/evennia.contrib.game_systems.storage.tests.md.txt b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.tests.md.txt new file mode 100644 index 0000000000..fccdd5fe58 --- /dev/null +++ b/docs/latest/_sources/api/evennia.contrib.game_systems.storage.tests.md.txt @@ -0,0 +1,10 @@ +```{eval-rst} +evennia.contrib.game\_systems.storage.tests +================================================== + +.. automodule:: evennia.contrib.game_systems.storage.tests + :members: + :undoc-members: + :show-inheritance: + +``` \ No newline at end of file diff --git a/docs/latest/api/evennia-api.html b/docs/latest/api/evennia-api.html index 7d9506ed22..2741bb1c6f 100644 --- a/docs/latest/api/evennia-api.html +++ b/docs/latest/api/evennia-api.html @@ -315,6 +315,11 @@
  • evennia.contrib.game_systems.puzzles.tests
  • +
  • evennia.contrib.game_systems.storage +
  • evennia.contrib.game_systems.turnbattle
  • +
  • evennia.contrib.game_systems.storage +
  • evennia.contrib.game_systems.turnbattle
  • +
  • evennia.contrib.game_systems.storage +
  • evennia.contrib.game_systems.turnbattle
  • +
  • evennia.contrib.game_systems.storage +
  • evennia.contrib.game_systems.turnbattle
  • at_pre_drop() (evennia.contrib.game_systems.turnbattle.tb_equip.TBEArmor method) @@ -4048,6 +4062,8 @@
  • CmdLineInput (class in evennia.utils.eveditor)
  • CmdLink (class in evennia.commands.default.building) +
  • +
  • CmdList (class in evennia.contrib.game_systems.storage.storage)
  • CmdListArmedPuzzles (class in evennia.contrib.game_systems.puzzles.puzzles)
  • @@ -4115,10 +4131,10 @@
  • CmdOffer (class in evennia.contrib.game_systems.barter.barter)
  • - - + +
  • CmdRetrieve (class in evennia.contrib.game_systems.storage.storage) +
  • CmdRSS2Chan (class in evennia.commands.default.comms)
  • CmdSaveYesNo (class in evennia.utils.eveditor) @@ -4326,6 +4344,10 @@
  • CmdStop (class in evennia.contrib.grid.slow_exit.slow_exit) +
  • +
  • CmdStorage (class in evennia.contrib.game_systems.storage.storage) +
  • +
  • CmdStore (class in evennia.contrib.game_systems.storage.storage)
  • CmdStunt (class in evennia.contrib.tutorials.evadventure.combat_twitch)
  • @@ -7213,6 +7235,27 @@ +
  • + evennia.contrib.game_systems.storage + +
  • +
  • + evennia.contrib.game_systems.storage.storage + +
  • +
  • + evennia.contrib.game_systems.storage.tests + +
  • @@ -7712,6 +7755,8 @@
  • module
  • + + - - +
  • StorageCmdSet (class in evennia.contrib.game_systems.storage.storage) +
  • +
  • StorageCommand (class in evennia.contrib.game_systems.storage.storage) +
  • Store (class in evennia.scripts.scripts)
  • store() (evennia.server.models.ServerConfig method) @@ -22435,6 +22548,8 @@
  • test_list_cmdsets() (evennia.commands.default.tests.TestBuilding method) +
  • +
  • test_list_nothing_stored() (evennia.contrib.game_systems.storage.tests.TestStorage method)
  • test_load_recipes() (evennia.contrib.game_systems.crafting.tests.TestCraftUtils method)
  • @@ -22749,6 +22864,8 @@
  • test_remove__with_obj() (evennia.contrib.tutorials.evadventure.tests.test_equipment.TestEquipment method)
  • test_remove__with_slot() (evennia.contrib.tutorials.evadventure.tests.test_equipment.TestEquipment method) +
  • +
  • test_remove_add_storage() (evennia.contrib.game_systems.storage.tests.TestStorage method)
  • test_remove_combatant() (evennia.contrib.tutorials.evadventure.tests.test_combat.EvAdventureTurnbasedCombatHandlerTest method)
  • @@ -22838,10 +22955,10 @@
  • test_sessions() (evennia.commands.default.tests.TestAccount method)
  • - - +