mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-07 22:16:44 +01:00
Improve network syncing of spells and fix some shield radius resets
This commit is contained in:
parent
5fb54aa2fd
commit
36e22f1ead
8 changed files with 101 additions and 87 deletions
|
@ -51,7 +51,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
/**
|
||||
* The spell being cast
|
||||
*/
|
||||
private Spell spell;
|
||||
private final SpellReference<Spell> spell = new SpellReference<>();
|
||||
|
||||
public float pitch;
|
||||
public float yaw;
|
||||
|
@ -70,7 +70,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
}
|
||||
|
||||
public PlaceableSpell setSpell(Spell spell) {
|
||||
this.spell = spell;
|
||||
this.spell.set(spell);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
|
||||
@Override
|
||||
public Collection<Spell> getDelegates() {
|
||||
return List.of(spell);
|
||||
return List.of(spell.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,8 +162,8 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld());
|
||||
Vec3d pos = getPosition().orElse(position.orElse(source.asEntity().getPos()));
|
||||
entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch());
|
||||
PlaceableSpell copy = spell.toPlaceable();
|
||||
if (spell instanceof PlacementDelegate delegate) {
|
||||
PlaceableSpell copy = spell.get().toPlaceable();
|
||||
if (spell.get() instanceof PlacementDelegate delegate) {
|
||||
delegate.onPlaced(source, copy, entity);
|
||||
}
|
||||
entity.getSpellSlot().put(copy);
|
||||
|
@ -272,13 +272,12 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
|
||||
@Override
|
||||
protected void loadDelegates(NbtCompound compound) {
|
||||
spell = Spell.SERIALIZER.read(compound.getCompound("spell"));
|
||||
spell.fromNBT(compound.getCompound("spell"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveDelegates(NbtCompound compound) {
|
||||
compound.put("spell", Spell.SERIALIZER.write(spell));
|
||||
|
||||
compound.put("spell", spell.toNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
|||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
/**
|
||||
* Interface for a magic spells
|
||||
|
@ -129,10 +130,11 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
static Spell readNbt(@Nullable NbtCompound compound) {
|
||||
static <T extends Spell> T readNbt(@Nullable NbtCompound compound) {
|
||||
try {
|
||||
if (compound != null && compound.contains("effect_id")) {
|
||||
Spell effect = SpellType.getKey(compound).withTraits().create();
|
||||
@SuppressWarnings("unchecked")
|
||||
T effect = (T)SpellType.getKey(compound).withTraits().create();
|
||||
|
||||
if (effect != null) {
|
||||
effect.fromNBT(compound);
|
||||
|
@ -147,6 +149,10 @@ public interface Spell extends NbtSerialisable, Affine {
|
|||
return null;
|
||||
}
|
||||
|
||||
static UUID getUuid(@Nullable NbtCompound compound) {
|
||||
return compound == null || !compound.containsUuid("uuid") ? Util.NIL_UUID : compound.getUuid("uuid");
|
||||
}
|
||||
|
||||
static NbtCompound writeNbt(Spell effect) {
|
||||
NbtCompound compound = effect.toNBT();
|
||||
effect.getType().toNbt(compound);
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
||||
public final class SpellReference<T extends Spell> implements NbtSerialisable {
|
||||
@Nullable
|
||||
private transient T spell;
|
||||
private int nbtHash;
|
||||
|
||||
@Nullable
|
||||
public T get() {
|
||||
return spell == null || spell.isDead() ? null : spell;
|
||||
}
|
||||
|
||||
public void set(T spell) {
|
||||
set(spell, null);
|
||||
}
|
||||
|
||||
public boolean hasDirtySpell() {
|
||||
return spell != null && spell.isDirty();
|
||||
}
|
||||
|
||||
public boolean set(T spell, @Nullable Caster<?> owner) {
|
||||
spell = spell == null || spell.isDead() ? null : spell;
|
||||
if (spell == this.spell) {
|
||||
return false;
|
||||
}
|
||||
T oldValue = this.spell;
|
||||
this.spell = spell;
|
||||
nbtHash = 0;
|
||||
if (owner != null && oldValue != null && (spell == null || !oldValue.getUuid().equals(spell.getUuid()))) {
|
||||
oldValue.destroy(owner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
if (spell != null && !spell.isDead()) {
|
||||
spell.toNBT(compound);
|
||||
spell.getType().toNbt(compound);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
final int hash = compound.hashCode();
|
||||
if (nbtHash == hash) {
|
||||
return;
|
||||
}
|
||||
nbtHash = hash;
|
||||
|
||||
if (spell == null || !Objects.equals(Spell.getUuid(compound), spell.getUuid())) {
|
||||
spell = Spell.readNbt(compound);
|
||||
} else {
|
||||
spell.fromNBT(compound);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,20 +17,20 @@ import net.minecraft.world.World;
|
|||
|
||||
public final class ThrowableSpell extends AbstractDelegatingSpell {
|
||||
|
||||
private Spell spell;
|
||||
private final SpellReference<Spell> spell = new SpellReference<>();
|
||||
|
||||
public ThrowableSpell(CustomisedSpellType<?> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public ThrowableSpell setSpell(Spell spell) {
|
||||
this.spell = spell;
|
||||
this.spell.set(spell);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Spell> getDelegates() {
|
||||
return List.of(spell);
|
||||
return List.of(spell.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,7 +63,7 @@ public final class ThrowableSpell extends AbstractDelegatingSpell {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
Spell s = spell.prepareForCast(caster, CastingMethod.STORED);
|
||||
Spell s = spell.get().prepareForCast(caster, CastingMethod.STORED);
|
||||
if (s == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public final class ThrowableSpell extends AbstractDelegatingSpell {
|
|||
MagicProjectileEntity projectile = UEntities.MAGIC_BEAM.create(world);
|
||||
projectile.setPosition(entity.getX(), entity.getEyeY() - 0.1F, entity.getZ());
|
||||
projectile.setOwner(entity);
|
||||
projectile.setItem(UItems.GEMSTONE.getDefaultStack(spell.getType()));
|
||||
projectile.setItem(UItems.GEMSTONE.getDefaultStack(spell.get().getType()));
|
||||
s.apply(projectile);
|
||||
projectile.setVelocity(entity, entity.getPitch(), entity.getYaw(), 0, 1.5F, divergance);
|
||||
projectile.setNoGravity(true);
|
||||
|
@ -83,12 +83,12 @@ public final class ThrowableSpell extends AbstractDelegatingSpell {
|
|||
|
||||
@Override
|
||||
protected void loadDelegates(NbtCompound compound) {
|
||||
spell = Spell.SERIALIZER.read(compound.getCompound("spell"));
|
||||
spell.fromNBT(compound.getCompound("spell"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveDelegates(NbtCompound compound) {
|
||||
compound.put("spell", Spell.SERIALIZER.write(spell));
|
||||
compound.put("spell", spell.toNBT());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -115,7 +115,7 @@ public abstract class AbstractSpell implements Spell {
|
|||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
dirty = false;
|
||||
if (compound.contains("uuid")) {
|
||||
if (compound.containsUuid("uuid")) {
|
||||
uuid = compound.getUuid("uuid");
|
||||
}
|
||||
dying = compound.getBoolean("dying");
|
||||
|
|
|
@ -78,6 +78,7 @@ public class ShieldSpell extends AbstractSpell {
|
|||
|
||||
@Override
|
||||
public boolean tick(Caster<?> source, Situation situation) {
|
||||
rangeMultiplier.update(source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 500L);
|
||||
radius.update((float)getDrawDropOffRange(source), 200L);
|
||||
|
||||
if (source.isClient()) {
|
||||
|
@ -104,6 +105,8 @@ public class ShieldSpell extends AbstractSpell {
|
|||
|
||||
@Override
|
||||
public void tickDying(Caster<?> caster) {
|
||||
rangeMultiplier.update(caster instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 10L);
|
||||
radius.update((float)getDrawDropOffRange(caster), 10L);
|
||||
prevTicksDying = ticksDying;
|
||||
if (ticksDying++ > 25) {
|
||||
super.tickDying(caster);
|
||||
|
@ -124,7 +127,7 @@ public class ShieldSpell extends AbstractSpell {
|
|||
|
||||
public float getRadius(float tickDelta) {
|
||||
float base = radius.getValue();
|
||||
float scale = 1 - MathHelper.clamp(MathHelper.lerp(tickDelta, (float)prevTicksDying, ticksDying), 0, 1);
|
||||
float scale = 1 - MathHelper.clamp(MathHelper.lerp(tickDelta, (float)prevTicksDying, ticksDying) / 25F, 0, 1);
|
||||
return base * scale;
|
||||
}
|
||||
|
||||
|
@ -132,8 +135,6 @@ public class ShieldSpell extends AbstractSpell {
|
|||
* Calculates the maximum radius of the shield. aka The area of effect.
|
||||
*/
|
||||
public double getDrawDropOffRange(Caster<?> source) {
|
||||
rangeMultiplier.update(source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 500L);
|
||||
|
||||
float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER);
|
||||
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier.getValue();
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public class ShieldSpellRenderer extends SpellRenderer<ShieldSpell> {
|
|||
|
||||
float thickness = 0.02F * MathHelper.sin(animationProgress / 30F);
|
||||
float alpha = 1 - Math.abs(MathHelper.sin(animationProgress / 20F)) * 0.2F;
|
||||
alpha *= MathHelper.clamp(radius - 1, 0, 1);
|
||||
|
||||
if (firstPerson) {
|
||||
matrices.translate(0, -1.75F, 0);
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
package com.minelittlepony.unicopia.network.datasync;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.SpellReference;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
|
||||
public class SpellNetworkedReference<T extends Spell> implements NetworkedReference<T> {
|
||||
private Optional<T> currentValue = Optional.empty();
|
||||
|
||||
@Nullable
|
||||
private NbtCompound lastValue;
|
||||
|
||||
private final SpellReference<T> currentValue = new SpellReference<>();
|
||||
private final Caster<?> owner;
|
||||
|
||||
private boolean dirty;
|
||||
|
||||
public SpellNetworkedReference(Caster<?> owner) {
|
||||
|
@ -26,81 +20,29 @@ public class SpellNetworkedReference<T extends Spell> implements NetworkedRefere
|
|||
|
||||
@Override
|
||||
public Optional<T> getReference() {
|
||||
return currentValue.filter(s -> !s.isDead());
|
||||
}
|
||||
|
||||
private boolean mustDelete(@Nullable NbtCompound comp) {
|
||||
return comp == null || !comp.contains("effect_id") || !comp.contains("uuid");
|
||||
}
|
||||
|
||||
private boolean mustReplace(NbtCompound comp) {
|
||||
return currentValue.isEmpty() || !currentValue.get().getUuid().equals(comp.getUuid("uuid"));
|
||||
}
|
||||
|
||||
private boolean mustUpdate(NbtCompound comp) {
|
||||
if (owner.isClient() && !Objects.equals(lastValue, comp)) {
|
||||
lastValue = comp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean mustSend() {
|
||||
return currentValue.filter(Spell::isDirty).isPresent();
|
||||
return Optional.ofNullable(currentValue.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateReference(@Nullable T newValue) {
|
||||
newValue = newValue == null || newValue.isDead() ? null : newValue;
|
||||
|
||||
@Nullable
|
||||
T oldValue = currentValue.orElse(null);
|
||||
if (oldValue != newValue) {
|
||||
dirty = true;
|
||||
currentValue = Optional.ofNullable(newValue);
|
||||
|
||||
if (oldValue != null && (newValue == null || !oldValue.getUuid().equals(newValue.getUuid()))) {
|
||||
oldValue.destroy(owner);
|
||||
}
|
||||
}
|
||||
dirty |= currentValue.set(newValue, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean fromNbt(NbtCompound comp) {
|
||||
dirty = false;
|
||||
|
||||
if (mustDelete(comp)) {
|
||||
updateReference(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mustReplace(comp)) {
|
||||
updateReference((T)Spell.readNbt(comp));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mustUpdate(comp)) {
|
||||
currentValue.ifPresent(s -> s.fromNBT(comp));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mustSend()) {
|
||||
updateReference(getReference().orElse(null));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
currentValue.fromNBT(comp);
|
||||
return isDirty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtCompound toNbt() {
|
||||
dirty = false;
|
||||
return getReference().map(Spell::writeNbt).orElseGet(NbtCompound::new);
|
||||
return currentValue.toNBT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return dirty || mustSend();
|
||||
return !owner.isClient() && (dirty || currentValue.hasDirtySpell());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue