NaturesAura/src/main/java/de/ellpeck/naturesaura/Helper.java
2018-11-09 00:35:00 +01:00

211 lines
9.4 KiB
Java

package de.ellpeck.naturesaura;
import baubles.api.BaublesApi;
import de.ellpeck.naturesaura.aura.Capabilities;
import de.ellpeck.naturesaura.aura.item.IAuraRecharge;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityImpl;
import de.ellpeck.naturesaura.compat.Compat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.ChunkProviderServer;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Consumer;
public final class Helper {
public static void getTileEntitiesInArea(World world, BlockPos pos, int radius, Consumer<TileEntity> consumer) {
for (int x = (pos.getX() - radius) >> 4; x <= (pos.getX() + radius) >> 4; x++) {
for (int z = (pos.getZ() - radius) >> 4; z <= (pos.getZ() + radius) >> 4; z++) {
if (isChunkLoaded(world, x, z)) {
for (TileEntity tile : world.getChunk(x, z).getTileEntityMap().values()) {
if (tile.getPos().distanceSq(pos) <= radius * radius)
consumer.accept(tile);
}
}
}
}
}
public static List<EntityItemFrame> getAttachedItemFrames(World world, BlockPos pos) {
List<EntityItemFrame> frames = world.getEntitiesWithinAABB(EntityItemFrame.class, new AxisAlignedBB(pos).grow(0.25));
for (int i = frames.size() - 1; i >= 0; i--) {
EntityItemFrame frame = frames.get(i);
BlockPos framePos = frame.getHangingPosition().offset(frame.facingDirection.getOpposite());
if (!pos.equals(framePos))
frames.remove(i);
}
return frames;
}
// For some reason this method isn't public in World, but I also don't want to have to make a new BlockPos
// or use the messy MutableBlockPos system just to see if a chunk is loaded, so this will have to do I guess
public static boolean isChunkLoaded(World world, int x, int z) {
IChunkProvider provider = world.getChunkProvider();
if (provider instanceof ChunkProviderServer)
return ((ChunkProviderServer) provider).chunkExists(x, z);
else
return !provider.provideChunk(x, z).isEmpty();
}
public static int blendColors(int c1, int c2, float ratio) {
int a = (int) ((c1 >> 24 & 0xFF) * ratio + (c2 >> 24 & 0xFF) * (1 - ratio));
int r = (int) ((c1 >> 16 & 0xFF) * ratio + (c2 >> 16 & 0xFF) * (1 - ratio));
int g = (int) ((c1 >> 8 & 0xFF) * ratio + (c2 >> 8 & 0xFF) * (1 - ratio));
int b = (int) ((c1 & 0xFF) * ratio + (c2 & 0xFF) * (1 - ratio));
return ((a & 255) << 24) | ((r & 255) << 16) | ((g & 255) << 8) | (b & 255);
}
public static int getItemIndex(List<ItemStack> list, ItemStack item, boolean nbt) {
for (int i = 0; i < list.size(); i++) {
if (areItemsEqual(list.get(i), item, nbt)) {
return i;
}
}
return -1;
}
public static boolean areItemsEqual(ItemStack first, ItemStack second, boolean nbt) {
if (!ItemStack.areItemsEqual(first, second))
return false;
return !nbt || ItemStack.areItemStackShareTagsEqual(first, second);
}
@SideOnly(Side.CLIENT)
public static void renderItemInWorld(ItemStack stack) {
if (!stack.isEmpty()) {
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
GlStateManager.pushAttrib();
RenderHelper.enableStandardItemLighting();
Minecraft.getMinecraft().getRenderItem().renderItem(stack, ItemCameraTransforms.TransformType.FIXED);
RenderHelper.disableStandardItemLighting();
GlStateManager.popAttrib();
GlStateManager.enableLighting();
GlStateManager.popMatrix();
}
}
@SideOnly(Side.CLIENT)
public static void renderItemInGui(ItemStack stack, int x, int y, float scale) {
GlStateManager.pushMatrix();
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.enableDepth();
GlStateManager.enableRescaleNormal();
GlStateManager.translate(x, y, 0);
GlStateManager.scale(scale, scale, scale);
Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, 0, 0);
Minecraft.getMinecraft().getRenderItem().renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRenderer, stack, 0, 0, null);
RenderHelper.disableStandardItemLighting();
GlStateManager.popMatrix();
}
public static boolean putStackOnTile(EntityPlayer player, EnumHand hand, BlockPos pos, int slot, boolean sound) {
TileEntity tile = player.world.getTileEntity(pos);
if (tile instanceof TileEntityImpl) {
IItemHandlerModifiable handler = ((TileEntityImpl) tile).getItemHandler(null);
if (handler != null) {
ItemStack handStack = player.getHeldItem(hand);
if (!handStack.isEmpty()) {
ItemStack remain = handler.insertItem(slot, handStack, player.world.isRemote);
if (!ItemStack.areItemStacksEqual(remain, handStack)) {
if (sound)
player.world.playSound(player, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
SoundEvents.ENTITY_ITEMFRAME_ADD_ITEM, SoundCategory.PLAYERS, 0.75F, 1F);
if (!player.world.isRemote)
player.setHeldItem(hand, remain);
return true;
}
}
if (!handler.getStackInSlot(slot).isEmpty()) {
if (sound)
player.world.playSound(player, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
SoundEvents.ENTITY_ITEMFRAME_REMOVE_ITEM, SoundCategory.PLAYERS, 0.75F, 1F);
if (!player.world.isRemote) {
player.addItemStackToInventory(handler.getStackInSlot(slot));
handler.setStackInSlot(slot, ItemStack.EMPTY);
}
return true;
}
}
}
return false;
}
public static ICapabilityProvider makeRechargeProvider(ItemStack stack) {
return new ICapabilityProvider() {
private final IAuraRecharge recharge = container -> {
int toDrain = 3;
if (stack.getItemDamage() > 0 && container.drainAura(toDrain, true) >= toDrain) {
stack.setItemDamage(stack.getItemDamage() - 1);
container.drainAura(toDrain, false);
}
};
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return capability == Capabilities.auraRecharge;
}
@Nullable
@Override
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
return capability == Capabilities.auraRecharge ? (T) this.recharge : null;
}
};
}
public static boolean extractAuraFromPlayer(EntityPlayer player, int amount, boolean simulate) {
if (player.capabilities.isCreativeMode)
return true;
if (Compat.baubles) {
IItemHandler baubles = BaublesApi.getBaublesHandler(player);
for (int i = 0; i < baubles.getSlots(); i++) {
ItemStack stack = baubles.getStackInSlot(i);
if (!stack.isEmpty() && stack.hasCapability(Capabilities.auraContainer, null)) {
amount -= stack.getCapability(Capabilities.auraContainer, null).drainAura(amount, simulate);
if (amount <= 0)
return true;
}
}
}
for (int i = 0; i < player.inventory.getSizeInventory(); i++) {
ItemStack stack = player.inventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.hasCapability(Capabilities.auraContainer, null)) {
amount -= stack.getCapability(Capabilities.auraContainer, null).drainAura(amount, simulate);
if (amount <= 0)
return true;
}
}
return false;
}
}