package com.thebrokenrail.gulliverreloaded.mixin; import com.thebrokenrail.gulliverreloaded.GulliverReloaded; import com.thebrokenrail.gulliverreloaded.ScaledEntity; import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.EntityPose; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.data.TrackedDataHandlerRegistry; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; 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.Map; @SuppressWarnings("unused") @Mixin(LivingEntity.class) public abstract class MixinLivingEntity implements ScaledEntity { private static final TrackedData SCALE = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.FLOAT); @Shadow public abstract Map getActiveStatusEffects(); @Override public float getScale() { return ((LivingEntity) (Object) this).getDataTracker().get(SCALE); } private float computeScale() { Map effects = getActiveStatusEffects(); if (effects != null && effects.size() > 0) { int shrink = effects.get(GulliverReloaded.SHRINK_EFFECT.getStatusEffect()) != null ? effects.get(GulliverReloaded.SHRINK_EFFECT.getStatusEffect()).getAmplifier() + 1 : 0; int grow = effects.get(GulliverReloaded.GROW_EFFECT.getStatusEffect()) != null ? effects.get(GulliverReloaded.GROW_EFFECT.getStatusEffect()).getAmplifier() + 1 : 0; float value = grow - shrink; if (value > 0) { return (float) Math.pow(2f, value); } else { return (float) Math.pow(0.5f, Math.abs(value)); } } else { return 1f; } } @Inject(at = @At("RETURN"), method = "getDimensions", cancellable = true) public void getDimensions(EntityPose pose, CallbackInfoReturnable info) { info.setReturnValue(scaleDimensions(info.getReturnValue())); } @Override public EntityDimensions scaleDimensions(EntityDimensions dimensions) { float scale = getScale(); return new EntityDimensions(Math.max(dimensions.width * scale, 0.5f), Math.max(dimensions.height * scale, 0.5f), dimensions.fixed); } @Inject(at = @At("RETURN"), method = "getJumpVelocity", cancellable = true) public void getJumpVelocity(CallbackInfoReturnable info) { info.setReturnValue(info.getReturnValue() * (float) Math.pow(getScale(), 0.2f)); } @Inject(at = @At("RETURN"), method = "getMovementSpeed()F", cancellable = true) public void getMovementSpeed(CallbackInfoReturnable info) { info.setReturnValue(info.getReturnValue() * (float) Math.pow(getScale(), 0.2f)); } @Inject(at = @At("RETURN"), method = "getEyeHeight", cancellable = true) public void getEyeHeight(EntityPose pose, EntityDimensions dimensions, CallbackInfoReturnable info) { if (pose != EntityPose.SLEEPING) { info.setReturnValue(info.getReturnValue() * getScale()); } } @Inject(at = @At("HEAD"), method = "tick") public void tick(CallbackInfo info) { if (!((LivingEntity) (Object) this).getEntityWorld().isClient()) { ((LivingEntity) (Object) this).getDataTracker().set(SCALE, computeScale()); } } @Inject(at = @At("RETURN"), method = "initDataTracker") public void initDataTracker(CallbackInfo info) { ((LivingEntity) (Object) this).getDataTracker().startTracking(SCALE, 1f); } @Inject(at = @At("RETURN"), method = "onTrackedDataSet") public void onTrackedDataSet(TrackedData data, CallbackInfo info) { if (SCALE.equals(data)) { ((LivingEntity) (Object) this).calculateDimensions(); } } }