From 23462c626c4b47e1af9f4579b23994f95388b082 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 20 Apr 2011 00:27:19 +0000 Subject: [PATCH] Further updates to the IMC2 system, making it a bit easier to use. --- src/commands/default/building.py | 2 +- src/commands/default/comms.py | 89 +++++-------- src/comms/imc2.py | 218 ++++++++++++++----------------- src/comms/models.py | 6 +- src/settings_default.py | 15 ++- 5 files changed, 147 insertions(+), 183 deletions(-) diff --git a/src/commands/default/building.py b/src/commands/default/building.py index 456c30047..d447681df 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -53,7 +53,7 @@ class ObjManipCommand(MuxCommand): objdef, aliases = [part.strip() for part in objdef.split(';', 1)] aliases = [alias.strip() for alias in aliases.split(';') if alias.strip()] if '/' in objdef: - objdef, attrs = [part.strip() for part in objdef.split('/', 1)] + objdef, attrs = [part.strip() for part in objdef.split('/', 1)] attrs = [part.strip().lower() for part in attrs.split('/') if part.strip()] # store data obj_defs[iside].append({"name":objdef, 'option':option, 'aliases':aliases}) diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index a278fc7f2..f9670415f 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -921,19 +921,20 @@ class CmdIMC2Chan(MuxCommand): imc2chan - link an evennia channel to imc2 Usage: - @imc2chan[/switches] = + @imc2chan[/switches] = Switches: - /disconnect - this will delete the bot and remove the imc2 connection to the channel. - /remove - " + /disconnect - this clear the imc2 connection to the channel. + /remove - " /list - show all imc2<->evennia mappings Example: - @imc2chan myimcchan = server02.mudbytes.net 9000 ievennia Gjds8372 LAKdf84e + @imc2chan myimcchan = ievennia - Connect an existing evennia channel to an IMC2 network and channel. You must have registered with the network - beforehand and obtained valid server- and client passwords. You will always connect using the name of your - mud, as defined by settings.SERVERNAME, so make sure this was the name you registered to the imc2 network. + Connect an existing evennia channel to a channel on an IMC2 + network. The network contact information is defined in settings and + should already be accessed at this point. Use @imcchanlist to see + available IMC channels. """ @@ -953,10 +954,11 @@ class CmdIMC2Chan(MuxCommand): # show all connections connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_') if connections: - cols = [["Evennia channel"], ["IMC channel"]] + cols = [["Evennia channel"], ["<->"], ["IMC channel"]] for conn in connections: cols[0].append(conn.channel.key) - cols[1].append(" ".join(conn.external_config.split('|')[:-3])) + cols[1].append("") + cols[2].append(conn.external_config) ftable = utils.format_table(cols) string = "" for ir, row in enumerate(ftable): @@ -969,44 +971,34 @@ class CmdIMC2Chan(MuxCommand): self.caller.msg("No connections found.") return - if not settings.IMC2_ENABLED: - string = """IMC2 is not enabled. You need to activate it in game/settings.py.""" - self.caller.msg(string) - return if not self.args or not self.rhs: - string = "Usage: @imc2chan[/switches] = " + string = "Usage: @imc2chan[/switches] = " self.caller.msg(string) return - channel = self.lhs - try: - imc2_network, imc2_port, imc2_channel, imc2_client_pwd, imc2_server_pwd = [part.strip() for part in self.rhs.split(None, 4)] - except Exception: - string = "Usage: @imc2chan[/switches] = " - string += "\nYou must supply a value in every position to define the IMC2 connnection.\nFor deletion, the tree last arguments (imc2channel and the two passwords) may be dummy values." - self.caller.msg(string) - return - - # get the name to use for connecting - mudname = settings.SERVERNAME - - if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches: - ok = imc2.delete_connection(imc2_network, imc2_port, mudname) + channel = self.lhs + imc2_channel = self.rhs + + if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches: + # we don't search for channels before this since we want to clear the link + # also if the channel no longer exists. + ok = imc2.delete_connection(channel, imc2_channel) if not ok: self.caller.msg("IMC2 connection could not be removed, does it exist?") else: self.caller.msg("IMC2 connection destroyed.") return + # actually get the channel object channel = find_channel(self.caller, channel) if not channel: return - ok = imc2.create_connection(channel, imc2_network, imc2_port, imc2_channel, mudname, imc2_client_pwd, imc2_server_pwd) + ok = imc2.create_connection(channel, imc2_channel) if not ok: - self.caller.msg("This IMC2 connection already exists.") + self.caller.msg("The connection %s <-> %s already exists." % (channel.key, imc2_channel)) return - self.caller.msg("Connection created. Connecting to IMC2 server.") + self.caller.msg("Created connection channel %s <-> IMC channel %s." % (channel.key, imc2_channel)) class CmdIMCInfo(MuxCommand): @@ -1024,7 +1016,6 @@ class CmdIMCInfo(MuxCommand): games or muds - as @imclist whois - as @imcwhois (requires an additional argument) update - force an update of all lists - Shows lists of games or channels on the IMC2 network. """ @@ -1046,21 +1037,15 @@ class CmdIMCInfo(MuxCommand): # update the lists import time from src.comms.imc2lib import imc2_packets as pck - from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CONNECTIONS - # update connected muds - for conn in IMC2_CONNECTIONS: - conn.send_packet(pck.IMC2PacketKeepAliveRequest()) + from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CLIENT + # update connected muds + IMC2_CLIENT.send_packet(pck.IMC2PacketKeepAliveRequest()) # prune inactive muds for name, mudinfo in IMC2_MUDLIST.mud_list.items(): if time.time() - mudinfo.last_updated > 3599: del IMC2_MUDLIST.mud_list[name] - # update channel list - checked_networks = [] - for conn in IMC2_CONNECTIONS: - network = conn.factory.network - if not network in checked_networks: - conn.send_packet(pck.IMC2PacketIceRefresh()) - checked_networks.append(network) + # update channel list + IMC2_CLIENT.send_packet(pck.IMC2PacketIceRefresh()) self.caller.msg("IMC2 lists were re-synced.") elif "games" in self.switches or "muds" in self.switches or self.cmdstring == "@imclist": @@ -1094,19 +1079,18 @@ class CmdIMCInfo(MuxCommand): if not self.args: self.caller.msg("Usage: @imcwhois ") return - from src.comms.imc2 import IMC2_CONNECTIONS - self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.") - for comm in IMC2_CONNECTIONS: - comm.msg_imc2(None, from_obj=self.caller.player, packet_type="imcwhois", data={"target":self.args}) + from src.comms.imc2 import IMC2_CLIENT + self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.") + IMC2_CLIENT.msg_imc2(None, from_obj=self.caller.player, packet_type="imcwhois", data={"target":self.args}) elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist": # show channels - from src.comms.imc2 import IMC2_CHANLIST, IMC2_CONNECTIONS + from src.comms.imc2 import IMC2_CHANLIST, IMC2_CLIENT channels = IMC2_CHANLIST.get_channel_list() string = "" nchans = 0 - string += "\n {GChannels on %s:{n" % (", ".join(conn.factory.network for conn in IMC2_CONNECTIONS)) + string += "\n {GChannels on %s:{n" % IMC2_CLIENT.factory.network cols = [["Full name"], ["Name"], ["Owner"], ["Perm"], ["Policy"]] for channel in channels: nchans += 1 @@ -1155,7 +1139,7 @@ class CmdIMCTell(MuxCommand): self.caller.msg(string) return - from src.comms.imc2 import IMC2_CONNECTIONS + from src.comms.imc2 import IMC2_CLIENT if not self.args or not '@' in self.lhs or not self.rhs: string = "Usage: imctell User@Mud = " @@ -1165,8 +1149,7 @@ class CmdIMCTell(MuxCommand): message = self.rhs.strip() data = {"target":target, "destination":destination} - for comm in IMC2_CONNECTIONS: - # we don't know which connection we aim for, so we send to all. - comm.msg_imc2(message, from_obj=self.caller.player, packet_type="imctell", data=data) + # send to imc2 + IMC2_CLIENT.msg_imc2(message, from_obj=self.caller.player, packet_type="imctell", data=data) self.caller.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message)) diff --git a/src/comms/imc2.py b/src/comms/imc2.py index 9c763b4e1..a1717f379 100644 --- a/src/comms/imc2.py +++ b/src/comms/imc2.py @@ -16,11 +16,17 @@ from src.comms.imc2lib import imc2_packets as pck from src.comms.imc2lib.imc2_trackers import IMC2MudList, IMC2ChanList from src.comms.imc2lib.imc2_listeners import handle_whois_reply +# IMC2 network setup +IMC2_MUDNAME = settings.SERVERNAME +IMC2_NETWORK = settings.IMC2_NETWORK +IMC2_PORT = settings.IMC2_PORT +IMC2_CLIENT_PWD = settings.IMC2_CLIENT_PWD +IMC2_SERVER_PWD = settings.IMC2_SERVER_PWD # channel to send info to INFOCHANNEL = Channel.objects.channel_search(settings.CHANNEL_MUDINFO[0]) # all linked channel connections -IMC2_CONNECTIONS = [] +IMC2_CLIENT = None # IMC2 debug mode IMC2_DEBUG = False # Use this instance to keep track of the other games on the network. @@ -58,11 +64,10 @@ class Send_IsAlive(Script): self.desc = "Send an IMC2 is-alive packet" self.persistent = True def at_repeat(self): - for channel in IMC2_CONNECTIONS: - channel.send_packet(pck.IMC2PacketIsAlive()) + IMC2_CLIENT.send_packet(pck.IMC2PacketIsAlive()) def is_valid(self): "Is only valid as long as there are channels to update" - return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) + return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_")) class Send_Keepalive_Request(Script): """ @@ -74,12 +79,11 @@ class Send_Keepalive_Request(Script): self.interval = 3500 self.desc = "Send an IMC2 keepalive-request packet" self.persistent = True - def at_repeat(self): - for channel in IMC2_CONNECTIONS: - channel.send_packet(pck.IMC2PacketKeepAliveRequest()) + def at_repeat(self): + IMC2_CLIENT.channel.send_packet(pck.IMC2PacketKeepAliveRequest()) def is_valid(self): "Is only valid as long as there are channels to update" - return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) + return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_")) class Prune_Inactive_Muds(Script): """ @@ -99,7 +103,7 @@ class Prune_Inactive_Muds(Script): del IMC2_MUDLIST.mud_list[name] def is_valid(self): "Is only valid as long as there are channels to update" - return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) + return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_")) class Sync_Server_Channel_List(Script): """ @@ -114,14 +118,13 @@ class Sync_Server_Channel_List(Script): self.desc = "Re-sync IMC2 network channel list" self.persistent = True def at_repeat(self): - checked_networks = [] - for channel in self.IMC2_CONNECTIONS: - network = channel.factory.network - if not network in checked_networks: - channel.send_packet(pkg.IMC2PacketIceRefresh()) - checked_networks.append(network) + checked_networks = [] + network = IMC2_CLIENT.factory.network + if not network in checked_networks: + channel.send_packet(pkg.IMC2PacketIceRefresh()) + checked_networks.append(network) def is_valid(self): - return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) + return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_")) # # IMC2 protocol # @@ -132,8 +135,8 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): authentication, and all necessary packets. """ def __init__(self): - global IMC2_CONNECTIONS - IMC2_CONNECTIONS.append(self) + global IMC2_CLIENT + IMC2_CLIENT = self self.is_authenticated = False self.auth_type = None self.server_name = None @@ -146,8 +149,9 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): Triggered after connecting to the IMC2 network. """ self.auth_type = "plaintext" - logger.log_infomsg("IMC2: Connected to network server.") - logger.log_infomsg("IMC2: Sending authentication packet.") + if IMC2_DEBUG: + logger.log_infomsg("IMC2: Connected to network server.") + logger.log_infomsg("IMC2: Sending authentication packet.") self.send_packet(pck.IMC2PacketAuthPlaintext()) def connectionLost(self, reason=None): @@ -155,8 +159,13 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): This is executed when the connection is lost for whatever reason. """ - pass # we don't need to do anything, it's cleaned up automatically. - + try: + service = SESSIONS.server.services.getServiceNamed("imc2_%s:%s(%s)" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME)) + except Exception: + return + if service.running: + service.stopService() + def send_packet(self, packet): """ Given a sub-class of IMC2Packet, assemble the packet and send it @@ -206,7 +215,7 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): self.sequence = int(time()) # Log to stdout and notify over MUDInfo. - auth_message = "Successfully authenticated to the '%s' network." % self.network_name + auth_message = "Successfully authenticated to the '%s' network." % self.factory.network logger.log_infomsg('IMC2: %s' % auth_message) msg_info(auth_message) @@ -228,23 +237,18 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): # If the packet lacks the 'echo' key, don't bother with it. if not conn_name or not packet.optional_data.get('echo', None): return - chan_name = conn_name.split(':', 1)[1] + imc2_channel = conn_name.split(':', 1)[1] - key = "imc2_%s" % conn_name - # Look for matching IMC2 channel maps. - conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key) + # Look for matching IMC2 channel maps mapping to this imc2 channel. + conns = ExternalChannelConnection.objects.filter(db_external_key__startswith="imc2_") + conns = [conn for conn in conns if imc2_channel in conn.db_external_config.split(",")] if not conns: + # we are not listening to this imc2 channel. return - - # get channel subscriptions - chansubs = conns[0].db_external_config.split("|")[2].split(",") - if not chan_name in chansubs: - # we are not listening to this channel. - return - - # Format the message to send to local channel. - message = '[%s] %s@%s: %s' % (self.factory.evennia_channel, packet.sender, packet.origin, packet.optional_data.get('text')) - for conn in (conn for conn in conns if conn.channel): + + # Format the message to send to local channel(s). + for conn in conns: + message = '[%s] %s@%s: %s' % (conn.channel.key, packet.sender, packet.origin, packet.optional_data.get('text')) conn.to_channel(message) def _format_tell(self, packet): @@ -252,7 +256,7 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): Handle tells over IMC2 by formatting the text properly """ return "{c%s@%s{n {wpages (over IMC):{n %s" % (packet.sender, packet.origin, - packet.optional_data.get('text', 'ERROR: No text provided.')) + packet.optional_data.get('text', 'ERROR: No text provided.')) def lineReceived(self, line): """ @@ -308,9 +312,6 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): """ Called by Evennia to send a message through the imc2 connection """ - conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key) - if not conns: - return if from_obj: if hasattr(from_obj, 'key'): from_name = from_obj.key @@ -318,11 +319,20 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): from_name = from_obj else: from_name = self.factory.mudname - + if packet_type == "imcbroadcast": - # send the packet - self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.servername, self.factory.channel[0], - from_name, message)) + if type(data) == dict: + conns = ExternalChannelConnection.objects.filter(db_external_key__startswith="imc2_", + db_channel=data.get("channel", "Unknown")) + if not conns: + return + # we remove the extra channel info since imc2 supplies this anyway + if ":" in message: + header, message = [part.strip() for part in message.split(":", 1)] + # send the packet + imc2_channel = conns[0].db_external_config.split(',')[0] # only send to the first channel + self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.servername, imc2_channel, + from_name, message)) elif packet_type == "imctell": # send a tell if type(data) == dict: @@ -338,24 +348,21 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol): class IMC2Factory(protocol.ClientFactory): """ - Creates instances of the IMC2Protocol. Should really only ever create one - in our particular instance. Tied in via src/server.py. + Creates instances of the IMC2Protocol. Should really only ever + need to create one connection. Tied in via src/server.py. """ protocol = IMC2Protocol - def __init__(self, key, channel, network, port, mudname, client_pwd, server_pwd, evennia_channel): - self.key = key - self.mudname = mudname - self.channel = channel # this is a list! - self.pretty_key = "%s:%s/%s (%s)" % (network, port, channel, mudname) + def __init__(self, network, port, mudname, client_pwd, server_pwd): + self.pretty_key = "%s:%s(%s)" % (network, port, mudname) self.network = network sname, host = network.split(".", 1) self.servername = sname.strip() + self.port = port + self.mudname = mudname self.protocol_version = '2' self.client_pwd = client_pwd self.server_pwd = server_pwd - self.evennia_channel = evennia_channel - def clientConnectionFailed(self, connector, reason): message = 'Connection failed: %s' % reason.getErrorMessage() @@ -368,12 +375,11 @@ class IMC2Factory(protocol.ClientFactory): logger.log_errmsg('IMC2: %s' % message) -def build_connection_key(imc2_network, imc2_port, imc2_mudname): +def build_connection_key(channel, imc2_channel): "Build an id hash for the connection" - return "imc2_%s:%s(%s)<>Evennia" % (imc2_network, imc2_port, imc2_mudname) - -def build_service_key(key): - return "IMC2:%s" % key + if hasattr(channel, "key"): + channel = channel.key + return "imc2_%s:%s(%s)%s<>%s" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME, imc2_channel, channel) def start_scripts(validate=False): """ @@ -393,97 +399,69 @@ def start_scripts(validate=False): if not search.scripts("IMC2_Sync_Server_Channel_List"): create.create_script(Sync_Server_Channel_List) -def create_connection(channel, imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd): +def create_connection(channel, imc2_channel): """ This will create a new IMC2<->channel connection. """ - key = build_connection_key(imc2_network, imc2_port, imc2_mudname) - if not type(channel) == Channel: new_channel = Channel.objects.filter(db_key=channel) if not new_channel: logger.log_errmsg("Cannot attach IMC2<->Evennia: Evennia Channel '%s' not found" % channel) return False channel = new_channel[0] - + key = build_connection_key(channel, imc2_channel) old_conns = ExternalChannelConnection.objects.filter(db_external_key=key) if old_conns: + # this evennia channel is already connected to imc. Check if imc2_channel is different. # connection already exists. We try to only connect a new channel - old_config = old_conns[0].db_external_config.split('|',5) - old_chan_subs = old_config[2].split(',') - if imc2_channel in old_chan_subs: + old_config = old_conns[0].db_external_config.split(",") + if imc2_channel in old_config: return False # we already listen to this channel else: - # We add thew new channel to the connection instead of creating a new connection. - old_chan_subs.append(imc2_channel) - old_chan_subs = ",".join(old_chan_subs) - old_config[2] = old_chan_subs # add a channel subscription to old config - old_conns[0].db_external_config = "|".join(old_config) + # We add a new imc2_channel to listen to + old_config.append(imc2_channel) + old_conns[0].db_external_config = ",".join(old_config) old_conns[0].save() return True + else: + # no old connection found; create a new one. + config = imc2_channel + # how the evennia channel will be able to contact this protocol in reverse + send_code = "from src.comms.imc2 import IMC2_CLIENT\n" + send_code += "data={'channel':from_channel}\n" + send_code += "IMC2_CLIENT.msg_imc2(message, from_obj=from_obj, data=data)\n" + conn = ExternalChannelConnection(db_channel=channel, db_external_key=key, db_external_send_code=send_code, + db_external_config=config) + conn.save() + return True - # new connection - config = "%s|%s|%s|%s|%s|%s" % (imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd) - # how the channel will be able to contact this protocol - send_code = "from src.comms.imc2 import IMC2_CONNECTIONS\n" - send_code += "matched_imc2s = [imc2 for imc2 in IMC2_CONNECTIONS if imc2.factory.key == '%s']\n" % key - send_code += "[imc2.msg_imc2(message, from_obj=from_obj) for imc2 in matched_imc2s]\n" - conn = ExternalChannelConnection(db_channel=channel, db_external_key=key, db_external_send_code=send_code, - db_external_config=config) - conn.save() - - # connect - connect_to_imc2(conn) - # start scripts (if needed) - start_scripts() - return True - -def delete_connection(imc2_network, imc2_port, mudname): +def delete_connection(channel, imc2_channel): "Destroy a connection" - - key = build_connection_key(imc2_network, imc2_port, mudname) - service_key = build_service_key(key) + if hasattr(channel, "key"): + channel = channel.key + key = build_connection_key(channel, imc2_channel) + try: conn = ExternalChannelConnection.objects.get(db_external_key=key) - except Exception: + except ExternalChannelConnection.DoesNotExist: return False conn.delete() - - try: - service = SESSIONS.server.services.getServiceNamed(service_key) - except Exception: - return True - if service.running: - SESSIONS.server.services.removeService(service) - # validate scripts - start_scripts(validate=True) return True -def connect_to_imc2(connection): - "Create the imc instance and connect to the IMC2 network and channel." +def connect_to_imc2(): + "Create the imc instance and connect to the IMC2 network." - # get config - key = utils.to_str(connection.external_key) - service_key = build_service_key(key) - imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd = \ - [utils.to_str(conf) for conf in connection.external_config.split('|')] - imc2_channel = imc2_channel.split(",") # connect - imc = internet.TCPClient(imc2_network, int(imc2_port), IMC2Factory(key, imc2_channel, imc2_network, imc2_port, imc2_mudname, - imc2_client_pwd, imc2_server_pwd, connection.channel.key)) - imc.setName(service_key) + imc = internet.TCPClient(IMC2_NETWORK, int(IMC2_PORT), IMC2Factory(IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME, + IMC2_CLIENT_PWD, IMC2_SERVER_PWD)) + imc.setName("imc2_%s:%s(%s)" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME)) SESSIONS.server.services.addService(imc) def connect_all(): """ - Activate all imc2 bots. - - Returns a list of (key, TCPClient) tuples for server to properly set services. + Activates the imc2 system. Called by the server if IMC2_ENABLED=True. """ - connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_') - for connection in connections: - connect_to_imc2(connection) - if connections: - start_scripts() + connect_to_imc2() + start_scripts() diff --git a/src/comms/models.py b/src/comms/models.py index c7daeaa66..b34a912a6 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -561,7 +561,7 @@ class Channel(SharedMemoryModel): conn.player.msg(msg, from_obj) except AttributeError: try: - conn.to_external(msg, from_obj) + conn.to_external(msg, from_obj, from_channel=self) except Exception: logger.log_trace("Cannot send msg to connection '%s'" % conn) return True @@ -780,7 +780,7 @@ class ExternalChannelConnection(SharedMemoryModel): from_obj = self.external_key self.channel.msg(message, from_obj=from_obj) - def to_external(self, message, from_obj=None): + def to_external(self, message, from_obj=None, from_channel=None): "Send channel -> external" # make sure we are not echoing back our own message to ourselves @@ -792,7 +792,7 @@ class ExternalChannelConnection(SharedMemoryModel): # we execute the code snippet that should make it possible for the # connection to contact the protocol correctly (as set by the protocol). # Note that the code block has access to the variables here, such - # as message and from_obj. + # as message, from_obj and from_channel. exec(to_str(self.external_send_code)) except Exception: logger.log_trace("Channel %s could not send to External %s" % (self.channel, self.external_key)) diff --git a/src/settings_default.py b/src/settings_default.py index d8413a2e7..6ef479653 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -281,13 +281,16 @@ IRC_ENABLED = False # use it, go to http://www.mudbytes.net/imc2-intermud-join-network. # Choose 'Other unsupported IMC2 version' from the choices and and # enter your information there. You should enter the same 'short mud -# name' as your SERVERNAME above. When enabled, the command @imc2chan -# becomes available in-game. It will take 'client password' and -# 'server password' as chosen when registering on mudbytes. The -# Evennia discussion channel 'ievennia' is on -# server02.mudbytes.net:9000. +# name' as your SERVERNAME above, then choose imc network server as +# well as client/server passwords same as below. When enabled, the +# command @imc2chan becomes available in-game and allows you to +# connect Evennia channels to IMC channels on the network. The Evennia +# discussion channel 'ievennia' is on server01.mudbytes.net:5000. IMC2_ENABLED = False - +IMC2_NETWORK = "server01.mudbytes.net" +IMC2_PORT = 5000 +IMC2_CLIENT_PWD = "" +IMC2_SERVER_PWD = "" ################################################### # Config for Django web features