Add mob execution toggle and stabilize knocked handling

This commit is contained in:
2026-01-16 23:34:47 +01:00
parent a6cd828628
commit dbefdfaa46
3 changed files with 46 additions and 15 deletions
@@ -54,6 +54,7 @@ public class KnockedManager {
public static void onPlayerTick(TickEvent.PlayerTickEvent event) { public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
if (!(event.player instanceof ServerPlayer sp)) return; if (!(event.player instanceof ServerPlayer sp)) return;
if (KnockedManager.isKnocked(sp)) { if (KnockedManager.isKnocked(sp)) {
applyKnockedEffects(sp);
boolean grounded = sp.onGround() || sp.isInWater(); boolean grounded = sp.onGround() || sp.isInWater();
sp.setNoGravity(false); sp.setNoGravity(false);
if (!grounded) { if (!grounded) {
@@ -168,14 +169,24 @@ public class KnockedManager {
DamageSource src = event.getSource(); DamageSource src = event.getSource();
if (!(entity instanceof Player player)) return; if (!(entity instanceof Player player)) return;
if (killingNow.contains(player.getUUID())) return; if (killingNow.contains(player.getUUID())) return;
if (MobKillHandler.isBeingMobExecuted(player.getUUID()) boolean isFatal = player.getHealth() - event.getAmount() <= 0;
|| PlayerExecutionHandler.isBeingPlayerExecuted(player.getUUID())) { if (isKnocked(player)) {
if (event.getSource().getEntity() instanceof LivingEntity) { if (src.is(KnockedBackDamageTags.BYPASS_KNOCKDOWN)) {
event.setCanceled(true); if (isFatal) {
killAndRemove(player);
}
return;
} }
knockedEntities.put(player.getUUID(), getKnockedDuration());
applyKnockedEffects(player);
event.setCanceled(true);
return;
}
if (MobKillHandler.isBeingMobExecuted(player.getUUID())
|| PlayerExecutionHandler.isBeingPlayerExecuted(player.getUUID())) {
event.setCanceled(true);
return; return;
} }
boolean isFatal = player.getHealth() - event.getAmount() <= 0;
if (isFatal) { if (isFatal) {
if (src.is(KnockedBackDamageTags.BYPASS_KNOCKDOWN)) { if (src.is(KnockedBackDamageTags.BYPASS_KNOCKDOWN)) {
killAndRemove(player); killAndRemove(player);
@@ -184,18 +195,12 @@ public class KnockedManager {
} }
boolean hasTotem = player.getMainHandItem().is(Items.TOTEM_OF_UNDYING) boolean hasTotem = player.getMainHandItem().is(Items.TOTEM_OF_UNDYING)
|| player.getOffhandItem().is(Items.TOTEM_OF_UNDYING); || player.getOffhandItem().is(Items.TOTEM_OF_UNDYING);
if (!isKnocked(player)) { if (isFatal) {
if (isFatal) { if (!hasTotem || !Config.COMMON.totemPreventsKnockdown.get()) {
if (!hasTotem || !Config.COMMON.totemPreventsKnockdown.get()) { event.setCanceled(true);
event.setCanceled(true); applyKnockedState(player);
applyKnockedState(player);
}
} }
return;
} }
knockedEntities.put(player.getUUID(), getKnockedDuration());
applyKnockedEffects(player);
event.setCanceled(true);
} }
@SubscribeEvent @SubscribeEvent
@@ -79,6 +79,24 @@ public class MobKillHandler {
private void tickKillAttempts() { private void tickKillAttempts() {
var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
if (!Config.COMMON.mobExecutionEnabled.get()) {
if (!killAttempts.isEmpty()) {
for (UUID knockedId : new HashSet<>(killAttempts.keySet())) {
Player knocked = getPlayerByUuid(knockedId);
if (knocked instanceof ServerPlayer sp) {
NetworkHandler.CHANNEL.send(
PacketDistributor.PLAYER.with(() -> sp),
new ExecutionProgressPacket(0, null)
);
}
if (knocked != null) {
setGripped(knocked, false);
}
}
killAttempts.clear();
}
return;
}
Map<UUID, KillAttempt> updated = new HashMap<>(); Map<UUID, KillAttempt> updated = new HashMap<>();
for (UUID knockedId : KnockedManager.getKnockedUuids()) { for (UUID knockedId : KnockedManager.getKnockedUuids()) {
Player knocked = getPlayerByUuid(knockedId); Player knocked = getPlayerByUuid(knockedId);
@@ -176,6 +194,9 @@ public class MobKillHandler {
} }
private boolean isMobAllowedToExecute(Mob mob) { private boolean isMobAllowedToExecute(Mob mob) {
if (!Config.COMMON.mobExecutionEnabled.get()) {
return false;
}
List<? extends String> allowlist = Config.COMMON.mobExecutionAllowlist.get(); List<? extends String> allowlist = Config.COMMON.mobExecutionAllowlist.get();
if (allowlist.isEmpty()) { if (allowlist.isEmpty()) {
return true; return true;
@@ -17,6 +17,7 @@ public class Config {
public static class Common { public static class Common {
public final ForgeConfigSpec.IntValue knockedDuration; public final ForgeConfigSpec.IntValue knockedDuration;
public final ForgeConfigSpec.IntValue executionTime; public final ForgeConfigSpec.IntValue executionTime;
public final ForgeConfigSpec.BooleanValue mobExecutionEnabled;
public final ForgeConfigSpec.BooleanValue totemPreventsKnockdown; public final ForgeConfigSpec.BooleanValue totemPreventsKnockdown;
public final ForgeConfigSpec.ConfigValue<List<? extends String>> mobExecutionAllowlist; public final ForgeConfigSpec.ConfigValue<List<? extends String>> mobExecutionAllowlist;
public final ForgeConfigSpec.ConfigValue<List<? extends String>> knockedPotionEffects; public final ForgeConfigSpec.ConfigValue<List<? extends String>> knockedPotionEffects;
@@ -32,6 +33,10 @@ public class Config {
.comment("How long (in ticks) it takes to execute a knocked player. Default: 60 (3 seconds).") .comment("How long (in ticks) it takes to execute a knocked player. Default: 60 (3 seconds).")
.defineInRange("executionTime", 60, 20, 200); .defineInRange("executionTime", 60, 20, 200);
mobExecutionEnabled = builder
.comment("If true, mobs can execute knocked players. Default: true.")
.define("mobExecutionEnabled", true);
mobExecutionAllowlist = builder mobExecutionAllowlist = builder
.comment("List of entity ids allowed to execute knocked players.", .comment("List of entity ids allowed to execute knocked players.",
"If empty, any hostile/aggro mob can execute.", "If empty, any hostile/aggro mob can execute.",