From b35ee455e5a8e5abd4d9f94bf5f1c4c5eea3032c Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Mon, 18 Apr 2022 22:10:41 -0400 Subject: [PATCH] Add existing commands --- .../grasscutter/commands/PlayerCommands.java | 586 +++++++++--------- .../grasscutter/commands/ServerCommands.java | 121 ++++ .../emu/grasscutter/game/GenshinPlayer.java | 11 +- src/main/java/emu/grasscutter/game/World.java | 2 +- .../java/emu/grasscutter/utils/Utils.java | 10 + 5 files changed, 431 insertions(+), 299 deletions(-) create mode 100644 src/main/java/emu/grasscutter/commands/ServerCommands.java diff --git a/src/main/java/emu/grasscutter/commands/PlayerCommands.java b/src/main/java/emu/grasscutter/commands/PlayerCommands.java index 9123cbd94..f427409c2 100644 --- a/src/main/java/emu/grasscutter/commands/PlayerCommands.java +++ b/src/main/java/emu/grasscutter/commands/PlayerCommands.java @@ -1,21 +1,17 @@ package emu.grasscutter.commands; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - +import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GenshinData; import emu.grasscutter.data.def.ItemData; import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.game.GenshinPlayer; +import emu.grasscutter.game.World; import emu.grasscutter.game.avatar.GenshinAvatar; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GenshinEntity; import emu.grasscutter.game.inventory.GenshinItem; +import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.FightProperty; @@ -23,306 +19,302 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketItemAddHintNotify; import emu.grasscutter.utils.Position; -public class PlayerCommands { - private static HashMap commandList = new HashMap(); - private static HashMap commandAliasList = new HashMap(); +import java.util.LinkedList; +import java.util.List; - - static { - try { - // Look for classes - for (Class cls : PlayerCommands.class.getDeclaredClasses()) { - // Get non abstract classes - if (!Modifier.isAbstract(cls.getModifiers())) { - Command commandAnnotation = cls.getAnnotation(Command.class); - PlayerCommand command = (PlayerCommand) cls.newInstance(); - - if (commandAnnotation != null) { - command.setLevel(commandAnnotation.gmLevel()); - command.setHelpText(commandAnnotation.helpText()); - for (String alias : commandAnnotation.aliases()) { - if (alias.length() == 0) { - continue; - } +/** + * A container for player-related commands. + */ +public final class PlayerCommands { + @Command(label = "give", aliases = {"g", "item", "giveitem"}, + usage = "Usage: give [player] [amount]") + public static class GiveCommand implements CommandHandler { - String commandName = alias; - commandAliasList.put(commandName, command); - } - } + @Override + public void execute(GenshinPlayer player, List args) { + int target, item, amount = 1; - String commandName = cls.getSimpleName().toLowerCase(); - commandList.put(commandName, command); - } - - } - } catch (Exception e) { - - } - } + switch(args.size()) { + default: + CommandHandler.sendMessage(player, "Usage: give [amount]"); + return; + case 1: + try { + item = Integer.parseInt(args.get(0)); + target = player.getId(); + } catch (NumberFormatException ignored) { + // TODO: Parse from item name using GM Handbook. + CommandHandler.sendMessage(player, "Invalid item id."); + return; + } + break; + case 2: + try { + target = Integer.parseInt(args.get(0)); + if(Grasscutter.getGameServer().getPlayerById(target) == null) { + target = player.getId(); amount = Integer.parseInt(args.get(1)); + item = Integer.parseInt(args.get(0)); + } else { + item = Integer.parseInt(args.get(1)); + } + } catch (NumberFormatException ignored) { + // TODO: Parse from item name using GM Handbook. + CommandHandler.sendMessage(player, "Invalid item or player ID."); + return; + } + break; + case 3: + try { + target = Integer.parseInt(args.get(0)); + if(Grasscutter.getGameServer().getPlayerById(target) == null) { + CommandHandler.sendMessage(player, "Invalid player ID."); return; + } - public static void handle(GenshinPlayer player, String msg) { - String[] split = msg.split(" "); - - // End if invalid - if (split.length == 0) { - return; - } + item = Integer.parseInt(args.get(1)); + amount = Integer.parseInt(args.get(2)); + } catch (NumberFormatException ignored) { + // TODO: Parse from item name using GM Handbook. + CommandHandler.sendMessage(player, "Invalid item or player ID."); + return; + } + break; + } - String first = split[0].toLowerCase().substring(1); - PlayerCommand c = PlayerCommands.commandList.get(first); - PlayerCommand a = PlayerCommands.commandAliasList.get(first); - - if (c != null || a != null) { - PlayerCommand cmd = c != null ? c : a; - // Level check - if (player.getGmLevel() < cmd.getLevel()) { - return; - } - // Execute - int len = Math.min(split[0].length() + 1, msg.length()); - cmd.execute(player, msg.substring(len)); - } - } - - public static abstract class PlayerCommand { - // GM level required to use this command - private int level; - private String helpText; + GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerById(target); + if(targetPlayer == null) { + CommandHandler.sendMessage(player, "Player not found."); return; + } - protected int getLevel() { return this.level; } - protected void setLevel(int minLevel) { this.level = minLevel; } + ItemData itemData = GenshinData.getItemDataMap().get(item); + if(itemData == null) { + CommandHandler.sendMessage(player, "Invalid item id."); return; + } + + this.item(targetPlayer, itemData, amount); + } - protected String getHelpText() { return this.helpText; } - protected void setHelpText(String helpText) { this.helpText = helpText; } + /** + * give [player] [itemId|itemName] [amount] + */ + @Override public void execute(List args) { + if(args.size() < 2) { + CommandHandler.sendMessage(null, "Usage: give [amount]"); + return; + } - // Main - public abstract void execute(GenshinPlayer player, String raw); - } - - // ================ Commands ================ + try { + int target = Integer.parseInt(args.get(0)); + int item = Integer.parseInt(args.get(1)); + int amount = 1; if(args.size() > 2) amount = Integer.parseInt(args.get(2)); + + GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerById(target); + if(targetPlayer == null) { + CommandHandler.sendMessage(null, "Player not found."); return; + } + + ItemData itemData = GenshinData.getItemDataMap().get(item); + if(itemData == null) { + CommandHandler.sendMessage(null, "Invalid item id."); return; + } + + this.item(targetPlayer, itemData, amount); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid item or player ID."); + } + } + + private void item(GenshinPlayer player, ItemData itemData, int amount) { + GenshinItem genshinItem = new GenshinItem(itemData); + if(itemData.isEquip()) { + List items = new LinkedList<>(); + for(int i = 0; i < amount; i++) { + items.add(genshinItem); + } player.getInventory().addItems(items); + player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop)); + } else { + genshinItem.setCount(amount); + player.getInventory().addItem(genshinItem); + player.sendPacket(new PacketItemAddHintNotify(genshinItem, ActionReason.SubfieldDrop)); + } + } + } + + @Command(label = "drop", aliases = {"d", "dropitem"}, + usage = "Usage: drop [amount]", + execution = Command.Execution.PLAYER) + public static class DropCommand implements CommandHandler { - @Command(aliases = {"h"}, helpText = "Shows this command") - public static class Help extends PlayerCommand { + @Override + public void execute(GenshinPlayer player, List args) { + if(args.size() < 1) { + CommandHandler.sendMessage(null, "Usage: drop [amount]"); + return; + } - @Override - public void execute(GenshinPlayer player, String raw) { - String helpMessage = "Grasscutter Commands: "; - for (Map.Entry cmd : commandList.entrySet()) { + try { + int item = Integer.parseInt(args.get(0)); + int amount = 1; if(args.size() > 1) amount = Integer.parseInt(args.get(1)); - helpMessage += "\n" + cmd.getKey() + " - " + cmd.getValue().helpText; - } + ItemData itemData = GenshinData.getItemDataMap().get(item); + if(itemData == null) { + CommandHandler.sendMessage(null, "Invalid item id."); return; + } - player.dropMessage(helpMessage); - } - } - - @Command(aliases = {"g", "item", "additem"}, helpText = "/give [item id] [count] - Gives {count} amount of {item id}") - public static class Give extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - String[] split = raw.split(" "); - int itemId = 0, count = 1; - - try { - itemId = Integer.parseInt(split[0]); - } catch (Exception e) { - itemId = 0; - } - - try { - count = Math.max(Math.min(Integer.parseInt(split[1]), Integer.MAX_VALUE), 1); - } catch (Exception e) { - count = 1; - } - - // Give - ItemData itemData = GenshinData.getItemDataMap().get(itemId); - GenshinItem item; - - if (itemData == null) { - player.dropMessage("Error: Item data not found"); - return; - } - - if (itemData.isEquip()) { - List items = new LinkedList<>(); - for (int i = 0; i < count; i++) { - item = new GenshinItem(itemData); - items.add(item); - } - player.getInventory().addItems(items); - player.sendPacket(new PacketItemAddHintNotify(items, ActionReason.SubfieldDrop)); - } else { - item = new GenshinItem(itemData, count); - player.getInventory().addItem(item); - player.sendPacket(new PacketItemAddHintNotify(item, ActionReason.SubfieldDrop)); - } - } - } - - @Command(aliases = {"d"}, helpText = "/drop [item id] [count] - Drops {count} amount of {item id}") - public static class Drop extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - String[] split = raw.split(" "); - int itemId = 0, count = 1; - - try { - itemId = Integer.parseInt(split[0]); - } catch (Exception e) { - itemId = 0; - } - - try { - count = Math.max(Math.min(Integer.parseInt(split[1]), Integer.MAX_VALUE), 1); - } catch (Exception e) { - count = 1; - } - - // Give - ItemData itemData = GenshinData.getItemDataMap().get(itemId); - - if (itemData == null) { - player.dropMessage("Error: Item data not found"); - return; - } - - if (itemData.isEquip()) { - float range = (5f + (.1f * count)); - for (int i = 0; i < count; i++) { - Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2)); - EntityItem entity = new EntityItem(player.getWorld(), player, itemData, pos, 1); - player.getWorld().addEntity(entity); - } - } else { - EntityItem entity = new EntityItem(player.getWorld(), player, itemData, player.getPos().clone().addY(3f), count); - player.getWorld().addEntity(entity); - } - } - } - - @Command(helpText = "/spawn [monster id] [count] - Creates {count} amount of {item id}") - public static class Spawn extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - String[] split = raw.split(" "); - int monsterId = 0, count = 1, level = 1; - - try { - monsterId = Integer.parseInt(split[0]); - } catch (Exception e) { - monsterId = 0; - } - - try { - level = Math.max(Math.min(Integer.parseInt(split[1]), 200), 1); - } catch (Exception e) { - level = 1; - } - - try { - count = Math.max(Math.min(Integer.parseInt(split[2]), 1000), 1); - } catch (Exception e) { - count = 1; - } - - // Give - MonsterData monsterData = GenshinData.getMonsterDataMap().get(monsterId); - - if (monsterData == null) { - player.dropMessage("Error: Monster data not found"); - return; - } - - float range = (5f + (.1f * count)); - for (int i = 0; i < count; i++) { - Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2)); - EntityMonster entity = new EntityMonster(player.getWorld(), monsterData, pos, level); - player.getWorld().addEntity(entity); - } - } - } - - @Command(helpText = "/killall") - public static class KillAll extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - List toRemove = new LinkedList<>(); - for (GenshinEntity entity : player.getWorld().getEntities().values()) { - if (entity instanceof EntityMonster) { - toRemove.add(entity); - } - } - toRemove.forEach(e -> player.getWorld().killEntity(e, 0)); - } - } - - @Command(helpText = "/resetconst - Resets all constellations for the currently active character") - public static class ResetConst extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity(); - - if (entity == null) { - return; - } - - GenshinAvatar avatar = entity.getAvatar(); - - avatar.getTalentIdList().clear(); - avatar.setCoreProudSkillLevel(0); - avatar.recalcStats(); - avatar.save(); - - player.dropMessage("Constellations for " + entity.getAvatar().getAvatarData().getName() + " have been reset. Please relogin to see changes."); - } - } - - @Command(helpText = "/godmode - Prevents you from taking damage") - public static class Godmode extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - player.setGodmode(!player.hasGodmode()); - player.dropMessage("Godmode is now " + (player.hasGodmode() ? "ON" : "OFF")); - } - } - - @Command(helpText = "/sethp [hp]") - public static class Sethp extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - String[] split = raw.split(" "); - int hp = 0; - - try { - hp = Math.max(Integer.parseInt(split[0]), 1); - } catch (Exception e) { - hp = 1; - } - - EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity(); - - if (entity == null) { - return; - } - - entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, hp); - entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); - } - } - - @Command(aliases = {"clearart"}, helpText = "/clearartifacts") - public static class ClearArtifacts extends PlayerCommand { - @Override - public void execute(GenshinPlayer player, String raw) { - List toRemove = new LinkedList<>(); - for (GenshinItem item : player.getInventory().getItems().values()) { - if (item.getItemType() == ItemType.ITEM_RELIQUARY && item.getLevel() == 1 && item.getExp() == 0 && !item.isLocked() && !item.isEquipped()) { - toRemove.add(item); - } - } - - player.getInventory().removeItems(toRemove); - } - } + if (itemData.isEquip()) { + float range = (5f + (.1f * amount)); + for (int i = 0; i < amount; i++) { + Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2)); + EntityItem entity = new EntityItem(player.getWorld(), player, itemData, pos, 1); + player.getWorld().addEntity(entity); + } + } else { + EntityItem entity = new EntityItem(player.getWorld(), player, itemData, player.getPos().clone().addY(3f), amount); + player.getWorld().addEntity(entity); + } + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid item or player ID."); + } + } + } + + @Command(label = "spawn", execution = Command.Execution.PLAYER, + usage = "Usage: spawn [level] [amount]") + public static class SpawnCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + if(args.size() < 1) { + CommandHandler.sendMessage(null, "Usage: spawn [amount]"); + return; + } + + try { + int entity = Integer.parseInt(args.get(0)); + int level = 1; if(args.size() > 1) level = Integer.parseInt(args.get(1)); + int amount = 1; if(args.size() > 2) amount = Integer.parseInt(args.get(2)); + + MonsterData entityData = GenshinData.getMonsterDataMap().get(entity); + if(entityData == null) { + CommandHandler.sendMessage(null, "Invalid entity id."); return; + } + + float range = (5f + (.1f * amount)); + for (int i = 0; i < amount; i++) { + Position pos = player.getPos().clone().addX((float) (Math.random() * range) - (range / 2)).addY(3f).addZ((float) (Math.random() * range) - (range / 2)); + EntityMonster monster = new EntityMonster(player.getWorld(), entityData, pos, level); + player.getWorld().addEntity(monster); + } + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid item or player ID."); + } + } + } + + @Command(label = "killall", + usage = "Usage: killall [sceneId]") + public static class KillAllCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + World world = player.getWorld(); + world.getEntities().values().stream() + .filter(entity -> entity instanceof EntityMonster) + .forEach(entity -> world.killEntity(entity, 0)); + } + + @Override + public void execute(List args) { + if(args.size() < 1) { + CommandHandler.sendMessage(null, "Usage: killall [sceneId]"); return; + } + + try { + int sceneId = Integer.parseInt(args.get(0)); + CommandHandler.sendMessage(null, "Killing all monsters in scene " + sceneId); + // TODO: Implement getting worlds by scene ID. + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid scene id."); + } + } + } + + @Command(label = "resetconst", aliases = {"resetconstellation"}, + usage = "Usage: resetconst [all]", execution = Command.Execution.PLAYER) + public static class ResetConstellationCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + if(args.size() > 0 && args.get(0).equalsIgnoreCase("all")) { + player.getAvatars().forEach(this::resetConstellation); + player.dropMessage("Reset all avatars' constellations."); + } else { + EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity(); + if(entity == null) + return; + + GenshinAvatar avatar = entity.getAvatar(); + this.resetConstellation(avatar); + + player.dropMessage("Constellations for " + avatar.getAvatarData().getName() + " have been reset. Please relog to see changes."); + } + } + + private void resetConstellation(GenshinAvatar avatar) { + avatar.getTalentIdList().clear(); + avatar.setCoreProudSkillLevel(0); + avatar.recalcStats(); + avatar.save(); + } + } + + @Command(label = "godmode", + usage = "Usage: godmode", execution = Command.Execution.PLAYER) + public static class GodModeCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + player.setGodmode(!player.inGodmode()); + player.dropMessage("Godmode is now " + (player.inGodmode() ? "enabled" : "disabled") + "."); + } + } + + @Command(label = "sethealth", aliases = {"sethp"}, + usage = "Usage: sethealth ", execution = Command.Execution.PLAYER) + public static class SetHealthCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + if(args.size() < 1) { + CommandHandler.sendMessage(null, "Usage: sethealth "); return; + } + + try { + int health = Integer.parseInt(args.get(0)); + EntityAvatar entity = player.getTeamManager().getCurrentAvatarEntity(); + if(entity == null) + return; + + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health); + entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + player.dropMessage("Health set to " + health + "."); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid health value."); + } + } + } + + @Command(label = "clearartifacts", aliases = {"clearart"}, + usage = "Usage: clearartifacts", execution = Command.Execution.PLAYER) + public static class ClearArtifactsCommand implements CommandHandler { + + @Override + public void execute(GenshinPlayer player, List args) { + Inventory playerInventory = player.getInventory(); + playerInventory.getItems().values().stream() + .filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY) + .filter(item -> item.getLevel() == 1 && item.getExp() == 0) + .filter(item -> !item.isLocked() && !item.isEquipped()) + .forEach(item -> playerInventory.removeItem(item, item.getCount())); + } + } } diff --git a/src/main/java/emu/grasscutter/commands/ServerCommands.java b/src/main/java/emu/grasscutter/commands/ServerCommands.java new file mode 100644 index 000000000..193ec2b50 --- /dev/null +++ b/src/main/java/emu/grasscutter/commands/ServerCommands.java @@ -0,0 +1,121 @@ +package emu.grasscutter.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.Account; +import emu.grasscutter.game.GenshinPlayer; + +import java.util.List; + +/** + * A container for server-related commands. + */ +public final class ServerCommands { + @Command(label = "reload", usage = "Usage: reload") + public static class ReloadCommand implements CommandHandler { + + @Override + public void execute(List args) { + Grasscutter.getLogger().info("Reloading config."); + Grasscutter.loadConfig(); + Grasscutter.getDispatchServer().loadQueries(); + Grasscutter.getLogger().info("Reload complete."); + } + + @Override + public void execute(GenshinPlayer player, List args) { + this.execute(args); + } + } + + @Command(label = "sendmessage", aliases = {"sendmsg", "msg"}, + usage = "Usage: sendmessage ") + public static class SendMessageCommand implements CommandHandler { + + @Override + public void execute(List args) { + if(args.size() < 2) { + CommandHandler.sendMessage(null, "Usage: sendmessage "); return; + } + + try { + int target = Integer.parseInt(args.get(0)); + String message = String.join(" ", args.subList(1, args.size())); + + GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerById(target); + if(targetPlayer == null) { + CommandHandler.sendMessage(null, "Player not found."); return; + } + + targetPlayer.dropMessage(message); + CommandHandler.sendMessage(null, "Message sent."); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid player ID."); + } + } + + @Override + public void execute(GenshinPlayer player, List args) { + if(args.size() < 2) { + CommandHandler.sendMessage(null, "Usage: sendmessage "); return; + } + + try { + int target = Integer.parseInt(args.get(0)); + String message = String.join(" ", args.subList(1, args.size())); + + GenshinPlayer targetPlayer = Grasscutter.getGameServer().getPlayerById(target); + if(targetPlayer == null) { + CommandHandler.sendMessage(null, "Player not found."); return; + } + + targetPlayer.sendMessage(player, message); + CommandHandler.sendMessage(null, "Message sent."); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid player ID."); + } + } + } + + @Command(label = "account", + usage = "Usage: account [uid]", + execution = Command.Execution.CONSOLE) + public static class AccountCommand implements CommandHandler { + + @Override + public void execute(List args) { + if(args.size() < 2) { + CommandHandler.sendMessage(null, "Usage: account [uid]"); return; + } + + String action = args.get(0); + String username = args.get(1); + + switch(action) { + default: + CommandHandler.sendMessage(null, "Usage: account [uid]"); + return; + case "create": + int uid = 0; + if(args.size() > 2) { + try { + uid = Integer.parseInt(args.get(2)); + } catch (NumberFormatException ignored) { + CommandHandler.sendMessage(null, "Invalid UID."); return; + } + } + + Account account = DatabaseHelper.createAccountWithId(username, uid); + if(account == null) { + CommandHandler.sendMessage(null, "Account already exists."); return; + } else CommandHandler.sendMessage(null, "Account created with UID " + account.getId() + "."); + return; + case "delete": + if(DatabaseHelper.deleteAccount(username)) { + CommandHandler.sendMessage(null, "Account deleted."); return; + } else CommandHandler.sendMessage(null, "Account not found."); + return; + } + } + } +} diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java index 57a561289..f9f1521e1 100644 --- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java +++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java @@ -485,7 +485,7 @@ public class GenshinPlayer { this.regionId = regionId; } - public boolean hasGodmode() { + public boolean inGodmode() { return godmode; } @@ -558,6 +558,15 @@ public class GenshinPlayer { public void dropMessage(Object message) { this.sendPacket(new PacketPrivateChatNotify(GenshinConstants.SERVER_CONSOLE_UID, getId(), message.toString())); } + + /** + * Sends a message to another player. + * @param sender The sender of the message. + * @param message The message to send. + */ + public void sendMessage(GenshinPlayer sender, Object message) { + this.sendPacket(new PacketPrivateChatNotify(sender.getId(), this.getId(), message.toString())); + } public void interactWith(int gadgetEntityId) { GenshinEntity entity = getWorld().getEntityById(gadgetEntityId); diff --git a/src/main/java/emu/grasscutter/game/World.java b/src/main/java/emu/grasscutter/game/World.java index a06b584f1..78744c0c1 100644 --- a/src/main/java/emu/grasscutter/game/World.java +++ b/src/main/java/emu/grasscutter/game/World.java @@ -344,7 +344,7 @@ public class World implements Iterable { // Godmode check if (target instanceof EntityAvatar) { - if (((EntityAvatar) target).getPlayer().hasGodmode()) { + if (((EntityAvatar) target).getPlayer().inGodmode()) { return; } } diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index 4293193d1..d4d1063a3 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -118,6 +118,16 @@ public final class Utils { } } + /** + * Get object with null fallback. + * @param nonNull The object to return if not null. + * @param fallback The object to return if null. + * @return One of the two provided objects. + */ + public static T requireNonNullElseGet(T nonNull, T fallback) { + return nonNull != null ? nonNull : fallback; + } + /** * Checks for required files and folders before startup. */