diff --git a/src/main/java/vazkii/botania/client/core/handler/LightningHandler.java b/src/main/java/vazkii/botania/client/core/handler/LightningHandler.java index 60362a756..79fbaa62b 100644 --- a/src/main/java/vazkii/botania/client/core/handler/LightningHandler.java +++ b/src/main/java/vazkii/botania/client/core/handler/LightningHandler.java @@ -60,9 +60,12 @@ public class LightningHandler { @SubscribeEvent public void onRenderWorldLast(RenderWorldLastEvent event) { Profiler profiler = Minecraft.getMinecraft().mcProfiler; + profiler.startSection("botania-particles"); ParticleRenderDispatcher.dispatch(); - profiler.startSection("lightning"); + profiler.startSection("redString"); + RedStringRenderer.renderAll(); + profiler.endStartSection("lightning"); float frame = event.partialTicks; Entity entity = Minecraft.getMinecraft().thePlayer; diff --git a/src/main/java/vazkii/botania/client/core/handler/RedStringRenderer.java b/src/main/java/vazkii/botania/client/core/handler/RedStringRenderer.java new file mode 100644 index 000000000..9065291ce --- /dev/null +++ b/src/main/java/vazkii/botania/client/core/handler/RedStringRenderer.java @@ -0,0 +1,98 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Nov 14, 2014, 7:05:32 PM (GMT)] + */ +package vazkii.botania.client.core.handler; + +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.Random; + +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.ChunkCoordinates; +import net.minecraftforge.common.util.ForgeDirection; + +import org.lwjgl.opengl.GL11; + +import vazkii.botania.common.block.tile.string.TileRedString; +import codechicken.lib.vec.Vector3; + +public final class RedStringRenderer { + + public static final Queue redStringTiles = new ArrayDeque(); + + public static void renderAll() { + TileRedString tile; + if(!redStringTiles.isEmpty()) { + GL11.glPushMatrix(); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glColor3f(0.6F, 0F, 0F); + + Tessellator.renderingWorldRenderer = false; + while((tile = redStringTiles.poll()) != null) + renderTile(tile); + + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + GL11.glPopMatrix(); + + } + } + + private static void renderTile(TileRedString tile) { + ForgeDirection dir = ForgeDirection.getOrientation(tile.getBlockMetadata()); + ChunkCoordinates bind = tile.getBinding(); + + if(bind != null) { + GL11.glPushMatrix(); + GL11.glTranslated(tile.xCoord + 0.5 - RenderManager.renderPosX, tile.yCoord + 0.5 - RenderManager.renderPosY, tile.zCoord + 0.5 - RenderManager.renderPosZ); + Vector3 vecOrig = new Vector3(bind.posX - tile.xCoord, bind.posY - tile.yCoord, bind.posZ - tile.zCoord); + Vector3 vecNorm = vecOrig.copy().normalize(); + Vector3 vecMag = vecNorm.copy().multiply(0.025); + Vector3 vecApply = vecMag.copy(); + + int stages = (int) (vecOrig.mag() / vecMag.mag()); + + Tessellator tessellator = Tessellator.instance; + GL11.glLineWidth(1F); + tessellator.startDrawing(GL11.GL_LINES); + + double len = (double) -ClientTickHandler.ticksInGame / 100F + new Random(dir.ordinal() ^ tile.xCoord ^ tile.yCoord ^ tile.zCoord).nextInt(10000); + double add = vecMag.mag(); + double rand = Math.random() - 0.5; + for(int i = 0; i < stages; i++) { + addVertexAtWithTranslation(tessellator, dir, vecApply.x, vecApply.y, vecApply.z, rand, len); + rand = Math.random() - 0.5; + vecApply.add(vecMag); + len += add; + addVertexAtWithTranslation(tessellator, dir, vecApply.x, vecApply.y, vecApply.z, rand, len); + } + + tessellator.draw(); + + GL11.glPopMatrix(); + } + } + + private static void addVertexAtWithTranslation(Tessellator tess, ForgeDirection dir, double xpos, double ypos, double zpos, double rand, double l) { + double freq = 20; + double ampl = 0.15 * (Math.sin(l * 2F) * 0.5 + 0.5) + 0.1; + double randMul = 0.05; + double x = xpos + Math.sin(l * freq) * ampl * Math.abs(Math.abs(dir.offsetX) - 1) + rand * randMul; + double y = ypos + Math.cos(l * freq) * ampl * Math.abs(Math.abs(dir.offsetY) - 1) + rand * randMul; + double z = zpos + (dir.offsetY == 0 ? Math.sin(l * freq) : Math.cos(l * freq)) * ampl * Math.abs(Math.abs(dir.offsetZ) - 1) + rand * randMul; + + tess.addVertex(x, y, z); + } + +} diff --git a/src/main/java/vazkii/botania/client/core/proxy/ClientProxy.java b/src/main/java/vazkii/botania/client/core/proxy/ClientProxy.java index b0882bac0..2bb847423 100644 --- a/src/main/java/vazkii/botania/client/core/proxy/ClientProxy.java +++ b/src/main/java/vazkii/botania/client/core/proxy/ClientProxy.java @@ -68,6 +68,7 @@ import vazkii.botania.client.render.tile.RenderTileEnchanter; import vazkii.botania.client.render.tile.RenderTileMiniIsland; import vazkii.botania.client.render.tile.RenderTilePool; import vazkii.botania.client.render.tile.RenderTilePylon; +import vazkii.botania.client.render.tile.RenderTileRedString; import vazkii.botania.client.render.tile.RenderTileRuneAltar; import vazkii.botania.client.render.tile.RenderTileSkullOverride; import vazkii.botania.client.render.tile.RenderTileSpawnerClaw; @@ -88,6 +89,7 @@ import vazkii.botania.common.block.tile.TileTerraPlate; import vazkii.botania.common.block.tile.TileTinyPotato; import vazkii.botania.common.block.tile.mana.TilePool; import vazkii.botania.common.block.tile.mana.TileSpreader; +import vazkii.botania.common.block.tile.string.TileRedStringContainer; import vazkii.botania.common.core.handler.ConfigHandler; import vazkii.botania.common.core.helper.Vector3; import vazkii.botania.common.core.proxy.CommonProxy; @@ -103,6 +105,7 @@ import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.ReflectionHelper; public class ClientProxy extends CommonProxy { @@ -167,6 +170,9 @@ public class ClientProxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileBrewery.class, new RenderTileBrewery()); ClientRegistry.bindTileEntitySpecialRenderer(TileTerraPlate.class, new RenderTileTerraPlate()); + RenderTileRedString redStringRender = new RenderTileRedString(); + ClientRegistry.bindTileEntitySpecialRenderer(TileRedStringContainer.class, redStringRender); + if(Loader.instance().getMCVersionString().equals("Minecraft 1.7.10")) ClientRegistry.bindTileEntitySpecialRenderer(TileEntitySkull.class, new RenderTileSkullOverride()); diff --git a/src/main/java/vazkii/botania/client/render/tile/RenderTileRedString.java b/src/main/java/vazkii/botania/client/render/tile/RenderTileRedString.java new file mode 100644 index 000000000..2118cbedd --- /dev/null +++ b/src/main/java/vazkii/botania/client/render/tile/RenderTileRedString.java @@ -0,0 +1,30 @@ +/** + * This class was created by . It's distributed as + * part of the Botania Mod. Get the Source Code in github: + * https://github.com/Vazkii/Botania + * + * Botania is Open Source and distributed under a + * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License + * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB) + * + * File Created @ [Nov 14, 2014, 6:52:09 PM (GMT)] + */ +package vazkii.botania.client.render.tile; + +import org.lwjgl.opengl.GL11; + +import vazkii.botania.client.core.handler.RedStringRenderer; +import vazkii.botania.common.block.tile.string.TileRedString; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChunkCoordinates; + +public class RenderTileRedString extends TileEntitySpecialRenderer { + + @Override + public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float partticks) { + TileRedString trs = (TileRedString) tileentity; + RedStringRenderer.redStringTiles.add(trs); + } +} + diff --git a/src/main/java/vazkii/botania/common/block/tile/string/TileRedString.java b/src/main/java/vazkii/botania/common/block/tile/string/TileRedString.java index c02a6aa40..00b5f4f34 100644 --- a/src/main/java/vazkii/botania/common/block/tile/string/TileRedString.java +++ b/src/main/java/vazkii/botania/common/block/tile/string/TileRedString.java @@ -12,6 +12,7 @@ package vazkii.botania.common.block.tile.string; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.ChunkCoordinates; import net.minecraftforge.common.util.ForgeDirection; import vazkii.botania.api.wand.ITileBound; @@ -28,6 +29,9 @@ public abstract class TileRedString extends TileMod implements ITileBound { int y = yCoord; int z = zCoord; int range = getRange(); + ChunkCoordinates currBinding = getBinding(); + setBinding(null); + for(int i = 0; i < range; i++) { x += dir.offsetX; y += dir.offsetY; @@ -39,9 +43,10 @@ public abstract class TileRedString extends TileMod implements ITileBound { if(tile instanceof TileRedString) continue; - if(acceptBlock(x, y, z) && (binding == null || binding.posX != x || binding.posY != y || binding.posZ != z)) { - binding = new ChunkCoordinates(x, y, z); - onBound(x, y, z); + if(acceptBlock(x, y, z)) { + setBinding(new ChunkCoordinates(x, y, z)); + if((currBinding == null || currBinding.posX != x || currBinding.posY != y || currBinding.posZ != z)) + onBound(x, y, z); } } } @@ -55,10 +60,24 @@ public abstract class TileRedString extends TileMod implements ITileBound { public void onBound(int x, int y, int z) { // NO-OP } + + @Override + public AxisAlignedBB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } @Override public ChunkCoordinates getBinding() { return binding; } + + public void setBinding(ChunkCoordinates binding) { + this.binding = binding; + } + + public TileEntity getTileAtBinding() { + ChunkCoordinates binding = getBinding(); + return binding == null ? null : worldObj.getTileEntity(binding.posX, binding.posY, binding.posZ); + } } diff --git a/src/main/java/vazkii/botania/common/block/tile/string/TileRedStringContainer.java b/src/main/java/vazkii/botania/common/block/tile/string/TileRedStringContainer.java index cbdea4133..d25dcb7a1 100644 --- a/src/main/java/vazkii/botania/common/block/tile/string/TileRedStringContainer.java +++ b/src/main/java/vazkii/botania/common/block/tile/string/TileRedStringContainer.java @@ -11,10 +11,15 @@ */ package vazkii.botania.common.block.tile.string; +import vazkii.botania.common.core.helper.InventoryHelper; +import vazkii.botania.common.lib.LibBlockNames; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; -public class TileRedStringContainer extends TileRedString { +public class TileRedStringContainer extends TileRedString implements ISidedInventory { @Override public boolean acceptBlock(int x, int y, int z) { @@ -22,4 +27,97 @@ public class TileRedStringContainer extends TileRedString { return tile != null && tile instanceof IInventory; } + @Override + public int getSizeInventory() { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).getSizeInventory() : 0; + } + + @Override + public ItemStack getStackInSlot(int slot) { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).getStackInSlot(slot) : null; + } + + @Override + public ItemStack decrStackSize(int slot, int count) { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).decrStackSize(slot, count) : null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).getStackInSlotOnClosing(slot) : null; + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) { + TileEntity tile = getTileAtBinding(); + if(tile instanceof IInventory) + ((IInventory) tile).setInventorySlotContents(slot, stack); + } + + @Override + public String getInventoryName() { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).getInventoryName() : LibBlockNames.RED_STRING_CONTAINER; + } + + @Override + public boolean hasCustomInventoryName() { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).hasCustomInventoryName() : false; + } + + @Override + public int getInventoryStackLimit() { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).getInventoryStackLimit() : 0; + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).isUseableByPlayer(player) : false; + } + + @Override + public void openInventory() { + TileEntity tile = getTileAtBinding(); + if(tile instanceof IInventory) + ((IInventory) tile).openInventory(); + } + + @Override + public void closeInventory() { + TileEntity tile = getTileAtBinding(); + if(tile instanceof IInventory) + ((IInventory) tile).closeInventory(); + } + + @Override + public boolean isItemValidForSlot(int slot, ItemStack stack) { + TileEntity tile = getTileAtBinding(); + return tile instanceof IInventory ? ((IInventory) tile).isItemValidForSlot(slot, stack) : false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int side) { + TileEntity tile = getTileAtBinding(); + return tile instanceof ISidedInventory ? ((ISidedInventory) tile).getAccessibleSlotsFromSide(side) : tile instanceof IInventory ? InventoryHelper.buildSlotsForLinearInventory((IInventory) tile) : new int[0]; + } + + @Override + public boolean canInsertItem(int slot, ItemStack stack, int side) { + TileEntity tile = getTileAtBinding(); + return tile instanceof ISidedInventory ? ((ISidedInventory) tile).canInsertItem(slot, stack, side) : true; + } + + @Override + public boolean canExtractItem(int slot, ItemStack stack, int side) { + TileEntity tile = getTileAtBinding(); + return tile instanceof ISidedInventory ? ((ISidedInventory) tile).canExtractItem(slot, stack, side) : true; + } + } diff --git a/src/main/java/vazkii/botania/common/core/helper/InventoryHelper.java b/src/main/java/vazkii/botania/common/core/helper/InventoryHelper.java index 83af6e737..cdcc65635 100644 --- a/src/main/java/vazkii/botania/common/core/helper/InventoryHelper.java +++ b/src/main/java/vazkii/botania/common/core/helper/InventoryHelper.java @@ -133,9 +133,7 @@ public class InventoryHelper { if(inventory instanceof ISidedInventory) availableSlots = ((ISidedInventory) inventory).getAccessibleSlotsFromSide(side.ordinal()); else { - availableSlots = new int[slotCount]; - for(int i = 0; i < slotCount; i++) - availableSlots[i] = i; + availableSlots = buildSlotsForLinearInventory(inventory); } for(int i : availableSlots) { @@ -200,6 +198,14 @@ public class InventoryHelper { return inventory; } + public static int[] buildSlotsForLinearInventory(IInventory inv) { + int[] slots = new int[inv.getSizeInventory()]; + for (int i = 0; i < slots.length; i++) + slots[i] = i; + + return slots; + } + public static class GenericInventory implements IInventory { protected String inventoryTitle;