diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index 1c20f14bc4..d984854389 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -808,27 +808,42 @@ class CmdPage(COMMAND_DEFAULT_CLASS): lastpages = pages[-number:] else: lastpages = pages - to_template = "|w{date}|n{sender}|n |cto {receiver}|n:> {message}" - from_template = "|w{date}|n{receiver}|n |gfrom {sender}|n:< {message}" + to_template = "|w{date}{clr} {sender}|nto{clr}{receiver}|n:> {message}" + from_template = "|w{date}{clr} {receiver}|nfrom{clr}{sender}|n:< {message}" listing = [] + prev_selfsend = False for page in lastpages: - receiver = "" - sender = "" - template = from_template - sending = False - if self.caller in page.senders: + multi_send = len(page.senders) > 1 + multi_recv = len(page.receivers) > 1 + sending = self.caller in page.senders + # self-messages all look like sends, so we assume they always + # come in close pairs and treat the second of the pair as the recv. + selfsend = sending and self.caller in page.receivers + if selfsend: + if prev_selfsend: + # this is actually a receive of a self-message + sending = False + prev_selfsend = False + else: + prev_selfsend = True + + clr = "|c" if sending else "|g" + + sender = f"|n,{clr}".join(obj.key for obj in page.senders) + receiver = f"|n,{clr}".join([obj.name for obj in page.receivers]) + if sending: template = to_template - sending = True - - if len(page.receivers) > 1 or sending: - receiver = "|n,|c ".join([obj.name for obj in page.receivers]) - - if len(page.senders) > 1 or not sending: - sender = "|n,|c".join(obj.key for obj in page.senders) + sender = f"{sender} " if multi_send else "" + receiver = f" {receiver}" if multi_recv else f" {receiver}" + else: + template = from_template + receiver = f"{receiver} " if multi_recv else "" + sender = f" {sender} " if multi_send else f" {sender}" listing.append( template.format( date=utils.datetime_format(page.date_created), + clr=clr, sender=sender, receiver=receiver, message=page.message, diff --git a/evennia/commands/default/general.py b/evennia/commands/default/general.py index 12ec9acf62..6b739e022b 100644 --- a/evennia/commands/default/general.py +++ b/evennia/commands/default/general.py @@ -378,10 +378,12 @@ class CmdInventory(COMMAND_DEFAULT_CLASS): if not items: string = "You are not carrying anything." else: + from evennia.utils.ansi import raw as raw_ansi table = self.styled_table(border="header") for item in items: - table.add_row("|C%s|n" % item.name, item.db.desc or "") - string = "|wYou are carrying:\n%s" % table + table.add_row(f"|C{item.name}|n", + "{}|n".format(utils.crop(raw_ansi(item.db.desc), width=50) or "")) + string = f"|wYou are carrying:\n{table}" self.caller.msg(string) diff --git a/evennia/contrib/tutorial_world/intro_menu.py b/evennia/contrib/tutorial_world/intro_menu.py index 6d886d06e0..f35b49a52f 100644 --- a/evennia/contrib/tutorial_world/intro_menu.py +++ b/evennia/contrib/tutorial_world/intro_menu.py @@ -1,9 +1,14 @@ """ -Game tutor +Intro menu / game tutor Evennia contrib - Griatch 2020 -This contrib is a tutorial menu using the EvMenu menu-templating system. +This contrib is an intro-menu for general MUD and evennia usage using the +EvMenu menu-templating system. + +EvMenu templating is a way to create a menu using a string-format instead +of creating all nodes manually. Of course, for full functionality one must +still create the goto-callbacks. """ @@ -11,24 +16,92 @@ from evennia import create_object from evennia import CmdSet from evennia.utils.evmenu import parse_menu_template, EvMenu -# goto callables +# Goto callbacks and helper resources for the menu def do_nothing(caller, raw_string, **kwargs): + """ + Re-runs the current node + """ return None + def send_testing_tagged(caller, raw_string, **kwargs): - caller.msg(("This is a message tagged with 'testing' and " - "should appear in the pane you selected!\n " - f"You wrote: '{raw_string}'", {"type": "testing"})) - return None + """ + Test to send a message to a pane tagged with 'testing' in the webclient. -def send_string(caller, raw_string, **kwargs): - caller.msg(raw_string) + """ + caller.msg( + ( + "This is a message tagged with 'testing' and " + "should appear in the pane you selected!\n " + f"You wrote: '{raw_string}'", + {"type": "testing"}, + ) + ) return None -# resources for the look-demo +# Resources for the first help-command demo + + +class DemoCommandSetHelp(CmdSet): + """ + Demo the help command + """ + + key = "Help Demo Set" + priority = 2 + + def at_cmdset_creation(self): + from evennia import default_cmds + + self.add(default_cmds.CmdHelp()) + + +def goto_command_demo_help(caller, raw_string, **kwargs): + "Sets things up before going to the help-demo node" + _maintain_demo_room(caller, delete=True) + caller.cmdset.remove(DemoCommandSetRoom) + caller.cmdset.remove(DemoCommandSetComms) + caller.cmdset.add(DemoCommandSetHelp) # TODO - make persistent + return kwargs.get("gotonode") or "command_demo_help" + + +# Resources for the comms demo + + +class DemoCommandSetComms(CmdSet): + """ + Demo communications + """ + + key = "Color Demo Set" + priority = 2 + no_exits = True + no_objs = True + + def at_cmdset_creation(self): + from evennia import default_cmds + + self.add(default_cmds.CmdHelp()) + self.add(default_cmds.CmdSay()) + self.add(default_cmds.CmdPose()) + self.add(default_cmds.CmdPage()) + self.add(default_cmds.CmdColorTest()) + + +def goto_command_demo_comms(caller, raw_string, **kwargs): + """ + Setup and go to the color demo node. + """ + caller.cmdset.remove(DemoCommandSetHelp) + caller.cmdset.remove(DemoCommandSetRoom) + caller.cmdset.add(DemoCommandSetComms) + return kwargs.get("gotonode") or "comms_demo_start" + + +# Resources for the room demo _ROOM_DESC = """ This is a small and comfortable wood cabin. Bright sunlight is shining in @@ -111,6 +184,7 @@ This is a fist-sized stone covered in runes: """ + def _maintain_demo_room(caller, delete=False): """ Handle the creation/cleanup of demo assets. We store them @@ -135,98 +209,95 @@ def _maintain_demo_room(caller, delete=False): del caller.db.tutorial_world_demo_room_data elif not roomdata: # create and describe the cabin and box - room1 = create_object("evennia.objects.objects.DefaultRoom", - key="A small, cozy cabin") + room1 = create_object("evennia.objects.objects.DefaultRoom", key="A small, cozy cabin") room1.db.desc = _ROOM_DESC.strip() - box = create_object("evennia.objects.objects.DefaultObject", - key="small wooden box") + box = create_object( + "evennia.objects.objects.DefaultObject", key="small wooden box", location=room1 + ) box.db.desc = _BOX_DESC.strip() - box.location = room1 # create and describe the meadow and stone - room2 = create_object("evennia.objects.objects.DefaultRoom", - key="A lush summer meadow") + room2 = create_object("evennia.objects.objects.DefaultRoom", key="A lush summer meadow") room2.db.desc = _MEADOW_DESC.strip() - stone = create_object("evennia.objects.objects.DefaultObject", - key="carved stone") + stone = create_object( + "evennia.objects.objects.DefaultObject", key="carved stone", location=room2 + ) stone.db.desc = _STONE_DESC.strip() # make the linking exits - door_out = create_object("evennia.objects.objects.DefaultExit", - key="Door", - location=room1, - destination=room2) + door_out = create_object( + "evennia.objects.objects.DefaultExit", key="Door", location=room1, destination=room2 + ) door_out.db.desc = _DOOR_DESC_OUT.strip() - door_in = create_object("evennia.objects.objects.DefaultExit", - key="entrance to the cabin", - aliases=["door", "in"], - location=room2, - destination=room1) + door_in = create_object( + "evennia.objects.objects.DefaultExit", + key="entrance to the cabin", + aliases=["door", "in", "entrance"], + location=room2, + destination=room1, + ) door_in.db.desc = _DOOR_DESC_IN.strip() # store references for easy removal later - caller.db.tutorial_world_demo_room_data = (caller.location, - room1, box, - room2, stone, - door_out, door_in) + caller.db.tutorial_world_demo_room_data = ( + caller.location, + room1, + box, + room2, + stone, + door_out, + door_in, + ) # move caller into room caller.location = room1 + class DemoCommandSetRoom(CmdSet): """ - Demo the `look` command. + Demo some general in-game commands command. """ - key = "cmd_demo_cmdset_room" + + key = "Room Demo Set" priority = 2 no_exits = False no_objs = False def at_cmdset_creation(self): from evennia import default_cmds + self.add(default_cmds.CmdHelp()) self.add(default_cmds.CmdLook()) self.add(default_cmds.CmdGet()) self.add(default_cmds.CmdDrop()) + self.add(default_cmds.CmdInventory()) self.add(default_cmds.CmdExamine()) self.add(default_cmds.CmdPy()) + def goto_command_demo_room(caller, raw_string, **kwargs): - """Generate a little 2-room environment for testing out some commands.""" + """ + Setup and go to the demo-room node. Generates a little 2-room environment + for testing out some commands. + """ _maintain_demo_room(caller) - caller.cmdset.remove(DemoCommandSetRoom) + caller.cmdset.remove(DemoCommandSetHelp) + caller.cmdset.remove(DemoCommandSetComms) caller.cmdset.add(DemoCommandSetRoom) # TODO - make persistent return "command_demo_room" -# resources for the general command demo -class DemoCommandSetHelp(CmdSet): - """ - Demo other commands. - """ - key = "cmd_demo_cmdset_help" - priority = 2 +# register all callables that can be used in the menu template - def at_cmdset_creation(self): - from evennia import default_cmds - self.add(default_cmds.CmdHelp()) +GOTO_CALLABLES = { + "send_testing_tagged": send_testing_tagged, + "do_nothing": do_nothing, + "goto_command_demo_help": goto_command_demo_help, + "goto_command_demo_comms": goto_command_demo_comms, + "goto_command_demo_room": goto_command_demo_room, +} -def goto_command_demo_help(caller, raw_string, **kwargs): - _maintain_demo_room(caller, delete=True) - caller.cmdset.remove(DemoCommandSetRoom) - caller.cmdset.add(DemoCommandSetHelp) # TODO - make persistent - return "command_demo_help" - - -def command_passthrough(caller, raw_string, **kwargs): - cmd = kwargs.get("cmd") - on_success = kwargs.get('on_success') - if cmd: - caller.execute_cmd(cmd) - else: - caller.execute_cmd(raw_string) - return on_success - +# Main menu definition MENU_TEMPLATE = """ @@ -245,7 +316,10 @@ Write |wnext|n to continue or select a number to jump to that lesson. 1 (next);1;next;n: About Evennia -> about_evennia 2: What is a MUD/MU*? -> about_muds 3: Using the webclient -> using webclient - 4: Playing the game -> goto_command_demo_help() + 4: The help command -> goto_command_demo_help() + 5: Communicating with others -> goto_command_demo_help(gotonode='talk on channels') + 6: Using colors -> goto_command_demo_comms(gotonode='testing_colors') + 7: Moving and exploring -> goto_command_demo_room() # --------------------------------------------------------------------------------- @@ -271,7 +345,7 @@ to graphical MMORPG-style games like World of Warcraft. back;b: About Evennia -> about_evennia next;n: Using the webclient -> using webclient - back to top;t: start + back to start;start;t: start >: using webclient # --------------------------------------------------------------------------------- @@ -299,10 +373,10 @@ There is also some |wextra|n info to learn about customizing the webclient. ## OPTIONS - back: About MUDs -> about_muds + back;b: About MUDs -> about_muds extra: Customizing the webclient -> customizing the webclient - next: Playing the game -> goto_command_demo_help() - back to top: start + next;n: Playing the game -> goto_command_demo_help() + back to start;start: start >: goto_command_demo_help() # --------------------------------------------------------------------------------- @@ -334,7 +408,7 @@ to a web client pane with a specific tag that you set yourself. ## OPTIONS - back: using webclient + back;b: using webclient > test *: send tagged message to new pane -> send_testing_tagged() # --------------------------------------------------------------------------------- @@ -357,21 +431,21 @@ At the moment you only have |whelp|n and some |wChannel Names|n (the '