Extend spawn command (#1777)

* add missing EntityTypes

* small command refactorings and improvements
* move common command patterns and methods to CommandHelpers
* let the spawn command detect the entityType instead of spawning every entity as EntityVehicle
* add extra options for spawning gadgets for better debuging and testing

* More spawn command additions and cleanups+EntityVehicle changes
* Moved remaining patterns from GiveCommand and ClearCommand to CommandHelpers
* Added patterns for hp, maxhp, atk, def and (monster)ai for the spawn command
* Moved intParam parsing via regex to the CommandHelpers
* Read most of EntityVehicle stats from the ConfigGadget instead of hardcoding them

Co-authored-by: hartie95 <mail@hartie95.de>
This commit is contained in:
Alexander Hartmann
2022-09-16 19:04:20 +02:00
committed by GitHub
Unverified
parent 9671a76af2
commit 08f361954a
9 changed files with 298 additions and 169 deletions
@@ -6,35 +6,34 @@ import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import lombok.Setter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static emu.grasscutter.command.CommandHelpers.*;
@Command(
label = "clear",
usage = {"(all|wp|art|mat) [lv<max level>] [r<max refinement>] [<max rarity>*]"},
permission = "player.clearinv",
permissionTargeted = "player.clearinv.others")
public final class ClearCommand implements CommandHandler {
private static Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java doesn't have raw string literals :(
private static Pattern refineRegex = Pattern.compile("r(\\d+)");
private static Pattern rankRegex = Pattern.compile("(\\d+)\\*");
private static int matchIntOrNeg(Pattern pattern, String arg) {
Matcher match = pattern.matcher(arg);
if (match.find()) {
return Integer.parseInt(match.group(1)); // This should be exception-safe as only \d+ can be passed to it (i.e. non-empty string of pure digits)
}
return -1;
}
private static final Map<Pattern, BiConsumer<ClearItemParameters, Integer>> intCommandHandlers = Map.ofEntries(
Map.entry(lvlRegex, ClearItemParameters::setLvl),
Map.entry(refineRegex, ClearItemParameters::setRefinement),
Map.entry(rankRegex, ClearItemParameters::setRank)
);
private static class ClearItemParameters {
public int lvl = 1;
public int refinement = 1;
public int rank = 4;
};
@Setter public int lvl = 1;
@Setter public int refinement = 1;
@Setter public int rank = 4;
}
private Stream<GameItem> getOther(ItemType type, Inventory playerInventory, ClearItemParameters param) {
return playerInventory.getItems().values().stream()
@@ -59,28 +58,8 @@ public final class ClearCommand implements CommandHandler {
Inventory playerInventory = targetPlayer.getInventory();
ClearItemParameters param = new ClearItemParameters();
// Extract any tagged arguments (e.g. "lv90", "x100", "r5")
for (int i = args.size() - 1; i >= 0; i--) { // Reverse iteration as we are deleting elements
String arg = args.get(i).toLowerCase();
boolean deleteArg = false;
int argNum;
// Note that a single argument can actually match all of these, e.g. "lv90r5*"
if ((argNum = matchIntOrNeg(lvlRegex, arg)) != -1) {
param.lvl = argNum;
deleteArg = true;
}
if ((argNum = matchIntOrNeg(refineRegex, arg)) != -1) {
param.refinement = argNum;
deleteArg = true;
}
if ((argNum = matchIntOrNeg(rankRegex, arg)) != -1) {
param.rank = argNum;
deleteArg = true;
}
if (deleteArg) {
args.remove(i);
}
}
// Extract any tagged int arguments (e.g. "lv90", "x100", "r5")
parseIntParameters(args, param, intCommandHandlers);
if (args.size() < 1) {
sendUsageMessage(sender);