Skip to content

Commit

Permalink
Rework toxic buildup
Browse files Browse the repository at this point in the history
Fix static resources not getting loaded properly
  • Loading branch information
kd8lvt committed Nov 6, 2024
1 parent 4e76838 commit 1565fc2
Show file tree
Hide file tree
Showing 22 changed files with 300 additions and 36 deletions.
9 changes: 7 additions & 2 deletions src/main/java/com/kd8lvt/exclusionzone/ExclusionZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
import com.kd8lvt.exclusionzone.registry.ModItems;
import com.kd8lvt.exclusionzone.registry.ModRegistries;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.item.ItemGroup;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExclusionZone implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("exclusionzone");
public static final String MOD_ID = "exclusionzone";
public static final boolean IN_DEV = FabricLoader.getInstance().isDevelopmentEnvironment();
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static MinecraftServer Server = null;

@Override
Expand All @@ -21,6 +24,8 @@ public void onInitialize() {

//Event Handlers
ModEventHandlers.registerAll();

LOGGER.info("Dev Environment According To Fabric: "+IN_DEV);
}

//TODO: Get rid of this and do things properly
Expand All @@ -30,7 +35,7 @@ public static void runCommand(String cmd) {
}

public static Identifier id(String id) {
return Identifier.of("exclusionzone",id);
return Identifier.of(MOD_ID,id);
}

public static void setServer(MinecraftServer server) {
Expand Down
45 changes: 23 additions & 22 deletions src/main/java/com/kd8lvt/exclusionzone/api/ToxicBuildupTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import com.kd8lvt.exclusionzone.content.entity.CaroInvictusEntity;
import com.kd8lvt.exclusionzone.registry.ModAttributes;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.s2c.play.OverlayMessageS2CPacket;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Style;
Expand All @@ -20,6 +21,7 @@
import java.util.Objects;
import java.util.UUID;

import static com.kd8lvt.exclusionzone.ExclusionZone.IN_DEV;
import static com.kd8lvt.exclusionzone.registry.ModAttributes.TOXIN_RESISTANCE;

@SuppressWarnings("unused")
Expand All @@ -32,17 +34,9 @@ public static void tickFor(LivingEntity entity) {
if (buildup > 2000) setBuildup(entity,2000f);
if (buildup < 0) setBuildup(entity,0f);

boolean increaseTox = false;
if (Objects.equals(entity.getWorld().getBiome(entity.getBlockPos()).getIdAsString(), "exclusionzone:exclusion_zone")) {
for (ItemStack stack : entity.getAllArmorItems()) {
if (stack.isEmpty()) {
increaseTox = true;
break;
}
}
}
boolean increaseTox = (Objects.equals(entity.getWorld().getBiome(entity.getBlockPos()).getIdAsString(), "exclusionzone:exclusion_zone"));

if (!entity.getWorld().getEntitiesByClass(CaroInvictusEntity.class, new Box(entity.getBlockPos().offset(Direction.DOWN,8).offset(Direction.SOUTH,8).offset(Direction.EAST,8).toCenterPos(),entity.getBlockPos().offset(Direction.UP,8).offset(Direction.NORTH,8).offset(Direction.WEST,8).toCenterPos()), caroInvictusEntity -> caroInvictusEntity.hasDied).isEmpty()) increaseTox = true;
if (!increaseTox && !entity.getWorld().getEntitiesByClass(CaroInvictusEntity.class, new Box(entity.getBlockPos().offset(Direction.DOWN,8).offset(Direction.SOUTH,8).offset(Direction.EAST,8).toCenterPos(),entity.getBlockPos().offset(Direction.UP,8).offset(Direction.NORTH,8).offset(Direction.WEST,8).toCenterPos()), caroInvictusEntity -> caroInvictusEntity.hasDied).isEmpty()) increaseTox = true;

if (increaseTox) incrementBuildup(entity);
else decrementBuildupUnresisted(entity,1f);
Expand All @@ -67,17 +61,23 @@ private static void trySendActionbar(LivingEntity entity, Float buildup) {

private static void applyEffects(LivingEntity entity) {
Float buildup = buildupTracker.get(entity.getUuid());
if (buildup > 200) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS,20,0,true,false,false));
if (buildup > 400) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS,20,0,true,false,false));
if (buildup > 600) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.HUNGER,20,0,true,false,false));
if (buildup > 800) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.MINING_FATIGUE,20,0,true,false,false));
if (buildup > 1000) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.WEAKNESS,20,1,true,false,false));
if (buildup > 1200) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.DARKNESS,200,0,true,false,false));
if (buildup > 1400) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.NAUSEA,20,0,true,false,false));
if (buildup > 1600) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.POISON,20,0,true,false,false));
if (buildup > 1800) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.POISON,20,5,true,false,false));
if (buildup > 200) applyEffect(entity,StatusEffects.WEAKNESS,20,0);
if (buildup > 400) applyEffect(entity,StatusEffects.SLOWNESS,20,0);
if (buildup > 600) applyEffect(entity,StatusEffects.HUNGER,20,0);
if (buildup > 800) applyEffect(entity,StatusEffects.MINING_FATIGUE,20,0);
if (buildup > 1000) applyEffect(entity,StatusEffects.WEAKNESS,20,1);
if (buildup > 1400) applyEffect(entity,StatusEffects.NAUSEA,20,0);
if (buildup > 1200) applyEffect(entity,StatusEffects.DARKNESS,200,0);
if (buildup > 1600 && buildup <= 1800) applyEffect(entity, StatusEffects.POISON, 250, 0);
if (buildup > 1800) applyEffect(entity, StatusEffects.POISON, 250, 5);
//Intentionally > instead of >= to prevent a weird issue with wither only damaging after a few ticks
if (buildup > 2000) entity.addStatusEffect(new StatusEffectInstance(StatusEffects.WITHER,200,0,true,false,false));
if (buildup >= 1900) applyEffect(entity, StatusEffects.WITHER, 250, 0);
}

private static void applyEffect(LivingEntity entity, RegistryEntry<StatusEffect> effect, int duration, int amplifier) {
if (entity.hasStatusEffect(effect) && !entity.getStatusEffect(effect).isDurationBelow(5) && amplifier <= entity.getStatusEffect(effect).getAmplifier()) return;
if (IN_DEV) entity.addStatusEffect(new StatusEffectInstance(effect,duration,amplifier));
else entity.addStatusEffect(new StatusEffectInstance(effect,duration,amplifier,true,false,false));
}

/**
Expand All @@ -93,7 +93,8 @@ private static void applyEffects(LivingEntity entity) {
* @return delta, after resistance has been applied
*/
public static Float applyResistance(LivingEntity entity,Float delta) {
return (float) (delta * (1-entity.getAttributes().getValue(TOXIN_RESISTANCE)));
//toxin resist is 1 by default, to allow for percentage modifications. hence TOXIN_RESISTANCE-1
return (float) (delta * (1-(entity.getAttributes().getValue(TOXIN_RESISTANCE)-1)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.Locale;
import java.util.concurrent.CompletableFuture;

import static com.kd8lvt.exclusionzone.ExclusionZone.MOD_ID;

public abstract class AbstractExclusionZoneLangProvider extends FabricLanguageProvider {
public AbstractExclusionZoneLangProvider(FabricDataOutput dataOutput, Locale locale, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
super(dataOutput, locale.toLanguageTag().toLowerCase().replace("-","_"), registryLookup);
Expand All @@ -24,8 +26,6 @@ public AbstractExclusionZoneLangProvider(FabricDataOutput dataOutput, Locale loc
public void generateTranslations(RegistryWrapper.WrapperLookup registryLookup, TranslationBuilder builder) {
addAllItems(builder);
addAllTags(builder);

builder.add("tooltips.exclusionzone.research_notes.header","Research Notes:");
}

/**
Expand All @@ -52,6 +52,18 @@ public static void addPotion(TranslationBuilder builder, String id, String effec
builder.add("item.minecraft.tipped_arrow.effect."+id,"Tipped Arrow of "+name);
}

public static void addAttribute(TranslationBuilder builder, String id, String translated) {
addMisc(builder,"attribute",id,translated);
}

public static void addEnchantment(TranslationBuilder builder, String id, String translated) {
addMisc(builder,"enchantment",id,translated);
}

private static void addMisc(TranslationBuilder builder, String pfx, String id, String translated) {
builder.add(pfx+"."+MOD_ID+"."+id,translated);
}

/**
* Loops through the keys in {@link ModRegistries#ITEMS} and fires {@link AbstractExclusionZoneLangProvider#onItemFound} for each.<br />
* Additionally, if the item implements {@link IHasResearchNotes}, it fires {@link AbstractExclusionZoneLangProvider#onTooltipFound} for each of the its tooltips.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ public class DynamicEntityAttribute extends EntityAttribute {
public DynamicEntityAttribute(String translationKey) {
super(translationKey, 0d);
}
public DynamicEntityAttribute(String translationKey,double fallback) {
super(translationKey, fallback);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kd8lvt.exclusionzone.datagen;

import com.kd8lvt.exclusionzone.datagen.enchantment.EnchantmentGenerator;
import com.kd8lvt.exclusionzone.datagen.lang.LangProviders;
import com.kd8lvt.exclusionzone.datagen.loot.LootProviders;
import com.kd8lvt.exclusionzone.datagen.recipe.RecipeProviders;
Expand All @@ -21,5 +22,7 @@ public void onInitializeDataGenerator(FabricDataGenerator generator) {
pack.addProvider(ModelProvider::new);
//Loot Tables
LootProviders.register(pack);
//Enchantments
pack.addProvider(EnchantmentGenerator::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.kd8lvt.exclusionzone.datagen.enchantment;

import com.kd8lvt.exclusionzone.registry.ModAttributes;
import com.kd8lvt.exclusionzone.registry.ModEnchantments;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider;
import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition;
import net.minecraft.component.EnchantmentEffectComponentTypes;
import net.minecraft.component.type.AttributeModifierSlot;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
import net.minecraft.enchantment.effect.AttributeEnchantmentEffect;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.attribute.EntityAttribute;
import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.item.Item;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagKey;

import java.util.concurrent.CompletableFuture;

import static com.kd8lvt.exclusionzone.ExclusionZone.MOD_ID;

public class EnchantmentGenerator extends FabricDynamicRegistryProvider {

public EnchantmentGenerator(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
super(output, registriesFuture);
}

@Override
protected void configure(RegistryWrapper.WrapperLookup registries, Entries entries) {
RegistryWrapper<Item> itemLookup = registries.getWrapperOrThrow(RegistryKeys.ITEM);

register(
entries,
ModEnchantments.KEYS.TOXICUS_PERDITIO,
createAttributeEnchantment(
itemLookup,
ModEnchantments.KEYS.TOXICUS_PERDITIO,
ItemTags.WEAPON_ENCHANTABLE,
10,
5,
Enchantment.leveledCost(1,10), //base cost/level
Enchantment.leveledCost(1,15), //max cost/level)
7,
AttributeModifierSlot.forEquipmentSlot(EquipmentSlot.MAINHAND),
ModAttributes.TOXIN_DAMAGE,
EnchantmentLevelBasedValue.linear(20,20),
EntityAttributeModifier.Operation.ADD_VALUE
)
);

register(
entries,
ModEnchantments.KEYS.TOXICAE_PRAESIDIUM,
createAttributeEnchantment(
itemLookup,
ModEnchantments.KEYS.TOXICAE_PRAESIDIUM,
ItemTags.ARMOR_ENCHANTABLE,
10,
4,
Enchantment.leveledCost(1,10), //base cost/level
Enchantment.leveledCost(1,15), //max cost/level)
7,
AttributeModifierSlot.ARMOR,
ModAttributes.TOXIN_RESISTANCE,
EnchantmentLevelBasedValue.linear(0.1f,0.1f),
EntityAttributeModifier.Operation.ADD_VALUE
)
);
}

private static void register(Entries entries, RegistryKey<Enchantment> key, Enchantment.Builder builder, ResourceCondition... conditions) {
entries.add(key,builder.build(key.getValue()),conditions);
}

private static Enchantment.Builder createAttributeEnchantment(RegistryWrapper<Item> itemLookup, RegistryKey<Enchantment> registryKey, TagKey<Item> appliesToTag, int weight, int maxLevel, Enchantment.Cost baseLeveledCost, Enchantment.Cost maxLeveledCost, int anvilCost, AttributeModifierSlot modifierSlot, RegistryEntry<EntityAttribute> attrKey, EnchantmentLevelBasedValue toApplyPerLevel, EntityAttributeModifier.Operation operation) {
return Enchantment.builder(
Enchantment.definition(
itemLookup.getOrThrow(appliesToTag),
weight,
maxLevel,
baseLeveledCost,
maxLeveledCost,
anvilCost,
modifierSlot
)
).addEffect(
EnchantmentEffectComponentTypes.ATTRIBUTES,
new AttributeEnchantmentEffect(
registryKey.getValue(),
attrKey,
toApplyPerLevel,
operation
)
);
}

@Override
public String getName() {
return MOD_ID+"/Enchantments";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ public EnglishLangProvider(FabricDataOutput dataOutput, CompletableFuture<Regist
public void generateTranslations(RegistryWrapper.WrapperLookup registryLookup, TranslationBuilder builder) {
super.generateTranslations(registryLookup, builder); //THIS MUST STAY HERE TO PROPERLY CALL THE .onThingFound METHODS

builder.add("tooltips.exclusionzone.research_notes.header","Research Notes:");
addAttribute(builder,"generic.toxin_resistance","Toxin Resistance");
addAttribute(builder,"generic.toxin_damage","Toxic Damage");

addEnchantment(builder,"toxicae_praesidium","Toxicae Praesidium");
addEnchantment(builder,"toxicus_perditio","Toxicae Perditio");

addPotion(builder,"milk","Cleansing");
addPotion(builder,"kill_focus","Focused","Focus");
}
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/com/kd8lvt/exclusionzone/mixin/ArmorItemMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.kd8lvt.exclusionzone.mixin;

import com.kd8lvt.exclusionzone.registry.ModAttributes;
import net.minecraft.component.type.AttributeModifierSlot;
import net.minecraft.component.type.AttributeModifiersComponent;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.attribute.EntityAttributeModifier;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.registry.entry.RegistryEntry;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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.CallbackInfoReturnable;

import java.util.Map;
import java.util.function.Supplier;

@Mixin(ArmorItem.class)
public abstract class ArmorItemMixin {
//I highly doubt this actually needs to be a mixin. This is just cleaner than my original solution.
@Inject(at=@At(value = "RETURN"),method="getAttributeModifiers",cancellable = true)
private void getAttributeModifiers(CallbackInfoReturnable<AttributeModifiersComponent> cir) {
AttributeModifiersComponent comp = cir.getReturnValue();
if (comp == AttributeModifiersComponent.DEFAULT) return;
Double toxRes = getToxicResistanceForItem();
if (toxRes.isNaN()) return;
cir.setReturnValue(cir.getReturnValue().with(
ModAttributes.TOXIN_RESISTANCE,
new EntityAttributeModifier(
ModAttributes.MODIFIERS.forArmorResistance(type),
toxRes,
EntityAttributeModifier.Operation.ADD_MULTIPLIED_BASE
),
AttributeModifierSlot.forEquipmentSlot(this.getSlotType())
)
);
}

/*
Programmatically generate armor's toxin resistance values.
Not guarantied to function with negative values, and outputs NaN if it doesn't like something about the input.
Interactive Desmos graph for the output "curve": https://www.desmos.com/calculator/wqi6fd5poc
*/
@Unique
private static final Map<ArmorItem.Type,Double> baseValues = Map.of(
ArmorItem.Type.HELMET, 1.0,
ArmorItem.Type.CHESTPLATE, 3.0,
ArmorItem.Type.LEGGINGS, 2.0,
ArmorItem.Type.BOOTS, 1.0
);
@Unique
private static final Map<ArmorItem.Type,Double> scalingFactors = Map.of(
ArmorItem.Type.HELMET, 0.15,
ArmorItem.Type.CHESTPLATE, 0.5,
ArmorItem.Type.LEGGINGS, 0.25,
ArmorItem.Type.BOOTS, 0.1
);
@Unique
private Double getToxicResistanceForItem() {
//Animal armor
if (this.type == ArmorItem.Type.BODY) return 1.0;

//Player armor
Integer def = material.value().defense().get(type);
Double base = baseValues.get(type);
Double scale = scalingFactors.get(type);
if (def == null || scale == null) return Double.NaN;
return (base/def)*scale;
}

@Shadow @Final private Supplier<AttributeModifiersComponent> attributeModifiers;
@Shadow public abstract EquipmentSlot getSlotType();
@Shadow @Final protected RegistryEntry<ArmorMaterial> material;
@Shadow @Final protected ArmorItem.Type type;
}

Loading

0 comments on commit 1565fc2

Please sign in to comment.