mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-20 02:45:52 +01:00
Fix player fields not being set
line seps r weird
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user