From d83dd30445c7c7cd16d093b3bd48ad5d8f522132 Mon Sep 17 00:00:00 2001 From: illuc Date: Thu, 8 Jan 2026 20:55:01 +0200 Subject: [PATCH] more stuff --- TODO.md | 0 .../IPlayerHealthDataAccessor.java | 13 ++ .../PrototypePain/MixinMoodleRegister.java | 22 +++ .../MixinPlayerHealthDataExtras.java | 114 +++++++++++++++ .../mixin/Tfc/MixinFoodData.java | 132 ++++++++++++++++++ .../mixin/Tfc/MixinHealthBar.java | 101 ++++++++++++++ .../vanilla/MixinRemovePlayerNametag.java | 16 +++ .../registers/RegisterMoodles.java | 9 ++ 8 files changed, 407 insertions(+) create mode 100644 TODO.md create mode 100644 src/main/java/xyz/illuc/neuralgiacore/IPlayerHealthDataAccessor.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinMoodleRegister.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinPlayerHealthDataExtras.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinFoodData.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinHealthBar.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/mixin/vanilla/MixinRemovePlayerNametag.java create mode 100644 src/main/java/xyz/illuc/neuralgiacore/registers/RegisterMoodles.java diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/xyz/illuc/neuralgiacore/IPlayerHealthDataAccessor.java b/src/main/java/xyz/illuc/neuralgiacore/IPlayerHealthDataAccessor.java new file mode 100644 index 0000000..40ec844 --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/IPlayerHealthDataAccessor.java @@ -0,0 +1,13 @@ +package xyz.illuc.neuralgiacore; + +public interface IPlayerHealthDataAccessor { + + float getSepsis(); + void setSepsis(float value); + + float getSickness(); + void setSickness(float value); + + float getVomitTime(); + void setVomitTime(float value); +} diff --git a/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinMoodleRegister.java b/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinMoodleRegister.java new file mode 100644 index 0000000..47e98be --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinMoodleRegister.java @@ -0,0 +1,22 @@ +package xyz.illuc.neuralgiacore.mixin.PrototypePain; + +import net.adinvas.prototype_pain.client.moodles.MoodleController; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import static net.adinvas.prototype_pain.client.moodles.MoodleController.registerMoodle; + +/* + Mixin to let me register custom moodles +*/ +@Mixin(MoodleController.class) +public class MixinMoodleRegister { + + @Inject(method = "", at = @At(value = "INVOKE", target = "Lnet/adinvas/prototype_pain/client/moodles/MoodleController;registerMoodle(Lnet/adinvas/prototype_pain/client/moodles/AbstractMoodleVisual;)V", ordinal = 0)) + private static void onClInit(CallbackInfo ci) { + + registerMoodle(new SepsisMoodle()); + } +} diff --git a/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinPlayerHealthDataExtras.java b/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinPlayerHealthDataExtras.java new file mode 100644 index 0000000..e727184 --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/mixin/PrototypePain/MixinPlayerHealthDataExtras.java @@ -0,0 +1,114 @@ +package xyz.illuc.neuralgiacore.mixin.PrototypePain; + +import net.adinvas.prototype_pain.limbs.PlayerHealthData; +import net.minecraft.nbt.CompoundTag; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import xyz.illuc.tfcpain.IPlayerHealthDataAccessor; + +@Mixin(PlayerHealthData.class) +public class MixinPlayerHealthDataExtras implements IPlayerHealthDataAccessor { + + // Add your new variable here + @Unique + private float sepsis = 0.0f; + + @Unique + private float sickness = 0.0f; + + @Unique + private float vomitTime = 0.0f; + + + @Unique + public float getSepsis() { + return this.sepsis; + } + + @Unique + public void setSepsis(float value) { + this.sepsis = value; + } + + + @Unique + public float getSickness() { + return this.sickness; + } + + @Unique + public void setSickness(float value) { + this.sickness = value; + } + + @Override + public float getVomitTime() { + return this.vomitTime; + } + + @Override + public void setVomitTime(float value) { + this.vomitTime = value; + } + + // Inject into serializeNBT to save the new variable + @Inject( + method = "serializeNBT", + at = @At("RETURN"), + remap = false + ) + private void onSerializeNBT(CompoundTag nbt, CallbackInfoReturnable cir) { + CompoundTag tag = cir.getReturnValue(); + tag.putFloat("Sepsis", this.sepsis); + tag.putFloat("Sickness", this.sickness); + tag.putFloat("VomitTimer", this.vomitTime); + } + + // Inject into deserializeNBT to load the new variable + @Inject( + method = "deserializeNBT", + at = @At("TAIL"), + remap = false + ) + private void onDeserializeNBT(CompoundTag nbt, CallbackInfo ci) { + if (nbt.contains("Sepsis")) { + this.sepsis = nbt.getFloat("Sepsis"); + } + if (nbt.contains("Sickness")) { + this.sickness = nbt.getFloat("Sickness"); + } + if (nbt.contains("VomitTimer")) { + this.vomitTime = nbt.getFloat("VomitTimer"); + } + } + + /* + // Inject into copyFrom to copy the new variable + @Inject( + method = "copyFrom", + at = @At("TAIL"), + remap = false + ) + private void onCopyFrom(PlayerHealthData other, CallbackInfo ci) { + if (other instanceof MixinPlayerHealthDataExtras otherMixin) { + this.customVariable = otherMixin.getCustomVariable(); + } + } */ + + // Inject into resetToDefaults to reset the new variable + @Inject( + method = "resetToDefaults", + at = @At("TAIL"), + remap = false + ) + private void onResetToDefaults(CallbackInfo ci) { + this.sepsis = 0.0f; + this.sickness = 0.0f; + this.vomitTime = 0.0f; + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinFoodData.java b/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinFoodData.java new file mode 100644 index 0000000..a227116 --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinFoodData.java @@ -0,0 +1,132 @@ +package xyz.illuc.neuralgiacore.mixin.Tfc; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import net.adinvas.prototype_pain.PlayerHealthProvider; +import net.dries007.tfc.common.capabilities.food.FoodData; +import net.dries007.tfc.common.capabilities.food.Nutrient; +import net.dries007.tfc.common.capabilities.food.TFCFoodData; +import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.player.Abilities; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import xyz.illuc.tfcpain.IPlayerHealthDataAccessor; + +@Mixin(TFCFoodData.class) +public class MixinFoodData { + @Shadow private float thirst; + + @Shadow @Final private Player sourcePlayer; + + @Redirect(method = "tick", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/entity/player/Player;getAbilities()Lnet/minecraft/world/entity/player/Abilities;") + ) + private Abilities redir(Player instance){ + + return null; + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;tick(Lnet/minecraft/world/entity/player/Player;)V", shift = At.Shift.AFTER)) + private void injected(Player player, CallbackInfo ci, @Local LocalRef difficulty) { + difficulty.set(Difficulty.PEACEFUL); //Disables the default thirst thing + } + + @Inject(method = "eat(Lnet/dries007/tfc/common/capabilities/food/FoodData;)V", at = @At(value = "HEAD"), remap = false) + private void modifySickness(CallbackInfo ci, @Local FoodData data) { + // Get the player's CURRENT nutrition levels (before eating) + net.minecraft.world.food.FoodData nutrition = this.sourcePlayer.getFoodData(); + + if (nutrition instanceof TFCFoodData) { + TFCFoodData tfcNutrition = (TFCFoodData) nutrition; + + // Get player's current nutrition values + float grains = tfcNutrition.getNutrition().getNutrient(Nutrient.GRAIN); + float vegetables = tfcNutrition.getNutrition().getNutrient(Nutrient.VEGETABLES); + float fruit = tfcNutrition.getNutrition().getNutrient(Nutrient.FRUIT); + float protein = tfcNutrition.getNutrition().getNutrient(Nutrient.PROTEIN); + float dairy = tfcNutrition.getNutrition().getNutrient(Nutrient.DAIRY); + + // Check if any nutrients are critically low (below 0.2 or 20%) + int deficientCount = 0; + float totalDeficiency = 0; + + if (grains < 0.1f) { + deficientCount++; + totalDeficiency += (0.1f - grains); + } + if (vegetables < 0.1f) { + deficientCount++; + totalDeficiency += (0.1f - vegetables); + } + if (fruit < 0.1f) { + deficientCount++; + totalDeficiency += (0.1f - fruit); + } + if (protein < 0.1f) { + deficientCount++; + totalDeficiency += (0.1f - protein); + } + if (dairy < 0.1f) { + deficientCount++; + totalDeficiency += (0.1f - dairy); + } + + // Calculate total sickness to add + float totalSicknessToAdd = 0; + + // 1. Add sickness from nutrient deficiency + if (deficientCount > 0) { + // More deficient nutrients = more sickness + // Severity also matters (how far below 20%) + float deficiencySickness = (deficientCount * 2.0f) + (totalDeficiency * 10.0f); + deficiencySickness = Math.min(deficiencySickness, 8.0f); // Cap deficiency sickness + totalSicknessToAdd += deficiencySickness; + } + + // 2. Add sickness from imbalance (existing code) + // Calculate the average nutrition level + float average = (grains + vegetables + fruit + protein + dairy) / 5.0f; + + // Calculate imbalance - sum of squared differences from average + float imbalance = 0; + imbalance += (float) Math.pow(grains - average, 2); + imbalance += (float) Math.pow(vegetables - average, 2); + imbalance += (float) Math.pow(fruit - average, 2); + imbalance += (float) Math.pow(protein - average, 2); + imbalance += (float) Math.pow(dairy - average, 2); + + // Normalize imbalance (divide by 5 and take square root to get standard deviation) + float stdDev = (float) Math.sqrt(imbalance / 5.0f); + + // Only add sickness if imbalance is significant (std dev > 0.25 or 25%) + if (stdDev > 0.25f) { + // Scale sickness based on severity of imbalance + // At 0.25 std dev = 0.5 sickness, at 0.40 std dev = 3 sickness + float imbalanceSickness = (stdDev - 0.25f) * 16.7f; + imbalanceSickness = Math.min(imbalanceSickness, 5.0f); // Cap imbalance sickness + totalSicknessToAdd += imbalanceSickness*100; + } + + // Apply total sickness if any was calculated + if (totalSicknessToAdd > 0) { + // Cap total sickness added per meal + totalSicknessToAdd = Math.min(totalSicknessToAdd, 10.0f); + + float finalSicknessToAdd = totalSicknessToAdd; + this.sourcePlayer.getCapability(PlayerHealthProvider.PLAYER_HEALTH_DATA).ifPresent(h -> { + IPlayerHealthDataAccessor accessor = (IPlayerHealthDataAccessor) h; + float currentSickness = accessor.getSickness(); + accessor.setSickness(Math.max(0, Math.min(100, currentSickness + finalSicknessToAdd))); + }); + } + } + } + +} diff --git a/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinHealthBar.java b/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinHealthBar.java new file mode 100644 index 0000000..37a7d8d --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/mixin/Tfc/MixinHealthBar.java @@ -0,0 +1,101 @@ +package xyz.illuc.neuralgiacore.mixin.Tfc; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.adinvas.prototype_pain.PlayerHealthProvider; +import net.dries007.tfc.client.IngameOverlays; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import static net.dries007.tfc.client.IngameOverlays.setup; +import static net.minecraft.util.Mth.clamp; + +@Mixin(IngameOverlays.class) +public class MixinHealthBar { + @Redirect( + method = "renderHealth", + at = @At(value = "INVOKE", target = "Lnet/dries007/tfc/client/IngameOverlays;renderHealthBar(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraftforge/client/gui/overlay/ForgeGui;Lnet/minecraft/client/gui/GuiGraphics;II)V"), + remap = false + ) + private static void renderHealth(LivingEntity player, ForgeGui gui, GuiGraphics graphics, int width, int height) { + tfcpain$renderConscioussnes(gui, graphics, width, height); + tfcpain$renderOxygen(gui, graphics, width, height); + + } + @Unique + private static final ResourceLocation TEXTURE = new ResourceLocation("tfcpain", "textures/overlay.png"); + + @Unique + private static void tfcpain$renderConscioussnes(ForgeGui gui, GuiGraphics graphics, int width, int height) { + PoseStack stack = graphics.pose(); + Minecraft minecraft = Minecraft.getInstance(); + if ( gui.shouldDrawSurvivalElements() && setup(gui, minecraft)) { + Player player = (Player)minecraft.getCameraEntity(); + + assert player != null; + + + player.getCapability(PlayerHealthProvider.PLAYER_HEALTH_DATA, null).ifPresent(cap-> { + var fill = cap.getContiousness()/100; + fill = clamp(fill, 0.0F, 1.0F); + + int centerX = width / 2; + int y = height - gui.leftHeight; + + stack.pushPose(); + stack.translate(centerX - 91, y+4, 0.0F); + + graphics.blit(TEXTURE, 0, 0, 0, 20, 90, 5); + graphics.blit(TEXTURE, 0, 0, 0, 25, (int)(90.0F * fill), 5); + + stack.popPose(); + + gui.leftHeight += 10; + }); + + } + + } + + @Unique + private static void tfcpain$renderOxygen(ForgeGui gui, GuiGraphics graphics, int width, int height) { + PoseStack stack = graphics.pose(); + Minecraft minecraft = Minecraft.getInstance(); + if ( gui.shouldDrawSurvivalElements() && setup(gui, minecraft)) { + Player player = (Player)minecraft.getCameraEntity(); + + assert player != null; + + + + + player.getCapability(PlayerHealthProvider.PLAYER_HEALTH_DATA, null).ifPresent(cap-> { + var fill = cap.getOxygen()/100; + fill = clamp(fill, 0.0F, 1.0F); + + int centerX = width / 2; + int y = height - gui.leftHeight; + + stack.pushPose(); + stack.translate(centerX - 91, y+8, 0.0F); + + graphics.blit(TEXTURE, 0, 0, 90, 20, 90, 5); + graphics.blit(TEXTURE, 0, 0, 90, 25, (int)(90.0F * fill), 5); + + stack.popPose(); + + gui.leftHeight += 10; + }); + + } + + } +} + diff --git a/src/main/java/xyz/illuc/neuralgiacore/mixin/vanilla/MixinRemovePlayerNametag.java b/src/main/java/xyz/illuc/neuralgiacore/mixin/vanilla/MixinRemovePlayerNametag.java new file mode 100644 index 0000000..d2bfc41 --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/mixin/vanilla/MixinRemovePlayerNametag.java @@ -0,0 +1,16 @@ +package xyz.illuc.neuralgiacore.mixin.vanilla; + +@Mixin(EntityRenderer.class) +public abstract class MixinNametag { + @Inject( + method = "renderNameTag", + at = @At("HEAD"), + cancellable = true, + remap = true + ) + private void removeNametag(Entity entity, Component p_114499_, PoseStack p_114500_, MultiBufferSource p_114501_, int p_114502_, CallbackInfo ci) { + if (entity instanceof Player) { + ci.cancel(); + } + } +} diff --git a/src/main/java/xyz/illuc/neuralgiacore/registers/RegisterMoodles.java b/src/main/java/xyz/illuc/neuralgiacore/registers/RegisterMoodles.java new file mode 100644 index 0000000..f1f1afd --- /dev/null +++ b/src/main/java/xyz/illuc/neuralgiacore/registers/RegisterMoodles.java @@ -0,0 +1,9 @@ +package xyz.illuc.neuralgiacore; + +@Mod.EventBusSubscriber(modid = Tfcpain.MODID, value = Dist.CLIENT) +public class MoodleController { + static { + registerMoodle(new SepsisMoodle()); + registerMoodle(new SicknessMoodle()); + } +} \ No newline at end of file