Added EntityCreature#switchEntityType

This commit is contained in:
Felix Cravic 2020-12-05 01:36:06 +01:00
parent cd44732cbc
commit 6bd6d22651
2 changed files with 57 additions and 20 deletions

View File

@ -103,7 +103,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
private final Set<Entity> passengers = new CopyOnWriteArraySet<>();
private long lastUpdate;
private final EntityType entityType;
protected EntityType entityType; // UNSAFE to change, modify at your own risk
// Network synchronization, send the absolute position of the entity each X milliseconds
private static final UpdateOption SYNCHRONIZATION_COOLDOWN = new UpdateOption(1500, TimeUnit.MILLISECOND);

View File

@ -21,7 +21,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
public abstract class EntityCreature extends LivingEntity implements NavigableEntity {
@ -40,6 +42,11 @@ public abstract class EntityCreature extends LivingEntity implements NavigableEn
private Entity target;
/**
* Lock used to support #switchEntityType
*/
private Object entityTypeLock = new Object();
// Equipments
private ItemStack mainHandItem;
private ItemStack offHandItem;
@ -148,33 +155,63 @@ public abstract class EntityCreature extends LivingEntity implements NavigableEn
@Override
public boolean addViewer(@NotNull Player player) {
final boolean result = super.addViewer(player);
synchronized (entityTypeLock) {
final boolean result = super.addViewer(player);
final PlayerConnection playerConnection = player.getPlayerConnection();
final PlayerConnection playerConnection = player.getPlayerConnection();
EntityMovementPacket entityMovementPacket = new EntityMovementPacket();
entityMovementPacket.entityId = getEntityId();
EntityMovementPacket entityMovementPacket = new EntityMovementPacket();
entityMovementPacket.entityId = getEntityId();
SpawnLivingEntityPacket spawnLivingEntityPacket = new SpawnLivingEntityPacket();
spawnLivingEntityPacket.entityId = getEntityId();
spawnLivingEntityPacket.entityUuid = getUuid();
spawnLivingEntityPacket.entityType = getEntityType().getId();
spawnLivingEntityPacket.position = getPosition();
spawnLivingEntityPacket.headPitch = 0;
SpawnLivingEntityPacket spawnLivingEntityPacket = new SpawnLivingEntityPacket();
spawnLivingEntityPacket.entityId = getEntityId();
spawnLivingEntityPacket.entityUuid = getUuid();
spawnLivingEntityPacket.entityType = getEntityType().getId();
spawnLivingEntityPacket.position = getPosition();
spawnLivingEntityPacket.headPitch = 0;
playerConnection.sendPacket(entityMovementPacket);
playerConnection.sendPacket(spawnLivingEntityPacket);
playerConnection.sendPacket(getVelocityPacket());
playerConnection.sendPacket(getMetadataPacket());
playerConnection.sendPacket(entityMovementPacket);
playerConnection.sendPacket(spawnLivingEntityPacket);
playerConnection.sendPacket(getVelocityPacket());
playerConnection.sendPacket(getMetadataPacket());
// Equipments synchronization
syncEquipments(playerConnection);
// Equipments synchronization
syncEquipments(playerConnection);
if (hasPassenger()) {
playerConnection.sendPacket(getPassengersPacket());
if (hasPassenger()) {
playerConnection.sendPacket(getPassengersPacket());
}
return result;
}
}
return result;
@Override
public boolean removeViewer(@NotNull Player player) {
synchronized (entityTypeLock) {
return super.removeViewer(player);
}
}
/**
* Changes the entity type of this entity.
* <p>
* Works by changing the internal entity type field and by calling {@link #removeViewer(Player)}
* followed by {@link #addViewer(Player)} to all current viewers.
* <p>
* Be aware that this only change the visual of the entity, the {@link net.minestom.server.collision.BoundingBox}
* will not be modified.
*
* @param entityType the new entity type
*/
public void switchEntityType(@NotNull EntityType entityType) {
synchronized (entityTypeLock) {
this.entityType = entityType;
Set<Player> viewers = new HashSet<>(getViewers());
getViewers().forEach(this::removeViewer);
viewers.forEach(this::addViewer);
}
}
/**