buildcraft/common/buildcraft/transport/TravelingItem.java
2015-04-02 14:46:57 +02:00

330 lines
8.3 KiB
Java

/**
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.transport;
import java.util.EnumSet;
import java.util.Map;
import com.google.common.collect.MapMaker;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.BuildCraftCore;
import buildcraft.api.core.EnumColor;
import buildcraft.api.core.Position;
import buildcraft.core.lib.inventory.StackHelper;
public class TravelingItem {
public static final TravelingItemCache serverCache = new TravelingItemCache();
public static final TravelingItemCache clientCache = new TravelingItemCache();
public static final InsertionHandler DEFAULT_INSERTION_HANDLER = new InsertionHandler();
private static int maxId = 0;
public final EnumSet<ForgeDirection> blacklist = EnumSet.noneOf(ForgeDirection.class);
public double xCoord, yCoord, zCoord;
public final int id;
public boolean toCenter = true;
public EnumColor color;
public ForgeDirection input = ForgeDirection.UNKNOWN;
public ForgeDirection output = ForgeDirection.UNKNOWN;
protected float speed = 0.01F;
protected ItemStack itemStack;
protected TileEntity container;
protected NBTTagCompound extraData;
protected InsertionHandler insertionHandler = DEFAULT_INSERTION_HANDLER;
/* CONSTRUCTORS */
protected TravelingItem(int id) {
this.id = id;
}
public static TravelingItem make(int id) {
TravelingItem item = new TravelingItem(id);
getCache().cache(item);
return item;
}
public static TravelingItem make() {
return make(maxId < Short.MAX_VALUE ? ++maxId : (maxId = Short.MIN_VALUE));
}
public static TravelingItem make(double x, double y, double z, ItemStack stack) {
TravelingItem item = make();
item.xCoord = x;
item.yCoord = y;
item.zCoord = z;
item.itemStack = stack.copy();
return item;
}
public static TravelingItem make(NBTTagCompound nbt) {
TravelingItem item = make();
item.readFromNBT(nbt);
return item;
}
public static TravelingItemCache getCache() {
if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) {
return clientCache;
}
return serverCache;
}
/* GETTING & SETTING */
public void setPosition(double x, double y, double z) {
this.xCoord = x;
this.yCoord = y;
this.zCoord = z;
}
public void movePosition(double x, double y, double z) {
this.xCoord += x;
this.yCoord += y;
this.zCoord += z;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public ItemStack getItemStack() {
return itemStack;
}
public void setItemStack(ItemStack item) {
this.itemStack = item;
}
public TileEntity getContainer() {
return container;
}
public void setContainer(TileEntity container) {
this.container = container;
}
public NBTTagCompound getExtraData() {
if (extraData == null) {
extraData = new NBTTagCompound();
}
return extraData;
}
public boolean hasExtraData() {
return extraData != null;
}
@Deprecated
public void setInsetionHandler(InsertionHandler handler) {
if (handler == null) {
return;
}
this.insertionHandler = handler;
}
public void setInsertionHandler(InsertionHandler handler) {
if (handler == null) {
return;
}
this.insertionHandler = handler;
}
public InsertionHandler getInsertionHandler() {
return insertionHandler;
}
public void reset() {
toCenter = true;
blacklist.clear();
input = ForgeDirection.UNKNOWN;
output = ForgeDirection.UNKNOWN;
}
/* SAVING & LOADING */
public void readFromNBT(NBTTagCompound data) {
setPosition(data.getDouble("x"), data.getDouble("y"), data.getDouble("z"));
setSpeed(data.getFloat("speed"));
setItemStack(ItemStack.loadItemStackFromNBT(data.getCompoundTag("Item")));
toCenter = data.getBoolean("toCenter");
input = ForgeDirection.getOrientation(data.getByte("input"));
output = ForgeDirection.getOrientation(data.getByte("output"));
byte c = data.getByte("color");
if (c != -1) {
color = EnumColor.fromId(c);
}
if (data.hasKey("extraData")) {
extraData = data.getCompoundTag("extraData");
}
}
public void writeToNBT(NBTTagCompound data) {
data.setDouble("x", xCoord);
data.setDouble("y", yCoord);
data.setDouble("z", zCoord);
data.setFloat("speed", getSpeed());
NBTTagCompound itemStackTag = new NBTTagCompound();
getItemStack().writeToNBT(itemStackTag);
data.setTag("Item", itemStackTag);
data.setBoolean("toCenter", toCenter);
data.setByte("input", (byte) input.ordinal());
data.setByte("output", (byte) output.ordinal());
data.setByte("color", color != null ? (byte) color.ordinal() : -1);
if (extraData != null) {
data.setTag("extraData", extraData);
}
}
public EntityItem toEntityItem() {
if (container != null && !container.getWorldObj().isRemote) {
if (getItemStack().stackSize <= 0) {
return null;
}
Position motion = new Position(0, 0, 0, output);
motion.moveForwards(0.1 + getSpeed() * 2F);
EntityItem entity = new EntityItem(container.getWorldObj(), xCoord, yCoord, zCoord, getItemStack());
entity.lifespan = BuildCraftCore.itemLifespan * 20;
entity.delayBeforeCanPickup = 10;
float f3 = 0.00F + container.getWorldObj().rand.nextFloat() * 0.04F - 0.02F;
entity.motionX = (float) container.getWorldObj().rand.nextGaussian() * f3 + motion.x;
entity.motionY = (float) container.getWorldObj().rand.nextGaussian() * f3 + motion.y;
entity.motionZ = (float) container.getWorldObj().rand.nextGaussian() * f3 + +motion.z;
return entity;
}
return null;
}
public float getEntityBrightness(float f) {
int i = MathHelper.floor_double(xCoord);
int j = MathHelper.floor_double(zCoord);
if (container != null && container.getWorldObj().blockExists(i, 128 / 2, j)) {
double d = 0.66000000000000003D;
int k = MathHelper.floor_double(yCoord + d);
return container.getWorldObj().getLightBrightness(i, k, j);
} else {
return 0.0F;
}
}
public boolean isCorrupted() {
return itemStack == null || itemStack.stackSize <= 0 || itemStack.getItem() == null;
}
public boolean canBeGroupedWith(TravelingItem otherItem) {
if (otherItem == this) {
return false;
}
if (toCenter != otherItem.toCenter) {
return false;
}
if (output != otherItem.output) {
return false;
}
if (color != otherItem.color) {
return false;
}
if (hasExtraData() || otherItem.hasExtraData()) {
return false;
}
if (insertionHandler != DEFAULT_INSERTION_HANDLER) {
return false;
}
if (!blacklist.equals(otherItem.blacklist)) {
return false;
}
if (otherItem.isCorrupted()) {
return false;
}
return StackHelper.canStacksMerge(itemStack, otherItem.itemStack);
}
public boolean tryMergeInto(TravelingItem otherItem) {
if (!canBeGroupedWith(otherItem)) {
return false;
}
if (StackHelper.mergeStacks(itemStack, otherItem.itemStack, false) == itemStack.stackSize) {
StackHelper.mergeStacks(itemStack, otherItem.itemStack, true);
itemStack.stackSize = 0;
return true;
}
return false;
}
public boolean ignoreWeight() {
return false;
}
@Override
public int hashCode() {
return this.id;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TravelingItem other = (TravelingItem) obj;
if (this.id != other.id) {
return false;
}
return true;
}
@Override
public String toString() {
return "TravelingItem: " + id;
}
public static class InsertionHandler {
public boolean canInsertItem(TravelingItem item, IInventory inv) {
return true;
}
}
public static class TravelingItemCache {
private final Map<Integer, TravelingItem> itemCache = new MapMaker().weakValues().makeMap();
public void cache(TravelingItem item) {
itemCache.put(item.id, item);
}
public TravelingItem get(int id) {
return itemCache.get(id);
}
}
}