Added a fancy render system to enable things like stairs and redstone dust to be rendered properly in the visualization and multiblock preview systems.

This commit is contained in:
SoundLogic committed 2015-09-05 01:52:53 -05:00
1 parent 3f2dbde039
commit 93143e92a6
9 files changed
+286 -37

No files matched your search

@@ -13,6 +13,7 @@ package vazkii.botania.api.lexicon.multiblock;
import java.util.HashMap;
import java.util.Map;
import vazkii.botania.api.lexicon.multiblock.component.MultiblockComponent;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.world.IBlockAccess;
@@ -24,6 +25,8 @@ public interface IMultiblockRenderHook {
public static Map<Block, IMultiblockRenderHook> renderHooks = new HashMap();
public void renderBlockForMultiblock(IBlockAccess world, Multiblock mb, Block block, int meta, RenderBlocks renderBlocks);
public void renderBlockForMultiblock(IBlockAccess world, Multiblock mb, Block block, int meta, RenderBlocks renderBlocks, MultiblockComponent comp, float alpha);
public boolean needsTranslate(Block block);
}
@@ -11,6 +11,8 @@
package vazkii.botania.api.lexicon.multiblock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import net.minecraft.block.Block;
@@ -29,15 +31,20 @@ public class Multiblock {
public List<ItemStack> materials = new ArrayList();
public int minX, minY, minZ, maxX, maxY, maxZ, offX, offY, offZ;
public HashMap<List<Integer>, MultiblockComponent> locationCache = new HashMap<List<Integer>, MultiblockComponent>();
/**
* Adds a multiblock component to this multiblock. The component's x y z
* coords should be pivoted to the center of the structure.
*/
public void addComponent(MultiblockComponent component) {
if(getComponentForLocation(component.relPos.posX, component.relPos.posY, component.relPos.posZ) != null)
throw new IllegalArgumentException("Location in multiblock already occupied");
components.add(component);
changeAxisForNewComponent(component.relPos.posX, component.relPos.posY, component.relPos.posZ);
calculateCostForNewComponent(component);
addComponentToLocationCache(component);
}
/**
@@ -102,6 +109,7 @@ public class Multiblock {
public void rotate(double angle) {
for(MultiblockComponent comp : getComponents())
comp.rotate(angle);
updateLocationCache();
}
public Multiblock copy() {
@@ -149,5 +157,32 @@ public class Multiblock {
public int getZSize() {
return Math.abs(minZ) + Math.abs(maxZ) + 1;
}
/**
* Rebuilds the location cache
*/
public void updateLocationCache() {
locationCache.clear();
for(MultiblockComponent comp : components)
addComponentToLocationCache(comp);
}
/**
* Adds a single component to the location cache
*/
private void addComponentToLocationCache(MultiblockComponent comp) {
ChunkCoordinates pos = comp.getRelativePosition();
locationCache.put(Arrays.asList(
pos.posX,
pos.posY,
pos.posZ
), comp);
}
/**
* Gets the component for a given location
*/
public MultiblockComponent getComponentForLocation(int x, int y, int z) {
return locationCache.get(Arrays.asList(x, y, z));
}
}
@@ -10,8 +10,11 @@
*/
package vazkii.botania.api.lexicon.multiblock.component;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
@@ -24,11 +27,27 @@ public class MultiblockComponent {
public ChunkCoordinates relPos;
public final Block block;
public final int meta;
public final TileEntity tileEntity;
public boolean doFancyRender;
public MultiblockComponent(ChunkCoordinates relPos, Block block, int meta) {
this(relPos, block, meta, null);
}
public MultiblockComponent(ChunkCoordinates relPos, Block block, int meta, boolean doFancyRender) {
this(relPos, block, meta, doFancyRender, null);
}
public MultiblockComponent(ChunkCoordinates relPos, Block block, int meta, TileEntity tileEntity) {
this(relPos, block, meta, block.hasTileEntity() == (tileEntity != null), tileEntity);
}
public MultiblockComponent(ChunkCoordinates relPos, Block block, int meta, boolean doFancyRender, TileEntity tileEntity) {
this.relPos = relPos;
this.block = block;
this.meta = meta;
this.tileEntity = tileEntity;
this.doFancyRender = doFancyRender;
}
public ChunkCoordinates getRelativePosition() {
@@ -63,6 +82,15 @@ public class MultiblockComponent {
}
public MultiblockComponent copy() {
return new MultiblockComponent(relPos, block, meta);
return new MultiblockComponent(relPos, block, meta, tileEntity);
}
public TileEntity getTileEntity() {
return tileEntity;
}
@SideOnly(Side.CLIENT)
public boolean shouldDoFancyRender() {
return doFancyRender;
}
}
@@ -1,4 +1,4 @@
@API(owner = "Botania", apiVersion = "61", provides = "BotaniaAPI")
@API(owner = "Botania", apiVersion = "62", provides = "BotaniaAPI")
package vazkii.botania.api;
import cpw.mods.fml.common.API;
@@ -0,0 +1,132 @@
/**
* This class was created by <SoundLogic>. 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 the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Aug 31, 2015, 11:40:59 PM (GMT)]
*/
package vazkii.botania.client.core.handler;
import vazkii.botania.api.lexicon.multiblock.Multiblock;
import vazkii.botania.api.lexicon.multiblock.component.MultiblockComponent;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.util.ForgeDirection;
/**
* This class acts as a wrapper around a block access to
* replace blocks with the blocks involved in the multiblock specified
*/
public class MultiblockBlockAccess implements IBlockAccess {
protected IBlockAccess originalBlockAccess;
protected boolean hasBlockAccess = false;
protected Multiblock multiblock;
protected int anchorX, anchorY, anchorZ;
@Override
public Block getBlock(int x, int y, int z) {
MultiblockComponent comp=getComponent(x, y, z);
if(comp != null)
return comp.getBlock();
if(hasBlockAccess)
return originalBlockAccess.getBlock(x, y, z);
return Blocks.air;
}
@Override
public TileEntity getTileEntity(int x, int y, int z) {
MultiblockComponent comp=getComponent(x, y, z);
if(comp != null)
return comp.getTileEntity();
if(hasBlockAccess)
return originalBlockAccess.getTileEntity(x, y, z);
return null;
}
@Override
public int getLightBrightnessForSkyBlocks(int x, int y, int z, int p_72802_4_) {
if(hasBlockAccess)
return originalBlockAccess.getLightBrightnessForSkyBlocks(x,y,z,p_72802_4_);
return 15728640;
}
@Override
public int getBlockMetadata(int x, int y, int z) {
MultiblockComponent comp=getComponent(x, y, z);
if(comp != null)
return comp.getMeta();
if(hasBlockAccess)
return originalBlockAccess.getBlockMetadata(x, y, z);
return 0;
}
@Override
public int isBlockProvidingPowerTo(int x, int y, int z, int direction) {
return 0;
}
@Override
public boolean isAirBlock(int x, int y, int z) {
MultiblockComponent comp=getComponent(x, y, z);
if(comp != null)
return false;
if(hasBlockAccess)
return originalBlockAccess.isAirBlock(x, y, z);
return true;
}
@Override
public BiomeGenBase getBiomeGenForCoords(int x, int z) {
if(hasBlockAccess)
return originalBlockAccess.getBiomeGenForCoords(x, z);
return null;
}
@Override
public int getHeight() {
if(hasBlockAccess)
return originalBlockAccess.getHeight();
return 256;
}
@Override
public boolean extendedLevelsInChunkCache() {
if(hasBlockAccess)
return originalBlockAccess.extendedLevelsInChunkCache();
return false;
}
@Override
public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default) {
if(hasBlockAccess)
return originalBlockAccess.isSideSolid(x, y, z, side, _default);
return _default;
}
/**
* Updates the block access to the new parameters
*/
public void update(IBlockAccess access, Multiblock mb, int anchorX, int anchorY, int anchorZ) {
this.originalBlockAccess = access;
this.multiblock = mb;
this.anchorX = anchorX;
this.anchorY = anchorY;
this.anchorZ = anchorZ;
this.hasBlockAccess = access != null;
}
/**
* Returns the multiblock component for the coordinates, adjusted based on the anchor
*/
protected MultiblockComponent getComponent(int x, int y, int z) {
MultiblockComponent comp = multiblock.getComponentForLocation(x - anchorX, y - anchorY, z - anchorZ);
return comp;
}
}
@@ -13,6 +13,7 @@ package vazkii.botania.client.core.handler;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.EntityPlayer;
@@ -22,6 +23,7 @@ import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
@@ -39,6 +41,8 @@ public final class MultiblockRenderHandler {
public static boolean rendering = false;
private static MultiblockBlockAccess blockAccess = new MultiblockBlockAccess();
private static RenderBlocks blockRender = RenderBlocks.getInstance();
public static MultiblockSet currentMultiblock;
public static ChunkCoordinates anchor;
@@ -77,8 +81,11 @@ public final class MultiblockRenderHandler {
rendering = true;
Multiblock mb = anchor != null ? currentMultiblock.getForIndex(angle) : currentMultiblock.getForEntity(player);
boolean didAny = false;
blockAccess.update(player.worldObj, mb, anchorX, anchorY, anchorZ);
for(MultiblockComponent comp : mb.getComponents())
if(renderComponent(player.worldObj, mb, comp, anchorX, anchorY, anchorZ))
if(renderComponentInWorld(player.worldObj, mb, comp, anchorX, anchorY, anchorZ))
didAny = true;
rendering = false;
@@ -89,7 +96,7 @@ public final class MultiblockRenderHandler {
}
}
private boolean renderComponent(World world, Multiblock mb, MultiblockComponent comp, int anchorX, int anchorY, int anchorZ) {
private boolean renderComponentInWorld(World world, Multiblock mb, MultiblockComponent comp, int anchorX, int anchorY, int anchorZ) {
ChunkCoordinates pos = comp.getRelativePosition();
int x = pos.posX + anchorX;
int y = pos.posY + anchorY;
@@ -98,21 +105,75 @@ public final class MultiblockRenderHandler {
return false;
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslated(-RenderManager.renderPosX, -RenderManager.renderPosY, -RenderManager.renderPosZ);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glColor4f(1F, 1F, 1F, 0.4F);
GL11.glTranslated(x + 0.5 - RenderManager.renderPosX, y + 0.5 - RenderManager.renderPosY, z + 0.5 - RenderManager.renderPosZ);
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
blockRender.useInventoryTint = false;
Block block = comp.getBlock();
if(IMultiblockRenderHook.renderHooks.containsKey(block))
IMultiblockRenderHook.renderHooks.get(block).renderBlockForMultiblock(world, mb, block, comp.getMeta(), blockRender);
else blockRender.renderBlockAsItem(comp.getBlock(), comp.getMeta(), 1F);
GL11.glEnable(GL11.GL_DEPTH_TEST);
doRenderComponent(mb, comp, x, y, z, 0.4F);
GL11.glPopMatrix();
return true;
}
public static void renderMultiblockOnPage(Multiblock mb) {
GL11.glTranslated(-0.5, -0.5, -0.5);
blockAccess.update(null, mb, mb.offX, mb.offY, mb.offZ);
for(MultiblockComponent comp : mb.getComponents()) {
ChunkCoordinates pos = comp.getRelativePosition();
doRenderComponent(mb, comp, pos.posX + mb.offX, pos.posY + mb.offY, pos.posZ + mb.offZ, 1);
}
}
private static void doRenderComponent(Multiblock mb, MultiblockComponent comp, int x, int y, int z, float alpha) {
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
Block block = comp.getBlock();
int meta = comp.getMeta();
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
blockRender.useInventoryTint = false;
if(block == null)
return;
if(IMultiblockRenderHook.renderHooks.containsKey(block)) {
GL11.glColor4f(1F, 1F, 1F, alpha);
IMultiblockRenderHook renderHook = IMultiblockRenderHook.renderHooks.get(block);
if(renderHook.needsTranslate(block)) {
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5);
}
renderHook.renderBlockForMultiblock(blockAccess, mb, block, comp.getMeta(), blockRender, comp, alpha);
}
else {
if(comp.shouldDoFancyRender()) {
int color = block.colorMultiplier(blockAccess, x, y, z);
float red = (float)(color >> 16 & 255) / 255.0F;
float green = (float)(color >> 8 & 255) / 255.0F;
float blue = (float)(color & 255) / 255.0F;
GL11.glColor4f(red, green, blue, alpha);
IBlockAccess oldBlockAccess = blockRender.blockAccess;
blockRender.blockAccess = blockAccess;
Tessellator tessellator = Tessellator.instance;
blockRender.renderAllFaces = true;
tessellator.startDrawingQuads();
tessellator.disableColor();
try {
blockRender.renderBlockByRenderType(block, x, y, z);
}
catch(Exception e) {
comp.doFancyRender = false;
}
tessellator.draw();
blockRender.renderAllFaces = false;
blockRender.blockAccess = oldBlockAccess;
}
else {
int color = block.getRenderColor(meta);
float red = (float)(color >> 16 & 255) / 255.0F;
float green = (float)(color >> 8 & 255) / 255.0F;
float blue = (float)(color & 255) / 255.0F;
GL11.glColor4f(red, green, blue, alpha);
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5);
blockRender.renderBlockAsItem(block, meta, 1F);
}
}
GL11.glColor4f(1F, 1F, 1F, 1F);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glPopMatrix();
}
}
@@ -18,6 +18,7 @@ import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import vazkii.botania.api.lexicon.multiblock.IMultiblockRenderHook;
import vazkii.botania.api.lexicon.multiblock.Multiblock;
import vazkii.botania.api.lexicon.multiblock.component.MultiblockComponent;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
public class RenderSpecialFlower implements ISimpleBlockRenderingHandler, IMultiblockRenderHook {
@@ -119,11 +120,16 @@ public class RenderSpecialFlower implements ISimpleBlockRenderingHandler, IMulti
}
@Override
public void renderBlockForMultiblock(IBlockAccess world, Multiblock mb, Block block, int meta, RenderBlocks renderBlocks) {
public void renderBlockForMultiblock(IBlockAccess world, Multiblock mb, Block block, int meta, RenderBlocks renderBlocks, MultiblockComponent comp, float alpha) {
Tessellator tess = Tessellator.instance;
tess.startDrawingQuads();
drawCrossedSquares(world, block, block.getIcon(0, meta), 0, 0, 0, -0.5, -0.5, -0.5, 1F, renderBlocks);
tess.draw();
}
@Override
public boolean needsTranslate(Block block) {
return true;
}
}
@@ -22,6 +22,7 @@ import vazkii.botania.api.lexicon.LexiconCategory;
import vazkii.botania.api.lexicon.LexiconEntry;
import vazkii.botania.api.lexicon.LexiconPage;
import vazkii.botania.api.lexicon.LexiconRecipeMappings;
import vazkii.botania.api.lexicon.multiblock.Multiblock;
import vazkii.botania.client.lib.LibResources;
import vazkii.botania.common.Botania;
import vazkii.botania.common.achievement.ModAchievements;
@@ -86,11 +86,9 @@ public class PageMultiblock extends LexiconPage {
GL11.glRotatef(-20F, 1, 0, 0);
GL11.glRotatef(gui.getElapsedTicks(), 0, 1, 0);
MultiblockRenderHandler.renderMultiblockOnPage(mb);
for(MultiblockComponent comp : mb.getComponents()) {
ChunkCoordinates pos = comp.getRelativePosition();
renderBlock(comp.getBlock(), comp.getMeta(), pos.posX + mb.offX, pos.posY + mb.offY, pos.posZ + mb.offZ);
}
GL11.glPopMatrix();
FontRenderer font = Minecraft.getMinecraft().fontRenderer;
@@ -125,21 +123,6 @@ public class PageMultiblock extends LexiconPage {
GL11.glPopMatrix();
}
public void renderBlock(Block block, int meta, int x, int y, int z) {
if(block != null) {
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
GL11.glPushMatrix();
GL11.glTranslatef(x, y, z);
RenderBlocks blockRender = RenderBlocks.getInstance();
if(IMultiblockRenderHook.renderHooks.containsKey(block))
IMultiblockRenderHook.renderHooks.get(block).renderBlockForMultiblock(Minecraft.getMinecraft().theWorld, mb, block, meta, blockRender);
else blockRender.renderBlockAsItem(block, meta, 0.8F);
GL11.glPopMatrix();
}
}
@Override
public void onOpened(IGuiLexiconEntry gui) {
button = new GuiButton(101, gui.getLeft() + 30, gui.getTop() + gui.getHeight() - 50, gui.getWidth() - 60, 20, getButtonStr());