diff --git a/PALAMOD_CDC.md b/PALAMOD_CDC.md index 9d45c0b..cc406da 100644 --- a/PALAMOD_CDC.md +++ b/PALAMOD_CDC.md @@ -557,6 +557,12 @@ avant M4 (TODO:crafts-machines). 20F/5C/1B/1L recalcules, 4 rotations, lave source exigee) + diagnostic clic droit sur le coeur. GUI + tetes + modifieurs : M-grinder-3. VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED : orientation exacte du B (tableau wiki ambigu). +- M-grinder-3 LIVRE 2026-10-19 ~03:20 : BE dediee PalaGrinderBlockEntity (inventaire 9 slots, + jauge fuel 0-100 en lingots paladium, persistee) + GUI DispenserMenu + coeur avec ticker + + diagnostic deplace dans useWithoutItem (le callback UseBlockCallback ne doit pas renvoyer + SUCCESS sinon la GUI ne s'ouvre pas — lecon). Tetes + modifieurs : M-grinder-4 (pas de + textures legacy pour les tetes). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. + UNVERIFIED en jeu (GUI + fuel). - Client/mod : boucle visuelle OPERATIONNELLE 2026-10-19 (Xvfb :99 + runClient SDL x11 + captures Java Robot + pilotage xdotool + vision_analyze) : menu, Select World, monde New World (creatif, cheats), /give, pose de bloc, inventaire, F3+T. Screens : scratch vis*.png. diff --git a/mods/pala/src/main/java/fr/surviepote/pala/PalaBlockEntities.java b/mods/pala/src/main/java/fr/surviepote/pala/PalaBlockEntities.java index c146029..39cd717 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/PalaBlockEntities.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/PalaBlockEntities.java @@ -1,5 +1,6 @@ package fr.surviepote.pala; +import fr.surviepote.pala.machine.PalaGrinderBlockEntity; import fr.surviepote.pala.machine.PalaMachineBlockEntity; import java.util.Set; import net.minecraft.core.Registry; @@ -14,11 +15,16 @@ public final class PalaBlockEntities { } public static BlockEntityType MACHINE; + public static BlockEntityType GRINDER; public static void register() { MACHINE = Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, Identifier.fromNamespaceAndPath("pala", "machine"), new BlockEntityType<>(PalaMachineBlockEntity::new, Set.of(PalaBlocks.PALADIUM_CRUSHER, PalaBlocks.PALADIUM_FURNACE))); + GRINDER = Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, + Identifier.fromNamespaceAndPath("pala", "grinder"), + new BlockEntityType<>(PalaGrinderBlockEntity::new, + Set.of(PalaBlocks.GRINDER_BLOCK))); } } diff --git a/mods/pala/src/main/java/fr/surviepote/pala/PalaBlocks.java b/mods/pala/src/main/java/fr/surviepote/pala/PalaBlocks.java index 854afb9..014587d 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/PalaBlocks.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/PalaBlocks.java @@ -1,5 +1,6 @@ package fr.surviepote.pala; +import fr.surviepote.pala.machine.PalaGrinderBlock; import fr.surviepote.pala.machine.PalaMachineBlock; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; @@ -34,8 +35,8 @@ public final class PalaBlocks { public static final Block AMETHYST_ORE = register("amethyst_ore", new Block(BlockBehaviour.Properties.of().setId(blockId("amethyst_ore")).strength(3.0F, 5.0F).sound(SoundType.STONE).requiresCorrectToolForDrops())); public static final Block AMETHYST_ORE_BLOCK = register("amethyst_ore_block", new Block(BlockBehaviour.Properties.of().setId(blockId("amethyst_ore_block")).strength(5.0F, 8.0F).sound(SoundType.METAL).requiresCorrectToolForDrops())); // M-grinder-1 (wiki grinder §2) : 1 block + 5 casing + 20 frame + 1 lave (26 blocs). - // Crafts M-grinder-2 ; multibloc + GUI M-grinder-2/3. - public static final Block GRINDER_BLOCK = register("grinder_block", new Block(BlockBehaviour.Properties.of().setId(blockId("grinder_block")).strength(5.0F, 10.0F).sound(SoundType.METAL).requiresCorrectToolForDrops())); + // M-grinder-3 : coeur avec BE + GUI (PalaGrinderBlock). + public static final Block GRINDER_BLOCK = register("grinder_block", new PalaGrinderBlock(BlockBehaviour.Properties.of().setId(blockId("grinder_block")).strength(5.0F, 10.0F).sound(SoundType.METAL).requiresCorrectToolForDrops())); public static final Block GRINDER_CASING = register("grinder_casing", new Block(BlockBehaviour.Properties.of().setId(blockId("grinder_casing")).strength(5.0F, 10.0F).sound(SoundType.METAL).requiresCorrectToolForDrops())); public static final Block GRINDER_FRAME = register("grinder_frame", new Block(BlockBehaviour.Properties.of().setId(blockId("grinder_frame")).strength(5.0F, 10.0F).sound(SoundType.METAL).requiresCorrectToolForDrops())); public static final Block AMETHYST_SPIKE = register("amethyst_spike", new Block(BlockBehaviour.Properties.of().setId(blockId("amethyst_spike")).strength(1.0F, 10.0F).sound(SoundType.GRAVEL))); diff --git a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaItemUseEvents.java b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaItemUseEvents.java index 80c4b4e..ffc7e29 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaItemUseEvents.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaItemUseEvents.java @@ -26,7 +26,6 @@ import net.fabricmc.fabric.api.event.player.UseItemCallback; import fr.surviepote.pala.PalaBlocks; import fr.surviepote.pala.PalaItems; -import fr.surviepote.pala.machine.PalaGrinder; // Portage des procedures "clic droit" MCreator : // - batons : ProcedureHealStick/ HyperJumpStick/ SpeedStick/ StickOfGod/ StrenghStickRightClickedInAir @@ -138,15 +137,10 @@ public final class PalaItemUseEvents { ItemStack stack = player.getItemInHand(hand); Item item = stack.isEmpty() ? null : stack.getItem(); - // --- Grinder : clic droit sur le coeur -> etat du multibloc (M-grinder-2). - // GUI + crafts en M-grinder-3 ; ici diagnostic seul (ne casse rien). - if (target.getBlock() == PalaBlocks.GRINDER_BLOCK) { - boolean formed = PalaGrinder.isFormed(sl, pos); - sp.sendSystemMessage(net.minecraft.network.chat.Component.literal(formed - ? "§6[Grinder] §aStructure complete (20 frames, 5 casings, lave)." - : "§6[Grinder] §cStructure incomplete (attendu : 3x3x3, voir wiki).")); - return InteractionResult.SUCCESS; - } + // --- Grinder : le coeur (PalaGrinderBlock) gere lui-meme le clic droit + // (diagnostic PalaGrinder.isFormed + ouverture GUI). Rien a faire ici : PASS + // pour laisser useWithoutItem du bloc s'executer (un SUCCESS du callback + // annulerait l'ouverture de la GUI). // --- Semis sur farmland (graine en main, dessus libre) --- if (target.getBlock() == Blocks.FARMLAND && item != null) { diff --git a/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlock.java b/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlock.java new file mode 100644 index 0000000..0c7a556 --- /dev/null +++ b/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlock.java @@ -0,0 +1,59 @@ +package fr.surviepote.pala.machine; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +// M-grinder-3 : bloc coeur du multibloc (avec BE persistee + GUI). Le diagnostic de +// structure (PalaGrinder.isFormed via UseBlockCallback) reste actif en parallele : +// clic droit = message d'etat + ouverture GUI. +public class PalaGrinderBlock extends Block implements EntityBlock { + + public PalaGrinderBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new PalaGrinderBlockEntity(pos, state); + } + + @Override + @SuppressWarnings("unchecked") + public BlockEntityTicker getTicker(Level level, BlockState state, + BlockEntityType type) { + if (level instanceof net.minecraft.server.level.ServerLevel) { + return (lvl, pos, blockState, blockEntity) -> { + if (blockEntity instanceof PalaGrinderBlockEntity grinder) { + grinder.serverTick(); + } + }; + } + return null; + } + + @Override + protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, + Player player, BlockHitResult hit) { + if (!level.isClientSide() && level.getBlockEntity(pos) instanceof MenuProvider provider) { + if (player instanceof ServerPlayer sp + && !PalaGrinder.isFormed((net.minecraft.server.level.ServerLevel) level, pos)) { + sp.sendSystemMessage(Component.literal( + "§6[Grinder] §7Structure incomplete : la forge ne fonctionnera pas.")); + } + player.openMenu(provider); + } + return InteractionResult.SUCCESS; + } +} diff --git a/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlockEntity.java b/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlockEntity.java new file mode 100644 index 0000000..ecaf190 --- /dev/null +++ b/mods/pala/src/main/java/fr/surviepote/pala/machine/PalaGrinderBlockEntity.java @@ -0,0 +1,85 @@ +package fr.surviepote.pala.machine; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.DispenserMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; + +import fr.surviepote.pala.PalaBlockEntities; +import fr.surviepote.pala.PalaItems; + +// M-grinder-3 (wiki grinder §3) : block entity du coeur. GUI = menu vanilla Dispenser +// (9 slots, utilises : 0 socket, 1 pattern, 2 combustible, 3 sortie ; 4-8 reserves pour +// l'assemblage tete+stick en M-grinder-4). +// Jauge 0-100 alimentee en lingots paladium (1 lingot = +10, UNVERIFIED : wiki dit "6 +// paladium minimum pour une tete" sans echelle de jauge). Tetes + modifieurs en +// M-grinder-4 (pas de textures legacy pour les tetes : aucun placeholder cree). +public class PalaGrinderBlockEntity extends BlockEntity implements MenuProvider { + + private static final int FUEL_PER_INGOT = 10; + private static final int FUEL_COOLDOWN_TICKS = 20; + + private final SimpleContainer inventory = new SimpleContainer(9); + private int fuel; + private int fuelCooldown; + + public PalaGrinderBlockEntity(BlockPos pos, BlockState state) { + super(PalaBlockEntities.GRINDER, pos, state); + } + + public int fuel() { + return fuel; + } + + public void serverTick() { + boolean changed = false; + if (fuelCooldown > 0) { + fuelCooldown--; + changed = true; + } else if (fuel < 100) { + ItemStack combustible = inventory.getItem(2); + if (!combustible.isEmpty() && combustible.is(PalaItems.PALADIUM_INGOT)) { + combustible.shrink(1); + fuel = Math.min(100, fuel + FUEL_PER_INGOT); + fuelCooldown = FUEL_COOLDOWN_TICKS; + changed = true; + } + } + if (changed) { + setChanged(); + } + } + + @Override + protected void saveAdditional(ValueOutput output) { + super.saveAdditional(output); + inventory.storeAsItemList(output.list("Items", ItemStack.CODEC)); + output.putInt("Fuel", fuel); + } + + @Override + protected void loadAdditional(ValueInput input) { + super.loadAdditional(input); + inventory.fromItemList(input.listOrEmpty("Items", ItemStack.CODEC)); + fuel = input.getIntOr("Fuel", 0); + } + + @Override + public Component getDisplayName() { + return Component.literal("Grinder (" + fuel + "/100)"); + } + + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + return new DispenserMenu(containerId, playerInventory, inventory); + } +} diff --git a/server/mods/pala-0.2.1.jar b/server/mods/pala-0.2.1.jar index 9f83e46..5229238 100644 Binary files a/server/mods/pala-0.2.1.jar and b/server/mods/pala-0.2.1.jar differ