command.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. """
  2. Commands
  3. Commands describe the input the account can do to the game.
  4. """
  5. import re
  6. import random
  7. from evennia import utils, default_cmds, create_script, logger
  8. from evennia.utils import evtable
  9. from evennia.contrib.health_bar import display_meter
  10. from evennia.utils import inherits_from
  11. from evennia.utils.utils import list_to_string
  12. from evennia.utils.eveditor import EvEditor
  13. from utils.building import create_exit
  14. from utils.utils import has_tag, fmt_light, fmt_dark, toggle_effect, has_effect, indefinite_article
  15. from typeclasses.exits import BaseDoor
  16. from typeclasses.rooms import IndoorRoom
  17. from typeclasses.objects import Item, EquippableItem
  18. from typeclasses.scripts import Script, CmdActionScript
  19. CMD_SEARCH_TIME = 5
  20. class Command(default_cmds.MuxCommand):
  21. """
  22. Inherit from this if you want to create your own command styles
  23. from scratch. Note that Evennia's default commands inherits from
  24. MuxCommand instead.
  25. Note that the class's `__doc__` string (this text) is
  26. used by Evennia to create the automatic help entry for
  27. the command, so make sure to document consistently here.
  28. Each Command implements the following methods, called
  29. in this order (only func() is actually required):
  30. - at_pre_cmd(): If this returns anything truthy, execution is aborted.
  31. - parse(): Should perform any extra parsing needed on self.args
  32. and store the result on self.
  33. - func(): Performs the actual work.
  34. - at_post_cmd(): Extra actions, often things done after
  35. every command, like prompts.
  36. """
  37. def parse(self):
  38. """
  39. We need to expand the default parsing to get all
  40. the cases, see the module doc.
  41. """
  42. # get all the normal parsing done (switches etc)
  43. super().parse()
  44. obj_defs = ([], []) # stores left- and right-hand side of '='
  45. obj_attrs = ([], []) # "
  46. for iside, arglist in enumerate((self.lhslist, self.rhslist)):
  47. # lhslist/rhslist is already split by ',' at this point
  48. for objdef in arglist:
  49. aliases, option, attrs = [], None, []
  50. if ":" in objdef:
  51. objdef, option = [part.strip() for part in objdef.rsplit(":", 1)]
  52. if ";" in objdef:
  53. objdef, aliases = [part.strip() for part in objdef.split(";", 1)]
  54. aliases = [alias.strip() for alias in aliases.split(";") if alias.strip()]
  55. if "/" in objdef:
  56. objdef, attrs = [part.strip() for part in objdef.split("/", 1)]
  57. attrs = [part.strip().lower() for part in attrs.split("/") if part.strip()]
  58. # store data
  59. obj_defs[iside].append({"name": objdef, "option": option, "aliases": aliases})
  60. obj_attrs[iside].append({"name": objdef, "attrs": attrs})
  61. # store for future access
  62. self.lhs_objs = obj_defs[0]
  63. self.rhs_objs = obj_defs[1]
  64. self.lhs_objattr = obj_attrs[0]
  65. self.rhs_objattr = obj_attrs[1]
  66. def at_post_cmd(self):
  67. caller = self.caller
  68. prompt = "|_|/°|w%s|n°: " % (caller.location)
  69. caller.msg(prompt=prompt)
  70. # overloading the look command with our custom MuxCommand with at_post_cmd hook
  71. class CmdLook(default_cmds.CmdLook, Command):
  72. pass
  73. class CmdDrop(default_cmds.CmdDrop, Command):
  74. pass
  75. class CmdGet(Command):
  76. """
  77. pick up something
  78. Usage:
  79. get <obj> [from <container>]
  80. Picks up an object from your location and puts it in
  81. your inventory.
  82. """
  83. key = "get"
  84. aliases = "grab"
  85. locks = "cmd:all()"
  86. arg_regex = r"\s|$"
  87. def parse(self):
  88. """
  89. Handle parsing of:
  90. <object> [FROM <container>]
  91. """
  92. self.args = args = self.args.strip().lower()
  93. if "from" in args:
  94. obj, *rest = args.split(" from ", 1)
  95. container = rest[0] if rest else ""
  96. else:
  97. obj = self.args
  98. container = ""
  99. self.obj_name = obj.strip()
  100. self.container_name = container.strip()
  101. def func(self):
  102. """implements the command."""
  103. caller = self.caller
  104. if not self.args or not self.obj_name:
  105. caller.msg("Get what?")
  106. return
  107. if inherits_from(caller.location, IndoorRoom) and not caller.location.db.is_lit and not caller.is_superuser:
  108. caller.msg("Its too dark to get anything.")
  109. return
  110. if self.container_name:
  111. container = caller.search(self.container_name, location=caller.location)
  112. obj = caller.search(self.obj_name, location=container)
  113. else:
  114. obj = caller.search(self.obj_name, location=caller.location)
  115. if not obj:
  116. return
  117. if caller == obj:
  118. caller.msg("You can't get yourself.")
  119. return
  120. if not obj.access(caller, "get"):
  121. if obj.db.get_err_msg:
  122. caller.msg(obj.db.get_err_msg)
  123. else:
  124. caller.msg("You can't get that.")
  125. return
  126. # calling at_before_get hook method
  127. if not obj.at_before_get(caller):
  128. return
  129. success = obj.move_to(caller, quiet=True)
  130. if not success:
  131. caller.msg("This can't be picked up.")
  132. else:
  133. caller.msg("You pick up %s." % obj.name)
  134. caller.location.msg_contents(
  135. "%s picks up %s." % (caller.name, obj.name), exclude=caller
  136. )
  137. # calling at_get hook method
  138. obj.at_get(caller)
  139. class CmdCharacter(Command):
  140. """
  141. Show character sheet.
  142. Usage:
  143. character
  144. Displays a list of your current ability values.
  145. """
  146. key = "character"
  147. aliases = ["char"]
  148. lock = "cmd:all()"
  149. help_category = "General"
  150. def func(self):
  151. self.caller.msg(
  152. '\u250B|w' + " {0:27}".format(self.caller.name,) + '|n\u250B|/')
  153. self.caller.msg('-HEALTH' + '-' * 23)
  154. meter = display_meter(self.caller.get_health(), 100,
  155. empty_color="222", align="center", fill_color=["R"])
  156. self.caller.msg(meter)
  157. self.caller.msg('-MANA' + '-' * 25)
  158. meter = display_meter(self.caller.get_mana(), 100,
  159. empty_color="222", align="center", fill_color=["B"])
  160. self.caller.msg(meter + '|/')
  161. str, agi, intel = self.caller.get_abilities()
  162. table = evtable.EvTable(border="tablecols")
  163. table.add_column("STRENGTH", "AGILITY",
  164. "INTELLECT", header="Attributes")
  165. table.add_column("|g%03d|n/100" % str, "|g%03d|n/100" %
  166. agi, "|g%03d|n/100" % intel, header="")
  167. self.caller.msg(table)
  168. class CmdLight(Command):
  169. """
  170. A command to light objects that support it.
  171. Usage:
  172. light <someone>
  173. Light an object in your inventory.
  174. """
  175. key = "light"
  176. aliases = []
  177. lock = "cmd:all()"
  178. help_category = "General"
  179. arg_regex = r"(?:^(?:\s+|\/).*$)|^$"
  180. def func(self):
  181. caller = self.caller
  182. if not self.args:
  183. self.msg("Light what?")
  184. return
  185. else:
  186. target = caller.search(self.args)
  187. if not target:
  188. self.msg("Light what?")
  189. return
  190. if not target.access(caller, 'light'):
  191. self.msg("You cannot do that.")
  192. return
  193. if not has_effect(target, "emit_light"):
  194. toggle_effect(target, "emit_light")
  195. self.msg("You light {}.".format(target.name))
  196. else:
  197. toggle_effect(target, "emit_light")
  198. self.msg("You put off {}.".format(target.name))
  199. if caller.location and inherits_from(caller.location, IndoorRoom):
  200. caller.location.check_light_state()
  201. class CmdSearch(Command):
  202. """
  203. """
  204. key = "search"
  205. aliases = ["ss"]
  206. locks = "cmd:all()"
  207. help_category = "General"
  208. arg_regex = r"(?:^(?:\s+|\/).*$)|^$"
  209. def func(self):
  210. caller = self.caller
  211. if has_effect(caller, "is_busy"):
  212. caller.msg("You are already busy {}.".format(caller.db.current_action.busy_msg()))
  213. return
  214. if not self.args:
  215. target = caller.location
  216. if not target:
  217. caller.msg("You have no location to search!")
  218. return
  219. else:
  220. target = caller.search(self.args)
  221. if not target:
  222. caller.msg("You cannot search {}!".format(self.args))
  223. return
  224. if target.access(caller, "search"):
  225. toggle_effect(caller, "is_busy")
  226. caller.msg("You search {}.".format(target.get_display_name(caller)))
  227. action_script = create_script("commands.command.CmdSearchComplete", obj=caller, interval=CMD_SEARCH_TIME, attributes=[("target", self.args)])
  228. caller.db.current_action = action_script
  229. else:
  230. caller.msg("You cannot search {}!".format(target.get_display_name(caller)))
  231. class CmdSearchComplete(CmdActionScript):
  232. def at_script_creation(self):
  233. super().at_script_creation()
  234. self.key = "cmd_search_complete"
  235. self.desc = ""
  236. self.db.target = ""
  237. def at_repeat(self):
  238. caller = self.obj
  239. target_string = self.db.target
  240. if has_effect(caller, "is_busy"):
  241. toggle_effect(caller, "is_busy")
  242. if not target_string:
  243. target = caller.location
  244. if not target:
  245. caller.msg("You have no location to search!")
  246. return
  247. else:
  248. target = caller.search(target_string)
  249. if not target:
  250. caller.msg("You cannot search {} anymore!".format(target_string))
  251. return
  252. if target.access(caller, "search"):
  253. items = []
  254. for con in target.contents:
  255. if inherits_from(con, Item) and con.access(caller, "get"):
  256. items.append(con)
  257. if items:
  258. found_item_idx = random.randrange(0, len(items))
  259. found_item = items[found_item_idx]
  260. found_item_name = found_item.get_numbered_name(1, caller)[0]
  261. caller.msg("You find {}.".format(found_item_name))
  262. if not found_item.access(caller, "get"):
  263. if found_item.db.get_err_msg:
  264. caller.msg(found_item.db.get_err_msg)
  265. else:
  266. caller.msg("You can't get that.")
  267. return
  268. # calling at_before_get hook method
  269. if not found_item.at_before_get(caller):
  270. return
  271. success = found_item.move_to(caller, quiet=True)
  272. if not success:
  273. caller.msg("This can't be picked up.")
  274. else:
  275. caller.msg("You pick up %s." % found_item_name)
  276. caller.location.msg_contents(
  277. "%s picks up %s." % (caller.name, found_item_name), exclude=caller
  278. )
  279. # calling at_get hook method
  280. found_item.at_get(caller)
  281. else:
  282. caller.msg("There is nothing to be found here.")
  283. else:
  284. caller.msg("You cannot search {} anymore!".format(target.get_display_name(caller)))
  285. def busy_msg(self):
  286. return "searching {}".format(self.db.target)
  287. class CmdPut(Command):
  288. """
  289. Put an item inside a container
  290. Usage:
  291. put <item> in <container>
  292. """
  293. key = "put"
  294. locks = "cmd:all()"
  295. help_category = "General"
  296. def parse(self):
  297. """
  298. Handle parsing of:
  299. <item> in <container>
  300. """
  301. self.args = args = self.args.strip().lower()
  302. item_name, container_name = "", ""
  303. if " in " in args:
  304. item_name, *rest = args.split(" in ", 1)
  305. container_name = rest[0] if rest else ""
  306. self.item_name = item_name.strip()
  307. self.container_name = container_name.strip()
  308. def func(self):
  309. caller = self.caller
  310. if not self.args or not self.item_name or not self.container_name:
  311. caller.msg("Usage: put <item> in <container>")
  312. return
  313. item = caller.search(self.item_name, typeclass="typeclasses.objects.Item")
  314. if not item:
  315. return
  316. container = caller.search(self.container_name, typeclass="typeclasses.objects.ContainerFeature")
  317. if not container:
  318. return
  319. if not item.access(caller, "get"):
  320. caller.msg("You cannot do that with {}.".format(item.name))
  321. return
  322. if not container.access(caller, "put"):
  323. caller.msg("You cannot access {}.".format(container.name))
  324. return
  325. if has_tag(item, "equipped", "general"):
  326. caller.msg("{} is equipped. Remove it first.".format(item.name))
  327. return
  328. item.move_to(container, use_destination=False)
  329. caller.msg("You put {} inside {}.".format(item.name, container.name))
  330. class CmdOpenCloseDoor(Command):
  331. """
  332. Open and close a door
  333. Usage:
  334. open <door>
  335. close <door>
  336. """
  337. key = "op"
  338. aliases = ["close"]
  339. locks = "cmd:all()"
  340. help_category = "General"
  341. def func(self):
  342. if not self.args:
  343. self.caller.msg("Usage: open||close <door>")
  344. return
  345. door = self.caller.search(self.args)
  346. if not door:
  347. return
  348. if not inherits_from(door, BaseDoor):
  349. self.caller.msg("This is not a door.")
  350. return
  351. if self.cmdstring == "op":
  352. if door.locks.check(self.caller, "traverse"):
  353. self.caller.msg("%s is already open." % door.key)
  354. else:
  355. door.setlock("traverse:true()")
  356. self.caller.msg("You open %s." % door.key)
  357. else: # close
  358. if not door.locks.check(self.caller, "traverse"):
  359. self.caller.msg("%s is already closed." % door.key)
  360. else:
  361. door.setlock("traverse:false()")
  362. self.caller.msg("You close %s." % door.key)
  363. class CmdEquip(Command):
  364. key = "equip"
  365. aliases = ["eq", "remove"]
  366. lock = "cmd:all()"
  367. help_category = "General"
  368. arg_regex = r"\s.+|$"
  369. def func(self):
  370. caller = self.caller
  371. if not self.args:
  372. caller.msg("You cannot do that.")
  373. return
  374. item = caller.search(self.args, location=caller, nofound_string="")
  375. if not item:
  376. caller.msg("You don't have any {}".format(self.args))
  377. return
  378. if inherits_from(item, EquippableItem) and item.access(caller, "equip"):
  379. if self.cmdstring == "remove":
  380. if has_tag(item, "equipped", "general"):
  381. if item.at_unequip(caller, ""):
  382. self.remove(caller, item)
  383. else:
  384. return
  385. else:
  386. caller.msg("{} is not equipped.".format(item.name))
  387. return
  388. else:
  389. if has_tag(item, "equipped", "general"):
  390. caller.msg("{} is already equipped.".format(item.name))
  391. return
  392. slots = [slot for slot in caller.db.equipment.keys() if item.db.slot in slot]
  393. if not slots:
  394. caller.msg("You don't have {} {}".format(indefinite_article(item.db.slot), item.db.slot))
  395. return
  396. selected_slot = slots[0]
  397. # find an empty slot
  398. empty_slots = [slot for slot in slots if not caller.db.equipment[slot]]
  399. if empty_slots:
  400. selected_slot = empty_slots[0]
  401. # remove equipment if slot is already in use
  402. if caller.db.equipment[selected_slot]:
  403. old_equipment = caller.search(caller.db.equipment[selected_slot], location=caller, quiet=True)
  404. if old_equipment:
  405. if old_equipment[0].at_unequip(caller, selected_slot):
  406. self.remove(caller, old_equipment[0])
  407. else:
  408. return
  409. if item.at_equip(caller, selected_slot):
  410. caller.db.equipment[selected_slot] = item.dbref
  411. item.tags.add("equipped", category="general")
  412. caller.msg("You equip |w{}|n on |w{}|n".format(item.name, selected_slot))
  413. caller.location.msg_contents("{} equips |w{}|n on {}".format(caller.name, item.name, selected_slot), exclude=caller)
  414. else:
  415. caller.msg("You cannot equip {}".format(item.name))
  416. def remove(self, caller, item):
  417. selected_slot = [slot for slot in caller.db.equipment.keys() if caller.db.equipment[slot] == item.dbref][0]
  418. caller.msg("You remove {} from {}".format(item, selected_slot))
  419. caller.db.equipment[selected_slot] = None
  420. item.tags.remove("equipped", category="general")
  421. class CmdInventory(Command):
  422. """
  423. view inventory
  424. Usage:
  425. inventory
  426. inv
  427. Shows your inventory.
  428. """
  429. key = "inventory"
  430. aliases = ["inv", "i"]
  431. locks = "cmd:all()"
  432. arg_regex = r"$"
  433. def func(self):
  434. """check inventory"""
  435. items = self.caller.contents
  436. if not items:
  437. string = "You are not carrying anything."
  438. else:
  439. from evennia.utils.ansi import raw as raw_ansi
  440. table = self.styled_table()
  441. for item in items:
  442. effect_string = ""
  443. if has_tag(item, 'equipped', 'general'):
  444. effect_string += "|w⚒|n"
  445. else:
  446. effect_string += "|=a⚒|n"
  447. if has_effect(item, 'emit_light'):
  448. effect_string += "|y☀|n"
  449. else:
  450. effect_string += "|=a☀|n"
  451. table.add_row(
  452. f"|w{item.name}|n",
  453. effect_string,
  454. "{}|n".format(utils.crop(raw_ansi(item.db.desc), width=50) or ""),
  455. )
  456. string = f"|wYou are carrying:\n{table}"
  457. self.caller.msg(string)
  458. class CmdTestPy(Command):
  459. key = "testpy"
  460. aliases = ["testpy"]
  461. lock = "cmd:false()"
  462. help_category = "General"
  463. arg_regex = r"\s.+|$"
  464. def func(self):
  465. caller = self.caller
  466. caller.msg(self.lhs_objs)
  467. pattern = re.compile(r'''((?:[^ "']|"[^"]*"|'[^']*')+)''')
  468. self.args = pattern.split(self.lhs)[1::2]
  469. # room = create_room(self.args[0].strip(" \"'"), int(self.args[1].strip(" \"'")), int(self.args[2].strip(" \"'")), self.args[3].strip(" \"'"))
  470. # caller.msg(room)
  471. # exit = create_exit("exit_empty", caller.location, "north")
  472. # caller.msg(exit)
  473. # caller.msg(dkmud_oob=({"testarg": "valuetestarg"}))
  474. # if not self.args:
  475. # target = caller.location
  476. # if not target:
  477. # caller.msg("You have no location to test!")
  478. # return
  479. # else:
  480. # target = caller.search(self.args)
  481. # if not target:
  482. # return
  483. # -------------------------------------------------------------
  484. #
  485. # The default commands inherit from
  486. #
  487. # evennia.commands.default.muxcommand.MuxCommand.
  488. #
  489. # If you want to make sweeping changes to default commands you can
  490. # uncomment this copy of the MuxCommand parent and add
  491. #
  492. # COMMAND_DEFAULT_CLASS = "commands.command.MuxCommand"
  493. #
  494. # to your settings file. Be warned that the default commands expect
  495. # the functionality implemented in the parse() method, so be
  496. # careful with what you change.
  497. #
  498. # -------------------------------------------------------------
  499. # from evennia.utils import utils
  500. #
  501. #
  502. # class MuxCommand(Command):
  503. # """
  504. # This sets up the basis for a MUX command. The idea
  505. # is that most other Mux-related commands should just
  506. # inherit from this and don't have to implement much
  507. # parsing of their own unless they do something particularly
  508. # advanced.
  509. #
  510. # Note that the class's __doc__ string (this text) is
  511. # used by Evennia to create the automatic help entry for
  512. # the command, so make sure to document consistently here.
  513. # """
  514. # def has_perm(self, srcobj):
  515. # """
  516. # This is called by the cmdhandler to determine
  517. # if srcobj is allowed to execute this command.
  518. # We just show it here for completeness - we
  519. # are satisfied using the default check in Command.
  520. # """
  521. # return super().has_perm(srcobj)
  522. #
  523. # def at_pre_cmd(self):
  524. # """
  525. # This hook is called before self.parse() on all commands
  526. # """
  527. # pass
  528. #
  529. # def at_post_cmd(self):
  530. # """
  531. # This hook is called after the command has finished executing
  532. # (after self.func()).
  533. # """
  534. # pass
  535. #
  536. # def parse(self):
  537. # """
  538. # This method is called by the cmdhandler once the command name
  539. # has been identified. It creates a new set of member variables
  540. # that can be later accessed from self.func() (see below)
  541. #
  542. # The following variables are available for our use when entering this
  543. # method (from the command definition, and assigned on the fly by the
  544. # cmdhandler):
  545. # self.key - the name of this command ('look')
  546. # self.aliases - the aliases of this cmd ('l')
  547. # self.permissions - permission string for this command
  548. # self.help_category - overall category of command
  549. #
  550. # self.caller - the object calling this command
  551. # self.cmdstring - the actual command name used to call this
  552. # (this allows you to know which alias was used,
  553. # for example)
  554. # self.args - the raw input; everything following self.cmdstring.
  555. # self.cmdset - the cmdset from which this command was picked. Not
  556. # often used (useful for commands like 'help' or to
  557. # list all available commands etc)
  558. # self.obj - the object on which this command was defined. It is often
  559. # the same as self.caller.
  560. #
  561. # A MUX command has the following possible syntax:
  562. #
  563. # name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]]
  564. #
  565. # The 'name[ with several words]' part is already dealt with by the
  566. # cmdhandler at this point, and stored in self.cmdname (we don't use
  567. # it here). The rest of the command is stored in self.args, which can
  568. # start with the switch indicator /.
  569. #
  570. # This parser breaks self.args into its constituents and stores them in the
  571. # following variables:
  572. # self.switches = [list of /switches (without the /)]
  573. # self.raw = This is the raw argument input, including switches
  574. # self.args = This is re-defined to be everything *except* the switches
  575. # self.lhs = Everything to the left of = (lhs:'left-hand side'). If
  576. # no = is found, this is identical to self.args.
  577. # self.rhs: Everything to the right of = (rhs:'right-hand side').
  578. # If no '=' is found, this is None.
  579. # self.lhslist - [self.lhs split into a list by comma]
  580. # self.rhslist - [list of self.rhs split into a list by comma]
  581. # self.arglist = [list of space-separated args (stripped, including '=' if it exists)]
  582. #
  583. # All args and list members are stripped of excess whitespace around the
  584. # strings, but case is preserved.
  585. # """
  586. # raw = self.args
  587. # args = raw.strip()
  588. #
  589. # # split out switches
  590. # switches = []
  591. # if args and len(args) > 1 and args[0] == "/":
  592. # # we have a switch, or a set of switches. These end with a space.
  593. # switches = args[1:].split(None, 1)
  594. # if len(switches) > 1:
  595. # switches, args = switches
  596. # switches = switches.split('/')
  597. # else:
  598. # args = ""
  599. # switches = switches[0].split('/')
  600. # arglist = [arg.strip() for arg in args.split()]
  601. #
  602. # # check for arg1, arg2, ... = argA, argB, ... constructs
  603. # lhs, rhs = args, None
  604. # lhslist, rhslist = [arg.strip() for arg in args.split(',')], []
  605. # if args and '=' in args:
  606. # lhs, rhs = [arg.strip() for arg in args.split('=', 1)]
  607. # lhslist = [arg.strip() for arg in lhs.split(',')]
  608. # rhslist = [arg.strip() for arg in rhs.split(',')]
  609. #
  610. # # save to object properties:
  611. # self.raw = raw
  612. # self.switches = switches
  613. # self.args = args.strip()
  614. # self.arglist = arglist
  615. # self.lhs = lhs
  616. # self.lhslist = lhslist
  617. # self.rhs = rhs
  618. # self.rhslist = rhslist
  619. #
  620. # # if the class has the account_caller property set on itself, we make
  621. # # sure that self.caller is always the account if possible. We also create
  622. # # a special property "character" for the puppeted object, if any. This
  623. # # is convenient for commands defined on the Account only.
  624. # if hasattr(self, "account_caller") and self.account_caller:
  625. # if utils.inherits_from(self.caller, "evennia.objects.objects.DefaultObject"):
  626. # # caller is an Object/Character
  627. # self.character = self.caller
  628. # self.caller = self.caller.account
  629. # elif utils.inherits_from(self.caller, "evennia.accounts.accounts.DefaultAccount"):
  630. # # caller was already an Account
  631. # self.character = self.caller.get_puppet(self.session)
  632. # else:
  633. # self.character = None