Skip to content

Instantly share code, notes, and snippets.

@NeatMonster
Created August 21, 2013 21:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NeatMonster/6300254 to your computer and use it in GitHub Desktop.
Save NeatMonster/6300254 to your computer and use it in GitHub Desktop.
package fr.neatmonster.chestdrop;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SkullType;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.block.Skull;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.Skeleton.SkeletonType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
public class ChestDrop extends JavaPlugin implements Listener {
private static class TypeAndData {
public static TypeAndData fromString(final String string) {
try {
final int typeId = Integer.parseInt(string.split(":")[0]);
byte data = (byte) 0;
if (string.split(":").length > 1)
data = (byte) Integer.parseInt(string.split(":")[1]);
return new TypeAndData(Material.getMaterial(typeId), data);
} catch (final Exception e) {
logger.warning(logTag + "Failed to parse '" + string + "'!");
return null;
}
}
private final byte data;
private final Material type;
public TypeAndData(final Material type) {
this(type, (byte) 0);
}
public TypeAndData(final Material type, final byte data) {
this.type = type;
this.data = data;
}
public byte getData() {
return data;
}
public Material getType() {
return type;
}
@Override
public String toString() {
return type.getId() + ":" + data;
}
}
private static final Logger logger = Logger.getLogger("Minecraft-Server");
private static final String logTag = "[ChestDrop] ";
private final Map<Location, Inventory> chestInventories = new HashMap<Location, Inventory>();
private final Map<Location, Long> chestTimes = new HashMap<Location, Long>();
private final Map<String, TypeAndData> chestTypes = new HashMap<String, TypeAndData>();
private int despawnTime = 10;
private boolean invincible = true;
private boolean playerChests = true;
private File saveFile = null;
private void load() {
try {
final YamlConfiguration saveConfig = new YamlConfiguration();
saveConfig.load(saveFile);
chestInventories.clear();
chestTimes.clear();
for (final String string : saveConfig.getKeys(false)) {
Inventory inventory = null;
if (!saveConfig.get(string).equals("<blank>")) {
@SuppressWarnings("unchecked")
final ItemStack[] content = ((List<ItemStack>) saveConfig.get(string)).toArray(new ItemStack[0]);
inventory = getServer().createInventory(null, content.length);
inventory.setContents(content);
}
chestInventories.put(toLocation(string), inventory);
chestTimes.put(toLocation(string), System.currentTimeMillis() - saveConfig.getLong("times." + string));
final Block block = toLocation(string).getBlock();
getServer().getScheduler().runTaskLater(this, new Runnable() {
@Override
public void run() {
chestInventories.remove(block.getLocation());
block.setType(Material.AIR);
chestTimes.remove(block.getLocation());
save();
}
}, despawnTime * 20L - saveConfig.getLong("times." + string) / 50L);
}
} catch (final Exception e) {
logger.severe(logTag + "Loading failed: " + e + ":");
}
}
@EventHandler
public void onBlockBreak(final BlockBreakEvent event) {
if (invincible && chestInventories.containsKey(event.getBlock().getLocation()))
event.setCancelled(true);
save();
}
@Override
public void onDisable() {
save();
}
@Override
public void onEnable() {
invincible = getConfig().getBoolean("invincible", true);
getConfig().set("invincible", invincible);
despawnTime = getConfig().getInt("despawnTime", 10);
getConfig().set("despawnTime", despawnTime);
playerChests = getConfig().getBoolean("playerChests", true);
getConfig().set("playerChests", playerChests);
for (final EntityType entityType : EntityType.values()) {
TypeAndData chestType;
switch (entityType) {
case SKELETON:
chestType = new TypeAndData(Material.SKULL, (byte) 0);
break;
case ZOMBIE:
chestType = new TypeAndData(Material.SKULL, (byte) 2);
break;
case PLAYER:
chestType = new TypeAndData(Material.SKULL, (byte) 3);
break;
case CREEPER:
chestType = new TypeAndData(Material.SKULL, (byte) 4);
break;
default:
chestType = new TypeAndData(Material.CHEST);
}
chestType = TypeAndData.fromString(getConfig().getString("chestTypes." + entityType.name(), chestType.toString()));
getConfig().set("chestTypes." + entityType.name(), chestType.toString());
chestTypes.put(entityType.name(), chestType);
}
TypeAndData chestType = new TypeAndData(Material.SKULL, (byte) 1);
chestType = TypeAndData.fromString(getConfig().getString("chestTypes.WITHER_SKELETON", chestType.toString()));
getConfig().set("chestTypes.WITHER_SKELETON", chestType.toString());
chestTypes.put("WITHER_SKELETON", chestType);
saveConfig();
saveFile = new File(getDataFolder().getPath(), "save.yml");
if (!saveFile.exists())
try {
saveFile.createNewFile();
} catch (final IOException e) {
}
getServer().getPluginManager().registerEvents(this, this);
load();
}
@EventHandler
public void onEntityDeath(final EntityDeathEvent event) {
if (event.getDrops().size() == 0 || !playerChests && event.getEntityType() == EntityType.PLAYER || event.getEntity().getKiller() == null
|| !(event.getEntity().getKiller() instanceof Player))
return;
String entityTypeName = event.getEntityType().name();
if (entityTypeName.equals("SKELETON") && ((Skeleton) event.getEntity()).getSkeletonType() == SkeletonType.WITHER)
entityTypeName = "WITHER_SKELETON";
final TypeAndData chestType = chestTypes.get(entityTypeName);
final Block block = event.getEntity().getLocation().getBlock();
block.setType(chestType.getType());
if (block.getType() == Material.SKULL) {
final Skull skull = (Skull) block.getState();
SkullType skullType;
switch (chestType.getData()) {
case 0:
skullType = SkullType.SKELETON;
break;
case 1:
skullType = SkullType.WITHER;
break;
case 2:
skullType = SkullType.ZOMBIE;
break;
case 4:
skullType = SkullType.CREEPER;
break;
default:
skullType = SkullType.PLAYER;
}
skull.setSkullType(skullType);
if (skullType == SkullType.PLAYER && event.getEntity() instanceof Player)
skull.setOwner(((Player) event.getEntity()).getName());
skull.update();
} else
block.setData(chestType.getData());
if (block.getType() == Material.CHEST) {
final Chest chest = (Chest) block.getState();
for (final ItemStack drop : event.getDrops())
chest.getInventory().addItem(drop);
chestInventories.put(block.getLocation(), null);
} else {
final int size = ((event.getDrops().size() - 1) / 9 + 1) * 9;
final Inventory inventory = getServer().createInventory(null, size);
for (final ItemStack drop : event.getDrops())
inventory.addItem(drop);
chestInventories.put(block.getLocation(), inventory);
}
event.getDrops().clear();
chestTimes.put(block.getLocation(), System.currentTimeMillis());
getServer().getScheduler().runTaskLater(this, new Runnable() {
@Override
public void run() {
chestInventories.remove(block.getLocation());
block.setType(Material.AIR);
chestTimes.remove(block.getLocation());
save();
}
}, despawnTime * 20L);
save();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerInteract(final PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getClickedBlock() == null || event.getClickedBlock().getType() == Material.CHEST
|| !chestInventories.containsKey(event.getClickedBlock().getLocation()))
return;
event.getPlayer().openInventory(chestInventories.get(event.getClickedBlock().getLocation()));
save();
}
private void save() {
try {
final YamlConfiguration saveConfig = new YamlConfiguration();
for (final Location location : chestInventories.keySet()) {
saveConfig.set(toString(location), chestInventories.get(location) == null ? "<blank>" : chestInventories.get(location).getContents());
saveConfig.set("times." + toString(location), System.currentTimeMillis() - chestTimes.get(location));
}
saveConfig.save(saveFile);
} catch (final Exception e) {
e.printStackTrace();
logger.severe(logTag + "Saving failed: " + e + "!");
}
}
private Location toLocation(final String string) {
final World world = getServer().getWorld(string.split("_")[0]);
final int x = Integer.parseInt(string.split("_")[1]);
final int y = Integer.parseInt(string.split("_")[2]);
final int z = Integer.parseInt(string.split("_")[3]);
return new Location(world, x, y, z);
}
private String toString(final Location location) {
return location.getWorld().getName() + "_" + location.getBlockX() + "_" + location.getBlockY() + "_" + location.getBlockZ();
}
}
name: ChestDrop
version: 1.0
author: NeatMonster
main: fr.neatmonster.chestdrop.ChestDrop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment