Jump to content

[1.16.4] IVertexBuffer color method issue


midomidori

Recommended Posts

Hello! I've been trying to make a block in Forge that stores a simple liquid, and a renderer that would show that liquid in the block itself.
I have been attempting to get the renderer to work with only water at first, since it's probably easier to get a simple case to work instead of trying to implement everything at once when you don't fully understand Forge itself.
Unfortunately the texture seems to be completely black, and when I try to adjust the buffer's color function, it seems like it doesn't change anything. (alpha on 255 still keeps the texture that is rendered semi-transparent, however alpha being 0 does make the texture invisible)
Any ideas on what to do from here? I copied a lot of code from Eidolon (https://github.com/elucent/eidolon/blob/master/), most specifically the Crucible tile entity & renderer for this part, and the Crucible seems to work fine with this code. (I have not attempted compiling his mod manually yet however)


Here are my bits of code:

InfuserBlockRenderer class:

package com.midori.liquimancy.common.tile;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.WaterFluid;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ColorHelper.PackedColor;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.biome.BiomeColors;

public class InfuserBlockRenderer extends TileEntityRenderer<InfuserTileEntity> {
    public InfuserBlockRenderer(TileEntityRendererDispatcher rendererDispatcherIn) {
        super(rendererDispatcherIn);
    }

    @Override
    public void render(InfuserTileEntity tileEntityIn, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn) {
        Minecraft mc = Minecraft.getInstance();
        if (tileEntityIn.containsFluid()) {
            TextureAtlasSprite water = mc.getAtlasSpriteGetter(AtlasTexture.LOCATION_BLOCKS_TEXTURE)
                    .apply(new ResourceLocation("minecraft", "block/water_still"));

            IVertexBuilder builder = bufferIn.getBuffer(RenderType.getTranslucentNoCrumbling());
            Matrix4f mat = matrixStackIn.getLast().getMatrix();
            int color = BiomeColors.getWaterColor(tileEntityIn.getWorld(), tileEntityIn.getPos());
            int r = PackedColor.getRed(color), g = PackedColor.getGreen(color),
                    b = PackedColor.getBlue(color), a = PackedColor.getAlpha(color);
            System.out.println("colors: " + r + ", "+ g + ", "+ b + ", " + a);

            builder.pos(mat, 0.125f, 0.75f, 0.125f).color(r, g, b, 192).tex(water.getInterpolatedU(2), water.getInterpolatedV(2)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex();
            builder.pos(mat, 0.125f, 0.75f, 0.875f).color(r, g, b, 192).tex(water.getInterpolatedU(14), water.getInterpolatedV(2)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex();
            builder.pos(mat, 0.875f, 0.75f, 0.875f).color(r, g, b, 192).tex(water.getInterpolatedU(14), water.getInterpolatedV(14)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex();
            builder.pos(mat, 0.875f, 0.75f, 0.125f).color(r, g, b, 192).tex(water.getInterpolatedU(2), water.getInterpolatedV(14)).lightmap(combinedLightIn).normal(0, 1, 0).endVertex();

        }
    }
}

 

InfuserTileEntity class:

package com.midori.liquimancy.common.tile;

import com.midori.liquimancy.Registry;
import com.midori.liquimancy.network.PacketHandler;
import com.midori.liquimancy.network.SyncPacket;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraftforge.fml.network.PacketDistributor;

import java.util.HashMap;

public class InfuserTileEntity extends TileEntity implements ITickableTileEntity {
    Fluid contains;
    //TODO: change the location of this dictionary and make it public
    //TODO: make this dictionary generate on mod load
    HashMap<String, ResourceLocation> fluidMap = new HashMap<>();

    public InfuserTileEntity() {
        this(Registry.INFUSER_TILE_ENTITY);
    }

    public InfuserTileEntity(TileEntityType<?> tileEntityTypeIn) {
        super(tileEntityTypeIn);
        fluidMap.put("water", new ResourceLocation("minecraft", "block/water_still"));
        fluidMap.put("lava", new ResourceLocation("minecraft", "block/lava_still"));
    }

    public void sync() {
        markDirty();
        if (world.isRemote)
            PacketHandler.INSTANCE.sendToServer(new SyncPacket(pos, write(new CompoundNBT())));
        else
            PacketHandler.INSTANCE.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), new SyncPacket(pos, write(new CompoundNBT())));
    }


    public boolean containsFluid() {
        return contains != null;
    }

    public Fluid getFluid() {
        return contains;
    }

    public ResourceLocation getResource(String type) {
        return null;
    }

    public ActionResultType onActivation(PlayerEntity player, Hand handIn, BlockRayTraceResult resultIn) {
        if (player.getHeldItem(handIn).getItem() == Items.WATER_BUCKET)
        {
            contains = Fluids.WATER;
            player.setHeldItem(handIn, new ItemStack(Items.BUCKET, 1));
            if(!world.isRemote) {
                sync();
            }
            return ActionResultType.SUCCESS;
        }
        else if (player.getHeldItem(handIn).getItem() == Items.LAVA_BUCKET)
        {
            contains = Fluids.LAVA;
            player.setHeldItem(handIn, new ItemStack(Items.BUCKET, 1));
            if(!world.isRemote) {
                sync();
            }
            return ActionResultType.SUCCESS;
        }
        return ActionResultType.PASS;
    }

    @Override
    public void tick() {

    }

}

 

InfuserBlock class:

package com.midori.liquimancy.common.block;

import com.midori.liquimancy.common.tile.InfuserTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;

public class InfuserBlock extends Block {
    TileEntityType<InfuserTileEntity> type;

    public InfuserBlock(Properties properties) {
        super(properties);
    }

    public void setTileEntityType(TileEntityType<InfuserTileEntity> type) {
        this.type = type;
    }

    public TileEntityType<InfuserTileEntity> getTileEntityType() {
        return type;
    }

    @Override
    public TileEntity createTileEntity(BlockState state, IBlockReader world) {
        return type.create();
    }

    @Override
    public boolean hasTileEntity(BlockState state) {
        return true;
    }

    @Override
    public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult resultIn) {
        if (hasTileEntity(state)) {
            TileEntity te = worldIn.getTileEntity(pos);
            return ((InfuserTileEntity) worldIn.getTileEntity(pos)).onActivation(player, handIn, resultIn);
        }
        return super.onBlockActivated(state, worldIn, pos, player, handIn, resultIn);
    }
}


I bind my tile entity and renderer together like this in my mod class

	@OnlyIn(Dist.CLIENT)
    private void doClientStuff(final FMLClientSetupEvent event) {
        ClientRegistry.bindTileEntityRenderer(Registry.INFUSER_TILE_ENTITY, (trd) -> new InfuserBlockRenderer(trd));
    }

:

And finally, I register my tile entity like this in the Registry class I have:

//TODO: make work for any tile entity
    static <T extends TileEntity> TileEntityType<T> addTileEntity(IForgeRegistry<TileEntityType<?>> registry, String name, Supplier<T> factory, InfuserBlock... blocks) {
        TileEntityType<T> type = TileEntityType.Builder.<T>create(factory, blocks).build(null);
        System.out.println("fired registery for " + name);
        type.setRegistryName("liquimancy", name);
        registry.register(type);
        for (InfuserBlock block : blocks) block.setTileEntityType((TileEntityType<InfuserTileEntity>) type);
        return type;
    }
      
    public static TileEntityType<InfuserTileEntity> INFUSER_TILE_ENTITY;

    @SubscribeEvent
    public void registerTiles(RegistryEvent.Register<TileEntityType<?>> evt) {
        INFUSER_TILE_ENTITY = addTileEntity(evt.getRegistry(), "infuser_tile", InfuserTileEntity::new, (InfuserBlock)INFUSER_BLOCK.get());
    }

 

Example of my weird rendering (please ignore the not correct sizedness of the texture (which I reverted back to see if it changed anything), and the weird placeholder texture (which in retrospect looks a lot like a diglett :o))

Note how it is black compared to the blue water next to it. Meanwhile the console is giving me this output:

[21:19:24] [Render thread/INFO] [STDOUT/]: [com.midori.liquimancy.common.tile.InfuserBlockRenderer:render:37]: colors: 63, 118, 228, 0

:afbeelding.png.dbdb7ee375ee9f91948cd7f10341c306.png

 

If there is a class or function I should give with this for easier or further identification of this issue, please let me know!

 

Link to comment
Share on other sites

Not sure where your problem is at, but the render code is good. I hacked it in 1.16.4 example mod and didn't change a thing in the render class and used a brick slab model for the infuser block and I got this

 

2021-02-04_12.30.12.png

Edited by lupicus
Link to comment
Share on other sites

5 hours ago, lupicus said:

Not sure where your problem is at, but the render code is good. I hacked it in 1.16.4 example mod and didn't change a thing in the render class and used a brick slab model for the infuser block and I got this

 

2021-02-04_12.30.12.png

That's extra weird!!! I just tried editing the model and it still pops up as black...
But it's nice to know that the render code is good. I changed the model aswel just to see and the issue doesn't seem to be there either. I just wonder where it's messing up now...
Thank you for showing me this though!! It's greatly appreciated ^^


EDIT: on second thought, can you show me exactly how you added the renderer to the tile entity?? I'm so confused as to why this just works for you but not for me...

Edited by midomidori
Link to comment
Share on other sites

I just inserted your line into example mod doClientStuff:

    private void doClientStuff(final FMLClientSetupEvent event) {
        // do something that can only be done on the client
        LOGGER.info("Got game settings {}", event.getMinecraftSupplier().get().gameSettings);
        ClientRegistry.bindTileEntityRenderer(ModTileEntities.INFUSER_BLOCK, (trd) -> new InfuserBlockRenderer(trd));
    }

Here is my dummy block and tile entity (nothing really special going on here):

public class InfuserBlock extends Block
{
	public InfuserBlock(Properties properties) {
		super(properties);
	}

	@Override
	public boolean hasTileEntity(BlockState state) {
		return true;
	}

	@Override
	public TileEntity createTileEntity(BlockState state, IBlockReader world) {
		return new InfuserTileEntity();
	}
}
public class InfuserTileEntity extends TileEntity
{
	public InfuserTileEntity() {
		super(ModTileEntities.INFUSER_BLOCK);
	}

	public boolean containsFluid() {
		return true;
	}
}

I played with my version and found that if I remove the notSolid() property when I create the InfuserBlock then it looks black. If you change your properties then you might need to place a new one down.

Edited by lupicus
Link to comment
Share on other sites

5 hours ago, lupicus said:

I just inserted your line into example mod doClientStuff:


    private void doClientStuff(final FMLClientSetupEvent event) {
        // do something that can only be done on the client
        LOGGER.info("Got game settings {}", event.getMinecraftSupplier().get().gameSettings);
        ClientRegistry.bindTileEntityRenderer(ModTileEntities.INFUSER_BLOCK, (trd) -> new InfuserBlockRenderer(trd));
    }

Here is my dummy block and tile entity (nothing really special going on here):


public class InfuserBlock extends Block
{
	public InfuserBlock(Properties properties) {
		super(properties);
	}

	@Override
	public boolean hasTileEntity(BlockState state) {
		return true;
	}

	@Override
	public TileEntity createTileEntity(BlockState state, IBlockReader world) {
		return new InfuserTileEntity();
	}
}

public class InfuserTileEntity extends TileEntity
{
	public InfuserTileEntity() {
		super(ModTileEntities.INFUSER_BLOCK);
	}

	public boolean containsFluid() {
		return true;
	}
}

I played with my version and found that if I remove the notSolid() property when I create the InfuserBlock then it looks black. If you change your properties then you might need to place a new one down.

THANK YOU the notSolid property was the culprit!! I did not have it but now it renders perfectly!!! You're a life saver!!!!

Link to comment
Share on other sites

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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