Created
August 21, 2013 21:03
-
-
Save NeatMonster/6300254 to your computer and use it in GitHub Desktop.
ChestDrop v1.0 - http://bukkit.fr/index.php?threads/9614/
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.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(); | |
} | |
} |
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: 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