[Feature] Custom Connected Texture Layout
A3Bagged opened this issue ยท 6 comments
Hello, first i'd like to thank you for this mod and the time you've put into it.
My question goes as follows; is it possible to add the posibility to create and add custom atlas layouts? (is this is doable i'm sorry, i coulnd't find anything where FULL, HORIZONTAL etc originates from in 'ConnectingTextureLayout' class.
Why?
Well i'm finding myself the need of "full" layout, which isnt bad but im now creating walls which don't need all the fancy stuff. It would be nice to have "simple" having the posibility of a 3x3, or a 3x3 standalone.
It would be nice if we could add a custom layout which can be used in .png.mcmeta in case we have custom needs.
(For example, having a vertical layout connect also sideways (horizontal), thus the 3x3 or just a 4x4 connection (which you need simple layout for). I can't think of any other senarios at the top of my head but i know i've come across 1 or 2 when building my mod and texturing stuff having to "cheat" around the existing layouts.
Sincerely, Chris.
I am somewhat confused how a custom layout would work. Can you give an example?
You mention 3x3, but that would not be enough to do all connections. How would you use a 3x3 layout?
3x3 Tile 9texture example
Yes, let's take a look at this image:
Right now these are 3 different blocks, with each having a texture atlas for connecting textures.
Bottom block = pieced layout
middle block = horizontal layout
top block = pieced layout
I understand depending on your texture you can't always use pieced unless it's somewhat seamless.
Using the below example of one of my blocks would not work with pieced layout.
If i were to have a "3x3" only grid this outcome could be mapped to one texture and possibly one block.
Now you might say, but what about the parts if there is a corner?
Like these, that normally would be mapped by the other tiles in FULL.
Well, it's perhaps possible to extend it horizontally and vertically.
Below i've made a example:
The textures will re-use the middle ones until it meets an end (no blocks connected to the right side = right side tiles).
Same goes for vertically, it will keep using the middle row until there's no blocks conencted to the top or bottom, then it will map the top and bottom tiles to those blocks.
This will kind of act like "Simple" layout with the adittion to be able to use a 3x3 or larger connecting blocks.
If i were to take Simple layout and make a 8x8 wall in game, the blocks will not look right.
So we would be forced to use FULL unless it's possible to use pieced
Hopefully this explains, this way it's quicker without having to sort out all the other ones (which can be confusing at first). And also keeping textures and thus files lower.
Custom Layout
To achieve this "custom layout" i can take FullLayoutHandler.java and change it to work on a 3x3 atlas renaming it for example:
public class Custom3x3LayoutHandler extends ConnectingTextureLayoutHandler.SimpleHandler {
But the problem lies in ConnectingTextureLayout that only looks for the existing layout types (full, horizontal, vertical, compact etc), not our newly created Custom3x3Layout which in this case making a .mcmeta like will do nothing:
{
"fusion": {
"type": "connecting",
"layout": "custom3x3"
}
}
Because fusion wouldn't know this new layout exists without changing any of fusions files and manually adding our custom3x3 layout to ConnectingTextureLayout.java.
Another question.
Is it possible in current state to have connected textures repeat for a max amount of blocks?
Example with 2 different blocks here (they are slightly different but act as they were the same)
What i'm trying to explain, if there was a posibility to alter .json fle (as you would with
"connections: [ { "type": "is_same_block" }, { "type": "match_block", "block": "minecraft:dirt"} ]")
To have it say like: Connect to 3 blocks, if 4rd block start over.
Not sure if this is currently in the mod or even doable without needing 2 different blocks that don't connect.
To achieve this "custom layout" i can take
FullLayoutHandler.javaand change it to work on a 3x3 atlas renaming it for example:
public class Custom3x3LayoutHandler extends ConnectingTextureLayoutHandler.SimpleHandler {
Ah I didn't realize you wanted to implement which tile to pick in code. I though you meant somehow specifying it in the texture metadata json. With json, I feel like it would be a pain to specify which tile to use under which conditions, but through code you'd of course have much more flexibility.
I somewhat moved away from adding things to Fusion's API as it keeps breaking with newer Minecraft versions and I also have already had to make multiple breaking changes, because of new features and the way Fusion works. So not too sure, but will be something for me to look into when I get back to working on Fusion.
For this example, how would it differentiate between faces 1 and 2. Both seem like they would use a corner tile, rather than face 2 using the middle right tile. If it is because of block 1 to the top right, then what tile would face 2 use if you remove just block 1?
Is it possible in current state to have connected textures repeat for a max amount of blocks?
Example with 2 different blocks here (they are slightly different but act as they were the same)
Nope. The problem is that you might have to check up to an unlimited number of blocks.
Let's say I have a 3 by 3 texture that you want to apply to copper blocks and 10 blocks of copper next to each other.

To know how to group the blocks, you would need to know how many blocks came before it (or after if starting from the right). Thus, for the last block you would need to check 9 blocks to the left until there's no more copper blocks. This would become very slow when there's for example 100 or 1000 blocks next to each other.
It would also not work if the row of blocks extends past the chunks loaded on the client as the client wouldn't know how many blocks are still present beyond it.
Fusion does have the continuous texture type which repeats every x blocks, but you'd of course not be able to have borders as it simply uses the block's position rather than what blocks are around it.
Seems reasonable as its not a major feature, more a quality of life update. currently i've gotten away with 3 different blocks with the pieced layout which works fine, but a template like Simple that adds a "center block" would've been nice although i can see the need for corner blocks.
Thank you
Okay i have some news.
I managed to get the 2x2 tiling work as mentioned above.
It's using vanilla mechanics `blockstates` to prevent the texture connection onto the next 'tile'
Having different blockstates prevents them from connecting.
It's using one block for both blockstates.
The block seen here is using templatate: 'pieced'
Blockstate Json
"variants": {
"variant=0": { "model": "decorativepack:block/foundation_test_block" },
"variant=1": { "model": "decorativepack:block/foundation_test_block" }
}
}
The code that makes this work
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import java.util.HashMap;
import java.util.Map;
public class FloorBlock extends Block {
public static final IntegerProperty VARIANT = IntegerProperty.create("variant", 0, 1);
// Keep track of grid origins per world (simple example)
private static final Map<LevelAccessor, BlockPos> gridOrigins = new HashMap<>();
private final int gridSize;
public FloorBlock(BlockBehaviour.Properties props, int gridSize) {
super(props);
this.gridSize = gridSize;
this.registerDefaultState(this.defaultBlockState().setValue(VARIANT, 0));
}
@Override
public BlockState getStateForPlacement(net.minecraft.world.item.context.BlockPlaceContext ctx) {
LevelAccessor level = ctx.getLevel();
BlockPos pos = ctx.getClickedPos();
// If no origin yet, use this first block as origin
gridOrigins.putIfAbsent(level, pos);
return computeVariant(level, pos);
}
@Override
public BlockState updateShape(BlockState state, net.minecraft.core.Direction facing,
BlockState facingState, LevelAccessor level,
BlockPos currentPos, BlockPos facingPos) {
return computeVariant(level, currentPos);
}
private BlockState computeVariant(LevelAccessor level, BlockPos pos) {
BlockPos origin = gridOrigins.getOrDefault(level, new BlockPos(0,0,0));
// Compute macro coordinates relative to origin using gridSize
int macroX = Math.floorDiv(pos.getX() - origin.getX(), this.gridSize);
int macroZ = Math.floorDiv(pos.getZ() - origin.getZ(), this.gridSize);
// Determine variant: 0 or 1
int variant = (macroX + macroZ) & 1;
return this.defaultBlockState().setValue(VARIANT, variant);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(VARIANT);
}
}
It does need some adjusting as right now it's set on a "fixed" grid, whatever block you place down first should set the "grid" so you can have one grid offset from the other