pala M-afk: kick inactivite + bypass grade (wiki reglement)
This commit is contained in:
@@ -591,6 +591,11 @@ avant M4 (TODO:crafts-machines).
|
|||||||
vert = +50 000 XP fermier, rainbow = +50 000 aux 4 metiers (wiki VERIFIE). Autres couleurs
|
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
|
= mapping non publie (TODO:mapping-bonbons, sans effet). VERIFIE : build SUCCESSFUL, boot
|
||||||
Done, 0 erreur, lang 228 cles. UNVERIFIED en jeu.
|
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 +
|
- 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.
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ public final class PalaConfig {
|
|||||||
public String discordUrl = "https://discord.gg/paladium";
|
public String discordUrl = "https://discord.gg/paladium";
|
||||||
public String shopUrl = "https://boutique.paladium-pvp.fr/";
|
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).
|
// Cooldowns sticks PvP en secondes. UNVERIFIED (durees balance staff, M5).
|
||||||
public Map<String, Integer> stickCooldowns = new HashMap<>(Map.of(
|
public Map<String, Integer> stickCooldowns = new HashMap<>(Map.of(
|
||||||
"heal_stick", 60, "speed_stick", 30, "hyper_jump_stick", 30,
|
"heal_stick", 60, "speed_stick", 30, "hyper_jump_stick", 30,
|
||||||
@@ -204,7 +207,8 @@ public final class PalaConfig {
|
|||||||
"rankNodes", "hunterKills", "farmerHarvest", "crusherXp",
|
"rankNodes", "hunterKills", "farmerHarvest", "crusherXp",
|
||||||
"crusherResults", "crusherFuels", "crusherInfiniteFuels",
|
"crusherResults", "crusherFuels", "crusherInfiniteFuels",
|
||||||
"furnaceSmelts", "furnaceFuels",
|
"furnaceSmelts", "furnaceFuels",
|
||||||
"serverName", "wikiUrl", "discordUrl", "shopUrl");
|
"serverName", "wikiUrl", "discordUrl", "shopUrl",
|
||||||
|
"afkKickMinutes");
|
||||||
boolean complete = true;
|
boolean complete = true;
|
||||||
try (Reader keysReader = Files.newBufferedReader(path)) {
|
try (Reader keysReader = Files.newBufferedReader(path)) {
|
||||||
com.google.gson.JsonObject obj =
|
com.google.gson.JsonObject obj =
|
||||||
|
|||||||
@@ -27,6 +27,22 @@ public final class PalaPermissions {
|
|||||||
PalaStorage.get().markDirty();
|
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<String> 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.
|
/** 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). */
|
* Prend la source (PermissionSet vanilla 26.3, verifie au javap) + le joueur (rang interne). */
|
||||||
public static boolean has(CommandSourceStack source, ServerPlayer player, String node) {
|
public static boolean has(CommandSourceStack source, ServerPlayer player, String node) {
|
||||||
|
|||||||
@@ -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<java.util.UUID, Snapshot> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ public final class PalaEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void registerAll() {
|
public static void registerAll() {
|
||||||
|
PalaAfk.register();
|
||||||
PalaArmorEvents.register();
|
PalaArmorEvents.register();
|
||||||
PalaItemUseEvents.register();
|
PalaItemUseEvents.register();
|
||||||
PalaToolEvents.register();
|
PalaToolEvents.register();
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user