Jump to content

Zemelua

Members
  • Posts

    190
  • Joined

  • Last visited

Everything posted by Zemelua

  1. I'm looking for a way to replace the missing texture (black and purple texture when the model or texture generation fails) with another in one of the events (probably ModelBakedEvent). The resource pack method is not suitable because I only want to replace the block item in my mod with a new texture and leave the vanilla missing texture as it is. What I want to know is: 1. Which event should I use to replace the texture before the model is generated? 2. Which method of the event should be used to get the model that is about to be generated 3. How to check that the model belongs to your mod and that the missing texture is used 4. Finally, which method should be used to replace the texture of the model
  2. I use a translator, so I'm sorry if my English is unnatural. Well, as the title says, I'm pretty sure I understand what Capability is, but there are a few things I don't understand. -Is it correct to understand that Capability is for holding arbitrary data by associating it with an object such as a player or TileEntity? -In many cases, it seems recommended to use Capability instead of implementing IInventory when creating a TileEntity with an inventory, why? What are the drawbacks of implementing Vanilla's I Inventory and what are the benefits of using Capability? -Although it overlaps a little with the second question, when implementing Magic Point in Player, of course it is not possible to rewrite the Vanilla Player class, so it is necessary to link the player and Magic Point instance using Capability. I understand that. But should I use Capability for new entity and tile entities as well? Is it even a very simple inheritance of Vanilla's ChestTileEntity?
  3. Oh, I didn't know that Java spec. I used an indexed for loop and it worked perfectly. Thank you.
  4. public class BumpkinBlock extends HorizontalBlock { private static final EnumProperty<BumpkinPart> PART = UMUBlockStateProperties.BUMPKIN_PART; private static final VoxelShape DOWN_NORTH_WEST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(11, 0, 3, 16, 16, 6), Block.makeCuboidShape(3, 0, 11, 6, 16, 16), Block.makeCuboidShape(6, 0, 6, 16, 16, 16) ); private static final VoxelShape DOWN_NORTH_EAST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(0, 0, 3, 5, 16, 6), Block.makeCuboidShape(10, 0, 11, 13, 16, 16), Block.makeCuboidShape(0, 0, 6, 10, 16, 16) ); private static final VoxelShape DOWN_SOUTH_WEST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(11, 0, 10, 16, 16, 13), Block.makeCuboidShape(3, 0, 0, 6, 16, 5), Block.makeCuboidShape(6, 0, 0, 16, 16, 10) ); private static final VoxelShape DOWN_SOUTH_EAST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(0, 0, 10, 5, 16, 13), Block.makeCuboidShape(10, 0, 0, 13, 16, 5), Block.makeCuboidShape(0, 0, 0, 10, 16, 10) ); private static final VoxelShape UP_NORTH_WEST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(11, 0, 3, 16, 5, 6), Block.makeCuboidShape(3, 0, 11, 6, 5, 16), Block.makeCuboidShape(6, 0, 6, 16, 5, 16) ); private static final VoxelShape UP_NORTH_EAST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(0, 0, 3, 5, 5, 6), Block.makeCuboidShape(10, 0, 11, 13, 5, 16), Block.makeCuboidShape(0, 0, 6, 10, 5, 16) ); private static final VoxelShape UP_SOUTH_WEST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(11, 0, 10, 16, 5, 13), Block.makeCuboidShape(3, 0, 0, 6, 5, 5), Block.makeCuboidShape(6, 0, 0, 16, 5, 10) ); private static final VoxelShape UP_SOUTH_EAST_SHAPE = VoxelShapes.or( Block.makeCuboidShape(0, 0, 10, 5, 5, 13), Block.makeCuboidShape(10, 0, 0, 13, 5, 5), Block.makeCuboidShape(0, 0, 0, 10, 5, 10) ); public static final List<List<BlockPos>> BUMPKINS = new ArrayList<>(); public BumpkinBlock(Properties builder) { super(builder); this.setDefaultState(this.getStateContainer().getBaseState() .with(PART, BumpkinPart.LOWER_FRONT_LEFT).with(HORIZONTAL_FACING, Direction.NORTH) ); } @Override public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { switch (state.get(HORIZONTAL_FACING)) { case NORTH: switch (state.get(PART)) { case LOWER_FRONT_LEFT: return DOWN_NORTH_WEST_SHAPE; case LOWER_FRONT_RIGHT: return DOWN_NORTH_EAST_SHAPE; case LOWER_BACK_LEFT: return DOWN_SOUTH_WEST_SHAPE; case LOWER_BACK_RIGHT: return DOWN_SOUTH_EAST_SHAPE; case UPPER_FRONT_LEFT: return UP_NORTH_WEST_SHAPE; case UPPER_FRONT_RIGHT: return UP_NORTH_EAST_SHAPE; case UPPER_BACK_LEFT: return UP_SOUTH_WEST_SHAPE; case UPPER_BACK_RIGHT: return UP_SOUTH_EAST_SHAPE; } case SOUTH: switch (state.get(PART)) { case LOWER_FRONT_LEFT: return DOWN_SOUTH_EAST_SHAPE; case LOWER_FRONT_RIGHT: return DOWN_SOUTH_WEST_SHAPE; case LOWER_BACK_LEFT: return DOWN_NORTH_EAST_SHAPE; case LOWER_BACK_RIGHT: return DOWN_NORTH_WEST_SHAPE; case UPPER_FRONT_LEFT: return UP_SOUTH_EAST_SHAPE; case UPPER_FRONT_RIGHT: return UP_SOUTH_WEST_SHAPE; case UPPER_BACK_LEFT: return UP_NORTH_EAST_SHAPE; case UPPER_BACK_RIGHT: return UP_NORTH_WEST_SHAPE; } case WEST: switch (state.get(PART)) { case LOWER_FRONT_LEFT: return DOWN_SOUTH_WEST_SHAPE; case LOWER_FRONT_RIGHT: return DOWN_NORTH_WEST_SHAPE; case LOWER_BACK_LEFT: return DOWN_SOUTH_EAST_SHAPE; case LOWER_BACK_RIGHT: return DOWN_NORTH_EAST_SHAPE; case UPPER_FRONT_LEFT: return UP_SOUTH_WEST_SHAPE; case UPPER_FRONT_RIGHT: return UP_NORTH_WEST_SHAPE; case UPPER_BACK_LEFT: return UP_SOUTH_EAST_SHAPE; case UPPER_BACK_RIGHT: return UP_NORTH_EAST_SHAPE; } case EAST: switch (state.get(PART)) { case LOWER_FRONT_LEFT: return DOWN_NORTH_EAST_SHAPE; case LOWER_FRONT_RIGHT: return DOWN_SOUTH_EAST_SHAPE; case LOWER_BACK_LEFT: return DOWN_NORTH_WEST_SHAPE; case LOWER_BACK_RIGHT: return DOWN_SOUTH_WEST_SHAPE; case UPPER_FRONT_LEFT: return UP_NORTH_EAST_SHAPE; case UPPER_FRONT_RIGHT: return UP_SOUTH_EAST_SHAPE; case UPPER_BACK_LEFT: return UP_NORTH_WEST_SHAPE; case UPPER_BACK_RIGHT: return UP_SOUTH_WEST_SHAPE; } default: return VoxelShapes.fullCube(); } } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { BlockPos pos = context.getPos(); Direction face = context.getPlacementHorizontalFacing(); World world = context.getWorld(); if (pos.getY() < 255 && world.getBlockState(pos.offset(face.rotateYCCW())).isReplaceable(context) && world.getBlockState(pos.offset(face)).isReplaceable(context) && world.getBlockState(pos.offset(face).offset(face.rotateYCCW())).isReplaceable(context) && world.getBlockState(pos.up()).isReplaceable(context) && world.getBlockState(pos.up().offset(face.rotateYCCW())).isReplaceable(context) && world.getBlockState(pos.up().offset(face)).isReplaceable(context) && world.getBlockState(pos.up().offset(face).offset(face.rotateYCCW())).isReplaceable(context) ) { return this.getDefaultState().with(HORIZONTAL_FACING, face.getOpposite()); } return null; } @Override public void onBlockPlacedBy(World worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { Direction face = Optional.ofNullable(placer).map(Entity::getHorizontalFacing).orElse(Direction.NORTH); worldIn.setBlockState(pos.offset(face.rotateYCCW()), state.with(PART, BumpkinPart.LOWER_FRONT_RIGHT)); worldIn.setBlockState(pos.offset(face), state.with(PART, BumpkinPart.LOWER_BACK_LEFT)); worldIn.setBlockState(pos.offset(face).offset(face.rotateYCCW()), state.with(PART, BumpkinPart.LOWER_BACK_RIGHT)); worldIn.setBlockState(pos.up(), state.with(PART, BumpkinPart.UPPER_FRONT_LEFT)); worldIn.setBlockState(pos.up().offset(face.rotateYCCW()), state.with(PART, BumpkinPart.UPPER_FRONT_RIGHT)); worldIn.setBlockState(pos.up().offset(face), state.with(PART, BumpkinPart.UPPER_BACK_LEFT)); worldIn.setBlockState(pos.up().offset(face).offset(face.rotateYCCW()), state.with(PART, BumpkinPart.UPPER_BACK_RIGHT)); BUMPKINS.add(new ArrayList<>(Arrays.asList( pos, pos.offset(face.rotateYCCW()), pos.offset(face), pos.offset(face).offset(face.rotateYCCW()), pos.up(), pos.up().offset(face.rotateYCCW()), pos.up().offset(face), pos.up().offset(face).offset(face.rotateYCCW()) ))); } @Override public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, BlockPos currentPos, BlockPos facingPos) { for (List<BlockPos> parts : BUMPKINS) { if (parts.contains(currentPos)) { if (parts.stream().map(i -> worldIn.getBlockState(i).matchesBlock(this)).collect(Collectors.toList()).contains(false)) { //parts.stream().forEach(i -> worldIn.setBlockState(i, Blocks.AIR.getDefaultState(), 3)); parts.remove(currentPos); if (parts.isEmpty()) BUMPKINS.remove(parts); return Blocks.AIR.getDefaultState(); } } } return stateIn; } @Override protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) { builder.add(PART, HORIZONTAL_FACING); } } I'm now making a block that is 2x2x2 and can be put / destroyed like one big block. In the case of the above code, it is put / destroyed several times well, but if it is installed occasionally, it will cause a crash. I'm probably aware that the code itself is terrible, but how do you specifically fix it? Below is a copy of the crash report: [03:00:18] [Render thread/INFO] [STDOUT/]: [net.minecraft.util.registry.Bootstrap:printToSYSOUT:130]: ---- Minecraft Crash Report ---- // Hi. I'm Minecraft, and I'm a crashaholic. Time: 21/04/21 3:00 Description: Unexpected error java.util.ConcurrentModificationException: null at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911) ~[?:1.8.0_282] {} at java.util.ArrayList$Itr.next(ArrayList.java:861) ~[?:1.8.0_282] {} at io.github.zemelua.umumod.block.BumpkinBlock.updatePostPlacement(BumpkinBlock.java:172) ~[main/:?] {re:classloading} at net.minecraft.block.AbstractBlock$AbstractBlockState.updatePostPlacement(AbstractBlock.java:749) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.block.AbstractBlock$AbstractBlockState.updateNeighbours(AbstractBlock.java:684) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.world.World.markAndNotifyBlock(World.java:274) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:241) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:205) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:315) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B} at io.github.zemelua.umumod.block.BumpkinBlock.onBlockPlacedBy(BumpkinBlock.java:158) ~[main/:?] {re:classloading} at net.minecraft.item.BlockItem.tryPlace(BlockItem.java:69) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.item.BlockItem.onItemUse(BlockItem.java:42) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading} at net.minecraft.item.ItemStack.lambda$onItemUse$5(ItemStack.java:195) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:210) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:195) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.client.multiplayer.PlayerController.func_217292_a(PlayerController.java:319) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.rightClickMouse(Minecraft.java:1407) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.processKeyBinds(Minecraft.java:1692) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.runTick(Minecraft.java:1507) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:979) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.run(Minecraft.java:612) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_282] {} at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_282] {} at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_282] {} at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_282] {} at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.0.9.jar:?] {} at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:105) [forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {} A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Thread: Render thread Stacktrace: at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911) ~[?:1.8.0_282] {} at java.util.ArrayList$Itr.next(ArrayList.java:861) ~[?:1.8.0_282] {} at io.github.zemelua.umumod.block.BumpkinBlock.updatePostPlacement(BumpkinBlock.java:172) ~[?:?] {re:classloading} at net.minecraft.block.AbstractBlock$AbstractBlockState.updatePostPlacement(AbstractBlock.java:749) ~[forge:?] {re:classloading} at net.minecraft.block.AbstractBlock$AbstractBlockState.updateNeighbours(AbstractBlock.java:684) ~[forge:?] {re:classloading} at net.minecraft.world.World.markAndNotifyBlock(World.java:274) ~[forge:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:241) ~[forge:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:205) ~[forge:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.world.World.setBlockState(World.java:315) ~[forge:?] {re:classloading,pl:accesstransformer:B} at io.github.zemelua.umumod.block.BumpkinBlock.onBlockPlacedBy(BumpkinBlock.java:158) ~[?:?] {re:classloading} at net.minecraft.item.BlockItem.tryPlace(BlockItem.java:69) ~[forge:?] {re:classloading} at net.minecraft.item.BlockItem.onItemUse(BlockItem.java:42) ~[forge:?] {re:classloading} at net.minecraft.item.ItemStack.lambda$onItemUse$5(ItemStack.java:195) ~[forge:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:210) ~[forge:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.item.ItemStack.onItemUse(ItemStack.java:195) ~[forge:?] {re:classloading,xf:fml:forge:filled_map.4,xf:fml:forge:itemstack} at net.minecraft.client.multiplayer.PlayerController.func_217292_a(PlayerController.java:319) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.rightClickMouse(Minecraft.java:1407) ~[forge:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.processKeyBinds(Minecraft.java:1692) ~[forge:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} -- Affected level -- Details: All players: 1 total; [ClientPlayerEntity['Dev'/191, l='ClientLevel', x=-18.58, y=65.07, z=40.20]] Chunk stats: Client Chunk Cache: 841, 573 Level dimension: minecraft:overworld Level spawn location: World: (-48,67,0), Chunk: (at 0,4,0 in -3,0; contains blocks -48,0,0 to -33,255,15), Region: (-1,0; contains chunks -32,0 to -1,31, blocks -512,0,0 to -1,255,511) Level time: 99811 game time, 12364 day time Server brand: forge Server type: Integrated singleplayer server Stacktrace: at net.minecraft.client.world.ClientWorld.fillCrashReport(ClientWorld.java:465) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.addGraphicsAndWorldToCrashReport(Minecraft.java:2091) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.Minecraft.run(Minecraft.java:633) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A} at net.minecraft.client.main.Main.main(Main.java:184) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_282] {} at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_282] {} at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_282] {} at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_282] {} at net.minecraftforge.userdev.FMLUserdevClientLaunchProvider.lambda$launchService$0(FMLUserdevClientLaunchProvider.java:52) ~[forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandlerDecorator.launch(LaunchServiceHandlerDecorator.java:37) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:54) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.LaunchServiceHandler.launch(LaunchServiceHandler.java:72) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.run(Launcher.java:82) [modlauncher-8.0.9.jar:?] {} at cpw.mods.modlauncher.Launcher.main(Launcher.java:66) [modlauncher-8.0.9.jar:?] {} at net.minecraftforge.userdev.LaunchTesting.main(LaunchTesting.java:105) [forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-recomp.jar:?] {} -- System Details -- Details: Minecraft Version: 1.16.5 Minecraft Version ID: 1.16.5 Operating System: Windows 10 (amd64) version 10.0 Java Version: 1.8.0_282, Amazon.com Inc. Java VM Version: OpenJDK 64-Bit Server VM (mixed mode), Amazon.com Inc. Memory: 397839344 bytes (379 MB) / 1187512320 bytes (1132 MB) up to 1873805312 bytes (1787 MB) CPUs: 12 JVM Flags: 1 total; -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump ModLauncher: 8.0.9+86+master.3cf110c ModLauncher launch target: fmluserdevclient ModLauncher naming: mcp ModLauncher services: /mixin-0.8.2.jar mixin PLUGINSERVICE /eventbus-4.0.0.jar eventbus PLUGINSERVICE /forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-launcher.jar object_holder_definalize PLUGINSERVICE /forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-launcher.jar runtime_enum_extender PLUGINSERVICE /accesstransformers-3.0.1.jar accesstransformer PLUGINSERVICE /forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-launcher.jar capability_inject_definalize PLUGINSERVICE /forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-launcher.jar runtimedistcleaner PLUGINSERVICE /mixin-0.8.2.jar mixin TRANSFORMATIONSERVICE /forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.5-launcher.jar fml TRANSFORMATIONSERVICE FML: 36.1 Forge: net.minecraftforge:36.1.4 FML Language Providers: [email protected] minecraft@1 Mod List: client-extra.jar |Minecraft |minecraft |1.16.5 |DONE |a1:d4:5e:04:4f:d3:d6:e0:7b:37:97:cf:77:b0:de:ad:4a:47:ce:8c:96:49:5f:0a:cf:8c:ae:b2:6d:4b:8a:3f forge-1.16.5-36.1.4_mapped_snapshot_20210309-1.16.|Forge |forge |36.1.4 |DONE |NOSIGNATURE main |UMUMod |umu |NONE |DONE |NOSIGNATURE Crash Report UUID: 4fe8a232-4f3d-47fc-aad2-ea52bb00aa0b Launched Version: MOD_DEV Backend library: LWJGL version 3.2.2 build 10 Backend API: Intel(R) UHD Graphics 630 GL version 4.6.0 - Build 27.20.100.9126, Intel GL Caps: Using framebuffer using OpenGL 3.0 Using VBOs: Yes Is Modded: Definitely; Client brand changed to 'forge' Type: Client (map_client.txt) Graphics mode: fancy Resource Packs: Current Language: English (US) CPU: 12x Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz [03:00:18] [Render thread/INFO] [STDOUT/]: [net.minecraft.util.registry.Bootstrap:printToSYSOUT:130]: #@!@# Game crashed! Crash report saved to: #@!@# D:\User\Zemelua\Projects\Minecraft Mod\UMU Mod\run\.\crash-reports\crash-2021-04-21_03.00.18-client.txt AL lib: (EE) alc_cleanup: 1 device not closed
  5. Looking at the ItemLayerModel, it seems that each pixel of the texture is overwritten and generated as a quad, but in the ItemModelGenerator rendering the spawnegg item, simply add the quad of the upper layer to the quad of the lower layer. It looks like it's being returned in a list. Is the transparent part overwritten just by adding a Quad with the same shape but a different texture later, like the latter?
  6. This may be a simple question, but how do I stack two TextureAtlasSprites A and B to generate a new TextureAtlasSprite? In other words, the base A is overwritten with pixels other than the transparent part of B.
  7. public class ConnectedTexturesModel implements IModelGeometry<ConnectedTexturesModel> { IConnection[] connections; public ConnectedTexturesModel(IConnection[] connections) { this.connections = connections; } @Override public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) { return new BakedModel(connections, modelTransform); } @Override public Collection<RenderMaterial> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) { // return new ArrayList<>(Arrays.asList(new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation("expansionmod", "block/plaster_half_timber_none")))); List<RenderMaterial> textures = new ArrayList(); Arrays.stream(connections).forEach(i -> textures.addAll(i.getTextures())); return textures; } public static final class BakedModel implements IBakedModel { IConnection[] connections; private IModelTransform modelTransform; private final List<TextureAtlasSprite> sprites = new ArrayList<TextureAtlasSprite>(Arrays.asList( null, null, null, null, null, null )); private static final ModelProperty<ConnectedTexturesModelData> CONNECTED_TEXTURES_DATA = new ModelProperty<>(); public BakedModel(IConnection[] connections, IModelTransform modelTransform) { this.connections = connections; this.modelTransform = modelTransform; } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) { for (int i = 0; i < connections.length; i++) { IConnection connection = connections[i]; if (extraData.hasProperty(CONNECTED_TEXTURES_DATA)) { sprites.set(i, connection.makeTexture( extraData.getData(CONNECTED_TEXTURES_DATA).world, extraData.getData(CONNECTED_TEXTURES_DATA).pos, state, Direction.byIndex(i)) ); //ExpansionMod.LOGGER.debug(sprites.toString()); //ExpansionMod.LOGGER.debug(connections[2].getTextures().toString()); } else { sprites.set(i, new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, MissingTextureSprite.getLocation()).getSprite()); } } //ExpansionMod.LOGGER.debug(sprites.get(2).toString()); //ExpansionMod.LOGGER.debug(new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation("expansionmod", "block/plaster_half_timber_cross")).getSprite().toString()); List<BakedQuad> quads = new ArrayList<>(); TextureAtlasSprite down = sprites.get(0); TextureAtlasSprite up = sprites.get(1); TextureAtlasSprite north = sprites.get(2); TextureAtlasSprite south = sprites.get(3); TextureAtlasSprite west = sprites.get(4); TextureAtlasSprite east = sprites.get(5); if (side == Direction.DOWN) { quads.add(buildQuad(Direction.DOWN, down, 0, 0, 1, down.getMinU(), down.getMinV(), 0, 0, 0, down.getMinU(), down.getMaxV(), 1, 0, 0, down.getMaxU(), down.getMaxV(), 1, 0, 1, down.getMaxU(), down.getMinV() )); } if (side == Direction.UP) { quads.add(buildQuad(Direction.UP, up, 0, 1, 0, up.getMinU(), up.getMinV(), 0, 1, 1, up.getMinU(), up.getMaxV(), 1, 1, 1, up.getMaxU(), up.getMaxV(), 1, 1, 0, up.getMaxU(), up.getMinV() )); } if (side == Direction.NORTH) { quads.add(buildQuad(Direction.NORTH, north, 1, 1, 0, north.getMinU(), north.getMinV(), 1, 0, 0, north.getMinU(), north.getMaxV(), 0, 0, 0, north.getMaxU(), north.getMaxV(), 0, 1, 0, north.getMaxU(), north.getMinV() )); } if (side == Direction.SOUTH) { quads.add(buildQuad(Direction.SOUTH, south, 0, 1, 1, south.getMinU(), south.getMinV(), 0, 0, 1, south.getMinU(), south.getMaxV(), 1, 0, 1, south.getMaxU(), south.getMaxV(), 1, 1, 1, south.getMaxU(), south.getMinV() )); } if (side == Direction.WEST) { quads.add(buildQuad(Direction.WEST, west, 0, 1, 0, west.getMinU(), west.getMinV(), 0, 0, 0, west.getMinU(), west.getMaxV(), 0, 0, 1, west.getMaxU(), west.getMaxV(), 0, 1, 1, west.getMaxU(), west.getMinV() )); } if (side == Direction.EAST) { quads.add(buildQuad(Direction.EAST, east, 1, 1, 1, east.getMinU(), east.getMinV(), 1, 0, 1, east.getMinU(), east.getMaxV(), 1, 0, 0, east.getMaxU(), east.getMaxV(), 1, 1, 0, east.getMaxU(), east.getMinV() )); } return quads; } @Override public IModelData getModelData(@Nonnull IBlockDisplayReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) { if (tileData == EmptyModelData.INSTANCE) { tileData = new ModelDataMap.Builder().withProperty(CONNECTED_TEXTURES_DATA).build(); } tileData.setData(CONNECTED_TEXTURES_DATA, new ConnectedTexturesModelData(world, pos)); return tileData; } private BakedQuad buildQuad(Direction side, TextureAtlasSprite sprite, float x0, float y0, float z0, float u0, float v0, float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3) { BakedQuadBuilder builder = new BakedQuadBuilder(sprite); builder.setApplyDiffuseLighting(true); builder.setContractUVs(true); boolean hasTransform = this.modelTransform.getRotation().isIdentity(); IVertexConsumer consumer = hasTransform ? new TRSRTransformer(builder, this.modelTransform.getRotation()) : builder; builder.setQuadOrientation(side); putVertex(consumer, side, x0, y0, z0, u0, v0); putVertex(consumer, side, x1, y1, z1, u1, v1); putVertex(consumer, side, x2, y2, z2, u2, v2); putVertex(consumer, side, x3, y3, z3, u3, v3); return builder.build(); } private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v) { ImmutableList<VertexFormatElement> elements = consumer.getVertexFormat().getElements(); for (int e = 0; e <= elements.size() - 1; e++) { VertexFormatElement element = elements.get(e); switch (element.getUsage()) { case POSITION: consumer.put(e, x, y, z, 1.0f); break; case COLOR: consumer.put(e, 1.0f, 1.0f, 1.0f, 1.0f); break; case NORMAL: float offX = (float) side.getXOffset(); float offY = (float) side.getYOffset(); float offZ = (float) side.getZOffset(); consumer.put(e, offX, offY, offZ, 0.0f); break; case UV: if (element.getIndex() == 0) { consumer.put(e, u, v, 0f, 1f); break; } default: consumer.put(e); break; } } } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { throw new AssertionError("IBakedModel::getQuads should never be called, only IForgeBakedModel::getQuads"); } @Override public boolean isAmbientOcclusion() { return true; } @Override public boolean isGui3d() { return true; } @Override public boolean isSideLit() { return false; } @Override public boolean isBuiltInRenderer() { return false; } @Override public TextureAtlasSprite getParticleTexture() { return sprites.get(2); } @Override public ItemOverrideList getOverrides() { return null; } } public static class Loader implements IModelLoader<ConnectedTexturesModel> { public static Loader INSTANCE = new Loader(); @Override public void onResourceManagerReload(IResourceManager resourceManager) { } @Override public ConnectedTexturesModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) { List<IConnection> connections = new ArrayList<>(Arrays.asList( NormalConnection.missing(), NormalConnection.missing(), NormalConnection.missing(), NormalConnection.missing(), NormalConnection.missing(), NormalConnection.missing() )); if (modelContents.has("faces")) { JsonObject facesJson = modelContents.get("faces").getAsJsonObject(); if (facesJson.has("all")) { for (Direction face : Direction.values()) { IConnection connection = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("all"), IConnection.class); connections.set(face.getIndex(), connection); } } if (facesJson.has("end")) { IConnection connection = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("end"), IConnection.class); connections.set(Direction.DOWN.getIndex(), connection); connections.set(Direction.UP.getIndex(), connection); } if (facesJson.has("side")) { IConnection connection = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("side"), IConnection.class); connections.set(Direction.NORTH.getIndex(), connection); connections.set(Direction.SOUTH.getIndex(), connection); connections.set(Direction.WEST.getIndex(), connection); connections.set(Direction.EAST.getIndex(), connection); } for (Direction face : Direction.values()) { IConnection connection = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get(face.toString()), IConnection.class); if (modelContents.has(face.toString())) { connections.set(face.getIndex(), connection); } } } return new ConnectedTexturesModel(connections.toArray(new IConnection[connections.size()])); } } } I created a custom model like this and it's working fine. Now, in models / item / custom_item.json, when you specify the json of this custom model for parent, how to draw it like a normal cube block? If my perception is correct, I first need to check if the model is a block or an item and generate a cubic item model. If this is correct 1. How to check if the block is being modeled or the item is being modeled now 2. Cube item model class I would like to know.
  8. This may be a terribly simple question, but how do you make sure that one BlockState and one BlockState are the same block? So, for example, where are the methods that return true if both BlockStates are oak_planks, one oak_planks and one white_wool false?
  9. Well, does that mean that the current code renders the north side 6 times and the south side 6 times? Should I pass side to buildQuad and call it only once?
  10. Thank you. I think this is the side argument of type Direction, but what does that mean, for example, side == Direction.NORTH?
  11. public class ConnectedTexturesModel implements IModelGeometry<ConnectedTexturesModel> { ConnectedTextures[] faces; public ConnectedTexturesModel(ConnectedTextures[] faces) { this.faces = faces; } @Override public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) { ExpansionMod.LOGGER.debug("baketexture"); return new BakedModel(faces, modelTransform); } @Override public Collection<RenderMaterial> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) { List<RenderMaterial> materials = new ArrayList<>(); for (ConnectedTextures face : faces) { switch (face.type) { case NORMAL: for (ResourceLocation texture : ((List<ResourceLocation>) face.contents)) { materials.add(new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, texture)); } break; case TILES: for (TilesConnection.Tile tile : ((List<TilesConnection.Tile>) face.contents)) { for (ResourceLocation texture : tile.textures) { materials.add(new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, texture)); } } break; //for (ConnectedTextures.Tiles tiles : ((List<ConnectedTextures.Tiles>) face.contents)) { //} } } return materials; } public static final class BakedModel implements IBakedModel { private IModelTransform modelTransform; ConnectedTextures[] faces; private List<TextureAtlasSprite> sprites; private static final ModelProperty<ConnectedTexturesModelData> CONNECTED_TEXTURES_DATA = new ModelProperty<>(); public BakedModel(ConnectedTextures[] faces, IModelTransform modelTransform) { this.faces = faces; this.modelTransform = modelTransform; sprites = new ArrayList<>( Arrays.asList( null, null, null, null, null, null //new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation("block/missing")).getSprite(), ) ); } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) { for (int i = 0; i < faces.length; i++) { ConnectedTextures face = faces[i]; switch (face.type) { case NORMAL: ResourceLocation texture = ((List<ResourceLocation>) face.contents).get(0); sprites.set(i, new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, texture).getSprite()); break; case TILES: ResourceLocation textureTile = ((List<TilesConnection.Tile>) face.contents).get(0).textures.get(0); sprites.set(i, new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, textureTile).getSprite()); break; //for (ConnectedTextures.Tiles tiles : ((List<ConnectedTextures.Tiles>) face.contents)) { //} } } if (extraData.hasProperty(CONNECTED_TEXTURES_DATA)) { ExpansionMod.LOGGER.debug(extraData.getData(CONNECTED_TEXTURES_DATA).pos + "extraPos"); } List<BakedQuad> quads = new ArrayList<>(); TextureAtlasSprite down = sprites.get(0); TextureAtlasSprite up = sprites.get(1); TextureAtlasSprite north = sprites.get(2); TextureAtlasSprite south = sprites.get(3); TextureAtlasSprite west = sprites.get(4); TextureAtlasSprite east = sprites.get(5); quads.add(buildQuad(Direction.NORTH, north, 1, 1, 0, north.getMinU(), north.getMinV(), 1, 0, 0, north.getMinU(), north.getMaxV(), 0, 0, 0, north.getMaxU(), north.getMaxV(), 0, 1, 0, north.getMaxU(), north.getMinV() )); quads.add(buildQuad(Direction.SOUTH, south, 0, 1, 1, south.getMinU(), south.getMinV(), 0, 0, 1, south.getMinU(), south.getMaxV(), 1, 0, 1, south.getMaxU(), south.getMaxV(), 1, 1, 1, south.getMaxU(), south.getMinV() )); return quads; } @Override public IModelData getModelData(@Nonnull IBlockDisplayReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) { if (tileData == EmptyModelData.INSTANCE) { tileData = new ModelDataMap.Builder().withProperty(CONNECTED_TEXTURES_DATA).build(); } tileData.setData(CONNECTED_TEXTURES_DATA, new ConnectedTexturesModelData(world, pos)); return tileData; } private BakedQuad buildQuad(Direction side, TextureAtlasSprite sprite, float x0, float y0, float z0, float u0, float v0, float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3) { BakedQuadBuilder builder = new BakedQuadBuilder(sprite); builder.setApplyDiffuseLighting(true); builder.setContractUVs(true); boolean hasTransform = this.modelTransform.getRotation().isIdentity(); IVertexConsumer consumer = hasTransform ? new TRSRTransformer(builder, this.modelTransform.getRotation()) : builder; builder.setQuadOrientation(side); putVertex(consumer, side, x0, y0, z0, u0, v0); putVertex(consumer, side, x1, y1, z1, u1, v1); putVertex(consumer, side, x2, y2, z2, u2, v2); putVertex(consumer, side, x3, y3, z3, u3, v3); return builder.build(); } private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v) { ImmutableList<VertexFormatElement> elements = consumer.getVertexFormat().getElements(); for (int e = 0; e <= elements.size() - 1; e++) { VertexFormatElement element = elements.get(e); switch (element.getUsage()) { case POSITION: consumer.put(e, x, y, z, 1.0f); break; case COLOR: consumer.put(e, 1.0f, 1.0f, 1.0f, 1.0f); break; case NORMAL: float offX = (float) side.getXOffset(); float offY = (float) side.getYOffset(); float offZ = (float) side.getZOffset(); consumer.put(e, offX, offY, offZ, 0.0f); break; case UV: if (element.getIndex() == 0) { consumer.put(e, u, v, 0f, 1f); break; } default: consumer.put(e); break; } } } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { throw new AssertionError("IBakedModel::getQuads should never be called, only IForgeBakedModel::getQuads"); } @Override public boolean isAmbientOcclusion() { return true; } @Override public boolean isGui3d() { return true; } @Override public boolean isSideLit() { return false; } @Override public boolean isBuiltInRenderer() { return false; } @Override public TextureAtlasSprite getParticleTexture() { return sprites.get(2); } @Override public ItemOverrideList getOverrides() { return null; } } public static class Loader implements IModelLoader<ConnectedTexturesModel> { public static Loader INSTANCE = new Loader(); @Override public void onResourceManagerReload(IResourceManager resourceManager) { } @Override public ConnectedTexturesModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) { //List<ConnectedTextures> faces = new ArrayList<>(); ConnectedTextures[] faces = new ConnectedTextures[6]; if (modelContents.has("faces")) { JsonObject facesJson = modelContents.get("faces").getAsJsonObject(); if (facesJson.has("all")) { for (int i = 0; i < Direction.values().length; i++) { faces[i] = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("all"), ConnectedTextures.class); } } if (facesJson.has("end")) { for (int i = 0; i < 2; i++) { faces[i] = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("end"), ConnectedTextures.class); } } if (facesJson.has("side")) { for (int i = 2; i < 6; i++) { faces[i] = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get("side"), ConnectedTextures.class); } } for (Direction face : Direction.values()) { if (modelContents.has(face.toString())) { faces[face.getIndex()] = ExpansionModModelLoaderRegistry.ExpandedBlockModelDeserializer.INSTANCE.fromJson(facesJson.get(face.toString()), ConnectedTextures.class); } } } return new ConnectedTexturesModel(faces); } } } In the above code, the sprite of the surface in contact with other blocks is drawn like the image. How can I prevent this from being drawn? Also, although not directly related to that, is there a way to get from the blockstate whether a sprite of a particular face is drawn (in contact with another block) or the sprite itself?
  12. In ConnectedTextureMod, it seems that you can change the texture by texture.png.mcmeta (similar to defining animation). If you dig deeper into the code, it looks like TextureStitchEvent.Pre is reading the metadata, but I'm not sure what's really going on.
  13. Although it is not the purpose, I tried to use the mcmeta file instead of modelJSON by referring to ConnectedTexturesMod to organize the code, but even if I go back to Loader etc., it seems that I am using modelJSON only. Don't know where the code you're reading from mcmeta is ...? https://github.com/Chisel-Team/ConnectedTexturesMod
  14. Thank you. I'll give it a try. If it doesn't work, I may ask you another question.
  15. When the north faces of multiple blocks are connected, the shape will be a rectangle of up to 3x3, and the texture will be pasted according to the shape. At this time, since it is necessary to indicate the position of the north surface of one block in the rectangular parallelepiped, there are two types of properties, the size (CT_SHAPE_NORTH) and the position (CT_LOC_NORTH) of the rectangle to which the surface of the block belongs. there is. The same applies to the remaining three sides.
  16. In IBakedMode#getQuads, I want to check if there are blocks of the same type on the top, bottom, left and right, and replace the texture of the model accordingly. To do this, I first need to get the coordinates of the block.
  17. I can add a TileEntity, but I don't know how to get it with IBakedModel # getQuads. Looking at various vanilla codes, it seems that you can get the TileEntity if you know the coordinates, but I don't know how to get the coordinates. Or, I want to create a Connecting Texture after all, so I can use IBakedModel # getQuads to get the top, bottom, left, and right blocks without using TileEntity. After all, it's the same as the problem with TileEntity. So how do you get the coordinates with IBakedModel # getQuads?
  18. understood. I will try TileEntity.
  19. public class HalfTimberBlock extends Block { public static final EnumProperty<TimberType> TIMBER_NORTH = ExpansionModBlockStateProperties.TIMBER_TYPE_NORTH; public static final EnumProperty<TimberType> TIMBER_SOUTH = ExpansionModBlockStateProperties.TIMBER_TYPE_SOUTH; public static final EnumProperty<TimberType> TIMBER_WEST = ExpansionModBlockStateProperties.TIMBER_TYPE_WEST; public static final EnumProperty<TimberType> TIMBER_EAST = ExpansionModBlockStateProperties.TIMBER_TYPE_EAST; public static final EnumProperty<Combination3x3> CT_SHAPE_NORTH = ExpansionModBlockStateProperties.CT_SHAPE_3x3_NORTH; public static final EnumProperty<Combination3x3> CT_SHAPE_SOUTH = ExpansionModBlockStateProperties.CT_SHAPE_3x3_SOUTH; public static final EnumProperty<Combination3x3> CT_SHAPE_WEST = ExpansionModBlockStateProperties.CT_SHAPE_3x3_WEST; public static final EnumProperty<Combination3x3> CT_SHAPE_EAST = ExpansionModBlockStateProperties.CT_SHAPE_3x3_EAST; public static final EnumProperty<Combination3x3> CT_LOC_NORTH = ExpansionModBlockStateProperties.CT_LOC_3x3_NORTH; public static final EnumProperty<Combination3x3> CT_LOC_SOUTH = ExpansionModBlockStateProperties.CT_LOC_3x3_SOUTH; public static final EnumProperty<Combination3x3> CT_LOC_WEST = ExpansionModBlockStateProperties.CT_LOC_3x3_WEST; public static final EnumProperty<Combination3x3> CT_LOC_EAST = ExpansionModBlockStateProperties.CT_LOC_3x3_EAST; public HalfTimberBlock(Properties properties) { super(properties); this.setDefaultState(this.stateContainer.getBaseState() .with(TIMBER_NORTH, TimberType.CROSS) .with(TIMBER_SOUTH, TimberType.NONE) .with(TIMBER_WEST, TimberType.LEFT) .with(TIMBER_EAST, TimberType.RIGHT) .with(CT_SHAPE_NORTH, Combination3x3.COMBINATION1x1) .with(CT_SHAPE_SOUTH, Combination3x3.COMBINATION1x1) .with(CT_SHAPE_WEST, Combination3x3.COMBINATION1x1) .with(CT_SHAPE_EAST, Combination3x3.COMBINATION1x1) .with(CT_LOC_NORTH, Combination3x3.COMBINATION1x1) .with(CT_LOC_SOUTH, Combination3x3.COMBINATION1x1) .with(CT_LOC_WEST, Combination3x3.COMBINATION1x1) .with(CT_LOC_EAST, Combination3x3.COMBINATION1x1) ); } @Override public BlockState getStateForPlacement(BlockItemUseContext context) { int rotation = MathHelper.floor((double)(context.getPlacementYaw() * 8.0F / 360.0F) + 0.5D) & 7; TimberType[] rotations = new TimberType[4]; switch (rotation % 2) { case 0: int index0 = rotation / 2; ExpansionMod.LOGGER.debug(rotation); ExpansionMod.LOGGER.debug(index0); rotations[index0] = TimberType.CROSS; index0 ++; if (index0 == 4) index0 = 0; rotations[index0] = TimberType.RIGHT; index0 ++; if (index0 == 4) index0 = 0; rotations[index0] = TimberType.NONE; index0 ++; if (index0 == 4) index0 = 0; rotations[index0] = TimberType.LEFT; break; case 1: int index1 = (rotation + 1) / 2; if (index1 == 4) index1 = 0; rotations[index1] = TimberType.LEFT; index1 ++; if (index1 == 4) index1 = 0; rotations[index1] = TimberType.LEFT; index1 ++; if (index1 == 4) index1 = 0; rotations[index1] = TimberType.RIGHT; index1 ++; if (index1 == 4) index1 = 0; rotations[index1] = TimberType.RIGHT; break; } return this.getDefaultState() .with(TIMBER_NORTH, rotations[0]) .with(TIMBER_SOUTH, rotations[2]) .with(TIMBER_WEST, rotations[3]) .with(TIMBER_EAST, rotations[1]); } @Override protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) { builder.add( TIMBER_NORTH, TIMBER_SOUTH, TIMBER_WEST, TIMBER_EAST, CT_SHAPE_NORTH, CT_SHAPE_SOUTH, CT_SHAPE_WEST, CT_SHAPE_EAST, CT_LOC_NORTH, CT_LOC_SOUTH, CT_LOC_WEST, CT_LOC_EAST ); } } public enum TimberType implements IStringSerializable { NONE("none"), RIGHT("right"), LEFT("left"), CROSS("cross"); private final String shapeName; TimberType(String shapeName) { this.shapeName = shapeName; } @Override public String toString() { return this.getString(); } @Override public String getString() { return this.shapeName; } } public enum Combination3x3 implements IStringSerializable { COMBINATION1x1("1x1"), COMBINATION1x2("1x2"), COMBINATION1x3("1x3"), COMBINATION2x1("2x1"), COMBINATION2x2("2x2"), COMBINATION2x3("2x3"), COMBINATION3x1("3x1"), COMBINATION3x2("3x2"), COMBINATION3x3("3x3"); private final String combinationName; Combination3x3(String combinationName) { this.combinationName = combinationName; } @Override public String toString() { return this.getString(); } @Override public String getString() { return this.combinationName; } } In the above code, when I start Minecraft, it becomes "no response" in the middle of loading, and loading does not end from there. Removing the Combination3x3 EnumProperty builder.add and setDefaultState (this.stateContainer.getBaseState (). With () works fine, but using the 8 Combination3x3 properties doesn't finish loading. What's in the error log? Was not displayed. What is happening? How can I fix it?
  20. Thank you! It was also possible to create a list of ResourceLocations when deserializing Json and register them one by one with TextureStitchEvent.Pre, but it was possible to realize it by recreating a list of RenderMaterials from all ResourceLocations with IModelGeometry # getTextures.
  21. Keep the question simple. How do I create a TextureAtlasSprite for a texture in assets/modid/textures/block/mod_block.png from the string "modid: block/mod_block"?
  22. After some research, I found that TextureStitchEvent.Pre should be linked to AtlasTexture.LOCATION_BLOCKS_TEXTURE, but I would like to use this Sprite as a dynamic texture in IBakedModel. In other words, is there a way to dynamically associate it with AtlasTexture.LOCATION_BLOCKS_TEXTURE, or any other way? I also looked at how vanilla reads "texture": "modid: block / mod_block", but as far as I can see, it's all tied to AtlasTexture.LOCATION_BLOCKS_TEXTURE, which is confusing.
  23. new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, "modid:block/mod_block").getSprite(); I want to create a Sprite with the above code, but it would be minecraft: block / missingno instead. Is there a way to use mod textures as sprite?
  24. public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData) { Collection<Property<?>> properties = state.getProperties(); List<BakedQuad> quads = new ArrayList<>(); for (Map.Entry<String, JsonElement> variantElements : variants.entrySet()) { //String JSONVariants = variantElement.getAsString(); String[] JSONProperties = variantElements.getKey().split(",", 0); for (String JSONProperty : JSONProperties) { String propertyName = JSONProperty.split("=", 2)[0]; Integer propertyValue = Integer.valueOf(JSONProperty.split("=", 2)[1]); for (Property<?> property : properties) { if (!property.getName().equalsIgnoreCase(propertyName) && state.get(property) == propertyValue) { TextureAtlasSprite sprite = new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation(/*variantElements.getValue().getAsJsonObject().get("top").getAsString()*/"block/oak_planks")).getSprite(); List<TextureAtlasSprite> sprites = new ArrayList<>(); ExpansionMod.LOGGER.debug(sprite.toString()); quads.add(buildQuad(Direction.NORTH, sprite, 1, 1, 0, sprite.getMinU(), sprite.getMinV(), 1, 0, 0, sprite.getMinU(), sprite.getMaxV(), 0, 0, 0, sprite.getMaxU(), sprite.getMaxV(), 0, 1, 0, sprite.getMaxU(), sprite.getMinV() )); quads.add(buildQuad(Direction.SOUTH, sprite, 0, 1, 1, sprite.getMinU(), sprite.getMinV(), 0, 0, 1, sprite.getMinU(), sprite.getMaxV(), 1, 0, 1, sprite.getMaxU(), sprite.getMaxV(), 1, 1, 1, sprite.getMaxU(), sprite.getMinV() )); } } } } ExpansionMod.LOGGER.debug(quads); return quads; } private BakedQuad buildQuad(Direction side, TextureAtlasSprite sprite, float x0, float y0, float z0, float u0, float v0, float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3) { BakedQuadBuilder builder = new BakedQuadBuilder(sprite); builder.setApplyDiffuseLighting(true); builder.setContractUVs(true); boolean hasTransform = this.modelTransform.getRotation().isIdentity(); IVertexConsumer consumer = hasTransform ? new TRSRTransformer(builder, this.modelTransform.getRotation()) : builder; builder.setQuadOrientation(side); putVertex(consumer, side, x0, y0, z0, u0, v0); putVertex(consumer, side, x1, y1, z1, u1, v1); putVertex(consumer, side, x2, y2, z2, u2, v2); putVertex(consumer, side, x3, y3, z3, u3, v3); return builder.build(); } private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v) { ImmutableList<VertexFormatElement> elements = consumer.getVertexFormat().getElements(); for(int e = 0; e <= elements.size() - 1; e ++){ VertexFormatElement element = elements.get(e); switch(element.getUsage()){ case POSITION : consumer.put(e, x, y, z, 1.0f); break; case COLOR : consumer.put(e, 1.0f, 1.0f, 1.0f, 1.0f); break; case NORMAL : float offX = (float) side.getXOffset(); float offY = (float) side.getYOffset(); float offZ = (float) side.getZOffset(); consumer.put(e, offX, offY, offZ, 0.0f); break; case UV : if(element.getIndex() == 0){ consumer.put(e, u, v, 0f, 1f); break; } default : consumer.put(e); break; } } } With the above code, I'm trying to model the block on the right side of the image. The block on the left is oak_planks. As you can see, the custom model on the right has a single color and no shade. How can I shade this model?
  25. public class VariantsTextureModel implements IModelGeometry<VariantsTextureModel> { private JsonObject variants; public VariantsTextureModel(JsonObject variants) { this.variants = variants; } @Override public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) { return new BakedModel(variants, modelTransform); } @Override public Collection<RenderMaterial> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) { return Collections.emptyList(); } public static final class BakedModel implements IBakedModel { private JsonObject variants; IModelTransform modelTransform; public BakedModel(JsonObject variants, IModelTransform modelTransform) { this.variants = variants; this.modelTransform = modelTransform; } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData) { Collection<Property<?>> properties = state.getProperties(); List<BakedQuad> quads = new ArrayList<>(); for (Map.Entry<String, JsonElement> variantElements : variants.entrySet()) { //String JSONVariants = variantElement.getAsString(); String[] JSONProperties = variantElements.getKey().split(",", 0); for (String JSONProperty : JSONProperties) { String propertyName = JSONProperty.split("=", 2)[0]; Integer propertyValue = Integer.valueOf(JSONProperty.split("=", 2)[1]); for (Property<?> property : properties) { if (!property.getName().equalsIgnoreCase(propertyName) && state.get(property) == propertyValue) { TextureAtlasSprite sprite = new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation(/*variantElements.getValue().getAsJsonObject().get("top").getAsString()*/"block/oak_planks")).getSprite(); List<TextureAtlasSprite> sprites = new ArrayList<>(); ExpansionMod.LOGGER.debug(sprite.toString()); quads.add(buildQuad(Direction.NORTH, sprite, 0, 0, 0, sprite.getMinU(), sprite.getMaxV(), 0, 1, 0, sprite.getMinU(), sprite.getMinV(), 1, 1, 0, sprite.getMaxU(), sprite.getMinV(), 1, 0, 0, sprite.getMaxU(), sprite.getMaxV() )); quads.add(buildQuad(Direction.SOUTH, sprite, 0, 0, 1, sprite.getMinU(), sprite.getMaxV(), 0, 1, 1, sprite.getMinU(), sprite.getMinV(), 1, 1, 1, sprite.getMaxU(), sprite.getMinV(), 1, 0, 1, sprite.getMaxU(), sprite.getMaxV() )); } } } } ExpansionMod.LOGGER.debug(quads); return quads; } @Override public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) { throw new AssertionError("IBakedModel::getQuads should never be called, only IForgeBakedModel::getQuads"); } private BakedQuad buildQuad(Direction side, TextureAtlasSprite sprite, float x0, float y0, float z0, float u0, float v0, float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3) { BakedQuadBuilder builder = new BakedQuadBuilder(sprite); boolean hasTransform = this.modelTransform.getRotation().isIdentity(); IVertexConsumer consumer = hasTransform ? new TRSRTransformer(builder, this.modelTransform.getRotation()) : builder; builder.setQuadOrientation(side); putVertex(consumer, side, x0, y0, z0, u0, v0); putVertex(consumer, side, x1, y1, z1, u1, v1); putVertex(consumer, side, x2, y2, z2, u2, v2); putVertex(consumer, side, x3, y3, z3, u3, v3); return builder.build(); } private static void putVertex(IVertexConsumer consumer, Direction side, float x, float y, float z, float u, float v) { ImmutableList<VertexFormatElement> elements = consumer.getVertexFormat().getElements(); for(int e = 0; e <= elements.size() - 1; e ++){ VertexFormatElement element = elements.get(e); switch(element.getUsage()){ case POSITION : consumer.put(e, x, y, z, 1.0f); break; case COLOR : consumer.put(e, 1.0f, 1.0f, 1.0f, 1.0f); break; case NORMAL : float offX = (float) side.getXOffset(); float offY = (float) side.getYOffset(); float offZ = (float) side.getZOffset(); consumer.put(e, offX, offY, offZ, 0.0f); break; case UV : if(element.getIndex() == 0){ consumer.put(e, u, v, 0f, 1f); break; } default : consumer.put(e); break; } } } @Override public boolean isAmbientOcclusion() { return false; } @Override public boolean isGui3d() { return false; } @Override public boolean isSideLit() { return false; } @Override public boolean isBuiltInRenderer() { return false; } @Override public TextureAtlasSprite getParticleTexture() { return null; } @Override public ItemOverrideList getOverrides() { return null; } } public static class Loader implements IModelLoader<VariantsTextureModel> { public static final Loader INSTANCE = new Loader(); @Override public void onResourceManagerReload(IResourceManager resourceManager) { } @Override public VariantsTextureModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) { JsonObject variants = new JsonObject(); if (modelContents.has("variants")) { variants = modelContents.get("variants").getAsJsonObject(); } return new VariantsTextureModel(variants); } } } Good news! I looked up various vanilla code, existing mod code, etc. and managed to code to this state. However, at present, both the north and south sides are displayed facing north when viewed from the north side, and both sides are not displayed when viewed from the south side. In other words, the south side is not behaving correctly. In the code above, `quads.add (buildQuad (Direction.SOUTH, sprite, sprite, 0, 0, 1, sprite.getMinU (), sprite.getMaxV (), 0, 1, 1, sprite.getMinU (), sprite.getMinV (), 1, 1, 1, sprite.getMaxU (), sprite.getMinV (), 1, 0, 1, sprite.getMaxU (), sprite.getMaxV () ));` Which value should be changed to render correctly?
×
×
  • Create New...

Important Information

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