nosingleplayer: zero Shadow (résolution superclass cassée en 26.3)

This commit is contained in:
kisakay
2026-10-18 21:28:03 +02:00
parent 5782acc08a
commit 37c955d67a
106 changed files with 2324 additions and 28 deletions
@@ -12,6 +12,7 @@ public class Pala implements ModInitializer {
@Override
public void onInitialize() {
PalaRegistries.registerAll();
fr.surviepote.pala.events.PalaEvents.registerAll();
LOGGER.info("[SurviePote] Pala initialisé.");
}
}
@@ -0,0 +1,24 @@
package fr.surviepote.pala;
import fr.surviepote.pala.machine.PalaMachineBlockEntity;
import java.util.Set;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.level.block.entity.BlockEntityType;
// Block entities Pala (machines crusher + furnace).
public final class PalaBlockEntities {
private PalaBlockEntities() {
}
public static BlockEntityType<PalaMachineBlockEntity> MACHINE;
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)));
}
}
@@ -1,5 +1,6 @@
package fr.surviepote.pala;
import fr.surviepote.pala.machine.PalaMachineBlock;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
@@ -47,7 +48,8 @@ public final class PalaBlocks {
public static final Block ORANGE_BLUE_STAGE2 = register("orange_blue_stage2", new Block(BlockBehaviour.Properties.of().strength(0.0F, 0.0F).sound(SoundType.CROP).noCollision().instabreak()));
public static final Block ORANGE_BLUE_STAGE3 = register("orange_blue_stage3", new Block(BlockBehaviour.Properties.of().strength(0.0F, 0.0F).sound(SoundType.CROP).noCollision().instabreak()));
public static final Block ORANGE_BLUE_STAGE4 = register("orange_blue_stage4", new Block(BlockBehaviour.Properties.of().strength(0.0F, 0.0F).sound(SoundType.CROP).noCollision().instabreak()));
public static final Block PALADIUM_CRUSHER = register("paladium_crusher", new Block(BlockBehaviour.Properties.of().strength(1.0F, 10.0F).sound(SoundType.METAL)));
public static final Block PALADIUM_CRUSHER = register("paladium_crusher", new PalaMachineBlock());
public static final Block PALADIUM_FURNACE = register("paladium_furnace", new PalaMachineBlock());
public static final Block PALADIUM_GREEN_ORE = register("paladium_green_ore", new Block(BlockBehaviour.Properties.of().strength(5.5F, 9.0F).sound(SoundType.STONE).requiresCorrectToolForDrops()));
public static final Block PALADIUM_GREEN_ORE_BLOCK = register("paladium_green_ore_block", new Block(BlockBehaviour.Properties.of().strength(5.0F, 10.0F).sound(SoundType.METAL).requiresCorrectToolForDrops()));
public static final Block PALADIUM_ORE = register("paladium_ore", new Block(BlockBehaviour.Properties.of().strength(5.0F, 8.0F).sound(SoundType.STONE).requiresCorrectToolForDrops()));
@@ -1,10 +1,27 @@
package fr.surviepote.pala;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderingRegistry;
import net.minecraft.client.renderer.block.FluidModel;
import net.minecraft.client.resources.model.sprite.Material;
import net.minecraft.resources.Identifier;
public class PalaClient implements ClientModInitializer {
private static FluidModel.Unbaked fluidModel(String still, String flowing) {
Material stillMat = new Material(Identifier.fromNamespaceAndPath("pala", "block/" + still));
Material flowingMat = new Material(Identifier.fromNamespaceAndPath("pala", "block/" + flowing));
// Pas de texture d'overlay dediee : on reutilise le still.
return new FluidModel.Unbaked(stillMat, flowingMat, stillMat, state -> -1);
}
@Override
public void onInitializeClient() {
FluidRenderingRegistry.register(PalaFluids.ANGELIC_WATER, PalaFluids.ANGELIC_WATER_FLOWING,
fluidModel("angelicwater_still", "angelicwater_flowing"));
FluidRenderingRegistry.register(PalaFluids.FAKE_WATER, PalaFluids.FAKE_WATER_FLOWING,
fluidModel("sulfuricwater_still", "sulfuricwater_flowing"));
FluidRenderingRegistry.setBlockTransparency(PalaFluids.ANGELIC_WATER_BLOCK, false);
FluidRenderingRegistry.setBlockTransparency(PalaFluids.FAKE_WATER_BLOCK, false);
}
}
@@ -0,0 +1,62 @@
package fr.surviepote.pala;
import com.mojang.brigadier.Command;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
// Commandes Pala : /end /nether /overworld (permission niveau 4, legacy).
// Origine : CommandEnd/Nether/Overworld + procedures *CommandExecuted qui
// teleportaient le joueur au spawn de la dimension visee. Ici via
// TeleportTransition (API 26.x), sans le Teleporter custom du legacy.
public final class PalaCommands {
private PalaCommands() {
}
public static void register() {
CommandRegistrationCallback.EVENT.register((dispatcher, context, selection) -> {
dispatcher.register(Commands.literal("end")
.requires(source -> Commands.LEVEL_OWNERS.check(source.permissions()))
.executes(command -> teleport(command.getSource(), Level.END)));
dispatcher.register(Commands.literal("nether")
.requires(source -> Commands.LEVEL_OWNERS.check(source.permissions()))
.executes(command -> teleport(command.getSource(), Level.NETHER)));
dispatcher.register(Commands.literal("overworld")
.requires(source -> Commands.LEVEL_OWNERS.check(source.permissions()))
.executes(command -> teleport(command.getSource(), Level.OVERWORLD)));
});
}
private static int teleport(CommandSourceStack source, ResourceKey<Level> dimension) {
try {
ServerPlayer player = source.getPlayerOrException();
MinecraftServer server = source.getServer();
ServerLevel target = server.getLevel(dimension);
BlockPos spawn;
if (dimension == Level.END) {
spawn = ServerLevel.END_SPAWN_POINT;
} else {
spawn = target.getRespawnData().pos();
}
Vec3 pos = new Vec3(spawn.getX() + 0.5, spawn.getY() + 1.0, spawn.getZ() + 0.5);
player.teleport(new TeleportTransition(target, pos, Vec3.ZERO, player.getYRot(), player.getXRot(),
TeleportTransition.DO_NOTHING));
target.playSound(null, pos.x(), pos.y(), pos.z(), SoundEvents.ENDERMAN_TELEPORT,
SoundSource.NEUTRAL, 1.0F, 1.0F);
return Command.SINGLE_SUCCESS;
} catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) {
return 0;
}
}
}
@@ -0,0 +1,187 @@
package fr.surviepote.pala;
import java.util.function.Supplier;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.BucketItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.material.PushReaction;
// Fluides Pala : angelic_water + fake_water (defs AngelicWater/FakeWater).
// Version complete FlowingFluid (Still + Flowing + FluidBlock + seau),
// comportement eau vanilla. Les effets au contact (procedures
// AngelicWaterMobplayerCollidesBlock / FakeWaterMobplayerCollidesBlock)
// ne sont PAS portes (procedures hors scope) : TODO.
// Note : les recipes pala:fake_water / pala:angelic_water ciblent ces ids,
// fournis ici comme BlockItems du bloc de fluide (comme en 1.12) ; les seaux
// sont pala:<nom>_bucket.
public final class PalaFluids {
private PalaFluids() {
}
// Une variante Still/Flowing d'un fluide Pala, cablee via suppliers
// (le bloc et le seau n'existent pas encore a la construction).
public static final class Variant extends FlowingFluid {
private final Supplier<Fluid> still;
private final Supplier<Fluid> flowing;
private final Supplier<LiquidBlock> block;
private final Supplier<Item> bucket;
private final boolean source;
public Variant(Supplier<Fluid> still, Supplier<Fluid> flowing,
Supplier<LiquidBlock> block, Supplier<Item> bucket, boolean source) {
this.still = still;
this.flowing = flowing;
this.block = block;
this.bucket = bucket;
this.source = source;
}
@Override
public Fluid getFlowing() {
return flowing.get();
}
@Override
public Fluid getSource() {
return still.get();
}
@Override
public Item getBucket() {
return bucket.get();
}
@Override
public boolean isSource(FluidState state) {
return source;
}
@Override
public int getAmount(FluidState state) {
return source ? 8 : state.getValue(LEVEL);
}
@Override
protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> builder) {
super.createFluidStateDefinition(builder);
builder.add(LEVEL);
}
@Override
protected BlockState createLegacyBlock(FluidState state) {
return block.get().defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(state));
}
@Override
public int getTickDelay(LevelReader level) {
return 5;
}
@Override
protected int getSlopeFindDistance(LevelReader level) {
return 4;
}
@Override
protected int getDropOff(LevelReader level) {
return 1;
}
@Override
protected boolean canConvertToSource(net.minecraft.server.level.ServerLevel level) {
return true;
}
@Override
protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state) {
}
@Override
protected boolean canBeReplacedWith(FluidState state, BlockGetter level, BlockPos pos, Fluid fluid, Direction direction) {
return direction == Direction.DOWN && !isSame(fluid);
}
@Override
protected float getExplosionResistance() {
return 100.0F;
}
@Override
public boolean isSame(Fluid fluid) {
return fluid == getSource() || fluid == getFlowing();
}
}
public static final class PalaFluidBlock extends LiquidBlock {
public PalaFluidBlock(Supplier<FlowingFluid> fluid) {
super(fluid.get(), BlockBehaviour.Properties.of().mapColor(MapColor.WATER).replaceable()
.noCollision().strength(100.0F).pushReaction(PushReaction.IGNORE_ENTITY)
.noLootTable().liquid().sound(SoundType.EMPTY));
}
}
public static FlowingFluid ANGELIC_WATER;
public static FlowingFluid ANGELIC_WATER_FLOWING;
public static LiquidBlock ANGELIC_WATER_BLOCK;
public static Item ANGELIC_WATER_BUCKET;
public static FlowingFluid FAKE_WATER;
public static FlowingFluid FAKE_WATER_FLOWING;
public static LiquidBlock FAKE_WATER_BLOCK;
public static Item FAKE_WATER_BUCKET;
private static FlowingFluid registerFluid(String path, Supplier<Fluid> still, Supplier<Fluid> flowing,
Supplier<LiquidBlock> block, Supplier<Item> bucket, boolean source) {
return Registry.register(BuiltInRegistries.FLUID, Identifier.fromNamespaceAndPath("pala", path),
new Variant(still, flowing, block, bucket, source));
}
public static void register() {
ANGELIC_WATER = registerFluid("angelic_water", () -> ANGELIC_WATER, () -> ANGELIC_WATER_FLOWING,
() -> ANGELIC_WATER_BLOCK, () -> ANGELIC_WATER_BUCKET, true);
ANGELIC_WATER_FLOWING = registerFluid("angelic_water_flowing", () -> ANGELIC_WATER, () -> ANGELIC_WATER_FLOWING,
() -> ANGELIC_WATER_BLOCK, () -> ANGELIC_WATER_BUCKET, false);
ANGELIC_WATER_BLOCK = Registry.register(BuiltInRegistries.BLOCK,
Identifier.fromNamespaceAndPath("pala", "angelic_water"),
new PalaFluidBlock(() -> ANGELIC_WATER));
// BlockItem sous l'id pala:angelic_water (cible de angelicwaterrecipe.json).
Registry.register(BuiltInRegistries.ITEM, Identifier.fromNamespaceAndPath("pala", "angelic_water"),
new BlockItem(ANGELIC_WATER_BLOCK, new Item.Properties()));
ANGELIC_WATER_BUCKET = Registry.register(BuiltInRegistries.ITEM,
Identifier.fromNamespaceAndPath("pala", "angelic_water_bucket"),
new BucketItem(ANGELIC_WATER, new Item.Properties().stacksTo(1)));
FAKE_WATER = registerFluid("fake_water", () -> FAKE_WATER, () -> FAKE_WATER_FLOWING,
() -> FAKE_WATER_BLOCK, () -> FAKE_WATER_BUCKET, true);
FAKE_WATER_FLOWING = registerFluid("fake_water_flowing", () -> FAKE_WATER, () -> FAKE_WATER_FLOWING,
() -> FAKE_WATER_BLOCK, () -> FAKE_WATER_BUCKET, false);
FAKE_WATER_BLOCK = Registry.register(BuiltInRegistries.BLOCK,
Identifier.fromNamespaceAndPath("pala", "fake_water"),
new PalaFluidBlock(() -> FAKE_WATER));
// BlockItem sous l'id pala:fake_water (cible de fakewaterrecipe.json).
Registry.register(BuiltInRegistries.ITEM, Identifier.fromNamespaceAndPath("pala", "fake_water"),
new BlockItem(FAKE_WATER_BLOCK, new Item.Properties()));
FAKE_WATER_BUCKET = Registry.register(BuiltInRegistries.ITEM,
Identifier.fromNamespaceAndPath("pala", "fake_water_bucket"),
new BucketItem(FAKE_WATER, new Item.Properties().stacksTo(1)));
}
}
@@ -1,5 +1,6 @@
package fr.surviepote.pala;
import fr.surviepote.pala.item.DynamiteGunItem;
import net.minecraft.core.Registry;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -135,6 +136,9 @@ public final class PalaItems {
public static final Item TITANE_LEGGINGS = register("titane_leggings", new Item(new Item.Properties().durability(18).humanoidArmor(PalaArmorMaterials.TITANE, ArmorType.LEGGINGS)));
public static final Item TITANE_BOOTS = register("titane_boots", new Item(new Item.Properties().durability(18).humanoidArmor(PalaArmorMaterials.TITANE, ArmorType.BOOTS)));
public static final Item WEIGHTED_BOOTS = register("weighted_boots", new Item(new Item.Properties().durability(16).humanoidArmor(PalaArmorMaterials.WEIGHTED_BOOTS, ArmorType.BOOTS)));
public static final Item DYNAMITE = register("dynamite", new DynamiteGunItem(1.5F));
public static final Item DYNAMITE_NINJA = register("dynamite_ninja", new DynamiteGunItem(1.5F));
public static final Item ENDIUM_DYNAMITE = register("endium_dynamite", new DynamiteGunItem(1.8F));
public static void register() {
}
@@ -8,7 +8,10 @@ public final class PalaRegistries {
public static void registerAll() {
PalaItems.register();
PalaFluids.register();
PalaBlocks.register();
PalaBlockEntities.register();
PalaCommands.register();
PalaTabs.register();
PalaWorldgen.register();
}
@@ -121,6 +121,11 @@ public final class PalaTabs {
output.accept(PalaItems.TITANE_PICKAXE);
output.accept(PalaItems.TITANE_SHOVEL);
output.accept(PalaItems.TITANE_SWORD);
output.accept(PalaItems.DYNAMITE);
output.accept(PalaItems.DYNAMITE_NINJA);
output.accept(PalaItems.ENDIUM_DYNAMITE);
output.accept(PalaFluids.ANGELIC_WATER_BUCKET);
output.accept(PalaFluids.FAKE_WATER_BUCKET);
output.accept(PalaItems.AMETHYST_HELMET);
output.accept(PalaItems.AMETHYST_CHESTPLATE);
output.accept(PalaItems.AMETHYST_LEGGINGS);
@@ -173,6 +178,7 @@ public final class PalaTabs {
output.accept(PalaBlocks.ORANGE_BLUE_STAGE3);
output.accept(PalaBlocks.ORANGE_BLUE_STAGE4);
output.accept(PalaBlocks.PALADIUM_CRUSHER);
output.accept(PalaBlocks.PALADIUM_FURNACE);
output.accept(PalaBlocks.PALADIUM_ORE);
output.accept(PalaBlocks.PALADIUM_ORE_BLOCK);
output.accept(PalaBlocks.PALADIUM_GREEN_ORE);
@@ -0,0 +1,115 @@
package fr.surviepote.pala.events;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.PalaItems;
// Portage des procedures d'armure MCreator (tick quand la piece est portee) :
// ProcedurePaladiumArmor{Helmet,Body,Leggings,Boots}TickEvent,
// ProcedureEndiumArmor{Helmet,Body,Leggings,Boots}TickEvent,
// ProcedureWeightedBootsBootsTickEvent, ProcedurePickaxeOfTheGodLevel25ToolInHandTick.
// Origine : effets donnes par piece portee ; Endium complet -> invisibilite.
// WeightedBoots : ralentissement de chute + explosion a l'atterrissage dur (legacy).
public final class PalaArmorEvents {
private PalaArmorEvents() {
}
public static void register() {
ServerTickEvents.END_SERVER_TICK.register(server -> {
for (ServerPlayer player : server.getPlayerList().getPlayers()) {
onPlayerTick(player);
}
});
}
private static void effect(LivingEntity entity, Holder<MobEffect> effect, int duration, int amplifier) {
entity.addEffect(new MobEffectInstance(effect, duration, amplifier, false, false));
}
private static boolean wearing(ServerPlayer player, EquipmentSlot slot, net.minecraft.world.item.Item item) {
ItemStack stack = player.getItemBySlot(slot);
return !stack.isEmpty() && stack.getItem() == item;
}
private static void onPlayerTick(ServerPlayer player) {
// --- Armure Paladium (1 procedure par piece dans le legacy) ---
if (wearing(player, EquipmentSlot.HEAD, PalaItems.PALADIUM_HELMET)) {
effect(player, net.minecraft.world.effect.MobEffects.NIGHT_VISION, 860, 1);
}
if (wearing(player, EquipmentSlot.CHEST, PalaItems.PALADIUM_CHESTPLATE)) {
effect(player, net.minecraft.world.effect.MobEffects.STRENGTH, 70, 3);
}
if (wearing(player, EquipmentSlot.LEGS, PalaItems.PALADIUM_LEGGINGS)) {
effect(player, net.minecraft.world.effect.MobEffects.RESISTANCE, 90, 3);
}
if (wearing(player, EquipmentSlot.FEET, PalaItems.PALADIUM_BOOTS)) {
effect(player, net.minecraft.world.effect.MobEffects.REGENERATION, 80, 1);
}
// --- Armure Endium ---
if (wearing(player, EquipmentSlot.HEAD, PalaItems.ENDIUM_HELMET)) {
effect(player, net.minecraft.world.effect.MobEffects.NIGHT_VISION, 860, 4);
}
if (wearing(player, EquipmentSlot.CHEST, PalaItems.ENDIUM_CHESTPLATE)) {
effect(player, net.minecraft.world.effect.MobEffects.STRENGTH, 60, 6);
effect(player, net.minecraft.world.effect.MobEffects.REGENERATION, 60, 4);
}
if (wearing(player, EquipmentSlot.LEGS, PalaItems.ENDIUM_LEGGINGS)) {
effect(player, net.minecraft.world.effect.MobEffects.RESISTANCE, 60, 6);
}
if (wearing(player, EquipmentSlot.FEET, PalaItems.ENDIUM_BOOTS)) {
effect(player, net.minecraft.world.effect.MobEffects.HASTE, 60, 1);
}
if (wearing(player, EquipmentSlot.HEAD, PalaItems.ENDIUM_HELMET)
&& wearing(player, EquipmentSlot.CHEST, PalaItems.ENDIUM_CHESTPLATE)
&& wearing(player, EquipmentSlot.LEGS, PalaItems.ENDIUM_LEGGINGS)
&& wearing(player, EquipmentSlot.FEET, PalaItems.ENDIUM_BOOTS)) {
effect(player, net.minecraft.world.effect.MobEffects.INVISIBILITY, 60, 1);
}
// --- Bottes lestées (ProcedureWeightedBootsBootsTickEvent) ---
// En l'air : resistance + levitation negative (chute ralentie) ;
// atterrissage violent : explosion proportionnelle a la vitesse de chute.
if (wearing(player, EquipmentSlot.FEET, PalaItems.WEIGHTED_BOOTS)) {
net.minecraft.server.level.ServerLevel level = player.level();
net.minecraft.core.BlockPos pos = player.blockPosition();
boolean airBelow = level.getBlockState(pos.below(3)).isAir();
if (airBelow) {
effect(player, net.minecraft.world.effect.MobEffects.RESISTANCE, 10, 15);
effect(player, net.minecraft.world.effect.MobEffects.LEVITATION, 10, -75);
} else if (!level.getBlockState(pos.below(2)).isAir() && player.getDeltaMovement().y < -2.0) {
double power = Math.abs(player.getDeltaMovement().y) + 0.25;
level.explode(player, pos.getX(), pos.getY(), pos.getZ(), (float) power, true,
net.minecraft.world.level.Level.ExplosionInteraction.BLOCK);
player.sendSystemMessage(net.minecraft.network.chat.Component.literal("§l§cEXPLOSION !!!!"));
ItemStack boots = player.getItemBySlot(EquipmentSlot.FEET);
boots.hurtAndBreak(1, player, EquipmentSlot.FEET);
}
}
// --- Pioche divine niveau 25 en main (ProcedurePickaxeOfTheGodLevel25ToolInHandTick) ---
ItemStack hand = player.getMainHandItem();
if (!hand.isEmpty() && hand.getItem() == PalaItems.PICKAXE_OF_THE_GOD_LEVEL25) {
effect(player, net.minecraft.world.effect.MobEffects.SPEED, 8, 2);
effect(player, net.minecraft.world.effect.MobEffects.HASTE, 3, 3);
}
// --- Slime Pad : rebond +2 (ProcedureSlimePadEntityCollidesInTheBlock) ---
net.minecraft.server.level.ServerLevel sl = player.level();
net.minecraft.core.BlockPos feet = player.blockPosition();
if (sl.getBlockState(feet).getBlock() == PalaBlocks.SLIME_PAD
|| sl.getBlockState(feet.below()).getBlock() == PalaBlocks.SLIME_PAD) {
player.teleportTo(feet.getX() + 0.5, feet.getY() + 2.0, feet.getZ() + 0.5);
}
}
}
@@ -0,0 +1,131 @@
package fr.surviepote.pala.events;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import fr.surviepote.pala.PalaBlocks;
// Portage des procedures de croissance MCreator :
// ProcedureFikutsiStage0UpdateTick, ProcedureKiwanoStage0UpdateTick,
// ProcedureOkamiStage0UpdateTick, ProcedureOrangeBlueStage0UpdateTick
// (stade N -> stade N+1 sur tick aleatoire).
// Les blocs PalaBlocks etant des Block simples sans randomTick (lecture seule, non modifiables),
// la croissance est reimplementee par suivi des positions plantees : avancee d'un stade
// toutes les ~5 s (100 ticks serveur), avec elagage des entrees devenues invalides.
public final class PalaCropEvents {
private static final int MAX_TRACKED = 8192;
private static final Map<ResourceKey<Level>, Set<BlockPos>> TRACKED = new HashMap<>();
private PalaCropEvents() {
}
public static void register() {
ServerTickEvents.END_SERVER_TICK.register(server -> {
if (server.getTickCount() % 100 != 0) {
return;
}
for (ServerLevel level : server.getAllLevels()) {
growLevel(level);
}
});
}
public static void track(ServerLevel level, BlockPos pos) {
Set<BlockPos> set = TRACKED.computeIfAbsent(level.dimension(), k -> new HashSet<>());
if (set.size() >= MAX_TRACKED) {
Iterator<BlockPos> it = set.iterator();
if (it.hasNext()) {
it.next();
it.remove();
}
}
set.add(pos.immutable());
}
public static void untrack(ServerLevel level, BlockPos pos) {
Set<BlockPos> set = TRACKED.get(level.dimension());
if (set != null) {
set.remove(pos);
}
}
private static void growLevel(ServerLevel level) {
Set<BlockPos> set = TRACKED.get(level.dimension());
if (set == null || set.isEmpty()) {
return;
}
Iterator<BlockPos> it = set.iterator();
while (it.hasNext()) {
BlockPos pos = it.next();
if (!level.isLoaded(pos)) {
continue;
}
BlockState state = level.getBlockState(pos);
Block next = nextStage(state.getBlock());
if (next == null) {
it.remove();
} else {
level.setBlock(pos, next.defaultBlockState(), 3, 512);
}
}
}
private static Block nextStage(Block block) {
if (block == PalaBlocks.FIKUTSI_STAGE0) {
return PalaBlocks.FIKUTSI_STAGE1;
}
if (block == PalaBlocks.FIKUTSI_STAGE1) {
return PalaBlocks.FIKUTSI_STAGE2;
}
if (block == PalaBlocks.FIKUTSI_STAGE2) {
return PalaBlocks.FIKUTSI_STAGE3;
}
if (block == PalaBlocks.KIWANO_STAGE0) {
return PalaBlocks.KIWANO_STAGE1;
}
if (block == PalaBlocks.KIWANO_STAGE1) {
return PalaBlocks.KIWANO_STAGE2;
}
if (block == PalaBlocks.KIWANO_STAGE2) {
return PalaBlocks.KIWANO_STAGE3;
}
if (block == PalaBlocks.KIWANO_STAGE3) {
return PalaBlocks.KIWANO_STAGE4;
}
if (block == PalaBlocks.OKAMI_STAGE0) {
return PalaBlocks.OKAMI_STAGE1;
}
if (block == PalaBlocks.OKAMI_STAGE1) {
return PalaBlocks.OKAMI_STAGE2;
}
if (block == PalaBlocks.OKAMI_STAGE2) {
return PalaBlocks.OKAMI_STAGE3;
}
if (block == PalaBlocks.ORANGE_BLUE_STAGE0) {
return PalaBlocks.ORANGE_BLUE_STAGE1;
}
if (block == PalaBlocks.ORANGE_BLUE_STAGE1) {
return PalaBlocks.ORANGE_BLUE_STAGE2;
}
if (block == PalaBlocks.ORANGE_BLUE_STAGE2) {
return PalaBlocks.ORANGE_BLUE_STAGE3;
}
if (block == PalaBlocks.ORANGE_BLUE_STAGE3) {
return PalaBlocks.ORANGE_BLUE_STAGE4;
}
return null;
}
}
@@ -0,0 +1,40 @@
package fr.surviepote.pala.events;
import fr.surviepote.pala.PalaCommands;
// Point d'entree des 62 procedures MCreator portees en events Fabric 26.3.
//
// Portees (53) :
// - armures : Paladium x4, Endium x4, WeightedBoots, Pioche divine 25 en main (PalaArmorEvents) ;
// - clic droit air : Heal/HyperJump/Speed/God/Strengh sticks, LegendaryStoneOfPower,
// XpBerries, HangGlider (PalaItemUseEvents) ;
// - clic droit bloc : semis x4, XpBush, ExtrapolatedBucket, recolte stades murs (PalaItemUseEvents) ;
// - casse : niveaux Pioche divine + XP 25, Marteau 3x3, recoltes x8, farmland sous cultures x5,
// loterie graines sur herbe (PalaToolEvents) ;
// - croissance cultures x5 via suivi de positions (PalaCropEvents) ;
// - commandes /end /nether /overworld : portees par le scope sibling
// fr.surviepote.pala.PalaCommands (reutilise ici, pas de doublon) ;
// - ProcedureDurability : helper fondu dans hurtAndBreak.
//
// SKIP avec raisons (9) :
// - ProcedureAngelicWaterMobplayerCollidesBlock, ProcedureFakeWaterMobplayerCollidesBlock :
// fluides non portes (voir consignes) ;
// - ProcedureDynamiteBulletHitsBlock, ProcedureEndiumDynamiteHit :
// declencheurs lies aux guns non portes ;
// - ProcedureLengendaryStoneOfTeleportationRightClickedInAir : procedure d'origine vide (no-op) ;
// - ProcedurePalaAppleFoodEaten : pas de hook "nourriture mangee" dans fabric-api sans mixin ;
// - ProcedurePaladiumCrusherUpdateTick, ProcedurePaladiumCrusherGenerateButton,
// ProcedurePaladiumFurnaceUpdateTick : TileEntity + GUIs non portes (voir consignes).
public final class PalaEvents {
private PalaEvents() {
}
public static void registerAll() {
PalaArmorEvents.register();
PalaItemUseEvents.register();
PalaToolEvents.register();
PalaCropEvents.register();
PalaCommands.register();
}
}
@@ -0,0 +1,220 @@
package fr.surviepote.pala.events;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.PalaItems;
// Portage des procedures "clic droit" MCreator :
// - batons : ProcedureHealStick/ HyperJumpStick/ SpeedStick/ StickOfGod/ StrenghStickRightClickedInAir
// (cooldown 100, usure 1, son, effet(s)) ;
// - ProcedureLegendaryStoneOfPowerRightClickedInAir (regen + resistance, gros cooldown) ;
// - ProcedureXpBerriesRightClickedInAir (+38 XP, consomme 1 baie) ;
// - ProcedureHangGliderRightClickedInAir (levitation negative = plane, + resistance) ;
// - ProcedurePalaAppleFoodEaten : SKIP (pas de hook "nourriture mangee" dans fabric-api
// sans mixin ; TODO si mixin LivingEntity#completeUsing juge utile) ;
// - semis sur farmland : ProcedureFikutsiRighClickedOnBlock, ProcedureKiwano/O kami/OrangeBlueRightClickedOnBlock ;
// - ProcedureXpBushPlantRightClicked (donne une baie) ;
// - ProcedureExtrapolatedBucketRightClickedOnBlock (retire lave/eau source) ;
// - recolte clic droit des stades murs : ProcedureFikutsiStage3Casser, ProcedureOkamiStage3Casser
// (+ equivalents kiwano/orangebleue, coherents avec leurs handlers de casse).
public final class PalaItemUseEvents {
private PalaItemUseEvents() {
}
public static void register() {
UseItemCallback.EVENT.register(PalaItemUseEvents::onUseItem);
UseBlockCallback.EVENT.register(PalaItemUseEvents::onUseBlock);
}
private static void effect(Player player, Holder<MobEffect> effect, int duration, int amplifier) {
player.addEffect(new MobEffectInstance(effect, duration, amplifier, false, false));
}
private static void stickBaseline(ServerPlayer player, ServerLevel level, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
player.getCooldowns().addCooldown(stack, 100);
stack.hurtAndBreak(1, player, hand);
BlockPos pos = player.blockPosition();
level.playSound(null, pos.getX(), pos.getY(), pos.getZ(),
SoundEvents.ENDER_DRAGON_AMBIENT, SoundSource.NEUTRAL, 1.0F, 1.0F);
}
private static InteractionResult onUseItem(Player player, Level level, InteractionHand hand) {
if (level.isClientSide() || !(player instanceof ServerPlayer sp)) {
return InteractionResult.PASS;
}
ServerLevel sl = sp.level();
ItemStack stack = player.getItemInHand(hand);
if (stack.isEmpty()) {
return InteractionResult.PASS;
}
Item item = stack.getItem();
if (item == PalaItems.HEAL_STICK) {
stickBaseline(sp, sl, hand);
sp.addEffect(new MobEffectInstance(MobEffects.INSTANT_HEALTH, 1, 6, false, false));
return InteractionResult.PASS;
}
if (item == PalaItems.HYPER_JUMP_STICK) {
stickBaseline(sp, sl, hand);
effect(sp, MobEffects.JUMP_BOOST, 80, 40);
return InteractionResult.PASS;
}
if (item == PalaItems.SPEED_STICK) {
stickBaseline(sp, sl, hand);
effect(sp, MobEffects.SPEED, 80, 40);
return InteractionResult.PASS;
}
if (item == PalaItems.STICK_OF_GOD) {
stickBaseline(sp, sl, hand);
effect(sp, MobEffects.SPEED, 60, 5);
effect(sp, MobEffects.STRENGTH, 80, 2);
effect(sp, MobEffects.SATURATION, 240, 2);
effect(sp, MobEffects.REGENERATION, 60, 1);
return InteractionResult.PASS;
}
if (item == PalaItems.STRENGHT_STICK) {
ItemStack held = sp.getItemInHand(hand);
sp.getCooldowns().addCooldown(held, 100);
held.hurtAndBreak(1, sp, hand);
BlockPos pos = sp.blockPosition();
sl.playSound(null, pos.getX(), pos.getY(), pos.getZ(),
SoundEvents.WITHER_SHOOT, SoundSource.NEUTRAL, 1.0F, 1.0F);
effect(sp, MobEffects.STRENGTH, 60, 3);
return InteractionResult.PASS;
}
if (item == PalaItems.LEGENDARY_STONE_OF_POWER) {
sp.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 240, 3, true, true));
sp.addEffect(new MobEffectInstance(MobEffects.RESISTANCE, 240, 4, true, true));
sp.getCooldowns().addCooldown(stack, 192000);
return InteractionResult.PASS;
}
if (item == PalaItems.XP_BERRIES) {
sp.giveExperiencePoints(38);
stack.shrink(1);
return InteractionResult.PASS;
}
if (item == PalaItems.HANG_GLIDER) {
effect(sp, MobEffects.LEVITATION, 5, -4);
effect(sp, MobEffects.RESISTANCE, 1, 5);
return InteractionResult.PASS;
}
return InteractionResult.PASS;
}
private static InteractionResult onUseBlock(Player player, Level level, InteractionHand hand,
net.minecraft.world.phys.BlockHitResult hit) {
if (level.isClientSide() || !(player instanceof ServerPlayer sp)) {
return InteractionResult.PASS;
}
ServerLevel sl = sp.level();
BlockPos pos = hit.getBlockPos();
BlockState target = sl.getBlockState(pos);
ItemStack stack = player.getItemInHand(hand);
Item item = stack.isEmpty() ? null : stack.getItem();
// --- Semis sur farmland (graine en main, dessus libre) ---
if (target.getBlock() == Blocks.FARMLAND && item != null) {
Block crop = null;
if (item == PalaItems.FIKUTSI_SEEDS) {
crop = PalaBlocks.FIKUTSI_STAGE0;
} else if (item == PalaItems.KIWANO_SEEDS) {
crop = PalaBlocks.KIWANO_STAGE0;
} else if (item == PalaItems.OKAMI_SEEDS) {
crop = PalaBlocks.OKAMI_STAGE0;
} else if (item == PalaItems.ORANGE_BLUE_SEEDS) {
crop = PalaBlocks.ORANGE_BLUE_STAGE0;
}
if (crop != null && sl.getBlockState(pos.above()).isAir()) {
sl.setBlock(pos.above(), crop.defaultBlockState(), 3, 512);
PalaCropEvents.track(sl, pos.above());
if (!sp.isCreative()) {
stack.shrink(1);
}
return InteractionResult.SUCCESS;
}
}
// --- Recolte au clic droit des stades murs ---
Block matured = target.getBlock();
if (matured == PalaBlocks.FIKUTSI_STAGE3) {
sl.destroyBlock(pos, false, sp, 512);
drop(sl, pos, PalaItems.EGG_PLANT_FRUIT, 1);
drop(sl, pos, PalaItems.FIKUTSI_SEEDS, 1);
PalaCropEvents.untrack(sl, pos);
return InteractionResult.SUCCESS;
}
if (matured == PalaBlocks.OKAMI_STAGE3) {
sl.destroyBlock(pos, false, sp, 512);
drop(sl, pos, PalaItems.OKAMI_FRUIT, 1);
drop(sl, pos, PalaItems.OKAMI_SEEDS, 1);
PalaCropEvents.untrack(sl, pos);
return InteractionResult.SUCCESS;
}
if (matured == PalaBlocks.KIWANO_STAGE4) {
sl.destroyBlock(pos, false, sp, 512);
drop(sl, pos, PalaItems.KIWANO, 1);
drop(sl, pos, PalaItems.KIWANO_SEEDS, 1);
PalaCropEvents.untrack(sl, pos);
return InteractionResult.SUCCESS;
}
if (matured == PalaBlocks.ORANGE_BLUE_STAGE4) {
sl.destroyBlock(pos, false, sp, 512);
drop(sl, pos, PalaItems.ORANGE_BLUE_FRUIT, 1);
drop(sl, pos, PalaItems.ORANGE_BLUE_SEEDS, 1);
PalaCropEvents.untrack(sl, pos);
return InteractionResult.SUCCESS;
}
// --- Buisson XP : donne une baie (ProcedureXpBushPlantRightClicked) ---
if (matured == PalaBlocks.XP_BUSH) {
ItemStack berries = new ItemStack(PalaItems.XP_BERRIES, 1);
if (!sp.getInventory().add(berries)) {
drop(sl, pos, PalaItems.XP_BERRIES, 1);
}
return InteractionResult.SUCCESS;
}
// --- Seau extrapole : retire un bloc source de lave ou d'eau ---
if (item == PalaItems.EXTRAPOLATED_BUCKET
&& (sl.getFluidState(pos).is(FluidTags.LAVA) || sl.getFluidState(pos).is(FluidTags.WATER))
&& sl.getFluidState(pos).isSource()) {
stack.hurtAndBreak(1, sp, hand);
sl.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, 512);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}
static void drop(ServerLevel level, BlockPos pos, Item item, int count) {
ItemEntity entity = new ItemEntity(level, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
new ItemStack(item, count));
entity.setPickUpDelay(10);
level.addFreshEntity(entity);
}
}
@@ -0,0 +1,294 @@
package fr.surviepote.pala.events;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.PalaItems;
// Portage des procedures "bloc detruit avec l'outil / par le joueur" MCreator :
// - ProcedurePickaxeOfTheGodBlockDestroyedWithTool : compteur "level" en CustomData,
// evolution vers le niveau suivant aux seuils legacy, messages joueur ;
// - ProcedurePickaxeOfTheGodLevel25BlockDestroyedWithTool : +1 XP par bloc ;
// - ProcedurePaladiumHammerBlockDestroyedWithTool : casse 3x3 autour du bloc
// (plan horizontal ou vertical selon le pitch / l'orientation, jamais la bedrock) ;
// - recoltes : ProcedureFikutsi/Kiwano/Okami/OrangeBlueStage0BlockDestroyByPlayer
// (stade mur -> fruit, sinon -> graine) + bonus 30% des procedures
// *BlockDestroyedByPlayer + pepite d'endium 5% (ProcedureOrangeBlueStage4BlockDestroyedByPlayer) ;
// - ProcedureBreakBlockUnderCrops(+ForFikutsi/Kiwano/Okami/OrangeBlue) : si la farmland
// sous une culture disparait, la culture casse avec drop adapte ;
// - ProcedureHaveKiwanoSeeds : loterie de graines sur herbe coupee ;
// - ProcedureDurability : useure simple, reutilisee via hurtAndBreak dans les autres handlers.
public final class PalaToolEvents {
// Seuils legacy d'evolution : niveau courant -> (seuil, niveau suivant).
private record GodLevel(Item item, double threshold, Item next) {
}
private static final Set<Item> GOD_PICKAXES = new HashSet<>();
private static final Map<Item, GodLevel> GOD_UPGRADES = new java.util.HashMap<>();
static {
Item base = PalaItems.PICKAXE_OF_THE_GOD;
Item l1 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL1;
Item l2 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL2;
Item l3 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL3;
Item l4 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL4;
Item l5 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL5;
Item l6 = PalaItems.PICKAXE_OF_THE_GOD_LEVE6;
Item l7 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL7;
Item l8 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL8;
Item l9 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL9;
Item l10 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL10;
Item l11 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL11;
Item l12 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL12;
Item l13 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL13;
Item l14 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL14;
Item l15 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL15;
Item l16 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL16;
Item l17 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL17;
Item l18 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL18;
Item l19 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL19;
Item l20 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL20;
Item l21 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL21;
Item l22 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL22;
Item l23 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL23;
Item l24 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL24;
Item l25 = PalaItems.PICKAXE_OF_THE_GOD_LEVEL25;
Item[] chain = {base, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14,
l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, l25};
double[] thresholds = {25, 50, 100, 175, 300, 500, 750, 900, 1100, 1350, 1500, 1675, 1900,
2050, 2200, 2600, 2800, 3100, 3500, 3500, 3500, 3500, 3500, 3500, 3500};
for (Item item : chain) {
GOD_PICKAXES.add(item);
}
for (int i = 0; i < thresholds.length; i++) {
GOD_UPGRADES.put(chain[i], new GodLevel(chain[i], thresholds[i], chain[i + 1]));
}
}
private PalaToolEvents() {
}
public static void register() {
PlayerBlockBreakEvents.AFTER.register(PalaToolEvents::afterBreak);
}
private static void afterBreak(Level level, Player player, BlockPos pos, BlockState state,
BlockEntity blockEntity) {
if (level.isClientSide() || !(level instanceof ServerLevel sl)
|| !(player instanceof ServerPlayer sp)) {
return;
}
Block broken = state.getBlock();
ItemStack hand = sp.getMainHandItem();
Item held = hand.isEmpty() ? null : hand.getItem();
// --- Pioche divine : compteur + evolution ---
if (held != null && GOD_PICKAXES.contains(held)) {
if (held == PalaItems.PICKAXE_OF_THE_GOD_LEVEL25) {
sp.giveExperiencePoints(1);
} else {
GodLevel upgrade = GOD_UPGRADES.get(held);
if (upgrade != null) {
double value = hand.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY)
.copyTag().getDoubleOr("level", -1.0) + 1.0;
if (value >= upgrade.threshold()) {
sp.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(upgrade.next(), 1));
sp.sendSystemMessage(Component.literal("§2Your "
+ new ItemStack(held).getItemName().getString()
+ " §2Leveled Up to "
+ new ItemStack(upgrade.next()).getItemName().getString()));
} else {
final double stored = value;
CustomData.update(DataComponents.CUSTOM_DATA, hand,
tag -> tag.putDouble("level", stored));
sp.sendOverlayMessage(Component.literal("§6You Need to Mine "
+ (int) (upgrade.threshold() - stored) + " §6To Level Up"));
}
}
}
}
// --- Marteau paladium : 3x3 ---
if (held == PalaItems.PALADIUM_HAMMER) {
hammerArea(sl, sp, pos);
}
// --- Recoltes : drops selon stade ---
handleCropBreak(sl, broken, pos);
// --- Farmland cassee sous une culture -> la culture casse aussi ---
if (broken == Blocks.FARMLAND) {
BlockPos above = pos.above();
Block crop = sl.getBlockState(above).getBlock();
if (isCropStage(crop)) {
sl.destroyBlock(above, false, sp, 512);
PalaCropEvents.untrack(sl, above);
dropForUprooted(sl, above, crop);
}
}
// --- Herbe coupee : loterie de graines ---
if (broken == Blocks.SHORT_GRASS) {
roll(sp, sl, pos, 0.004, PalaItems.ORANGE_BLUE_SEEDS);
roll(sp, sl, pos, 0.005, PalaItems.KIWANO_SEEDS);
roll(sp, sl, pos, 0.02, PalaItems.FIKUTSI_SEEDS);
roll(sp, sl, pos, 0.01, PalaItems.OKAMI_SEEDS);
roll(sp, sl, pos, 0.005, PalaItems.KIWANO_SEEDS);
roll(sp, sl, pos, 0.004, PalaItems.ORANGE_BLUE_SEEDS);
roll(sp, sl, pos, 0.02, PalaItems.FIKUTSI_SEEDS);
roll(sp, sl, pos, 0.01, PalaItems.OKAMI_SEEDS);
roll(sp, sl, pos, 0.005, PalaItems.ORANGE_BLUE_SEEDS);
roll(sp, sl, pos, 0.009, PalaItems.KIWANO_SEEDS);
roll(sp, sl, pos, 0.02, PalaItems.FIKUTSI_SEEDS);
roll(sp, sl, pos, 0.01, PalaItems.OKAMI_SEEDS);
}
}
private static void roll(ServerPlayer player, ServerLevel level, BlockPos pos, double chance, Item item) {
if (Math.random() < chance) {
PalaItemUseEvents.drop(level, pos, item, 1);
}
}
private static boolean isCropStage(Block block) {
return block == PalaBlocks.FIKUTSI_STAGE0 || block == PalaBlocks.FIKUTSI_STAGE1
|| block == PalaBlocks.FIKUTSI_STAGE2 || block == PalaBlocks.FIKUTSI_STAGE3
|| block == PalaBlocks.KIWANO_STAGE0 || block == PalaBlocks.KIWANO_STAGE1
|| block == PalaBlocks.KIWANO_STAGE2 || block == PalaBlocks.KIWANO_STAGE3
|| block == PalaBlocks.KIWANO_STAGE4 || block == PalaBlocks.OKAMI_STAGE0
|| block == PalaBlocks.OKAMI_STAGE1 || block == PalaBlocks.OKAMI_STAGE2
|| block == PalaBlocks.OKAMI_STAGE3 || block == PalaBlocks.ORANGE_BLUE_STAGE0
|| block == PalaBlocks.ORANGE_BLUE_STAGE1 || block == PalaBlocks.ORANGE_BLUE_STAGE2
|| block == PalaBlocks.ORANGE_BLUE_STAGE3 || block == PalaBlocks.ORANGE_BLUE_STAGE4;
}
private static void handleCropBreak(ServerLevel level, Block broken, BlockPos pos) {
if (broken == PalaBlocks.FIKUTSI_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.EGG_PLANT_FRUIT, 1);
PalaItemUseEvents.drop(level, pos, PalaItems.FIKUTSI_SEEDS, 1);
} else if (broken == PalaBlocks.FIKUTSI_STAGE0 || broken == PalaBlocks.FIKUTSI_STAGE1
|| broken == PalaBlocks.FIKUTSI_STAGE2) {
PalaItemUseEvents.drop(level, pos, PalaItems.FIKUTSI_SEEDS, 1);
if (Math.random() < 0.3) {
PalaItemUseEvents.drop(level, pos, PalaItems.EGG_PLANT_FRUIT, 1);
}
} else if (broken == PalaBlocks.KIWANO_STAGE4) {
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO, 1);
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO_SEEDS, 1);
} else if (broken == PalaBlocks.KIWANO_STAGE0 || broken == PalaBlocks.KIWANO_STAGE1
|| broken == PalaBlocks.KIWANO_STAGE2 || broken == PalaBlocks.KIWANO_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO_SEEDS, 1);
if (Math.random() < 0.3) {
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO, 1);
}
} else if (broken == PalaBlocks.OKAMI_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_FRUIT, 1);
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_SEEDS, 1);
} else if (broken == PalaBlocks.OKAMI_STAGE0 || broken == PalaBlocks.OKAMI_STAGE1
|| broken == PalaBlocks.OKAMI_STAGE2) {
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_SEEDS, 1);
if (Math.random() < 0.3) {
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_FRUIT, 1);
}
} else if (broken == PalaBlocks.ORANGE_BLUE_STAGE4) {
if (Math.random() < 0.05) {
PalaItemUseEvents.drop(level, pos, PalaItems.ENDIUM_NUGGET, 1);
}
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_FRUIT, 1);
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_SEEDS, 1);
} else if (broken == PalaBlocks.ORANGE_BLUE_STAGE0 || broken == PalaBlocks.ORANGE_BLUE_STAGE1
|| broken == PalaBlocks.ORANGE_BLUE_STAGE2 || broken == PalaBlocks.ORANGE_BLUE_STAGE3) {
if (Math.random() < 0.05) {
PalaItemUseEvents.drop(level, pos, PalaItems.ENDIUM_NUGGET, 1);
}
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_SEEDS, 1);
if (Math.random() < 0.3) {
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_FRUIT, 1);
}
} else {
return;
}
PalaCropEvents.untrack(level, pos);
}
private static void dropForUprooted(ServerLevel level, BlockPos pos, Block crop) {
if (crop == PalaBlocks.FIKUTSI_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.EGG_PLANT_FRUIT, 1);
} else if (crop == PalaBlocks.KIWANO_STAGE4) {
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO, 1);
} else if (crop == PalaBlocks.OKAMI_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_FRUIT, 1);
} else if (crop == PalaBlocks.ORANGE_BLUE_STAGE4) {
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_FRUIT, 1);
} else if (crop == PalaBlocks.FIKUTSI_STAGE0 || crop == PalaBlocks.FIKUTSI_STAGE1
|| crop == PalaBlocks.FIKUTSI_STAGE2) {
PalaItemUseEvents.drop(level, pos, PalaItems.FIKUTSI_SEEDS, 1);
} else if (crop == PalaBlocks.KIWANO_STAGE0 || crop == PalaBlocks.KIWANO_STAGE1
|| crop == PalaBlocks.KIWANO_STAGE2 || crop == PalaBlocks.KIWANO_STAGE3) {
PalaItemUseEvents.drop(level, pos, PalaItems.KIWANO_SEEDS, 1);
} else if (crop == PalaBlocks.OKAMI_STAGE0 || crop == PalaBlocks.OKAMI_STAGE1
|| crop == PalaBlocks.OKAMI_STAGE2) {
PalaItemUseEvents.drop(level, pos, PalaItems.OKAMI_SEEDS, 1);
} else {
PalaItemUseEvents.drop(level, pos, PalaItems.ORANGE_BLUE_SEEDS, 1);
}
}
// Casse 3x3 autour du bloc : plan horizontal si le joueur vise vers le bas/haut,
// plan vertical face a lui sinon. Jamais la bedrock, jamais les blocs sans drop durci.
private static void hammerArea(ServerLevel level, ServerPlayer player, BlockPos center) {
int[][] offsets;
float pitch = player.getXRot();
if (pitch > 40.0F || pitch < -40.0F) {
offsets = new int[][]{{1, 0, 0}, {-1, 0, 0}, {1, 0, 1}, {1, 0, -1},
{-1, 0, -1}, {-1, 0, 1}, {0, 0, 1}, {0, 0, -1}};
} else {
net.minecraft.core.Direction facing = player.getDirection();
if (facing == net.minecraft.core.Direction.NORTH || facing == net.minecraft.core.Direction.SOUTH) {
offsets = new int[][]{{1, 0, 0}, {-1, 0, 0}, {1, 1, 0}, {-1, -1, 0},
{-1, 1, 0}, {1, -1, 0}, {0, 1, 0}, {0, -1, 0}};
} else {
offsets = new int[][]{{0, 0, 1}, {0, 0, -1}, {0, 1, 1}, {0, -1, -1},
{0, 1, -1}, {0, -1, 1}, {0, 1, 0}, {0, -1, 0}};
}
}
for (int[] o : offsets) {
BlockPos target = center.offset(o[0], o[1], o[2]);
BlockState state = level.getBlockState(target);
if (state.isAir() || state.getBlock() == Blocks.BEDROCK) {
continue;
}
if (state.getDestroySpeed(level, target) < 0.0F) {
continue;
}
level.destroyBlock(target, true, player, 512);
}
}
// Registre des niveaux de pioche divine reconnus (utile pour extensions).
static boolean isGodPickaxe(Item item) {
return GOD_PICKAXES.contains(item);
}
}
@@ -0,0 +1,39 @@
package fr.surviepote.pala.item;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.hurtingprojectile.SmallFireball;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
// Portage minimal des 3 guns Pala (Dynamite, Ninja Dynamite, Endium Dynamite).
// Origine (Forge 1.12, MCreator) : item a charge qui tirait une fleche custom
// avec degats/knockback reglables + explosion a l'impact (procedures
// DynamiteBulletHitsBlock / EndiumDynamiteHit, non portees).
// Ici : tire un projectile vanilla SmallFireball (enflamme + degats).
// TODO : entite custom pour retrouver degats 1.2-1.3, knockback 2-3 et
// l'explosion de puissance 2 a l'impact ; consommation de munitions.
public class DynamiteGunItem extends Item {
private final float speed;
public DynamiteGunItem(float speed) {
super(new Properties().stacksTo(1));
this.speed = speed;
}
@Override
public InteractionResult use(Level level, Player player, net.minecraft.world.InteractionHand hand) {
if (level instanceof ServerLevel serverLevel) {
SmallFireball ball = new SmallFireball(serverLevel, player, player.getLookAngle().scale(speed));
serverLevel.addFreshEntity(ball);
level.playSound(null, player.getX(), player.getY(), player.getZ(),
SoundEvents.FIRECHARGE_USE, SoundSource.PLAYERS, 1.0F, 1.0F);
player.getCooldowns().addCooldown(player.getItemInHand(hand), 15);
}
return InteractionResult.SUCCESS;
}
}
@@ -0,0 +1,57 @@
package fr.surviepote.pala.machine;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
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.SoundType;
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.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
// 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,
// le reste inutilise) + logique de cuisson serveur.
// TODO : ScreenHandler + ecran customs (slots places comme le legacy),
// bouton Generate du crusher, vraies recettes, textures de faces.
public class PalaMachineBlock extends Block implements EntityBlock {
public PalaMachineBlock() {
super(BlockBehaviour.Properties.of().strength(3.5F, 10.0F).sound(SoundType.METAL)
.requiresCorrectToolForDrops());
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new PalaMachineBlockEntity(pos, state);
}
@Override
@SuppressWarnings("unchecked")
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
if (level instanceof ServerLevel) {
return (lvl, pos, blockState, blockEntity) -> {
if (blockEntity instanceof PalaMachineBlockEntity machine) {
machine.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) {
player.openMenu(provider);
}
return InteractionResult.SUCCESS;
}
}
@@ -0,0 +1,106 @@
package fr.surviepote.pala.machine;
import fr.surviepote.pala.PalaBlockEntities;
import fr.surviepote.pala.PalaBlocks;
import fr.surviepote.pala.PalaItems;
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.item.Items;
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;
// 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).
public class PalaMachineBlockEntity extends BlockEntity implements MenuProvider {
private static final int COOK_TIME_FURNACE = 200;
private static final int COOK_TIME_CRUSHER = 100;
private final SimpleContainer inventory = new SimpleContainer(9);
private int progress;
public PalaMachineBlockEntity(BlockPos pos, BlockState state) {
super(PalaBlockEntities.MACHINE, pos, state);
}
public boolean isCrusher() {
return getBlockState().is(PalaBlocks.PALADIUM_CRUSHER);
}
public void serverTick() {
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)
&& (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) {
progress = 0;
input.shrink(1);
fuel.shrink(1);
if (output.isEmpty()) {
inventory.setItem(2, result.copy());
} else {
output.grow(result.getCount());
}
}
setChanged();
} else if (progress != 0) {
progress = 0;
setChanged();
}
}
private static ItemStack smeltResult(ItemStack input) {
if (input.is(PalaBlocks.PALADIUM_ORE.asItem())) {
return new ItemStack(PalaItems.PALADIUM_INGOT);
}
if (input.is(PalaBlocks.PALADIUM_GREEN_ORE.asItem())) {
return new ItemStack(PalaItems.PALADIUM_GREEN_INGOT);
}
return ItemStack.EMPTY;
}
private static boolean isFuel(ItemStack stack) {
return stack.is(Items.COAL) || stack.is(Items.CHARCOAL);
}
@Override
protected void saveAdditional(ValueOutput output) {
super.saveAdditional(output);
inventory.storeAsItemList(output.list("Items", ItemStack.CODEC));
output.putInt("Progress", progress);
}
@Override
protected void loadAdditional(ValueInput input) {
super.loadAdditional(input);
inventory.fromItemList(input.listOrEmpty("Items", ItemStack.CODEC));
progress = input.getIntOr("Progress", 0);
}
@Override
public Component getDisplayName() {
return Component.translatable(isCrusher() ? "container.pala.paladium_crusher" : "container.pala.paladium_furnace");
}
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new DispenserMenu(containerId, playerInventory, inventory);
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "pala:block/angelic_water"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "pala:block/fake_water"
}
}
}
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "pala:block/paladium_furnace"
}
}
}
@@ -153,5 +153,17 @@
"block.pala.tranny": "Tranny",
"block.pala.trixium_ore": "Trixium Ore",
"block.pala.trixium_ore_block": "Trixium Block",
"block.pala.xp_bush": "Xp Bush"
"block.pala.xp_bush": "Xp Bush",
"item.pala.dynamite": "Dynamite",
"item.pala.dynamite_ninja": "Ninja Dynamite",
"item.pala.endium_dynamite": "Endium Dynamite",
"item.pala.angelic_water": "AngelicWater",
"item.pala.fake_water": "FakeWater",
"item.pala.angelic_water_bucket": "Angelic Water Bucket",
"item.pala.fake_water_bucket": "Fake Water Bucket",
"block.pala.angelic_water": "AngelicWater",
"block.pala.fake_water": "FakeWater",
"block.pala.paladium_furnace": "Paladium Furnace",
"container.pala.paladium_crusher": "Paladium Crusher",
"container.pala.paladium_furnace": "PaladiumFurnace"
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "pala:block/angelicwater_still"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "pala:block/sulfuricwater_still"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "pala:block/paladium_furnace_side"
}
}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/block/angelicwater_still"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/bucket_angelic"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/dynamite"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/dynamite_ninja"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/dynamite_endium"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/block/sulfuricwater_still"}}
@@ -0,0 +1 @@
{"parent": "minecraft:item/generated", "textures": {"layer0": "pala:item/bucket_sulfuric"}}
@@ -0,0 +1,3 @@
{
"parent": "pala:block/paladium_furnace"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,5 @@
{
"animation": {
"frametime": 2
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,3 @@
{
"animation": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

@@ -0,0 +1,3 @@
{
"animation": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,5 @@
{
"animation": {
"frametime": 2
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

@@ -0,0 +1,33 @@
{
"display": {
"icon": {
"id": "pala:endium_nugget"
},
"title": {
"text": "First Endium"
},
"description": {
"text": "First Endium"
},
"frame": "goal",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"has_nugget": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": ["pala:endium_nugget"]
}
]
}
}
},
"requirements": [["has_nugget"]],
"rewards": {
"experience": 4
}
}
@@ -0,0 +1,33 @@
{
"display": {
"icon": {
"id": "pala:endium_ingot"
},
"title": {
"text": "First Endium Ingot"
},
"description": {
"text": "this player have crafted a endium ingot for the first time"
},
"frame": "challenge",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"has_ingot": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": ["pala:endium_ingot"]
}
]
}
}
},
"requirements": [["has_ingot"]],
"rewards": {
"experience": 4
}
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:amethyst_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:amethyst_ingot"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/amethyst_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:amethyst_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/amethyst_ore_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:amethyst_spike"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/amethyst_spike"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:cave_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/cave_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:fikutsi_stage0"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/fikutsi_stage0"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:fikutsi_stage1"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/fikutsi_stage1"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:fikutsi_stage2"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/fikutsi_stage2"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:fikutsi_stage3"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/fikutsi_stage3"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:findium_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:findium_gem"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/findium_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:findium_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/findium_ore_block"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:kisakay_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:kisakay_ingot"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kisakay_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kisakay_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kisakay_ore_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kiwano_stage0"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kiwano_stage0"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kiwano_stage1"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kiwano_stage1"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kiwano_stage2"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kiwano_stage2"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kiwano_stage3"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kiwano_stage3"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:kiwano_stage4"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/kiwano_stage4"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:okami_stage0"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/okami_stage0"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:okami_stage1"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/okami_stage1"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:okami_stage2"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/okami_stage2"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:okami_stage3"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/okami_stage3"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:orange_blue_stage0"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/orange_blue_stage0"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:orange_blue_stage1"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/orange_blue_stage1"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:orange_blue_stage2"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/orange_blue_stage2"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:orange_blue_stage3"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/orange_blue_stage3"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:orange_blue_stage4"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/orange_blue_stage4"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:paladium_crusher"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/paladium_crusher"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:paladium_green_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:paladium_green_ingot"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/paladium_green_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:paladium_green_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/paladium_green_ore_block"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:paladium_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:paladium_ingot"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/paladium_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:paladium_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/paladium_ore_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:slime_pad"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/slime_pad"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:titane_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:titane_ingot"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/titane_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:titane_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/titane_ore_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:tranny"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/tranny"
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:block",
"pools": [
{
"entries": [
{
"type": "minecraft:alternatives",
"children": [
{
"type": "minecraft:item",
"condition": "minecraft:tool/can_silk_touch",
"name": "pala:trixium_ore"
},
{
"type": "minecraft:item",
"modifier": [
{
"type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{
"type": "minecraft:explosion_decay"
}
],
"name": "pala:trixium_gem"
}
]
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/trixium_ore"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:trixium_ore_block"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/trixium_ore_block"
}
@@ -0,0 +1,18 @@
{
"type": "minecraft:block",
"pools": [
{
"condition": {
"type": "minecraft:survives_explosion"
},
"entries": [
{
"type": "minecraft:item",
"name": "pala:xp_bush"
}
],
"rolls": 1
}
],
"random_sequence": "pala:blocks/xp_bush"
}