Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

[1.10.2] Play texture animation on multiple blocks independent from each other

Featured Replies

Posted

I have a block that can be activated by right clicking an item bound to the block. Once the block is activated, it should play an animated texture and then explode. The length of the animation is equal to the length of a timer in the block's tile entity. The problem is that multiple blocks activated at different points in time play the exact same texture frames at the same time and the animation starts at a random frame because the TextureAtlasSprite of the animation is ticked in the background all the time. Is there a way to get the animation to start on activation of the block and to get the animation to be independent between multiple blocks without using a TESR or swapping the block model every tick? If needed, I will provide the model, the block class and the tile entity class when I am back at my computer.

Ok, is there an easy way to use an animated TextureAtlasSprite to render that animation in a TESR or would I need to load all 106 frames of that animation as separate textures and draw them?

Ok, thanks, I'll try that ASAP.

  • 2 weeks later...

I finally found time to try this.

This is the code I tried:

package XFactHD.rssmc.client.renderer.tesr;

import XFactHD.rssmc.common.blocks.gadget.BlockThermiteCharge;
import XFactHD.rssmc.common.blocks.gadget.TileEntityThermiteCharge;
import XFactHD.rssmc.common.utils.helper.LogHelper;
import XFactHD.rssmc.common.utils.helper.PropertyHolder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL11;

public class TESRThermiteCharge extends TileEntitySpecialRenderer<TileEntityThermiteCharge>
{
    @Override
    public void renderTileEntityAt(TileEntityThermiteCharge te, double x, double y, double z, float partialTicks, int destroyStage)
    {
        if (te.hasWorldObj() && te.getWorld().getBlockState(te.getPos()).getBlock() instanceof BlockThermiteCharge && te.isActive())
        {
            GlStateManager.pushMatrix();

            BlockPos pos = te.getPos();
            //LogHelper.info("X=" + x + ", Y=" + y + ", Z=" + z + " | PosX=" + pos.getX() + ", PosY=" + pos.getY() + ", PosZ=" + pos.getZ());

            EnumFacing facing = te.getWorld().getBlockState(te.getPos()).getValue(PropertyHolder.FACING_NOT_UP);
            double posX = pos.getX() + (facing == EnumFacing.EAST ? -(1F / 16F) : facing == EnumFacing.WEST ? 1F / 16F : 0);
            double posY = pos.getY() + (facing == EnumFacing.DOWN ? 1F / 16F : 0);
            double posZ = pos.getZ() + (facing == EnumFacing.NORTH ? -(1F / 16F) : facing == EnumFacing.SOUTH ? 1F / 16F : 0);

            int index = 105 - te.getTime();
            TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("rssmc:blocks/block_thermite_charge_burning/block_thermite_charge_burning_" + index);

            OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);

            Tessellator tess = Tessellator.getInstance();
            VertexBuffer buffer = tess.getBuffer();
            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
            buffer.pos(posX, posY, posZ).tex(sprite.getInterpolatedU(16), sprite.getInterpolatedV(16)).endVertex();
            buffer.pos(posX, posY, posZ).tex(sprite.getInterpolatedU(16), sprite.getInterpolatedV( 0)).endVertex();
            buffer.pos(posX, posY, posZ).tex(sprite.getInterpolatedU( 0), sprite.getInterpolatedV( 0)).endVertex();
            buffer.pos(posX, posY, posZ).tex(sprite.getInterpolatedU( 0), sprite.getInterpolatedV(16)).endVertex();
            tess.draw();

            GlStateManager.popMatrix();
        }
    }
}

As far as I can see, it doesn't render. The currently commented LogHelper call indicates that the renderer is called and the code inside the if statement is active when it is needed. The textures do also exist and are loaded in the TextureStitchEvent.Pre event.

Why can I not use TASs when I use 105 independent textures as seen in this line:

TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("rssmc:blocks/block_thermite_charge_burning/block_thermite_charge_burning_" + index);

 

After adding

bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);

it still does not render.

 

This code is from another one of my mods and it works flawlessly while doing almost the same thing:

package XFactHD.advtech.client.render;

import XFactHD.advtech.client.utils.ClientUtils;
import XFactHD.advtech.common.blocks.storage.TileEntityFluidTank;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.opengl.GL11;

public class RenderTileFluidTank extends TileEntitySpecialRenderer<TileEntityFluidTank>
{
    @Override
    public void renderTileEntityAt(TileEntityFluidTank te, double x, double y, double z, float partialTicks, int destroyStage)
    {
        GlStateManager.pushMatrix();
        int capacity = te.getFluidHandler().getCapacity();
        FluidStack fluid = te.getFluidHandler().getFluid();
        if (fluid != null)
        {
            Tessellator tess = Tessellator.getInstance();
            VertexBuffer buffer = tess.getBuffer();

            buffer.setTranslation(x, y, z);

            bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
            TextureAtlasSprite still = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(fluid.getFluid().getStill().toString());
            TextureAtlasSprite flow =  Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(fluid.getFluid().getFlowing().toString());

            double posY = .1 + (.8 * ((float) fluid.amount / (float) capacity));
            double topV = 15 - (14 * (.8 * ((float) fluid.amount / (float) capacity)));
            float[] color = ClientUtils.getRGBAFloatArrayFromHexColor(fluid.getFluid().getColor(fluid));

            RenderHelper.disableStandardItemLighting();

            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos( 4F/16F, posY, 12F/16F).tex(still.getInterpolatedU( 4), still.getInterpolatedV( 4)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F, posY, 12F/16F).tex(still.getInterpolatedU(12), still.getInterpolatedV( 4)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F, posY,  4F/16F).tex(still.getInterpolatedU(12), still.getInterpolatedV(12)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos( 4F/16F, posY,  4F/16F).tex(still.getInterpolatedU( 4), still.getInterpolatedV(12)).color(color[0], color[1], color[2], color[3]).endVertex();
            tess.draw();

            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos(12F/16F, 1/16F, 12F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F,  posY, 12F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos( 4F/16F,  posY, 12F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos( 4F/16F, 1/16F, 12F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            tess.draw();

            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos( 4F/16F, 1/16F, 4F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos( 4F/16F,  posY, 4F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F,  posY, 4F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F, 1/16F, 4F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            tess.draw();

            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos(12F/16F, 1/16F,  4F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F,  posY,  4F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F,  posY, 12F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(12F/16F, 1/16F, 12F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            tess.draw();

            buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
            buffer.pos(4F/16F, 1/16F, 12F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(4F/16F,  posY, 12F/16F).tex(flow.getInterpolatedU(12), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(4F/16F,  posY,  4F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(topV)).color(color[0], color[1], color[2], color[3]).endVertex();
            buffer.pos(4F/16F, 1/16F,  4F/16F).tex(flow.getInterpolatedU( 4), flow.getInterpolatedV(  15)).color(color[0], color[1], color[2], color[3]).endVertex();
            tess.draw();

            RenderHelper.enableStandardItemLighting();

            buffer.setTranslation(0, 0, 0);
        }
        GlStateManager.popMatrix();
    }
}

 

Edited by XFactHD

The animation has 105 stages/frames.

I got it to work now. For some reason using the coordinates given by renderTileEntityAt in VertexBuffer#pos() doesn't do the same thing as using them in VertexBuffer#setTranslation and only putting small offsets into VertexBuffer#pos().

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.