pala M-grinder-2: detecteur multibloc 3x3x3 + diagnostic clic droit

This commit is contained in:
Anaïs Saraiva
2026-10-19 03:14:31 +02:00
parent be6c0306e3
commit 41f4ff8f0a
4 changed files with 111 additions and 0 deletions
@@ -26,6 +26,7 @@ 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
@@ -137,6 +138,16 @@ 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;
}
// --- Semis sur farmland (graine en main, dessus libre) ---
if (target.getBlock() == Blocks.FARMLAND && item != null) {
Block crop = null;
@@ -0,0 +1,96 @@
package fr.surviepote.pala.machine;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Block;
import fr.surviepote.pala.PalaBlocks;
// M-grinder-2 (wiki grinder §2) : detection du multibloc 3x3x3 (20 frame + 5 casing +
// 1 block + 1 lave = 26 blocs + lave).
//
// Structure (totaux wiki VERIFIES par comptage : 8F+1C par couche haute/basse, 4F+3C+1B+1L
// au milieu) :
// couche -1 et +1 : F F F / F C F / F F F
// couche 0 : F C F / C L C / F B F (B = face sud en rotation 0)
// Le B peut etre sur n'importe quelle face horizontale : 4 rotations testees.
// UNVERIFIED : orientation exacte du B et ordre des couches (tableau wiki ambigu) —
// a confirmer en jeu (M-grinder-3). La detection ne casse rien si KO (message seulement).
public final class PalaGrinder {
private PalaGrinder() {
}
// (dx, dy, dz, attendu) en rotation 0. Attendu : 'F' frame, 'C' casing, 'B' block, 'L' lave.
private static final Object[][] CELLS = cells();
private static Object[][] cells() {
java.util.List<Object[]> list = new java.util.ArrayList<>();
// Couches -1 et +1 : frame partout sauf casing au centre.
for (int dy : new int[]{-1, 1}) {
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
char expect = (dx == 0 && dz == 0) ? 'C' : 'F';
list.add(new Object[]{dx, dy, dz, expect});
}
}
}
// Couche 0 : coins F, aretes N/S/E = C, arete sud = B, centre = L.
list.add(new Object[]{-1, 0, -1, 'F'});
list.add(new Object[]{0, 0, -1, 'C'});
list.add(new Object[]{1, 0, -1, 'F'});
list.add(new Object[]{-1, 0, 0, 'C'});
list.add(new Object[]{0, 0, 0, 'L'});
list.add(new Object[]{1, 0, 0, 'C'});
list.add(new Object[]{-1, 0, 1, 'F'});
list.add(new Object[]{0, 0, 1, 'B'});
list.add(new Object[]{1, 0, 1, 'F'});
return list.toArray(new Object[0][]);
}
// Rotation 0-3 autour de Y : (x, z) -> (z, -x) applique r fois.
private static int[] rot(int x, int z, int r) {
for (int i = 0; i < r; i++) {
int nx = z;
int nz = -x;
x = nx;
z = nz;
}
return new int[]{x, z};
}
private static boolean match(ServerLevel level, BlockPos origin, int r) {
for (Object[] cell : CELLS) {
int[] xz = rot((int) cell[0], (int) cell[2], r);
BlockPos pos = origin.offset(xz[0], (int) cell[1], xz[1]);
char expect = (char) cell[3];
if (expect == 'L') {
if (!(level.getFluidState(pos).is(FluidTags.LAVA)
&& level.getFluidState(pos).isSource())) {
return false;
}
continue;
}
Block want = expect == 'F' ? PalaBlocks.GRINDER_FRAME
: expect == 'C' ? PalaBlocks.GRINDER_CASING : PalaBlocks.GRINDER_BLOCK;
if (level.getBlockState(pos).getBlock() != want) {
return false;
}
}
return true;
}
/** Vrai si le GRINDER_BLOCK en origin est le coeur d'un multibloc forme (4 rotations). */
public static boolean isFormed(ServerLevel level, BlockPos origin) {
if (level.getBlockState(origin).getBlock() != PalaBlocks.GRINDER_BLOCK) {
return false;
}
for (int r = 0; r < 4; r++) {
if (match(level, origin, r)) {
return true;
}
}
return false;
}
}