From b475ce92896e32977cdafc11f680eff330d1d3f9 Mon Sep 17 00:00:00 2001 From: FlutterSprite Date: Sun, 3 Jun 2018 02:52:16 -0700 Subject: [PATCH] More functionality + cleanup --- evennia/contrib/fieldfill.py | 128 ++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 39 deletions(-) diff --git a/evennia/contrib/fieldfill.py b/evennia/contrib/fieldfill.py index c1fdb9c10f..071558c88c 100644 --- a/evennia/contrib/fieldfill.py +++ b/evennia/contrib/fieldfill.py @@ -2,7 +2,7 @@ Fyield Fyill """ -from evennia.utils import evmenu, evtable, delay +from evennia.utils import evmenu, evtable, delay, list_to_string from evennia import Command from evennia.server.sessionhandler import SESSIONS @@ -20,9 +20,8 @@ Optional: default - Initial value (blank if not given) blankmsg - Message to show when field is blank cantclear - Field can't be cleared if True + required - If True, form cannot be submitted while field is blank verifyfunc - Name of a callable used to verify input - preformtxt - Text to put before the whole form table. Can be put in any field. - postformtxt - Text to put after the whole form table. Can be put in any field. """ @@ -48,7 +47,7 @@ class FieldEvMenu(evmenu.EvMenu): return nodetext -def init_fill_field(formtemplate, caller, callback): +def init_fill_field(formtemplate, caller, callback, pretext="", posttext="", submitcmd="submit", borderstyle="cells"): """ Presents a player with a fillable form. """ @@ -59,7 +58,11 @@ def init_fill_field(formtemplate, caller, callback): kwargs = { "formdata":blank_formdata, "formtemplate": formtemplate, - "callback": callback + "callback": callback, + "pretext": pretext, + "posttext": posttext, + "submitcmd": submitcmd, + "borderstyle": borderstyle } # Initialize menu of selections @@ -70,31 +73,62 @@ def menunode_fieldfill(caller, raw_string, **kwargs): """ Repeating node to fill a menu field """ - # Syntax error goes here - syntax_err = "Syntax: = |/Or: clear , help, show, quit" # Retrieve menu info formdata = caller.ndb._menutree.formdata formtemplate = caller.ndb._menutree.formtemplate callback = caller.ndb._menutree.callback + pretext = caller.ndb._menutree.pretext + posttext = caller.ndb._menutree.posttext + submitcmd = caller.ndb._menutree.submitcmd + borderstyle = caller.ndb._menutree.borderstyle + + # Syntax error + syntax_err = "Syntax: = |/Or: clear , help, show, quit|/'%s' to submit form" % submitcmd + + # Set help text, including listing the 'submit' command + help_text = """Available commands: +|w = :|n Set given field to new value, replacing the old value +|wclear :|n Clear the value in the given field, making it blank +|wshow|n: Show the form's current values +|whelp|n: Display this help screen +|wquit|n: Quit the form menu without submitting +|w%s|n: Submit this form and quit the menu""" % submitcmd # Display current form data - text = display_formdata(formtemplate, formdata) + text = (display_formdata(formtemplate, formdata, pretext=pretext, + posttext=posttext, borderstyle=borderstyle), help_text) options = ({"key": "_default", "goto":"menunode_fieldfill"}) if raw_string: - # Test for 'submit' command - if raw_string.lower().strip() == "submit": + # Test for given 'submit' command + if raw_string.lower().strip() == submitcmd: + # Test to see if any blank fields are required + blank_and_required = [] + for field in formtemplate: + if "required" in field.keys(): + # If field is required but current form data for field is blank + if field["required"] == True and formdata[field["fieldname"]] == None: + # Add to blank and required fields + blank_and_required.append(field["fieldname"]) + if len(blank_and_required) > 0: + caller.msg("The following blank fields require a value: %s" % list_to_string(blank_and_required)) + text = (None, help_text) + return text, options + + # If everything checks out, pass form data to the callback and end the menu! callback(caller, formdata) return None, None + # Test for 'show' command if raw_string.lower().strip() == "show": return text, options + # Test for 'clear' command cleartest = raw_string.lower().strip().split(" ", 1) if cleartest[0].lower() == "clear": - text = None + text = (None, help_text) if len(cleartest) < 2: caller.msg(syntax_err) return text, options @@ -106,7 +140,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): if not matched_field: caller.msg("Field '%s' does not exist!" % cleartest[1]) - text = None + text = (None, help_text) return text, options # Test to see if field can be cleared @@ -114,7 +148,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): if field["fieldname"] == matched_field and "cantclear" in field.keys(): if field["cantclear"] == True: caller.msg("Field '%s' can't be cleared!" % matched_field) - text = None + text = (None, help_text) return text, options @@ -125,7 +159,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): return text, options if "=" not in raw_string: - text = None + text = (None, help_text) caller.msg(syntax_err) return text, options @@ -137,7 +171,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): # Syntax error of field name is too short or blank if len(fieldname) < 3: caller.msg(syntax_err) - text = None + text = (None, help_text) return text, options # Attempt to match field name to field in form data @@ -149,7 +183,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): # No matched field if matched_field == None: caller.msg("Field '%s' does not exist!" % fieldname) - text = None + text = (None, help_text) return text, options # Set new field value if match @@ -175,12 +209,12 @@ def menunode_fieldfill(caller, raw_string, **kwargs): if max_value != None: if len(newvalue) > max_value: caller.msg("Field '%s' has a maximum length of %i characters." % (matched_field, max_value)) - text = None + text = (None, help_text) return text, options if min_value != None: if len(newvalue) < min_value: caller.msg("Field '%s' reqiures a minimum length of %i characters." % (matched_field, min_value)) - text = None + text = (None, help_text) return text, options # Field type number update @@ -189,13 +223,13 @@ def menunode_fieldfill(caller, raw_string, **kwargs): newvalue = int(newvalue) except: caller.msg("Field '%s' requires a number." % matched_field) - text = None + text = (None, help_text) return text, options # Call verify function if present if verifyfunc: if verifyfunc(caller, newvalue) == False: - text = None + text = (None, help_text) return text, options elif verifyfunc(caller, newvalue) != True: newvalue = verifyfunc(caller, newvalue) @@ -204,7 +238,7 @@ def menunode_fieldfill(caller, raw_string, **kwargs): formdata.update({matched_field:newvalue}) caller.ndb._menutree.formdata = formdata caller.msg("Field '%s' set to: %s" % (matched_field, str(newvalue))) - text = None + text = (None, help_text) return text, options @@ -223,11 +257,13 @@ def form_template_to_dict(formtemplate): return formdict -def display_formdata(formtemplate, formdata): +def display_formdata(formtemplate, formdata, + pretext="", posttext="", borderstyle="cells"): """ Displays a form's current data as a table """ - formtable = evtable.EvTable(border="cells", valign="t", maxwidth=80) + + formtable = evtable.EvTable(border=borderstyle, valign="t", maxwidth=80) field_name_width = 5 for field in formtemplate: @@ -250,17 +286,8 @@ def display_formdata(formtemplate, formdata): formtable.reformat_column(0, align="r", width=field_name_width) # formtable.reformat_column(1, pad_left=0) - - # Get pre-text and/or post-text - pretext = "" - posttext = "" - for field in formtemplate: - if "preformtxt" in field: - pretext = field["preformtxt"] + "|/" - if "postformtxt" in field: - posttext = "|/" + field["postformtxt"] - return pretext + str(formtable) + posttext + return pretext + "|/" + str(formtable) + "|/" + posttext @@ -272,22 +299,35 @@ def verify_online_player(caller, value): session_list = SESSIONS.get_sessions() char_list = [] matched_character = None + + # Get a list of online characters for session in session_list: if not session.logged_in: + # Skip over logged out characters continue + # Append to our list of online characters otherwise char_list.append(session.get_puppet()) - print char_list + + # Match player input to a character name for character in char_list: - if value.lower() in character.key.lower(): + if value.lower() == character.key.lower(): matched_character = character + + # If input didn't match to a character if not matched_character: + # Send the player an error message unique to this function caller.msg("No character matching '%s' is online." % value) + # Returning False indicates the new value is not valid return False + + # Returning anything besides True or False will replace the player's input with the returned value + # In this case, the value becomes a reference to the character object + # You can store data besides strings and integers in the 'formdata' dictionary this way! return matched_character SAMPLE_FORM = [ -{"fieldname":"Player", "fieldtype":"text", "max":30, "blankmsg":"(Name of an online player)", "verifyfunc":verify_online_player, - "preformtxt":"Send a delayed message to another player:", "postformtxt":"Syntax: = |/Or: clear , help, show, quit"}, +{"fieldname":"Character", "fieldtype":"text", "max":30, "blankmsg":"(Name of an online player)", + "required":True, "verifyfunc":verify_online_player}, {"fieldname":"Delay", "fieldtype":"number", "min":3, "max":30, "default":10, "cantclear":True}, {"fieldname":"Message", "fieldtype":"text", "min":3, "max":200, "blankmsg":"(Message up to 200 characters)"} ] @@ -311,16 +351,26 @@ class CmdTestMenu(Command): key = "testmenu" def func(self): - init_fill_field(SAMPLE_FORM, self.caller, init_delayed_message) + + pretext = "|cSend a delayed message to another player ---------------------------------------|n" + posttext = ("|c--------------------------------------------------------------------------------|n|/" + "Syntax: type |c = |n to change the values of the form. Given|/" + "player must be currently logged in, delay is given in seconds. When you are|/" + "finished, type '|csend|n' to send the message.|/") + + init_fill_field(SAMPLE_FORM, self.caller, init_delayed_message, + pretext=pretext, posttext=posttext, + submitcmd="send", borderstyle="none") def sendmessage(obj, text): obj.msg(text) def init_delayed_message(caller, formdata): - player_to_message = formdata["Player"] + player_to_message = formdata["Character"] message_delay = formdata["Delay"] message = ("Message from %s: " % caller) + formdata["Message"] + caller.msg("Message sent to %s!" % player_to_message) deferred = delay(message_delay, sendmessage, player_to_message, message) return