pala M-xpcurve: seuils XP wiki + XP broyer crusher + gate silk-touch

This commit is contained in:
Anaïs Saraiva
2026-10-19 03:38:25 +02:00
parent 52c3229684
commit 0e97130479
5 changed files with 82 additions and 7 deletions
+6
View File
@@ -581,6 +581,12 @@ avant M4 (TODO:crafts-machines).
existants (findium, amethyste, graines, pepite endium). ECART : lots speciaux inexistants existants (findium, amethyste, graines, pepite endium). ECART : lots speciaux inexistants
(voidstone, excavatrices...) => TODO:recompenses-items. + furnaceSmelts completee (6 minerais). (voidstone, excavatrices...) => TODO:recompenses-items. + furnaceSmelts completee (6 minerais).
VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu (level-up joueur). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu (level-up joueur).
- M-xpcurve LIVRE 2026-10-19 ~03:40 : seuils XP wiki VERIFIES (table mineur niv.2-20 :
22 123 a 2 594 953, points = milliers) en config data-driven + formule au-dela ; XP
"broyer" fermier au crusher (3/4.5/6, attribution dernier ouvreur, ECART documente) ;
pas d'XP au toucher de soie (wiki) ; hammerArea confirme sans XP (destroyBlock direct).
TODO:crusher-xp CLOS. VERIFIE : build SUCCESSFUL, boot Done, 0 erreur, 19 cles config.
UNVERIFIED en jeu.
- Client/mod : boucle visuelle OPERATIONNELLE 2026-10-19 (Xvfb :99 + runClient SDL x11 + - 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 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. (creatif, cheats), /give, pose de bloc, inventaire, F3+T. Screens : scratch vis*.png.
@@ -43,9 +43,20 @@ public final class PalaConfig {
Map.entry("pala:paladium_green_ore", 20.0), Map.entry("pala:trixium_ore", 10.0), Map.entry("pala:paladium_green_ore", 20.0), Map.entry("pala:trixium_ore", 10.0),
Map.entry("pala:findium_ore", 10.0))); Map.entry("pala:findium_ore", 10.0)));
// Courbe XP : cout du niveau n. UNVERIFIED (formule placeholder, a caler M5). // Courbe XP : seuils wiki VERIFIES (page Evolution mineur, "XP necessaire" : les points
// sont des separateurs de milliers : 22.123 = 22 123). Niveaux 2-20 en table exacte ;
// au-dela : formule de prolongation (xpBase * n^xpExponent, UNVERIFIED). La table mineur
// s'applique aux 4 metiers (seule table publiee ; ECART documente).
public double xpBase = 100.0; public double xpBase = 100.0;
public double xpExponent = 1.5; public double xpExponent = 1.5;
public Map<Integer, Long> levelThresholds = new HashMap<>(Map.ofEntries(
Map.entry(2, 22123L), Map.entry(3, 40390L), Map.entry(4, 73751L),
Map.entry(5, 118886L), Map.entry(6, 176611L), Map.entry(7, 247616L),
Map.entry(8, 332507L), Map.entry(9, 431826L), Map.entry(10, 546062L),
Map.entry(11, 675669L), Map.entry(12, 821062L), Map.entry(13, 982632L),
Map.entry(14, 1160743L), Map.entry(15, 1355741L), Map.entry(16, 1567953L),
Map.entry(17, 1797690L), Map.entry(18, 2045248L), Map.entry(19, 2310912L),
Map.entry(20, 2594953L)));
// Niveau mineur requis pour /nether (wiki recompenses mineur niv.3, VERIFIE). // Niveau mineur requis pour /nether (wiki recompenses mineur niv.3, VERIFIE).
public int netherMinerLevel = 3; public int netherMinerLevel = 3;
@@ -92,6 +103,13 @@ public final class PalaConfig {
Map.entry("minecraft:melon", new double[]{4, 3}), Map.entry("minecraft:melon", new double[]{4, 3}),
Map.entry("minecraft:pumpkin", new double[]{5, 6}))); Map.entry("minecraft:pumpkin", new double[]{5, 6})));
// M-xpcurve (wiki fermier "Broyer", VERIFIE) : fruit -> [xp, niveau requis].
// Eggplant 3@8, chervil==okami 4.5@12, kiwano 6@16. Attribution : dernier ouvreur
// de la GUI (BE, ECART documente : pas de tracking du deposant).
public Map<String, double[]> crusherXp = new HashMap<>(Map.of(
"pala:egg_plant_fruit", new double[]{3, 8},
"pala:okami_fruit", new double[]{4.5, 12},
"pala:kiwano", new double[]{6, 16}));
// M4a : recettes machines data-driven (CDC §3.4). Cles = ids de registres. // M4a : recettes machines data-driven (CDC §3.4). Cles = ids de registres.
// Defauts = legacy+wiki VERIFIES (M3). Rechargeables via /pala reload. // Defauts = legacy+wiki VERIFIES (M3). Rechargeables via /pala reload.
public Map<String, String> crusherResults = new HashMap<>(Map.of( public Map<String, String> crusherResults = new HashMap<>(Map.of(
@@ -182,9 +200,10 @@ public final class PalaConfig {
// pour les materialiser si une cle attendue manque. Une table explicitement // pour les materialiser si une cle attendue manque. Une table explicitement
// videe (cle presente, tableau vide) est respectee telle quelle. // videe (cle presente, tableau vide) est respectee telle quelle.
java.util.Set<String> expected = java.util.Set.of("minerXp", "xpBase", java.util.Set<String> expected = java.util.Set.of("minerXp", "xpBase",
"xpExponent", "netherMinerLevel", "stickCooldowns", "rankNodes", "xpExponent", "levelThresholds", "netherMinerLevel", "stickCooldowns",
"hunterKills", "farmerHarvest", "crusherResults", "crusherFuels", "rankNodes", "hunterKills", "farmerHarvest", "crusherXp",
"crusherInfiniteFuels", "furnaceSmelts", "furnaceFuels", "crusherResults", "crusherFuels", "crusherInfiniteFuels",
"furnaceSmelts", "furnaceFuels",
"serverName", "wikiUrl", "discordUrl", "shopUrl"); "serverName", "wikiUrl", "discordUrl", "shopUrl");
boolean complete = true; boolean complete = true;
try (Reader keysReader = Files.newBufferedReader(path)) { try (Reader keysReader = Files.newBufferedReader(path)) {
@@ -222,8 +241,12 @@ public final class PalaConfig {
} }
} }
/** Cout XP total pour atteindre le niveau n (n >= 1). */ /** Cout XP total pour atteindre le niveau n (n >= 1) : table wiki 2-20, formule au-dela. */
public long xpForLevel(int level) { public long xpForLevel(int level) {
Long exact = levelThresholds.get(level);
if (exact != null) {
return exact;
}
return (long) (xpBase * Math.pow(level, xpExponent)); return (long) (xpBase * Math.pow(level, xpExponent));
} }
} }
@@ -137,6 +137,19 @@ public final class PalaToolEvents {
return true; return true;
} }
// M-xpcurve (wiki mineur) : le toucher de soie ne donne pas d'XP metier.
private static boolean hasSilkTouch(ServerLevel level, ItemStack hand) {
if (hand.isEmpty()) {
return false;
}
net.minecraft.core.Holder<net.minecraft.world.item.enchantment.Enchantment> silk =
level.registryAccess()
.lookupOrThrow(net.minecraft.core.registries.Registries.ENCHANTMENT)
.getOrThrow(net.minecraft.world.item.enchantment.Enchantments.SILK_TOUCH);
return net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(silk,
hand) > 0;
}
private static void afterBreak(Level level, Player player, BlockPos pos, BlockState state, private static void afterBreak(Level level, Player player, BlockPos pos, BlockState state,
BlockEntity blockEntity) { BlockEntity blockEntity) {
if (level.isClientSide() || !(level instanceof ServerLevel sl) if (level.isClientSide() || !(level instanceof ServerLevel sl)
@@ -147,8 +160,10 @@ public final class PalaToolEvents {
ItemStack hand = sp.getMainHandItem(); ItemStack hand = sp.getMainHandItem();
Item held = hand.isEmpty() ? null : hand.getItem(); Item held = hand.isEmpty() ? null : hand.getItem();
// --- Metiers : XP mineur (M0) --- // --- Metiers : XP mineur (M0) : pas de XP au toucher de soie (wiki) ---
if (!hasSilkTouch(sl, hand)) {
PalaJobs.onBlockBreak(sp, sl, pos, state); PalaJobs.onBlockBreak(sp, sl, pos, state);
}
// --- Metiers : XP fermier recoltes vanilla (M5a) --- // --- Metiers : XP fermier recoltes vanilla (M5a) ---
PalaJobEvents.onHarvest(sp, state); PalaJobEvents.onHarvest(sp, state);
@@ -47,6 +47,8 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
private final SimpleContainer inventory = new SimpleContainer(9); private final SimpleContainer inventory = new SimpleContainer(9);
private int progress; private int progress;
private double luck; private double luck;
// M-xpcurve : dernier ouvreur de la GUI (attribution XP "broyer" fermier).
private String lastOpener = "";
public PalaMachineBlockEntity(BlockPos pos, BlockState state) { public PalaMachineBlockEntity(BlockPos pos, BlockState state) {
super(PalaBlockEntities.MACHINE, pos, state); super(PalaBlockEntities.MACHINE, pos, state);
@@ -88,6 +90,7 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
output.grow(1); output.grow(1);
} }
luck = 0.0; luck = 0.0;
grantCrusherXp(fruit);
} }
setChanged(); setChanged();
} }
@@ -149,12 +152,35 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
return PalaConfig.get().furnaceFuels.contains(id) || PalaConfig.get().crusherFuels.contains(id); return PalaConfig.get().furnaceFuels.contains(id) || PalaConfig.get().crusherFuels.contains(id);
} }
// M-xpcurve (wiki fermier "Broyer") : XP au dernier ouvreur a chaque production.
private void grantCrusherXp(ItemStack fruit) {
if (lastOpener.isEmpty() || level == null || level.isClientSide()) {
return;
}
double[] table = PalaConfig.get().crusherXp.get(itemId(fruit));
if (table == null) {
return;
}
net.minecraft.server.level.ServerPlayer opener;
try {
opener = ((net.minecraft.server.level.ServerLevel) level).getServer().getPlayerList()
.getPlayer(java.util.UUID.fromString(lastOpener));
} catch (IllegalArgumentException e) {
return;
}
if (opener != null
&& fr.surviepote.pala.core.PalaJobs.levelOf(opener, "fermier") >= (int) table[1]) {
fr.surviepote.pala.core.PalaJobs.addXp(opener, "fermier", table[0]);
}
}
@Override @Override
protected void saveAdditional(ValueOutput output) { protected void saveAdditional(ValueOutput output) {
super.saveAdditional(output); super.saveAdditional(output);
inventory.storeAsItemList(output.list("Items", ItemStack.CODEC)); inventory.storeAsItemList(output.list("Items", ItemStack.CODEC));
output.putInt("Progress", progress); output.putInt("Progress", progress);
output.putDouble("Luck", luck); output.putDouble("Luck", luck);
output.putString("LastOpener", lastOpener);
} }
@Override @Override
@@ -163,6 +189,7 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
inventory.fromItemList(input.listOrEmpty("Items", ItemStack.CODEC)); inventory.fromItemList(input.listOrEmpty("Items", ItemStack.CODEC));
progress = input.getIntOr("Progress", 0); progress = input.getIntOr("Progress", 0);
luck = input.getDoubleOr("Luck", 0.0); luck = input.getDoubleOr("Luck", 0.0);
lastOpener = input.getStringOr("LastOpener", "");
} }
@Override @Override
@@ -172,6 +199,10 @@ public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider
@Override @Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
if (player instanceof net.minecraft.server.level.ServerPlayer sp) {
lastOpener = sp.getUUID().toString();
setChanged();
}
return new DispenserMenu(containerId, playerInventory, inventory); return new DispenserMenu(containerId, playerInventory, inventory);
} }
} }
Binary file not shown.