diff --git a/PALAMOD_CDC.md b/PALAMOD_CDC.md index 2490749..4aa359d 100644 --- a/PALAMOD_CDC.md +++ b/PALAMOD_CDC.md @@ -591,6 +591,11 @@ avant M4 (TODO:crafts-machines). vert = +50 000 XP fermier, rainbow = +50 000 aux 4 metiers (wiki VERIFIE). Autres couleurs = mapping non publie (TODO:mapping-bonbons, sans effet). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur, lang 228 cles. UNVERIFIED en jeu. +- M-afk LIVRE 2026-10-19 ~03:50 : kick AFK (wiki reglement/grades) : inactivite pos+rot + controlee chaque seconde, limite afkKickMinutes (defaut 10), bypass pala.afk.bypass. + Lecon : authlib absent du compileClasspath (getGameProfile inutilisable) -> PermissionSet + joueur (player.permissions()). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur, 20 cles. + UNVERIFIED en jeu (10 min d'inactivite requises). - 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 (creatif, cheats), /give, pose de bloc, inventaire, F3+T. Screens : scratch vis*.png. 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 25d56a1..4eca7f9 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 @@ -67,6 +67,9 @@ public final class PalaConfig { public String discordUrl = "https://discord.gg/paladium"; public String shopUrl = "https://boutique.paladium-pvp.fr/"; + // M-afk (wiki reglement/grades) : kick apres N minutes sans activite (defaut 10). + public int afkKickMinutes = 10; + // Cooldowns sticks PvP en secondes. UNVERIFIED (durees balance staff, M5). public Map stickCooldowns = new HashMap<>(Map.of( "heal_stick", 60, "speed_stick", 30, "hyper_jump_stick", 30, @@ -204,7 +207,8 @@ public final class PalaConfig { "rankNodes", "hunterKills", "farmerHarvest", "crusherXp", "crusherResults", "crusherFuels", "crusherInfiniteFuels", "furnaceSmelts", "furnaceFuels", - "serverName", "wikiUrl", "discordUrl", "shopUrl"); + "serverName", "wikiUrl", "discordUrl", "shopUrl", + "afkKickMinutes"); 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/PalaPermissions.java b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaPermissions.java index d016a8f..51e754d 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/core/PalaPermissions.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/core/PalaPermissions.java @@ -27,6 +27,22 @@ public final class PalaPermissions { PalaStorage.get().markDirty(); } + /** OP niveau 2+ bypass tout (PermissionSet joueur, meme pattern que has) ; sinon rang. */ + public static boolean hasNode(ServerPlayer player, String node) { + if (net.minecraft.commands.Commands.LEVEL_ADMINS.check(player.permissions())) { + return true; + } + List nodes = PalaConfig.get().rankNodes.getOrDefault(rankOf(player), List.of()); + if (nodes.contains(node) || nodes.contains("pala.*")) { + return true; + } + int dot = node.lastIndexOf('.'); + if (dot > 0 && nodes.contains(node.substring(0, dot) + ".*")) { + return true; + } + return false; + } + /** OP niveau 2+ (LEVEL_ADMINS) bypass tout ; sinon noeud exact ou wildcard pala.* du rang. * Prend la source (PermissionSet vanilla 26.3, verifie au javap) + le joueur (rang interne). */ public static boolean has(CommandSourceStack source, ServerPlayer player, String node) { diff --git a/mods/pala/src/main/java/fr/surviepote/pala/events/PalaAfk.java b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaAfk.java new file mode 100644 index 0000000..21ae0f0 --- /dev/null +++ b/mods/pala/src/main/java/fr/surviepote/pala/events/PalaAfk.java @@ -0,0 +1,58 @@ +package fr.surviepote.pala.events; + +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; + +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; + +import fr.surviepote.pala.core.PalaConfig; +import fr.surviepote.pala.core.PalaPermissions; + +// M-afk (wiki reglement + grades) : les fermes AFK sont interdites et le kick AFK existe +// (durees par grade : 10/15/20 min + bonus). Ici : limite unique en config (defaut 10 min, +// afkKickMinutes), bypass par noeud pala.afk.bypass (grades via /pala rank + rankNodes). +// Activite = position + rotation : identiques d'un controle a l'autre (1 s) = inactif. +public final class PalaAfk { + + private PalaAfk() { + } + + private record Snapshot(double x, double y, double z, float yaw, float pitch, long seconds) { + } + + private static final java.util.Map SEEN = new java.util.HashMap<>(); + private static int tick; + + public static void register() { + ServerTickEvents.END_SERVER_TICK.register(server -> { + if (++tick % 20 != 0) { + return; + } + int limit = PalaConfig.get().afkKickMinutes * 60; + for (ServerPlayer player : server.getPlayerList().getPlayers()) { + Snapshot prev = SEEN.get(player.getUUID()); + Snapshot now = new Snapshot(player.getX(), player.getY(), player.getZ(), + player.getYRot(), player.getXRot(), 0); + if (prev != null && prev.x() == now.x() && prev.y() == now.y() + && prev.z() == now.z() && prev.yaw() == now.yaw() + && prev.pitch() == now.pitch()) { + long seconds = prev.seconds() + 1; + if (seconds >= limit + && !PalaPermissions.hasNode(player, "pala.afk.bypass")) { + SEEN.remove(player.getUUID()); + player.connection.disconnect(Component.literal( + "§cExpulse pour AFK (" + PalaConfig.get().afkKickMinutes + + " min sans activite).")); + continue; + } + SEEN.put(player.getUUID(), + new Snapshot(now.x(), now.y(), now.z(), now.yaw(), now.pitch(), + seconds)); + } else { + SEEN.put(player.getUUID(), + new Snapshot(now.x(), now.y(), now.z(), now.yaw(), now.pitch(), 0)); + } + } + }); + } +} 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 331c2cb..a19e3f9 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 @@ -34,6 +34,7 @@ public final class PalaEvents { } public static void registerAll() { + PalaAfk.register(); PalaArmorEvents.register(); PalaItemUseEvents.register(); PalaToolEvents.register(); diff --git a/server/mods/pala-0.2.1.jar b/server/mods/pala-0.2.1.jar index 5ee96e0..45105fd 100644 Binary files a/server/mods/pala-0.2.1.jar and b/server/mods/pala-0.2.1.jar differ