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