Refactor MobKillHandler logic and increase execution delay.
This commit is contained in:
@@ -1,179 +1,153 @@
|
|||||||
package net.fretux.knockedback;
|
package net.fretux.knockedback;
|
||||||
|
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
|
||||||
import net.minecraft.world.entity.Mob;
|
import net.minecraft.world.entity.Mob;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||||
import net.minecraftforge.event.TickEvent;
|
import net.minecraftforge.event.TickEvent;
|
||||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static net.fretux.knockedback.KnockedManager.removeKnockedState;
|
import static net.fretux.knockedback.KnockedManager.removeKnockedState;
|
||||||
import static net.fretux.knockedback.KnockedManager.setGripped;
|
import static net.fretux.knockedback.KnockedManager.setGripped;
|
||||||
|
|
||||||
|
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||||
public class MobKillHandler {
|
public class MobKillHandler {
|
||||||
private static final int EXECUTION_DELAY_TICKS = 3 * 20;
|
private static final int EXECUTION_DELAY_TICKS = 3 * 20;
|
||||||
|
|
||||||
public static boolean isBeingMobExecuted(UUID knockedId) {
|
|
||||||
return killAttempts.containsKey(knockedId);
|
|
||||||
}
|
|
||||||
private static final Map<UUID, KillAttempt> killAttempts = new HashMap<>();
|
private static final Map<UUID, KillAttempt> killAttempts = new HashMap<>();
|
||||||
|
|
||||||
private static class KillAttempt {
|
private static class KillAttempt {
|
||||||
private final UUID mobUuid;
|
private final UUID mobUuid;
|
||||||
private int timeLeft;
|
private int timeLeft;
|
||||||
|
|
||||||
public KillAttempt(UUID mobUuid, int timeLeft) {
|
public KillAttempt(UUID mobUuid, int timeLeft) {
|
||||||
this.mobUuid = mobUuid;
|
this.mobUuid = mobUuid;
|
||||||
this.timeLeft = timeLeft;
|
this.timeLeft = timeLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isBeingMobExecuted(UUID knockedId) {
|
||||||
|
return killAttempts.containsKey(knockedId);
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onServerTick(TickEvent.ServerTickEvent event) {
|
public void onServerTick(TickEvent.ServerTickEvent event) {
|
||||||
if (event.phase == TickEvent.Phase.END && event.side.isServer()) {
|
if (event.phase != TickEvent.Phase.END || !event.side.isServer()) return;
|
||||||
tickKillAttempts();
|
tickKillAttempts();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onMobHurt(LivingHurtEvent event) {
|
public void onMobHurt(LivingHurtEvent event) {
|
||||||
LivingEntity entity = event.getEntity();
|
LivingEntity entity = event.getEntity();
|
||||||
if (!(entity instanceof Mob mob)) {
|
if (!(entity instanceof Mob mob)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
UUID mobUuid = mob.getUUID();
|
|
||||||
boolean mobWasReset = false;
|
|
||||||
UUID playerToRelease = null;
|
|
||||||
|
|
||||||
for (Map.Entry<UUID, KillAttempt> entry : killAttempts.entrySet()) {
|
UUID mobUuid = mob.getUUID();
|
||||||
KillAttempt attempt = entry.getValue();
|
UUID toRelease = null;
|
||||||
if (attempt.mobUuid.equals(mobUuid)) {
|
for (var e : killAttempts.entrySet()) {
|
||||||
playerToRelease = entry.getKey();
|
if (e.getValue().mobUuid.equals(mobUuid)) {
|
||||||
mobWasReset = true;
|
toRelease = e.getKey();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (toRelease != null) {
|
||||||
if (playerToRelease != null) {
|
killAttempts.remove(toRelease);
|
||||||
killAttempts.remove(playerToRelease);
|
Player p = getPlayerByUuid(toRelease);
|
||||||
Player player = getPlayerByUuid(playerToRelease);
|
if (p != null) {
|
||||||
if (player != null) {
|
setGripped(p, false);
|
||||||
KnockedManager.setGripped(player, false);
|
|
||||||
mob.setTarget(null);
|
mob.setTarget(null);
|
||||||
mob.getNavigation().stop();
|
mob.getNavigation().stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mobWasReset) {
|
|
||||||
System.out.println("Mob hit: Canceling execution attempt and releasing gripped player.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void clearKillAttempt(UUID playerUuid) {
|
|
||||||
killAttempts.remove(playerUuid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickKillAttempts() {
|
private void tickKillAttempts() {
|
||||||
Map<UUID, KillAttempt> updatedAttempts = new HashMap<>();
|
var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
|
||||||
|
Map<UUID, KillAttempt> updated = new HashMap<>();
|
||||||
for (UUID knockedPlayerUuid : KnockedManager.getKnockedUuids()) {
|
for (UUID knockedId : KnockedManager.getKnockedUuids()) {
|
||||||
Player knockedPlayer = getPlayerByUuid(knockedPlayerUuid);
|
Player knocked = getPlayerByUuid(knockedId);
|
||||||
if (knockedPlayer == null || !knockedPlayer.isAlive()) {
|
if (knocked == null || !knocked.isAlive()) continue;
|
||||||
|
if (CarryManager.isBeingCarried(knockedId)) {
|
||||||
|
setGripped(knocked, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Mob mobInRange = getMobInRange(knockedPlayer);
|
Mob mob = getMobInRange(knocked);
|
||||||
if (mobInRange == null) {
|
if (mob == null) {
|
||||||
setGripped(knockedPlayer, false);
|
setGripped(knocked, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
setGripped(knockedPlayer, true);
|
setGripped(knocked, true);
|
||||||
KillAttempt attempt = killAttempts.get(knockedPlayerUuid);
|
KillAttempt attempt = killAttempts.get(knockedId);
|
||||||
if (attempt == null || !attempt.mobUuid.equals(mobInRange.getUUID())) {
|
if (attempt == null || !attempt.mobUuid.equals(mob.getUUID())) {
|
||||||
attempt = new KillAttempt(mobInRange.getUUID(), EXECUTION_DELAY_TICKS);
|
attempt = new KillAttempt(mob.getUUID(), EXECUTION_DELAY_TICKS);
|
||||||
} else {
|
} else {
|
||||||
attempt.timeLeft--;
|
attempt.timeLeft--;
|
||||||
gripPlayer(knockedPlayer, mobInRange);
|
if (knocked instanceof ServerPlayer sp) {
|
||||||
|
NetworkHandler.CHANNEL.send(
|
||||||
|
PacketDistributor.PLAYER.with(() -> sp),
|
||||||
|
new ExecutionProgressPacket(attempt.timeLeft)
|
||||||
|
);
|
||||||
|
}
|
||||||
if (attempt.timeLeft <= 0) {
|
if (attempt.timeLeft <= 0) {
|
||||||
executeKnockedPlayer(knockedPlayer, mobInRange);
|
executeKnockedPlayer(knocked, mob);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatedAttempts.put(knockedPlayerUuid, attempt);
|
updated.put(knockedId, attempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5) Replace the map
|
||||||
killAttempts.clear();
|
killAttempts.clear();
|
||||||
killAttempts.putAll(updatedAttempts);
|
killAttempts.putAll(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gripPlayer(Player knockedPlayer, Mob mob) {
|
private void executeKnockedPlayer(Player knocked, Mob mob) {
|
||||||
mob.setTarget(knockedPlayer);
|
removeKnockedState(knocked);
|
||||||
|
knocked.setHealth(0.0F);
|
||||||
mob.getNavigation().stop();
|
mob.getNavigation().stop();
|
||||||
spawnExecutionParticles(knockedPlayer, mob);
|
if (knocked instanceof ServerPlayer sp) {
|
||||||
|
NetworkHandler.CHANNEL.send(
|
||||||
|
PacketDistributor.PLAYER.with(() -> sp),
|
||||||
|
new ExecutionProgressPacket(0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
knocked.sendSystemMessage(Component.literal(
|
||||||
private void executeKnockedPlayer(Player knockedPlayer, Mob mob) {
|
|
||||||
knockedPlayer.setHealth(0.0F);
|
|
||||||
mob.getNavigation().stop();
|
|
||||||
removeKnockedState(knockedPlayer);
|
|
||||||
knockedPlayer.sendSystemMessage(Component.literal(
|
|
||||||
"You were executed by " + mob.getName().getString() + "!"
|
"You were executed by " + mob.getName().getString() + "!"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Mob getMobInRange(Player knockedPlayer) {
|
private Mob getMobInRange(Player p) {
|
||||||
if (knockedPlayer.level() instanceof ServerLevel serverLevel) {
|
if (!(p.level() instanceof ServerLevel world)) return null;
|
||||||
double range = 2.5;
|
double r = 2.5;
|
||||||
AABB aabb = new AABB(
|
AABB box = new AABB(
|
||||||
knockedPlayer.getX() - range, knockedPlayer.getY() - range, knockedPlayer.getZ() - range,
|
p.getX()-r, p.getY()-r, p.getZ()-r,
|
||||||
knockedPlayer.getX() + range, knockedPlayer.getY() + range, knockedPlayer.getZ() + range
|
p.getX()+r, p.getY()+r, p.getZ()+r
|
||||||
);
|
);
|
||||||
return serverLevel.getEntitiesOfClass(Mob.class, aabb).stream()
|
return world.getEntitiesOfClass(Mob.class, box).stream()
|
||||||
.filter(mob -> isHostile(mob) || isAggressiveNeutral(mob))
|
.filter(m -> isHostile(m) || isAggressiveNeutral(m))
|
||||||
.findAny()
|
.findAny().orElse(null);
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHostile(Mob mob) {
|
private boolean isHostile(Mob m) {
|
||||||
return mob instanceof net.minecraft.world.entity.monster.Monster;
|
return m instanceof net.minecraft.world.entity.monster.Monster;
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAggressiveNeutral(Mob mob) {
|
|
||||||
if (mob instanceof net.minecraft.world.entity.animal.Wolf wolf) {
|
|
||||||
return wolf.isAngry();
|
|
||||||
}
|
|
||||||
if (mob instanceof net.minecraft.world.entity.monster.EnderMan enderman) {
|
|
||||||
return enderman.isCreepy();
|
|
||||||
}
|
}
|
||||||
|
private boolean isAggressiveNeutral(Mob m) {
|
||||||
|
if (m instanceof net.minecraft.world.entity.animal.Wolf w) return w.isAngry();
|
||||||
|
if (m instanceof net.minecraft.world.entity.monster.EnderMan e) return e.isCreepy();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Player getPlayerByUuid(UUID uuid) {
|
private Player getPlayerByUuid(UUID id) {
|
||||||
var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
|
var srv = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
|
||||||
if (server != null) {
|
return srv != null ? srv.getPlayerList().getPlayer(id) : null;
|
||||||
return server.getPlayerList().getPlayer(uuid);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void spawnExecutionParticles(Player knockedPlayer, Mob mobInRange) {
|
|
||||||
if (knockedPlayer.level() instanceof ServerLevel serverLevel) {
|
|
||||||
serverLevel.sendParticles(
|
|
||||||
net.minecraft.core.particles.ParticleTypes.ANGRY_VILLAGER,
|
|
||||||
mobInRange.getX(),
|
|
||||||
mobInRange.getY() + mobInRange.getBbHeight() / 2,
|
|
||||||
mobInRange.getZ(),
|
|
||||||
1, 0.1, 0.2, 0.1, 0.005
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ import java.util.UUID;
|
|||||||
@Mod.EventBusSubscriber(modid = "knockedback", bus = Mod.EventBusSubscriber.Bus.FORGE)
|
@Mod.EventBusSubscriber(modid = "knockedback", bus = Mod.EventBusSubscriber.Bus.FORGE)
|
||||||
public class PlayerExecutionHandler {
|
public class PlayerExecutionHandler {
|
||||||
public static final double EXECUTION_RANGE = 2.0;
|
public static final double EXECUTION_RANGE = 2.0;
|
||||||
public static final int EXECUTION_DELAY_TICKS = 60;
|
public static final int EXECUTION_DELAY_TICKS = 100;
|
||||||
|
|
||||||
public static boolean isBeingPlayerExecuted(UUID knockedId) {
|
public static boolean isBeingPlayerExecuted(UUID knockedId) {
|
||||||
return executionAttempts.containsKey(knockedId);
|
return executionAttempts.containsKey(knockedId);
|
||||||
|
|||||||
Reference in New Issue
Block a user