/*
* This file is part of Skript.
*
* Skript 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.
*
* Skript 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 Skript. If not, see <http://www.gnu.org/licenses/>.
*
*
* Copyright 2011-2014 Peter Güttinger
*
*/
package ch.njol.skript.expressions;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Furnace;
import org.bukkit.event.Event;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.Nullable;
import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.effects.Delay;
import ch.njol.skript.expressions.base.PropertyExpression;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.Getter;
import ch.njol.skript.util.InventorySlot;
import ch.njol.skript.util.Slot;
import ch.njol.util.Kleenean;
/**
* @author Peter Güttinger
*/
@Name("Furnace Slot")
@Description({"A slot of a furnace, i.e. either the ore, fuel or result slot.",
"Remember to use '<a href='#ExprBlock'>block</a>' and not 'furnace', as 'furnace' is not an existing expression."})
@Examples({"set the fuel slot of the clicked block to a lava bucket",
"set the block's ore slot to 64 iron ore",
"give the result of the block to the player",
"clear the result slot of the block"})
@Since("1.0")
public class ExprFurnaceSlot extends PropertyExpression<Block, Slot> {
private final static int ORE = 0, FUEL = 1, RESULT = 2;
private final static String[] slotNames = {"ore", "fuel", "result"};
static {
register(ExprFurnaceSlot.class, Slot.class, "(" + ORE + "¦ore|" + FUEL + "¦fuel|" + RESULT + "¦result)[s] [slot[s]]", "blocks");
}
int slot;
@SuppressWarnings({"unchecked", "null"})
@Override
public boolean init(final Expression<?>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parser) {
setExpr((Expression<Block>) exprs[0]);
slot = parser.mark;
return true;
}
private final class FurnaceEventSlot extends InventorySlot {
private final Event e;
public FurnaceEventSlot(final Event e, final FurnaceInventory invi) {
super(invi, slot);
this.e = e;
}
@Override
@Nullable
public ItemStack getItem() {
if (e instanceof FurnaceSmeltEvent) {
if (slot == RESULT) {
if (getTime() >= 0)
return ((FurnaceSmeltEvent) e).getResult().clone();
else
return super.getItem();
} else if (slot == ORE) {
if (getTime() <= 0) {
return super.getItem();
} else {
final ItemStack i = super.getItem();
if (i == null)
return null;
i.setAmount(i.getAmount() - 1);
return i.getAmount() == 0 ? new ItemStack(Material.AIR, 1) : i;
}
} else {
return super.getItem();
}
} else {
if (slot == FUEL) {
if (getTime() <= 0) {
return super.getItem();
} else {
final ItemStack i = super.getItem();
if (i == null)
return null;
i.setAmount(i.getAmount() - 1);
return i.getAmount() == 0 ? new ItemStack(Material.AIR, 1) : i;
}
} else {
return super.getItem();
}
}
}
@SuppressWarnings("synthetic-access")
@Override
public void setItem(final @Nullable ItemStack item) {
if (e instanceof FurnaceSmeltEvent) {
if (slot == RESULT && getTime() >= 0) {
if (item == null || item.getType() == Material.AIR) { // null/air crashes the server on account of a NPE if using event.setResult(...)
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
FurnaceEventSlot.super.setItem(null);
}
});
} else {
((FurnaceSmeltEvent) e).setResult(item);
}
} else if (slot == ORE && getTime() >= 0) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
FurnaceEventSlot.super.setItem(item);
}
});
} else {
super.setItem(item);
}
} else {
if (slot == FUEL && getTime() >= 0) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Skript.getInstance(), new Runnable() {
@Override
public void run() {
FurnaceEventSlot.super.setItem(item);
}
});
} else {
super.setItem(item);
}
}
}
}
@Override
@Nullable
protected Slot[] get(final Event e, final Block[] source) {
return get(source, new Getter<Slot, Block>() {
@SuppressWarnings("null")
@Override
@Nullable
public Slot get(final Block b) {
if (b.getType() != Material.FURNACE && b.getType() != Material.BURNING_FURNACE)
return null;
if (getTime() >= 0 && (e instanceof FurnaceSmeltEvent && b.equals(((FurnaceSmeltEvent) e).getBlock()) || e instanceof FurnaceBurnEvent && b.equals(((FurnaceBurnEvent) e).getBlock())) && !Delay.isDelayed(e)) {
return new FurnaceEventSlot(e, ((Furnace) b.getState()).getInventory());
} else {
return new InventorySlot(((Furnace) b.getState()).getInventory(), slot);
}
}
});
}
@Override
public Class<Slot> getReturnType() {
return Slot.class;
}
@Override
public String toString(final @Nullable Event e, final boolean debug) {
if (e == null)
return "the " + (getTime() == -1 ? "past " : getTime() == 1 ? "future " : "") + slotNames[slot] + " slot of " + getExpr().toString(e, debug);
return Classes.getDebugMessage(getSingle(e));
}
@SuppressWarnings("unchecked")
@Override
public boolean setTime(final int time) {
return super.setTime(time, getExpr(), FurnaceSmeltEvent.class, FurnaceBurnEvent.class);
}
}