pala M3: crusher fidele legacy (fruits/luck/auto-generate) + furnace mixed fuels + gate fermier 8

This commit is contained in:
Anaïs Saraiva
2026-10-18 23:54:37 +02:00
parent 3330b5bd04
commit 610dc597fb
4 changed files with 103 additions and 15 deletions
@@ -1,7 +1,9 @@
package fr.surviepote.pala.machine;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Player;
@@ -16,6 +18,9 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.core.PalaJobs;
// Blocs machines Pala (PaladiumCrusherGUI / PaladiumFurnaceGUI, type 1 = lies au bloc).
// Minimum fonctionnel : bloc + block entity + inventaire 9 slots expose via
// le menu vanilla Dispenser (3x3, slots 0/1 entree+combustible, slot 2 sortie,
@@ -49,6 +54,14 @@ public class PalaMachineBlock extends Block implements EntityBlock {
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
// M3 (wiki crusher : "disponible a partir du niveau 8" fermier, VERIFIE).
if (!level.isClientSide() && state.is(PalaBlocks.PALADIUM_CRUSHER)
&& player instanceof ServerPlayer sp && PalaJobs.levelOf(sp, "fermier") < 8) {
sp.sendSystemMessage(Component.literal(
"§cCrusher verrouille : fermier niveau 8 requis (actuel : "
+ PalaJobs.levelOf(sp, "fermier") + ")."));
return InteractionResult.FAIL;
}
if (!level.isClientSide() && level.getBlockEntity(pos) instanceof MenuProvider provider) {
player.openMenu(provider);
}
@@ -1,5 +1,7 @@
package fr.surviepote.pala.machine;
import java.util.Map;
import fr.surviepote.pala.PalaBlockEntities;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.PalaItems;
@@ -11,6 +13,7 @@ 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.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -19,16 +22,37 @@ import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
// Block entity partagee crusher/furnace. Inventaire 9 slots (menu vanilla
// Dispenser 3x3) : slot 0 = entree, slot 1 = combustible (charbon),
// slot 2 = sortie. Cuisson : minerai de paladium -> lingot (le crusher
// cuit 2x plus vite, a la place du bouton Generate du legacy : TODO).
// Dispenser 3x3) : slot 0 = entree, slot 1 = combustible, slot 2 = sortie.
//
// M3 — crusher fidele au legacy (ProcedurePaladiumCrusherUpdateTick +
// ProcedurePaladiumCrusherGenerateButton, legacy-src-backup) :
// - slot 0 = fruit (eggplant->amethyste, okami->titane, kiwano->paladium,
// orange_blue->nugget endium). Le wiki actuel cite "chervil"->titane ; les
// textures chervil* sont deja utilisees par okami (fruit+seeds) et aucun
// asset okami* n'existe => equivalence chervil==okami (TODO:chervil, a
// confirmer visuellement, pas de doublon cree) ;
// - slot 1 = mixed coal (legacy : pala+creative ; wiki actuel : aussi gold,
// amethyste, titane => les 4 + creative). Creative = infini (legacy) ;
// sinon 20 % de consommer 1/tick (legacy) ;
// - "luck" += 1/128 par tick (legacy 0.0078125), gate luck < 1 ;
// - auto-generate a luck >= 1 (legacy : bouton manuel a proba luck ; a luck=1
// le succes est certain => meme resultat sans GUI custom ; ECART documente) ;
// - le crusher NE cuit plus de minerais (legacy+wiki : fruits uniquement).
// Furnace : minerais pala + combustible charbon vanilla ET mixed coals.
public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider {
private static final int COOK_TIME_FURNACE = 200;
private static final int COOK_TIME_CRUSHER = 100;
private static final double LUCK_PER_TICK = 1.0 / 128.0;
private static final Map<Item, Item> CRUSHER_RESULTS = Map.of(
PalaItems.EGG_PLANT_FRUIT, PalaItems.AMETHYST_INGOT,
PalaItems.OKAMI_FRUIT, PalaItems.TITANE_INGOT,
PalaItems.KIWANO, PalaItems.PALADIUM_INGOT,
PalaItems.ORANGE_BLUE_FRUIT, PalaItems.ENDIUM_NUGGET);
private final SimpleContainer inventory = new SimpleContainer(9);
private int progress;
private double luck;
public PalaMachineBlockEntity(BlockPos pos, BlockState state) {
super(PalaBlockEntities.MACHINE, pos, state);
@@ -39,17 +63,52 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
}
public void serverTick() {
if (isCrusher()) {
crusherTick();
} else {
furnaceTick();
}
}
private void crusherTick() {
ItemStack fruit = inventory.getItem(0);
ItemStack fuel = inventory.getItem(1);
ItemStack output = inventory.getItem(2);
Item result = CRUSHER_RESULTS.get(fruit.getItem());
if (result == null || luck >= 1.0 || !isMixedFuel(fuel)) {
return;
}
boolean infinite = fuel.is(PalaItems.CREATIVE_MIXED_COAL);
if (output.isEmpty() || (output.is(result)
&& output.getCount() + 1 <= output.getMaxStackSize())) {
fruit.shrink(1);
if (!infinite && Math.random() < 0.2) {
fuel.shrink(1);
}
luck = Math.min(1.0, luck + LUCK_PER_TICK);
if (luck >= 1.0) {
if (output.isEmpty()) {
inventory.setItem(2, new ItemStack(result));
} else {
output.grow(1);
}
luck = 0.0;
}
setChanged();
}
}
private void furnaceTick() {
ItemStack input = inventory.getItem(0);
ItemStack fuel = inventory.getItem(1);
ItemStack output = inventory.getItem(2);
ItemStack result = smeltResult(input);
boolean canCook = !result.isEmpty() && isFuel(fuel)
boolean canCook = !result.isEmpty() && isFurnaceFuel(fuel)
&& (output.isEmpty() || (ItemStack.isSameItemSameComponents(output, result)
&& output.getCount() + result.getCount() <= output.getMaxStackSize()));
if (canCook) {
progress++;
int target = isCrusher() ? COOK_TIME_CRUSHER : COOK_TIME_FURNACE;
if (progress >= target) {
if (progress >= COOK_TIME_FURNACE) {
progress = 0;
input.shrink(1);
fuel.shrink(1);
@@ -76,8 +135,14 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
return ItemStack.EMPTY;
}
private static boolean isFuel(ItemStack stack) {
return stack.is(Items.COAL) || stack.is(Items.CHARCOAL);
private static boolean isMixedFuel(ItemStack stack) {
return stack.is(PalaItems.PALA_MIXED_COAL) || stack.is(PalaItems.CREATIVE_MIXED_COAL)
|| stack.is(PalaItems.AMETHYST_MIXED_COAL) || stack.is(PalaItems.TITANE_MIXED_COAL)
|| stack.is(PalaItems.GOLD_MIXED_COAL);
}
private static boolean isFurnaceFuel(ItemStack stack) {
return stack.is(Items.COAL) || stack.is(Items.CHARCOAL) || isMixedFuel(stack);
}
@Override
@@ -85,6 +150,7 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
super.saveAdditional(output);
inventory.storeAsItemList(output.list("Items", ItemStack.CODEC));
output.putInt("Progress", progress);
output.putDouble("Luck", luck);
}
@Override
@@ -92,6 +158,7 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
super.loadAdditional(input);
inventory.fromItemList(input.listOrEmpty("Items", ItemStack.CODEC));
progress = input.getIntOr("Progress", 0);
luck = input.getDoubleOr("Luck", 0.0);
}
@Override