From dbb226bcde255fe562df10f156431bf7739721f5 Mon Sep 17 00:00:00 2001 From: fretuks Date: Sat, 23 May 2026 19:44:51 +0200 Subject: [PATCH] add "Help Up" feature for knocked players, improve execution handling, and update mod version to 1.6.0 --- .../net/fretux/knockedback/CarryManager.java | 62 +++++++++++++++---- .../knockedback/ExecuteKnockedPacket.java | 5 +- .../net/fretux/knockedback/HelpUpHandler.java | 13 ++-- .../fretux/knockedback/KnockedManager.java | 9 +++ .../fretux/knockedback/MobKillHandler.java | 5 ++ .../knockedback/PlayerExecutionHandler.java | 32 +++++++--- 6 files changed, 100 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/fretux/knockedback/CarryManager.java b/src/main/java/net/fretux/knockedback/CarryManager.java index d32db78..4c3dc13 100644 --- a/src/main/java/net/fretux/knockedback/CarryManager.java +++ b/src/main/java/net/fretux/knockedback/CarryManager.java @@ -10,6 +10,7 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.event.entity.EntityMountEvent; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; +import net.minecraft.server.level.ServerLevel; import java.util.*; @@ -26,11 +27,15 @@ public class CarryManager { Optional existing = carrier.getPassengers().stream() .filter(p -> p instanceof Player) .map(p -> (Player) p) + .filter(p -> carrier.getUUID().equals(carrying.get(p.getUUID()))) .findFirst(); if (existing.isPresent()) { stopCarry(existing.get(), carrier); return; } + if (stopCarrying(carrier.getUUID())) { + return; + } Player near = findNearestKnocked(carrier); if (near != null) startCarry(carrier, near); } @@ -45,18 +50,19 @@ public class CarryManager { && !isBeingCarried(p.getUUID()) && !PlayerExecutionHandler.isBeingPlayerExecuted(p.getUUID()) && !HelpUpHandler.isBeingHelped(p.getUUID())) - .findFirst() + .min(Comparator.comparingDouble(carrier::distanceToSqr)) .orElse(null); } private static void startCarry(ServerPlayer carrier, Player knocked) { - knocked.startRiding(carrier, true); - carrying.put(knocked.getUUID(), carrier.getUUID()); - ClientboundSetPassengersPacket mountPacket = new ClientboundSetPassengersPacket(carrier); - carrier.connection.send(mountPacket); - if (knocked instanceof ServerPlayer spKnocked) { - spKnocked.connection.send(mountPacket); + if (knocked.level() != carrier.level()) { + return; } + if (!knocked.startRiding(carrier, true)) { + return; + } + carrying.put(knocked.getUUID(), carrier.getUUID()); + sendPassengerUpdate(carrier); KnockedbackAdvancements.recordCarry(carrier); carrier.sendSystemMessage(Component.translatable("message.knockedback.picked_up", knocked.getDisplayName())); knocked.sendSystemMessage(Component.translatable("message.knockedback.being_carried", carrier.getDisplayName())); @@ -66,15 +72,43 @@ public class CarryManager { private static void stopCarry(Player knocked, ServerPlayer carrier) { carrying.remove(knocked.getUUID()); knocked.stopRiding(); - ClientboundSetPassengersPacket dismountPacket = new ClientboundSetPassengersPacket(carrier); - carrier.connection.send(dismountPacket); - if (knocked instanceof ServerPlayer spKnocked) { - spKnocked.connection.send(dismountPacket); - } + sendPassengerUpdate(carrier); carrier.sendSystemMessage(Component.translatable("message.knockedback.dropped", knocked.getDisplayName())); knocked.sendSystemMessage(Component.translatable("message.knockedback.been_dropped", carrier.getDisplayName())); } + public static void stopCarry(UUID knockedId) { + UUID carrierId = carrying.get(knockedId); + if (carrierId == null) return; + var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); + ServerPlayer carrier = NetworkHandlerHelper.getPlayerByUuid(server, carrierId); + ServerPlayer knocked = NetworkHandlerHelper.getPlayerByUuid(server, knockedId); + if (carrier != null && knocked != null) { + stopCarry(knocked, carrier); + } else { + carrying.remove(knockedId); + } + } + + public static boolean stopCarrying(UUID carrierId) { + List knockedIds = carrying.entrySet().stream() + .filter(entry -> entry.getValue().equals(carrierId)) + .map(Map.Entry::getKey) + .toList(); + for (UUID knockedId : knockedIds) { + stopCarry(knockedId); + } + return !knockedIds.isEmpty(); + } + + private static void sendPassengerUpdate(ServerPlayer carrier) { + if (carrier.level() instanceof ServerLevel level) { + level.getChunkSource().broadcastAndSend(carrier, new ClientboundSetPassengersPacket(carrier)); + } else { + carrier.connection.send(new ClientboundSetPassengersPacket(carrier)); + } + } + @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent ev) { if (ev.phase != TickEvent.Phase.END || !ev.side.isServer()) return; @@ -87,7 +121,9 @@ public class CarryManager { ServerPlayer knocked = NetworkHandlerHelper.getPlayerByUuid(server, knockedId); if (carrier == null || knocked == null || !KnockedManager.isKnocked(knocked) - || carrier.distanceTo(knocked) > CARRY_RANGE) { + || carrier.level() != knocked.level() + || knocked.getVehicle() != carrier + || carrier.distanceToSqr(knocked) > CARRY_RANGE * CARRY_RANGE) { toDrop.add(knockedId); } } diff --git a/src/main/java/net/fretux/knockedback/ExecuteKnockedPacket.java b/src/main/java/net/fretux/knockedback/ExecuteKnockedPacket.java index afc9bb3..ddf3f82 100644 --- a/src/main/java/net/fretux/knockedback/ExecuteKnockedPacket.java +++ b/src/main/java/net/fretux/knockedback/ExecuteKnockedPacket.java @@ -45,8 +45,9 @@ public class ExecuteKnockedPacket { .map(uuid -> NetworkHandlerHelper.getPlayerByUuid(executor.getServer(), uuid)) .filter(player -> player != null && !player.getUUID().equals(executor.getUUID()) - && player.distanceTo(executor) <= (float) PlayerExecutionHandler.EXECUTION_RANGE) - .findFirst() + && player.level() == executor.level() + && player.distanceToSqr(executor) <= PlayerExecutionHandler.EXECUTION_RANGE * PlayerExecutionHandler.EXECUTION_RANGE) + .min(java.util.Comparator.comparingDouble(executor::distanceToSqr)) .orElse(null); } } diff --git a/src/main/java/net/fretux/knockedback/HelpUpHandler.java b/src/main/java/net/fretux/knockedback/HelpUpHandler.java index b94b20a..5a8502e 100644 --- a/src/main/java/net/fretux/knockedback/HelpUpHandler.java +++ b/src/main/java/net/fretux/knockedback/HelpUpHandler.java @@ -115,14 +115,17 @@ public class HelpUpHandler { HelpUpAttempt attempt = entry.getValue(); ServerPlayer knocked = getPlayerByUuid(knockedId); ServerPlayer helper = getPlayerByUuid(attempt.helperId); - if (knocked == null || helper == null || !KnockedManager.isKnocked(knocked)) { + if (knocked == null || helper == null + || !KnockedManager.isKnocked(knocked) + || KnockedManager.isKnocked(helper)) { toCancel.add(knockedId); continue; } if (CarryManager.isBeingCarried(knockedId) || PlayerExecutionHandler.isBeingPlayerExecuted(knockedId) || MobKillHandler.isBeingMobExecuted(knockedId) - || helper.distanceTo(knocked) > HELP_UP_RANGE) { + || helper.level() != knocked.level() + || helper.distanceToSqr(knocked) > HELP_UP_RANGE * HELP_UP_RANGE) { toCancel.add(knockedId); continue; } @@ -143,7 +146,9 @@ public class HelpUpHandler { if (attempt == null) continue; ServerPlayer knocked = getPlayerByUuid(knockedId); ServerPlayer helper = getPlayerByUuid(attempt.helperId); - if (knocked == null || helper == null) { + if (knocked == null || helper == null + || helper.level() != knocked.level() + || helper.distanceToSqr(knocked) > HELP_UP_RANGE * HELP_UP_RANGE) { cancelHelpUp(knockedId); continue; } @@ -190,7 +195,7 @@ public class HelpUpHandler { && !PlayerExecutionHandler.isBeingPlayerExecuted(player.getUUID()) && !MobKillHandler.isBeingMobExecuted(player.getUUID()) && !isBeingHelped(player.getUUID())) - .findFirst() + .min(java.util.Comparator.comparingDouble(helper::distanceToSqr)) .orElse(null); } diff --git a/src/main/java/net/fretux/knockedback/KnockedManager.java b/src/main/java/net/fretux/knockedback/KnockedManager.java index e9f6a99..c6c5005 100644 --- a/src/main/java/net/fretux/knockedback/KnockedManager.java +++ b/src/main/java/net/fretux/knockedback/KnockedManager.java @@ -69,9 +69,11 @@ public class KnockedManager { } public static void removeKnockedState(LivingEntity entity) { + CarryManager.stopCarry(entity.getUUID()); knockedEntities.remove(entity.getUUID()); setGripped(entity, false); MobKillHandler.clearKillAttempt(entity.getUUID()); + PlayerExecutionHandler.cancelExecution(entity.getUUID()); HelpUpHandler.cancelHelpUp(entity.getUUID()); entity.setPose(Pose.STANDING); if (entity instanceof ServerPlayer sp) { @@ -211,8 +213,12 @@ public class KnockedManager { knockedEntities.remove(playerId); grippedEntities.remove(playerId); MobKillHandler.clearKillAttempt(playerId); + PlayerExecutionHandler.cancelExecution(playerId); + PlayerExecutionHandler.cancelExecutionByExecutor(playerId); HelpUpHandler.cancelHelpUp(playerId); HelpUpHandler.cancelHelpUpByHelper(playerId); + CarryManager.stopCarry(playerId); + CarryManager.stopCarrying(playerId); NetworkHandler.CHANNEL.send( PacketDistributor.PLAYER.with(() -> sp), new KnockedTimePacket(0) @@ -238,7 +244,10 @@ public class KnockedManager { return; } HelpUpHandler.cancelHelpUpByHelper(sp.getUUID()); + PlayerExecutionHandler.cancelExecutionByExecutor(sp.getUUID()); + CarryManager.stopCarrying(sp.getUUID()); if (!isKnocked(sp)) { + CarryManager.stopCarry(sp.getUUID()); return; } killAndRemove(sp); diff --git a/src/main/java/net/fretux/knockedback/MobKillHandler.java b/src/main/java/net/fretux/knockedback/MobKillHandler.java index 3c4b79d..2296ba9 100644 --- a/src/main/java/net/fretux/knockedback/MobKillHandler.java +++ b/src/main/java/net/fretux/knockedback/MobKillHandler.java @@ -109,6 +109,11 @@ public class MobKillHandler { setGripped(knocked, false); continue; } + if (PlayerExecutionHandler.isBeingPlayerExecuted(knockedId) + || HelpUpHandler.isBeingHelped(knockedId)) { + setGripped(knocked, false); + continue; + } KillAttempt attempt = killAttempts.get(knockedId); Mob mob = attempt != null ? getMobInRangeById(knocked, attempt.mobUuid) : null; if (mob == null) { diff --git a/src/main/java/net/fretux/knockedback/PlayerExecutionHandler.java b/src/main/java/net/fretux/knockedback/PlayerExecutionHandler.java index c877349..d3878bd 100644 --- a/src/main/java/net/fretux/knockedback/PlayerExecutionHandler.java +++ b/src/main/java/net/fretux/knockedback/PlayerExecutionHandler.java @@ -70,13 +70,17 @@ public class PlayerExecutionHandler { executor.sendSystemMessage(Component.translatable("message.knockedback.cannot_execute_while_knocked")); return; } + if (isExecuting(executor.getUUID())) return; UUID knockedId = target.getUUID(); if (!KnockedManager.isKnocked(target)) return; + if (executor.level() != target.level() + || executor.distanceToSqr(target) > EXECUTION_RANGE * EXECUTION_RANGE) return; if (CarryManager.isBeingCarried(target.getUUID())) { executor.sendSystemMessage(Component.translatable("message.knockedback.cannot_execute_carried_player")); return; } if (HelpUpHandler.isBeingHelped(knockedId)) return; + if (MobKillHandler.isBeingMobExecuted(knockedId)) return; if (executionAttempts.containsKey(knockedId)) return; executionAttempts.put(knockedId, new PlayerExecutionAttempt(executor.getUUID())); executor.sendSystemMessage(Component.translatable("message.knockedback.execution_started")); @@ -105,12 +109,9 @@ public class PlayerExecutionHandler { } } - @SubscribeEvent - public static void onLivingHurt(LivingHurtEvent event) { - if (!(event.getEntity() instanceof ServerPlayer hurtPlayer)) return; - UUID hurtId = hurtPlayer.getUUID(); + public static void cancelExecutionByExecutor(UUID executorId) { List toCancel = executionAttempts.entrySet().stream() - .filter(entry -> entry.getValue().executorUuid.equals(hurtId)) + .filter(entry -> entry.getValue().executorUuid.equals(executorId)) .map(Map.Entry::getKey) .toList(); for (UUID knockedId : toCancel) { @@ -118,12 +119,24 @@ public class PlayerExecutionHandler { } } + @SubscribeEvent + public static void onLivingHurt(LivingHurtEvent event) { + if (!(event.getEntity() instanceof ServerPlayer hurtPlayer)) return; + cancelExecutionByExecutor(hurtPlayer.getUUID()); + } + private static ServerPlayer getPlayerByUuid(UUID uuid) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); return server.getPlayerList().getPlayer(uuid); } public static void executeKnockedPlayer(ServerPlayer executor, LivingEntity knockedPlayer) { + if (!KnockedManager.isKnocked(knockedPlayer) + || executor.level() != knockedPlayer.level() + || executor.distanceToSqr(knockedPlayer) > EXECUTION_RANGE * EXECUTION_RANGE) { + cancelExecution(knockedPlayer.getUUID()); + return; + } UUID id = knockedPlayer.getUUID(); executionAttempts.remove(id); KnockedManager.removeKnockedState(knockedPlayer); @@ -159,11 +172,16 @@ public class PlayerExecutionHandler { PlayerExecutionAttempt attempt = entry.getValue(); ServerPlayer knocked = getPlayerByUuid(knockedId); ServerPlayer executor = getPlayerByUuid(attempt.executorUuid); - if (knocked == null || executor == null || !KnockedManager.isKnocked(knocked)) { + if (knocked == null || executor == null + || !KnockedManager.isKnocked(knocked) + || KnockedManager.isKnocked(executor)) { toCancel.add(knockedId); continue; } - if (executor.distanceTo(knocked) > EXECUTION_RANGE) { + if (executor.level() != knocked.level() + || executor.distanceToSqr(knocked) > EXECUTION_RANGE * EXECUTION_RANGE + || CarryManager.isBeingCarried(knockedId) + || HelpUpHandler.isBeingHelped(knockedId)) { toCancel.add(knockedId); continue; }