Jump to content

[Solved] [1.15.2] Rendering fixed lines between tile entities


profjb58

Recommended Posts

I'm wondering how I can render fixed lines between tile entities in a simular way to buildcraft markers or immersive engineering wires.

The actual rendering and render types i've figured out and I have it rendering from a single tile to a player mostly using mcjtys tutorial https://wiki.mcjty.eu/modding/index.php?title=Tut15_Ep15 for tile entity rendering.

the issue is that I essentially have a kind of linked list of a bunch of points that are all linked together using real world positions but to draw this on the clientside relative to the player seems incredibly difficult since the only event I can think of
is the client tick events and then I don't know how I would grab the matrix stack equivalent positions relative to the player from the actual positions within the world. I'm not sure if thats even possible.

 

The vast majority of the code is essentially very simular to mcjtys tutorial code with a few very minor edits so for a better reference: https://wiki.mcjty.eu/modding/index.php?title=Tut15_Ep15 for tile entity rendering.


Tile > player method (currently works)

static void drawTileToPlayer(TileEntity tile, ClientPlayerEntity player, MatrixStack matrixStack){
        IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
        IVertexBuilder lineBuilder = buffer.getBuffer(CustomRenderTypes.THICK_LINES);

        BlockPos playerPos = player.getPosition();
        BlockPos tilePos = tile.getPos();
        int px = playerPos.getX();
        int py = playerPos.getY();
        int pz = playerPos.getZ();

        float[] lineColour = getLineColour(tile.getBlockState().getBlock());
        drawLine(lineBuilder, generateProjectedMatrix(matrixStack),tilePos.getX() + 0.5f,tilePos.getY() + 0.6f,tilePos.getZ() + 0.5f, px + 0.5f, py + 0.5f, pz + 0.5f, lineColour);

        matrixStack.pop();
        buffer.finish(CustomRenderTypes.THICK_LINES);
    }

This draws a line from the tile to the player position using a matrix stack from the renderworldlastevent event.

Generate projected matrix

private static Matrix4f generateProjectedMatrix(MatrixStack matrixStack){
        //  Begin pushing to the matrix stack.
        matrixStack.push();

        //  Get actual position of player and translate back to the actual location. E.g. blockpos is discrete integers. projected view isn't.
        Vec3d projectedView = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView();
        matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);

        return matrixStack.getLast().getMatrix();
    }

 

Drawline method

private static void drawLine(IVertexBuilder builder, Matrix4f posMatrix, float x1, float y1, float z1, float x2, float y2, float z2, float[] colour){
        builder.pos(posMatrix, x1, y1, z1)
                .color(colour[0], colour[1], colour[2], colour[3])
                .endVertex();
        builder.pos(posMatrix, x2, y2, z2)
                .color(colour[0], colour[1], colour[2], colour[3])
                .endVertex();
    }


I did think of using blocks simular to string that would generate between the marker points as they are placed but unlike buildcraft i'm fixing where you can place the markers in the X & Z planes but not in the Y plane so that wont work.
 

Edited by profjb58
Link to comment
Share on other sites

So i've managed to get it working (partially). I've attached an image of it.
Essentially it kinda works. It renders properly but say if another render event happens during when I place the markers down, this line gets broken. It also produces a random pattern when logging back in and out. This is acctually kinda cool and i'm guessing is because the render world last event is essentially pretty much random.

 

static void drawTileToTile(TileEntity tileStart, TileEntity tileEnd, ClientPlayerEntity player, MatrixStack matrixStack){
        IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
        IVertexBuilder lineBuilder = buffer.getBuffer(CustomRenderTypes.THICK_LINES);
        
        BlockPos tileStartPos = tileStart.getPos();
        BlockPos tileEndPos = tileEnd.getPos();

        float[] lineColour = getLineColour(tileStart.getBlockState().getBlock());
        drawLine(lineBuilder, generateProjectedMatrix(matrixStack),tileStartPos.getX() + 0.5f,tileStartPos.getY() + 0.6f,tileStartPos.getZ() + 0.5f,
                tileEndPos.getX() + 0.5f, tileEndPos.getY() + 0.5f, tileEndPos.getZ() + 0.5f, lineColour);

        matrixStack.pop();
        buffer.finish(CustomRenderTypes.THICK_LINES);
    }

Modified code for drawing between tiles. I included

2020-07-06_23.57.25.jpg

2020-07-07_00.02.07.jpg

Link to comment
Share on other sites

Howdy

I would suggest that you should use the TER to render your lines.

Since your TileEntity stores the position of the next marker, just draw a line to the next position (relative to the position of the TE being drawn, of course).  Very simple, very scaleable.  renderworldlastevent should be a last resort I think.

The only likely issue is that lines will disappear when the TE is unloaded (goes out of chunk range), which may become very noticeable if the markers are far apart from each other, i.e. you are close to one of the markers when the next marker goes off the edge of the chunk limit.

 

You could probably work around this by drawing to both the previous and the next markers; if necessary keeping track of which lines have already been drawn during that frame so that you don't draw the same line twice.

 

-TGG

 

 

  • Thanks 1
Link to comment
Share on other sites

I had a quick go last night thinking that might be the best approach. I'm almost certain it's the only approach that would be scaleable now.
The idea of drawing 2 lines from either marker so either one is unlikely to stop rendering upon unloading a chunk is a brilliant idea, thank you. Since I have previous and next positions that is entirely possible for every marker as well.

The only problems i'm having now is the ability to update the rendering based upon the information of the connected tile entities (markers) updating. E.g. one being removed or added. I have the correct methods overrided and sending data, e.g. onDataPacket, getUpdatePacket. I think I might be missing something here. I'll send the code for it.
There is also a weird effect whereby once the player stops looking at the tile the connecting tiles lines dissapear. Thinking about it though drawing 2 lines between the markers would fix this I think.


gist link: https://gist.github.com/profjb58/3b7960e437386228c3f472bd05e49764
(A lot of code, didn't want to spam this thread)


I think i'm limiting the amount of data I sync to the client from what I can tell to only include

  • 'connectedFacing > direction the marker is pointing'
  • 'isTail' > is this marker the tail of the list.
  • prevMarker & nextMarker' *

* The only variables required for the TER. everything else used for drawing a line from the tail (end marker) to the player.


p.s. the gist code is a bit of a mess. It works but i'm sure there is a better way of laying it out.
 

Edited by profjb58
pastebin sucks
Link to comment
Share on other sites

  • 2 weeks later...

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
    • It is an issue with quark - update it to this build: https://www.curseforge.com/minecraft/mc-mods/quark/files/3642325
    • Remove Instant Massive Structures Mod from your server     Add new crash-reports with sites like https://paste.ee/  
  • Topics

×
×
  • Create New...

Important Information

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