Added Config File

This commit is contained in:
2025-10-17 03:50:09 +02:00
parent bd62a201f9
commit 6fd5d84900
8 changed files with 129 additions and 101 deletions
@@ -1,58 +0,0 @@
package net.fretux.knockedback;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class Config
{
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
private static final ForgeConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER
.comment("Whether to log the dirt block on common setup")
.define("logDirtBlock", true);
private static final ForgeConfigSpec.IntValue MAGIC_NUMBER = BUILDER
.comment("A magic number")
.defineInRange("magicNumber", 42, 0, Integer.MAX_VALUE);
public static final ForgeConfigSpec.ConfigValue<String> MAGIC_NUMBER_INTRODUCTION = BUILDER
.comment("What you want the introduction message to be for the magic number")
.define("magicNumberIntroduction", "The magic number is... ");
// a list of strings that are treated as resource locations for items
private static final ForgeConfigSpec.ConfigValue<List<? extends String>> ITEM_STRINGS = BUILDER
.comment("A list of items to log on common setup.")
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), Config::validateItemName);
static final ForgeConfigSpec SPEC = BUILDER.build();
public static boolean logDirtBlock;
public static int magicNumber;
public static String magicNumberIntroduction;
public static Set<Item> items;
private static boolean validateItemName(final Object obj)
{
return obj instanceof final String itemName && ForgeRegistries.ITEMS.containsKey(new ResourceLocation(itemName));
}
@SubscribeEvent
static void onLoad(final ModConfigEvent event)
{
logDirtBlock = LOG_DIRT_BLOCK.get();
magicNumber = MAGIC_NUMBER.get();
magicNumberIntroduction = MAGIC_NUMBER_INTRODUCTION.get();
items = ITEM_STRINGS.get().stream()
.map(itemName -> ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName)))
.collect(Collectors.toSet());
}
}
@@ -14,6 +14,7 @@ import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.fretux.knockedback.config.Config;
import org.slf4j.Logger;
@Mod(KnockedBack.MOD_ID)
@@ -22,7 +23,7 @@ public class KnockedBack {
private static final Logger LOGGER = LogUtils.getLogger();
public KnockedBack() {
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.COMMON_SPEC);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new KnockedEffect());
@@ -10,6 +10,7 @@ import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.PacketDistributor;
import net.fretux.knockedback.config.Config;
import java.util.*;
@@ -17,14 +18,17 @@ import java.util.*;
public class KnockedManager {
private static final Map<UUID, Integer> knockedEntities = new HashMap<>();
private static final Set<UUID> grippedEntities = new HashSet<>();
private static final int KNOCKED_DURATION = 400;
private static int getKnockedDuration() {
return Config.COMMON.knockedDuration.get();
}
public static void applyKnockedState(LivingEntity entity) {
if (!(entity instanceof Player)) {
return;
}
if (!isKnocked(entity)) {
knockedEntities.put(entity.getUUID(), KNOCKED_DURATION);
knockedEntities.put(entity.getUUID(), getKnockedDuration());
entity.setHealth(1.0F);
}
}
@@ -34,16 +38,15 @@ public class KnockedManager {
if (!(event.player instanceof ServerPlayer sp)) return;
if (KnockedManager.isKnocked(sp)) {
boolean grounded = sp.onGround() || sp.isInWater();
sp.setNoGravity(false); // Always allow gravity
sp.setNoGravity(false);
if (!grounded) {
sp.setDeltaMovement(0, sp.getDeltaMovement().y() - 0.08, 0); // Gravity acceleration
sp.setDeltaMovement(0, sp.getDeltaMovement().y() - 0.08, 0);
}
}
}
public static boolean isKnocked(LivingEntity entity) {
return knockedEntities.containsKey(entity.getUUID());
}
@@ -126,43 +129,45 @@ public class KnockedManager {
}
}
private static void killAndRemove(LivingEntity entity) {
removeKnockedState(entity);
entity.kill();
}
@SubscribeEvent
public static void onLivingHurt(LivingHurtEvent event) {
LivingEntity entity = event.getEntity();
if (!(entity instanceof Player player)) {
return;
}
if (player.getMainHandItem().getItem() == Items.TOTEM_OF_UNDYING
|| player.getOffhandItem().getItem() == Items.TOTEM_OF_UNDYING) {
return;
}
if (!(entity instanceof Player player)) return;
DamageSource src = event.getSource();
String damageType = src.getMsgId();
boolean isFatal = player.getHealth() - event.getAmount() <= 0;
if (!isKnocked(entity)) {
if (isFatal) {
if (src.getEntity() instanceof LivingEntity) {
event.setCanceled(true);
applyKnockedState(entity);
}
if (isFatal && Config.COMMON.explosionsBypassKnockdown.get() &&
(damageType.contains("explosion") || damageType.contains("fireworks"))) {
killAndRemove(player);
return;
}
if (isFatal && Config.COMMON.fallDamageBypassesKnockdown.get() && damageType.contains("fall")) {
killAndRemove(player);
return;
}
if (isFatal && Config.COMMON.lavaBypassesKnockdown.get() &&
(damageType.contains("lava") || damageType.contains("inFire") ||
damageType.contains("fire") || damageType.contains("onFire") ||
damageType.contains("fireball") || damageType.contains("hotFloor"))) {
killAndRemove(player);
return;
}
boolean hasTotem = player.getMainHandItem().is(Items.TOTEM_OF_UNDYING)
|| player.getOffhandItem().is(Items.TOTEM_OF_UNDYING);
if (isFatal && !isKnocked(entity)) {
if (!hasTotem || !Config.COMMON.totemPreventsKnockdown.get()) {
event.setCanceled(true);
applyKnockedState(entity);
}
return;
}
knockedEntities.put(entity.getUUID(), KNOCKED_DURATION);
if (damageType.equals("fire") || damageType.equals("lava") || damageType.equals("onFire") ||
damageType.equals("explosion") || damageType.equals("explosion.player") || damageType.equals("fireball")) {
entity.setHealth(0.0F);
removeKnockedState(entity);
PlayerExecutionHandler.cancelExecution(entity.getUUID());
return;
if (isKnocked(entity)) {
knockedEntities.put(entity.getUUID(), getKnockedDuration());
event.setCanceled(true);
}
if ((damageType.equals("fall") || damageType.equals("explosion") || damageType.equals("explosion.player")) &&
event.getAmount() >= entity.getHealth()) {
entity.setHealth(0.0F);
removeKnockedState(entity);
PlayerExecutionHandler.cancelExecution(entity.getUUID());
return;
}
event.setCanceled(true);
}
}
@@ -1,6 +1,5 @@
package net.fretux.knockedback;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
@@ -12,6 +11,7 @@ import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.PacketDistributor;
import net.fretux.knockedback.config.Config;
import javax.annotation.Nullable;
import java.util.*;
@@ -21,7 +21,10 @@ import static net.fretux.knockedback.KnockedManager.setGripped;
@Mod.EventBusSubscriber(modid = KnockedBack.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class MobKillHandler {
private static final int EXECUTION_DELAY_TICKS = 3 * 20;
public static int getExecutionTime() {
return Config.COMMON.executionTime.get();
}
private static final Map<UUID, KillAttempt> killAttempts = new HashMap<>();
private static class KillAttempt {
@@ -46,6 +49,7 @@ public class MobKillHandler {
@SubscribeEvent
public void onMobHurt(LivingHurtEvent event) {
if (!Config.COMMON.mobsCanExecute.get()) return;
LivingEntity entity = event.getEntity();
if (!(entity instanceof Mob mob)) return;
UUID mobUuid = mob.getUUID();
@@ -75,6 +79,10 @@ public class MobKillHandler {
private void tickKillAttempts() {
var server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
if (!net.fretux.knockedback.config.Config.COMMON.mobsCanExecute.get()) {
killAttempts.clear();
return;
}
Map<UUID, KillAttempt> updated = new HashMap<>();
for (UUID knockedId : KnockedManager.getKnockedUuids()) {
Player knocked = getPlayerByUuid(knockedId);
@@ -103,7 +111,7 @@ public class MobKillHandler {
setGripped(knocked, true);
KillAttempt attempt = killAttempts.get(knockedId);
if (attempt == null || !attempt.mobUuid.equals(mob.getUUID())) {
attempt = new KillAttempt(mob.getUUID(), EXECUTION_DELAY_TICKS);
attempt = new KillAttempt(mob.getUUID(), getExecutionTime());
} else {
attempt.timeLeft--;
if (knocked instanceof ServerPlayer sp) {
@@ -1,5 +1,6 @@
package net.fretux.knockedback;
import net.fretux.knockedback.config.Config;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
@@ -20,7 +21,9 @@ import java.util.UUID;
@Mod.EventBusSubscriber(modid = "knockedback", bus = Mod.EventBusSubscriber.Bus.FORGE)
public class PlayerExecutionHandler {
public static final double EXECUTION_RANGE = 2.0;
public static final int EXECUTION_DELAY_TICKS = 60;
public static int getExecutionTime() {
return Config.COMMON.executionTime.get();
}
public static boolean isBeingPlayerExecuted(UUID knockedId) {
return executionAttempts.containsKey(knockedId);
}
@@ -52,12 +55,12 @@ public class PlayerExecutionHandler {
public PlayerExecutionAttempt(UUID executorUuid) {
this.executorUuid = executorUuid;
this.timeLeft = EXECUTION_DELAY_TICKS;
this.timeLeft = getExecutionTime();
}
}
public static void register() {
MinecraftForge.EVENT_BUS.register(new PlayerExecutionHandler());
MinecraftForge.EVENT_BUS.register(new PlayerExecutionHandler());
}
public static void startExecution(ServerPlayer executor, Player target) {
@@ -12,7 +12,6 @@ import net.minecraftforge.fml.common.Mod;
public class ExecutionProgressOverlay {
private static final int BAR_WIDTH = 100;
private static final int BAR_HEIGHT = 8;
private static final int TOTAL_TICKS = net.fretux.knockedback.PlayerExecutionHandler.EXECUTION_DELAY_TICKS;
@SubscribeEvent
public static void onRender(RenderGuiOverlayEvent.Post event) {
@@ -23,7 +22,8 @@ public class ExecutionProgressOverlay {
int sh = mc.getWindow().getGuiScaledHeight();
int x = (sw - BAR_WIDTH) / 2;
int y = (sh - BAR_HEIGHT) / 2;
float progress = 1.0f - (ClientExecutionState.getTimeLeft() / (float) TOTAL_TICKS);
int totalTicks = net.fretux.knockedback.PlayerExecutionHandler.getExecutionTime();
float progress = 1.0f - (ClientExecutionState.getTimeLeft() / (float) totalTicks);
int fillWidth = (int) (BAR_WIDTH * progress);
gui.fill(x, y, x + BAR_WIDTH, y + BAR_HEIGHT, 0x80000000);
gui.fill(x, y, x + fillWidth, y + BAR_HEIGHT, 0x80FFFFFF);
@@ -0,0 +1,62 @@
package net.fretux.knockedback.config;
import net.minecraftforge.common.ForgeConfigSpec;
public class Config {
public static final ForgeConfigSpec COMMON_SPEC;
public static final Common COMMON;
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
COMMON = new Common(builder);
COMMON_SPEC = builder.build();
}
public static class Common {
public final ForgeConfigSpec.IntValue knockedDuration;
public final ForgeConfigSpec.IntValue executionTime;
public final ForgeConfigSpec.BooleanValue totemPreventsKnockdown;
public final ForgeConfigSpec.BooleanValue explosionsBypassKnockdown;
public final ForgeConfigSpec.BooleanValue fallDamageBypassesKnockdown;
public final ForgeConfigSpec.BooleanValue lavaBypassesKnockdown;
public final ForgeConfigSpec.BooleanValue mobsCanExecute;
public Common(ForgeConfigSpec.Builder builder) {
builder.push("general");
knockedDuration = builder
.comment("How long (in ticks) a player remains knocked before recovering. Default: 400 (20 seconds).")
.defineInRange("knockedDuration", 400, 100, 1200);
executionTime = builder
.comment("How long (in ticks) it takes to execute a knocked player. Default: 60 (3 seconds).")
.defineInRange("executionTime", 60, 20, 200);
builder.pop().push("damage_behavior");
totemPreventsKnockdown = builder
.comment("If true, Totems of Undying prevent entering the knocked state. Default: true.")
.define("totemPreventsKnockdown", true);
explosionsBypassKnockdown = builder
.comment("If true, explosions immediately kill instead of knocking down. Default: true.")
.define("explosionsBypassKnockdown", true);
fallDamageBypassesKnockdown = builder
.comment("If true, fatal fall damage kills instead of knocking down. Default: true.")
.define("fallDamageBypassesKnockdown", true);
lavaBypassesKnockdown = builder
.comment("If true, lava or fire damage kills instead of knocking down. Default: true.")
.define("lavaBypassesKnockdown", true);
builder.pop().push("mobs");
mobsCanExecute = builder
.comment("If true, hostile and aggressive neutral mobs can execute knocked players. Default: true.")
.define("mobsCanExecute", true);
builder.pop();
}
}
}