/*
* CraftZ
* Copyright (C) JangoBrick <http://jangobrick.de/>
*
* 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 craftZ.worldData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Chest;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import craftZ.CraftZ;
import craftZ.modules.ChestRefiller;
import craftZ.util.EntityChecker;
import craftZ.util.ItemRenamer;
import craftZ.util.StackParser;
public class LootChest extends WorldDataObject {
private final ChestRefiller refiller;
private final String list;
private final Location loc;
private final String face;
private int refillCountdown, despawnCountdown;
public LootChest(ChestRefiller refiller, ConfigurationSection data) {
this(refiller, data.getName(), data.getString("list"),
new Location(refiller.world(), data.getInt("coords.x"), data.getInt("coords.y"), data.getInt("coords.z")),
data.getString("face"));
}
public LootChest(ChestRefiller refiller, String id, String list, Location loc, String face) {
super(id);
this.refiller = refiller;
this.list = list;
this.loc = loc;
this.face = face == null ? "n" : face.toLowerCase();
}
public String getList() {
return list;
}
public Location getLocation() {
return loc.clone();
}
public String getFace() {
return face;
}
public BlockFace getBlockFace() {
return face.equals("s") ? BlockFace.SOUTH
: (face.equals("e") ? BlockFace.EAST
: (face.equals("w") ? BlockFace.WEST
: BlockFace.NORTH));
}
public void save() {
save("Data.lootchests");
}
@Override
public void store(ConfigurationSection section) {
section.set("coords.x", loc.getBlockX());
section.set("coords.y", loc.getBlockY());
section.set("coords.z", loc.getBlockZ());
section.set("face", face);
section.set("list", list);
}
public List<String> getLootDefinitions(boolean multiplied) {
List<String> defs = refiller.getConfig("loot").getStringList("Loot.lists." + list);
List<String> ndefs = new ArrayList<String>();
if (!multiplied || defs == null)
return ndefs;
for (int i=0; i<defs.size(); i++) {
String str = defs.get(i);
int count = 1;
String itm = str;
Pattern pattern = Pattern.compile("^([0-9]+)x");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
count = Integer.parseInt(matcher.group(1));
itm = str.substring(matcher.end());
}
for (int a=0; a<count; a++) {
ndefs.add(itm);
}
}
return ndefs;
}
public void refill(boolean placeChest) {
Block block = loc.getBlock();
double mpv = refiller.getPropertyInt("max-player-vicinity", list);
if ((mpv > 0 && EntityChecker.areEntitiesNearby(loc, mpv, EntityType.PLAYER, 1))
|| (!placeChest && block.getType() != Material.CHEST)) {
startRefill(false);
return;
}
block.setType(Material.CHEST);
Chest chest = (Chest) block.getState();
Inventory inv = chest.getInventory();
BlockFace face = getBlockFace();
((org.bukkit.material.Chest) chest.getData()).setFacingDirection(face);
for (Iterator<ItemStack> it=inv.iterator(); it.hasNext(); ) { // do not refill if already full
ItemStack stack = it.next();
if (stack != null && stack.getType() != Material.AIR) {
if (refiller.getPropertyBoolean("despawn", list)) {
despawnCountdown = refiller.getPropertyInt("time-before-despawn", list) * 20;
}
return;
}
}
List<String> defs = getLootDefinitions(true);
if (!defs.isEmpty()) {
int min = refiller.getPropertyInt("min-stacks-filled", list);
int max = refiller.getPropertyInt("max-stacks-filled", list);
for (int i = 0, n = (min + (max > min ? CraftZ.RANDOM.nextInt(max - min) : 0)); i < n; i++) {
ItemStack stack = StackParser.fromString(defs.get(CraftZ.RANDOM.nextInt(defs.size())), false);
if (stack != null) {
chest.getInventory().addItem(stack);
}
}
ItemRenamer.on(chest).setSpecificNames(ItemRenamer.DEFAULT_MAP);
}
if (refiller.getPropertyBoolean("despawn", list)) {
despawnCountdown = refiller.getPropertyInt("time-before-despawn", list) * 20;
}
}
public void startRefill(boolean drop) {
refillCountdown = refiller.getPropertyInt("time-before-refill", list) * 20;
Block block = loc.getBlock();
try { // try-catch-clause is workaround for NPE when Bukkit calls CraftInventory.getSize() [got an idea why this happens, anybody?]
BlockState bs = block.getState();
if (bs instanceof Chest && !drop)
((Chest) bs).getInventory().clear();
} catch (NullPointerException ex) { }
block.setType(Material.AIR);
}
public void onServerTick() {
if (despawnCountdown > 0) {
if (--despawnCountdown <= 0)
startRefill(refiller.getPropertyBoolean("drop-on-despawn", list));
} else if (refillCountdown > 0) {
if (--refillCountdown <= 0)
refill(true);
}
}
}