diff --git a/PALAMOD_CDC.md b/PALAMOD_CDC.md index fe1e320..d6921e9 100644 --- a/PALAMOD_CDC.md +++ b/PALAMOD_CDC.md @@ -534,6 +534,10 @@ avant M4 (TODO:crafts-machines). APIs verifiees javap) + /spawn (tp spawn overworld, delai wiki 3 s via END_SERVER_TICK, file UUID). Refacto teleport() vers teleportPlayer(). VERIFIE : build SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu (pas de joueur). +- M-tpa LIVRE 2026-10-19 ~02:50 : /tpa (demande, expire 60 s) + /tpaccept (tp dans 3 s + wiki + invisibilite 15 s wiki via MobEffectInstance, APIs verifiees javap) + /tpdeny. + Bug corrige avant build : tp vers la cible (TpaTask), pas vers soi-meme. VERIFIE : build + SUCCESSFUL, boot Done, 0 erreur. UNVERIFIED en jeu (2 joueurs requis). - 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/PalaCommands.java b/mods/pala/src/main/java/fr/surviepote/pala/PalaCommands.java index ae65c0b..247badd 100644 --- a/mods/pala/src/main/java/fr/surviepote/pala/PalaCommands.java +++ b/mods/pala/src/main/java/fr/surviepote/pala/PalaCommands.java @@ -34,6 +34,16 @@ public final class PalaCommands { // M-cmd-util : /spawn differe (delai wiki 3 s = 60 ticks). UUID -> tick d'execution. private static final java.util.Map SPAWN_QUEUE = new java.util.HashMap<>(); + // M-tpa (wiki commandes) : demandes /tpa en attente. Cible -> (demandeur, tick d'expiration). + private static final java.util.Map TPA_REQUESTS = new java.util.HashMap<>(); + // TP differees vers un joueur (acceptees) : teleporte -> (cible, tick d'execution). + private static final java.util.Map TPA_QUEUE = new java.util.HashMap<>(); + + private record TpaRequest(java.util.UUID from, long expireTick) { + } + + private record TpaTask(java.util.UUID target, long at) { + } private PalaCommands() { } @@ -78,8 +88,18 @@ public final class PalaCommands { .executes(command -> craft(command.getSource()))); dispatcher.register(Commands.literal("spawn") .executes(command -> spawn(command.getSource()))); + dispatcher.register(Commands.literal("tpa") + .then(Commands.argument("cible", EntityArgument.player()) + .executes(command -> tpa(command.getSource(), + EntityArgument.getPlayer(command, "cible"))))); + dispatcher.register(Commands.literal("tpaccept") + .executes(command -> tpRespond(command.getSource(), true))); + dispatcher.register(Commands.literal("tpdeny") + .executes(command -> tpRespond(command.getSource(), false))); net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents.END_SERVER_TICK .register(PalaCommands::tickSpawnQueue); + net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents.END_SERVER_TICK + .register(PalaCommands::tickTpaQueue); }); } @@ -280,4 +300,90 @@ public final class PalaCommands { teleportPlayer(player, overworld, overworld.getRespawnData().pos()); } } + + // /tpa : demande de tp (expire apres 60 s). /tpaccept : tp dans 3 s (wiki) + + // invisibilite 15 s du teleporte (wiki). /tpdeny : refus. + private static int tpa(CommandSourceStack source, ServerPlayer cible) { + try { + ServerPlayer player = source.getPlayerOrException(); + if (player.getUUID().equals(cible.getUUID())) { + source.sendFailure(Component.literal("§cDemande vers soi-meme impossible.")); + return 0; + } + MinecraftServer server = source.getServer(); + TPA_REQUESTS.put(cible.getUUID(), + new TpaRequest(player.getUUID(), (long) server.getTickCount() + 1200L)); + player.sendSystemMessage(Component.literal( + "§6[Pala] §7Demande envoyee a " + cible.getScoreboardName() + ".")); + cible.sendSystemMessage(Component.literal("§6[Pala] §7" + player.getScoreboardName() + + " veut se teleporter a vous : §a/tpaccept §7ou §c/tpdeny §7(60 s).")); + return Command.SINGLE_SUCCESS; + } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { + return 0; + } + } + + private static int tpRespond(CommandSourceStack source, boolean accept) { + try { + ServerPlayer player = source.getPlayerOrException(); + MinecraftServer server = source.getServer(); + TpaRequest request = TPA_REQUESTS.remove(player.getUUID()); + if (request == null || server.getTickCount() > request.expireTick()) { + source.sendFailure(Component.literal("§cAucune demande en attente.")); + return 0; + } + ServerPlayer demandeur = server.getPlayerList().getPlayer(request.from()); + if (demandeur == null) { + source.sendFailure(Component.literal("§cDemandeur deconnecte.")); + return 0; + } + if (!accept) { + demandeur.sendSystemMessage(Component.literal("§6[Pala] §7" + + player.getScoreboardName() + " a refuse votre demande.")); + player.sendSystemMessage(Component.literal("§6[Pala] §7Demande refusee.")); + return Command.SINGLE_SUCCESS; + } + TPA_QUEUE.put(demandeur.getUUID(), + new TpaTask(player.getUUID(), (long) server.getTickCount() + 60L)); + demandeur.sendSystemMessage(Component.literal( + "§6[Pala] §7Demande acceptee, teleportation dans 3 secondes...")); + player.sendSystemMessage(Component.literal("§6[Pala] §7Demande acceptee.")); + return Command.SINGLE_SUCCESS; + } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { + return 0; + } + } + + private static void tickTpaQueue(MinecraftServer server) { + if (TPA_QUEUE.isEmpty()) { + if (!TPA_REQUESTS.isEmpty()) { + int now = server.getTickCount(); + TPA_REQUESTS.entrySet().removeIf(entry -> now > entry.getValue().expireTick()); + } + return; + } + int now = server.getTickCount(); + java.util.Iterator> it = + TPA_QUEUE.entrySet().iterator(); + while (it.hasNext()) { + java.util.Map.Entry entry = it.next(); + if (now < entry.getValue().at()) { + continue; + } + it.remove(); + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); + ServerPlayer cible = server.getPlayerList().getPlayer(entry.getValue().target()); + if (player == null || cible == null) { + continue; + } + ServerLevel level = cible.level(); + BlockPos pos = cible.blockPosition(); + player.teleport(new TeleportTransition(level, new Vec3(pos.getX() + 0.5, pos.getY() + 1.0, + pos.getZ() + 0.5), Vec3.ZERO, cible.getYRot(), cible.getXRot(), + TeleportTransition.DO_NOTHING)); + player.addEffect(new net.minecraft.world.effect.MobEffectInstance( + net.minecraft.world.effect.MobEffects.INVISIBILITY, 300, 0, false, false)); + } + TPA_REQUESTS.entrySet().removeIf(entry -> now > entry.getValue().expireTick()); + } } diff --git a/server/mods/pala-0.2.1.jar b/server/mods/pala-0.2.1.jar index d11e220..3859f5e 100644 Binary files a/server/mods/pala-0.2.1.jar and b/server/mods/pala-0.2.1.jar differ