mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Fixed faithful entities not remembering their owner after a save and reload. #136
This commit is contained in:
parent
47a2046188
commit
238ca4bff7
6 changed files with 133 additions and 63 deletions
|
@ -29,11 +29,8 @@ public class TargetSelecter {
|
|||
|
||||
public Stream<Entity> getEntities(Caster<?> source, double radius, BiPredicate<Caster<?>, Entity> filter) {
|
||||
targets.values().removeIf(Target::tick);
|
||||
|
||||
Predicate<Entity> ownerCheck = isOwnerOrFriend(spell, source);
|
||||
|
||||
return source.findAllEntitiesInRange(radius)
|
||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && !ownerCheck.test(entity) && !SpellPredicate.IS_SHIELD_LIKE.isOn(entity))
|
||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity) && !SpellPredicate.IS_SHIELD_LIKE.isOn(entity))
|
||||
.filter(entity -> !(entity instanceof SpellbookEntity))
|
||||
.filter(e -> filter.test(source, e))
|
||||
.map(i -> {
|
||||
|
@ -47,19 +44,26 @@ public class TargetSelecter {
|
|||
}
|
||||
|
||||
public static <T extends Entity> Predicate<T> notOwnerOrFriend(Affine spell, Caster<?> source) {
|
||||
return TargetSelecter.<T>isOwnerOrFriend(spell, source).negate();
|
||||
return target -> notOwnerOrFriend(spell, source, target);
|
||||
}
|
||||
|
||||
public static <T extends Entity> Predicate<T> isOwnerOrFriend(Affine spell, Caster<?> source) {
|
||||
return target -> isOwnerOrFriend(spell, source, target);
|
||||
}
|
||||
|
||||
public static <T extends Entity> boolean notOwnerOrFriend(Affine spell, Caster<?> source, Entity target) {
|
||||
return !isOwnerOrFriend(spell, source, target);
|
||||
}
|
||||
|
||||
public static <T extends Entity> boolean isOwnerOrFriend(Affine spell, Caster<?> source, Entity target) {
|
||||
Entity owner = source.getMaster();
|
||||
|
||||
if (!(spell.isFriendlyTogether(source) && EquinePredicates.PLAYER_UNICORN.test(owner))) {
|
||||
return e -> FriendshipBraceletItem.isComrade(source, e);
|
||||
return FriendshipBraceletItem.isComrade(source, target);
|
||||
}
|
||||
|
||||
return entity -> {
|
||||
return FriendshipBraceletItem.isComrade(source, entity) || (owner != null && (Pony.equal(entity, owner) || owner.isConnectedThroughVehicle(entity)));
|
||||
};
|
||||
return FriendshipBraceletItem.isComrade(source, target)
|
||||
|| (owner != null && (Pony.equal(target, owner) || owner.isConnectedThroughVehicle(target)));
|
||||
}
|
||||
|
||||
static final class Target {
|
||||
|
|
|
@ -6,52 +6,66 @@ import net.minecraft.client.render.VertexConsumer;
|
|||
import net.minecraft.client.render.VertexConsumers;
|
||||
|
||||
public class PassThroughVertexConsumer extends VertexConsumers.Union implements VertexConsumer {
|
||||
private final Applicate<ColorFix> colorFix;
|
||||
private final Applicate<FUvFix> textureFix;
|
||||
private final Applicate<IUvFix> overlayFix;
|
||||
private final Applicate<IUvFix> lightFix;
|
||||
private final float[] buffer = new float[8];
|
||||
|
||||
private final Applicate<ColorFix, ColorFix.VertexConsumer> colorFix;
|
||||
private final Applicate<FUvFix, FUvFix.VertexConsumer> textureFix;
|
||||
private final Applicate<IUvFix, IUvFix.VertexConsumer> overlayFix;
|
||||
|
||||
private PassThroughVertexConsumer(VertexConsumer parent, Parameters parameters) {
|
||||
super(new VertexConsumer[] {parent});
|
||||
colorFix = Applicate.of(parameters.colorFix, (self, r, g, b, a) -> super.color(r, g, b, a));
|
||||
textureFix = Applicate.of(parameters.textureFix, (self, u, v) -> super.texture(u, v));
|
||||
overlayFix = Applicate.of(parameters.overlayFix, (self, u, v) -> super.overlay(u, v));
|
||||
lightFix = Applicate.of(parameters.lightFix, (self, u, v) -> super.light(u, v));
|
||||
colorFix = Applicate.of(parameters.colorFix, ColorFix.NULL, super::color, (newR, newG, newB, newA) -> {
|
||||
buffer[0] = newR / 255F;
|
||||
buffer[1] = newG / 255F;
|
||||
buffer[2] = newB / 255F;
|
||||
buffer[3] = newA / 255F;
|
||||
});
|
||||
textureFix = Applicate.of(parameters.textureFix, FUvFix.NULL, super::texture, (u, v) -> {
|
||||
buffer[4] = u;
|
||||
buffer[5] = v;
|
||||
});
|
||||
overlayFix = Applicate.of(parameters.overlayFix, IUvFix.NULL, super::overlay, (u, v) -> {
|
||||
buffer[6] = u;
|
||||
buffer[7] = v;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer color(int r, int g, int b, int a) {
|
||||
colorFix.getFix().apply(this, r, g, b, a);
|
||||
colorFix.getFix().apply(colorFix.setter, r, g, b, a);
|
||||
colorFix.nested = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer texture(float u, float v) {
|
||||
textureFix.getFix().apply(this, u, v);
|
||||
textureFix.getFix().apply(textureFix.setter, u, v);
|
||||
textureFix.nested = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer overlay(int u, int v) {
|
||||
overlayFix.getFix().apply(this, u, v);
|
||||
overlayFix.getFix().apply(overlayFix.setter, u, v);
|
||||
overlayFix.nested = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer light(int u, int v) {
|
||||
lightFix.getFix().apply(this, u, v);
|
||||
lightFix.nested = false;
|
||||
return this;
|
||||
public void vertex(float x, float y, float z, float red, float green, float blue, float alpha, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) {
|
||||
colorFix.getFix().apply(colorFix.collector, (int)(red * 255), (int)(green * 255F), (int)(blue * 255), (int)(alpha * 255));
|
||||
colorFix.nested = false;
|
||||
textureFix.getFix().apply(textureFix.collector, u, v);
|
||||
textureFix.nested = false;
|
||||
overlayFix.getFix().apply(overlayFix.collector, overlay & 0xFFFF, overlay >> 16 & 0xFFFF);
|
||||
overlayFix.nested = false;
|
||||
super.vertex(x, y, z, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], (int)buffer[6] | (int)buffer[7] << 16, light, normalX, normalY, normalZ);
|
||||
}
|
||||
|
||||
public static class Parameters {
|
||||
private @Nullable ColorFix colorFix;
|
||||
private @Nullable FUvFix textureFix;
|
||||
private @Nullable IUvFix overlayFix;
|
||||
private @Nullable IUvFix lightFix;
|
||||
|
||||
public Parameters color(ColorFix fix) {
|
||||
colorFix = fix;
|
||||
|
@ -68,25 +82,24 @@ public class PassThroughVertexConsumer extends VertexConsumers.Union implements
|
|||
return this;
|
||||
}
|
||||
|
||||
public Parameters light(IUvFix fix) {
|
||||
lightFix = fix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VertexConsumer build(VertexConsumer parent) {
|
||||
return new PassThroughVertexConsumer(parent, this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Applicate<T> {
|
||||
private static class Applicate<T extends Applicate.Applicatable<V>, V> {
|
||||
public final T fix;
|
||||
public final T fallback;
|
||||
public final V setter;
|
||||
public final V collector;
|
||||
|
||||
public boolean nested;
|
||||
|
||||
public Applicate(T fix, T fallback) {
|
||||
public Applicate(T fix, T fallback, V setter, V collector) {
|
||||
this.fix = fix;
|
||||
this.fallback = fallback;
|
||||
this.setter = setter;
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
public T getFix() {
|
||||
|
@ -97,21 +110,48 @@ public class PassThroughVertexConsumer extends VertexConsumers.Union implements
|
|||
}
|
||||
}
|
||||
|
||||
static <T> Applicate<T> of(@Nullable T fix, T fallback) {
|
||||
return new Applicate<>(fix == null ? fallback : fix, fallback);
|
||||
static <T extends Applicate.Applicatable<V>, V> Applicate<T, V> of(@Nullable T fix, T fallback, V setter, V collector) {
|
||||
return new Applicate<>(fix == null ? fallback : fix, fallback, setter, collector);
|
||||
}
|
||||
|
||||
interface Applicatable<T> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface PosFix {
|
||||
public interface PosFix extends Applicate.Applicatable<PosFix.VertexConsumer> {
|
||||
void apply(VertexConsumer consumer, float x, float y, float z);
|
||||
|
||||
public interface VertexConsumer {
|
||||
void vertex(float x, float y, float z);
|
||||
}
|
||||
}
|
||||
public interface ColorFix {
|
||||
public interface ColorFix extends Applicate.Applicatable<ColorFix.VertexConsumer> {
|
||||
ColorFix NULL = (self, r, g, b, a) -> self.color(r, g, b, a);
|
||||
void apply(VertexConsumer consumer, int r, int g, int b, int a);
|
||||
|
||||
public interface VertexConsumer {
|
||||
void color(int r, int g, int b, int a);
|
||||
|
||||
default void color(float r, float g, float b, float a) {
|
||||
color((int)(r * 255), (int)(g * 255), (int)(b * 255), (int)(a * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
public interface FUvFix {
|
||||
public interface FUvFix extends Applicate.Applicatable<FUvFix.VertexConsumer> {
|
||||
FUvFix NULL = (self, u, v) -> self.uv(u, v);
|
||||
void apply(VertexConsumer consumer, float u, float v);
|
||||
|
||||
public interface VertexConsumer {
|
||||
void uv(float u, float v);
|
||||
}
|
||||
}
|
||||
public interface IUvFix {
|
||||
public interface IUvFix extends Applicate.Applicatable<IUvFix.VertexConsumer> {
|
||||
IUvFix NULL = (self, u, v) -> self.uv(u, v);
|
||||
void apply(VertexConsumer consumer, int u, int v);
|
||||
|
||||
public interface VertexConsumer {
|
||||
void uv(int u, int v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,10 +74,14 @@ public class WorldRenderDelegate {
|
|||
float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
|
||||
|
||||
if (!recurseMinion && pony instanceof Creature creature && creature.isMinion()) {
|
||||
recurseMinion = true;
|
||||
dispatcher.render(creature.asEntity(), x, y, z, yaw, tickDelta, matrices, layer -> MINION_OVERLAY.build(vertices.getBuffer(layer)), light);
|
||||
recurseMinion = false;
|
||||
|
||||
try {
|
||||
recurseMinion = true;
|
||||
dispatcher.render(creature.asEntity(), x, y, z, yaw, tickDelta, matrices, layer -> {
|
||||
return MINION_OVERLAY.build(vertices.getBuffer(layer));
|
||||
}, light);
|
||||
} finally {
|
||||
recurseMinion = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,13 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
|
||||
private boolean discordedChanged = true;
|
||||
|
||||
private final Predicate<LivingEntity> targetPredicate = TargetSelecter.<LivingEntity>notOwnerOrFriend(this, this).and(e -> {
|
||||
return Equine.of(e)
|
||||
.filter(eq -> eq instanceof Creature)
|
||||
.filter(eq -> ((Creature)eq).hasCommonOwner(this))
|
||||
.isEmpty();
|
||||
});
|
||||
|
||||
public Creature(LivingEntity entity) {
|
||||
super(entity, EFFECT);
|
||||
physics = new EntityPhysics<>(entity, GRAVITY);
|
||||
|
@ -77,7 +84,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
}
|
||||
|
||||
public boolean isMinion() {
|
||||
return owner.getId().isPresent();
|
||||
return getMasterReference().isSet();
|
||||
}
|
||||
|
||||
public boolean isDiscorded() {
|
||||
|
@ -92,13 +99,15 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
@Override
|
||||
@NotNull
|
||||
public LivingEntity getMaster() {
|
||||
NbtCompound data = entity.getDataTracker().get(MASTER);
|
||||
owner.fromNBT(data);
|
||||
return owner.getOrEmpty(asWorld()).orElse(entity);
|
||||
return getMasterReference().getOrEmpty(asWorld()).orElse(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityReference<LivingEntity> getMasterReference() {
|
||||
if (entity.getDataTracker().containsKey(MASTER)) {
|
||||
NbtCompound data = entity.getDataTracker().get(MASTER);
|
||||
owner.fromNBT(data);
|
||||
}
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
@ -127,7 +136,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
goals.add(3, eatMuffinGoal);
|
||||
}
|
||||
|
||||
if (owner.isPresent(asWorld())) {
|
||||
if (getMasterReference().isSet()) {
|
||||
initMinionAi(targets);
|
||||
}
|
||||
|
||||
|
@ -143,18 +152,13 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
}
|
||||
}
|
||||
|
||||
private void initMinionAi(GoalSelector targets) {
|
||||
Predicate<LivingEntity> filter = TargetSelecter.<LivingEntity>notOwnerOrFriend(this, this).and(e -> {
|
||||
return Equine.of(e)
|
||||
.filter(eq -> eq instanceof Creature)
|
||||
.filter(eq -> ((Creature)eq).hasCommonOwner(this))
|
||||
.isEmpty();
|
||||
});
|
||||
|
||||
|
||||
private void initMinionAi(GoalSelector targets) {
|
||||
clearGoals(targets);
|
||||
targets.add(2, new ActiveTargetGoal<>((MobEntity)entity, PlayerEntity.class, true, filter));
|
||||
targets.add(2, new ActiveTargetGoal<>((MobEntity)entity, HostileEntity.class, true, filter));
|
||||
targets.add(2, new ActiveTargetGoal<>((MobEntity)entity, SlimeEntity.class, true, filter));
|
||||
targets.add(2, new ActiveEnemyGoal<>(PlayerEntity.class));
|
||||
targets.add(2, new ActiveEnemyGoal<>(HostileEntity.class));
|
||||
targets.add(2, new ActiveEnemyGoal<>(SlimeEntity.class));
|
||||
}
|
||||
|
||||
private void initDiscordedAi() {
|
||||
|
@ -189,6 +193,9 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
discordedChanged = false;
|
||||
initDiscordedAi();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -273,7 +280,7 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
getSpellSlot().get(true).ifPresent(effect -> {
|
||||
compound.put("effect", Spell.writeNbt(effect));
|
||||
});
|
||||
compound.put("master", owner.toNBT());
|
||||
compound.put("master", getMasterReference().toNBT());
|
||||
physics.toNBT(compound);
|
||||
compound.putBoolean("discorded", isDiscorded());
|
||||
}
|
||||
|
@ -286,11 +293,26 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
|||
}
|
||||
if (compound.contains("master", NbtElement.COMPOUND_TYPE)) {
|
||||
owner.fromNBT(compound.getCompound("master"));
|
||||
if (owner.isPresent(asWorld())) {
|
||||
if (entity.getDataTracker().containsKey(MASTER)) {
|
||||
entity.getDataTracker().set(MASTER, owner.toNBT());
|
||||
}
|
||||
if (owner.isSet()) {
|
||||
targets.ifPresent(this::initMinionAi);
|
||||
}
|
||||
}
|
||||
physics.fromNBT(compound);
|
||||
setDiscorded(compound.getBoolean("discorded"));
|
||||
}
|
||||
|
||||
private class ActiveEnemyGoal<T extends LivingEntity> extends ActiveTargetGoal<T> {
|
||||
public ActiveEnemyGoal(Class<T> targetClass) {
|
||||
super((MobEntity)entity, targetClass, true, Creature.this.targetPredicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldContinue() {
|
||||
LivingEntity target = this.mob.getTarget();
|
||||
return target != null && targetPredicate.test(mob, target) && super.shouldContinue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ public class EntityReference<T extends Entity> implements NbtSerialisable {
|
|||
return pos;
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return getId().isPresent();
|
||||
}
|
||||
|
||||
public boolean referenceEquals(Entity entity) {
|
||||
return entity != null && entity.getUuid().equals(uuid.orElse(null));
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.minelittlepony.unicopia.entity;
|
|||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageSources;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgSpawnProjectile;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
|
@ -14,8 +12,6 @@ import net.minecraft.entity.data.TrackedData;
|
|||
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
|
Loading…
Reference in a new issue