Fix player fields not being set

line seps r weird
This commit is contained in:
KingRainbow44
2023-04-10 22:46:19 -04:00
parent 5e56b5e3a8
commit 06cbae31fa
453 changed files with 63228 additions and 63071 deletions

View File

@@ -1,158 +1,158 @@
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.achievement.AchievementData;
import emu.grasscutter.game.achievement.AchievementControlReturns;
import emu.grasscutter.game.achievement.Achievements;
import emu.grasscutter.game.player.Player;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
@Command(
label = "achievement",
usage = {
"(grant|revoke) <achievementId>",
"progress <achievementId> <progress>",
"grantall",
"revokeall"
},
aliases = {"am"},
permission = "player.achievement",
permissionTargeted = "player.achievement.others",
targetRequirement = Command.TargetRequirement.PLAYER,
threading = true)
public final class AchievementCommand implements CommandHandler {
private static void sendSuccessMessage(Player sender, String cmd, Object... args) {
CommandHandler.sendTranslatedMessage(
sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args);
}
private static Optional<Integer> parseInt(String s) {
try {
return Optional.of(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) {
var counter = new AtomicInteger();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.filter(AchievementData::isParent)
.forEach(
data -> {
var success = achievements.grant(data.getId());
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
counter.addAndGet(success.getChangedAchievementStatusNum());
}
});
sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname());
}
private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) {
var counter = new AtomicInteger();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.filter(AchievementData::isParent)
.forEach(
data -> {
var success = achievements.revoke(data.getId());
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
counter.addAndGet(success.getChangedAchievementStatusNum());
}
});
sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname());
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
return;
}
var command = args.remove(0).toLowerCase();
var achievements = Achievements.getByPlayer(targetPlayer);
switch (command) {
case "grant" -> this.grant(sender, targetPlayer, achievements, args);
case "revoke" -> this.revoke(sender, targetPlayer, achievements, args);
case "progress" -> this.progress(sender, targetPlayer, achievements, args);
case "grantall" -> grantAll(sender, targetPlayer, achievements);
case "revokeall" -> revokeAll(sender, targetPlayer, achievements);
default -> this.sendUsageMessage(sender);
}
}
private void grant(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
var ret = achievements.grant(integer);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname());
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
case ALREADY_ACHIEVED -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey(), targetPlayer.getNickname());
}
},
() -> this.sendUsageMessage(sender));
}
private void revoke(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
var ret = achievements.revoke(integer);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname());
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
case NOT_YET_ACHIEVED -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey(), targetPlayer.getNickname());
}
},
() -> this.sendUsageMessage(sender));
}
private void progress(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 2) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
parseInt(args.remove(0))
.ifPresentOrElse(
progress -> {
var ret = achievements.progress(integer, progress);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(
sender, "progress", targetPlayer.getNickname(), integer, progress);
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
}
},
() -> this.sendUsageMessage(sender));
},
() -> this.sendUsageMessage(sender));
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.achievement.AchievementData;
import emu.grasscutter.game.achievement.AchievementControlReturns;
import emu.grasscutter.game.achievement.Achievements;
import emu.grasscutter.game.player.Player;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
@Command(
label = "achievement",
usage = {
"(grant|revoke) <achievementId>",
"progress <achievementId> <progress>",
"grantall",
"revokeall"
},
aliases = {"am"},
permission = "player.achievement",
permissionTargeted = "player.achievement.others",
targetRequirement = Command.TargetRequirement.PLAYER,
threading = true)
public final class AchievementCommand implements CommandHandler {
private static void sendSuccessMessage(Player sender, String cmd, Object... args) {
CommandHandler.sendTranslatedMessage(
sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args);
}
private static Optional<Integer> parseInt(String s) {
try {
return Optional.of(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) {
var counter = new AtomicInteger();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.filter(AchievementData::isParent)
.forEach(
data -> {
var success = achievements.grant(data.getId());
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
counter.addAndGet(success.getChangedAchievementStatusNum());
}
});
sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname());
}
private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) {
var counter = new AtomicInteger();
GameData.getAchievementDataMap().values().stream()
.filter(AchievementData::isUsed)
.filter(AchievementData::isParent)
.forEach(
data -> {
var success = achievements.revoke(data.getId());
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
counter.addAndGet(success.getChangedAchievementStatusNum());
}
});
sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname());
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
return;
}
var command = args.remove(0).toLowerCase();
var achievements = Achievements.getByPlayer(targetPlayer);
switch (command) {
case "grant" -> this.grant(sender, targetPlayer, achievements, args);
case "revoke" -> this.revoke(sender, targetPlayer, achievements, args);
case "progress" -> this.progress(sender, targetPlayer, achievements, args);
case "grantall" -> grantAll(sender, targetPlayer, achievements);
case "revokeall" -> revokeAll(sender, targetPlayer, achievements);
default -> this.sendUsageMessage(sender);
}
}
private void grant(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
var ret = achievements.grant(integer);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname());
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
case ALREADY_ACHIEVED -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey(), targetPlayer.getNickname());
}
},
() -> this.sendUsageMessage(sender));
}
private void revoke(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 1) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
var ret = achievements.revoke(integer);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname());
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
case NOT_YET_ACHIEVED -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey(), targetPlayer.getNickname());
}
},
() -> this.sendUsageMessage(sender));
}
private void progress(
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
if (args.size() < 2) {
this.sendUsageMessage(sender);
}
parseInt(args.remove(0))
.ifPresentOrElse(
integer -> {
parseInt(args.remove(0))
.ifPresentOrElse(
progress -> {
var ret = achievements.progress(integer, progress);
switch (ret.getRet()) {
case SUCCESS -> sendSuccessMessage(
sender, "progress", targetPlayer.getNickname(), integer, progress);
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
sender, ret.getRet().getKey());
}
},
() -> this.sendUsageMessage(sender));
},
() -> this.sendUsageMessage(sender));
}
}

View File

@@ -1,139 +1,139 @@
package emu.grasscutter.command.commands;
import static emu.grasscutter.command.CommandHelpers.*;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.event.entity.EntityDamageEvent;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import lombok.Setter;
@Command(
label = "entity",
usage = {
"<configId gadget> [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>]",
"<configId monster> [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>]"
},
permission = "server.entity")
public final class EntityCommand implements CommandHandler {
private static final Map<Pattern, BiConsumer<EntityParameters, Integer>> intCommandHandlers =
Map.ofEntries(
Map.entry(stateRegex, EntityParameters::setState),
Map.entry(maxHPRegex, EntityParameters::setMaxHP),
Map.entry(hpRegex, EntityParameters::setHp),
Map.entry(defRegex, EntityParameters::setDef),
Map.entry(atkRegex, EntityParameters::setAtk),
Map.entry(aiRegex, EntityParameters::setAi));
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
EntityParameters param = new EntityParameters();
parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be the id and the rest the pos
if (args.size() != 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException();
}
try {
param.configId = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.cfgId"));
}
param.scene = targetPlayer.getScene();
var entity = param.scene.getEntityByConfigId(param.configId);
if (entity == null) {
CommandHandler.sendMessage(sender, translate(sender, "commands.entity.not_found_error"));
return;
}
applyFightProps(entity, param);
applyGadgetParams(entity, param);
applyMonsterParams(entity, param);
CommandHandler.sendMessage(sender, translate(sender, "commands.status.success"));
}
private void applyGadgetParams(GameEntity entity, EntityParameters param) {
if (!(entity instanceof EntityGadget)) {
return;
}
if (param.state != -1) {
((EntityGadget) entity).updateState(param.state);
}
}
private void applyMonsterParams(GameEntity entity, EntityParameters param) {
if (!(entity instanceof EntityMonster)) {
return;
}
if (param.ai != -1) {
((EntityMonster) entity).setAiId(param.ai);
// TODO notify
}
}
private void applyFightProps(GameEntity entity, EntityParameters param) {
var changedFields = new ArrayList<FightProperty>();
if (param.maxHP != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_MAX_HP, param.maxHP, changedFields);
}
if (param.hp != -1) {
float targetHp = param.hp == 0 ? Float.MAX_VALUE : param.hp;
float oldHp = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_HP, targetHp, changedFields);
EntityDamageEvent event =
new EntityDamageEvent(entity, oldHp - targetHp, ElementType.None, null);
callHPEvents(entity, event);
}
if (param.atk != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_ATTACK, param.atk, changedFields);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk, changedFields);
}
if (param.def != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_DEFENSE, param.def, changedFields);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def, changedFields);
}
if (!changedFields.isEmpty()) {
entity
.getScene()
.broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, changedFields));
}
}
private void callHPEvents(GameEntity entity, EntityDamageEvent event) {
entity.runLuaCallbacks(event);
}
private void setFightProperty(
GameEntity entity, FightProperty property, float value, List<FightProperty> modifiedProps) {
entity.setFightProperty(property, value);
modifiedProps.add(property);
}
private static class EntityParameters {
@Setter public int configId = -1;
@Setter public int state = -1;
@Setter public int hp = -1;
@Setter public int maxHP = -1;
@Setter public int atk = -1;
@Setter public int def = -1;
@Setter public int ai = -1;
public Scene scene = null;
}
}
package emu.grasscutter.command.commands;
import static emu.grasscutter.command.CommandHelpers.*;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.server.event.entity.EntityDamageEvent;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import lombok.Setter;
@Command(
label = "entity",
usage = {
"<configId gadget> [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>]",
"<configId monster> [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>]"
},
permission = "server.entity")
public final class EntityCommand implements CommandHandler {
private static final Map<Pattern, BiConsumer<EntityParameters, Integer>> intCommandHandlers =
Map.ofEntries(
Map.entry(stateRegex, EntityParameters::setState),
Map.entry(maxHPRegex, EntityParameters::setMaxHP),
Map.entry(hpRegex, EntityParameters::setHp),
Map.entry(defRegex, EntityParameters::setDef),
Map.entry(atkRegex, EntityParameters::setAtk),
Map.entry(aiRegex, EntityParameters::setAi));
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
EntityParameters param = new EntityParameters();
parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be the id and the rest the pos
if (args.size() != 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException();
}
try {
param.configId = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.cfgId"));
}
param.scene = targetPlayer.getScene();
var entity = param.scene.getEntityByConfigId(param.configId);
if (entity == null) {
CommandHandler.sendMessage(sender, translate(sender, "commands.entity.not_found_error"));
return;
}
applyFightProps(entity, param);
applyGadgetParams(entity, param);
applyMonsterParams(entity, param);
CommandHandler.sendMessage(sender, translate(sender, "commands.status.success"));
}
private void applyGadgetParams(GameEntity entity, EntityParameters param) {
if (!(entity instanceof EntityGadget)) {
return;
}
if (param.state != -1) {
((EntityGadget) entity).updateState(param.state);
}
}
private void applyMonsterParams(GameEntity entity, EntityParameters param) {
if (!(entity instanceof EntityMonster)) {
return;
}
if (param.ai != -1) {
((EntityMonster) entity).setAiId(param.ai);
// TODO notify
}
}
private void applyFightProps(GameEntity entity, EntityParameters param) {
var changedFields = new ArrayList<FightProperty>();
if (param.maxHP != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_MAX_HP, param.maxHP, changedFields);
}
if (param.hp != -1) {
float targetHp = param.hp == 0 ? Float.MAX_VALUE : param.hp;
float oldHp = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_HP, targetHp, changedFields);
EntityDamageEvent event =
new EntityDamageEvent(entity, oldHp - targetHp, ElementType.None, null);
callHPEvents(entity, event);
}
if (param.atk != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_ATTACK, param.atk, changedFields);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk, changedFields);
}
if (param.def != -1) {
setFightProperty(entity, FightProperty.FIGHT_PROP_DEFENSE, param.def, changedFields);
setFightProperty(entity, FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def, changedFields);
}
if (!changedFields.isEmpty()) {
entity
.getScene()
.broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, changedFields));
}
}
private void callHPEvents(GameEntity entity, EntityDamageEvent event) {
entity.runLuaCallbacks(event);
}
private void setFightProperty(
GameEntity entity, FightProperty property, float value, List<FightProperty> modifiedProps) {
entity.setFightProperty(property, value);
modifiedProps.add(property);
}
private static class EntityParameters {
@Setter public int configId = -1;
@Setter public int state = -1;
@Setter public int hp = -1;
@Setter public int maxHP = -1;
@Setter public int atk = -1;
@Setter public int def = -1;
@Setter public int ai = -1;
public Scene scene = null;
}
}

View File

@@ -1,72 +1,72 @@
package emu.grasscutter.command.commands;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.world.SceneGroupInstance;
import java.util.List;
@Command(
label = "group",
aliases = {"g"},
usage = {"(refresh) [<groupId>] [<suiteId>]"},
permission = "player.group",
permissionTargeted = "player.group.others")
public final class GroupCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) {
return;
}
String cmd = args.remove(0).toLowerCase();
int groupId = 0;
int suiteId = 0;
switch (args.size()) {
case 2:
try {
suiteId = Integer.parseInt(args.get(1));
} catch (Exception e) {
CommandHandler.sendMessage(sender, translate(sender, "commands.group.invalid_suiteid"));
return;
} // Fallthrough
case 1:
try {
groupId = Integer.parseInt(args.get(0));
} catch (Exception e) {
CommandHandler.sendMessage(sender, translate(sender, "commands.group.invalid_groupid"));
return;
}
break;
default:
sendUsageMessage(sender);
return;
}
switch (cmd) {
case "refresh" -> {
SceneGroupInstance groupInstance =
targetPlayer.getScene().getScriptManager().getGroupInstanceById(groupId);
if (groupInstance == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.group.group_not_found", groupId));
return;
}
if (args.size() >= 2) {
targetPlayer.getScene().getScriptManager().refreshGroup(groupInstance, suiteId, false);
} else {
targetPlayer.getScene().getScriptManager().refreshGroup(groupInstance);
}
CommandHandler.sendMessage(sender, translate(sender, "commands.group.refreshed", groupId));
}
default -> {
sendUsageMessage(sender);
}
}
}
}
package emu.grasscutter.command.commands;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.world.SceneGroupInstance;
import java.util.List;
@Command(
label = "group",
aliases = {"g"},
usage = {"(refresh) [<groupId>] [<suiteId>]"},
permission = "player.group",
permissionTargeted = "player.group.others")
public final class GroupCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.isEmpty()) {
return;
}
String cmd = args.remove(0).toLowerCase();
int groupId = 0;
int suiteId = 0;
switch (args.size()) {
case 2:
try {
suiteId = Integer.parseInt(args.get(1));
} catch (Exception e) {
CommandHandler.sendMessage(sender, translate(sender, "commands.group.invalid_suiteid"));
return;
} // Fallthrough
case 1:
try {
groupId = Integer.parseInt(args.get(0));
} catch (Exception e) {
CommandHandler.sendMessage(sender, translate(sender, "commands.group.invalid_groupid"));
return;
}
break;
default:
sendUsageMessage(sender);
return;
}
switch (cmd) {
case "refresh" -> {
SceneGroupInstance groupInstance =
targetPlayer.getScene().getScriptManager().getGroupInstanceById(groupId);
if (groupInstance == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.group.group_not_found", groupId));
return;
}
if (args.size() >= 2) {
targetPlayer.getScene().getScriptManager().refreshGroup(groupInstance, suiteId, false);
} else {
targetPlayer.getScene().getScriptManager().refreshGroup(groupInstance);
}
CommandHandler.sendMessage(sender, translate(sender, "commands.group.refreshed", groupId));
}
default -> {
sendUsageMessage(sender);
}
}
}
}

View File

@@ -1,279 +1,279 @@
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.tower.TowerLevelRecord;
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Command(
label = "setProp",
aliases = {"prop"},
usage = {"<prop> <value>"},
permission = "player.setprop",
permissionTargeted = "player.setprop.others")
public final class SetPropCommand implements CommandHandler {
// List of map areas. Unfortunately, there is no readily available source for them in excels or
// bins.
private static final List<Integer> sceneAreas =
List.of(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 32, 100, 101, 102, 103, 200, 210, 300, 400, 401, 402, 403);
Map<String, Prop> props;
public SetPropCommand() {
this.props = new HashMap<>();
// Full PlayerProperty enum that won't be advertised but can be used by devs
for (PlayerProperty prop : PlayerProperty.values()) {
String name = prop.toString().substring(5); // PROP_EXP -> EXP
String key = name.toLowerCase(); // EXP -> exp
this.props.put(key, new Prop(name, prop));
}
// Add special props
Prop worldlevel =
new Prop("World Level", PlayerProperty.PROP_PLAYER_WORLD_LEVEL, PseudoProp.WORLD_LEVEL);
this.props.put("worldlevel", worldlevel);
this.props.put("wl", worldlevel);
Prop abyss = new Prop("Tower Level", PseudoProp.TOWER_LEVEL);
this.props.put("abyss", abyss);
this.props.put("abyssfloor", abyss);
this.props.put("ut", abyss);
this.props.put("tower", abyss);
this.props.put("towerlevel", abyss);
this.props.put("unlocktower", abyss);
Prop bplevel = new Prop("BP Level", PseudoProp.BP_LEVEL);
this.props.put("bplevel", bplevel);
this.props.put("bp", bplevel);
this.props.put("battlepass", bplevel);
Prop godmode = new Prop("GodMode", PseudoProp.GOD_MODE);
this.props.put("godmode", godmode);
this.props.put("god", godmode);
Prop nostamina = new Prop("UnlimitedStamina", PseudoProp.UNLIMITED_STAMINA);
this.props.put("unlimitedstamina", nostamina);
this.props.put("us", nostamina);
this.props.put("nostamina", nostamina);
this.props.put("nostam", nostamina);
this.props.put("ns", nostamina);
Prop unlimitedenergy = new Prop("UnlimitedEnergy", PseudoProp.UNLIMITED_ENERGY);
this.props.put("unlimitedenergy", unlimitedenergy);
this.props.put("ue", unlimitedenergy);
Prop setopenstate = new Prop("SetOpenstate", PseudoProp.SET_OPENSTATE);
this.props.put("setopenstate", setopenstate);
this.props.put("so", setopenstate);
Prop unsetopenstate = new Prop("UnsetOpenstate", PseudoProp.UNSET_OPENSTATE);
this.props.put("unsetopenstate", unsetopenstate);
this.props.put("uo", unsetopenstate);
Prop unlockmap = new Prop("UnlockMap", PseudoProp.UNLOCK_MAP);
this.props.put("unlockmap", unlockmap);
this.props.put("um", unlockmap);
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() != 2) {
sendUsageMessage(sender);
return;
}
String propStr = args.get(0).toLowerCase();
String valueStr = args.get(1).toLowerCase();
int value;
if (!props.containsKey(propStr)) {
sendUsageMessage(sender);
return;
}
try {
value =
switch (valueStr.toLowerCase()) {
case "on", "true" -> 1;
case "off", "false" -> 0;
case "toggle" -> -1;
default -> Integer.parseInt(valueStr);
};
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
return;
}
boolean success = false;
Prop prop = props.get(propStr);
success =
switch (prop.pseudoProp) {
case WORLD_LEVEL -> targetPlayer.setWorldLevel(value);
case BP_LEVEL -> targetPlayer.getBattlePassManager().setLevel(value);
case TOWER_LEVEL -> this.setTowerLevel(sender, targetPlayer, value);
case GOD_MODE, UNLIMITED_STAMINA, UNLIMITED_ENERGY -> this.setBool(
sender, targetPlayer, prop.pseudoProp, value);
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
case UNLOCK_MAP -> unlockMap(targetPlayer);
default -> targetPlayer.setProperty(prop.prop, value);
};
if (success) {
if (targetPlayer == sender) {
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.set_to", prop.name, valueStr);
} else {
String uidStr = targetPlayer.getAccount().getId();
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.set_for_to", prop.name, uidStr, valueStr);
}
} else {
if (prop.prop
!= PlayerProperty.PROP_NONE) { // PseudoProps need to do their own error messages
int min = targetPlayer.getPropertyMin(prop.prop);
int max = targetPlayer.getPropertyMax(prop.prop);
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.invalid.value_between", prop.name, min, max);
}
}
}
private boolean setTowerLevel(Player sender, Player targetPlayer, int topFloor) {
List<Integer> floorIds = targetPlayer.getServer().getTowerSystem().getAllFloors();
if (topFloor < 0 || topFloor > floorIds.size()) {
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.invalid.value_between", "Tower Level", 0, floorIds.size());
return false;
}
Map<Integer, TowerLevelRecord> recordMap = targetPlayer.getTowerManager().getRecordMap();
// Add records for each unlocked floor
for (int floor : floorIds.subList(0, topFloor)) {
if (!recordMap.containsKey(floor)) {
recordMap.put(floor, new TowerLevelRecord(floor));
}
}
// Remove records for each floor past our target
for (int floor : floorIds.subList(topFloor, floorIds.size())) {
recordMap.remove(floor);
}
// Six stars required on Floor 8 to unlock Floor 9+
if (topFloor > 8) {
recordMap
.get(floorIds.get(7))
.setLevelStars(
0,
6); // levelIds seem to start at 1 for Floor 1 Chamber 1, so this doesn't get shown at
// all
}
return true;
}
private boolean setBool(Player sender, Player targetPlayer, PseudoProp pseudoProp, int value) {
boolean enabled =
switch (pseudoProp) {
case GOD_MODE -> targetPlayer.isInGodMode();
case UNLIMITED_STAMINA -> targetPlayer.isUnlimitedStamina();
case UNLIMITED_ENERGY -> !targetPlayer.getEnergyManager().isEnergyUsage();
default -> false;
};
enabled =
switch (value) {
case -1 -> !enabled;
case 0 -> false;
default -> true;
};
switch (pseudoProp) {
case GOD_MODE:
targetPlayer.setInGodMode(enabled);
break;
case UNLIMITED_STAMINA:
targetPlayer.setUnlimitedStamina(enabled);
break;
case UNLIMITED_ENERGY:
targetPlayer.getEnergyManager().setEnergyUsage(!enabled);
break;
default:
return false;
}
return true;
}
private boolean setOpenState(Player targetPlayer, int state, int value) {
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(state, value));
return true;
}
private boolean unlockMap(Player targetPlayer) {
// Unlock.
GameData.getScenePointsPerScene()
.forEach(
(sceneId, scenePoints) -> {
// Unlock trans points.
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
// Unlock map areas.
targetPlayer.getUnlockedSceneAreas(sceneId).addAll(sceneAreas);
});
// Send notify.
int playerScene = targetPlayer.getSceneId();
targetPlayer.sendPacket(
new PacketScenePointUnlockNotify(
playerScene, targetPlayer.getUnlockedScenePoints(playerScene)));
targetPlayer.sendPacket(
new PacketSceneAreaUnlockNotify(
playerScene, targetPlayer.getUnlockedSceneAreas(playerScene)));
return true;
}
enum PseudoProp {
NONE,
WORLD_LEVEL,
TOWER_LEVEL,
BP_LEVEL,
GOD_MODE,
UNLIMITED_STAMINA,
UNLIMITED_ENERGY,
SET_OPENSTATE,
UNSET_OPENSTATE,
UNLOCK_MAP
}
static class Prop {
String name;
PlayerProperty prop;
PseudoProp pseudoProp;
public Prop(PlayerProperty prop) {
this(prop.toString(), prop, PseudoProp.NONE);
}
public Prop(String name) {
this(name, PlayerProperty.PROP_NONE, PseudoProp.NONE);
}
public Prop(String name, PseudoProp pseudoProp) {
this(name, PlayerProperty.PROP_NONE, pseudoProp);
}
public Prop(String name, PlayerProperty prop) {
this(name, prop, PseudoProp.NONE);
}
public Prop(String name, PlayerProperty prop, PseudoProp pseudoProp) {
this.name = name;
this.prop = prop;
this.pseudoProp = pseudoProp;
}
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.tower.TowerLevelRecord;
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Command(
label = "setProp",
aliases = {"prop"},
usage = {"<prop> <value>"},
permission = "player.setprop",
permissionTargeted = "player.setprop.others")
public final class SetPropCommand implements CommandHandler {
// List of map areas. Unfortunately, there is no readily available source for them in excels or
// bins.
private static final List<Integer> sceneAreas =
List.of(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 32, 100, 101, 102, 103, 200, 210, 300, 400, 401, 402, 403);
Map<String, Prop> props;
public SetPropCommand() {
this.props = new HashMap<>();
// Full PlayerProperty enum that won't be advertised but can be used by devs
for (PlayerProperty prop : PlayerProperty.values()) {
String name = prop.toString().substring(5); // PROP_EXP -> EXP
String key = name.toLowerCase(); // EXP -> exp
this.props.put(key, new Prop(name, prop));
}
// Add special props
Prop worldlevel =
new Prop("World Level", PlayerProperty.PROP_PLAYER_WORLD_LEVEL, PseudoProp.WORLD_LEVEL);
this.props.put("worldlevel", worldlevel);
this.props.put("wl", worldlevel);
Prop abyss = new Prop("Tower Level", PseudoProp.TOWER_LEVEL);
this.props.put("abyss", abyss);
this.props.put("abyssfloor", abyss);
this.props.put("ut", abyss);
this.props.put("tower", abyss);
this.props.put("towerlevel", abyss);
this.props.put("unlocktower", abyss);
Prop bplevel = new Prop("BP Level", PseudoProp.BP_LEVEL);
this.props.put("bplevel", bplevel);
this.props.put("bp", bplevel);
this.props.put("battlepass", bplevel);
Prop godmode = new Prop("GodMode", PseudoProp.GOD_MODE);
this.props.put("godmode", godmode);
this.props.put("god", godmode);
Prop nostamina = new Prop("UnlimitedStamina", PseudoProp.UNLIMITED_STAMINA);
this.props.put("unlimitedstamina", nostamina);
this.props.put("us", nostamina);
this.props.put("nostamina", nostamina);
this.props.put("nostam", nostamina);
this.props.put("ns", nostamina);
Prop unlimitedenergy = new Prop("UnlimitedEnergy", PseudoProp.UNLIMITED_ENERGY);
this.props.put("unlimitedenergy", unlimitedenergy);
this.props.put("ue", unlimitedenergy);
Prop setopenstate = new Prop("SetOpenstate", PseudoProp.SET_OPENSTATE);
this.props.put("setopenstate", setopenstate);
this.props.put("so", setopenstate);
Prop unsetopenstate = new Prop("UnsetOpenstate", PseudoProp.UNSET_OPENSTATE);
this.props.put("unsetopenstate", unsetopenstate);
this.props.put("uo", unsetopenstate);
Prop unlockmap = new Prop("UnlockMap", PseudoProp.UNLOCK_MAP);
this.props.put("unlockmap", unlockmap);
this.props.put("um", unlockmap);
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() != 2) {
sendUsageMessage(sender);
return;
}
String propStr = args.get(0).toLowerCase();
String valueStr = args.get(1).toLowerCase();
int value;
if (!props.containsKey(propStr)) {
sendUsageMessage(sender);
return;
}
try {
value =
switch (valueStr.toLowerCase()) {
case "on", "true" -> 1;
case "off", "false" -> 0;
case "toggle" -> -1;
default -> Integer.parseInt(valueStr);
};
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
return;
}
boolean success = false;
Prop prop = props.get(propStr);
success =
switch (prop.pseudoProp) {
case WORLD_LEVEL -> targetPlayer.setWorldLevel(value);
case BP_LEVEL -> targetPlayer.getBattlePassManager().setLevel(value);
case TOWER_LEVEL -> this.setTowerLevel(sender, targetPlayer, value);
case GOD_MODE, UNLIMITED_STAMINA, UNLIMITED_ENERGY -> this.setBool(
sender, targetPlayer, prop.pseudoProp, value);
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
case UNLOCK_MAP -> unlockMap(targetPlayer);
default -> targetPlayer.setProperty(prop.prop, value);
};
if (success) {
if (targetPlayer == sender) {
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.set_to", prop.name, valueStr);
} else {
String uidStr = targetPlayer.getAccount().getId();
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.set_for_to", prop.name, uidStr, valueStr);
}
} else {
if (prop.prop
!= PlayerProperty.PROP_NONE) { // PseudoProps need to do their own error messages
int min = targetPlayer.getPropertyMin(prop.prop);
int max = targetPlayer.getPropertyMax(prop.prop);
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.invalid.value_between", prop.name, min, max);
}
}
}
private boolean setTowerLevel(Player sender, Player targetPlayer, int topFloor) {
List<Integer> floorIds = targetPlayer.getServer().getTowerSystem().getAllFloors();
if (topFloor < 0 || topFloor > floorIds.size()) {
CommandHandler.sendTranslatedMessage(
sender, "commands.generic.invalid.value_between", "Tower Level", 0, floorIds.size());
return false;
}
Map<Integer, TowerLevelRecord> recordMap = targetPlayer.getTowerManager().getRecordMap();
// Add records for each unlocked floor
for (int floor : floorIds.subList(0, topFloor)) {
if (!recordMap.containsKey(floor)) {
recordMap.put(floor, new TowerLevelRecord(floor));
}
}
// Remove records for each floor past our target
for (int floor : floorIds.subList(topFloor, floorIds.size())) {
recordMap.remove(floor);
}
// Six stars required on Floor 8 to unlock Floor 9+
if (topFloor > 8) {
recordMap
.get(floorIds.get(7))
.setLevelStars(
0,
6); // levelIds seem to start at 1 for Floor 1 Chamber 1, so this doesn't get shown at
// all
}
return true;
}
private boolean setBool(Player sender, Player targetPlayer, PseudoProp pseudoProp, int value) {
boolean enabled =
switch (pseudoProp) {
case GOD_MODE -> targetPlayer.isInGodMode();
case UNLIMITED_STAMINA -> targetPlayer.isUnlimitedStamina();
case UNLIMITED_ENERGY -> !targetPlayer.getEnergyManager().isEnergyUsage();
default -> false;
};
enabled =
switch (value) {
case -1 -> !enabled;
case 0 -> false;
default -> true;
};
switch (pseudoProp) {
case GOD_MODE:
targetPlayer.setInGodMode(enabled);
break;
case UNLIMITED_STAMINA:
targetPlayer.setUnlimitedStamina(enabled);
break;
case UNLIMITED_ENERGY:
targetPlayer.getEnergyManager().setEnergyUsage(!enabled);
break;
default:
return false;
}
return true;
}
private boolean setOpenState(Player targetPlayer, int state, int value) {
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(state, value));
return true;
}
private boolean unlockMap(Player targetPlayer) {
// Unlock.
GameData.getScenePointsPerScene()
.forEach(
(sceneId, scenePoints) -> {
// Unlock trans points.
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
// Unlock map areas.
targetPlayer.getUnlockedSceneAreas(sceneId).addAll(sceneAreas);
});
// Send notify.
int playerScene = targetPlayer.getSceneId();
targetPlayer.sendPacket(
new PacketScenePointUnlockNotify(
playerScene, targetPlayer.getUnlockedScenePoints(playerScene)));
targetPlayer.sendPacket(
new PacketSceneAreaUnlockNotify(
playerScene, targetPlayer.getUnlockedSceneAreas(playerScene)));
return true;
}
enum PseudoProp {
NONE,
WORLD_LEVEL,
TOWER_LEVEL,
BP_LEVEL,
GOD_MODE,
UNLIMITED_STAMINA,
UNLIMITED_ENERGY,
SET_OPENSTATE,
UNSET_OPENSTATE,
UNLOCK_MAP
}
static class Prop {
String name;
PlayerProperty prop;
PseudoProp pseudoProp;
public Prop(PlayerProperty prop) {
this(prop.toString(), prop, PseudoProp.NONE);
}
public Prop(String name) {
this(name, PlayerProperty.PROP_NONE, PseudoProp.NONE);
}
public Prop(String name, PseudoProp pseudoProp) {
this(name, PlayerProperty.PROP_NONE, pseudoProp);
}
public Prop(String name, PlayerProperty prop) {
this(name, prop, PseudoProp.NONE);
}
public Prop(String name, PlayerProperty prop, PseudoProp pseudoProp) {
this.name = name;
this.prop = prop;
this.pseudoProp = pseudoProp;
}
}
}

View File

@@ -1,217 +1,217 @@
package emu.grasscutter.command.commands;
import static emu.grasscutter.command.CommandHelpers.*;
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.data.excels.monster.MonsterData;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.utils.Position;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import lombok.Setter;
@Command(
label = "spawn",
aliases = {"drop", "s"},
usage = {
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>"
},
permission = "server.spawn",
permissionTargeted = "server.spawn.others")
public final class SpawnCommand implements CommandHandler {
private static final Map<Pattern, BiConsumer<SpawnParameters, Integer>> intCommandHandlers =
Map.ofEntries(
Map.entry(lvlRegex, SpawnParameters::setLvl),
Map.entry(amountRegex, SpawnParameters::setAmount),
Map.entry(stateRegex, SpawnParameters::setState),
Map.entry(blockRegex, SpawnParameters::setBlockId),
Map.entry(groupRegex, SpawnParameters::setGroupId),
Map.entry(configRegex, SpawnParameters::setConfigId),
Map.entry(maxHPRegex, SpawnParameters::setMaxHP),
Map.entry(hpRegex, SpawnParameters::setHp),
Map.entry(defRegex, SpawnParameters::setDef),
Map.entry(atkRegex, SpawnParameters::setAtk),
Map.entry(aiRegex, SpawnParameters::setAi));
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
SpawnParameters param = new SpawnParameters();
parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be the id and the rest the pos
if (args.size() < 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException();
}
switch (args.size()) {
case 4:
try {
float x, y, z;
x = Float.parseFloat(args.get(1));
y = Float.parseFloat(args.get(2));
z = Float.parseFloat(args.get(3));
param.pos = new Position(x, y, z);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.execution.argument_error"));
} // Fallthrough
case 1:
try {
param.id = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.generic.invalid.entityId"));
}
break;
default:
sendUsageMessage(sender);
return;
}
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
ItemData itemData = GameData.getItemDataMap().get(param.id);
if (monsterData == null && gadgetData == null && itemData == null) {
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId"));
return;
}
param.scene = targetPlayer.getScene();
if (param.scene.getEntities().size() + param.amount > GAME_OPTIONS.sceneEntityLimit) {
param.amount =
Math.max(
Math.min(
GAME_OPTIONS.sceneEntityLimit - param.scene.getEntities().size(), param.amount),
0);
CommandHandler.sendMessage(
sender, translate(sender, "commands.spawn.limit_reached", param.amount));
if (param.amount <= 0) {
return;
}
}
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
if (param.pos == null) {
param.pos = targetPlayer.getPosition();
}
for (int i = 0; i < param.amount; i++) {
Position pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
GameEntity entity = null;
if (itemData != null) {
entity = createItem(itemData, param, pos);
}
if (gadgetData != null) {
pos.addY(-3);
entity = createGadget(gadgetData, param, pos, targetPlayer);
}
if (monsterData != null) {
entity = createMonster(monsterData, param, pos);
}
applyCommonParameters(entity, param);
param.scene.addEntity(entity);
}
CommandHandler.sendMessage(
sender, translate(sender, "commands.spawn.success", param.amount, param.id));
}
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
return new EntityItem(param.scene, null, itemData, pos, 1, true);
}
private EntityMonster createMonster(
MonsterData monsterData, SpawnParameters param, Position pos) {
var entity = new EntityMonster(param.scene, monsterData, pos, param.lvl);
if (param.ai != -1) {
entity.setAiId(param.ai);
}
return entity;
}
private EntityBaseGadget createGadget(
GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
EntityBaseGadget entity;
if (gadgetData.getType() == EntityType.Vehicle) {
entity =
new EntityVehicle(
param.scene, targetPlayer, param.id, 0, pos, targetPlayer.getRotation());
} else {
entity = new EntityGadget(param.scene, param.id, pos, targetPlayer.getRotation());
if (param.state != -1) {
((EntityGadget) entity).setState(param.state);
}
}
return entity;
}
private void applyCommonParameters(GameEntity entity, SpawnParameters param) {
if (param.blockId != -1) {
entity.setBlockId(param.blockId);
}
if (param.groupId != -1) {
entity.setGroupId(param.groupId);
}
if (param.configId != -1) {
entity.setConfigId(param.configId);
}
if (param.maxHP != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, param.maxHP);
entity.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, param.maxHP);
}
if (param.hp != -1) {
entity.setFightProperty(
FightProperty.FIGHT_PROP_CUR_HP, param.hp == 0 ? Float.MAX_VALUE : param.hp);
}
if (param.atk != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_ATTACK, param.atk);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk);
}
if (param.def != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_DEFENSE, param.def);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def);
}
}
private Position GetRandomPositionInCircle(Position origin, double radius) {
Position target = origin.clone();
double angle = Math.random() * 360;
double r = Math.sqrt(Math.random() * radius * radius);
target.addX((float) (r * Math.cos(angle))).addZ((float) (r * Math.sin(angle)));
return target;
}
private static class SpawnParameters {
@Setter public int id;
@Setter public int lvl = 1;
@Setter public int amount = 1;
@Setter public int blockId = -1;
@Setter public int groupId = -1;
@Setter public int configId = -1;
@Setter public int state = -1;
@Setter public int hp = -1;
@Setter public int maxHP = -1;
@Setter public int atk = -1;
@Setter public int def = -1;
@Setter public int ai = -1;
@Setter public Position pos = null;
public Scene scene = null;
}
}
package emu.grasscutter.command.commands;
import static emu.grasscutter.command.CommandHelpers.*;
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.GadgetData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.data.excels.monster.MonsterData;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.utils.Position;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import lombok.Setter;
@Command(
label = "spawn",
aliases = {"drop", "s"},
usage = {
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>"
},
permission = "server.spawn",
permissionTargeted = "server.spawn.others")
public final class SpawnCommand implements CommandHandler {
private static final Map<Pattern, BiConsumer<SpawnParameters, Integer>> intCommandHandlers =
Map.ofEntries(
Map.entry(lvlRegex, SpawnParameters::setLvl),
Map.entry(amountRegex, SpawnParameters::setAmount),
Map.entry(stateRegex, SpawnParameters::setState),
Map.entry(blockRegex, SpawnParameters::setBlockId),
Map.entry(groupRegex, SpawnParameters::setGroupId),
Map.entry(configRegex, SpawnParameters::setConfigId),
Map.entry(maxHPRegex, SpawnParameters::setMaxHP),
Map.entry(hpRegex, SpawnParameters::setHp),
Map.entry(defRegex, SpawnParameters::setDef),
Map.entry(atkRegex, SpawnParameters::setAtk),
Map.entry(aiRegex, SpawnParameters::setAi));
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
SpawnParameters param = new SpawnParameters();
parseIntParameters(args, param, intCommandHandlers);
// At this point, first remaining argument MUST be the id and the rest the pos
if (args.size() < 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException();
}
switch (args.size()) {
case 4:
try {
float x, y, z;
x = Float.parseFloat(args.get(1));
y = Float.parseFloat(args.get(2));
z = Float.parseFloat(args.get(3));
param.pos = new Position(x, y, z);
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.execution.argument_error"));
} // Fallthrough
case 1:
try {
param.id = Integer.parseInt(args.get(0));
} catch (NumberFormatException ignored) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.generic.invalid.entityId"));
}
break;
default:
sendUsageMessage(sender);
return;
}
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
ItemData itemData = GameData.getItemDataMap().get(param.id);
if (monsterData == null && gadgetData == null && itemData == null) {
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId"));
return;
}
param.scene = targetPlayer.getScene();
if (param.scene.getEntities().size() + param.amount > GAME_OPTIONS.sceneEntityLimit) {
param.amount =
Math.max(
Math.min(
GAME_OPTIONS.sceneEntityLimit - param.scene.getEntities().size(), param.amount),
0);
CommandHandler.sendMessage(
sender, translate(sender, "commands.spawn.limit_reached", param.amount));
if (param.amount <= 0) {
return;
}
}
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
if (param.pos == null) {
param.pos = targetPlayer.getPosition();
}
for (int i = 0; i < param.amount; i++) {
Position pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
GameEntity entity = null;
if (itemData != null) {
entity = createItem(itemData, param, pos);
}
if (gadgetData != null) {
pos.addY(-3);
entity = createGadget(gadgetData, param, pos, targetPlayer);
}
if (monsterData != null) {
entity = createMonster(monsterData, param, pos);
}
applyCommonParameters(entity, param);
param.scene.addEntity(entity);
}
CommandHandler.sendMessage(
sender, translate(sender, "commands.spawn.success", param.amount, param.id));
}
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
return new EntityItem(param.scene, null, itemData, pos, 1, true);
}
private EntityMonster createMonster(
MonsterData monsterData, SpawnParameters param, Position pos) {
var entity = new EntityMonster(param.scene, monsterData, pos, param.lvl);
if (param.ai != -1) {
entity.setAiId(param.ai);
}
return entity;
}
private EntityBaseGadget createGadget(
GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
EntityBaseGadget entity;
if (gadgetData.getType() == EntityType.Vehicle) {
entity =
new EntityVehicle(
param.scene, targetPlayer, param.id, 0, pos, targetPlayer.getRotation());
} else {
entity = new EntityGadget(param.scene, param.id, pos, targetPlayer.getRotation());
if (param.state != -1) {
((EntityGadget) entity).setState(param.state);
}
}
return entity;
}
private void applyCommonParameters(GameEntity entity, SpawnParameters param) {
if (param.blockId != -1) {
entity.setBlockId(param.blockId);
}
if (param.groupId != -1) {
entity.setGroupId(param.groupId);
}
if (param.configId != -1) {
entity.setConfigId(param.configId);
}
if (param.maxHP != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, param.maxHP);
entity.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, param.maxHP);
}
if (param.hp != -1) {
entity.setFightProperty(
FightProperty.FIGHT_PROP_CUR_HP, param.hp == 0 ? Float.MAX_VALUE : param.hp);
}
if (param.atk != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_ATTACK, param.atk);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk);
}
if (param.def != -1) {
entity.setFightProperty(FightProperty.FIGHT_PROP_DEFENSE, param.def);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def);
}
}
private Position GetRandomPositionInCircle(Position origin, double radius) {
Position target = origin.clone();
double angle = Math.random() * 360;
double r = Math.sqrt(Math.random() * radius * radius);
target.addX((float) (r * Math.cos(angle))).addZ((float) (r * Math.sin(angle)));
return target;
}
private static class SpawnParameters {
@Setter public int id;
@Setter public int lvl = 1;
@Setter public int amount = 1;
@Setter public int blockId = -1;
@Setter public int groupId = -1;
@Setter public int configId = -1;
@Setter public int state = -1;
@Setter public int hp = -1;
@Setter public int maxHP = -1;
@Setter public int atk = -1;
@Setter public int def = -1;
@Setter public int ai = -1;
@Setter public Position pos = null;
public Scene scene = null;
}
}

View File

@@ -1,129 +1,129 @@
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.utils.Language;
import java.util.List;
@Command(
label = "talent",
usage = {"set <talentId> <level>", "(n|e|q|all) <level>", "getid"},
permission = "player.settalent",
permissionTargeted = "player.settalent.others")
public final class TalentCommand implements CommandHandler {
private void setTalentLevel(Player sender, Avatar avatar, int skillId, int newLevel) {
if (avatar.setSkillLevel(skillId, newLevel)) {
long nameHash = GameData.getAvatarSkillDataMap().get(skillId).getNameTextMapHash();
var name = Language.getTextMapKey(nameHash);
CommandHandler.sendTranslatedMessage(
sender, "commands.talent.set_id", skillId, name, newLevel);
} else {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
}
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
sendUsageMessage(sender);
return;
}
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
AvatarSkillDepotData skillDepot = avatar.getSkillDepot();
if (skillDepot
== null) { // Avatars without skill depots aren't a suitable target even with manual skillId
// specified
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
return;
}
int skillId = 0;
int newLevel = -1;
String cmdSwitch = args.get(0).toLowerCase();
switch (cmdSwitch) {
default -> {
sendUsageMessage(sender);
}
case "set" -> {
if (args.size() < 3) {
sendUsageMessage(sender);
return;
}
try {
skillId = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
return;
}
try {
newLevel = Integer.parseInt(args.get(2));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
setTalentLevel(sender, avatar, skillId, newLevel);
}
case "n", "e", "q" -> {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
try {
newLevel = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
skillId =
switch (cmdSwitch) {
default -> skillDepot.getSkills().get(0);
case "e" -> skillDepot.getSkills().get(1);
case "q" -> skillDepot.getEnergySkill();
};
setTalentLevel(sender, avatar, skillId, newLevel);
}
case "all" -> {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
try {
newLevel = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
// This stops setTalentLevel from outputting 3 "levels out of range" messages
if (newLevel < 1 || newLevel > 15) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
return;
}
int finalNewLevel = newLevel;
skillDepot
.getSkillsAndEnergySkill()
.forEach(id -> setTalentLevel(sender, avatar, id, finalNewLevel));
}
case "getid" -> {
var map = GameData.getAvatarSkillDataMap();
skillDepot
.getSkillsAndEnergySkill()
.forEach(
id -> {
var talent = map.get(id);
if (talent == null) return;
var talentName = Language.getTextMapKey(talent.getNameTextMapHash());
var talentDesc = Language.getTextMapKey(talent.getDescTextMapHash());
CommandHandler.sendTranslatedMessage(
sender, "commands.talent.id_desc", id, talentName, talentDesc);
});
}
}
}
}
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.utils.Language;
import java.util.List;
@Command(
label = "talent",
usage = {"set <talentId> <level>", "(n|e|q|all) <level>", "getid"},
permission = "player.settalent",
permissionTargeted = "player.settalent.others")
public final class TalentCommand implements CommandHandler {
private void setTalentLevel(Player sender, Avatar avatar, int skillId, int newLevel) {
if (avatar.setSkillLevel(skillId, newLevel)) {
long nameHash = GameData.getAvatarSkillDataMap().get(skillId).getNameTextMapHash();
var name = Language.getTextMapKey(nameHash);
CommandHandler.sendTranslatedMessage(
sender, "commands.talent.set_id", skillId, name, newLevel);
} else {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
}
}
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
sendUsageMessage(sender);
return;
}
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
AvatarSkillDepotData skillDepot = avatar.getSkillDepot();
if (skillDepot
== null) { // Avatars without skill depots aren't a suitable target even with manual skillId
// specified
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
return;
}
int skillId = 0;
int newLevel = -1;
String cmdSwitch = args.get(0).toLowerCase();
switch (cmdSwitch) {
default -> {
sendUsageMessage(sender);
}
case "set" -> {
if (args.size() < 3) {
sendUsageMessage(sender);
return;
}
try {
skillId = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
return;
}
try {
newLevel = Integer.parseInt(args.get(2));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
setTalentLevel(sender, avatar, skillId, newLevel);
}
case "n", "e", "q" -> {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
try {
newLevel = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
skillId =
switch (cmdSwitch) {
default -> skillDepot.getSkills().get(0);
case "e" -> skillDepot.getSkills().get(1);
case "q" -> skillDepot.getEnergySkill();
};
setTalentLevel(sender, avatar, skillId, newLevel);
}
case "all" -> {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
try {
newLevel = Integer.parseInt(args.get(1));
} catch (NumberFormatException ignored) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
return;
}
// This stops setTalentLevel from outputting 3 "levels out of range" messages
if (newLevel < 1 || newLevel > 15) {
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
return;
}
int finalNewLevel = newLevel;
skillDepot
.getSkillsAndEnergySkill()
.forEach(id -> setTalentLevel(sender, avatar, id, finalNewLevel));
}
case "getid" -> {
var map = GameData.getAvatarSkillDataMap();
skillDepot
.getSkillsAndEnergySkill()
.forEach(
id -> {
var talent = map.get(id);
if (talent == null) return;
var talentName = Language.getTextMapKey(talent.getNameTextMapHash());
var talentDesc = Language.getTextMapKey(talent.getDescTextMapHash());
CommandHandler.sendTranslatedMessage(
sender, "commands.talent.id_desc", id, talentName, talentDesc);
});
}
}
}
}

View File

@@ -1,156 +1,156 @@
package emu.grasscutter.command.commands;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.activity.trialavatar.TrialAvatarActivityHandler;
import emu.grasscutter.game.activity.trialavatar.TrialAvatarPlayerData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActivityType;
import emu.grasscutter.server.packet.send.PacketActivityInfoNotify;
import emu.grasscutter.utils.JsonUtils;
import java.util.List;
@Command(
label = "trialAvatarActivity",
aliases = {"taa"},
usage = {
"change <scheduleId>",
"toggleDungeon <index(start from 1)|all>",
"toggleReward <index(start from 1)|all>"
},
permission = "player.trialavataractivity",
permissionTargeted = "player.trialavataractivity.others")
public final class TrialAvatarActivityCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
var action = args.get(0).toLowerCase();
var param = args.get(1);
var playerDataOption =
targetPlayer
.getActivityManager()
.getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_TRIAL_AVATAR);
if (playerDataOption.isEmpty()) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
var playerData = playerDataOption.get();
var handler = (TrialAvatarActivityHandler) playerData.getActivityHandler();
if (handler == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
var trialAvatarPlayerData =
JsonUtils.decode(playerData.getDetail(), TrialAvatarPlayerData.class);
if (trialAvatarPlayerData == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
switch (action) {
default -> this.sendUsageMessage(sender);
case "change" -> {
if (!param.chars().allMatch(Character::isDigit)) { // if its not number
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
if (TrialAvatarPlayerData.getAvatarIdList(Integer.parseInt(param)).isEmpty()) {
CommandHandler.sendMessage(
sender,
translate(
sender,
"commands.trialAvatarActivity.schedule_not_found",
Integer.parseInt(param)));
return;
}
playerData.setDetail(TrialAvatarPlayerData.create(Integer.parseInt(param)));
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_schedule", Integer.parseInt(param)));
}
case "toggledungeon" -> {
if (param.chars().allMatch(Character::isDigit)) { // if its number
if (Integer.parseInt(param) - 1 >= trialAvatarPlayerData.getRewardInfoList().size()
|| Integer.parseInt(param) - 1 <= 0) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
TrialAvatarPlayerData.RewardInfoItem rewardInfo =
trialAvatarPlayerData.getRewardInfoList().get(Integer.parseInt(param) - 1);
rewardInfo.setPassedDungeon(!rewardInfo.isPassedDungeon());
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_dungeon", Integer.parseInt(param)));
} else {
if (!param.equals("all")) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
trialAvatarPlayerData
.getRewardInfoList()
.forEach(r -> r.setPassedDungeon(!r.isPassedDungeon()));
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.success_dungeon_all"));
}
}
case "togglereward" -> {
if (param.chars().allMatch(Character::isDigit)) { // if its number
if (Integer.parseInt(param) - 1 >= trialAvatarPlayerData.getRewardInfoList().size()
|| Integer.parseInt(param) - 1 <= 0) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
TrialAvatarPlayerData.RewardInfoItem rewardInfo =
trialAvatarPlayerData.getRewardInfoList().get(Integer.parseInt(param) - 1);
rewardInfo.setReceivedReward(!rewardInfo.isReceivedReward());
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_reward", Integer.parseInt(param)));
} else {
if (!param.toLowerCase().equals("all")) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
trialAvatarPlayerData
.getRewardInfoList()
.forEach(r -> r.setReceivedReward(!r.isReceivedReward()));
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.success_reward_all"));
}
}
}
targetPlayer.sendPacket(
new PacketActivityInfoNotify(
handler.toProto(playerData, targetPlayer.getActivityManager().getConditionExecutor())));
}
}
package emu.grasscutter.command.commands;
import static emu.grasscutter.utils.Language.translate;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.activity.trialavatar.TrialAvatarActivityHandler;
import emu.grasscutter.game.activity.trialavatar.TrialAvatarPlayerData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActivityType;
import emu.grasscutter.server.packet.send.PacketActivityInfoNotify;
import emu.grasscutter.utils.JsonUtils;
import java.util.List;
@Command(
label = "trialAvatarActivity",
aliases = {"taa"},
usage = {
"change <scheduleId>",
"toggleDungeon <index(start from 1)|all>",
"toggleReward <index(start from 1)|all>"
},
permission = "player.trialavataractivity",
permissionTargeted = "player.trialavataractivity.others")
public final class TrialAvatarActivityCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 2) {
sendUsageMessage(sender);
return;
}
var action = args.get(0).toLowerCase();
var param = args.get(1);
var playerDataOption =
targetPlayer
.getActivityManager()
.getPlayerActivityDataByActivityType(ActivityType.NEW_ACTIVITY_TRIAL_AVATAR);
if (playerDataOption.isEmpty()) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
var playerData = playerDataOption.get();
var handler = (TrialAvatarActivityHandler) playerData.getActivityHandler();
if (handler == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
var trialAvatarPlayerData =
JsonUtils.decode(playerData.getDetail(), TrialAvatarPlayerData.class);
if (trialAvatarPlayerData == null) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.not_found"));
return;
}
switch (action) {
default -> this.sendUsageMessage(sender);
case "change" -> {
if (!param.chars().allMatch(Character::isDigit)) { // if its not number
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
if (TrialAvatarPlayerData.getAvatarIdList(Integer.parseInt(param)).isEmpty()) {
CommandHandler.sendMessage(
sender,
translate(
sender,
"commands.trialAvatarActivity.schedule_not_found",
Integer.parseInt(param)));
return;
}
playerData.setDetail(TrialAvatarPlayerData.create(Integer.parseInt(param)));
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_schedule", Integer.parseInt(param)));
}
case "toggledungeon" -> {
if (param.chars().allMatch(Character::isDigit)) { // if its number
if (Integer.parseInt(param) - 1 >= trialAvatarPlayerData.getRewardInfoList().size()
|| Integer.parseInt(param) - 1 <= 0) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
TrialAvatarPlayerData.RewardInfoItem rewardInfo =
trialAvatarPlayerData.getRewardInfoList().get(Integer.parseInt(param) - 1);
rewardInfo.setPassedDungeon(!rewardInfo.isPassedDungeon());
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_dungeon", Integer.parseInt(param)));
} else {
if (!param.equals("all")) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
trialAvatarPlayerData
.getRewardInfoList()
.forEach(r -> r.setPassedDungeon(!r.isPassedDungeon()));
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.success_dungeon_all"));
}
}
case "togglereward" -> {
if (param.chars().allMatch(Character::isDigit)) { // if its number
if (Integer.parseInt(param) - 1 >= trialAvatarPlayerData.getRewardInfoList().size()
|| Integer.parseInt(param) - 1 <= 0) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
TrialAvatarPlayerData.RewardInfoItem rewardInfo =
trialAvatarPlayerData.getRewardInfoList().get(Integer.parseInt(param) - 1);
rewardInfo.setReceivedReward(!rewardInfo.isReceivedReward());
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender,
translate(
sender, "commands.trialAvatarActivity.success_reward", Integer.parseInt(param)));
} else {
if (!param.toLowerCase().equals("all")) {
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.invalid_param"));
return;
}
trialAvatarPlayerData
.getRewardInfoList()
.forEach(r -> r.setReceivedReward(!r.isReceivedReward()));
playerData.setDetail(trialAvatarPlayerData);
playerData.save();
CommandHandler.sendMessage(
sender, translate(sender, "commands.trialAvatarActivity.success_reward_all"));
}
}
}
targetPlayer.sendPacket(
new PacketActivityInfoNotify(
handler.toProto(playerData, targetPlayer.getActivityManager().getConditionExecutor())));
}
}