Files
refinedstorage/src/main/java/com/raoulvdberge/refinedstorage/RSUtils.java
Raoul Van den Berge e65fb4b7cf Fix more bugs
2016-11-27 13:48:47 +01:00

357 lines
13 KiB
Java
Executable File

package com.raoulvdberge.refinedstorage;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.storage.AccessType;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.storage.fluid.FluidStorageNBT;
import com.raoulvdberge.refinedstorage.apiimpl.storage.item.ItemStorageNBT;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
public final class RSUtils {
public static final ItemStack EMPTY_BUCKET = new ItemStack(Items.BUCKET);
public static final DecimalFormat QUANTITY_FORMATTER = new DecimalFormat("####0.#", DecimalFormatSymbols.getInstance(Locale.US));
private static final String NBT_INVENTORY = "Inventory_%d";
private static final String NBT_SLOT = "Slot";
private static final String NBT_ACCESS_TYPE = "AccessType";
static {
QUANTITY_FORMATTER.setRoundingMode(RoundingMode.DOWN);
}
public static void writeItemStack(ByteBuf buf, INetworkMaster network, ItemStack stack, boolean displayCraftText) {
buf.writeInt(Item.getIdFromItem(stack.getItem()));
buf.writeInt(stack.getCount());
buf.writeInt(stack.getItemDamage());
ByteBufUtils.writeTag(buf, stack.getItem().getNBTShareTag(stack));
buf.writeInt(API.instance().getItemStackHashCode(stack));
buf.writeBoolean(network.hasPattern(stack));
buf.writeBoolean(displayCraftText);
}
public static void writeFluidStack(ByteBuf buf, FluidStack stack) {
buf.writeInt(API.instance().getFluidStackHashCode(stack));
ByteBufUtils.writeUTF8String(buf, FluidRegistry.getFluidName(stack.getFluid()));
buf.writeInt(stack.amount);
ByteBufUtils.writeTag(buf, stack.tag);
}
public static Pair<Integer, FluidStack> readFluidStack(ByteBuf buf) {
return Pair.of(buf.readInt(), new FluidStack(FluidRegistry.getFluid(ByteBufUtils.readUTF8String(buf)), buf.readInt(), ByteBufUtils.readTag(buf)));
}
public static void createStorages(ItemStack disk, int slot, ItemStorageNBT[] itemStorages, FluidStorageNBT[] fluidStorages, Function<ItemStack, ItemStorageNBT> itemStorageSupplier, Function<ItemStack, FluidStorageNBT> fluidStorageNBTSupplier) {
if (disk.isEmpty()) {
itemStorages[slot] = null;
fluidStorages[slot] = null;
} else {
if (disk.getItem() == RSItems.STORAGE_DISK) {
itemStorages[slot] = itemStorageSupplier.apply(disk);
} else if (disk.getItem() == RSItems.FLUID_STORAGE_DISK) {
fluidStorages[slot] = fluidStorageNBTSupplier.apply(disk);
}
}
}
public static ItemStack getStack(@Nullable ItemStack stack) {
return stack == null ? ItemStack.EMPTY : stack;
}
public static NonNullList<ItemStack> toNonNullList(List<ItemStack> list) {
NonNullList<ItemStack> other = NonNullList.create();
for (ItemStack item : list) {
if (item != null) {
other.add(item);
}
}
return other;
}
public static void writeItems(IItemHandler handler, int id, NBTTagCompound tag) {
NBTTagList tagList = new NBTTagList();
for (int i = 0; i < handler.getSlots(); i++) {
if (!handler.getStackInSlot(i).isEmpty()) {
NBTTagCompound stackTag = new NBTTagCompound();
stackTag.setInteger(NBT_SLOT, i);
handler.getStackInSlot(i).writeToNBT(stackTag);
tagList.appendTag(stackTag);
}
}
tag.setTag(String.format(NBT_INVENTORY, id), tagList);
}
public static void readItems(IItemHandlerModifiable handler, int id, NBTTagCompound tag) {
String name = String.format(NBT_INVENTORY, id);
if (tag.hasKey(name)) {
NBTTagList tagList = tag.getTagList(name, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < tagList.tagCount(); i++) {
int slot = tagList.getCompoundTagAt(i).getInteger(NBT_SLOT);
if (slot >= 0 && slot < handler.getSlots()) {
handler.setStackInSlot(slot, new ItemStack(tagList.getCompoundTagAt(i)));
}
}
}
}
public static void writeItemsLegacy(IInventory inventory, int id, NBTTagCompound tag) {
NBTTagList tagList = new NBTTagList();
for (int i = 0; i < inventory.getSizeInventory(); i++) {
if (!inventory.getStackInSlot(i).isEmpty()) {
NBTTagCompound stackTag = new NBTTagCompound();
stackTag.setInteger(NBT_SLOT, i);
inventory.getStackInSlot(i).writeToNBT(stackTag);
tagList.appendTag(stackTag);
}
}
tag.setTag(String.format(NBT_INVENTORY, id), tagList);
}
public static void readItemsLegacy(IInventory inventory, int id, NBTTagCompound tag) {
String name = String.format(NBT_INVENTORY, id);
if (tag.hasKey(name)) {
NBTTagList tagList = tag.getTagList(name, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < tagList.tagCount(); i++) {
int slot = tagList.getCompoundTagAt(i).getInteger(NBT_SLOT);
ItemStack stack = new ItemStack(tagList.getCompoundTagAt(i));
if (!stack.isEmpty()) {
inventory.setInventorySlotContents(slot, stack);
}
}
}
}
public static NBTTagList serializeFluidStackList(IFluidStackList list) {
NBTTagList tagList = new NBTTagList();
for (FluidStack stack : list.getStacks()) {
tagList.appendTag(stack.writeToNBT(new NBTTagCompound()));
}
return tagList;
}
public static IFluidStackList readFluidStackList(NBTTagList tagList) {
IFluidStackList list = API.instance().createFluidStackList();
for (int i = 0; i < tagList.tagCount(); ++i) {
FluidStack stack = FluidStack.loadFluidStackFromNBT(tagList.getCompoundTagAt(i));
if (stack != null) {
list.add(stack);
}
}
return list;
}
public static void writeAccessType(NBTTagCompound tag, AccessType type) {
tag.setInteger(NBT_ACCESS_TYPE, type.getId());
}
public static AccessType readAccessType(NBTTagCompound tag) {
return tag.hasKey(NBT_ACCESS_TYPE) ? getAccessType(tag.getInteger(NBT_ACCESS_TYPE)) : AccessType.INSERT_EXTRACT;
}
public static AccessType getAccessType(int id) {
for (AccessType type : AccessType.values()) {
if (type.getId() == id) {
return type;
}
}
return AccessType.INSERT_EXTRACT;
}
public static IItemHandler getItemHandler(TileEntity tile, EnumFacing side) {
if (tile == null) {
return null;
}
IItemHandler handler = tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side) ? tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side) : null;
if (handler == null) {
if (side != null && tile instanceof ISidedInventory) {
handler = new SidedInvWrapper((ISidedInventory) tile, side);
} else if (tile instanceof IInventory) {
handler = new InvWrapper((IInventory) tile);
}
}
return handler;
}
public static IFluidHandler getFluidHandler(TileEntity tile, EnumFacing side) {
return (tile != null && tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side)) ? tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side) : null;
}
public static Pair<ItemStack, FluidStack> getFluidFromStack(ItemStack stack, boolean simulate) {
if (stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) {
IFluidHandlerItem fluidHandler = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);
FluidStack result = fluidHandler.drain(Fluid.BUCKET_VOLUME, !simulate);
return Pair.of(fluidHandler.getContainer(), result);
}
return Pair.of(null, null);
}
public static boolean hasFluidBucket(FluidStack stack) {
return stack.getFluid() == FluidRegistry.WATER || stack.getFluid() == FluidRegistry.LAVA || stack.getFluid().getName().equals("milk") || FluidRegistry.getBucketFluids().contains(stack.getFluid());
}
public static FluidStack copyStackWithSize(FluidStack stack, int size) {
FluidStack copy = stack.copy();
copy.amount = size;
return copy;
}
public static FluidStack copyStack(FluidStack stack) {
return stack == null ? null : stack.copy();
}
public static String formatQuantity(int qty) {
if (qty >= 1000000) {
return QUANTITY_FORMATTER.format((float) qty / 1000000F) + "M";
} else if (qty >= 1000) {
return QUANTITY_FORMATTER.format((float) qty / 1000F) + "K";
}
return String.valueOf(qty);
}
private static class AdvancedRayTraceResultBase<T extends RayTraceResult> {
public final AxisAlignedBB bounds;
public final T hit;
public AdvancedRayTraceResultBase(T mop, AxisAlignedBB bounds) {
this.hit = mop;
this.bounds = bounds;
}
public boolean valid() {
return hit != null && bounds != null;
}
public double squareDistanceTo(Vec3d vec) {
return hit.hitVec.squareDistanceTo(vec);
}
}
public static class AdvancedRayTraceResult extends AdvancedRayTraceResultBase<RayTraceResult> {
public AdvancedRayTraceResult(RayTraceResult mop, AxisAlignedBB bounds) {
super(mop, bounds);
}
}
public static Vec3d getStart(EntityPlayer player) {
return new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
}
public static Vec3d getEnd(EntityPlayer player) {
double reachDistance = player instanceof EntityPlayerMP ? ((EntityPlayerMP) player).interactionManager.getBlockReachDistance() : (player.capabilities.isCreativeMode ? 5.0D : 4.5D);
Vec3d lookVec = player.getLookVec();
Vec3d start = getStart(player);
return start.addVector(lookVec.xCoord * reachDistance, lookVec.yCoord * reachDistance, lookVec.zCoord * reachDistance);
}
public static AdvancedRayTraceResult collisionRayTrace(BlockPos pos, Vec3d start, Vec3d end, Collection<AxisAlignedBB> boxes) {
double minDistance = Double.POSITIVE_INFINITY;
AdvancedRayTraceResult hit = null;
int i = -1;
for (AxisAlignedBB aabb : boxes) {
AdvancedRayTraceResult result = aabb == null ? null : collisionRayTrace(pos, start, end, aabb, i, null);
if (result != null) {
double d = result.squareDistanceTo(start);
if (d < minDistance) {
minDistance = d;
hit = result;
}
}
i++;
}
return hit;
}
public static AdvancedRayTraceResult collisionRayTrace(BlockPos pos, Vec3d start, Vec3d end, AxisAlignedBB bounds, int subHit, Object hitInfo) {
RayTraceResult result = bounds.offset(pos).calculateIntercept(start, end);
if (result == null) {
return null;
}
result = new RayTraceResult(RayTraceResult.Type.BLOCK, result.hitVec, result.sideHit, pos);
result.subHit = subHit;
result.hitInfo = hitInfo;
return new AdvancedRayTraceResult(result, bounds);
}
}