Last active
August 29, 2015 14:03
-
-
Save NeatMonster/f29b5fcb681c4231102c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fr.neatmonster.keylocks; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.UUID; | |
import org.bukkit.ChatColor; | |
import org.bukkit.Material; | |
import org.bukkit.Sound; | |
import org.bukkit.block.Block; | |
import org.bukkit.block.BlockFace; | |
import org.bukkit.block.Chest; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.block.Action; | |
import org.bukkit.event.block.BlockBreakEvent; | |
import org.bukkit.event.block.BlockPlaceEvent; | |
import org.bukkit.event.entity.EntityExplodeEvent; | |
import org.bukkit.event.inventory.InventoryClickEvent; | |
import org.bukkit.event.inventory.InventoryCloseEvent; | |
import org.bukkit.event.inventory.InventoryDragEvent; | |
import org.bukkit.event.inventory.PrepareItemCraftEvent; | |
import org.bukkit.event.player.PlayerDropItemEvent; | |
import org.bukkit.event.player.PlayerInteractEntityEvent; | |
import org.bukkit.event.player.PlayerInteractEvent; | |
import org.bukkit.inventory.AnvilInventory; | |
import org.bukkit.inventory.CraftingInventory; | |
import org.bukkit.inventory.Inventory; | |
import org.bukkit.inventory.ItemStack; | |
import org.bukkit.inventory.ShapedRecipe; | |
import org.bukkit.inventory.meta.ItemMeta; | |
import org.bukkit.plugin.java.JavaPlugin; | |
public class KeyLocks extends JavaPlugin implements Listener { | |
private static final ItemStack BUNCHOFKEYS; | |
private static final ItemMeta BUNCHOFKEYS_META; | |
private static final int BUNCHOFKEYS_SIZE = 9; | |
private static final ItemMeta CHEST_META; | |
private static final ItemStack KEY; | |
private static final ItemStack KEY_CLONE; | |
private static final ItemMeta KEY_META; | |
private static final ItemStack MASTERKEY; | |
private static final ItemMeta MASTERKEY_META; | |
static { | |
KEY = new ItemStack(Material.TRIPWIRE_HOOK); | |
KEY_META = KEY.getItemMeta(); | |
KEY_META.setDisplayName(ChatColor.GOLD + "Key"); | |
KEY.setItemMeta(KEY_META); | |
KEY_CLONE = KEY.clone(); | |
KEY_CLONE.setAmount(2); | |
BUNCHOFKEYS = new ItemStack(Material.NAME_TAG); | |
BUNCHOFKEYS_META = BUNCHOFKEYS.getItemMeta(); | |
BUNCHOFKEYS_META.setDisplayName(ChatColor.GOLD + "Bunch of Keys"); | |
BUNCHOFKEYS.setItemMeta(BUNCHOFKEYS_META); | |
CHEST_META = new ItemStack(Material.CHEST).getItemMeta(); | |
CHEST_META.setDisplayName(ChatColor.GOLD + "Locked Chest"); | |
MASTERKEY = new ItemStack(Material.TRIPWIRE_HOOK); | |
MASTERKEY_META = MASTERKEY.getItemMeta(); | |
MASTERKEY_META.setDisplayName(ChatColor.GOLD + "Master Key"); | |
MASTERKEY.setItemMeta(MASTERKEY_META); | |
} | |
private static String getChestName(final Block block) { | |
if (block != null && block.getType() == Material.CHEST) | |
return ((Chest) block.getState()).getInventory().getName(); | |
return null; | |
} | |
private static List<String> getLore(final ItemStack item) { | |
final List<String> lore = new ArrayList<String>(); | |
if (item != null && item.hasItemMeta() && item.getItemMeta().getLore() != null) | |
lore.addAll(item.getItemMeta().getLore()); | |
return lore; | |
} | |
private static String getUUID(final String name) { | |
if (name != null && name.contains("#")) | |
return name.split("#")[1].replaceAll(ChatColor.COLOR_CHAR + "", ""); | |
return null; | |
} | |
private static boolean isBunchOfKeys(final ItemStack item) { | |
return item != null && item.getType() == Material.NAME_TAG && item.hasItemMeta() | |
&& item.getItemMeta().getDisplayName().equals(BUNCHOFKEYS_META.getDisplayName()); | |
} | |
private static boolean isChest(final ItemStack item) { | |
return item != null && item.getType() == Material.CHEST && item.hasItemMeta() | |
&& item.getItemMeta().getDisplayName().startsWith(CHEST_META.getDisplayName()); | |
} | |
private static boolean isKey(final ItemStack item) { | |
return item != null && item.getType() == Material.TRIPWIRE_HOOK && item.hasItemMeta() | |
&& item.getItemMeta().getDisplayName().equals(KEY_META.getDisplayName()); | |
} | |
private static boolean isMasterKey(final ItemStack item) { | |
return item != null && item.getType() == Material.TRIPWIRE_HOOK && item.hasItemMeta() | |
&& item.getItemMeta().getDisplayName().equals(MASTERKEY_META.getDisplayName()); | |
} | |
private static String obfuscate(final String text) { | |
String obfuscated = ""; | |
for (final char c : text.toCharArray()) | |
obfuscated += ChatColor.COLOR_CHAR + "" + c; | |
return obfuscated; | |
} | |
private static void setChestName(final Block block, final String name) { | |
try { | |
if (block != null && block.getType() == Material.CHEST) { | |
final Chest chest = (Chest) block.getState(); | |
final Field chestField = chest.getClass().getDeclaredField("chest"); | |
chestField.setAccessible(true); | |
final Object tileEntityChest = chestField.get(chest); | |
final Method aMethod = tileEntityChest.getClass().getMethod("a", String.class); | |
aMethod.invoke(tileEntityChest, name); | |
} | |
} catch (final Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
private static void setLore(final ItemStack item, final List<String> lore) { | |
if (item != null) { | |
final ItemMeta itemMeta = item.getItemMeta(); | |
itemMeta.setLore(lore); | |
item.setItemMeta(itemMeta); | |
} | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onBlockBreak(final BlockBreakEvent event) { | |
final Block block = event.getBlock(); | |
final String name = getChestName(block); | |
if (getUUID(name) != null) { | |
block.setType(Material.AIR); | |
final ItemStack chest = new ItemStack(Material.CHEST); | |
final ItemMeta chestMeta = chest.getItemMeta(); | |
chestMeta.setDisplayName(name); | |
chest.setItemMeta(chestMeta); | |
block.getWorld().dropItemNaturally(block.getLocation(), chest); | |
for (final BlockFace face : Arrays.asList(BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST)) | |
if (getChestName(block.getRelative(face)) != null) | |
setChestName(block.getRelative(face), null); | |
} | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onBlockPlace(final BlockPlaceEvent event) { | |
if (isKey(event.getItemInHand()) || isMasterKey(event.getItemInHand())) | |
event.setCancelled(true); | |
} | |
@Override | |
public void onEnable() { | |
getServer().getPluginManager().registerEvents(this, this); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onEntityExplode(final EntityExplodeEvent event) { | |
for (final Block block : new ArrayList<Block>(event.blockList())) | |
if (getChestName(block) != null) | |
event.blockList().remove(block); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onInventoryClick(final InventoryClickEvent event) { | |
final ItemStack item = event.getCurrentItem(); | |
final ItemStack cursor = event.getCursor(); | |
if (isBunchOfKeys(item) && getLore(item).size() == 0) | |
event.setCancelled(true); | |
else if (event.getInventory().getName().equals(BUNCHOFKEYS_META.getDisplayName()) | |
&& event.getRawSlot() < BUNCHOFKEYS_SIZE && item != null && (!isKey(item) || getLore(item).size() == 0) | |
&& cursor != null && (!isKey(cursor) || getLore(cursor).size() == 0)) | |
event.setCancelled(true); | |
else if (event.getInventory().getName().equals(BUNCHOFKEYS_META.getDisplayName()) | |
&& event.getRawSlot() < BUNCHOFKEYS_SIZE && cursor != null && isKey(cursor) | |
&& getLore(cursor).size() > 0) | |
for (int slot = 0; slot < BUNCHOFKEYS_SIZE; slot++) | |
if (cursor.equals(event.getInventory().getItem(slot))) { | |
event.setCancelled(true); | |
break; | |
} else if (event.getInventory() instanceof AnvilInventory && event.getRawSlot() == 0 && cursor != null | |
&& (isChest(cursor) || isKey(cursor) || isBunchOfKeys(cursor) || isMasterKey(cursor))) | |
event.setCancelled(true); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onInventoryClose(final InventoryCloseEvent event) { | |
final ItemStack item = event.getPlayer().getItemInHand(); | |
if (isBunchOfKeys(item) && getLore(item).size() == 0) { | |
final List<String> lore = new ArrayList<String>(); | |
for (final ItemStack key : event.getInventory().all(Material.TRIPWIRE_HOOK).values()) | |
lore.addAll(key.getItemMeta().getLore()); | |
if (lore.isEmpty()) | |
event.getPlayer().getInventory().setItemInHand(null); | |
else | |
setLore(item, lore); | |
} | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onInventoryDrag(final InventoryDragEvent event) { | |
final ItemStack cursor = event.getOldCursor(); | |
if (event.getInventory().getName().equals(BUNCHOFKEYS_META.getDisplayName())) | |
for (final int slot : event.getRawSlots()) | |
if (slot < BUNCHOFKEYS_SIZE && cursor != null && (!isKey(cursor) || getLore(cursor).size() == 0)) { | |
event.setCancelled(true); | |
break; | |
} | |
} | |
@Override | |
public void onLoad() { | |
final ShapedRecipe keyRecipe = new ShapedRecipe(KEY); | |
keyRecipe.shape(new String[] { "I", "L" }); | |
keyRecipe.setIngredient('I', Material.IRON_INGOT); | |
keyRecipe.setIngredient('L', Material.LEVER); | |
getServer().addRecipe(keyRecipe); | |
final ShapedRecipe cloneRecipe = new ShapedRecipe(KEY_CLONE); | |
cloneRecipe.shape(new String[] { "TT" }); | |
cloneRecipe.setIngredient('T', Material.TRIPWIRE_HOOK); | |
getServer().addRecipe(cloneRecipe); | |
final ShapedRecipe bunchOfKeysRecipe = new ShapedRecipe(BUNCHOFKEYS); | |
bunchOfKeysRecipe.shape(" S ", "STS", " S "); | |
bunchOfKeysRecipe.setIngredient('S', Material.STRING); | |
bunchOfKeysRecipe.setIngredient('T', Material.TRIPWIRE_HOOK); | |
getServer().addRecipe(bunchOfKeysRecipe); | |
final ShapedRecipe masterKeyRecipe = new ShapedRecipe(MASTERKEY); | |
masterKeyRecipe.shape("C", "L"); | |
masterKeyRecipe.setIngredient('C', Material.COMMAND); | |
masterKeyRecipe.setIngredient('L', Material.LEVER); | |
getServer().addRecipe(masterKeyRecipe); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onPlayerDropItem(final PlayerDropItemEvent event) { | |
final ItemStack item = event.getItemDrop().getItemStack(); | |
if (isBunchOfKeys(item) && getLore(item).size() == 0) | |
event.setCancelled(true); | |
} | |
@EventHandler | |
public void onPlayerInteract(final PlayerInteractEvent event) { | |
final Block block = event.getClickedBlock(); | |
final String name = getChestName(block); | |
final ItemStack item = event.getItem(); | |
final boolean isKey = isKey(item); | |
final boolean isBunchOfKeys = isBunchOfKeys(item); | |
final boolean isMasterKey = isMasterKey(item); | |
final boolean isBlank = (isKey || isBunchOfKeys) && getLore(item).size() == 0; | |
String uuid = getUUID(name); | |
if (event.getAction() == Action.LEFT_CLICK_BLOCK && name != null && uuid == null && isKey && isBlank) { | |
uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8); | |
setChestName(block, CHEST_META.getDisplayName() + obfuscate("#" + uuid)); | |
final String lore = ChatColor.BLUE + "" + block.getX() + ", " + block.getY() + ", " + block.getZ(); | |
if (item.getAmount() == 1) | |
setLore(item, Arrays.asList(lore + obfuscate("#" + uuid))); | |
else { | |
item.setAmount(item.getAmount() - 1); | |
final ItemStack singleItem = item.clone(); | |
singleItem.setAmount(1); | |
setLore(singleItem, Arrays.asList(lore + obfuscate("#" + uuid))); | |
event.getPlayer().getInventory().addItem(singleItem); | |
} | |
block.getWorld().playSound(block.getLocation(), Sound.ANVIL_USE, 1f, 1f); | |
} else if (name != null) { | |
if (uuid == null || isMasterKey) | |
return; | |
if (isKey && !isBlank || isBunchOfKeys) | |
for (final String oldLore : getLore(item)) | |
if (uuid.equals(getUUID(oldLore))) { | |
final String newLore = ChatColor.BLUE + "" + block.getX() + ", " + block.getY() + ", " | |
+ block.getZ() + obfuscate("#" + uuid); | |
if (!oldLore.equals(newLore)) { | |
final List<String> lore = getLore(item); | |
lore.set(lore.indexOf(oldLore), newLore); | |
setLore(item, lore); | |
} | |
return; | |
} | |
block.getWorld().playSound(block.getLocation(), Sound.ITEM_BREAK, 1f, 1f); | |
} else if (event.getAction() == Action.RIGHT_CLICK_AIR && isBunchOfKeys) { | |
final Inventory inventory = getServer().createInventory(event.getPlayer(), BUNCHOFKEYS_SIZE, | |
item.getItemMeta().getDisplayName()); | |
inventory.setMaxStackSize(1); | |
for (final String lore : getLore(item)) { | |
final ItemStack keyItem = KEY.clone(); | |
setLore(keyItem, Arrays.asList(lore)); | |
inventory.addItem(keyItem); | |
} | |
event.getPlayer().openInventory(inventory); | |
setLore(item, new ArrayList<String>()); | |
} else | |
return; | |
event.setCancelled(true); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onPlayerInteractEntity(final PlayerInteractEntityEvent event) { | |
if (isBunchOfKeys(event.getPlayer().getItemInHand())) | |
event.setCancelled(true); | |
} | |
@EventHandler(ignoreCancelled = true) | |
public void onPrepareItemCraft(final PrepareItemCraftEvent event) { | |
final CraftingInventory inventory = event.getInventory(); | |
if (event.getRecipe().getResult().equals(KEY_CLONE)) { | |
ItemStack key = null; | |
ItemStack blankKey = null; | |
for (final ItemStack item : inventory.all(Material.TRIPWIRE_HOOK).values()) { | |
key = isKey(item) && getLore(item).size() > 0 ? item : key; | |
blankKey = isKey(item) && getLore(item).size() == 0 ? item : blankKey; | |
} | |
if (key != null && blankKey != null) | |
setLore(inventory.getResult(), key.getItemMeta().getLore()); | |
else | |
inventory.setResult(null); | |
} else if (event.getRecipe().getResult().equals(BUNCHOFKEYS)) { | |
final ItemStack key = inventory.getItem(inventory.first(Material.TRIPWIRE_HOOK)); | |
if (isKey(key) && getLore(key).size() > 0) | |
setLore(inventory.getResult(), key.getItemMeta().getLore()); | |
else | |
event.getInventory().setResult(null); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: KeyLocks | |
version: 1.0.1 | |
author: NeatMonster | |
main: fr.neatmonster.keylocks.KeyLocks |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment