Chisel

Chisel

150M Downloads

[Info request] Using chisel blocks as camouflage for other blocks

desht opened this issue ยท 6 comments

commented

Not really a problem report, more a request for information and advice...

My mod (Modular Routers) has a "camouflage upgrade" item, which when inserted allows my router blocks to render as another block - the camouflage upgrade can store the blockstate of other blocks by shift-right-clicking them, and storing their blockstate in its NBT. You can see the code to do that here: https://github.com/desht/ModularRouters/blob/master/src/main/java/me/desht/modularrouters/client/RouterModel.java (basically, if a router has a camouflage upgrade installed, return the IBakedModel for the blockstate stored by the upgrade instead of the router's own model).

Now this works great for most blocks, but not Chisel blocks... I've verified through debugging that the stored camouflage blockstate is correctly being mapped to a team.chisel.client.render.ModelChiselBlock, but any routers camouflaging as a chisel block don't render at all, looking like a world hole. I'm guessing that's because the model's getQuads() is returning an empty list.

I've looked at the Chisel & CTM block model code, but I'm no rendering expert. I'm guessing the chisel block model needs more context from somewhere (possibly relating to connected textures?) but I'm not knowledgeable enough to know just what.

So this is a request for advice, really - is there something easy (or not so easy) that I can do in my mod to make my block render as a Chisel block?

commented

The problem is unrelated to your model, and instead is caused by this bit of code here:

https://github.com/desht/ModularRouters/blob/master/src/main/java/me/desht/modularrouters/block/BlockItemRouter.java#L97-L104

CTM adds a hook to Block#getExtendedState, so you need to respect that by calling super. Just do state = super.getExtendedState(...) at the top of the method.

Additionally, you should not be using extended blockstates outside of that method, and especially not for your default blockstate.

commented

Actually, a better fix might be to call super at the end of your method. So it would look like:

    @Override
    public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos) {
        TileEntityItemRouter router = TileEntityItemRouter.getRouterAt(world, pos);
        if (router != null) {
            state = ((IExtendedBlockState) state).withProperty(CAMOUFLAGE_STATE, router.getCamouflage());
        }
        return super.getExtendedState(state, world, pos);
    }
commented

Yes I see the ASM code inserting your custom getExtendedState() in CTM now. Unfortunately, that still doesn't seem to help. More debugging verifies that super.getExtendedState() actually does return a ChiselExtendedState and with your suggested change my model's getQuads() method gets a ChiselExtendedState parameter now, so that's good, I suppose.

However, I'm still just getting a regular IBlockState from the extended state - https://github.com/desht/ModularRouters/blob/MC1.11-master/src/main/java/me/desht/modularrouters/client/RouterModel.java#L37 - e.g. something like a chisel:andesite[variation=14] - and passing that to BlockModelShapes#getModelForState(), which is still returning an IBakedModel with an empty quad list. So clearly it's not enough just to pass a simple Chisel block state to BlockModelShapes#getModelForState().

(Also, not sure what you mean about using extended states outside that method? I only use them in that method, and in my model code. I'm aware extended states are only used by the client for rendering purposes).

commented

Here's the issue, Chisel models are layer sensitive, and your block only renders on CUTOUT_MIPPED so you don't get any of the quads since none can render on that layer. Your block needs to render on all layers.

https://github.com/desht/ModularRouters/blob/MC1.11-master/src/main/java/me/desht/modularrouters/block/BlockItemRouter.java#L118-L121

Also, you use IExtendedBlockState outside of getExtendedState here and here

commented

OK, clearly I have much research to do. Any pointers on getting a block to render in multiple layers? I was under the impression that a given block could only render in one layer.

Edit: oh god, is it really as simple as overriding Block#canRenderInLayer() to always return true? Since that seems to work!

Regarding IExtendedState usage, I was following example code from williewillus (https://github.com/williewillus/CamoBlock/blob/master/src/main/java/com/example/camoblock/CamoBlock.java) and GreyGhost (https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/mbe04_block_dynamic_block_model1/BlockCamouflage.java), both of which do reference IExtendedBlockState/ExtendedBlockState for setDefaultState() and in createBlockState().

commented

I made it work by:

  1. Changing BlockItemRouter#canRenderInLayer() to always return true
  2. Modifying the RouterModel to only render in those layers where the camouflaged block would also render (otherwise blocks like glass would appear opaque).

Thanks for your assistance with this, very much appreciated!