mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Implement a custom data tracker to sync values dynamically. Fixes #14
This commit is contained in:
parent
c1bcaaa78e
commit
771da650c4
9 changed files with 47 additions and 112 deletions
|
@ -32,7 +32,9 @@ public interface SpellContainer {
|
|||
/**
|
||||
* Gets the active effect for this caster updating it if needed.
|
||||
*/
|
||||
<T extends Spell> Optional<T> get(@Nullable SpellPredicate<T> type);
|
||||
default <T extends Spell> Optional<T> get(@Nullable SpellPredicate<T> type) {
|
||||
return stream(type).findFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active effect.
|
||||
|
@ -73,10 +75,12 @@ public interface SpellContainer {
|
|||
/**
|
||||
* Gets all active effects for this caster updating it if needed.
|
||||
*/
|
||||
Stream<Spell> stream();
|
||||
default Stream<Spell> stream() {
|
||||
return stream(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all active effects for this caster that match the given type updating it if needed.
|
||||
* Gets all active effects for this caster that match the given type.
|
||||
*/
|
||||
<T extends Spell> Stream<T> stream(@Nullable SpellPredicate<T> type);
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@ import net.minecraft.entity.SpawnGroup;
|
|||
import net.minecraft.entity.ai.goal.*;
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.data.TrackedData;
|
||||
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||
import net.minecraft.entity.mob.*;
|
||||
import net.minecraft.entity.passive.*;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -41,7 +39,6 @@ import net.minecraft.nbt.NbtElement;
|
|||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutable<LivingEntity> {
|
||||
static final TrackedData<NbtCompound> EFFECT = net.minecraft.entity.data.DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
||||
public static void boostrap() {}
|
||||
|
||||
private final EntityPhysics<LivingEntity> physics;
|
||||
|
|
|
@ -19,8 +19,6 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable, Pro
|
|||
|
||||
void setSpecies(Race race);
|
||||
|
||||
void initDataTracker();
|
||||
|
||||
/**
|
||||
* Called at the beginning of an update cycle.
|
||||
*/
|
||||
|
|
|
@ -47,10 +47,6 @@ public class ItemImpl implements Equine<ItemEntity> {
|
|||
race = tracker.startTracking(TrackableDataType.of(Race.PACKET_CODEC), Race.HUMAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initDataTracker() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onProjectileImpact(ProjectileEntity projectile) {
|
||||
return false;
|
||||
|
|
|
@ -76,8 +76,6 @@ import net.minecraft.util.math.MathHelper;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public abstract class Living<T extends LivingEntity> implements Equine<T>, Caster<T>, Transmittable {
|
||||
//private static final TrackedData<Optional<UUID>> CARRIER_ID = DataTracker.registerData(LivingEntity.class, TrackedDataHandlerRegistry.OPTIONAL_UUID);
|
||||
|
||||
protected final T entity;
|
||||
|
||||
private final EffectSync effectDelegate;
|
||||
|
@ -113,7 +111,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
this.entity = entity;
|
||||
this.trackers = Trackable.of(entity).getDataTrackers();
|
||||
this.tracker = trackers.getPrimaryTracker();
|
||||
this.effectDelegate = new EffectSync(this, Creature.EFFECT);
|
||||
this.effectDelegate = new EffectSync(this, tracker);
|
||||
this.sneakingHeuristic = addTicker(new Interactable(entity::isSneaking));
|
||||
this.landedHeuristic = addTicker(new Interactable(entity::isOnGround));
|
||||
this.jumpingHeuristic = addTicker(new Interactable(((LivingEntityDuck)entity)::isJumping));
|
||||
|
@ -121,11 +119,6 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
|||
carrierId = tracker.startTracking(TrackableDataType.of(PacketCodec.UUID), Util.NIL_UUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initDataTracker() {
|
||||
entity.getDataTracker().startTracking(Creature.EFFECT, new NbtCompound());
|
||||
}
|
||||
|
||||
public <Q extends Tickable> Q addTicker(Q tickable) {
|
||||
tickers.add(Objects.requireNonNull(tickable, "tickable cannot be null"));
|
||||
return tickable;
|
||||
|
|
|
@ -19,19 +19,15 @@ 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<NbtCompound> EFFECT = DataTracker.registerData(CastSpellEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
||||
|
||||
private final EntityPhysics<CastSpellEntity> physics = new EntityPhysics<>(this, Trackable.of(this).getDataTrackers().getPrimaryTracker());
|
||||
|
||||
private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
|
||||
private final EffectSync effectDelegate = new EffectSync(this, Trackable.of(this).getDataTrackers().getPrimaryTracker());
|
||||
|
||||
private final EntityReference<LivingEntity> owner = new EntityReference<>();
|
||||
|
||||
|
@ -45,7 +41,6 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
|
|||
|
||||
@Override
|
||||
protected void initDataTracker() {
|
||||
getDataTracker().startTracking(EFFECT, new NbtCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,7 +30,6 @@ import net.minecraft.fluid.Fluid;
|
|||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
abstract class MixinEntity implements EntityDuck, Trackable {
|
||||
|
@ -80,14 +79,6 @@ abstract class MixinEntity implements EntityDuck, Trackable {
|
|||
return self.hasVehicle() && self.getVehicle() instanceof LavaAffine affine && affine.isLavaAffine();
|
||||
}
|
||||
|
||||
|
||||
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "net/minecraft/entity/Entity.initDataTracker()V"))
|
||||
private void onInstanceInit(EntityType<?> type, World world, CallbackInfo info) {
|
||||
if (this instanceof Equine.Container c) {
|
||||
c.get().initDataTracker();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "isFireImmune", at = @At("HEAD"), cancellable = true)
|
||||
private void onIsFireImmune(CallbackInfoReturnable<Boolean> info) {
|
||||
if (isLavaAffine() || (this instanceof Equine.Container c) && c.get().getCompositeRace().includes(Race.KIRIN)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.minelittlepony.unicopia.network.datasync;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -14,9 +14,11 @@ import com.minelittlepony.unicopia.ability.magic.SpellContainer;
|
|||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.network.track.DataTracker;
|
||||
import com.minelittlepony.unicopia.network.track.TrackableDataType;
|
||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
import com.minelittlepony.unicopia.util.serialization.PacketCodec;
|
||||
|
||||
import net.minecraft.entity.data.TrackedData;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
||||
/**
|
||||
|
@ -32,19 +34,21 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
|
||||
private final Caster<?> owner;
|
||||
|
||||
private final TrackedData<NbtCompound> param;
|
||||
private final DataTracker tracker;
|
||||
private final DataTracker.Entry<NbtCompound> param;
|
||||
|
||||
@Nullable
|
||||
private NbtCompound lastValue;
|
||||
|
||||
public EffectSync(Caster<?> owner, TrackedData<NbtCompound> param) {
|
||||
spells = new NetworkedReferenceSet<>(Spell::getUuid, () -> new SpellNetworkedReference<>(owner));
|
||||
public EffectSync(Caster<?> owner, DataTracker tracker) {
|
||||
this.owner = owner;
|
||||
this.param = param;
|
||||
}
|
||||
this.tracker = tracker;
|
||||
this.param = tracker.startTracking(TrackableDataType.of(PacketCodec.NBT), new NbtCompound());
|
||||
spells = new NetworkedReferenceSet<>(Spell::getUuid, () -> new SpellNetworkedReference<>(owner));
|
||||
|
||||
public void initDataTracker() {
|
||||
owner.asEntity().getDataTracker().startTracking(param, new NbtCompound());
|
||||
tracker.onBeforeSend(param, () -> {
|
||||
if (spells.isDirty()) {
|
||||
tracker.set(param, spells.toNbt());
|
||||
}
|
||||
});
|
||||
tracker.onReceive(param, nbt -> spells.fromNbt(nbt));
|
||||
}
|
||||
|
||||
public boolean tick(Situation situation) {
|
||||
|
@ -78,20 +82,9 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
return spells.containsReference(id) || spells.getReferences().anyMatch(s -> s.equalsOrContains(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(@Nullable SpellPredicate<?> type) {
|
||||
return read(type).findFirst().isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Spell> Optional<T> get(@Nullable SpellPredicate<T> type) {
|
||||
return read(type).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(@Nullable Spell effect) {
|
||||
spells.addReference(effect);
|
||||
write();
|
||||
if (owner instanceof UpdateCallback callback) {
|
||||
callback.onSpellSet(effect);
|
||||
}
|
||||
|
@ -99,12 +92,7 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
|
||||
@Override
|
||||
public void remove(UUID id) {
|
||||
Spell spell = spells.getReference(id);
|
||||
spell.setDead();
|
||||
spell.tickDying(owner);
|
||||
if (spell.isDead()) {
|
||||
spells.removeReference(id);
|
||||
}
|
||||
discard(spells.getReference(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -113,13 +101,19 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
if (!test.test(spell)) {
|
||||
return initial;
|
||||
}
|
||||
discard(spell);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void discard(Spell spell) {
|
||||
if (spell != null) {
|
||||
spell.setDead();
|
||||
spell.tickDying(owner);
|
||||
if (spell.isDead()) {
|
||||
spells.removeReference(spell);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,55 +129,28 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Spell> stream() {
|
||||
return stream(null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T extends Spell> Stream<T> stream(@Nullable SpellPredicate<T> type) {
|
||||
return read(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clear() {
|
||||
if (spells.clear()) {
|
||||
write();
|
||||
if (owner instanceof UpdateCallback) {
|
||||
((UpdateCallback)owner).onSpellSet(null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Spell> Stream<T> read(@Nullable SpellPredicate<T> type) {
|
||||
if (owner.isClient()) {
|
||||
spells.fromNbt(owner.asEntity().getDataTracker().get(param));
|
||||
}
|
||||
write();
|
||||
|
||||
if (type == null) {
|
||||
return (Stream<T>)spells.getReferences();
|
||||
}
|
||||
return (Stream<T>)spells.getReferences().flatMap(s -> s.findMatches(type));
|
||||
}
|
||||
|
||||
private boolean reduce(Alteration alteration) {
|
||||
boolean initial = false;
|
||||
for (Spell i : read(null).toList()) {
|
||||
initial = alteration.apply(initial, i);
|
||||
@Override
|
||||
public boolean clear() {
|
||||
if (spells.clear()) {
|
||||
if (owner instanceof UpdateCallback c) {
|
||||
c.onSpellSet(null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
write();
|
||||
return initial;
|
||||
}
|
||||
|
||||
private void write() {
|
||||
if (spells.isDirty() && !owner.isClient()) {
|
||||
owner.asEntity().getDataTracker().set(param, spells.toNbt());
|
||||
}
|
||||
private boolean reduce(BiFunction<Boolean, Spell, Boolean> alteration) {
|
||||
return stream().toList().stream().reduce(false, alteration, (a, b) -> b);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,14 +161,10 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
spells.fromNbt(compound.getCompound("spells"));
|
||||
owner.asEntity().getDataTracker().set(param, spells.toNbt());
|
||||
tracker.set(param, spells.toNbt());
|
||||
}
|
||||
|
||||
public interface UpdateCallback {
|
||||
void onSpellSet(@Nullable Spell spell);
|
||||
}
|
||||
|
||||
private interface Alteration {
|
||||
boolean apply(boolean initial, Spell spell);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,9 @@ import net.minecraft.util.math.Vec3d;
|
|||
import net.minecraft.world.World;
|
||||
|
||||
public class MagicBeamEntity extends MagicProjectileEntity implements Caster<MagicBeamEntity>, MagicImmune {
|
||||
private static final TrackedData<NbtCompound> EFFECT = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.NBT_COMPOUND);
|
||||
private static final TrackedData<Boolean> HYDROPHOBIC = DataTracker.registerData(MagicBeamEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||
|
||||
private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
|
||||
private final EffectSync effectDelegate = new EffectSync(this, Trackable.of(this).getDataTrackers().getPrimaryTracker());
|
||||
private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this, Trackable.of(this).getDataTrackers().getPrimaryTracker());
|
||||
|
||||
public MagicBeamEntity(EntityType<MagicBeamEntity> type, World world) {
|
||||
|
@ -55,7 +54,6 @@ public class MagicBeamEntity extends MagicProjectileEntity implements Caster<Mag
|
|||
protected void initDataTracker() {
|
||||
super.initDataTracker();
|
||||
getDataTracker().startTracking(HYDROPHOBIC, false);
|
||||
getDataTracker().startTracking(EFFECT, new NbtCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue