Added Carrying Players by pressing V
This commit is contained in:
@@ -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();
|
||||
UUID playerId = entry.getKey();
|
||||
int timeLeft = entry.getValue();
|
||||
|
||||
// ① If a mob *or* a player is in the middle of executing them, pause:
|
||||
if (MobKillHandler.isBeingMobExecuted(playerId)
|
||||
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) {
|
||||
|
||||
// just re‑send the *current* timeLeft, do NOT decrement
|
||||
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
||||
if (p != null) {
|
||||
NetworkHandler.CHANNEL.send(
|
||||
@@ -80,7 +76,6 @@ public class KnockedManager {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ② Otherwise count down as normal:
|
||||
timeLeft--;
|
||||
if (timeLeft <= 0) {
|
||||
|
||||
@@ -15,5 +15,6 @@ public class NetworkHandler {
|
||||
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++, 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 final UUID executorUuid;
|
||||
private int timeLeft;
|
||||
|
||||
public PlayerExecutionAttempt(UUID executorUuid) {
|
||||
this.executorUuid = executorUuid;
|
||||
this.timeLeft = EXECUTION_DELAY_TICKS;
|
||||
@@ -64,6 +65,10 @@ public class PlayerExecutionHandler {
|
||||
public static void startExecution(ServerPlayer executor, Player target) {
|
||||
UUID knockedId = target.getUUID();
|
||||
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;
|
||||
executionAttempts.put(knockedId, new PlayerExecutionAttempt(executor.getUUID()));
|
||||
executor.sendSystemMessage(Component.literal("Execution started..."));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.fretux.knockedback.client;
|
||||
|
||||
import net.fretux.knockedback.CarryTogglePacket;
|
||||
import net.fretux.knockedback.ExecuteKnockedPacket;
|
||||
import net.fretux.knockedback.NetworkHandler;
|
||||
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
|
||||
public static void onClientTick(TickEvent.ClientTickEvent event) {
|
||||
if (Minecraft.getInstance().screen != null) return;
|
||||
@@ -41,5 +53,11 @@ public class ClientKeyHandler {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user