Merge pull request #12 from Fretuks/add-config-options-for-mob-interactions
Add mob execution allowlist and configurable knocked potion effects
This commit is contained in:
@@ -3,16 +3,20 @@ package net.fretux.knockedback;
|
|||||||
import net.fretux.knockedback.config.Config;
|
import net.fretux.knockedback.config.Config;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.damagesource.DamageSource;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
|
import net.minecraft.world.effect.MobEffect;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.Pose;
|
import net.minecraft.world.entity.Pose;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
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 net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.network.PacketDistributor;
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -42,6 +46,7 @@ public class KnockedManager {
|
|||||||
if (!isKnocked(entity)) {
|
if (!isKnocked(entity)) {
|
||||||
knockedEntities.put(entity.getUUID(), getKnockedDuration());
|
knockedEntities.put(entity.getUUID(), getKnockedDuration());
|
||||||
entity.setHealth(1.0F);
|
entity.setHealth(1.0F);
|
||||||
|
applyKnockedEffects((Player) entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +112,7 @@ public class KnockedManager {
|
|||||||
|| CarryManager.isBeingCarried(playerId)) {
|
|| CarryManager.isBeingCarried(playerId)) {
|
||||||
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
|
applyKnockedEffects(p);
|
||||||
NetworkHandler.CHANNEL.send(
|
NetworkHandler.CHANNEL.send(
|
||||||
PacketDistributor.PLAYER.with(() -> p),
|
PacketDistributor.PLAYER.with(() -> p),
|
||||||
new KnockedTimePacket(timeLeft)
|
new KnockedTimePacket(timeLeft)
|
||||||
@@ -118,6 +124,7 @@ public class KnockedManager {
|
|||||||
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) {
|
|| PlayerExecutionHandler.isBeingPlayerExecuted(playerId)) {
|
||||||
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
|
applyKnockedEffects(p);
|
||||||
NetworkHandler.CHANNEL.send(
|
NetworkHandler.CHANNEL.send(
|
||||||
PacketDistributor.PLAYER.with(() -> p),
|
PacketDistributor.PLAYER.with(() -> p),
|
||||||
new KnockedTimePacket(timeLeft)
|
new KnockedTimePacket(timeLeft)
|
||||||
@@ -139,6 +146,7 @@ public class KnockedManager {
|
|||||||
entry.setValue(timeLeft);
|
entry.setValue(timeLeft);
|
||||||
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
ServerPlayer p = NetworkHandlerHelper.getPlayerByUuid(server, playerId);
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
|
applyKnockedEffects(p);
|
||||||
NetworkHandler.CHANNEL.send(
|
NetworkHandler.CHANNEL.send(
|
||||||
PacketDistributor.PLAYER.with(() -> p),
|
PacketDistributor.PLAYER.with(() -> p),
|
||||||
new KnockedTimePacket(timeLeft)
|
new KnockedTimePacket(timeLeft)
|
||||||
@@ -186,6 +194,7 @@ public class KnockedManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
knockedEntities.put(player.getUUID(), getKnockedDuration());
|
knockedEntities.put(player.getUUID(), getKnockedDuration());
|
||||||
|
applyKnockedEffects(player);
|
||||||
event.setCanceled(true);
|
event.setCanceled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,4 +218,57 @@ public class KnockedManager {
|
|||||||
new GrippedStatePacket(playerId, false)
|
new GrippedStatePacket(playerId, false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void applyKnockedEffects(Player player) {
|
||||||
|
List<? extends String> configured = Config.COMMON.knockedPotionEffects.get();
|
||||||
|
if (configured.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String entry : configured) {
|
||||||
|
MobEffectInstance instance = parseEffect(entry);
|
||||||
|
if (instance == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MobEffect effect = instance.getEffect();
|
||||||
|
MobEffectInstance existing = player.getEffect(effect);
|
||||||
|
if (existing == null || existing.getDuration() < 20 || existing.getAmplifier() < instance.getAmplifier()) {
|
||||||
|
player.addEffect(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MobEffectInstance parseEffect(String entry) {
|
||||||
|
if (entry == null || entry.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String[] parts = entry.split(",");
|
||||||
|
if (parts.length < 3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ResourceLocation effectId = ResourceLocation.tryParse(parts[0].trim());
|
||||||
|
if (effectId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MobEffect effect = ForgeRegistries.MOB_EFFECTS.getValue(effectId);
|
||||||
|
if (effect == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Integer duration = parseInt(parts[1].trim());
|
||||||
|
Integer amplifier = parseInt(parts[2].trim());
|
||||||
|
if (duration == null || amplifier == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
boolean ambient = parts.length > 3 ? Boolean.parseBoolean(parts[3].trim()) : false;
|
||||||
|
boolean visible = parts.length > 4 ? Boolean.parseBoolean(parts[4].trim()) : true;
|
||||||
|
boolean showIcon = parts.length > 5 ? Boolean.parseBoolean(parts[5].trim()) : true;
|
||||||
|
return new MobEffectInstance(effect, duration, amplifier, ambient, visible, showIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer parseInt(String value) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ import net.minecraft.world.entity.player.Player;
|
|||||||
import net.minecraft.world.entity.LivingEntity;
|
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.server.level.ServerLevel;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
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 net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.network.PacketDistributor;
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -156,7 +158,7 @@ public class MobKillHandler {
|
|||||||
p.getX() + r, p.getY() + r, p.getZ() + r
|
p.getX() + r, p.getY() + r, p.getZ() + r
|
||||||
);
|
);
|
||||||
return world.getEntitiesOfClass(Mob.class, box).stream()
|
return world.getEntitiesOfClass(Mob.class, box).stream()
|
||||||
.filter(m -> isHostile(m) || isAggressiveNeutral(m, p))
|
.filter(m -> (isHostile(m) || isAggressiveNeutral(m, p)) && isMobAllowedToExecute(m))
|
||||||
.findAny().orElse(null);
|
.findAny().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,10 +171,19 @@ public class MobKillHandler {
|
|||||||
p.getX() + r, p.getY() + r, p.getZ() + r
|
p.getX() + r, p.getY() + r, p.getZ() + r
|
||||||
);
|
);
|
||||||
return world.getEntitiesOfClass(Mob.class, box).stream()
|
return world.getEntitiesOfClass(Mob.class, box).stream()
|
||||||
.filter(m -> m.getUUID().equals(mobId))
|
.filter(m -> m.getUUID().equals(mobId) && isMobAllowedToExecute(m))
|
||||||
.findAny().orElse(null);
|
.findAny().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMobAllowedToExecute(Mob mob) {
|
||||||
|
List<? extends String> allowlist = Config.COMMON.mobExecutionAllowlist.get();
|
||||||
|
if (allowlist.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ResourceLocation id = ForgeRegistries.ENTITY_TYPES.getKey(mob.getType());
|
||||||
|
return id != null && allowlist.contains(id.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean isHostile(Mob m) {
|
private boolean isHostile(Mob m) {
|
||||||
return m instanceof net.minecraft.world.entity.monster.Monster;
|
return m instanceof net.minecraft.world.entity.monster.Monster;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package net.fretux.knockedback.config;
|
|||||||
|
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
public static final ForgeConfigSpec COMMON_SPEC;
|
public static final ForgeConfigSpec COMMON_SPEC;
|
||||||
public static final Common COMMON;
|
public static final Common COMMON;
|
||||||
@@ -16,6 +18,8 @@ public class Config {
|
|||||||
public final ForgeConfigSpec.IntValue knockedDuration;
|
public final ForgeConfigSpec.IntValue knockedDuration;
|
||||||
public final ForgeConfigSpec.IntValue executionTime;
|
public final ForgeConfigSpec.IntValue executionTime;
|
||||||
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>> knockedPotionEffects;
|
||||||
|
|
||||||
public Common(ForgeConfigSpec.Builder builder) {
|
public Common(ForgeConfigSpec.Builder builder) {
|
||||||
builder.push("general");
|
builder.push("general");
|
||||||
@@ -28,6 +32,18 @@ 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);
|
||||||
|
|
||||||
|
mobExecutionAllowlist = builder
|
||||||
|
.comment("List of entity ids allowed to execute knocked players.",
|
||||||
|
"If empty, any hostile/aggro mob can execute.",
|
||||||
|
"Example: [\"minecraft:zombie\", \"modid:custom_mob\"]")
|
||||||
|
.defineListAllowEmpty("mobExecutionAllowlist", List.of(), o -> o instanceof String);
|
||||||
|
|
||||||
|
knockedPotionEffects = builder
|
||||||
|
.comment("Potion effects to apply while a player is knocked.",
|
||||||
|
"Format: effect_id,duration,amplifier[,ambient][,visible][,showIcon]",
|
||||||
|
"Example: [\"minecraft:slowness,200,1\", \"minecraft:weakness,200,0,true,false,false\"]")
|
||||||
|
.defineListAllowEmpty("knockedPotionEffects", List.of(), o -> o instanceof String);
|
||||||
|
|
||||||
builder.pop().push("damage_behavior");
|
builder.pop().push("damage_behavior");
|
||||||
|
|
||||||
totemPreventsKnockdown = builder
|
totemPreventsKnockdown = builder
|
||||||
|
|||||||
Reference in New Issue
Block a user