Dungeon items. Resolves #351

This commit is contained in:
Daniel Saukel 2018-08-11 18:30:59 +02:00
parent f29c6ed182
commit 397dd2c378
6 changed files with 257 additions and 0 deletions

View File

@ -37,6 +37,7 @@ public class DCommandCache extends DRECommandCache {
public static EnterCommand ENTER = new EnterCommand(); public static EnterCommand ENTER = new EnterCommand();
public static EscapeCommand ESCAPE = new EscapeCommand(); public static EscapeCommand ESCAPE = new EscapeCommand();
public static DeleteCommand DELETE = new DeleteCommand(); public static DeleteCommand DELETE = new DeleteCommand();
public static DungeonItemCommand DUNGEON_ITEM = new DungeonItemCommand();
public static GameCommand GAME = new GameCommand(); public static GameCommand GAME = new GameCommand();
public static GroupCommand GROUP = new GroupCommand(); public static GroupCommand GROUP = new GroupCommand();
public static HelpCommand HELP = new HelpCommand(); public static HelpCommand HELP = new HelpCommand();
@ -64,6 +65,7 @@ public class DCommandCache extends DRECommandCache {
BREAK, BREAK,
CREATE, CREATE,
DELETE, DELETE,
DUNGEON_ITEM,
EDIT, EDIT,
ENTER, ENTER,
ESCAPE, ESCAPE,

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2012-2018 Frank Baumann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.erethon.dungeonsxl.command;
import de.erethon.commons.chat.MessageUtil;
import de.erethon.commons.command.DRECommand;
import de.erethon.dungeonsxl.config.DMessage;
import de.erethon.dungeonsxl.player.DPermission;
import de.erethon.dungeonsxl.util.NBTUtil;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
/**
* @author Frank Baumann, Daniel Saukel
*/
public class DungeonItemCommand extends DRECommand {
public DungeonItemCommand() {
setCommand("dungeonItem");
setAliases("di");
setMinArgs(0);
setMaxArgs(1);
setHelp(DMessage.HELP_CMD_DUNGEON_ITEM.getMessage());
setPermission(DPermission.DUNGEON_ITEM.getNode());
setPlayerCommand(true);
setConsoleCommand(false);
}
@Override
public void onExecute(String[] args, CommandSender sender) {
Player player = (Player) sender;
PlayerInventory inv = player.getInventory();
ItemStack bukkitStack = inv.getItemInHand();
if (bukkitStack == null) {
MessageUtil.sendTitleMessage(player, DMessage.ERROR_NO_ITEM_IN_MAIN_HAND.getMessage());
return;
}
Object tag = NBTUtil.getTag(bukkitStack);
String action = args.length >= 2 ? args[1] : "info";
if (action.equalsIgnoreCase("true")) {
if (tag == null) {
tag = NBTUtil.createTag();
}
NBTUtil.addBoolean(tag, NBTUtil.DUNGEON_ITEM_KEY, true);
inv.setItemInHand(NBTUtil.setTag(bukkitStack, tag));
MessageUtil.sendMessage(sender, DMessage.CMD_DUNGEON_ITEM_SET_DUNGEON.getMessage());
MessageUtil.sendMessage(sender, DMessage.HELP_DUNGEON_ITEM.getMessage());
} else if (action.equalsIgnoreCase("false")) {
if (tag != null) {
NBTUtil.removeKey(tag, NBTUtil.DUNGEON_ITEM_KEY);
inv.setItemInHand(NBTUtil.setTag(bukkitStack, tag));
}
MessageUtil.sendMessage(sender, DMessage.CMD_DUNGEON_ITEM_INFO_GLOBAL.getMessage());
MessageUtil.sendMessage(sender, DMessage.HELP_GLOBAL_ITEM.getMessage());
} else {
if (tag != null && NBTUtil.hasKey(tag, NBTUtil.DUNGEON_ITEM_KEY)) {
MessageUtil.sendMessage(sender, DMessage.CMD_DUNGEON_ITEM_INFO_DUNGEON.getMessage());
MessageUtil.sendMessage(sender, DMessage.HELP_DUNGEON_ITEM.getMessage());
} else {
MessageUtil.sendMessage(sender, DMessage.CMD_DUNGEON_ITEM_INFO_GLOBAL.getMessage());
MessageUtil.sendMessage(sender, DMessage.HELP_GLOBAL_ITEM.getMessage());
}
}
}
}

View File

@ -37,6 +37,10 @@ public enum DMessage implements Message {
CMD_CHATSPY_START("Cmd_Chatspy_Start", "&6You started to spy the dungeon chat."), CMD_CHATSPY_START("Cmd_Chatspy_Start", "&6You started to spy the dungeon chat."),
CMD_DELETE_BACKUPS("Cmd_Delete_Backups", "&6Do you wish to delete all saved backups as well?"), CMD_DELETE_BACKUPS("Cmd_Delete_Backups", "&6Do you wish to delete all saved backups as well?"),
CMD_DELETE_SUCCESS("Cmd_Delete_Success", "&6Successfully deleted the map &4&v1&6."), CMD_DELETE_SUCCESS("Cmd_Delete_Success", "&6Successfully deleted the map &4&v1&6."),
CMD_DUNGEON_ITEM_INFO_DUNGEON("Cmd_DungeonItem_Info_Dungeon", "&6This item is a &4dungeon item&6."),
CMD_DUNGEON_ITEM_INFO_GLOBAL("Cmd_DungeonItem_Info_Global", "&6This item is a &4global item&6."),
CMD_DUNGEON_ITEM_SET_DUNGEON("Cmd_DungeonItem_Set_Dungeon", "&6Successfully made this item a &4dungeon item&6."),
CMD_DUNGEON_ITEM_SET_GLOBAL("Cmd_DungeonItem_Set_Global", "&6Successfully made this item a &4global item&6."),
CMD_ENTER_SUCCESS("Cmd_Enter", "&6The group &4&v1 &6successfully entered the game of the group &4&v2&6."), CMD_ENTER_SUCCESS("Cmd_Enter", "&6The group &4&v1 &6successfully entered the game of the group &4&v2&6."),
CMD_IMPORT_SUCCESS("Cmd_Import", "&6Successfully imported the world &4&v1&6."), CMD_IMPORT_SUCCESS("Cmd_Import", "&6Successfully imported the world &4&v1&6."),
CMD_INVITE_SUCCESS("Cmd_Invite_Success", "&6Player &4&v1&6 was successfully invited to edit the map &4&v2&6."), CMD_INVITE_SUCCESS("Cmd_Invite_Success", "&6Player &4&v1&6 was successfully invited to edit the map &4&v2&6."),
@ -77,6 +81,7 @@ public enum DMessage implements Message {
ERROR_NAME_TO_LONG("Error_NameToLong", "&4The name may not be longer than 15 characters!"), ERROR_NAME_TO_LONG("Error_NameToLong", "&4The name may not be longer than 15 characters!"),
ERROR_NO_CONSOLE_COMMAND("Error_NoConsoleCommand", "&6/dxl &v1&4 cannot be executed as console!"), ERROR_NO_CONSOLE_COMMAND("Error_NoConsoleCommand", "&6/dxl &v1&4 cannot be executed as console!"),
ERROR_NO_GAME("Error_NoGame", "&4You currently do not take part in a game."), ERROR_NO_GAME("Error_NoGame", "&4You currently do not take part in a game."),
ERROR_NO_ITEM_IN_MAIN_HAND("Error_NoItemInMainHand", "&4You do not have an item in your main hand."),
ERROR_NO_LEAVE_IN_TUTORIAL("Error_NoLeaveInTutorial", "&4You cannot use this command in the tutorial!"), ERROR_NO_LEAVE_IN_TUTORIAL("Error_NoLeaveInTutorial", "&4You cannot use this command in the tutorial!"),
ERROR_NO_PERMISSIONS("Error_NoPermissions", "&4You do not have permission to do this!"), ERROR_NO_PERMISSIONS("Error_NoPermissions", "&4You do not have permission to do this!"),
ERROR_NO_PLAYER_COMMAND("Error_NoPlayerCommand", "&6/dxl &v1&4 cannot be executed as player!"), ERROR_NO_PLAYER_COMMAND("Error_NoPlayerCommand", "&6/dxl &v1&4 cannot be executed as player!"),
@ -105,6 +110,7 @@ public enum DMessage implements Message {
HELP_CMD_CHATSPY("Help_Cmd_Chatspy", "/dxl chatspy - Dis/enables the spymode"), HELP_CMD_CHATSPY("Help_Cmd_Chatspy", "/dxl chatspy - Dis/enables the spymode"),
HELP_CMD_CREATE("Help_Cmd_Create", "/dxl create [name] - Creates a new dungeon map"), HELP_CMD_CREATE("Help_Cmd_Create", "/dxl create [name] - Creates a new dungeon map"),
HELP_CMD_DELETE("Help_Cmd_Delete", "/dxl delete [name] - Deletes a dungeon map"), HELP_CMD_DELETE("Help_Cmd_Delete", "/dxl delete [name] - Deletes a dungeon map"),
HELP_CMD_DUNGEON_ITEM("Help_Cmd_DungeonItem", "/dxl dungeonItem [true|false|info] - Sets the item stack in the player's hand to be one that cannot be taken out of a dungeon"),
HELP_CMD_EDIT("Help_Cmd_Edit", "/dxl edit [map] - Edit an existing dungeon map"), HELP_CMD_EDIT("Help_Cmd_Edit", "/dxl edit [map] - Edit an existing dungeon map"),
HELP_CMD_ENTER("Help_Cmd_Enter", "/dxl enter ([joining group]) [target group] - Let the joining group enter the game of the target group"), HELP_CMD_ENTER("Help_Cmd_Enter", "/dxl enter ([joining group]) [target group] - Let the joining group enter the game of the target group"),
HELP_CMD_ESCAPE("Help_Cmd_Escape", "/dxl escape - Leaves the current edit world without saving"), HELP_CMD_ESCAPE("Help_Cmd_Escape", "/dxl escape - Leaves the current edit world without saving"),
@ -138,6 +144,8 @@ public enum DMessage implements Message {
HELP_CMD_SETTINGS("Help_Cmd_Settings", "/dxl settings ([edit|global|player])- Opens the settings menu"), HELP_CMD_SETTINGS("Help_Cmd_Settings", "/dxl settings ([edit|global|player])- Opens the settings menu"),
HELP_CMD_TEST("Help_Cmd_Test", "/dxl test - Starts the game in test mode"), HELP_CMD_TEST("Help_Cmd_Test", "/dxl test - Starts the game in test mode"),
HELP_CMD_UNINVITE("Help_Cmd_Uninvite", "/dxl uninvite [player] [dungeon] - Uninvite a player to edit a dungeon"), HELP_CMD_UNINVITE("Help_Cmd_Uninvite", "/dxl uninvite [player] [dungeon] - Uninvite a player to edit a dungeon"),
HELP_DUNGEON_ITEM("Help_DungeonItem", "&6After finishing a game, &4dungeon items &6are removed from the player's inventory even if the respective dungeon setup in general allows to keep it."),
HELP_GLOBAL_ITEM("Help_GlobalItem", "&6After finishing a game, &4global items &6can be taken out of dungeons if the respective dungeon setup in general allows to keep the inventory."),
GROUP_BED_DESTROYED("Group_BedDestroyed", "&6The bed of the group &4&v1 &6has been destroyed by &4&v2&6!"), GROUP_BED_DESTROYED("Group_BedDestroyed", "&6The bed of the group &4&v1 &6has been destroyed by &4&v2&6!"),
GROUP_CONGRATS("Group_Congrats", "&6Congratulations!"), GROUP_CONGRATS("Group_Congrats", "&6Congratulations!"),
GROUP_CONGRATS_SUB("Group_CongratsSub", "&l&4Your group &v1 &4won the match!"), GROUP_CONGRATS_SUB("Group_CongratsSub", "&l&4Your group &v1 &4won the match!"),

View File

@ -26,6 +26,7 @@ import de.erethon.dungeonsxl.dungeon.Dungeon;
import de.erethon.dungeonsxl.event.dgroup.DGroupCreateEvent; import de.erethon.dungeonsxl.event.dgroup.DGroupCreateEvent;
import de.erethon.dungeonsxl.game.Game; import de.erethon.dungeonsxl.game.Game;
import de.erethon.dungeonsxl.global.DPortal; import de.erethon.dungeonsxl.global.DPortal;
import de.erethon.dungeonsxl.util.NBTUtil;
import de.erethon.dungeonsxl.world.DGameWorld; import de.erethon.dungeonsxl.world.DGameWorld;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@ -355,6 +356,16 @@ public class DGlobalPlayer implements PlayerWrapper {
} }
player.addPotionEffects(data.getOldPotionEffects()); player.addPotionEffects(data.getOldPotionEffects());
} else {
for (ItemStack item : player.getInventory().getStorageContents()) {
if (item == null) {
continue;
}
if (NBTUtil.isDungeonItem(item)) {
item.setAmount(0);
}
}
} }
} catch (NullPointerException exception) { } catch (NullPointerException exception) {

View File

@ -39,6 +39,7 @@ public enum DPermission {
CMD_EDIT("cmdedit", OP), CMD_EDIT("cmdedit", OP),
CREATE("create", OP), CREATE("create", OP),
DELETE("delete", OP), DELETE("delete", OP),
DUNGEON_ITEM("dungeonitem", OP),
EDIT("edit", OP), EDIT("edit", OP),
ENTER("enter", OP), ENTER("enter", OP),
ESCAPE("escape", TRUE), ESCAPE("escape", TRUE),

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2012-2018 Frank Baumann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.erethon.dungeonsxl.util;
import static de.erethon.commons.misc.ReflectionUtil.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.bukkit.inventory.ItemStack;
/**
* A minimalistic NMS ItemStack NBT util.
*
* @author Daniel Saukel
*/
public class NBTUtil {
public static final String DUNGEON_ITEM_KEY = "DungeonItem";
private static Method HAS_KEY;
private static Method REMOVE;
private static Method SET_BOOLEAN;
static {
try {
HAS_KEY = NBT_TAG_COMPOUND.getDeclaredMethod("hasKey", String.class);
REMOVE = NBT_TAG_COMPOUND.getDeclaredMethod("remove", String.class);
SET_BOOLEAN = NBT_TAG_COMPOUND.getDeclaredMethod("setBoolean", String.class, boolean.class);
} catch (NoSuchMethodException | SecurityException exception) {
exception.printStackTrace();
}
}
/**
* Returns the NBT data of an ItemStack
*
* @param item the Bukkit representation of the ItemStack
* @return the NBT data of the ItemStack
*/
public static Object getTag(ItemStack item) {
try {
return ITEM_STACK_GET_TAG.invoke(CRAFT_ITEM_STACK_AS_NMS_COPY.invoke(null, item));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
exception.printStackTrace();
return null;
}
}
/**
* Returns a new NBTTagCompound
*
* @return a new NBTTagCompound
*/
public static Object createTag() {
try {
return NBT_TAG_COMPOUND.newInstance();
} catch (IllegalAccessException | InstantiationException exception) {
exception.printStackTrace();
return null;
}
}
/**
* Returns a copy of the ItemStack with the applied NBT data
*
* @param item the Bukkit representation of the ItemStack
* @param tag the NBT data to set
* @return a new copy of the Bukkit ItemStack with the applied changes
*/
public static ItemStack setTag(ItemStack item, Object tag) {
try {
Object nmsStack = CRAFT_ITEM_STACK_AS_NMS_COPY.invoke(null, item);
ITEM_STACK_SET_TAG.invoke(nmsStack, tag);
return (ItemStack) CRAFT_ITEM_STACK_AS_BUKKIT_COPY.invoke(null, nmsStack);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
exception.printStackTrace();
return null;
}
}
/**
* Returns if the NBTTagCompound contains the key
*
* @param tag the NBTTagCompound
* @param key a key
* @return if the NBTTagCompound contains the key
*/
public static boolean hasKey(Object tag, String key) {
try {
return (boolean) HAS_KEY.invoke(tag, key);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
exception.printStackTrace();
return false;
}
}
/**
* Adds the key and its value to the NBTTagCompound
*
* @param tag the NBTTagCompound
* @param key the key to add
* @param value the value to add
*/
public static void addBoolean(Object tag, String key, boolean value) {
try {
SET_BOOLEAN.invoke(tag, key, value);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
exception.printStackTrace();
}
}
/**
* Removes the key from the NBTTagCompound
*
* @param tag the NBTTagCompound
* @param key the key to remove
*/
public static void removeKey(Object tag, String key) {
try {
REMOVE.invoke(tag, key);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
exception.printStackTrace();
}
}
/**
* Returns if the item is a dungeon item
*
* @param item a Bukkit ItemStack
* @return if the item is a dungeon item
*/
public static boolean isDungeonItem(ItemStack item) {
return getTag(item) != null && hasKey(getTag(item), DUNGEON_ITEM_KEY);
}
}