2021-03-04 22:30:43 +01:00
|
|
|
package com.minelittlepony.unicopia.entity;
|
|
|
|
|
2021-03-05 19:52:49 +01:00
|
|
|
import java.util.Optional;
|
2021-03-04 22:30:43 +01:00
|
|
|
import java.util.UUID;
|
2021-03-06 13:53:40 +01:00
|
|
|
import java.util.function.Consumer;
|
2021-03-04 22:30:43 +01:00
|
|
|
|
2021-08-04 15:38:03 +02:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
2021-03-04 22:30:43 +01:00
|
|
|
|
|
|
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
|
|
|
|
|
|
|
import net.minecraft.entity.Entity;
|
2022-01-01 23:43:21 +01:00
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
2021-08-04 15:38:03 +02:00
|
|
|
import net.minecraft.nbt.NbtCompound;
|
2021-12-27 13:05:31 +01:00
|
|
|
import net.minecraft.nbt.NbtElement;
|
2021-03-04 22:30:43 +01:00
|
|
|
import net.minecraft.server.world.ServerWorld;
|
2021-03-05 19:52:49 +01:00
|
|
|
import net.minecraft.util.math.Vec3d;
|
2021-03-04 22:30:43 +01:00
|
|
|
import net.minecraft.world.World;
|
|
|
|
|
2022-09-17 22:11:24 +02:00
|
|
|
/**
|
|
|
|
* An indirect reference to an entity by its unique id.
|
|
|
|
* Used to store the 'owner' reference for certain objects that allows them to\
|
|
|
|
* remember who they belong to even when the entity has been unloaded.
|
|
|
|
*
|
|
|
|
* @param <T> The type of the entity this reference points to.
|
|
|
|
*/
|
2021-03-04 22:30:43 +01:00
|
|
|
public class EntityReference<T extends Entity> implements NbtSerialisable {
|
|
|
|
|
2022-09-17 22:11:24 +02:00
|
|
|
/**
|
|
|
|
* Server UUID of the entity used to look up the entity instance on the server.
|
|
|
|
*/
|
2022-01-01 21:08:50 +01:00
|
|
|
private Optional<UUID> uuid = Optional.empty();
|
2022-09-17 22:11:24 +02:00
|
|
|
/**
|
|
|
|
* Corresponding client id used to look up the entity instance on the client.
|
|
|
|
*/
|
2021-03-04 22:30:43 +01:00
|
|
|
private int clientId;
|
2022-09-17 22:11:24 +02:00
|
|
|
/**
|
|
|
|
* The last-known position of the entity.
|
|
|
|
*/
|
2021-03-05 19:52:49 +01:00
|
|
|
private Optional<Vec3d> pos = Optional.empty();
|
|
|
|
|
2021-12-29 23:59:17 +01:00
|
|
|
public EntityReference() {}
|
|
|
|
|
|
|
|
public EntityReference(T entity) {
|
|
|
|
set(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
public EntityReference(NbtCompound nbt) {
|
|
|
|
fromNBT(nbt);
|
|
|
|
}
|
|
|
|
|
2022-09-17 19:13:39 +02:00
|
|
|
public void copyFrom(EntityReference<? extends T> other) {
|
2022-01-01 21:08:50 +01:00
|
|
|
uuid = other.uuid;
|
|
|
|
clientId = other.clientId;
|
|
|
|
pos = other.pos;
|
|
|
|
}
|
|
|
|
|
2021-03-04 22:30:43 +01:00
|
|
|
public void set(@Nullable T entity) {
|
|
|
|
if (entity != null) {
|
2022-01-01 21:08:50 +01:00
|
|
|
uuid = Optional.of(entity.getUuid());
|
2021-08-04 15:38:03 +02:00
|
|
|
clientId = entity.getId();
|
2021-03-05 19:52:49 +01:00
|
|
|
pos = Optional.of(entity.getPos());
|
2021-12-27 22:14:46 +01:00
|
|
|
} else {
|
2022-01-01 21:08:50 +01:00
|
|
|
uuid = Optional.empty();
|
2021-12-27 22:14:46 +01:00
|
|
|
clientId = 0;
|
|
|
|
pos = Optional.empty();
|
2021-03-04 22:30:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-14 16:48:34 +02:00
|
|
|
/**
|
|
|
|
* Gets the assigned entity's UUID
|
|
|
|
*/
|
2022-01-01 21:08:50 +01:00
|
|
|
public Optional<UUID> getId() {
|
|
|
|
return uuid;
|
|
|
|
}
|
|
|
|
|
2021-12-27 13:05:31 +01:00
|
|
|
/**
|
2022-09-14 16:48:34 +02:00
|
|
|
* Gets the last known position of the assigned entity.
|
2021-12-27 13:05:31 +01:00
|
|
|
*/
|
2021-03-05 19:52:49 +01:00
|
|
|
public Optional<Vec3d> getPosition() {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2022-02-23 19:03:14 +01:00
|
|
|
public boolean referenceEquals(Entity entity) {
|
|
|
|
return entity != null && entity.getUuid().equals(uuid.orElse(null));
|
|
|
|
}
|
|
|
|
|
2021-03-04 22:30:43 +01:00
|
|
|
public boolean isPresent(World world) {
|
2021-12-27 13:05:31 +01:00
|
|
|
return getOrEmpty(world).isPresent();
|
2021-03-04 22:30:43 +01:00
|
|
|
}
|
|
|
|
|
2021-03-06 13:53:40 +01:00
|
|
|
public void ifPresent(World world, Consumer<T> consumer) {
|
2021-12-27 13:05:31 +01:00
|
|
|
getOrEmpty(world).ifPresent(consumer);
|
2021-03-06 13:53:40 +01:00
|
|
|
}
|
|
|
|
|
2021-03-04 22:30:43 +01:00
|
|
|
@Nullable
|
|
|
|
public T get(World world) {
|
2021-12-27 13:05:31 +01:00
|
|
|
return getOrEmpty(world).orElse(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
public Optional<T> getOrEmpty(World world) {
|
2022-09-17 22:11:24 +02:00
|
|
|
if (uuid.isPresent() && world instanceof ServerWorld serverWorld) {
|
|
|
|
return uuid.map(serverWorld::getEntity).map(e -> (T)e).filter(this::checkReference);
|
2021-03-04 22:30:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (clientId != 0) {
|
2021-12-27 13:05:31 +01:00
|
|
|
return Optional.ofNullable((T)world.getEntityById(clientId)).filter(this::checkReference);
|
2021-03-04 22:30:43 +01:00
|
|
|
}
|
|
|
|
|
2021-12-27 13:05:31 +01:00
|
|
|
return Optional.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean checkReference(Entity e) {
|
|
|
|
pos = Optional.of(e.getPos());
|
2022-01-01 23:43:21 +01:00
|
|
|
return e instanceof PlayerEntity || !e.isRemoved();
|
2021-03-04 22:30:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-08-04 15:38:03 +02:00
|
|
|
public void toNBT(NbtCompound tag) {
|
2022-01-01 21:08:50 +01:00
|
|
|
uuid.ifPresent(uuid -> tag.putUuid("uuid", uuid));
|
|
|
|
pos.ifPresent(p -> tag.put("pos", NbtSerialisable.writeVector(p)));
|
2021-03-04 22:30:43 +01:00
|
|
|
tag.putInt("clientId", clientId);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-08-04 15:38:03 +02:00
|
|
|
public void fromNBT(NbtCompound tag) {
|
2022-01-01 21:08:50 +01:00
|
|
|
uuid = tag.containsUuid("uuid") ? Optional.of(tag.getUuid("uuid")) : Optional.empty();
|
2021-12-27 13:05:31 +01:00
|
|
|
pos = tag.contains("pos") ? Optional.ofNullable(NbtSerialisable.readVector(tag.getList("pos", NbtElement.DOUBLE_TYPE))) : Optional.empty();
|
2021-03-04 22:30:43 +01:00
|
|
|
clientId = tag.getInt("clientId");
|
|
|
|
}
|
|
|
|
}
|