track active effects on other players via synced effect particles
Accessor mixins expose LivingEntity's DATA_EFFECT_PARTICLES and ColorParticleOption's color; DamageSyncTracker maps the synced colors to resistance/slowness/strength (turtle master = resistance + slowness) for the nametag effect icons.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package cc.fros.mixin.entity;
|
||||
|
||||
import net.minecraft.core.particles.ColorParticleOption;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(ColorParticleOption.class)
|
||||
public interface ColorParticleOptionAccessor {
|
||||
|
||||
@Accessor("color")
|
||||
int fros$getColor();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cc.fros.mixin.entity;
|
||||
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
public interface LivingEntityEffectParticlesAccessor {
|
||||
|
||||
@Accessor("DATA_EFFECT_PARTICLES")
|
||||
static EntityDataAccessor<List<ParticleOptions>> fros$getDataEffectParticles() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package cc.fros.util;
|
||||
|
||||
import cc.fros.mixin.entity.ColorParticleOptionAccessor;
|
||||
import cc.fros.mixin.entity.LivingEntityEffectParticlesAccessor;
|
||||
import net.minecraft.core.particles.ColorParticleOption;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Detects active effects on other players from the effect particle data the
|
||||
* server syncs with them, ported from homovore's {@code DamageSyncTracker}.
|
||||
*/
|
||||
public final class DamageSyncTracker {
|
||||
|
||||
private DamageSyncTracker() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private static final int RESISTANCE_COLOR = MobEffects.RESISTANCE.value().getColor() & 0xFFFFFF;
|
||||
private static final int SLOWNESS_COLOR = MobEffects.SLOWNESS.value().getColor() & 0xFFFFFF;
|
||||
private static final int STRENGTH_COLOR = MobEffects.STRENGTH.value().getColor() & 0xFFFFFF;
|
||||
|
||||
private static boolean hasEffectColor(LivingEntity entity, int rgb) {
|
||||
List<ParticleOptions> particles = entity.getEntityData()
|
||||
.get(LivingEntityEffectParticlesAccessor.fros$getDataEffectParticles());
|
||||
if (particles.isEmpty()) return false;
|
||||
for (int i = 0, n = particles.size(); i < n; i++) {
|
||||
if (particles.get(i) instanceof ColorParticleOption color
|
||||
&& (((ColorParticleOptionAccessor) (Object) color).fros$getColor() & 0xFFFFFF) == rgb) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasResistance(LivingEntity entity) {
|
||||
return hasEffectColor(entity, RESISTANCE_COLOR);
|
||||
}
|
||||
|
||||
public static boolean hasSlowness(LivingEntity entity) {
|
||||
return hasEffectColor(entity, SLOWNESS_COLOR);
|
||||
}
|
||||
|
||||
public static boolean hasStrength(LivingEntity entity) {
|
||||
return hasEffectColor(entity, STRENGTH_COLOR);
|
||||
}
|
||||
|
||||
public static boolean isTurtleMaster(LivingEntity entity) {
|
||||
return hasResistance(entity) && hasSlowness(entity);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
"network.MixinConnection"
|
||||
],
|
||||
"client": [
|
||||
"entity.ColorParticleOptionAccessor",
|
||||
"entity.LivingEntityEffectParticlesAccessor",
|
||||
"entity.MixinAbstractClientPlayer",
|
||||
"entity.MixinClientPlayerEntity",
|
||||
"input.MixinKeyboardHandler",
|
||||
|
||||
Reference in New Issue
Block a user