Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/main/java/de/dafuqs/spectrum/items/food/SlushslideItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.dafuqs.spectrum.items.food;

import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.FoodComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;

import java.util.List;

public class SlushslideItem extends DrinkItem {

public SlushslideItem(Settings settings) {
super(settings);
}

@Override
public void appendTooltip(ItemStack itemStack, World world, List<Text> tooltip, TooltipContext tooltipContext) {
tooltip.add(Text.translatable("item.spectrum.slushslide.tooltip").formatted(Formatting.GRAY));
super.appendTooltip(itemStack, world, tooltip, tooltipContext);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static boolean testEffectFor(LivingEntity entity, StatusEffect effect) {
if (effect.isBeneficial())
return false;

if (SpectrumStatusEffectTags.isIn(SpectrumStatusEffectTags.SOPORIFIC, effect))
if (SpectrumStatusEffectTags.bypassesNectarGloves(effect))
return false;

var trinkets = TrinketsApi.getTrinketComponent(entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static void removeSingleStatusEffect(@NotNull LivingEntity entity, Status
List<StatusEffectInstance> negativeEffects = new ArrayList<>();
for (StatusEffectInstance statusEffectInstance : currentEffects) {
StatusEffect effect = statusEffectInstance.getEffectType();
if (effect.getCategory() == category && !SpectrumStatusEffectTags.isIn(SpectrumStatusEffectTags.SOPORIFIC, effect) && !SpectrumStatusEffectTags.isUnclearable(effect)) {
if (effect.getCategory() == category && !SpectrumStatusEffectTags.isIn(SpectrumStatusEffectTags.SOPORIFIC, effect) && !SpectrumStatusEffectTags.bypassesWhispyCirclet(effect)) {
negativeEffects.add(statusEffectInstance);
}
}
Expand Down Expand Up @@ -90,7 +90,7 @@ public static void shortenNegativeStatusEffects(@NotNull LivingEntity entity, in
}

public static boolean affects(StatusEffect statusEffect) {
return statusEffect.getCategory() == StatusEffectCategory.HARMFUL && !SpectrumStatusEffectTags.isIn(SpectrumStatusEffectTags.SOPORIFIC, statusEffect) && !SpectrumStatusEffectTags.isUnclearable(statusEffect);
return statusEffect.getCategory() == StatusEffectCategory.HARMFUL && !SpectrumStatusEffectTags.bypassesWhispyCirclet(statusEffect);
}

public static void preventPhantomSpawns(@NotNull ServerPlayerEntity serverPlayerEntity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.llamalad7.mixinextras.sugar.Local;
import de.dafuqs.spectrum.api.status_effect.Incurable;
import de.dafuqs.spectrum.registries.*;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.effect.StatusEffect;
Expand All @@ -26,6 +27,8 @@ private static void clearIncurableEffects(ServerCommandSource source, Collection
if (((Incurable) effect).spectrum$isIncurable())
((Incurable) effect).spectrum$setIncurable(false);
}
// manually remove fatal slumber to bypass turning it into eternal slumber
living.removeStatusEffect(SpectrumStatusEffects.FATAL_SLUMBER);
}
}

Expand Down
49 changes: 39 additions & 10 deletions src/main/java/de/dafuqs/spectrum/mixin/LivingEntityMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,21 +227,48 @@ public abstract class LivingEntityMixin {
private boolean spectrum$canHaveStatusEffect(boolean original, @Local(argsOnly = true) StatusEffectInstance statusEffectInstance) {
var instance = (LivingEntity) (Object) this;

if (original && this.hasStatusEffect(SpectrumStatusEffects.IMMUNITY) && statusEffectInstance.getEffectType().getCategory() == StatusEffectCategory.HARMFUL && !SpectrumStatusEffectTags.isImmunityImmune(statusEffectInstance.getEffectType())) {
if (Incurable.isIncurable(statusEffectInstance)) {
// if fatal slumber is applied, incoming immunity converts fatal->eternal and doesn't apply immunity
if (original && this.hasStatusEffect(SpectrumStatusEffects.FATAL_SLUMBER) && statusEffectInstance.getEffectType() == SpectrumStatusEffects.IMMUNITY) {
ImmunityStatusEffect.removeNegativeStatusEffects(instance);
addStatusEffect(new StatusEffectInstance(SpectrumStatusEffects.ETERNAL_SLUMBER, 6000));
return false;
}

// if eternal slumber is applied, incoming immunity loses 30s of duration but does still apply
if (original && this.hasStatusEffect(SpectrumStatusEffects.ETERNAL_SLUMBER) && statusEffectInstance.getEffectType() == SpectrumStatusEffects.IMMUNITY) {
ImmunityStatusEffect.removeNegativeStatusEffects(instance);
((StatusEffectInstanceAccessor) statusEffectInstance).setDuration(Math.max(0, statusEffectInstance.getDuration() - 600));
if (!instance.getWorld().isClient()) {
((ServerWorld) instance.getWorld()).getChunkManager().sendToNearbyPlayers(instance, new EntityStatusEffectS2CPacket(instance.getId(), statusEffectInstance));
}
return true;
}

// normal immunity handling (block incoming negative effects)
if (original && this.hasStatusEffect(SpectrumStatusEffects.IMMUNITY) && statusEffectInstance.getEffectType().getCategory() == StatusEffectCategory.HARMFUL && !SpectrumStatusEffectTags.bypassesImmunity(statusEffectInstance.getEffectType())) {
// incurable effects (and eternal slumber) cost chunks of immunity duration to block
if (Incurable.isIncurable(statusEffectInstance) || statusEffectInstance.getEffectType() == SpectrumStatusEffects.ETERNAL_SLUMBER) {
var immunity = getStatusEffect(SpectrumStatusEffects.IMMUNITY);
var cost = 600 * (statusEffectInstance.getAmplifier() + 1);
var immDuration = immunity.getDuration();

if (immunity.getDuration() >= cost) {
((StatusEffectInstanceAccessor) immunity).setDuration(Math.max(5, immunity.getDuration() - cost));
if (immDuration >= cost) {
((StatusEffectInstanceAccessor) immunity).setDuration(immDuration - cost);
if (!instance.getWorld().isClient()) {
((ServerWorld) instance.getWorld()).getChunkManager().sendToNearbyPlayers(instance, new EntityStatusEffectS2CPacket(instance.getId(), immunity));
}
return false;
} else {
removeStatusEffect(SpectrumStatusEffects.IMMUNITY);
return false;
}
else {
return true;
}
}

// fatal slumber removes the immunity and then turns into eternal slumber
if (statusEffectInstance.getEffectType() == SpectrumStatusEffects.FATAL_SLUMBER) {
removeStatusEffect(SpectrumStatusEffects.IMMUNITY);
addStatusEffect(new StatusEffectInstance(SpectrumStatusEffects.ETERNAL_SLUMBER, 6000));
return false;
}

return false;
Expand Down Expand Up @@ -496,8 +523,10 @@ private float getToughness() {
@Inject(method = "addStatusEffect(Lnet/minecraft/entity/effect/StatusEffectInstance;Lnet/minecraft/entity/Entity;)Z", at = @At("HEAD"), cancellable = true)
private void spectrum$modifyOrCancelEffects(StatusEffectInstance effect, Entity source, CallbackInfoReturnable<Boolean> cir) {
var entity = (LivingEntity) (Object) this;
var effectType = effect.getEffectType();

if (AetherGracedNectarGlovesItem.testEffectFor(entity, effect.getEffectType())) {
// trigger gloves only if you don't have immunity, or if you do have immunity but the incoming effect bypasses it
if ((!entity.hasStatusEffect(SpectrumStatusEffects.IMMUNITY) || SpectrumStatusEffectTags.bypassesImmunity(effectType)) && AetherGracedNectarGlovesItem.testEffectFor(entity, effectType)) {
var cost = (effect.getAmplifier() + 1) * AetherGracedNectarGlovesItem.HARMFUL_EFFECT_COST;

if (Incurable.isIncurable(effect))
Expand All @@ -510,13 +539,13 @@ private float getToughness() {
}

var resistanceModifier = MathHelper.clamp(SleepStatusEffect.getSleepResistance(effect, entity), 0.1F, 10F);
if (effect.getEffectType() == SpectrumStatusEffects.ETERNAL_SLUMBER) {
if (effectType == SpectrumStatusEffects.ETERNAL_SLUMBER) {
if (SleepStatusEffect.isImmuneish(entity)) {
((StatusEffectInstanceAccessor) effect).setDuration(Math.round(effect.getDuration() / resistanceModifier));
} else if (!entity.getType().isIn(SpectrumEntityTypeTags.SLEEP_RESISTANT)) {
((StatusEffectInstanceAccessor) effect).setDuration(StatusEffectInstance.INFINITE);
}
} else if (effect.getEffectType() == SpectrumStatusEffects.FATAL_SLUMBER) {
} else if (effectType == SpectrumStatusEffects.FATAL_SLUMBER) {
if (SleepStatusEffect.isImmuneish(entity) && entity.getType().isIn(ConventionalEntityTypeTags.BOSSES)) {
((StatusEffectInstanceAccessor) effect).setDuration(20 * 60);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import net.minecraft.entity.effect.*;
import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.server.world.*;
import org.jetbrains.annotations.*;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import java.util.*;

Expand All @@ -21,22 +23,40 @@ public abstract class LivingEntityPreventStatusClearMixin {

@Shadow
public abstract void remove(Entity.RemovalReason reason);


@Shadow
public abstract boolean addStatusEffect(StatusEffectInstance effect);

@Shadow
public abstract Map<StatusEffect,StatusEffectInstance> getActiveStatusEffects();

@Inject(method = "clearStatusEffects", at = @At("HEAD"))
private void spectrum$detectFatalSlumber(CallbackInfoReturnable<Boolean> cir, @Share("hasFatalSlumber") LocalBooleanRef hasFatalSlumber) {
hasFatalSlumber.set(getActiveStatusEffects().containsKey(SpectrumStatusEffects.FATAL_SLUMBER));
}

@Inject(method = "clearStatusEffects", at = @At("TAIL"))
private void spectrum$applyEternalSlumberIfFatalSlumberRemoved(CallbackInfoReturnable<Boolean> cir, @Share("hasFatalSlumber") LocalBooleanRef hasFatalSlumber) {
if (hasFatalSlumber.get()) {
addStatusEffect(new StatusEffectInstance(SpectrumStatusEffects.ETERNAL_SLUMBER, 6000));
}
}

@WrapWithCondition(method = "clearStatusEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;onStatusEffectRemoved(Lnet/minecraft/entity/effect/StatusEffectInstance;)V"))
private boolean spectrum$preventStatusClear(LivingEntity instance, StatusEffectInstance effect, @Share("blockRemoval") LocalBooleanRef blockRemoval) {
if (Incurable.isIncurable(effect)) {
if (affectedByImmunity(instance, effect.getAmplifier()))
return true;

if (effect.getDuration() > 1200) {
((StatusEffectInstanceAccessor) effect).setDuration(effect.getDuration() - 1200);
if (!instance.getWorld().isClient()) {
((ServerWorld) instance.getWorld()).getChunkManager().sendToNearbyPlayers(instance, new EntityStatusEffectS2CPacket(instance.getId(), effect));
}

blockRemoval.set(true);
return false;
// new duration = duration - 1min OR duration * 0.4, whichever is the smaller reduction
int duration = effect.getDuration();
((StatusEffectInstanceAccessor) effect).setDuration(Math.max(duration - 1200, (int)(duration * 0.4)));
if (!instance.getWorld().isClient()) {
((ServerWorld) instance.getWorld()).getChunkManager().sendToNearbyPlayers(instance, new EntityStatusEffectS2CPacket(instance.getId(), effect));
}

blockRemoval.set(true);
return false;
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ public class SpectrumEventListenersMixin {
@Unique
private static TriState _shouldRemove(LivingEntity entity, StatusEffectInstance effect, Object reason) {
if (Incurable.isIncurable(effect) && !affectedByImmunity(entity, effect.getAmplifier())) {
if (effect.getDuration() > 1200) {
((StatusEffectInstanceAccessor) effect).setDuration(effect.getDuration() - 1200);
if (!entity.getWorld().isClient()) {
((ServerWorld) entity.getWorld()).getChunkManager().sendToNearbyPlayers(entity, new EntityStatusEffectS2CPacket(entity.getId(), effect));
}
// new duration = duration - 1min OR duration * 0.4, whichever is the smaller reduction
int duration = effect.getDuration();
((StatusEffectInstanceAccessor) effect).setDuration(Math.max(duration - 1200, (int)(duration * 0.4)));
if (!entity.getWorld().isClient()) {
((ServerWorld) entity.getWorld()).getChunkManager().sendToNearbyPlayers(entity, new EntityStatusEffectS2CPacket(entity.getId(), effect));
}
return TriState.FALSE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent RESTORATION_TEA = new FoodComponent.Builder()
.hunger(2).saturationModifier(2F)
.hunger(2).saturationModifier(2F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.IMMUNITY, 1200), 1.0F)
.build();

Expand All @@ -96,7 +96,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent DEMON_TEA = new FoodComponent.Builder()
.snack().hunger(2).saturationModifier(0.2F)
.snack().hunger(2).saturationModifier(0.2F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.FRENZY, 800, 1), 2.0F / 3.0F)
.build();

Expand Down Expand Up @@ -135,7 +135,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent HOT_CHOCOLATE = new FoodComponent.Builder()
.hunger(6).saturationModifier(0.2F)
.hunger(6).saturationModifier(0.2F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.NOURISHING, 1200), 1.0F)
.build();

Expand All @@ -144,7 +144,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent KARAK_CHAI = new FoodComponent.Builder()
.hunger(5).saturationModifier(1F)
.hunger(5).saturationModifier(1F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.CALMING, 2400, 1), 1.0F)
.build();

Expand All @@ -154,7 +154,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent AZALEA_TEA = new FoodComponent.Builder()
.hunger(2).saturationModifier(0.1F)
.hunger(2).saturationModifier(0.1F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.SOMNOLENCE, 1200), 1.0F)
.build();

Expand Down Expand Up @@ -369,7 +369,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent GOLDEN_BRISTLE_TEA = new FoodComponent.Builder()
.hunger(6).saturationModifier(1F)
.hunger(6).saturationModifier(1F).alwaysEdible()
.statusEffect(new StatusEffectInstance(StatusEffects.INSTANT_HEALTH), 0.5F)
.statusEffect(new StatusEffectInstance(StatusEffects.STRENGTH, 600, 3), 1)
.statusEffect(new StatusEffectInstance(StatusEffects.RESISTANCE, 600, 0), 0.5F)
Expand Down Expand Up @@ -428,7 +428,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent PEACH_CREAM = new FoodComponent.Builder()
.hunger(8).saturationModifier(1F)
.hunger(8).saturationModifier(1F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.TOUGHNESS, 3000, 1), 1.0F)
.build();

Expand All @@ -455,7 +455,7 @@ public class SpectrumFoodComponents {
.build();

public static final FoodComponent SLUSHSLIDE = new FoodComponent.Builder()
.hunger(9).saturationModifier(0.6F)
.hunger(9).saturationModifier(0.6F).alwaysEdible()
.statusEffect(new StatusEffectInstance(SpectrumStatusEffects.SWIFTNESS, 2400, 1), 1.0F)
.statusEffect(new StatusEffectInstance(StatusEffects.HASTE, 2400, 1), 1.0F)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ public Map<Enchantment, Integer> getDefaultEnchantments() {
public static final Item PEACH_JAM = new Item(IS.of().food(SpectrumFoodComponents.PEACH_JAM));
public static final Item RABBIT_CREAM_PIE = new ItemWithTooltip(IS.of().food(SpectrumFoodComponents.RABBIT_CREAM_PIE), "item.spectrum.rabbit_cream_pie.tooltip");
public static final Item SEDATIVES = new SedativesItem(IS.of().food(SpectrumFoodComponents.SEDATIVES), "item.spectrum.sedatives.tooltip");
public static final Item SLUSHSLIDE = new ItemWithTooltip(IS.of().food(SpectrumFoodComponents.SLUSHSLIDE), "item.spectrum.slushslide.tooltip");
public static final Item SLUSHSLIDE = new SlushslideItem(IS.of(16).food(SpectrumFoodComponents.SLUSHSLIDE));
public static final Item SURSTROMMING = new Item(IS.of().food(SpectrumFoodComponents.SURSTROMMING));
public static final Item EVERNECTAR = new EvernectarItem(IS.of(1, Rarity.EPIC).food(SpectrumFoodComponents.EVERNECTAR).recipeRemainder(Items.GLASS_BOTTLE), "item.spectrum.evernectar.tooltip");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@

public class SpectrumStatusEffectTags {

public static TagKey<StatusEffect> NO_EFFECT_CLEAR;
public static TagKey<StatusEffect> IMMUNITY_IMMUNE;
public static TagKey<StatusEffect> BYPASSES_WHISPY_CIRCLET;
public static TagKey<StatusEffect> BYPASSES_NECTAR_GLOVES;
public static TagKey<StatusEffect> BYPASSES_IMMUNITY;
public static TagKey<StatusEffect> NO_DURATION_EXTENSION;
public static TagKey<StatusEffect> SOPORIFIC;
public static TagKey<StatusEffect> NIGHT_ALCHEMY;

public static void register() {
NO_EFFECT_CLEAR = of("unclearable");
IMMUNITY_IMMUNE = of("immunity_immune");
BYPASSES_WHISPY_CIRCLET = of("bypasses_whispy_circlet");
BYPASSES_NECTAR_GLOVES = of("bypasses_nectar_gloves");
BYPASSES_IMMUNITY = of("bypasses_immunity");
NO_DURATION_EXTENSION = of("no_duration_extension");
SOPORIFIC = of("soporific");
NIGHT_ALCHEMY = of("night_alchemy");
Expand All @@ -30,12 +32,16 @@ public static boolean isIn(TagKey<StatusEffect> tag, StatusEffect effect) {
return Registries.STATUS_EFFECT.getEntry(effect).isIn(tag);
}

public static boolean isImmunityImmune(StatusEffect statusEffect) {
return isIn(SpectrumStatusEffectTags.IMMUNITY_IMMUNE, statusEffect);
public static boolean bypassesImmunity(StatusEffect statusEffect) {
return isIn(SpectrumStatusEffectTags.BYPASSES_IMMUNITY, statusEffect);
}

public static boolean bypassesNectarGloves(StatusEffect statusEffect) {
return isIn(SpectrumStatusEffectTags.BYPASSES_NECTAR_GLOVES, statusEffect);
}

public static boolean isUnclearable(StatusEffect statusEffect) {
return isIn(SpectrumStatusEffectTags.NO_EFFECT_CLEAR, statusEffect);
public static boolean bypassesWhispyCirclet(StatusEffect statusEffect) {
return isIn(SpectrumStatusEffectTags.BYPASSES_WHISPY_CIRCLET, statusEffect);
}

public static boolean hasEffectWithTag(LivingEntity livingEntity, TagKey<StatusEffect> tag) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package de.dafuqs.spectrum.status_effects;

import de.dafuqs.spectrum.items.trinkets.*;
import de.dafuqs.spectrum.registries.*;
import net.minecraft.entity.*;
import net.minecraft.entity.attribute.*;
import net.minecraft.entity.effect.*;
import org.jetbrains.annotations.*;
import java.util.*;

public class ImmunityStatusEffect extends StatusEffect {

Expand All @@ -19,13 +22,28 @@ public boolean canApplyUpdateEffect(int duration, int amplifier) {
@Override
public void applyUpdateEffect(LivingEntity entity, int amplifier) {
super.applyUpdateEffect(entity, amplifier);
WhispyCircletItem.removeNegativeStatusEffects(entity);
removeNegativeStatusEffects(entity);
}

@Override
public void onApplied(LivingEntity entity, AttributeContainer attributes, int amplifier) {
super.onApplied(entity, attributes, amplifier);
WhispyCircletItem.removeNegativeStatusEffects(entity);
removeNegativeStatusEffects(entity);
}

public static void removeNegativeStatusEffects(@NotNull LivingEntity entity) {
Set<StatusEffect> effectsToRemove = new HashSet<>();
Collection<StatusEffectInstance> currentEffects = entity.getStatusEffects();
for (StatusEffectInstance instance : currentEffects) {
StatusEffect effectType = instance.getEffectType();
if (effectType.getCategory() == StatusEffectCategory.HARMFUL && !SpectrumStatusEffectTags.bypassesImmunity(effectType)) {
effectsToRemove.add(effectType);
}
}

for (StatusEffect effect : effectsToRemove) {
entity.removeStatusEffect(effect);
}
}

}
Loading
Loading