Jump to content

[1.18.2] [SOLVED] Custom block renderer, like cable mods do


Robsutar

Recommended Posts

I would like to make a block that changes its model according to adjacent blocks of the same type, linke applied, mekanism, pipez, and other mods that update the model of the cables when there is an adjacent one, also changing the VoxelShape, or collision box.

Forge version: 1.18.2

Edited by Robsutar
Link to comment
Share on other sites

In Vanilla, Redstone and Fences/Walls kinda do already this thing, where their shape changes according to the neighbors. You should check how they do, which properties are stored in the blockstate file and do the model files accordingly

Edited by JimiIT92
Typos
  • Thanks 1

Don't blame me if i always ask for your help. I just want to learn to be better :)

Link to comment
Share on other sites

On 6/22/2022 at 3:42 AM, JimiIT92 said:

In Vanilla, Redstone and Fences/Walls kinda do already this thing, where their shape changes according to the neighbors. You should check how they do, which properties are stored in the blockstate file and do the model files accordingly

Minecraft: 1.18.2
Forge: 1.18.2-40.1.0
Parchment: 2022.06.19-1.18.2

I'm in a similar situation and as you mentioned I was tracking how vanilla does this, I found the creation of of the Cobblestone Wall on the Vanilla Block class

public static final Block COBBLESTONE_WALL = register("cobblestone_wall", new WallBlock(BlockBehaviour.Properties.copy(COBBLESTONE)));

And tracked down the generation of a Wall Block (multipart):

return MultiPartGenerator
.multiPart(pWallBlock)
.with(
    Condition.condition().term(BlockStateProperties.UP, true), 
    Variant.variant().with(VariantProperties.MODEL, pPostModelLocation))
.with(
    Condition.condition().term(BlockStateProperties.NORTH_WALL, WallSide.LOW), 
    Variant.variant().with(VariantProperties.MODEL, pLowSideModelLocation).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.EAST_WALL, WallSide.LOW), 
    Variant.variant().with(VariantProperties.MODEL, pLowSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R90).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.SOUTH_WALL, WallSide.LOW), 
    Variant.variant().with(VariantProperties.MODEL, pLowSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R180).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.WEST_WALL, WallSide.LOW), 
    Variant.variant().with(VariantProperties.MODEL, pLowSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R270).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.NORTH_WALL, WallSide.TALL), 
    Variant.variant().with(VariantProperties.MODEL, pTallSideModelLocation).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.EAST_WALL, WallSide.TALL), 
    Variant.variant().with(VariantProperties.MODEL, pTallSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R90).with(VariantProperties.UV_LOCK, true)
).with(
    Condition.condition().term(BlockStateProperties.SOUTH_WALL, WallSide.TALL), 
    Variant.variant().with(VariantProperties.MODEL, pTallSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R180).with(VariantProperties.UV_LOCK, true))
.with(
    Condition.condition().term(BlockStateProperties.WEST_WALL, WallSide.TALL), 
    Variant.variant().with(VariantProperties.MODEL, pTallSideModelLocation)
    .with(VariantProperties.Y_ROT, VariantProperties.Rotation.R270).with(VariantProperties.UV_LOCK, true));

But the one thing I cannot track is the blockstate json. I tried to create one based on examples from open source mods, but seemes something changed because they where not working at first. After seeing the implementation of the generator, I changed the properties that I saw there to something like this:
 

{
  "multipart": [
    {   "when": { "up": "true" },
      "apply": { "model": "examplemod:block/examplemod_stone_wall_post", "uvlock": true }
    },
    {   "when": { "north": "low" },
      "apply": { "model": "examplemod:block/examplemod_stone_wall_side", "uvlock": true }
    },
    {   "when": { "east": "low" },
      "apply": { "model": "examplemod:block/examplemod_stone_wall_side", "y": 90, "uvlock": true }
    },
    {   "when": { "south": "low" },
      "apply": { "model": "examplemod:block/examplemod_stone_wall_side", "y": 180, "uvlock": true }
    },
    {   "when": { "west": "low" },
      "apply": { "model": "examplemod:block/examplemod_stone_wall_side", "y": 270, "uvlock": true }
    }
  ]
}

With this, and the models json created, the custom walls are generated and texture are there, but still, they do not connect with eachothers

2022-06-23-17-31-20-Minecraft-1-18-2-Sin
 

I'm guess I'm missing something on the json, but I cannot find any json on the generated Vanilla Minecraft (the one on external libs)

Link to comment
Share on other sites

Forge: 1.18.2-40.1.0
Parchment: 2022.06.19-1.18.2

I'm searching for a Wall blockstate.json example as I'm not finding any on the minecraft (external libreries) folder. I'm doing a custom wall for a new material, nothing fancy as I just want the normal behavior. This are the details of my implementation.

Registering the Block and WallBlock

public static final RegistryObject<Block> EXPERIMENTAL_STONE = registerBlock("experimental_stone", () -> new Block(BlockBehaviour.Properties.of(Material.STONE).strength(9f).requiresCorrectToolForDrops()), ExperimentalCreativeModeTab.EXPERIMENTAL_TAB);
public static final RegistryObject<WallBlock> EXPERIMENTAL_STONE_WALL = registerBlock("experimental_stone_wall", () -> new WallBlock(BlockBehaviour.Properties.copy(EXPERIMENTAL_STONE.get())), ExperimentalCreativeModeTab.EXPERIMENTAL_TAB);

private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block, CreativeModeTab tab){
    RegistryObject<T> toReturn = BLOCKS.register(name, block);
    registerBlockItem(name, toReturn, tab);
    return toReturn;
}

private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block, CreativeModeTab tab){
    return ExperimentalItems.ITEMS.register(name, () -> new BlockItem(block.get(), new Item.Properties().tab(tab)));
}

Current blockstate implementation:
assets/experimental/blockstates/experimental_stone.json

{
    "variants": {
      "": {
        "model": "experimental:block/experimental_stone"
      }
    }
  }

assets/experimental/blockstates/experimental_stone_wall.json

{
  "multipart": [
    {   "when": { "up": "true" },
      "apply": { "model": "experimental:block/experimental_stone_wall_post", "uvlock": true }
    },
    {   "when": { "north": "low" },
      "apply": { "model": "experimental:block/experimental_stone_wall_side", "uvlock": true }
    },
    {   "when": { "east": "low" },
      "apply": { "model": "experimental:block/experimental_stone_wall_side", "y": 90, "uvlock": true }
    },
    {   "when": { "south": "low" },
      "apply": { "model": "experimental:block/experimental_stone_wall_side", "y": 180, "uvlock": true }
    },
    {   "when": { "west": "low" },
      "apply": { "model": "experimental:block/experimental_stone_wall_side", "y": 270, "uvlock": true }
    },
    {   "when": { "north": "tall" },
      "apply": { "model": "experimental:block/experimental_stone_wall_post", "uvlock": true }
    },
    {   "when": { "east": "tall" },
      "apply": { "model": "experimental:block/experimental_stone_wall_post", "y": 90, "uvlock": true }
    },
    {   "when": { "south": "tall" },
      "apply": { "model": "experimental:block/experimental_stone_wall_post", "y": 180, "uvlock": true }
    },
    {   "when": { "west": "tall" },
      "apply": { "model": "experimental:block/experimental_stone_wall_post", "y": 270, "uvlock": true }
    }
  ]
}

With this, I don't se any error on logs, or any missing texture, and the wall block is attaching with anything that is not itself, but it would seem I'm missing a property for being able to attach to itself.
2022-06-23-17-31-20-Minecraft-1-18-2-Sin

I do find a declaration on the vanilla BlockStateData class with this: 

register(2224, "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'false',up:'false',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'false',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'false',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'false',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'false',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'true',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'true',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'true',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'false',south:'true',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'false',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'false',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'false',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'false',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'true',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'true',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'true',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'false',north:'true',south:'true',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'false',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'false',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'false',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'false',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'true',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'true',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'true',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'false',south:'true',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'false',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'false',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'false',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'false',up:'true',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'true',up:'false',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'true',up:'false',variant:'cobblestone',west:'true'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'true',up:'true',variant:'cobblestone',west:'false'}}", "{Name:'minecraft:cobblestone_wall',Properties:{east:'true',north:'true',south:'true',up:'true',variant:'cobblestone',west:'true'}}");

But when I try something similar to "north": true, it does generate an error and textures for the wall are not generated.:

←[mjava.lang.RuntimeException: Unknown value 'true' for property 'north' on 'Block{experimental:experimental_stone_wall}' in 'true'  
........ (removed the whole stacktrace as it ends here with the detail)
at [email protected]/cpw.mods.bootstraplauncher.BootstrapLauncher.main(BootstrapLauncher.java:149)      
←[33m[18:26:53] [Render thread/WARN] [minecraft/ModelBakery]: Unable to bake model: 'experimental:experimental_stone_wall#east=low,north=tall,south=none,up=true,waterlogged=false,west=none': java.lang.RuntimeException: Unknown value 'true' for property 'north' on 'Block{experimental:experimental_stone_wall}' in 'true'

Thanks in advance for the help!

Edited by aferrercrafter
typos
Link to comment
Share on other sites

you need to add walls and fences to tags for them to connect correctly. You would need to create a dir at the same level as your assets folder called `data` and inside that `tags/blocks/` then add `walls.json` inside which you would add 

{
  "replace": false,
  "values": [
    "modid:material_wall"
  ]
}

 

Link to comment
Share on other sites

14 hours ago, nanoaquila said:

you need to add walls and fences to tags for them to connect correctly. You would need to create a dir at the same level as your assets folder called `data` and inside that `tags/blocks/` then add `walls.json` inside which you would add 

{
  "replace": false,
  "values": [
    "modid:material_wall"
  ]
}

 

That did the trick, although I needed to put it on folder:
data/minecraft/tags/blocks/walls.json

Thanks both!

PD:

6 hours ago, diesieben07 said:

Duplicate threads merged. Please do not post duplicate threads.

First time on forum, my bad. I thought as it was a slight different question so I created a different thread, noted for next time!

Link to comment
Share on other sites

On 6/21/2022 at 9:10 PM, Robsutar said:

I would like to make a block that changes its model according to adjacent blocks of the same type, linke applied, mekanism, pipez, and other mods that update the model of the cables when there is an adjacent one, also changing the VoxelShape, or collision box.

Forge version: 1.18.2

About the custom template:

I used Boolean Property (Check the official tutorial on the forge website) to determine which model I would like to use, and I used a multipart model mine block, using the conditions of the Boolean Property
 

public class Cable extends Block{
    public static final BooleanProperty SOUTH_CONNECTED = BooleanProperty.create("south"); //Boolean Property
    /*   it is possible to put others, in the example I will only do it with the south direction
    public static final BooleanProperty NORTH_CONNECTED = BooleanProperty.create("north");
    public static final BooleanProperty NORTH_CONNECTED = BooleanProperty.create("north");
    */


    public Cable() {
            super(Properties.copy(Blocks.GLASS_PANE).dynamicShape());
			//register Default Block State
            this.registerDefaultState(stateDefinition.any()
                    //.setValue(NORTH_CONNECTED, false),
                    .setValue(SOUTH_CONNECTED, false); //by default I want it to be desconected
    }

	//Register boolean properties
	@Override
    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_49915_) {
        p_49915_.add(/*UP,DOWN,NORTH,EAST,*/SOUTH);
    }

	//Change Boolean Property when checking adjacent blocks
	@Override
    public BlockState getStateForPlacement(BlockPlaceContext context) {
        return getState(context.getLevel(), context.getClickedPos());
    }

    private BlockState getState(Level world, BlockPos pos) {
        return defaultBlockState()
                //.setValue(NORTH_CONNECTED, getSideValue(world, pos, Direction.NORTH),
                .setValue(SOUTH_CONNECTED, getSideValue(world, pos, Direction.SOUTH));
    }

    private bool getSideValue(Level world, BlockPos pos, Direction facing) {
        BlockState state = world.getBlockState(pos.relative(facing));
        Block block = state.getBlock();
		//If it's a Cable class block, I want it to connect
        return (block instanceof Cable);
    }

	//Updating boolean properties when an adjacent block is updated, was having a problem, when I broke a cable, it kept plugged in in the air;
	@Override
    public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos pos1, boolean b) {
        super.neighborChanged(state, world, pos, block, pos1, b);
        world.setBlockAndUpdate(pos,getState(world,pos));
    }
}


About the model:
The following json file is the blockstate of the block, located in "resources/assets/mod_id/blockstates/cable.json", but the models cited in the file ("sutarstorage:block/cable_core" and "sutarstorage:block/cable_part") are located in "resources/assets/mod_id/models/block/cabe_(part/core).json", both models were made using Blockbench

 

I made the json manually, but I'm already aware that there are ways to automate its generation.In case you want to copy the code, you will have to remove the comments

{
  "multipart": [
    {   "apply": { "model": "sutarstorage:block/cable_core" }},  ---> the base model, always visible

	--- Models that will only be rendered with certain condition
    {   "when": { "north": "true" },
      "apply": { "model": "sutarstorage:block/cable_part", "uvlock": false }
    },
    {   "when": { "south": "true" },
      "apply": { "model": "sutarstorage:block/cable_part", "y": 180, "uvlock": false }
    },
	---Note that the template is the same ("block/cable_part"), but rotated, it is possible to use other models instead
}


Special thanks to JimiIT92 and aferrercrafter

Link to comment
Share on other sites

  • Robsutar changed the title to [1.18.2] [SOLVED] Custom block renderer, like cable mods do

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.



×
×
  • Create New...

Important Information

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