Added Carrying Players by pressing V

This commit is contained in:
IM23a-spirgif
2025-04-25 18:43:11 +02:00
parent 4216aea33e
commit 0fad7fbdd3
6 changed files with 173 additions and 5 deletions
@@ -0,0 +1,129 @@
package net.fretux.knockedback;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
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 java.util.*;
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class CarryManager {
private static final Map<UUID, UUID> carrying = new HashMap<>();
private static final double CARRY_RANGE = 2.0;
public static void toggleCarry(ServerPlayer carrier) {
Optional<Player> existing = carrier.getPassengers().stream()
.filter(p -> p instanceof Player)
.map(p -> (Player)p)
.findFirst();
if (existing.isPresent()) {
stopCarry(existing.get(), carrier);
return;
}
Player near = findNearestKnocked(carrier);
if (near != null) {
startCarry(carrier, near);
}
}
private static Player findNearestKnocked(ServerPlayer carrier) {
AABB box = carrier.getBoundingBox().inflate(CARRY_RANGE);
return carrier
.getCommandSenderWorld()
.getEntitiesOfClass(Player.class, box).stream()
.filter(p -> KnockedManager.isKnocked(p)
&& !p.getUUID().equals(carrier.getUUID()))
.findFirst()
.orElse(null);
}
private static void startCarry(ServerPlayer carrier, Player knocked) {
// mount
knocked.startRiding(carrier, true);
carrying.put(knocked.getUUID(), carrier.getUUID());
carrier.sendSystemMessage(Component.literal("Picked up " + knocked.getName().getString()));
knocked.sendSystemMessage(Component.literal("You are being carried by " + carrier.getName().getString()));
knocked.startRiding(carrier, true);
carrying.put(knocked.getUUID(), carrier.getUUID());
carrier.connection.send(new ClientboundSetPassengersPacket(carrier));
}
private static void stopCarry(Player knocked, ServerPlayer carrier) {
knocked.stopRiding();
carrying.remove(knocked.getUUID());
carrier.connection.send(new ClientboundSetPassengersPacket(carrier));
carrier.sendSystemMessage(Component.literal("Dropped " + knocked.getName().getString()));
knocked.sendSystemMessage(Component.literal("You have been dropped"));
}
/**
* Called each server tick to drop if carrier hurt or out of range
*/
@SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent ev) {
if (ev.phase != TickEvent.Phase.END || !ev.side.isServer()) return;
var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
List<UUID> toDrop = new ArrayList<>();
for (var entry : carrying.entrySet()) {
UUID knockedId = entry.getKey();
UUID carrierId = entry.getValue();
ServerPlayer carrier = NetworkHandlerHelper.getPlayerByUuid(server, carrierId);
ServerPlayer knocked = NetworkHandlerHelper.getPlayerByUuid(server, knockedId);
if (carrier == null || knocked == null
|| !KnockedManager.isKnocked(knocked)
|| carrier.distanceTo(knocked) > CARRY_RANGE) {
toDrop.add(knockedId);
}
}
for (UUID kid : toDrop) {
UUID cid = carrying.get(kid);
ServerPlayer carrier = NetworkHandlerHelper.getPlayerByUuid(
net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(), cid);
ServerPlayer knocked = NetworkHandlerHelper.getPlayerByUuid(
net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(), kid);
if (carrier != null && knocked != null) stopCarry(knocked, carrier);
}
}
@SubscribeEvent
public static void onEntityMount(EntityMountEvent evt) {
if (!evt.isMounting()) {
if (evt.getEntityMounting() instanceof Player knocked
&& carrying.containsKey(knocked.getUUID())) {
evt.setCanceled(true);
}
}
}
/**
* Drop if carrier is hurt
*/
@SubscribeEvent
public static void onCarrierHurt(LivingHurtEvent ev) {
if (!(ev.getEntity() instanceof ServerPlayer carrier)) return;
carrying.entrySet().stream()
.filter(e -> e.getValue().equals(carrier.getUUID()))
.map(Map.Entry::getKey)
.findFirst()
.ifPresent(knockedId -> {
ServerPlayer knocked = NetworkHandlerHelper.getPlayerByUuid(
net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(), knockedId);
if (knocked != null) stopCarry(knocked, carrier);
});
}
public static boolean isBeingCarried(UUID knockedId) {
return carrying.containsKey(knockedId);
}
}
@@ -0,0 +1,20 @@
package net.fretux.knockedback;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public class CarryTogglePacket {
public static void encode(CarryTogglePacket msg, FriendlyByteBuf buf) {}
public static CarryTogglePacket decode(FriendlyByteBuf buf) { return new CarryTogglePacket(); }
public static void handle(CarryTogglePacket msg, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> {
ServerPlayer carrier = ctx.get().getSender();
if (carrier == null) return;
CarryManager.toggleCarry(carrier);
});
ctx.get().setPacketHandled(true);
}
}
@@ -65,12 +65,8 @@ public class KnockedManager {
Map.Entry<UUID, Integer> entry = it.next(); Map.Entry<UUID, Integer> entry = it.next();
UUID playerId = entry.getKey(); UUID playerId = entry.getKey();
int timeLeft = entry.getValue(); int timeLeft = entry.getValue();
// ① If a mob *or* a player is in the middle of executing them, pause:
if (MobKillHandler.isBeingMobExecuted(playerId) if (MobKillHandler.isBeingMobExecuted(playerId)
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) { || PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) {
// just re‑send the *current* timeLeft, do NOT decrement
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId); ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
if (p != null) { if (p != null) {
NetworkHandler.CHANNEL.send( NetworkHandler.CHANNEL.send(
@@ -80,7 +76,6 @@ public class KnockedManager {
} }
continue; continue;
} }
// ② Otherwise count down as normal: // ② Otherwise count down as normal:
timeLeft--; timeLeft--;
if (timeLeft <= 0) { if (timeLeft <= 0) {
@@ -15,5 +15,6 @@ public class NetworkHandler {
CHANNEL.registerMessage(id++, ExecuteKnockedPacket.class, ExecuteKnockedPacket::encode, ExecuteKnockedPacket::decode, ExecuteKnockedPacket::handle); CHANNEL.registerMessage(id++, ExecuteKnockedPacket.class, ExecuteKnockedPacket::encode, ExecuteKnockedPacket::decode, ExecuteKnockedPacket::handle);
CHANNEL.registerMessage(id++, KnockedTimePacket.class, KnockedTimePacket::encode, KnockedTimePacket::decode, KnockedTimePacket::handle); CHANNEL.registerMessage(id++, KnockedTimePacket.class, KnockedTimePacket::encode, KnockedTimePacket::decode, KnockedTimePacket::handle);
CHANNEL.registerMessage(id++, ExecutionProgressPacket.class, ExecutionProgressPacket::encode, ExecutionProgressPacket::decode, ExecutionProgressPacket::handle); CHANNEL.registerMessage(id++, ExecutionProgressPacket.class, ExecutionProgressPacket::encode, ExecutionProgressPacket::decode, ExecutionProgressPacket::handle);
CHANNEL.registerMessage(id++, CarryTogglePacket.class, CarryTogglePacket::encode, CarryTogglePacket::decode, CarryTogglePacket::handle);
} }
} }
@@ -50,6 +50,7 @@ public class PlayerExecutionHandler {
private static class PlayerExecutionAttempt { private static class PlayerExecutionAttempt {
private final UUID executorUuid; private final UUID executorUuid;
private int timeLeft; private int timeLeft;
public PlayerExecutionAttempt(UUID executorUuid) { public PlayerExecutionAttempt(UUID executorUuid) {
this.executorUuid = executorUuid; this.executorUuid = executorUuid;
this.timeLeft = EXECUTION_DELAY_TICKS; this.timeLeft = EXECUTION_DELAY_TICKS;
@@ -64,6 +65,10 @@ public class PlayerExecutionHandler {
public static void startExecution(ServerPlayer executor, Player target) { public static void startExecution(ServerPlayer executor, Player target) {
UUID knockedId = target.getUUID(); UUID knockedId = target.getUUID();
if (!KnockedManager.isKnocked(target)) return; if (!KnockedManager.isKnocked(target)) return;
if (CarryManager.isBeingCarried(target.getUUID())) {
executor.sendSystemMessage(Component.literal("Cannot execute someone you're carrying!"));
return;
}
if (executionAttempts.containsKey(knockedId)) return; if (executionAttempts.containsKey(knockedId)) return;
executionAttempts.put(knockedId, new PlayerExecutionAttempt(executor.getUUID())); executionAttempts.put(knockedId, new PlayerExecutionAttempt(executor.getUUID()));
executor.sendSystemMessage(Component.literal("Execution started...")); executor.sendSystemMessage(Component.literal("Execution started..."));
@@ -1,5 +1,6 @@
package net.fretux.knockedback.client; package net.fretux.knockedback.client;
import net.fretux.knockedback.CarryTogglePacket;
import net.fretux.knockedback.ExecuteKnockedPacket; import net.fretux.knockedback.ExecuteKnockedPacket;
import net.fretux.knockedback.NetworkHandler; import net.fretux.knockedback.NetworkHandler;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
@@ -29,6 +30,17 @@ public class ClientKeyHandler {
} }
} }
public static final KeyMapping CARRY_KEY = new KeyMapping(
"key.knockedback.carry",
GLFW.GLFW_KEY_V,
"key.categories.knockedback"
);
@SubscribeEvent
public static void registerCarryKey(RegisterKeyMappingsEvent e) {
e.register(CARRY_KEY);
}
@SubscribeEvent @SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) { public static void onClientTick(TickEvent.ClientTickEvent event) {
if (Minecraft.getInstance().screen != null) return; if (Minecraft.getInstance().screen != null) return;
@@ -41,5 +53,11 @@ public class ClientKeyHandler {
NetworkHandler.CHANNEL.sendToServer(new ExecuteKnockedPacket()); NetworkHandler.CHANNEL.sendToServer(new ExecuteKnockedPacket());
} }
} }
if (event.phase == TickEvent.Phase.END && CARRY_KEY.consumeClick()) {
Minecraft mc = Minecraft.getInstance();
if (mc.player != null && mc.screen == null) {
NetworkHandler.CHANNEL.sendToServer(new CarryTogglePacket());
}
}
} }
} }