pala M-enchants-2: Experience Bottler (fiole XP 1000)

This commit is contained in:
Anaïs Saraiva
2026-10-19 06:59:36 +02:00
parent b30d3128b1
commit 1c4efce590
6 changed files with 123 additions and 0 deletions
+4
View File
@@ -706,6 +706,10 @@ avant M4 (TODO:crafts-machines).
absente (table vanilla/enclume//enchant). TODO:M-enchants partiel (bottler, absente (table vanilla/enclume//enchant). TODO:M-enchants partiel (bottler,
overwhelmed, unclaim, anti-chute infaisable serveur, fake-water sans degats). overwhelmed, unclaim, anti-chute infaisable serveur, fake-water sans degats).
VERIFIE : build SUCCESSFUL, boot Done (datapack accepte), 0 erreur. UNVERIFIED en jeu. VERIFIE : build SUCCESSFUL, boot Done (datapack accepte), 0 erreur. UNVERIFIED en jeu.
- M-enchants-2 LIVRE 2026-10-19 ~06:55 : Experience Bottler (datapack + redirection XP
minage vers fiole CUSTOM_DATA 1000 max + lore contenu + clic droit = recuperation).
ECART : mineur uniquement, outils de minage uniquement (pas armure/arme).
VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu.
- M-palaforge LIVRE 2026-10-19 ~03:55 : bloc + BE partagee (3e mode) + gate mineur 14 + - M-palaforge LIVRE 2026-10-19 ~03:55 : bloc + BE partagee (3e mode) + gate mineur 14 +
table fonte wiki §3.2 (31 items, ratio floor usure) + fuels bois (+buche/planches/baton, table fonte wiki §3.2 (31 items, ratio floor usure) + fuels bois (+buche/planches/baton,
lave exclue : seau non rendu) + craft (1 findium + 4 furnaces + 4 briques, positions lave exclue : seau non rendu) + craft (1 findium + 4 furnaces + 4 briques, positions
@@ -60,10 +60,98 @@ public final class PalaJobs {
Double xp = PalaConfig.get().minerXp.get(id.toString()); Double xp = PalaConfig.get().minerXp.get(id.toString());
if (xp != null && levelOf(player, "mineur") >= PalaConfig.get().minerLevels if (xp != null && levelOf(player, "mineur") >= PalaConfig.get().minerLevels
.getOrDefault(id.toString(), 0)) { .getOrDefault(id.toString(), 0)) {
// M-enchants-2 (wiki Experience Bottler) : outil enchante + fiole vide en
// hotbar (contenu < 1000) => l'XP part dans la fiole au lieu du joueur.
// ECART : mineur uniquement (seul gain "casse-bloc" porte).
if (enchantLevel(level, player.getMainHandItem(), "experience_bottler") >= 1
&& bottleXp(player, "mineur", xp)) {
return;
}
addXp(player, "mineur", xp); addXp(player, "mineur", xp);
} }
} }
/** Niveau d'un enchant pala sur un item (0 si absent). */
public static int enchantLevel(ServerLevel level, net.minecraft.world.item.ItemStack stack,
String path) {
if (stack.isEmpty()) {
return 0;
}
net.minecraft.core.Holder<net.minecraft.world.item.enchantment.Enchantment> holder =
level.registryAccess()
.lookupOrThrow(net.minecraft.core.registries.Registries.ENCHANTMENT)
.getOrThrow(net.minecraft.resources.ResourceKey.create(
net.minecraft.core.registries.Registries.ENCHANTMENT,
net.minecraft.resources.Identifier.fromNamespaceAndPath(
"pala", path)));
return net.minecraft.world.item.enchantment.EnchantmentHelper
.getItemEnchantmentLevel(holder, stack);
}
// M-enchants-2 : verse de l'XP metier dans la premiere fiole admissible de la hotbar
// (slots 0-8, contenu < 1000). Vrai si verse (appelant : ne pas donner au joueur).
private static boolean bottleXp(ServerPlayer player, String job, double xp) {
net.minecraft.world.entity.player.Inventory inv = player.getInventory();
for (int i = 0; i < 9; i++) {
net.minecraft.world.item.ItemStack stack = inv.getItem(i);
if (stack.isEmpty()
|| !stack.is(fr.surviepote.pala.PalaItems.FLASK)) {
continue;
}
double stored = stack.getOrDefault(
net.minecraft.core.component.DataComponents.CUSTOM_DATA,
net.minecraft.world.item.component.CustomData.EMPTY).copyTag()
.getDoubleOr("bottler_xp", 0.0);
if (stored >= 1000.0) {
continue;
}
double put = Math.min(xp, 1000.0 - stored);
final double total = stored + put;
net.minecraft.world.item.component.CustomData.update(
net.minecraft.core.component.DataComponents.CUSTOM_DATA, stack,
tag -> {
tag.putDouble("bottler_xp", total);
tag.putString("bottler_job", job);
});
stack.set(net.minecraft.core.component.DataComponents.LORE,
new net.minecraft.world.item.component.ItemLore(java.util.List.of(
net.minecraft.network.chat.Component.literal(
"§7" + job + " : " + (int) total + " / 1000 XP"))));
return true;
}
return false;
}
/** Boire une fiole : recupere l'XP stockee dans son metier (M-enchants-2). */
public static boolean drinkFlask(ServerPlayer player,
net.minecraft.world.item.ItemStack stack) {
double stored = stack.getOrDefault(
net.minecraft.core.component.DataComponents.CUSTOM_DATA,
net.minecraft.world.item.component.CustomData.EMPTY).copyTag()
.getDoubleOr("bottler_xp", 0.0);
if (stored <= 0.0) {
return false;
}
String job = stack.getOrDefault(
net.minecraft.core.component.DataComponents.CUSTOM_DATA,
net.minecraft.world.item.component.CustomData.EMPTY).copyTag()
.getStringOr("bottler_job", "mineur");
if (!JOBS.contains(job)) {
job = "mineur";
}
addXp(player, job, stored);
net.minecraft.world.item.component.CustomData.update(
net.minecraft.core.component.DataComponents.CUSTOM_DATA, stack,
tag -> {
tag.putDouble("bottler_xp", 0.0);
tag.putString("bottler_job", "mineur");
});
stack.set(net.minecraft.core.component.DataComponents.LORE,
new net.minecraft.world.item.component.ItemLore(java.util.List.of(
net.minecraft.network.chat.Component.literal("§7Fiole vide"))));
return true;
}
/** Hook prise fourneau : cuisson mineur (table wiki "Cuire") + viandes chasseur. */ /** Hook prise fourneau : cuisson mineur (table wiki "Cuire") + viandes chasseur. */
public static void onSmeltTake(ServerPlayer player, net.minecraft.world.item.ItemStack stack) { public static void onSmeltTake(ServerPlayer player, net.minecraft.world.item.ItemStack stack) {
if (stack.isEmpty()) { if (stack.isEmpty()) {
@@ -150,6 +150,13 @@ public final class PalaItemUseEvents {
+ (n > 1 ? "s" : "") + ".")); + (n > 1 ? "s" : "") + "."));
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
// M-enchants-2 : boire une fiole pleine = recuperer l'XP stockee.
if (item == PalaItems.FLASK) {
if (fr.surviepote.pala.core.PalaJobs.drinkFlask(sp, stack)) {
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
// M-gadget-2 (wiki items lucky) : grappin — clic droit air, raycast 32 blocs, // M-gadget-2 (wiki items lucky) : grappin — clic droit air, raycast 32 blocs,
// tirage instantane vers le point d'impact (ECART : pas de crochet visible). // tirage instantane vers le point d'impact (ECART : pas de crochet visible).
if (item == PalaItems.GRAPPIN) { if (item == PalaItems.GRAPPIN) {
@@ -4,6 +4,7 @@
"item.pala.amethyst_mixed_coal": "Amethyst Mixed Coal", "item.pala.amethyst_mixed_coal": "Amethyst Mixed Coal",
"item.pala.amethyst_stick": "Amethyst Stick", "item.pala.amethyst_stick": "Amethyst Stick",
"item.pala.compressed_amethyst": "Compressed Amethyst", "item.pala.compressed_amethyst": "Compressed Amethyst",
"enchantment.pala.experience_bottler": "Experience Bottler",
"enchantment.pala.xp_stealer": "Voleur d'XP", "enchantment.pala.xp_stealer": "Voleur d'XP",
"block.pala.mystical_bookshelf": "Bibliotheque mystique", "block.pala.mystical_bookshelf": "Bibliotheque mystique",
"block.pala.cauldron_block": "Bloc du chaudron", "block.pala.cauldron_block": "Bloc du chaudron",
@@ -0,0 +1,23 @@
{
"anvil_cost": 4,
"description": {
"translate": "enchantment.pala.experience_bottler"
},
"effects": {
},
"max_cost": {
"base": 40,
"per_level_above_first": 10
},
"max_level": 1,
"min_cost": {
"base": 20,
"per_level_above_first": 10
},
"primary_items": "#minecraft:enchantable/mining",
"slots": [
"mainhand"
],
"supported_items": "#minecraft:enchantable/mining",
"weight": 2
}
Binary file not shown.