Jump to content

[1.14.2] TileEntity rendering + data syncing (+ TileEntity tick function every other tick)


Recommended Posts

Posted

Hi

 

I got my TileEntity working good now, now I want to add a type of render to it, and looking through the wiki the optimal way of doing it would be to use a TileEntityRendererFast. I would not say my TileEntity would be hard to render as it would only have to render a cuboid with varying alpha and texture depending on the TileEntity variables.

The issue I'm facing is that I have no idea how to do that, and better yet how to send the data to the client efficiently. I have it do stuff every tick, which is only changing one variable out of the three variables it stores, so I'm pretty sure using a custom message protocol is needed. The other two is what texture to use and whenever it should do a particle effect at the block (same texture). But I'm a bit lost about all this, going to write a summary and what little code I have on the TileEntityRendererFast and the actul TileEntity below:

 

A Tree Tap you place on a tree, I got the bucket and actual Tree Tap model working fine. The TileEntity stores what type of liquid it is (resin, water or none), whenever it can make the "bucket" start filling up with a particle effect and what volume there is in the bucket.

Something I was wondering is if there is a way to have a if statement that would only pass like every other tick or less, to simulate viscosity of different fluids and have the "drip" animation only happen that tick or something. That would also free up some of the network if I only need to send new information that particular tick.

 

2019-08-10_20_06_06_2.png.6f6fb37711f747f0939b7eb04939938d.png

 

 

TreeTapTileEntityRenderer.java

Spoiler

public class TreeTapTileEntityRenderer extends TileEntityRendererFast<TreeTapTileEntity>
{


    @Override
    public void renderTileEntityFast(TreeTapTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer)
    {


    }
}

 

 

 

TreeTapTileEntity.java

Spoiler

public class TreeTapTileEntity extends TileEntity implements ITickableTileEntity
{

    private int volume = 0;
    private boolean canFill = false;
    private FluidType fluidType = FluidType.NONE;

    public TreeTapTileEntity()
    {
        super(IntercraftTileEntities.TREETAP);
    }


    @Override
    public void tick()
    {
        if (canFill) {
            if (volume < 1000) {
                setVolume(volume+1);

                


            }
        }
    }


    @Override
    public CompoundNBT write(CompoundNBT compound)
    {
        compound.putInt("volume", volume);
        compound.putBoolean("can_fill",canFill);
        compound.putString("fluid_type",fluidType.toString());

        return super.write(compound);
    }

    @Override
    public void read(CompoundNBT compound)
    {
        super.read(compound);
        volume = compound.getInt("volume");
        canFill = compound.getBoolean("can_fill");
        fluidType = FluidType.valueOf(compound.getString("fluid_type").toUpperCase());

    }


    public int getVolume()
    {
        return volume;
    }

    public boolean getCanFill()
    {
        return canFill;
    }

    public FluidType getFluidType()
    {
        return this.fluidType;
    }

    public void setVolume(int value)
    {
        volume = value;
        markDirty();
    }

    public void setCanFill(boolean bool)
    {
        canFill = bool;
        markDirty();
    }

    public void setFluidType(FluidType type)
    {
        fluidType = type;
        markDirty();
    }
}

 

 

 

  • Like 1
Posted
7 hours ago, Simon_kungen said:

if there is a way to have a if statement that would only pass like every other tick

World#getTotalWorldTime (or something similar; can’t remember the spelling) returns the current world time. Modulo the total world time by 2 (or more if you would like the delay between triggers to be longer) and check if the result is equal to 0.

 

Use packets to send data from server to client.

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Posted
11 hours ago, DavidM said:

World#getTotalWorldTime (or something similar; can’t remember the spelling) returns the current world time. Modulo the total world time by 2 (or more if you would like the delay between triggers to be longer) and check if the result is equal to 0.

 

Use packets to send data from server to client.

Alright, that worked pretty well. I added this to my TileEntity;

Spoiler

@Override
public CompoundNBT getUpdateTag()
{
    CompoundNBT compound = super.getUpdateTag();
    compound.putInt("volume", volume);
    compound.putBoolean("can_fill",canFill);
    compound.putString("fluid_type",fluidType.getName());
    return compound;
}

@Override
public void handleUpdateTag(CompoundNBT compound)
{
    volume = compound.getInt("volume");
    canFill = compound.getBoolean("can_fill");
    fluidType = FluidType.valueOf(compound.getString("fluid_type").toUpperCase());
    super.handleUpdateTag(compound);
}

 

 

but when I tried to add a block update mechanic to it it wouldn't update:

Spoiler

@Override
public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt)
{
    CompoundNBT compound = pkt.getNbtCompound();
    volume = compound.getInt("volume");
    canFill = compound.getBoolean("can_fill");
    fluidType = FluidType.valueOf(compound.getString("fluid_type").toUpperCase());
    world.notifyBlockUpdate(pos,world.getBlockState(pos),world.getBlockState(pos),2);
}

@Nullable
@Override
public SUpdateTileEntityPacket getUpdatePacket()
{
    CompoundNBT compound = super.getUpdateTag();
    compound.putInt("volume", volume);
    compound.putBoolean("can_fill",canFill);
    compound.putString("fluid_type",fluidType.getName());

    return new SUpdateTileEntityPacket(pos, 1, compound);
}

 

 

 

I would like to add my own packet message to only send the data needed for that particular moment, but for now, a quick and dirty method would probably suffice for the time being.

 

Something I do wonder more is how I'm supposed to do the TileEntityRendererFast.

I registered this to the client, but the problem is that I have no idea how to work with this.

@Override
public void renderTileEntityFast(TreeTapTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer)
{
    // *Confusion sound*

    //buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);



}

 

A 3D cuboid with varying texture and height and of course what axis it should align to (in my blockstate). I tried to search for some example online how to work with this, but none of the uses was sufficient to me.

https://github.com/search?l=&q=TileEntityRendererFast+language%3AJava&type=Code

Posted

If anyone could tell me what I'm doing wrong, I would gladly accept any answer:

@Override
public void renderTileEntityFast(TreeTapTileEntity te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer)
{
    // *Confusion sound*


    BlockPos pos = te.getPos();

    net.minecraft.world.IEnviromentBlockReader world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
    BlockState state = world.getBlockState(pos);


    if (state.get(BlockProperties.BUCKET) != BucketType.NONE) {
        buffer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());


        buffer.pos(1,1,1).color(1,1,1,1);


    }


}

 

Here I don't really expect much except for absolutely anything to happen.

Posted

Alright, I got some help getting something to render, but as they said you have to keep in mind what direction it is supposed to render it from, which I have no idea how to do.

buffer.pos(0,0,0).color(0,0,1,1).endVertex();
buffer.pos(4,0,0).color(0,0,1,1).endVertex();
buffer.pos(0,0,4).color(0,0,1,1).endVertex();
buffer.pos(4,0,4).color(0,0,1,1).endVertex();

 

Something I realized was that the fluid level is only going to be seen from the top, which would mean I only need to render a single side (top) and then change the y value to represent the fluid level.

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.