Fix parsing issues in dice contrib. Resolve #3858

This commit is contained in:
Griatch 2026-02-14 09:13:25 +01:00
parent 661615a844
commit 7480772404
3 changed files with 37 additions and 12 deletions

View file

@ -26,6 +26,7 @@
- [Fix][pull3853]: Properly handle multimatch separations with native dashes, like
't-shirt-1' (count-infinity)
- [Fix][pull3733]: Allow `CmdSetAttribute` to use categery, view dicts by key (InspectorCaracal)
- [Fix][issue3858]: Fix parsing issues in dice contrib (Griatch)
- [Doc][pull3801]: Move Evennia doc build system to latest Sphinx/myST
(PowershellNinja, also honorary mention to electroglyph)
- [Doc][pull3800]: Describe support for Telnet SSH in HAProxy documentation (holl0wstar)
@ -53,6 +54,7 @@
[pull3853]: https://github.com/evennia/evennia/pull/3853
[pull3854]: https://github.com/evennia/evennia/pull/3853
[pull3733]: https://github.com/evennia/evennia/pull/3853
[issue3858]: https://github.com/evennia/evennia/issues/3858
## Evennia 5.0.1

View file

@ -253,8 +253,10 @@ class CmdDice(default_cmds.MuxCommand):
def func(self):
"""Mostly parsing for calling the dice roller function"""
helptxt = "Usage: @dice <nr>d<sides> [modifier] [conditional]"
if not self.args:
self.caller.msg("Usage: @dice <nr>d<sides> [modifier] [conditional]")
self.caller.msg(helptxt)
return
argstring = "".join(str(arg) for arg in self.args)
@ -264,36 +266,48 @@ class CmdDice(default_cmds.MuxCommand):
conditional = None
if len_parts < 3 or parts[1] != "d":
self.caller.msg(
"You must specify the die roll(s) as <nr>d<sides>."
" For example, 2d6 means rolling a 6-sided die 2 times."
)
self.caller.msg(f"Malformed input. {helptxt}")
return
# Limit the number of dice and sides a character can roll to prevent server slow down and crashes
ndicelimit = 10000 # Maximum number of dice
nsidelimit = 10000 # Maximum number of sides
if int(parts[0]) > ndicelimit or int(parts[2]) > nsidelimit:
self.caller.msg("The maximum roll allowed is %sd%s." % (ndicelimit, nsidelimit))
try:
if int(parts[0]) > ndicelimit or int(parts[2]) > nsidelimit:
self.caller.msg("The maximum roll allowed is %sd%s." % (ndicelimit, nsidelimit))
return
except ValueError:
self.caller.msg(f"Malformed input. {helptxt}")
return
ndice, nsides = parts[0], parts[2]
if len_parts == 3:
# just something like 1d6
ndice, nsides = parts[0], parts[2]
pass
elif len_parts == 5:
# either e.g. 1d6 + 3 or something like 1d6 > 3
ndice, nsides = parts[0], parts[2]
if parts[3] in ("+", "-", "*", "/"):
modifier = (parts[3], parts[4])
else: # assume it is a conditional
elif parts[3] in ("<", ">", "<=", ">=", "!=", "=="):
conditional = (parts[3], parts[4])
else:
self.caller.msg(f"Malformed input. {helptxt}")
return
elif len_parts == 7:
# the whole sequence, e.g. 1d6 + 3 > 5
modifier = (parts[3], parts[4])
conditional = (parts[5], parts[6])
ndice, nsides = parts[0], parts[2]
err = parts[3] not in ("+", "-", "*", "/")
err = err or parts[5] not in ("<", ">", "<=", ">=", "!=", "==")
if err:
self.caller.msg(f"Malformed input. {helptxt}")
return
else:
modifier = (parts[3], parts[4])
conditional = (parts[5], parts[6])
else:
# error
self.caller.msg("You must specify a valid die roll")
self.caller.msg(f"Malformed input. {helptxt}")
return
# do the roll
try:

View file

@ -35,3 +35,12 @@ class TestDice(BaseEvenniaCommandTest):
dice.roll(11, 1001, max_dicenum=10, max_dicetype=1000)
with self.assertRaises(TypeError):
dice.roll(10, 1001, max_dicenum=10, max_dicetype=1000)
def test_malformed_inputs(self, mocked_randint):
self.call(dice.CmdDice(), "d6", "Malformed input.")
self.call(dice.CmdDice(), "3d", "Malformed input.")
self.call(dice.CmdDice(), "3d6 +", "Malformed input.")
self.call(dice.CmdDice(), "3d6 -", "Malformed input.")
self.call(dice.CmdDice(), "foo 3d6 + 2", "Malformed input.")
self.call(dice.CmdDice(), "3d6 + 2 + 2", "Malformed input.")
self.call(dice.CmdDice(), "3d6 foo 2", "Malformed input.")