darkness effect + warden targetting fix

This commit is contained in:
ItsBlackGear 2022-07-22 04:00:45 -04:00
parent 7be1b91581
commit 6c66e8e946
16 changed files with 570 additions and 15 deletions

View file

@ -8,6 +8,7 @@ import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.registry.WBEnchantments;
import com.cursedcauldron.wildbackport.common.registry.WBGameEvents;
import com.cursedcauldron.wildbackport.common.registry.WBItems;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.cursedcauldron.wildbackport.common.registry.WBPositionSources;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBFeatures;
import com.cursedcauldron.wildbackport.common.registry.worldgen.RootPlacerType;
@ -43,6 +44,7 @@ public class WildBackport {
WBFeatures.FEATURES.register();
WBItems.ITEMS.register();
WBMemoryModules.MEMORIES.register();
WBMobEffects.EFFECTS.register();
WBParticleTypes.PARTICLES.register();
WBPositionSources.SOURCES.register();
RootPlacerType.PLACERS.register();

View file

@ -1,6 +1,7 @@
package com.cursedcauldron.wildbackport.common.blocks;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.tag.WBBlockTags;
import com.cursedcauldron.wildbackport.core.mixin.access.PointedDripstoneBlockAccessor;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
@ -18,7 +19,7 @@ public record DrippingFluid(BlockPos pos, Fluid fluid, BlockState sourceState) {
Optional<DrippingFluid> fluidAbove = getFluidAboveStalactite(world, blockPos, state);
if (fluidAbove.isPresent()) {
Fluid fluid = fluidAbove.get().fluid;
if (fluidAbove.get().sourceState().is(WBBlocks.MUD.get()) && fluid == Fluids.WATER) {
if (fluidAbove.get().sourceState().is(WBBlockTags.MUD) && fluid == Fluids.WATER) {
world.setBlockAndUpdate(fluidAbove.get().pos, Blocks.CLAY.defaultBlockState());
world.levelEvent(1504, blockPos, 0);
ci.cancel();
@ -30,7 +31,7 @@ public record DrippingFluid(BlockPos pos, Fluid fluid, BlockState sourceState) {
return !PointedDripstoneBlockAccessor.callIsStalactite(state) ? Optional.empty() : PointedDripstoneBlockAccessor.callFindRootBlock(level, pos, state, 11).map(blockPos -> {
BlockPos position = blockPos.above();
BlockState sourceState = level.getBlockState(position);
Fluid fluid = sourceState.is(WBBlocks.MUD.get()) && !level.dimensionType().ultraWarm() ? Fluids.WATER : level.getFluidState(position).getType();
Fluid fluid = sourceState.is(WBBlockTags.MUD) && !level.dimensionType().ultraWarm() ? Fluids.WATER : level.getFluidState(position).getType();
return new DrippingFluid(position, fluid, sourceState);
});
}

View file

@ -0,0 +1,40 @@
package com.cursedcauldron.wildbackport.common.effects;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import java.util.Optional;
import java.util.function.Supplier;
public interface EffectFactor {
static EffectFactor of(MobEffect effect) {
return (EffectFactor)effect;
}
MobEffect setFactorCalculationData(Supplier<FactorCalculationData> data);
Supplier<FactorCalculationData> getFactorCalculationData();
static Optional<FactorCalculationData> create(MobEffect effect) {
return Optional.ofNullable(of(effect).getFactorCalculationData().get());
}
interface Instance {
static Instance of(MobEffectInstance instance) {
return (Instance)instance;
}
void setFactorCalculationData(Optional<FactorCalculationData> data);
Optional<FactorCalculationData> getFactorCalculationData();
}
interface Network {
static Network of(Packet<?> packet) {
return (Network)packet;
}
FactorCalculationData getFactorCalculationData();
}
}

View file

@ -0,0 +1,70 @@
package com.cursedcauldron.wildbackport.common.effects;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.LivingEntity;
public class FactorCalculationData {
public static final Codec<FactorCalculationData> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(ExtraCodecs.NON_NEGATIVE_INT.fieldOf("padding_duration").forGetter(data -> {
return data.paddingDuration;
}), Codec.FLOAT.fieldOf("factor_start").orElse(0.0F).forGetter(data -> {
return data.factorStart;
}), Codec.FLOAT.fieldOf("factor_target").orElse(1.0F).forGetter(data -> {
return data.factorTarget;
}), Codec.FLOAT.fieldOf("factor_current").orElse(0.0F).forGetter(data -> {
return data.factorCurrent;
}), ExtraCodecs.NON_NEGATIVE_INT.fieldOf("effect_changed_timestamp").orElse(0).forGetter(data -> {
return data.effectChangedTimestamp;
}), Codec.FLOAT.fieldOf("factor_previous_frame").orElse(0.0F).forGetter(data -> {
return data.factorPreviousFrame;
}), Codec.BOOL.fieldOf("had_effect_last_tick").orElse(false).forGetter(data -> {
return data.hadEffectLastTick;
})).apply(instance, FactorCalculationData::new);
});
private final int paddingDuration;
private float factorStart;
private float factorTarget;
private float factorCurrent;
public int effectChangedTimestamp;
private float factorPreviousFrame;
private boolean hadEffectLastTick;
public FactorCalculationData(int paddingDuration, float factorStart, float factorTarget, float factorCurrent, int effectChangedTimestamp, float factorPreviousFrame, boolean hadEffectLastTick) {
this.paddingDuration = paddingDuration;
this.factorStart = factorStart;
this.factorTarget = factorTarget;
this.factorCurrent = factorCurrent;
this.effectChangedTimestamp = effectChangedTimestamp;
this.factorPreviousFrame = factorPreviousFrame;
this.hadEffectLastTick = hadEffectLastTick;
}
public FactorCalculationData(int paddingDuration) {
this(paddingDuration, 0.0F, 1.0F, 0.0F, 0, 0.0F, false);
}
public void update(MobEffectInstance instance) {
this.factorPreviousFrame = this.factorCurrent;
boolean inRange = instance.getDuration() > this.paddingDuration;
if (this.hadEffectLastTick != inRange) {
this.hadEffectLastTick = inRange;
this.effectChangedTimestamp = instance.getDuration();
this.factorStart = this.factorCurrent;
this.factorTarget = inRange ? 1.0F : 0.0F;
}
float delta = Mth.clamp(((float)this.effectChangedTimestamp - (float)instance.getDuration()) / (float)this.paddingDuration, 0.0F, 1.0F);
this.factorCurrent = Mth.lerp(delta, this.factorCurrent, this.factorTarget);
}
public float lerp(LivingEntity entity, float factor) {
if (entity.isRemoved()) this.factorPreviousFrame = this.factorCurrent;
return Mth.lerp(factor, this.factorPreviousFrame, this.factorCurrent);
}
}

View file

@ -3,13 +3,14 @@ package com.cursedcauldron.wildbackport.common.entities;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.animation.api.AnimationState;
import com.cursedcauldron.wildbackport.client.registry.WBSoundEvents;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.brain.WardenBrain;
import com.cursedcauldron.wildbackport.common.entities.brain.warden.SonicBoom;
import com.cursedcauldron.wildbackport.common.entities.access.api.Poses;
import com.cursedcauldron.wildbackport.common.entities.warden.Angriness;
import com.cursedcauldron.wildbackport.common.entities.warden.MobPositionSource;
import com.cursedcauldron.wildbackport.common.entities.warden.VibrationListenerSource;
import com.cursedcauldron.wildbackport.common.entities.warden.WardenAngerManager;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntities;
import com.cursedcauldron.wildbackport.common.registry.entity.WBMemoryModules;
import com.cursedcauldron.wildbackport.common.tag.WBGameEventTags;
@ -35,7 +36,6 @@ import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.damagesource.IndirectEntityDamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.EntitySelector;
@ -68,6 +68,7 @@ import java.util.Random;
//<>
//TODO: fix warden not detecting vibrations by players
public class Warden extends Monster implements VibrationListenerSource.VibrationConfig {
private static final EntityDataAccessor<Integer> ANGER = SynchedEntityData.defineId(Warden.class, EntityDataSerializers.INT);
private int tendrilPitchEnd;
@ -266,7 +267,7 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
}
private int getHeartRate() {
return 40 - Mth.floor(Mth.clamp((float)this.getAnger() / (float) Angriness.ANGRY.getThreshold(), 0.0F, 1.0F) * 30.0F);
return 40 - Mth.floor(Mth.clamp((float)this.getAnger() / (float)Angriness.ANGRY.getThreshold(), 0.0F, 1.0F) * 30.0F);
}
public float getTendrilPitch(float tickDelta) {
@ -353,7 +354,7 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
}
public static void addDarknessEffectToClosePlayers(ServerLevel level, Vec3 pos, @Nullable Entity entity, int range) {
MobEffectInstance instance = new MobEffectInstance(MobEffects.BLINDNESS, 260, 0, false, false);
MobEffectInstance instance = new MobEffectInstance(WBMobEffects.DARKNESS.get(), 260, 0, false, false);
MobUtils.addEffectToPlayersWithinDistance(level, entity, pos, range, instance, 200);
}
@ -408,7 +409,7 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
}
}
public Optional<LivingEntity> getEntityAngryAt() {
public Optional<LivingEntity> getPrimeSuspect() {
return this.getAngriness().isAngry() ? this.angerManager.getPrimeSuspect() : Optional.empty();
}
@ -423,7 +424,7 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
}
@Nullable @Override
public SpawnGroupData finalizeSpawn(ServerLevelAccessor accessor, DifficultyInstance difficulty, MobSpawnType spawn, @Nullable SpawnGroupData groupData, @Nullable CompoundTag tag) {
public SpawnGroupData finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType spawn, @Nullable SpawnGroupData groupData, @Nullable CompoundTag tag) {
this.getBrain().setMemoryWithExpiry(WBMemoryModules.DIG_COOLDOWN.get(), Unit.INSTANCE, 1200L);
if (spawn == MobSpawnType.TRIGGERED) {
this.setPose(Poses.EMERGING.get());
@ -431,7 +432,7 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
this.playSound(WBSoundEvents.WARDEN_AGITATED, 5.0F, 1.0F);
}
return super.finalizeSpawn(accessor, difficulty, spawn, groupData, tag);
return super.finalizeSpawn(level, difficulty, spawn, groupData, tag);
}
@Override
@ -452,8 +453,8 @@ public class Warden extends Monster implements VibrationListenerSource.Vibration
public void updateAttackTarget(LivingEntity entity) {
this.getBrain().eraseMemory(WBMemoryModules.ROAR_TARGET.get());
entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, entity);
entity.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, entity);
this.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
SonicBoom.setCooldown(this, 200);
}

View file

@ -95,15 +95,15 @@ public class WardenBrain {
}
private static void initIdleActivity(Brain<Warden> brain) {
brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new SetRoarTarget<>(Warden::getEntityAngryAt), new TryToSniff(), new RunOne<>(ImmutableMap.of(WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_ABSENT), ImmutableList.of(Pair.of(new RandomStroll(0.5F), 2), Pair.of(new DoNothing(30, 60), 1)))));
brain.addActivity(Activity.IDLE, 10, ImmutableList.of(new SetRoarTarget<>(Warden::getPrimeSuspect), new TryToSniff(), new RunOne<>(ImmutableMap.of(WBMemoryModules.IS_SNIFFING.get(), MemoryStatus.VALUE_ABSENT), ImmutableList.of(Pair.of(new RandomStroll(0.5F), 2), Pair.of(new DoNothing(30, 60), 1)))));
}
private static void initInvestigateActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.INVESTIGATE.get(), 5, ImmutableList.of(new SetRoarTarget<>(Warden::getEntityAngryAt), new GoToTargetLocation<>(WBMemoryModules.DISTURBANCE_LOCATION.get(), 2, 0.7F)), WBMemoryModules.DISTURBANCE_LOCATION.get());
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.INVESTIGATE.get(), 5, ImmutableList.of(new SetRoarTarget<>(Warden::getPrimeSuspect), new GoToTargetLocation<>(WBMemoryModules.DISTURBANCE_LOCATION.get(), 2, 0.7F)), WBMemoryModules.DISTURBANCE_LOCATION.get());
}
private static void initSniffingActivity(Brain<Warden> brain) {
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.SNIFF.get(), 5, ImmutableList.of(new SetRoarTarget<>(Warden::getEntityAngryAt), new Sniffing<>(SNIFFING_DURATION)), WBMemoryModules.IS_SNIFFING.get());
brain.addActivityAndRemoveMemoryWhenStopped(WBActivities.SNIFF.get(), 5, ImmutableList.of(new SetRoarTarget<>(Warden::getPrimeSuspect), new Sniffing<>(SNIFFING_DURATION)), WBMemoryModules.IS_SNIFFING.get());
}
private static void initRoarActivity(Brain<Warden> brain) {
@ -132,7 +132,7 @@ public class WardenBrain {
}
public static void setDisturbanceLocation(Warden warden, BlockPos pos) {
if (warden.level.getWorldBorder().isWithinBounds(pos) && warden.getEntityAngryAt().isEmpty() && warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()) {
if (warden.level.getWorldBorder().isWithinBounds(pos) && warden.getPrimeSuspect().isEmpty() && warden.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty()) {
setDigCooldown(warden);
warden.getBrain().setMemoryWithExpiry(WBMemoryModules.SNIFF_COOLDOWN.get(), Unit.INSTANCE, 100L);
warden.getBrain().setMemoryWithExpiry(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos), 100L);

View file

@ -0,0 +1,18 @@
package com.cursedcauldron.wildbackport.common.registry;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import com.cursedcauldron.wildbackport.common.effects.FactorCalculationData;
import com.cursedcauldron.wildbackport.core.api.CoreRegistry;
import com.cursedcauldron.wildbackport.core.mixin.access.MobEffectAccessor;
import net.minecraft.core.Registry;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import java.util.function.Supplier;
public class WBMobEffects {
public static final CoreRegistry<MobEffect> EFFECTS = CoreRegistry.create(Registry.MOB_EFFECT, WildBackport.MOD_ID);
public static final Supplier<MobEffect> DARKNESS = EFFECTS.register("darkness", () -> EffectFactor.of(MobEffectAccessor.createMobEffect(MobEffectCategory.HARMFUL, 2696993)).setFactorCalculationData(() -> new FactorCalculationData(22)));
}

View file

@ -20,4 +20,7 @@ public class WBBlockTags {
// Deep Dark
public static final TagKey<Block> SCULK_REPLACEABLE = TAGS.create("sculk_replaceable");
public static final TagKey<Block> SCULK_REPLACEABLE_WORLD_GEN = TAGS.create("sculk_replaceable_world_gen");
// Compatibility
public static final TagKey<Block> MUD = TAGS.create("mud");
}

View file

@ -0,0 +1,14 @@
package com.cursedcauldron.wildbackport.core.mixin.access;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(MobEffect.class)
public interface MobEffectAccessor {
@Invoker("<init>")
static MobEffect createMobEffect(MobEffectCategory mobEffectCategory, int i) {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,82 @@
package com.cursedcauldron.wildbackport.core.mixin.client;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Camera;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FogType;
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.callback.CallbackInfo;
@Mixin(FogRenderer.class)
public class FogRendererMixin {
@Shadow private static float fogRed;
@Shadow private static float fogGreen;
@Shadow private static float fogBlue;
private static float fogPartialTicks;
@Inject(method = "setupColor", at = @At("TAIL"))
private static void applyDarknessColor(Camera camera, float partialTicks, ClientLevel level, int viewDistance, float skyDarkness, CallbackInfo ci) {
FogType type = camera.getFluidInCamera();
fogPartialTicks = partialTicks;
double colorModifier = (camera.getPosition().y - (double)level.getMinBuildHeight()) * level.getLevelData().getClearColorScale();
if (camera.getEntity() instanceof LivingEntity living && living.hasEffect(WBMobEffects.DARKNESS.get())) {
MobEffectInstance effect = living.getEffect(WBMobEffects.DARKNESS.get());
if (effect != null) {
EffectFactor.Instance instance = EffectFactor.Instance.of(effect);
colorModifier = instance.getFactorCalculationData().isPresent() ? 1.0F - instance.getFactorCalculationData().get().lerp(living, partialTicks) : 0.0D;
}
}
if (colorModifier < 1.0D && type != FogType.LAVA) {
if (colorModifier < 0.0D) {
colorModifier = 0.0D;
}
colorModifier *= colorModifier;
fogRed = (float)((double)fogRed * colorModifier);
fogGreen = (float)((double)fogGreen * colorModifier);
fogBlue = (float)((double)fogBlue * colorModifier);
}
if (skyDarkness > 0.0F) {
fogRed = fogRed * (1.0F - skyDarkness) + fogRed * 0.7F * skyDarkness;
fogGreen = fogGreen * (1.0F - skyDarkness) + fogGreen * 0.6F * skyDarkness;
fogBlue = fogBlue * (1.0F - skyDarkness) + fogBlue * 0.6F * skyDarkness;
}
RenderSystem.clearColor(fogRed, fogGreen, fogBlue, 0.0F);
}
@Inject(method = "setupFog", at = @At("TAIL"), remap = false)
private static void applyDarknessFog(Camera camera, FogRenderer.FogMode mode, float viewDistance, boolean thickFog, CallbackInfo ci) {
FogType fogtype = camera.getFluidInCamera();
if (fogtype != FogType.WATER) {
if (camera.getEntity() instanceof LivingEntity living && living.hasEffect(WBMobEffects.DARKNESS.get())) {
MobEffectInstance effect = living.getEffect(WBMobEffects.DARKNESS.get());
if (effect != null) {
EffectFactor.Instance instance = EffectFactor.Instance.of(effect);
if (instance.getFactorCalculationData().isPresent()) {
float modifier = Mth.lerp(instance.getFactorCalculationData().get().lerp(living, fogPartialTicks), viewDistance, 15.0F);
float start = mode == FogRenderer.FogMode.FOG_SKY ? 0.0F : modifier * 0.75F;
RenderSystem.setShaderFogStart(start);
RenderSystem.setShaderFogEnd(modifier);
}
}
}
}
}
}

View file

@ -0,0 +1,133 @@
package com.cursedcauldron.wildbackport.core.mixin.client;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import com.cursedcauldron.wildbackport.common.registry.WBMobEffects;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
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.callback.CallbackInfo;
@Mixin(LightTexture.class)
public abstract class LightTextureMixin {
@Shadow @Final private Minecraft minecraft;
@Shadow private boolean updateLightTexture;
@Shadow private float blockLightRedFlicker;
@Shadow protected abstract float getBrightness(Level level, int i);
@Shadow @Final private DynamicTexture lightTexture;
@Shadow @Final private NativeImage lightPixels;
@Shadow protected abstract float notGamma(float f);
@Shadow @Final private GameRenderer renderer;
private LocalPlayer getPlayer() {
assert this.minecraft.player != null;
return this.minecraft.player;
}
private float getDarknessFactor(float delta) {
MobEffectInstance instance = this.getPlayer().getEffect(WBMobEffects.DARKNESS.get());
if (this.getPlayer().hasEffect(WBMobEffects.DARKNESS.get()) && instance != null && EffectFactor.Instance.of(instance).getFactorCalculationData().isPresent()) {
return EffectFactor.Instance.of(instance).getFactorCalculationData().get().lerp(this.getPlayer(), delta);
} else {
return 0.0F;
}
}
private float getDarkness(LivingEntity entity, float factor, float delta) {
return Math.max(0.0F, Mth.cos(((float)entity.tickCount - delta) * (float) Math.PI * 0.025F) * 0.45F * factor);
}
//TODO simplify
@Inject(method = "updateLightTexture", at = @At("HEAD"))
private void updateLight(float delta, CallbackInfo ci) {
if (this.updateLightTexture) {
this.updateLightTexture = false;
ClientLevel level = this.minecraft.level;
if (level != null) {
float skyDarken = level.getSkyDarken(1.0F);
float skyFlashTime = level.getSkyFlashTime() > 0 ? 1.0F : skyDarken * 0.95F + 0.05F;
float darknessFactor = this.getDarknessFactor(delta);
float darkness = this.getDarkness(this.getPlayer(), darknessFactor, delta);
float waterVision = this.getPlayer().getWaterVision();
float visionScale = this.getPlayer().hasEffect(MobEffects.NIGHT_VISION) ? GameRenderer.getNightVisionScale(this.getPlayer(), delta) : (waterVision > 0.0F && this.getPlayer().hasEffect(MobEffects.CONDUIT_POWER) ? waterVision : 0.0F);
Vector3f vec3f = new Vector3f(skyDarken, skyDarken, 1.0F);
vec3f.lerp(new Vector3f(1.0F, 1.0F, 1.0F), 0.35F);
float blockLightFlicker = this.blockLightRedFlicker + 1.5F;
Vector3f vec3f2 = new Vector3f();
for (int skyLight = 0; skyLight < 16; ++skyLight) {
for (int blockLight = 0; blockLight < 16; ++blockLight) {
float skyBrightness = this.getBrightness(level, skyLight) * skyFlashTime;
float blockBrightness = this.getBrightness(level, blockLight) * blockLightFlicker;
float yLight = blockBrightness * ((blockBrightness * 0.6F + 0.4F) * 0.6F + 0.4F);
float xzLight = blockBrightness * (blockBrightness * blockBrightness * 0.6F + 0.4F);
vec3f2.set(blockBrightness, yLight, xzLight);
boolean forceLightmap = level.effects().forceBrightLightmap();
if (forceLightmap) {
vec3f2.lerp(new Vector3f(0.99F, 1.12F, 1.0F), 0.25F);
vec3f2.clamp(0.0F, 1.0F);
} else {
Vector3f vec3f3 = vec3f.copy();
vec3f3.mul(skyBrightness);
vec3f2.add(vec3f3);
vec3f2.lerp(new Vector3f(0.75F, 0.75F, 0.75F), 0.04F);
if (this.renderer.getDarkenWorldAmount(delta) > 0.0f) {
float darkenWorldAmount = this.renderer.getDarkenWorldAmount(delta);
Vector3f vec3f4 = vec3f2.copy();
vec3f4.mul(0.7F, 0.6F, 0.6F);
vec3f2.lerp(vec3f4, darkenWorldAmount);
}
}
if (visionScale > 0.0F) {
float modifier = Math.max(vec3f2.x(), Math.max(vec3f2.y(), vec3f2.z()));
if (modifier < 1.0F) {
float scale = 1.0F / modifier;
Vector3f vec3f3 = vec3f2.copy();
vec3f3.mul(scale);
vec3f2.lerp(vec3f3, visionScale);
}
}
if (!forceLightmap) {
if (darkness > 0.0F) {
vec3f2.add(-darkness, -darkness, -darkness);
}
vec3f2.clamp(0.0F, 1.0F);
}
float gamma = (float)this.minecraft.options.gamma;
Vector3f vec3f3 = vec3f2.copy();
vec3f3.map(this::notGamma);
vec3f2.lerp(vec3f3, Math.max(0.0F, gamma - darknessFactor));
vec3f2.lerp(new Vector3f(0.75F, 0.75F, 0.75F), 0.04F);
vec3f2.clamp(0.0F, 1.0F);
vec3f2.mul(255.0F);
int x = (int)vec3f2.x();
int y = (int)vec3f2.y();
int z = (int)vec3f2.z();
this.lightPixels.setPixelRGBA(blockLight, skyLight, -16777216 | z << 16 | y << 8 | x);
}
}
this.lightTexture.upload();
}
}
}
}

View file

@ -0,0 +1,90 @@
package com.cursedcauldron.wildbackport.core.mixin.common;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import com.cursedcauldron.wildbackport.common.effects.FactorCalculationData;
import com.mojang.serialization.Dynamic;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.LivingEntity;
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.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional;
import java.util.function.Supplier;
@Mixin(MobEffect.class)
public class MobEffectMixin implements EffectFactor {
private Supplier<FactorCalculationData> factorCalculationData = () -> null;
@Override
public MobEffect setFactorCalculationData(Supplier<FactorCalculationData> data) {
this.factorCalculationData = data;
return MobEffect.class.cast(this);
}
@Override
public Supplier<FactorCalculationData> getFactorCalculationData() {
return this.factorCalculationData;
}
@Mixin(MobEffectInstance.class)
public static class MobEffectInstanceMixin implements EffectFactor.Instance {
@Shadow @Final private MobEffect effect;
@Shadow private int duration;
private Optional<FactorCalculationData> factorCalculationData;
@Inject(method = "<init>(Lnet/minecraft/world/effect/MobEffect;IIZZZLnet/minecraft/world/effect/MobEffectInstance;)V", at = @At("TAIL"))
private void wb$create(MobEffect effect, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, MobEffectInstance hiddenEffect, CallbackInfo ci) {
this.setFactorCalculationData(EffectFactor.create(effect));
}
@Inject(method = "<init>(Lnet/minecraft/world/effect/MobEffectInstance;)V", at = @At("TAIL"))
private void wb$create(MobEffectInstance instance, CallbackInfo ci) {
this.setFactorCalculationData(EffectFactor.create(this.effect));
}
@Override
public void setFactorCalculationData(Optional<FactorCalculationData> data) {
this.factorCalculationData = data;
}
@Override
public Optional<FactorCalculationData> getFactorCalculationData() {
return this.factorCalculationData;
}
@Inject(method = "update", at = @At("HEAD"), cancellable = true)
private void wb$update(MobEffectInstance instance, CallbackInfoReturnable<Boolean> cir) {
int i = instance.getDuration();
// int i = this.duration;
if (i != this.duration) {
this.factorCalculationData.ifPresent(data -> data.effectChangedTimestamp += this.duration - i);
cir.setReturnValue(true);
}
}
@Inject(method = "tick", at = @At("HEAD"))
private void wb$tick(LivingEntity entity, Runnable runnable, CallbackInfoReturnable<Boolean> cir) {
this.factorCalculationData.ifPresent(data -> data.update(MobEffectInstance.class.cast(this)));
}
@Inject(method = "writeDetailsTo", at = @At("TAIL"))
private void wb$write(CompoundTag tag, CallbackInfo ci) {
this.factorCalculationData.flatMap(instance -> FactorCalculationData.CODEC.encodeStart(NbtOps.INSTANCE, instance).resultOrPartial(WildBackport.LOGGER::error)).ifPresent(data -> tag.put("FactorCalculationData", data));
}
@Inject(method = "loadSpecifiedEffect", at = @At("TAIL"))
private static void wb$load(MobEffect effect, CompoundTag tag, CallbackInfoReturnable<MobEffectInstance> cir) {
Optional<FactorCalculationData> data = tag.contains("FactorCalculationData", 10) ? FactorCalculationData.CODEC.parse(new Dynamic<>(NbtOps.INSTANCE, tag.getCompound("FactorCalculationData"))).resultOrPartial(WildBackport.LOGGER::error) : Optional.empty();
EffectFactor.Instance.of(cir.getReturnValue()).setFactorCalculationData(data);
}
}
}

View file

@ -1,8 +1,44 @@
package com.cursedcauldron.wildbackport.core.mixin.network;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.PacketUtils;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
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.callback.CallbackInfo;
import java.util.Optional;
@Mixin(ClientPacketListener.class)
public class ClientPacketListenerMixin {
@Shadow private ClientLevel level;
@Shadow @Final private Minecraft minecraft;
//TODO simplify
@Inject(method = "handleUpdateMobEffect", at = @At("HEAD"), cancellable = true)
private void wb$updateEffect(ClientboundUpdateMobEffectPacket packet, CallbackInfo ci) {
PacketUtils.ensureRunningOnSameThread(packet, ClientPacketListener.class.cast(this), this.minecraft);
Entity entity = this.level.getEntity(packet.getEntityId());
if (entity instanceof LivingEntity living) {
MobEffect effect = MobEffect.byId(packet.getEffectId() & 0xFF);
if (effect != null) {
MobEffectInstance instance = new MobEffectInstance(effect, packet.getEffectDurationTicks(), packet.getEffectAmplifier(), packet.isEffectAmbient(), packet.isEffectVisible(), packet.effectShowsIcon());
instance.setNoCounter(packet.isSuperLongDuration());
EffectFactor.Instance.of(instance).setFactorCalculationData(Optional.ofNullable(EffectFactor.Network.of(packet).getFactorCalculationData()));
living.forceAddEffect(instance, null);
}
}
ci.cancel();
}
}

View file

@ -0,0 +1,53 @@
package com.cursedcauldron.wildbackport.core.mixin.network;
import com.cursedcauldron.wildbackport.common.effects.EffectFactor;
import com.cursedcauldron.wildbackport.common.effects.FactorCalculationData;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket;
import net.minecraft.world.effect.MobEffectInstance;
import org.jetbrains.annotations.Nullable;
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 java.util.function.BiConsumer;
import java.util.function.Function;
@Mixin(ClientboundUpdateMobEffectPacket.class)
public class ClientboundUpdateMobEffectPacketMixin implements EffectFactor.Network {
private FactorCalculationData factorCalculationData;
@Inject(method = "<init>(ILnet/minecraft/world/effect/MobEffectInstance;)V", at = @At("TAIL"))
private void create(int id, MobEffectInstance instance, CallbackInfo ci) {
this.factorCalculationData = EffectFactor.Instance.of(instance).getFactorCalculationData().orElse(null);
}
@Inject(method = "<init>(Lnet/minecraft/network/FriendlyByteBuf;)V", at = @At("TAIL"))
private void create(FriendlyByteBuf buf, CallbackInfo ci) {
this.factorCalculationData = this.readNullable(buf, buffer -> buffer.readWithCodec(FactorCalculationData.CODEC));
}
@Inject(method = "write", at = @At("TAIL"))
private void writeData(FriendlyByteBuf buf, CallbackInfo ci) {
this.writeNullable(buf, this.factorCalculationData, (buffer, data) -> buffer.writeWithCodec(FactorCalculationData.CODEC, data));
}
@Override
public FactorCalculationData getFactorCalculationData() {
return this.factorCalculationData;
}
private <T> T readNullable(FriendlyByteBuf buf, Function<FriendlyByteBuf, T> consumer) {
return buf.readBoolean() ? consumer.apply(buf) : null;
}
private <T> void writeNullable(FriendlyByteBuf buf, @Nullable T entry, BiConsumer<FriendlyByteBuf, T> consumer) {
if (entry != null) {
buf.writeBoolean(true);
consumer.accept(buf, entry);
} else {
buf.writeBoolean(false);
}
}
}

View file

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"wildbackport:mud"
]
}

View file

@ -11,6 +11,7 @@
"access.DoorBlockAccessor",
"access.FireBlockAccessor",
"access.MemoryModuleTypeAccessor",
"access.MobEffectAccessor",
"access.ModelPartAccessor",
"access.OverworldBiomesAccessor",
"access.PointedDripstoneBlockAccessor",
@ -32,6 +33,8 @@
"common.BlockEntityTypeMixin",
"common.FlyNodeEvaluatorMixin",
"common.LivingEntityMixin",
"common.MobEffectMixin",
"common.MobEffectMixin$MobEffectInstanceMixin",
"common.NoteBlockMixin",
"common.PathfinderMobMixin",
"common.PlayerMixin",
@ -40,9 +43,12 @@
"common.SculkSensorBlockMixin",
"extension.BoatTypeMixin",
"extension.PoseMixin",
"network.ClientboundUpdateMobEffectPacketMixin",
"network.ServerGamePacketListenerImplMixin"
],
"client": [
"client.FogRendererMixin",
"client.LightTextureMixin",
"client.LocalPlayerMixin",
"client.ModelPartMixin",
"client.PartDefinitionMixin",