diff --git a/PALAMOD_CDC.md b/PALAMOD_CDC.md index b8bab99..2f3b934 100644 --- a/PALAMOD_CDC.md +++ b/PALAMOD_CDC.md @@ -612,6 +612,10 @@ avant M4 (TODO:crafts-machines). UNVERIFIED en jeu. - M-faction-1c LIVRE 2026-10-19 ~04:20 : /f desc (chef, 140 car., sans speciaux — wiki) + /f help. VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu. +- M-faction-2 LIVRE 2026-10-19 ~04:30 : claims de chunks (/f claim/unclaim/unclaimall, + quota factionMaxClaims=10 UNVERIFIED) + protection stricte (membres+OP, wilderness libre). + Lecon : ResourceKey.location() n'existe plus en 26.3 -> identifier(). Grades/regions/elo : + M-faction-3. 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 + 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 diff --git a/mods/pala/src/main/java/fr/surviepote/pala/core/PalaConfig.java b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaConfig.java index 3f37eac..8a76ac8 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/core/PalaConfig.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaConfig.java @@ -85,6 +85,9 @@ public final class PalaConfig { // M-afk (wiki reglement/grades) : kick apres N minutes sans activite (defaut 10). public int afkKickMinutes = 10; + // M-faction-2 : claims de chunks (quota par faction, defaut 10, UNVERIFIED). + public int factionMaxClaims = 10; + // M-rtp (wiki commandes) : cooldown minutes entre deux /rtp (wiki : 15). public int rtpCooldownMinutes = 15; // Rayon max du /rtp autour du spawn (blocs). UNVERIFIED (wiki : "aleatoire", sans borne). @@ -234,7 +237,8 @@ public final class PalaConfig { "crusherResults", "crusherFuels", "crusherInfiniteFuels", "furnaceSmelts", "furnaceFuels", "serverName", "wikiUrl", "discordUrl", "shopUrl", - "afkKickMinutes", "rtpCooldownMinutes", "rtpRadius"); + "afkKickMinutes", "rtpCooldownMinutes", "rtpRadius", + "factionMaxClaims"); boolean complete = true; try (Reader keysReader = Files.newBufferedReader(path)) { com.google.gson.JsonObject obj = diff --git a/mods/pala/src/main/java/fr/surviepote/pala/core/PalaFactions.java b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaFactions.java index b5bb50d..15bc8cd 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/core/PalaFactions.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaFactions.java @@ -30,6 +30,8 @@ public final class PalaFactions { public List members = new ArrayList<>(); public String description = ""; public List invites = new ArrayList<>(); + // M-faction-2 : chunks revendiques ("dimension:x:z"). + public List claims = new ArrayList<>(); } private final Map factions = new HashMap<>(); @@ -66,6 +68,16 @@ public final class PalaFactions { dirty = true; } + /** Faction proprietaire du chunk (cle "dimension:x:z"), ou null. */ + public Faction byClaim(String key) { + for (Faction faction : factions.values()) { + if (faction.claims != null && faction.claims.contains(key)) { + return faction; + } + } + return null; + } + public void remove(String name) { if (factions.remove(name.toLowerCase(java.util.Locale.ROOT)) != null) { dirty = true; @@ -99,6 +111,9 @@ public final class PalaFactions { if (faction.invites == null) { faction.invites = new ArrayList<>(); } + if (faction.claims == null) { + faction.claims = new ArrayList<>(); + } factions.put(String.valueOf(entry.getKey()), faction); } } diff --git a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaEvents.java b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaEvents.java index a19e3f9..05a3eb2 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaEvents.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaEvents.java @@ -35,6 +35,7 @@ public final class PalaEvents { public static void registerAll() { PalaAfk.register(); + PalaFactionProtect.register(); PalaArmorEvents.register(); PalaItemUseEvents.register(); PalaToolEvents.register(); diff --git a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaFactionProtect.java b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaFactionProtect.java new file mode 100644 index 0000000..d0c7844 --- /dev/null +++ b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaFactionProtect.java @@ -0,0 +1,77 @@ +package fr.surviepote.pala.events; + +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.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; + +import fr.surviepote.pala.core.PalaFactions; + +// M-faction-2 (wiki Gestion faction + grades) : protection des chunks revendiques. +// Sans systeme de grades/regions (GUI, M-faction-3) : regle stricte — seuls les membres +// et les OP peuvent casser/poser/utiliser dans un chunk claim. Wilderness = libre. +public final class PalaFactionProtect { + + private PalaFactionProtect() { + } + + /** Cle de chunk "dimension:x:z". */ + public static String key(ServerLevel level, BlockPos pos) { + return level.dimension().identifier().toString() + ":" + + (pos.getX() >> 4) + ":" + (pos.getZ() >> 4); + } + + /** Vrai si le joueur peut agir ici (membre de la faction proprietaire, ou OP, ou libre). */ + public static boolean canAct(ServerPlayer player, ServerLevel level, BlockPos pos) { + PalaFactions.Faction owner = + PalaFactions.get().byClaim(key(level, pos)); + if (owner == null) { + return true; + } + if (owner.members.contains(player.getUUID().toString())) { + return true; + } + return net.minecraft.commands.Commands.LEVEL_ADMINS + .check(player.permissions()); + } + + public static void register() { + PlayerBlockBreakEvents.BEFORE.register(PalaFactionProtect::beforeBreak); + UseBlockCallback.EVENT.register(PalaFactionProtect::onUseBlock); + } + + private static boolean beforeBreak(Level level, Player player, BlockPos pos, BlockState state, + BlockEntity blockEntity) { + if (level.isClientSide() || !(level instanceof ServerLevel sl) + || !(player instanceof ServerPlayer sp)) { + return true; + } + if (canAct(sp, sl, pos)) { + return true; + } + sp.sendSystemMessage(Component.literal("§cTerritoire de faction protege.")); + return false; + } + + private static InteractionResult onUseBlock(Player player, Level level, InteractionHand hand, + BlockHitResult hit) { + if (level.isClientSide() || !(level instanceof ServerLevel sl) + || !(player instanceof ServerPlayer sp)) { + return InteractionResult.PASS; + } + if (canAct(sp, sl, hit.getBlockPos())) { + return InteractionResult.PASS; + } + return InteractionResult.FAIL; + } +} diff --git a/server/mods/pala-0.2.1.jar b/server/mods/pala-0.2.1.jar index 069fb7b..9ac93c2 100644 Binary files a/server/mods/pala-0.2.1.jar and b/server/mods/pala-0.2.1.jar differ