From a3a16d6593dabdabdbafe95325b6fe688d1df743 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Tue, 17 Nov 2015 04:46:50 -0800 Subject: [PATCH 01/11] Fix incorrect position passes to Block.getExplosionResistance from entities. --- patches/minecraft/net/minecraft/entity/Entity.java.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/minecraft/net/minecraft/entity/Entity.java.patch b/patches/minecraft/net/minecraft/entity/Entity.java.patch index c120a7df7d..31ec4be0b1 100644 --- a/patches/minecraft/net/minecraft/entity/Entity.java.patch +++ b/patches/minecraft/net/minecraft/entity/Entity.java.patch @@ -121,7 +121,7 @@ public float func_180428_a(Explosion p_180428_1_, World p_180428_2_, BlockPos p_180428_3_, IBlockState p_180428_4_) { - return p_180428_4_.func_177230_c().func_149638_a(this); -+ return p_180428_4_.func_177230_c().getExplosionResistance(p_180428_2_, p_180428_3_.func_177963_a(0, func_70047_e(), 0), this, p_180428_1_); ++ return p_180428_4_.func_177230_c().getExplosionResistance(p_180428_2_, p_180428_3_, this, p_180428_1_); } public boolean func_174816_a(Explosion p_174816_1_, World p_174816_2_, BlockPos p_174816_3_, IBlockState p_174816_4_, float p_174816_5_) From 904a30123d05872cba4e071df4ea667f66d22970 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Tue, 17 Nov 2015 04:47:43 -0800 Subject: [PATCH 02/11] Moved client side Block.onBlockDestroyed to after Item.onBlockDestroyed to match server order. --- .../multiplayer/PlayerControllerMP.java.patch | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch b/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch index d57d6ad632..76f35c6168 100644 --- a/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch +++ b/patches/minecraft/net/minecraft/client/multiplayer/PlayerControllerMP.java.patch @@ -13,16 +13,35 @@ if (this.field_78779_k.func_77145_d() && this.field_78776_a.field_71439_g.func_70694_bm() != null && this.field_78776_a.field_71439_g.func_70694_bm().func_77973_b() instanceof ItemSword) { return false; -@@ -130,7 +136,7 @@ +@@ -130,13 +136,7 @@ else { worldclient.func_175718_b(2001, p_178888_1_, Block.func_176210_f(iblockstate)); - boolean flag = worldclient.func_175698_g(p_178888_1_); -+ boolean flag = block1.removedByPlayer(worldclient, p_178888_1_, field_78776_a.field_71439_g, false); - if (flag) - { -@@ -360,11 +366,19 @@ +- if (flag) +- { +- block1.func_176206_d(worldclient, p_178888_1_, iblockstate); +- } +- + this.field_178895_c = new BlockPos(this.field_178895_c.func_177958_n(), -1, this.field_178895_c.func_177952_p()); + + if (!this.field_78779_k.func_77145_d()) +@@ -154,6 +154,13 @@ + } + } + ++ boolean flag = block1.removedByPlayer(worldclient, p_178888_1_, field_78776_a.field_71439_g, false); ++ ++ if (flag) ++ { ++ block1.func_176206_d(worldclient, p_178888_1_, iblockstate); ++ } ++ + return flag; + } + } +@@ -360,11 +367,19 @@ { if (this.field_78779_k != WorldSettings.GameType.SPECTATOR) { @@ -44,7 +63,7 @@ } if (!flag && p_178890_3_ != null && p_178890_3_.func_77973_b() instanceof ItemBlock) -@@ -397,7 +411,9 @@ +@@ -397,7 +412,9 @@ } else { @@ -55,7 +74,7 @@ } } else -@@ -428,9 +444,10 @@ +@@ -428,9 +445,10 @@ { p_78769_1_.field_71071_by.field_70462_a[p_78769_1_.field_71071_by.field_70461_c] = itemstack1; From 767d7339485258545b9e674f7ddb8ac4a348c857 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Wed, 18 Nov 2015 00:28:26 -0800 Subject: [PATCH 03/11] Enable the normal ModList GUI in game. Use GL_SCISSOR to support the transparent in-game GUI. --- .../fml/client/FMLClientHandler.java | 2 +- .../fml/client/GuiIngameModOptions.java | 55 --------------- .../minecraftforge/fml/client/GuiModList.java | 1 - .../fml/client/GuiModOptionList.java | 47 ------------- .../fml/client/GuiScrollingList.java | 68 ++++++------------- 5 files changed, 23 insertions(+), 150 deletions(-) delete mode 100644 src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java delete mode 100644 src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java diff --git a/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java b/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java index 978b753b19..68758588e2 100644 --- a/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java +++ b/src/main/java/net/minecraftforge/fml/client/FMLClientHandler.java @@ -710,7 +710,7 @@ public class FMLClientHandler implements IFMLSidedHandler public void showInGameModOptions(GuiIngameMenu guiIngameMenu) { - showGuiScreen(new GuiIngameModOptions(guiIngameMenu)); + showGuiScreen(new GuiModList(guiIngameMenu)); } public IModGuiFactory getGuiFactoryFor(ModContainer selectedMod) diff --git a/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java b/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java deleted file mode 100644 index fbee967cd9..0000000000 --- a/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.minecraftforge.fml.client; - -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.I18n; - -public class GuiIngameModOptions extends GuiScreen -{ - private final GuiScreen parentScreen; - protected String title = "Mod Options"; - private GuiModOptionList optionList; - - public GuiIngameModOptions(GuiScreen parentScreen) - { - this.parentScreen = parentScreen; - } - - @SuppressWarnings("unchecked") - @Override - public void initGui() - { - this.optionList=new GuiModOptionList(this); - //this.optionList.registerScrollButtons(this.buttonList, 7, 8); - this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 168, I18n.format("gui.done", new Object[0]))); - } - - @Override - protected void actionPerformed(GuiButton button) - { - if (button.enabled) - { - if (button.id == 200) - { - this.mc.gameSettings.saveOptions(); - this.mc.displayGuiScreen(this.parentScreen); - } - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) - { - // force a non-transparent background - this.drawDefaultBackground(); - this.optionList.drawScreen(mouseX, mouseY, partialTicks); - this.drawCenteredString(this.fontRendererObj, this.title, this.width / 2, 15, 0xFFFFFF); - super.drawScreen(mouseX, mouseY, partialTicks); - } - - FontRenderer getFontRenderer() { - return fontRendererObj; - } - -} diff --git a/src/main/java/net/minecraftforge/fml/client/GuiModList.java b/src/main/java/net/minecraftforge/fml/client/GuiModList.java index 9974788755..618464cbf8 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiModList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiModList.java @@ -578,7 +578,6 @@ public class GuiModList extends GuiScreen k += GuiModList.this.fontRendererObj.getStringWidth(((ChatComponentText)part).getChatComponentText_TextValue()); if (k >= x) { - System.out.println(part); GuiModList.this.func_175276_a(part); break; } diff --git a/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java b/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java deleted file mode 100644 index 21e3536f06..0000000000 --- a/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.minecraftforge.fml.client; - -import net.minecraft.client.renderer.Tessellator; - -public class GuiModOptionList extends GuiScrollingList { - - private GuiIngameModOptions parent; - - public GuiModOptionList(GuiIngameModOptions parent) - { - super(parent.mc, 150, parent.height, 32, parent.height - 65 + 4, 10, 35, parent.width, parent.height); - this.parent = parent; - } - - @Override - protected int getSize() - { - return 1; - } - - @Override - protected void elementClicked(int index, boolean doubleClick) - { - // TODO Auto-generated method stub - - } - - @Override - protected boolean isSelected(int index) - { - return false; - } - - @Override - protected void drawBackground() - { - } - - @Override - protected void drawSlot(int slotIdx, int entryRight, int slotTop, int slotBuffer, Tessellator tess) - { - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("Test 1", listWidth - 10), this.left + 3 , slotTop + 2, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("TEST 2", listWidth - 10), this.left + 3 , slotTop + 12, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("DISABLED", listWidth - 10), this.left + 3 , slotTop + 22, 0xFF2222); - } - -} diff --git a/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java b/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java index d7f374a1bc..d3dc65ee37 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java @@ -17,6 +17,7 @@ import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; @@ -95,15 +96,27 @@ public abstract class GuiScrollingList protected abstract void drawBackground(); + /** + * Draw anything special on the screen. GL_SCISSOR is enabled for anything that + * is rendered outside of the view box. Do not mess with SCISSOR unless you support this. + */ protected abstract void drawSlot(int slotIdx, int entryRight, int slotTop, int slotBuffer, Tessellator tess); @Deprecated protected void func_27260_a(int entryRight, int relativeY, Tessellator tess) {} + /** + * Draw anything special on the screen. GL_SCISSOR is enabled for anything that + * is rendered outside of the view box. Do not mess with SCISSOR unless you support this. + */ protected void drawHeader(int entryRight, int relativeY, Tessellator tess) { func_27260_a(entryRight, relativeY, tess); } @Deprecated protected void func_27255_a(int x, int y) {} protected void clickHeader(int x, int y) { func_27255_a(x, y); } @Deprecated protected void func_27257_b(int mouseX, int mouseY) {} + /** + * Draw anything special on the screen. GL_SCISSOR is enabled for anything that + * is rendered outside of the view box. Do not mess with SCISSOR unless you support this. + */ protected void drawScreen(int mouseX, int mouseY) { func_27257_b(mouseX, mouseY); } public int func_27256_c(int x, int y) @@ -251,6 +264,13 @@ public abstract class GuiScrollingList Tessellator tess = Tessellator.getInstance(); WorldRenderer worldr = tess.getWorldRenderer(); + ScaledResolution res = new ScaledResolution(client, client.displayWidth, client.displayHeight); + double scaleW = client.displayWidth / res.getScaledWidth_double(); + double scaleH = client.displayHeight / res.getScaledHeight_double(); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + GL11.glScissor((int)(left * scaleW), (int)(client.displayHeight - (bottom * scaleH)), + (int)(listWidth * scaleW), (int)(viewHeight * scaleH)); + if (this.client.theWorld != null) { this.drawGradientRect(this.left, this.top, this.right, this.bottom, 0xC0101010, 0xD0101010); @@ -310,34 +330,6 @@ public abstract class GuiScrollingList } GlStateManager.disableDepth(); - if (this.client.theWorld == null) - { - this.overlayBackground(0, this.top, 255, 255); - this.overlayBackground(this.bottom, this.listHeight, 255, 255); - } - - // Render the entire background over everything but our view - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.disableAlpha(); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - GlStateManager.disableTexture2D(); - worldr.startDrawingQuads(); - worldr.setColorRGBA_I(0, 0); - worldr.addVertexWithUV(this.left, this.top + border, 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV(this.right, this.top + border, 0.0D, 1.0D, 1.0D); - worldr.setColorRGBA_I(0, 255); - worldr.addVertexWithUV(this.right, this.top, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV(this.left, this.top, 0.0D, 0.0D, 0.0D); - tess.draw(); - worldr.startDrawingQuads(); - worldr.setColorRGBA_I(0, 255); - worldr.addVertexWithUV(this.left, this.bottom, 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV(this.right, this.bottom, 0.0D, 1.0D, 1.0D); - worldr.setColorRGBA_I(0, 0); - worldr.addVertexWithUV(this.right, this.bottom - border, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV(this.left, this.bottom - border, 0.0D, 0.0D, 0.0D); - tess.draw(); int extraHeight = this.getContentHeight() - viewHeight - border; if (extraHeight > 0) @@ -355,6 +347,7 @@ public abstract class GuiScrollingList barTop = this.top; } + GlStateManager.disableTexture2D(); worldr.startDrawingQuads(); worldr.setColorRGBA_I(0, 255); worldr.addVertexWithUV(scrollBarLeft, this.bottom, 0.0D, 0.0D, 1.0D); @@ -383,24 +376,7 @@ public abstract class GuiScrollingList GlStateManager.shadeModel(GL11.GL_FLAT); GlStateManager.enableAlpha(); GlStateManager.disableBlend(); - } - - private void overlayBackground(int top, int height, int alpha1, int alpah2) - { - Tessellator tess = Tessellator.getInstance(); - WorldRenderer worldr = tess.getWorldRenderer(); - this.client.renderEngine.bindTexture(Gui.optionsBackground); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - float scale = 32.0F; - double startUV = (screenWidth / scale) / screenWidth * (left-0); - worldr.startDrawingQuads(); - worldr.setColorRGBA_I(0x404040, alpah2); - worldr.addVertexWithUV(left, height, 0.0D, startUV, height / scale); - worldr.addVertexWithUV(left+listWidth+8, height, 0.0D, (left+listWidth+8) / scale, height / scale); - worldr.setColorRGBA_I(0x404040, alpha1); - worldr.addVertexWithUV(left+listWidth+8, top, 0.0D, (left+listWidth+8) / scale, top / scale); - worldr.addVertexWithUV(left, top, 0.0D, startUV, top / scale); - tess.draw(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); } protected void drawGradientRect(int left, int top, int right, int bottom, int color1, int color2) From 48b82567d25f89c4e87ee4207f8dca7de06b4af0 Mon Sep 17 00:00:00 2001 From: Choonster Date: Fri, 20 Nov 2015 11:02:37 +1100 Subject: [PATCH 04/11] BiomeManager: Fix off-by-one errors --- src/main/java/net/minecraftforge/common/BiomeManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/BiomeManager.java b/src/main/java/net/minecraftforge/common/BiomeManager.java index 1b4517603e..debdec98d3 100644 --- a/src/main/java/net/minecraftforge/common/BiomeManager.java +++ b/src/main/java/net/minecraftforge/common/BiomeManager.java @@ -147,7 +147,7 @@ public class BiomeManager public static ImmutableList getBiomes(BiomeType type) { int idx = type.ordinal(); - List list = idx > biomes.length ? null : biomes[idx]; + List list = idx >= biomes.length ? null : biomes[idx]; return list != null ? ImmutableList.copyOf(list) : null; } @@ -179,7 +179,7 @@ public class BiomeManager if (ret.ordinal() >= biomes.length) { - biomes = Arrays.copyOf(biomes, ret.ordinal()); + biomes = Arrays.copyOf(biomes, ret.ordinal() + 1); } return ret; From 6e68d8fe74a5949fdc3ba57e2782f4ea703225ec Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Thu, 19 Nov 2015 18:38:33 -0800 Subject: [PATCH 05/11] Fix bold font rendering, Unicode is 2x pixel density of normal. --- .../net/minecraft/client/gui/FontRenderer.java.patch | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/patches/minecraft/net/minecraft/client/gui/FontRenderer.java.patch b/patches/minecraft/net/minecraft/client/gui/FontRenderer.java.patch index 8f1d0c6bab..359c1e7803 100644 --- a/patches/minecraft/net/minecraft/client/gui/FontRenderer.java.patch +++ b/patches/minecraft/net/minecraft/client/gui/FontRenderer.java.patch @@ -85,7 +85,7 @@ } - float f1 = this.field_78293_l ? 0.5F : 1.0F; -+ float f1 = func_78263_a(c0) / 32f; ++ float f1 = j == -1 || this.field_78293_l ? 0.5f : 1f; boolean flag1 = (c0 == 0 || j == -1 || this.field_78293_l) && p_78255_2_; if (flag1) @@ -114,7 +114,7 @@ this.field_78295_j = p_180455_2_; this.field_78296_k = p_180455_3_; this.func_78255_a(p_180455_1_, p_180455_5_); -@@ -583,11 +593,6 @@ +@@ -583,12 +593,6 @@ int j = this.field_78287_e[p_78263_1_] >>> 4; int k = this.field_78287_e[p_78263_1_] & 15; @@ -123,10 +123,11 @@ - k = 15; - j = 0; - } - +- ++k; return (k - j) / 2 + 1; -@@ -842,6 +847,26 @@ + } +@@ -842,6 +846,26 @@ return this.field_78294_m; } From 1246f1a79119959039f68b2fcdceadfc320f3318 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Fri, 20 Nov 2015 11:18:00 -0800 Subject: [PATCH 06/11] Fix invalid position passed to isAir/getLight in World.playAmbientSound --- .../net/minecraft/world/World.java.patch | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/patches/minecraft/net/minecraft/world/World.java.patch b/patches/minecraft/net/minecraft/world/World.java.patch index d8bf6c7f2b..466255637c 100644 --- a/patches/minecraft/net/minecraft/world/World.java.patch +++ b/patches/minecraft/net/minecraft/world/World.java.patch @@ -176,7 +176,7 @@ { + if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, p_175685_1_, this.func_180495_p(p_175685_1_), java.util.EnumSet.allOf(EnumFacing.class)).isCanceled()) + return; -+ ++ this.func_180496_d(p_175685_1_.func_177976_e(), p_175685_2_); this.func_180496_d(p_175685_1_.func_177974_f(), p_175685_2_); this.func_180496_d(p_175685_1_.func_177977_b(), p_175685_2_); @@ -188,7 +188,7 @@ + directions.remove(p_175695_3_); + if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, p_175695_1_, this.func_180495_p(p_175695_1_), directions).isCanceled()) + return; -+ ++ if (p_175695_3_ != EnumFacing.WEST) { this.func_180496_d(p_175695_1_.func_177976_e(), p_175695_2_); @@ -590,16 +590,18 @@ int i; EntityPlayer entityplayer; int j; -@@ -2445,7 +2617,7 @@ +@@ -2444,8 +2616,9 @@ + Block block = p_147467_3_.func_177428_a(blockpos); l += p_147467_1_; i1 += p_147467_2_; ++ BlockPos worldpos = blockpos.func_177982_a(p_147467_1_, 0, p_147467_2_); - if (block.func_149688_o() == Material.field_151579_a && this.func_175699_k(blockpos) <= this.field_73012_v.nextInt(8) && this.func_175642_b(EnumSkyBlock.SKY, blockpos) <= 0) -+ if (block.isAir(this, blockpos) && this.func_175699_k(blockpos) <= this.field_73012_v.nextInt(8) && this.func_175642_b(EnumSkyBlock.SKY, blockpos) <= 0) ++ if (block.isAir(this, worldpos) && this.func_175699_k(worldpos) <= this.field_73012_v.nextInt(8) && this.func_175642_b(EnumSkyBlock.SKY, worldpos) <= 0) //Forge: isAir, and fix arguments to world positions instead of chunk position { EntityPlayer entityplayer = this.func_72977_a((double)l + 0.5D, (double)j1 + 0.5D, (double)i1 + 0.5D, 8.0D); -@@ -2485,6 +2657,11 @@ +@@ -2485,6 +2658,11 @@ public boolean func_175670_e(BlockPos p_175670_1_, boolean p_175670_2_) { @@ -611,7 +613,7 @@ BiomeGenBase biomegenbase = this.func_180494_b(p_175670_1_); float f = biomegenbase.func_180626_a(p_175670_1_); -@@ -2526,6 +2703,11 @@ +@@ -2526,6 +2704,11 @@ public boolean func_175708_f(BlockPos p_175708_1_, boolean p_175708_2_) { @@ -623,7 +625,7 @@ BiomeGenBase biomegenbase = this.func_180494_b(p_175708_1_); float f = biomegenbase.func_180626_a(p_175708_1_); -@@ -2543,7 +2725,7 @@ +@@ -2543,7 +2726,7 @@ { Block block = this.func_180495_p(p_175708_1_).func_177230_c(); @@ -632,7 +634,7 @@ { return true; } -@@ -2575,10 +2757,11 @@ +@@ -2575,10 +2758,11 @@ else { Block block = this.func_180495_p(p_175638_1_).func_177230_c(); @@ -647,7 +649,7 @@ { j = 1; } -@@ -2792,10 +2975,10 @@ +@@ -2792,10 +2976,10 @@ public List func_175674_a(Entity p_175674_1_, AxisAlignedBB p_175674_2_, Predicate p_175674_3_) { ArrayList arraylist = Lists.newArrayList(); @@ -662,7 +664,7 @@ for (int i1 = i; i1 <= j; ++i1) { -@@ -2854,10 +3037,10 @@ +@@ -2854,10 +3038,10 @@ public List func_175647_a(Class p_175647_1_, AxisAlignedBB p_175647_2_, Predicate p_175647_3_) { @@ -677,7 +679,7 @@ ArrayList arraylist = Lists.newArrayList(); for (int i1 = i; i1 <= j; ++i1) -@@ -2938,13 +3121,16 @@ +@@ -2938,13 +3122,16 @@ public void func_175650_b(Collection p_175650_1_) { @@ -696,7 +698,7 @@ } } -@@ -2957,7 +3143,9 @@ +@@ -2957,7 +3144,9 @@ { Block block1 = this.func_180495_p(p_175716_2_).func_177230_c(); AxisAlignedBB axisalignedbb = p_175716_3_ ? null : p_175716_1_.func_180640_a(this, p_175716_2_, p_175716_1_.func_176223_P()); @@ -707,7 +709,7 @@ } public int func_175627_a(BlockPos p_175627_1_, EnumFacing p_175627_2_) -@@ -3032,7 +3220,7 @@ +@@ -3032,7 +3221,7 @@ { IBlockState iblockstate = this.func_180495_p(p_175651_1_); Block block = iblockstate.func_177230_c(); @@ -716,7 +718,7 @@ } public boolean func_175640_z(BlockPos p_175640_1_) -@@ -3160,7 +3348,7 @@ +@@ -3160,7 +3349,7 @@ public long func_72905_C() { @@ -725,7 +727,7 @@ } public long func_82737_E() -@@ -3170,17 +3358,17 @@ +@@ -3170,17 +3359,17 @@ public long func_72820_D() { @@ -746,7 +748,7 @@ if (!this.func_175723_af().func_177746_a(blockpos)) { -@@ -3192,7 +3380,7 @@ +@@ -3192,7 +3381,7 @@ public void func_175652_B(BlockPos p_175652_1_) { @@ -755,7 +757,7 @@ } @SideOnly(Side.CLIENT) -@@ -3212,12 +3400,18 @@ +@@ -3212,12 +3401,18 @@ if (!this.field_72996_f.contains(p_72897_1_)) { @@ -774,7 +776,7 @@ return true; } -@@ -3307,8 +3501,7 @@ +@@ -3307,8 +3502,7 @@ public boolean func_180502_D(BlockPos p_180502_1_) { @@ -784,7 +786,7 @@ } public MapStorage func_175693_T() -@@ -3367,12 +3560,12 @@ +@@ -3367,12 +3561,12 @@ public int func_72800_K() { @@ -799,7 +801,7 @@ } public Random func_72843_D(int p_72843_1_, int p_72843_2_, int p_72843_3_) -@@ -3429,7 +3622,7 @@ +@@ -3429,7 +3623,7 @@ @SideOnly(Side.CLIENT) public double func_72919_O() { @@ -808,7 +810,7 @@ } public void func_175715_c(int p_175715_1_, BlockPos p_175715_2_, int p_175715_3_) -@@ -3461,29 +3654,21 @@ +@@ -3461,29 +3655,21 @@ public void func_175666_e(BlockPos p_175666_1_, Block p_175666_2_) { @@ -845,7 +847,7 @@ } } } -@@ -3553,4 +3738,82 @@ +@@ -3553,4 +3739,82 @@ short short1 = 128; return k >= -short1 && k <= short1 && l >= -short1 && l <= short1; } From f9024d2eb38ed92b0621be47fce4a8995bb8b822 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Mon, 16 Nov 2015 06:50:54 +0300 Subject: [PATCH 07/11] Implemented interpolation of TRSR transformations; B3D: added interpolation capabilities to B3DState, animated TESR example in ModelAnimationTest (pure TESR right now, no separation inside the example model between the static and dynamic parts right now). --- .../client/model/TRSRTransformation.java | 133 +++--- .../client/model/b3d/B3DLoader.java | 378 +++++++++++++++--- .../debug/ModelAnimationDebug.java | 286 +++++++++++++ .../blockstates/test_animation_block.json | 26 ++ 4 files changed, 717 insertions(+), 106 deletions(-) create mode 100644 src/test/java/net/minecraftforge/debug/ModelAnimationDebug.java create mode 100644 src/test/resources/assets/forgedebugmodelanimation/blockstates/test_animation_block.json diff --git a/src/main/java/net/minecraftforge/client/model/TRSRTransformation.java b/src/main/java/net/minecraftforge/client/model/TRSRTransformation.java index 34d7962ea6..54c5696f33 100644 --- a/src/main/java/net/minecraftforge/client/model/TRSRTransformation.java +++ b/src/main/java/net/minecraftforge/client/model/TRSRTransformation.java @@ -3,6 +3,8 @@ package net.minecraftforge.client.model; import javax.vecmath.Matrix3f; import javax.vecmath.Matrix4f; import javax.vecmath.Quat4f; +import javax.vecmath.Tuple3f; +import javax.vecmath.Tuple4f; import javax.vecmath.Vector3f; import javax.vecmath.Vector4f; @@ -181,7 +183,6 @@ public class TRSRTransformation implements IModelState, ITransformation { Matrix4f res = new Matrix4f(), t = new Matrix4f(); res.setIdentity(); - if(translation != null) res.setTranslation(translation); if(leftRot != null) { t.set(leftRot); @@ -200,6 +201,7 @@ public class TRSRTransformation implements IModelState, ITransformation t.set(rightRot); res.mul(t); } + if(translation != null) res.setTranslation(translation); return res; } @@ -221,7 +223,8 @@ public class TRSRTransformation implements IModelState, ITransformation b.set(m); b.mul(t); - sortSingularValues(b, v); + // FIXME: this doesn't work correctly for some reason; not crucial, so disabling for now; investigate in the future. + //sortSingularValues(b, v); Pair p; @@ -281,7 +284,7 @@ public class TRSRTransformation implements IModelState, ITransformation return f; } - private static final float eps = 1e-7f; + private static final float eps = 1e-6f; private static final float g = 3f + 2f * (float)Math.sqrt(2); private static final float cs = (float)Math.cos(Math.PI / 8); private static final float ss = (float)Math.sin(Math.PI / 8); @@ -365,50 +368,59 @@ public class TRSRTransformation implements IModelState, ITransformation Quat4f qt = new Quat4f(), ret = new Quat4f(0, 0, 0, 1); Pair p; // 01 - p = approxGivensQuat(m.m00, .5f * (m.m01 + m.m10), m.m11); - qt.set(0, 0, p.getLeft(), p.getRight()); - //qt.normalize(); - ret.mul(qt); - //t.set(qt); - t.setIdentity(); - t.m00 = qt.w * qt.w - qt.z * qt.z; - t.m11 = t.m00; - t.m10 = 2 * qt.z * qt.w; - t.m01 = -t.m10; - t.m22 = qt.w * qt.w + qt.z * qt.z; - m.mul(m, t); - t.transpose(); - m.mul(t, m); + if(m.m01 * m.m01 + m.m10 * m.m10 > eps) + { + p = approxGivensQuat(m.m00, .5f * (m.m01 + m.m10), m.m11); + qt.set(0, 0, p.getLeft(), p.getRight()); + //qt.normalize(); + ret.mul(qt); + //t.set(qt); + t.setIdentity(); + t.m00 = qt.w * qt.w - qt.z * qt.z; + t.m11 = t.m00; + t.m10 = 2 * qt.z * qt.w; + t.m01 = -t.m10; + t.m22 = qt.w * qt.w + qt.z * qt.z; + m.mul(m, t); + t.transpose(); + m.mul(t, m); + } // 02 - p = approxGivensQuat(m.m00, .5f * (m.m02 + m.m20), m.m22); - qt.set(0, -p.getLeft(), 0, p.getRight()); - //qt.normalize(); - ret.mul(qt); - //t.set(qt); - t.setIdentity(); - t.m00 = qt.w * qt.w - qt.y * qt.y; - t.m22 = t.m00; - t.m20 = -2 * qt.y * qt.w; - t.m02 = -t.m20; - t.m11 = qt.w * qt.w + qt.y * qt.y; - m.mul(m, t); - t.transpose(); - m.mul(t, m); + if(m.m02 * m.m02 + m.m20 * m.m20 > eps) + { + p = approxGivensQuat(m.m00, .5f * (m.m02 + m.m20), m.m22); + qt.set(0, -p.getLeft(), 0, p.getRight()); + //qt.normalize(); + ret.mul(qt); + //t.set(qt); + t.setIdentity(); + t.m00 = qt.w * qt.w - qt.y * qt.y; + t.m22 = t.m00; + t.m20 = -2 * qt.y * qt.w; + t.m02 = -t.m20; + t.m11 = qt.w * qt.w + qt.y * qt.y; + m.mul(m, t); + t.transpose(); + m.mul(t, m); + } // 12 - p = approxGivensQuat(m.m11, .5f * (m.m12 + m.m21), m.m22); - qt.set(p.getLeft(), 0, 0, p.getRight()); - //qt.normalize(); - ret.mul(qt); - //t.set(qt); - t.setIdentity(); - t.m11 = qt.w * qt.w - qt.x * qt.x; - t.m22 = t.m11; - t.m21 = 2 * qt.x * qt.w; - t.m12 = -t.m21; - t.m00 = qt.w * qt.w + qt.x * qt.x; - m.mul(m, t); - t.transpose(); - m.mul(t, m); + if(m.m12 * m.m12 + m.m21 * m.m21 > eps) + { + p = approxGivensQuat(m.m11, .5f * (m.m12 + m.m21), m.m22); + qt.set(p.getLeft(), 0, 0, p.getRight()); + //qt.normalize(); + ret.mul(qt); + //t.set(qt); + t.setIdentity(); + t.m11 = qt.w * qt.w - qt.x * qt.x; + t.m22 = t.m11; + t.m21 = 2 * qt.x * qt.w; + t.m12 = -t.m21; + t.m00 = qt.w * qt.w + qt.x * qt.x; + m.mul(m, t); + t.transpose(); + m.mul(t, m); + } return ret; } @@ -566,4 +578,35 @@ public class TRSRTransformation implements IModelState, ITransformation else if (!matrix.equals(other.matrix)) return false; return true; } + + public static Vector3f lerp(Tuple3f from, Tuple3f to, float progress) + { + Vector3f res = new Vector3f(from); + res.interpolate(from, to, progress); + return res; + } + + public static Vector4f lerp(Tuple4f from, Tuple4f to, float progress) + { + Vector4f res = new Vector4f(from); + res.interpolate(from, to, progress); + return res; + } + + public static Quat4f slerp(Quat4f from, Quat4f to, float progress) + { + Quat4f res = new Quat4f(); + res.interpolate(from, to, progress); + return res; + } + + public TRSRTransformation slerp(TRSRTransformation that, float progress) + { + return new TRSRTransformation( + lerp(this.getTranslation(), that.getTranslation(), progress), + slerp(this.getLeftRot(), that.getLeftRot(), progress), + lerp(this.getScale(), that.getScale(), progress), + slerp(this.getRightRot(), that.getRightRot(), progress) + ); + } } diff --git a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java index d75ab37dab..5cfad738db 100644 --- a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java +++ b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java @@ -25,6 +25,7 @@ import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.model.IBakedModel; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ICustomModelLoader; import net.minecraftforge.client.model.IFlexibleBakedModel; @@ -65,6 +66,9 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; /* * Loader for Blitz3D models. @@ -138,16 +142,19 @@ public class B3DLoader implements ICustomModelLoader FMLLog.severe("No mesh named %s in model %s, skipping", mesh, modelLocation); return ModelLoaderRegistry.getMissingModel(); } - return new Wrapper(modelLocation, model.getTextures(), model.getMeshes().get(mesh)); + return new ModelWrapper(modelLocation, model, ImmutableSet.of(mesh), 1); } if(!(model.getRoot().getKind() instanceof Mesh)) { - FMLLog.severe("No root mesh in model %s and no mesh name in location, skipping", modelLocation); - return ModelLoaderRegistry.getMissingModel(); + return new ModelWrapper(modelLocation, model, ImmutableSet.of(), 1); } - return new Wrapper(modelLocation, model.getTextures(), (Node)model.getRoot()); + return new ModelWrapper(modelLocation, model, ImmutableSet.of(((Node)model.getRoot()).getName()), 1); } + /** + * @deprecated Use json or IModelCustomData.process + */ + @Deprecated public static class B3DMeshLocation extends ResourceLocation { public final String mesh; @@ -192,17 +199,31 @@ public class B3DLoader implements ICustomModelLoader { private final Animation animation; private final int frame; + private final int nextFrame; + private final float progress; private final IModelState parent; public B3DState(Animation animation, int frame) { - this(animation, frame, null); + this(animation, frame, frame, 0); } public B3DState(Animation animation, int frame, IModelState parent) + { + this(animation, frame, frame, 0, parent); + } + + public B3DState(Animation animation, int frame, int nextFrame, float progress) + { + this(animation, frame, nextFrame, progress, null); + } + + public B3DState(Animation animation, int frame, int nextFrame, float progress, IModelState parent) { this.animation = animation; this.frame = frame; + this.nextFrame = nextFrame; + this.progress = MathHelper.clamp_float(progress, 0, 1); this.parent = getParent(parent); } @@ -223,17 +244,47 @@ public class B3DLoader implements ICustomModelLoader return frame; } + public int getNextFrame() + { + return nextFrame; + } + + public float getProgress() + { + return progress; + } + + public IModelState getParent() + { + return parent; + } + public TRSRTransformation apply(IModelPart part) { if(!(part instanceof PartWrapper)) { throw new IllegalArgumentException("B3DState can only be applied to b3d models"); } + Node node = ((PartWrapper)part).getNode(); + TRSRTransformation nodeTransform; + if(progress < 1e-5 || frame == nextFrame) + { + nodeTransform = getNodeMatrix(node, frame); + } + else if(progress > 1 - 1e-5) + { + nodeTransform = getNodeMatrix(node, nextFrame); + } + else + { + nodeTransform = getNodeMatrix(node, frame); + nodeTransform = nodeTransform.slerp(getNodeMatrix(node, nextFrame), progress); + } if(parent != null) { - return parent.apply(part).compose(getNodeMatrix(((PartWrapper)part).getNode())); + return parent.apply(part).compose(nodeTransform); } - return getNodeMatrix(((PartWrapper)part).getNode()); + return nodeTransform; } private static LoadingCache, Integer>, TRSRTransformation> cache = CacheBuilder.newBuilder() @@ -252,6 +303,11 @@ public class B3DLoader implements ICustomModelLoader return cache.getUnchecked(Triple., Integer>of(animation, node, frame)); } + public TRSRTransformation getNodeMatrix(Node node, int frame) + { + return cache.getUnchecked(Triple., Integer>of(animation, node, frame)); + } + public static TRSRTransformation getNodeMatrix(Animation animation, Node node, int frame) { TRSRTransformation ret = TRSRTransformation.identity(); @@ -326,20 +382,36 @@ public class B3DLoader implements ICustomModelLoader } } + /** + * @deprecated Use ModelWrapper, this will be removed in 1.9 + */ + @Deprecated public static class Wrapper extends PartWrapper implements IRetexturableModel, IModelCustomData { private final ResourceLocation location; + private final ImmutableSet meshes; private final ImmutableMap textures; public Wrapper(ResourceLocation location, List textures, B3DModel.Node mesh) { - this(location, buildTextures(textures), mesh); + this(location, ImmutableSet.of(), buildTextures(textures), mesh); } public Wrapper(ResourceLocation location, ImmutableMap textures, B3DModel.Node mesh) + { + this(location, ImmutableSet.of(), textures, mesh); + } + + public Wrapper(ResourceLocation location, ImmutableSet meshes, List textures, B3DModel.Node mesh) + { + this(location, meshes, buildTextures(textures), mesh); + } + + public Wrapper(ResourceLocation location, ImmutableSet meshes, ImmutableMap textures, B3DModel.Node mesh) { super(mesh); this.location = location; + this.meshes = meshes; this.textures = textures; } @@ -398,7 +470,7 @@ public class B3DLoader implements ICustomModelLoader } } builder.put("missingno", missing); - return new BakedWrapper(this, state, format, builder.build()); + return new BakedWrapper(getNode(), state, format, meshes, builder.build()); } public B3DState getDefaultState() @@ -465,29 +537,211 @@ public class B3DLoader implements ICustomModelLoader @Override public IModel process(ImmutableMap customData) { - // TODO keyframe - return null; + return this; + } + } + public static class ModelWrapper implements IRetexturableModel, IModelCustomData + { + private final ResourceLocation modelLocation; + private final B3DModel model; + private final ImmutableSet meshes; + private final ImmutableMap textures; + private final int defaultKey; + + public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet meshes, int defaultKey) + { + this(modelLocation, model, meshes, defaultKey, buildTextures(model.getTextures())); + } + + public ModelWrapper(ResourceLocation modelLocation, B3DModel model, ImmutableSet meshes, int defaultKey, ImmutableMap textures) + { + this.modelLocation = modelLocation; + this.model = model; + this.meshes = meshes; + this.textures = textures; + this.defaultKey = defaultKey; + } + + private static ImmutableMap buildTextures(List textures) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + + for(Texture t : textures) + { + String path = t.getPath(); + String location = getLocation(path); + if(!location.startsWith("#")) location = "#" + location; + builder.put(path, new ResourceLocation(location)); + } + return builder.build(); + } + + private static String getLocation(String path) + { + if(path.endsWith(".png")) path = path.substring(0, path.length() - ".png".length()); + return path; + } + + @Override + public Collection getDependencies() + { + return Collections.emptyList(); + } + + @Override + public Collection getTextures() + { + return Collections2.filter(textures.values(), new Predicate() + { + public boolean apply(ResourceLocation loc) + { + return !loc.getResourcePath().startsWith("#"); + } + }); + } + + @Override + public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function bakedTextureGetter) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + TextureAtlasSprite missing = bakedTextureGetter.apply(new ResourceLocation("missingno")); + for(Map.Entry e : textures.entrySet()) + { + if(e.getValue().getResourcePath().startsWith("#")) + { + FMLLog.severe("unresolved texture '%s' for b3d model '%s'", e.getValue().getResourcePath(), modelLocation); + builder.put(e.getKey(), missing); + } + else + { + builder.put(e.getKey(), bakedTextureGetter.apply(e.getValue())); + } + } + builder.put("missingno", missing); + return new BakedWrapper(model.getRoot(), state, format, meshes, builder.build()); + } + + @Override + public IModelState getDefaultState() + { + return new B3DState(model.getRoot().getAnimation(), defaultKey, defaultKey, 0); + } + + @Override + public IModel retexture(ImmutableMap textures) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for(Map.Entry e : this.textures.entrySet()) + { + String path = e.getKey(); + String loc = getLocation(path); + if(textures.containsKey(loc)) + { + String newLoc = textures.get(loc); + if(newLoc == null) newLoc = getLocation(path); + builder.put(e.getKey(), new ResourceLocation(newLoc)); + } + else + { + builder.put(e); + } + } + return new ModelWrapper(modelLocation, model, meshes, defaultKey, builder.build()); + } + + @Override + public IModel process(ImmutableMap data) + { + if(data.containsKey("mesh")) + { + JsonElement e = new JsonParser().parse(data.get("mesh")); + if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isString()) + { + return new ModelWrapper(modelLocation, model, ImmutableSet.of(e.getAsString()), defaultKey, textures); + } + else if (e.isJsonArray()) + { + ImmutableSet.Builder builder = ImmutableSet.builder(); + for(JsonElement s : e.getAsJsonArray()) + { + if(s.isJsonPrimitive() && s.getAsJsonPrimitive().isString()) + { + builder.add(s.getAsString()); + } + else + { + FMLLog.severe("unknown mesh definition '%s' in array for b3d model '%s'", s.toString(), modelLocation); + return this; + } + } + return new ModelWrapper(modelLocation, model, builder.build(), defaultKey, textures); + } + else + { + FMLLog.severe("unknown mesh definition '%s' for b3d model '%s'", e.toString(), modelLocation); + return this; + } + } + if(data.containsKey("key")) + { + JsonElement e = new JsonParser().parse(data.get("key")); + if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) + { + return new ModelWrapper(modelLocation, model, meshes, e.getAsNumber().intValue(), textures); + } + else + { + FMLLog.severe("unknown keyframe definition '%s' for b3d model '%s'", e.toString(), modelLocation); + return this; + } + } + return this; } } private static class BakedWrapper implements IFlexibleBakedModel, ISmartBlockModel, ISmartItemModel, IPerspectiveAwareModel { - private final B3DLoader.Wrapper model; + private final Node node; private final IModelState state; private final VertexFormat format; + private final ImmutableSet meshes; private final ImmutableMap textures; + private final LoadingCache cache; private ImmutableList quads; - private static final int BYTES_IN_INT = Integer.SIZE / Byte.SIZE; - private static final int VERTICES_IN_QUAD = 4; - - public BakedWrapper(B3DLoader.Wrapper model, IModelState state, VertexFormat format, ImmutableMap textures) + public BakedWrapper(Node node, IModelState state, VertexFormat format, ImmutableSet meshes, ImmutableMap textures) { - this.model = model; + this(node, state, format, meshes, textures, CacheBuilder.newBuilder() + .maximumSize(128) + .expireAfterAccess(2, TimeUnit.MINUTES) + .build(new CacheLoader() + { + public BakedWrapper load(Integer frame) throws Exception + { + IModelState parent = state; + Animation newAnimation = null; + if(parent instanceof B3DState) + { + B3DState ps = (B3DState)parent; + parent = ps.getParent(); + } + if(newAnimation == null) + { + newAnimation = node.getAnimation(); + } + return new BakedWrapper(node, new B3DState(newAnimation, frame, frame, 0, parent), format, meshes, textures); + } + })); + } + public BakedWrapper(Node node, IModelState state, VertexFormat format, ImmutableSet meshes, ImmutableMap textures, LoadingCache cache) + { + this.node = node; this.state = state; this.format = format; + this.meshes = meshes; this.textures = textures; + this.cache = cache; } public List getFaceQuads(EnumFacing side) @@ -495,47 +749,43 @@ public class B3DLoader implements ICustomModelLoader return Collections.emptyList(); } - @SuppressWarnings("unchecked") public List getGeneralQuads() { if(quads == null) { - Node mesh = model.getNode(); ImmutableList.Builder builder = ImmutableList.builder(); - for(Node child : mesh.getNodes().values()) + for(Node child : node.getNodes().values()) { - if(child.getKind() instanceof Mesh) - { - Node childMesh = (Node)child; - builder.addAll(new BakedWrapper(new B3DLoader.Wrapper(model.getLocation(), model.getTextureMap(), childMesh), state, format, textures).getGeneralQuads()); - } + builder.addAll(new BakedWrapper(child, state, format, meshes, textures).getGeneralQuads()); } - mesh.getKind().getWeightMap(); - Collection faces = mesh.getKind().getFaces(); - faces = mesh.getKind().bake(new Function, Matrix4f>() + if(node.getKind() instanceof Mesh && meshes.contains(node.getName())) { - // gets transformation in global space - public Matrix4f apply(Node node) + Mesh mesh = (Mesh)node.getKind(); + Collection faces = mesh.bake(new Function, Matrix4f>() { - return state.apply(PartWrapper.create(node)).getMatrix(); + // gets transformation in global space + public Matrix4f apply(Node node) + { + return state.apply(PartWrapper.create(node)).getMatrix(); + } + }); + for(Face f : faces) + { + UnpackedBakedQuad.Builder quadBuilder = new UnpackedBakedQuad.Builder(format); + quadBuilder.setQuadOrientation(EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z)); + quadBuilder.setQuadColored(); + List textures = null; + if(f.getBrush() != null) textures = f.getBrush().getTextures(); + TextureAtlasSprite sprite; + if(textures == null || textures.isEmpty()) sprite = this.textures.get("missingno"); + else if(textures.get(0) == B3DModel.Texture.White) sprite = ModelLoader.White.instance; + else sprite = this.textures.get(textures.get(0).getPath()); + putVertexData(quadBuilder, f.getV1(), f.getNormal(), sprite); + putVertexData(quadBuilder, f.getV2(), f.getNormal(), sprite); + putVertexData(quadBuilder, f.getV3(), f.getNormal(), sprite); + putVertexData(quadBuilder, f.getV3(), f.getNormal(), sprite); + builder.add(quadBuilder.build()); } - }); - for(Face f : faces) - { - UnpackedBakedQuad.Builder quadBuilder = new UnpackedBakedQuad.Builder(format); - quadBuilder.setQuadOrientation(EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z)); - quadBuilder.setQuadColored(); - List textures = null; - if(f.getBrush() != null) textures = f.getBrush().getTextures(); - TextureAtlasSprite sprite; - if(textures == null || textures.isEmpty()) sprite = this.textures.get("missingno"); - else if(textures.get(0) == B3DModel.Texture.White) sprite = ModelLoader.White.instance; - else sprite = this.textures.get(textures.get(0).getPath()); - putVertexData(quadBuilder, f.getV1(), f.getNormal(), sprite); - putVertexData(quadBuilder, f.getV2(), f.getNormal(), sprite); - putVertexData(quadBuilder, f.getV3(), f.getNormal(), sprite); - putVertexData(quadBuilder, f.getV3(), f.getNormal(), sprite); - builder.add(quadBuilder.build()); } quads = builder.build(); } @@ -632,24 +882,30 @@ public class B3DLoader implements ICustomModelLoader B3DState s = exState.getValue(B3DFrameProperty.instance); if(s != null) { - return getCachedModel(s.getFrame()); + //return getCachedModel(s.getFrame()); + IModelState parent = this.state; + Animation newAnimation = s.getAnimation(); + if(parent instanceof B3DState) + { + B3DState ps = (B3DState)parent; + parent = ps.getParent(); + } + if(newAnimation == null) + { + newAnimation = node.getAnimation(); + } + if(s.getFrame() == s.getNextFrame()) + { + return cache.getUnchecked(s.getFrame()); + } + B3DState newState = new B3DState(newAnimation, s.getFrame(), s.getNextFrame(), s.getProgress(), parent); + return new BakedWrapper(node, newState, format, meshes, textures); } } } return this; } - private final Map cache = new HashMap(); - - public BakedWrapper getCachedModel(int frame) - { - if(!cache.containsKey(frame)) - { - cache.put(frame, new BakedWrapper(model, new B3DState(model.getNode().getAnimation(), frame, state), format, textures)); - } - return cache.get(frame); - } - public VertexFormat getFormat() { return format; @@ -665,7 +921,7 @@ public class B3DLoader implements ICustomModelLoader { if(state instanceof IPerspectiveState) { - return Pair.of((IBakedModel)this, TRSRTransformation.blockCornerToCenter(((IPerspectiveState)state).forPerspective(cameraTransformType).apply(model)).getMatrix()); + return Pair.of((IBakedModel)this, TRSRTransformation.blockCornerToCenter(((IPerspectiveState)state).forPerspective(cameraTransformType).apply(PartWrapper.create(node))).getMatrix()); } return Pair.of((IBakedModel)this, null); } diff --git a/src/test/java/net/minecraftforge/debug/ModelAnimationDebug.java b/src/test/java/net/minecraftforge/debug/ModelAnimationDebug.java new file mode 100644 index 0000000000..2652ed0a85 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/ModelAnimationDebug.java @@ -0,0 +1,286 @@ +package net.minecraftforge.debug; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockPistonBase; +import net.minecraft.block.material.Material; +import net.minecraft.block.properties.IProperty; +import net.minecraft.block.properties.PropertyDirection; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.model.IBakedModel; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.server.gui.IUpdatePlayerListBox; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.client.model.ISmartBlockModel; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.client.model.b3d.B3DLoader; +import net.minecraftforge.client.model.b3d.B3DLoader.B3DFrameProperty; +import net.minecraftforge.client.model.b3d.B3DLoader.B3DState; +import net.minecraftforge.common.property.ExtendedBlockState; +import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.common.property.IUnlistedProperty; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; + +import org.lwjgl.opengl.GL11; + +@Mod(modid = ModelAnimationDebug.MODID, version = ModelAnimationDebug.VERSION) +public class ModelAnimationDebug +{ + public static final String MODID = "forgedebugmodelanimation"; + public static final String VERSION = "0.0"; + + public static String blockName = "test_animation_block"; + public static final PropertyDirection FACING = PropertyDirection.create("facing"); + + @SidedProxy(serverSide = "net.minecraftforge.debug.ModelAnimationDebug$CommonProxy", clientSide = "net.minecraftforge.debug.ModelAnimationDebug$ClientProxy") + public static CommonProxy proxy; + + public static class CommonProxy + { + public void preInit(FMLPreInitializationEvent event) + { + B3DLoader.instance.addDomain(MODID); + GameRegistry.registerBlock(new Block(Material.wood) + { + { + setCreativeTab(CreativeTabs.tabBlock); + setUnlocalizedName(MODID + "." + blockName); + } + + @Override + public ExtendedBlockState createBlockState() + { + return new ExtendedBlockState(this, new IProperty[]{ FACING }, new IUnlistedProperty[]{ B3DFrameProperty.instance }); + } + + @Override + public int getRenderType() { return -1; } + + @Override + public boolean isOpaqueCube() { return false; } + + @Override + public boolean isFullCube() { return false; } + + @Override + public IBlockState onBlockPlaced(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer) + { + return this.getDefaultState().withProperty(FACING, BlockPistonBase.getFacingFromEntity(world, pos, placer)); + } + + @Override + public IBlockState getStateFromMeta(int meta) { + return getDefaultState().withProperty(FACING, EnumFacing.getFront(meta)); + } + + @Override + public int getMetaFromState(IBlockState state) { + return ((EnumFacing)state.getValue(FACING)).getIndex(); + } + + @Override + public boolean hasTileEntity(IBlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(World world, IBlockState state) { + return new Chest(state); + } + + /*@Override + public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos) { + TileEntity te = world.getTileEntity(pos); + if(te instanceof Chest && state instanceof IExtendedBlockState) + { + return ((Chest)te).getState((IExtendedBlockState)state); + } + return super.getExtendedState(state, world, pos); + }*/ + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) + { + if(world.isRemote) + { + TileEntity te = world.getTileEntity(pos); + if(te instanceof Chest) + { + ((Chest)te).click(); + } + } + return false; + } + }, blockName); + } + + public void init(FMLInitializationEvent event) {} + } + + public static class ClientProxy extends CommonProxy + { + @Override + public void preInit(FMLPreInitializationEvent event) + { + super.preInit(event); + ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(GameRegistry.findBlock(MODID, blockName)), 0, new ModelResourceLocation(MODID.toLowerCase() + ":" + blockName, "inventory")); + } + + @Override + public void init(FMLInitializationEvent event) + { + super.init(event); + ClientRegistry.bindTileEntitySpecialRenderer(Chest.class, ChestRenderer.instance); + } + } + + @EventHandler + public void preInit(FMLPreInitializationEvent event) { proxy.preInit(event); } + + @EventHandler + public void init(FMLInitializationEvent event) { proxy.init(event); } + + private static class Chest extends TileEntity implements IUpdatePlayerListBox + { + private final int minFrame = 1; + private final int maxFrame = 10; + private int tick = minFrame; + private boolean opening = false; + private boolean closing = false; + + public Chest(IBlockState state) { + } + + /*public IExtendedBlockState getState(IExtendedBlockState state) { + return state.withProperty(B3DFrameProperty.instance, curState); + }*/ + + public void click() + { + if(opening || tick == maxFrame) + { + opening = false; + closing = true; + return; + } + if(closing || tick == minFrame) + { + closing = false; + opening = true; + return; + } + opening = true; + } + + @Override + public void update() + { + if(opening) + { + tick++; + if(tick >= maxFrame) + { + tick = maxFrame; + opening = false; + } + } + if(closing) + { + tick--; + if(tick <= minFrame) + { + tick = minFrame; + closing = false; + } + } + } + + public int getCurFrame() + { + return tick; + } + + public int getNextFrame() + { + if(opening) return Math.min(tick + 1, maxFrame); + if(closing) return Math.max(tick - 1, minFrame); + return tick; + } + } + + private static class ChestRenderer extends TileEntitySpecialRenderer + { + public static ChestRenderer instance = new ChestRenderer(); + private ChestRenderer() {} + + private final BlockRendererDispatcher blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher(); + + public void renderTileEntityAt(TileEntity te, double x, double y, double z, float partialTick, int breakStage) + { + IBlockState state = te.getWorld().getBlockState(te.getPos()); + IBakedModel model = this.blockRenderer.getModelFromBlockState(state, te.getWorld(), te.getPos()); + if(state instanceof IExtendedBlockState) + { + IExtendedBlockState exState = (IExtendedBlockState)state; + if(exState.getUnlistedNames().contains(B3DFrameProperty.instance)) + { + exState = exState.withProperty(B3DFrameProperty.instance, new B3DState(null, ((Chest)te).getCurFrame(), ((Chest)te).getNextFrame(), partialTick)); + if(model instanceof ISmartBlockModel) + { + model = ((ISmartBlockModel)model).handleBlockState(exState); + } + } + } + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + this.bindTexture(TextureMap.locationBlocksTexture); + RenderHelper.disableStandardItemLighting(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableBlend(); + GlStateManager.disableCull(); + + if (Minecraft.isAmbientOcclusionEnabled()) + { + GlStateManager.shadeModel(GL11.GL_SMOOTH); + } + else + { + GlStateManager.shadeModel(GL11.GL_FLAT); + } + + worldrenderer.startDrawingQuads(); + worldrenderer.setVertexFormat(DefaultVertexFormats.BLOCK); + worldrenderer.setTranslation(x - te.getPos().getX(), y - te.getPos().getY(), z - te.getPos().getZ()); + + this.blockRenderer.getBlockModelRenderer().renderModel(te.getWorld(), model, state, te.getPos(), worldrenderer, false); + + worldrenderer.setTranslation(0, 0, 0); + tessellator.draw(); + + RenderHelper.enableStandardItemLighting(); + } + } +} + diff --git a/src/test/resources/assets/forgedebugmodelanimation/blockstates/test_animation_block.json b/src/test/resources/assets/forgedebugmodelanimation/blockstates/test_animation_block.json new file mode 100644 index 0000000000..b12b0913d7 --- /dev/null +++ b/src/test/resources/assets/forgedebugmodelanimation/blockstates/test_animation_block.json @@ -0,0 +1,26 @@ +{ + "forge_marker": 1, + "defaults": { + "textures": { + "#chest": "entity/chest/normal" + }, + "model": "forgedebugmodelloaderregistry:chest.b3d", + "custom": { + "mesh": ["Cube.001"] + } + }, + "variants": { + "normal": [{}], + "inventory": [{ + "transform": "forge:default-block" + }], + "facing": { + "down": { "transform": { "rotation": { "x": 90 } } }, + "up": { "transform": { "rotation": { "x": 270 } } }, + "north": { "transform": { "rotation": { "y": 180 } } }, + "south": { "transform": "identity" }, + "west": { "transform": { "rotation": { "y": 90 } } }, + "east": { "transform": { "rotation": { "y": 270 } } } + } + } +} From f6ab01843c7bcdeb231304f7e6ae9e5735e910f1 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Thu, 19 Nov 2015 23:40:44 +0300 Subject: [PATCH 08/11] B3D loader: removed 2 redundand null checks, changed constructor args to final to fix (java6?) inner arg error. --- .../net/minecraftforge/client/model/b3d/B3DLoader.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java index 5cfad738db..91130d2d45 100644 --- a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java +++ b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java @@ -313,7 +313,7 @@ public class B3DLoader implements ICustomModelLoader TRSRTransformation ret = TRSRTransformation.identity(); Key key = null; if(animation != null) key = animation.getKeys().get(frame, node); - else if(key == null && node.getAnimation() != null && node.getAnimation() != animation) key = node.getAnimation().getKeys().get(frame, node); + else if(node.getAnimation() != null && node.getAnimation() != animation) key = node.getAnimation().getKeys().get(frame, node); if(key != null) { Node parent = node.getParent(); @@ -710,7 +710,7 @@ public class B3DLoader implements ICustomModelLoader private ImmutableList quads; - public BakedWrapper(Node node, IModelState state, VertexFormat format, ImmutableSet meshes, ImmutableMap textures) + public BakedWrapper(final Node node, final IModelState state, final VertexFormat format, final ImmutableSet meshes, final ImmutableMap textures) { this(node, state, format, meshes, textures, CacheBuilder.newBuilder() .maximumSize(128) @@ -720,16 +720,12 @@ public class B3DLoader implements ICustomModelLoader public BakedWrapper load(Integer frame) throws Exception { IModelState parent = state; - Animation newAnimation = null; + Animation newAnimation = node.getAnimation(); if(parent instanceof B3DState) { B3DState ps = (B3DState)parent; parent = ps.getParent(); } - if(newAnimation == null) - { - newAnimation = node.getAnimation(); - } return new BakedWrapper(node, new B3DState(newAnimation, frame, frame, 0, parent), format, meshes, textures); } })); From b5af11a89d5ea9eb53b257cd7dcaac43dda6a486 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Sat, 21 Nov 2015 07:45:56 +0300 Subject: [PATCH 09/11] Fix holes in generated item models. --- .../client/model/ItemLayerModel.java | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java index 89301016fa..8a0da4b4b8 100644 --- a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java +++ b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java @@ -215,31 +215,75 @@ public class ItemLayerModel implements IRetexturableModel { private static BakedQuad buildSideQuad(VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int u, int v) { + final float eps0 = 30e-5f; + final float eps1 = 45e-5f; + final float eps2 = .5f; + final float eps3 = .5f; float x0 = (float)u / sprite.getIconWidth(); float y0 = (float)v / sprite.getIconHeight(); float x1 = x0, y1 = y0; - float z1 = 7.5f / 16f, z2 = 8.5f / 16f; + float z1 = 7.5f / 16f - eps1, z2 = 8.5f / 16f + eps1; switch(side) { case WEST: - z1 = 8.5f / 16f; - z2 = 7.5f / 16f; + z1 = 8.5f / 16f + eps1; + z2 = 7.5f / 16f - eps1; case EAST: y1 = (v + 1f) / sprite.getIconHeight(); break; case DOWN: - z1 = 8.5f / 16f; - z2 = 7.5f / 16f; + z1 = 8.5f / 16f + eps1; + z2 = 7.5f / 16f - eps1; case UP: x1 = (u + 1f) / sprite.getIconWidth(); break; default: throw new IllegalArgumentException("can't handle z-oriented side"); } - float u0 = 16f * (x0 - side.getDirectionVec().getX() * 1e-2f / sprite.getIconWidth()); - float u1 = 16f * (x1 - side.getDirectionVec().getX() * 1e-2f / sprite.getIconWidth()); - float v0 = 16f * (1f - y0 - side.getDirectionVec().getY() * 1e-2f / sprite.getIconHeight()); - float v1 = 16f * (1f - y1 - side.getDirectionVec().getY() * 1e-2f / sprite.getIconHeight()); + float u0 = 16f * (x0 - side.getDirectionVec().getX() * eps3 / sprite.getIconWidth()); + float u1 = 16f * (x1 - side.getDirectionVec().getX() * eps3 / sprite.getIconWidth()); + float v0 = 16f * (1f - y0 - side.getDirectionVec().getY() * eps3 / sprite.getIconHeight()); + float v1 = 16f * (1f - y1 - side.getDirectionVec().getY() * eps3 / sprite.getIconHeight()); + switch(side) + { + case WEST: + case EAST: + y0 -= eps1; + y1 += eps1; + v0 -= eps2 / sprite.getIconHeight(); + v1 += eps2 / sprite.getIconHeight(); + break; + case DOWN: + case UP: + x0 -= eps1; + x1 += eps1; + u0 += eps2 / sprite.getIconWidth(); + u1 -= eps2 / sprite.getIconWidth(); + break; + default: + throw new IllegalArgumentException("can't handle z-oriented side"); + } + switch(side) + { + case WEST: + x0 += eps0; + x1 += eps0; + break; + case EAST: + x0 -= eps0; + x1 -= eps0; + break; + case DOWN: + y0 -= eps0; + y1 -= eps0; + break; + case UP: + y0 += eps0; + y1 += eps0; + break; + default: + throw new IllegalArgumentException("can't handle z-oriented side"); + } return buildQuad( format, transform, side.getOpposite(), tint, // getOpposite is related either to the swapping of V direction, or something else x0, y0, z1, sprite.getInterpolatedU(u0), sprite.getInterpolatedV(v0), From 0d06ea675884acd8fac11674a98ad17541b78f9f Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Sat, 21 Nov 2015 08:09:38 +0300 Subject: [PATCH 10/11] Removed face doubles from item models. --- .../client/model/ItemLayerModel.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java index 8a0da4b4b8..12d8638642 100644 --- a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java +++ b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java @@ -1,6 +1,7 @@ package net.minecraftforge.client.model; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.List; import java.util.Map; @@ -146,6 +147,7 @@ public class ItemLayerModel implements IRetexturableModel { int uMax = sprite.getIconWidth(); int vMax = sprite.getIconHeight(); + BitSet faces = new BitSet((uMax + 1) * (vMax + 1) * 4); for(int f = 0; f < sprite.getFrameCount(); f++) { int[] pixels = sprite.getFrameTextureData(f)[0]; @@ -160,26 +162,26 @@ public class ItemLayerModel implements IRetexturableModel { boolean t = isTransparent(pixels, uMax, vMax, u, v); if(ptu && !t) // left - transparent, right - opaque { - builder.add(buildSideQuad(format, transform, EnumFacing.WEST, tint, sprite, u, v)); + addSideQuad(builder, faces, format, transform, EnumFacing.WEST, tint, sprite, uMax, vMax, u, v); } if(!ptu && t) // left - opaque, right - transparent { - builder.add(buildSideQuad(format, transform, EnumFacing.EAST, tint, sprite, u, v)); + addSideQuad(builder, faces, format, transform, EnumFacing.EAST, tint, sprite, uMax, vMax, u, v); } if(ptv[u] && !t) // up - transparent, down - opaque { - builder.add(buildSideQuad(format, transform, EnumFacing.UP, tint, sprite, u, v)); + addSideQuad(builder, faces, format, transform, EnumFacing.UP, tint, sprite, uMax, vMax, u, v); } if(!ptv[u] && t) // up - opaque, down - transparent { - builder.add(buildSideQuad(format, transform, EnumFacing.DOWN, tint, sprite, u, v)); + addSideQuad(builder, faces, format, transform, EnumFacing.DOWN, tint, sprite, uMax, vMax, u, v); } ptu = t; ptv[u] = t; } if(!ptu) // last - opaque { - builder.add(buildSideQuad(format, transform, EnumFacing.EAST, tint, sprite, uMax, v)); + addSideQuad(builder, faces, format, transform, EnumFacing.EAST, tint, sprite, uMax, vMax, uMax, v); } } // last line @@ -187,7 +189,7 @@ public class ItemLayerModel implements IRetexturableModel { { if(!ptv[u]) { - builder.add(buildSideQuad(format, transform, EnumFacing.DOWN, tint, sprite, u, vMax)); + addSideQuad(builder, faces, format, transform, EnumFacing.DOWN, tint, sprite, uMax, vMax, u, vMax); } } } @@ -213,6 +215,18 @@ public class ItemLayerModel implements IRetexturableModel { return (pixels[u + (vMax - 1 - v) * uMax] >> 24 & 0xFF) == 0; } + private static void addSideQuad(ImmutableList.Builder builder, BitSet faces, VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int uMax, int vMax, int u, int v) + { + int si = side.ordinal(); + if(si > 4) si -= 2; + int index = (vMax + 1) * ((uMax + 1) * si + u) + v; + if(!faces.get(index)) + { + faces.set(index); + builder.add(buildSideQuad(format, transform, side, tint, sprite, u, v)); + } + } + private static BakedQuad buildSideQuad(VertexFormat format, TRSRTransformation transform, EnumFacing side, int tint, TextureAtlasSprite sprite, int u, int v) { final float eps0 = 30e-5f; From 11d237f5f2817bf08acee1271406763cba256304 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Sun, 22 Nov 2015 02:10:30 +0300 Subject: [PATCH 11/11] Fixed forge lighting working incorrectly outside 0x1000000 coordinates. --- .../model/pipeline/ForgeBlockModelRenderer.java | 13 +++++++++++-- .../client/model/pipeline/VertexLighterFlat.java | 7 ++++--- .../model/pipeline/WorldRendererConsumer.java | 9 ++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer.java b/src/main/java/net/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer.java index 7c8e638933..f7c7cf1965 100644 --- a/src/main/java/net/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer.java +++ b/src/main/java/net/minecraftforge/client/model/pipeline/ForgeBlockModelRenderer.java @@ -22,6 +22,7 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer return new VertexLighterFlat(); } }; + private final ThreadLocal lighterSmooth = new ThreadLocal() { @Override @@ -31,6 +32,8 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer } }; + private final ThreadLocal wrFlat = new ThreadLocal(); + private final ThreadLocal wrSmooth = new ThreadLocal(); private final ThreadLocal lastRendererFlat = new ThreadLocal(); private final ThreadLocal lastRendererSmooth = new ThreadLocal(); @@ -42,8 +45,11 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer if(wr != lastRendererFlat.get()) { lastRendererFlat.set(wr); - lighterFlat.get().setParent(new WorldRendererConsumer(wr)); + WorldRendererConsumer newCons = new WorldRendererConsumer(wr); + wrFlat.set(newCons); + lighterFlat.get().setParent(newCons); } + wrFlat.get().setOffset(pos); return render(lighterFlat.get(), world, model, block, pos, wr, checkSides); } else @@ -60,8 +66,11 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer if(wr != lastRendererSmooth.get()) { lastRendererSmooth.set(wr); - lighterSmooth.get().setParent(new WorldRendererConsumer(wr)); + WorldRendererConsumer newCons = new WorldRendererConsumer(wr); + wrSmooth.set(newCons); + lighterSmooth.get().setParent(newCons); } + wrSmooth.get().setOffset(pos); return render(lighterSmooth.get(), world, model, block, pos, wr, checkSides); } else diff --git a/src/main/java/net/minecraftforge/client/model/pipeline/VertexLighterFlat.java b/src/main/java/net/minecraftforge/client/model/pipeline/VertexLighterFlat.java index 039c3eb31f..6ded96597c 100644 --- a/src/main/java/net/minecraftforge/client/model/pipeline/VertexLighterFlat.java +++ b/src/main/java/net/minecraftforge/client/model/pipeline/VertexLighterFlat.java @@ -144,12 +144,13 @@ public class VertexLighterFlat extends QuadGatheringTransformer switch(parent.getVertexFormat().getElement(e).getUsage()) { case POSITION: - float[] pos = new float[4]; + // position adding moved to WorldRendererConsumer due to x and z not fitting completely into a float + /*float[] pos = new float[4]; System.arraycopy(position[v], 0, pos, 0, position[v].length); pos[0] += blockInfo.getBlockPos().getX(); pos[1] += blockInfo.getBlockPos().getY(); - pos[2] += blockInfo.getBlockPos().getZ(); - parent.put(e, pos); + pos[2] += blockInfo.getBlockPos().getZ();*/ + parent.put(e, position[v]); break; case NORMAL: if(normalIndex != -1) { diff --git a/src/main/java/net/minecraftforge/client/model/pipeline/WorldRendererConsumer.java b/src/main/java/net/minecraftforge/client/model/pipeline/WorldRendererConsumer.java index 2e9ee09aa2..fea7dff227 100644 --- a/src/main/java/net/minecraftforge/client/model/pipeline/WorldRendererConsumer.java +++ b/src/main/java/net/minecraftforge/client/model/pipeline/WorldRendererConsumer.java @@ -4,6 +4,7 @@ import java.util.Arrays; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; /** @@ -14,6 +15,7 @@ public class WorldRendererConsumer implements IVertexConsumer private final WorldRenderer renderer; private final int[] quadData; private int v = 0; + private BlockPos offset = BlockPos.ORIGIN; public WorldRendererConsumer(WorldRenderer renderer) { @@ -36,13 +38,18 @@ public class WorldRendererConsumer implements IVertexConsumer if(v == 4) { renderer.addVertexData(quadData); - renderer.putPosition(0, 0, 0); + renderer.putPosition(offset.getX(), offset.getY(), offset.getZ()); Arrays.fill(quadData, 0); v = 0; } } } + public void setOffset(BlockPos offset) + { + this.offset = new BlockPos(offset); + } + public void setQuadTint(int tint) {} public void setQuadOrientation(EnumFacing orientation) {} public void setQuadColored() {}