Fixed placed and projectile spells not syncing their level correctly. Also fixes placed shields not rendering

This commit is contained in:
Sollace 2024-05-22 13:58:20 +01:00
parent ca361049f5
commit e23cbcdd1c
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
6 changed files with 94 additions and 25 deletions

View file

@ -1,33 +1,32 @@
package com.minelittlepony.unicopia.ability.magic;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.MathHelper;
/**
* Object with levelling capabilities.
*/
public interface Levelled {
LevelStore EMPTY = fixed(0);
LevelStore ZERO = of(0, 1);
static LevelStore fixed(int level) {
return of(() -> level);
}
static LevelStore of(IntSupplier supplier) {
static LevelStore of(IntSupplier getter, IntConsumer setter, IntSupplier max) {
return new LevelStore() {
@Override
public int get() {
return supplier.getAsInt();
return getter.getAsInt();
}
@Override
public void set(int level) {
setter.accept(level);
}
@Override
public int getMax() {
return get();
return max.getAsInt();
}
};
}
@ -37,7 +36,9 @@ public interface Levelled {
}
static LevelStore fromNbt(NbtCompound compound) {
return of(compound.getInt("value"), compound.getInt("max"));
int max = Math.max(1, compound.getInt("max"));
int value = MathHelper.clamp(compound.getInt("value"), 0, max);
return of(value, max);
}
static LevelStore of(int level, int max) {
@ -70,6 +71,9 @@ public interface Levelled {
void set(int level);
default float getScaled(float max) {
if (getMax() == 0) {
return max;
}
return ((float)get() / getMax()) * max;
}

View file

@ -279,12 +279,12 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
@Override
public LevelStore getLevel() {
return Levelled.EMPTY;
return Levelled.ZERO;
}
@Override
public LevelStore getCorruption() {
return Levelled.EMPTY;
return Levelled.ZERO;
}
@Override

View file

@ -134,8 +134,8 @@ public class EntityReference<T extends Entity> implements NbtSerialisable {
entity.getPos(),
entity.getId(), entity instanceof PlayerEntity,
!entity.isAlive(),
Caster.of(entity).map(Caster::getLevel).map(Levelled::copyOf).orElse(Levelled.EMPTY),
Caster.of(entity).map(Caster::getCorruption).map(Levelled::copyOf).orElse(Levelled.EMPTY)
Caster.of(entity).map(Caster::getLevel).map(Levelled::copyOf).orElse(Levelled.ZERO),
Caster.of(entity).map(Caster::getCorruption).map(Levelled::copyOf).orElse(Levelled.ZERO)
);
}

View file

@ -17,11 +17,18 @@ import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityType;
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.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.minecraft.world.World;
public class CastSpellEntity extends LightEmittingEntity implements Caster<CastSpellEntity>, WeaklyOwned.Mutable<LivingEntity>, MagicImmune {
private static final TrackedData<Integer> LEVEL = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> MAX_LEVEL = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> CORRUPTION = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> MAX_CORRUPTION = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.INTEGER);
private final EntityPhysics<CastSpellEntity> physics = new EntityPhysics<>(this);
@ -29,8 +36,16 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
private final EntityReference<LivingEntity> owner = new EntityReference<>();
private LevelStore level = Levelled.EMPTY;
private LevelStore corruption = Levelled.EMPTY;
private final LevelStore level = Levelled.of(
() -> dataTracker.get(LEVEL),
l -> dataTracker.set(LEVEL, l),
() -> dataTracker.get(MAX_LEVEL)
);
private final LevelStore corruption = Levelled.of(
() -> dataTracker.get(CORRUPTION),
l -> dataTracker.set(CORRUPTION, l),
() -> dataTracker.get(MAX_CORRUPTION)
);
public CastSpellEntity(EntityType<?> type, World world) {
super(type, world);
@ -39,6 +54,10 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
@Override
protected void initDataTracker() {
dataTracker.startTracking(LEVEL, 0);
dataTracker.startTracking(CORRUPTION, 0);
dataTracker.startTracking(MAX_LEVEL, 1);
dataTracker.startTracking(MAX_CORRUPTION, 1);
}
@Override
@ -84,8 +103,10 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
}
public void setCaster(Caster<?> caster) {
this.level = Levelled.copyOf(caster.getLevel());
this.corruption = Levelled.copyOf(caster.getCorruption());
dataTracker.set(LEVEL, caster.getLevel().get());
dataTracker.set(MAX_LEVEL, caster.getLevel().getMax());
dataTracker.set(CORRUPTION, caster.getCorruption().get());
dataTracker.set(MAX_CORRUPTION, caster.getCorruption().getMax());
setMaster(caster);
}
@ -144,7 +165,11 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
owner.fromNBT(tag.getCompound("owner"));
}
spells.getSlots().fromNBT(tag);
level = Levelled.fromNbt(tag.getCompound("level"));
corruption = Levelled.fromNbt(tag.getCompound("corruption"));
var level = Levelled.fromNbt(tag.getCompound("level"));
dataTracker.set(MAX_LEVEL, level.getMax());
dataTracker.set(LEVEL, level.get());
var corruption = Levelled.fromNbt(tag.getCompound("corruption"));
dataTracker.set(MAX_CORRUPTION, corruption.getMax());
dataTracker.set(CORRUPTION, corruption.get());
}
}

View file

@ -4,6 +4,8 @@ import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.InteractionManager;
import com.minelittlepony.unicopia.ability.magic.Affine;
@ -31,10 +33,25 @@ import net.minecraft.world.World;
public class MagicBeamEntity extends MagicProjectileEntity implements Caster<MagicBeamEntity>, MagicImmune {
private static final TrackedData<Boolean> HYDROPHOBIC = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
private static final TrackedData<Integer> LEVEL = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> MAX_LEVEL = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> CORRUPTION = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.INTEGER);
private static final TrackedData<Integer> MAX_CORRUPTION = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.INTEGER);
private final SpellInventory spells = SpellSlots.ofSingle(this);
private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this);
private final LevelStore level = Levelled.of(
() -> dataTracker.get(LEVEL),
l -> dataTracker.set(LEVEL, l),
() -> dataTracker.get(MAX_LEVEL)
);
private final LevelStore corruption = Levelled.of(
() -> dataTracker.get(CORRUPTION),
l -> dataTracker.set(CORRUPTION, l),
() -> dataTracker.get(MAX_CORRUPTION)
);
public MagicBeamEntity(EntityType<MagicBeamEntity> type, World world) {
super(type, world);
}
@ -51,7 +68,11 @@ public class MagicBeamEntity extends MagicProjectileEntity implements Caster<Mag
@Override
protected void initDataTracker() {
super.initDataTracker();
getDataTracker().startTracking(HYDROPHOBIC, false);
dataTracker.startTracking(HYDROPHOBIC, false);
dataTracker.startTracking(LEVEL, 0);
dataTracker.startTracking(CORRUPTION, 0);
dataTracker.startTracking(MAX_LEVEL, 1);
dataTracker.startTracking(MAX_CORRUPTION, 1);
}
@Override
@ -92,14 +113,25 @@ public class MagicBeamEntity extends MagicProjectileEntity implements Caster<Mag
return this;
}
@Override
public void setOwner(@Nullable Entity entity) {
super.setOwner(entity);
Caster.of(entity).ifPresent(caster -> {
dataTracker.set(LEVEL, caster.getLevel().get());
dataTracker.set(MAX_LEVEL, caster.getLevel().getMax());
dataTracker.set(CORRUPTION, caster.getCorruption().get());
dataTracker.set(MAX_CORRUPTION, caster.getCorruption().getMax());
});
}
@Override
public LevelStore getLevel() {
return getMasterReference().getTarget().map(target -> target.level()).orElse(Levelled.EMPTY);
return level;
}
@Override
public LevelStore getCorruption() {
return getMasterReference().getTarget().map(target -> target.corruption()).orElse(Levelled.EMPTY);
return corruption;
}
@Override
@ -149,11 +181,19 @@ public class MagicBeamEntity extends MagicProjectileEntity implements Caster<Mag
getDataTracker().set(HYDROPHOBIC, compound.getBoolean("hydrophobic"));
physics.fromNBT(compound);
spells.getSlots().fromNBT(compound);
var level = Levelled.fromNbt(compound.getCompound("level"));
dataTracker.set(MAX_LEVEL, level.getMax());
dataTracker.set(LEVEL, level.get());
var corruption = Levelled.fromNbt(compound.getCompound("corruption"));
dataTracker.set(MAX_CORRUPTION, corruption.getMax());
dataTracker.set(CORRUPTION, corruption.get());
}
@Override
public void writeCustomDataToNbt(NbtCompound compound) {
super.writeCustomDataToNbt(compound);
compound.put("level", level.toNbt());
compound.put("corruption", corruption.toNbt());
compound.putBoolean("hydrophobic", getHydrophobic());
physics.toNBT(compound);
spells.getSlots().toNBT(compound);

View file

@ -78,7 +78,7 @@ public class MagicProjectileEntity extends ThrownItemEntity implements WeaklyOwn
}
@Override
public void setMaster(LivingEntity owner) {
public final void setMaster(LivingEntity owner) {
setOwner(owner);
}
@ -86,13 +86,13 @@ public class MagicProjectileEntity extends ThrownItemEntity implements WeaklyOwn
public void setOwner(@Nullable Entity entity) {
super.setOwner(entity);
if (entity instanceof LivingEntity l) {
getMasterReference().set(l);
WeaklyOwned.Mutable.super.setMaster(l);
}
}
@Override
@Nullable
public Entity getOwner() {
public final Entity getOwner() {
return getMaster();
}