mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-10 09:21:28 +01:00
Moved switchEntityType from EntityCreature to Entity
This commit is contained in:
parent
ca6546eb7d
commit
18da3e0168
@ -13,11 +13,15 @@ import net.minestom.server.event.Event;
|
||||
import net.minestom.server.event.EventCallback;
|
||||
import net.minestom.server.event.entity.*;
|
||||
import net.minestom.server.event.handler.EventHandler;
|
||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.inventory.EquipmentHandler;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.permission.Permission;
|
||||
import net.minestom.server.permission.PermissionHandler;
|
||||
import net.minestom.server.potion.Potion;
|
||||
@ -114,6 +118,11 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
private long ticks;
|
||||
private final EntityTickEvent tickEvent = new EntityTickEvent(this);
|
||||
|
||||
/**
|
||||
* Lock used to support #switchEntityType
|
||||
*/
|
||||
private final Object entityTypeLock = new Object();
|
||||
|
||||
public Entity(@NotNull EntityType entityType, @NotNull UUID uuid, @NotNull Position spawnPosition) {
|
||||
this.id = generateId();
|
||||
this.entityType = entityType;
|
||||
@ -313,18 +322,41 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(@NotNull Player player) {
|
||||
boolean result = this.viewers.add(player);
|
||||
if (!result)
|
||||
public final boolean addViewer(@NotNull Player player) {
|
||||
synchronized (this.entityTypeLock) {
|
||||
return addViewer0(player);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addViewer0(@NotNull Player player) {
|
||||
if (!this.viewers.add(player)) {
|
||||
return false;
|
||||
}
|
||||
player.viewableEntities.add(this);
|
||||
|
||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
playerConnection.sendPacket(getEntityType().getSpawnType().getSpawnPacket(this));
|
||||
playerConnection.sendPacket(getVelocityPacket());
|
||||
playerConnection.sendPacket(getMetadataPacket());
|
||||
|
||||
if (hasPassenger()) {
|
||||
playerConnection.sendPacket(getPassengersPacket());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeViewer(@NotNull Player player) {
|
||||
if (!viewers.remove(player))
|
||||
public final boolean removeViewer(@NotNull Player player) {
|
||||
synchronized (this.entityTypeLock) {
|
||||
return removeViewer0(player);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeViewer0(@NotNull Player player) {
|
||||
if (!viewers.remove(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket();
|
||||
destroyEntitiesPacket.entityIds = new int[]{getEntityId()};
|
||||
@ -339,6 +371,29 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P
|
||||
return unmodifiableViewers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final void switchEntityType(@NotNull EntityType entityType) {
|
||||
synchronized (entityTypeLock) {
|
||||
this.entityType = entityType;
|
||||
this.metadata = new Metadata(this);
|
||||
this.entityMeta = entityType.getMetaConstructor().apply(this, this.metadata);
|
||||
|
||||
Set<Player> viewers = new HashSet<>(getViewers());
|
||||
getViewers().forEach(this::removeViewer);
|
||||
viewers.forEach(this::addViewer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Data getData() {
|
||||
return data;
|
||||
|
@ -8,20 +8,14 @@ import net.minestom.server.entity.ai.TargetSelector;
|
||||
import net.minestom.server.entity.pathfinding.NavigableEntity;
|
||||
import net.minestom.server.entity.pathfinding.Navigator;
|
||||
import net.minestom.server.event.entity.EntityAttackEvent;
|
||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.play.EntityEquipmentPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
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;
|
||||
|
||||
public class EntityCreature extends LivingEntity implements NavigableEntity, EntityAI {
|
||||
|
||||
@ -35,31 +29,9 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
|
||||
|
||||
private Entity target;
|
||||
|
||||
/**
|
||||
* Lock used to support #switchEntityType
|
||||
*/
|
||||
private final Object entityTypeLock = new Object();
|
||||
|
||||
// Equipments
|
||||
private ItemStack mainHandItem;
|
||||
private ItemStack offHandItem;
|
||||
|
||||
private ItemStack helmet;
|
||||
private ItemStack chestplate;
|
||||
private ItemStack leggings;
|
||||
private ItemStack boots;
|
||||
|
||||
public EntityCreature(@NotNull EntityType entityType, @NotNull Position spawnPosition) {
|
||||
super(entityType, spawnPosition);
|
||||
|
||||
this.mainHandItem = ItemStack.getAirItem();
|
||||
this.offHandItem = ItemStack.getAirItem();
|
||||
|
||||
this.helmet = ItemStack.getAirItem();
|
||||
this.chestplate = ItemStack.getAirItem();
|
||||
this.leggings = ItemStack.getAirItem();
|
||||
this.boots = ItemStack.getAirItem();
|
||||
|
||||
heal();
|
||||
}
|
||||
|
||||
@ -108,56 +80,6 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(@NotNull Player player) {
|
||||
synchronized (entityTypeLock) {
|
||||
final boolean result = super.addViewer(player);
|
||||
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
|
||||
playerConnection.sendPacket(getEntityType().getSpawnType().getSpawnPacket(this));
|
||||
playerConnection.sendPacket(getVelocityPacket());
|
||||
playerConnection.sendPacket(getMetadataPacket());
|
||||
|
||||
// Equipments synchronization
|
||||
syncEquipments(playerConnection);
|
||||
|
||||
if (hasPassenger()) {
|
||||
playerConnection.sendPacket(getPassengersPacket());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kill animation delay before vanishing the entity.
|
||||
*
|
||||
@ -167,7 +89,6 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
|
||||
return removalAnimationDelay;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the removal animation delay of the entity.
|
||||
* <p>
|
||||
@ -221,78 +142,6 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemInMainHand() {
|
||||
return mainHandItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInMainHand(@NotNull ItemStack itemStack) {
|
||||
this.mainHandItem = itemStack;
|
||||
syncEquipment(EntityEquipmentPacket.Slot.MAIN_HAND);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemInOffHand() {
|
||||
return offHandItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInOffHand(@NotNull ItemStack itemStack) {
|
||||
this.offHandItem = itemStack;
|
||||
syncEquipment(EntityEquipmentPacket.Slot.OFF_HAND);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getHelmet() {
|
||||
return helmet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHelmet(@NotNull ItemStack itemStack) {
|
||||
this.helmet = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.HELMET);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.HELMET);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getChestplate() {
|
||||
return chestplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChestplate(@NotNull ItemStack itemStack) {
|
||||
this.chestplate = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.CHESTPLATE);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.CHESTPLATE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getLeggings() {
|
||||
return leggings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLeggings(@NotNull ItemStack itemStack) {
|
||||
this.leggings = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.LEGGINGS);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.LEGGINGS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getBoots() {
|
||||
return boots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoots(@NotNull ItemStack itemStack) {
|
||||
this.boots = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.BOOTS);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.BOOTS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Navigator getNavigator() {
|
||||
@ -323,9 +172,4 @@ public class EntityCreature extends LivingEntity implements NavigableEntity, Ent
|
||||
attack(target, false);
|
||||
}
|
||||
|
||||
private ItemStack getEquipmentItem(@NotNull ItemStack itemStack, @NotNull ArmorEquipEvent.ArmorSlot armorSlot) {
|
||||
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(this, itemStack, armorSlot);
|
||||
callEvent(ArmorEquipEvent.class, armorEquipEvent);
|
||||
return armorEquipEvent.getArmorItem();
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,13 @@ import net.minestom.server.entity.metadata.LivingEntityMeta;
|
||||
import net.minestom.server.event.entity.EntityDamageEvent;
|
||||
import net.minestom.server.event.entity.EntityDeathEvent;
|
||||
import net.minestom.server.event.entity.EntityFireEvent;
|
||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||
import net.minestom.server.event.item.PickupItemEvent;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.inventory.EquipmentHandler;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.play.CollectItemPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityPropertiesPacket;
|
||||
import net.minestom.server.network.packet.server.play.SoundEffectPacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
@ -75,10 +73,20 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
private int arrowCount;
|
||||
private float health = 1F;
|
||||
|
||||
// Equipments
|
||||
private ItemStack mainHandItem;
|
||||
private ItemStack offHandItem;
|
||||
|
||||
private ItemStack helmet;
|
||||
private ItemStack chestplate;
|
||||
private ItemStack leggings;
|
||||
private ItemStack boots;
|
||||
|
||||
public LivingEntity(@NotNull EntityType entityType, @NotNull Position spawnPosition) {
|
||||
super(entityType, spawnPosition);
|
||||
setupAttributes();
|
||||
setGravity(0.02f, 0.08f, 3.92f);
|
||||
initEquipments();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +96,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
super(entityType, uuid, spawnPosition);
|
||||
setupAttributes();
|
||||
setGravity(0.02f, 0.08f, 3.92f);
|
||||
initEquipments();
|
||||
}
|
||||
|
||||
public LivingEntity(@NotNull EntityType entityType) {
|
||||
@ -101,6 +110,94 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
this(entityType, uuid, new Position());
|
||||
}
|
||||
|
||||
private void initEquipments() {
|
||||
this.mainHandItem = ItemStack.getAirItem();
|
||||
this.offHandItem = ItemStack.getAirItem();
|
||||
|
||||
this.helmet = ItemStack.getAirItem();
|
||||
this.chestplate = ItemStack.getAirItem();
|
||||
this.leggings = ItemStack.getAirItem();
|
||||
this.boots = ItemStack.getAirItem();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemInMainHand() {
|
||||
return mainHandItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInMainHand(@NotNull ItemStack itemStack) {
|
||||
this.mainHandItem = itemStack;
|
||||
syncEquipment(EntityEquipmentPacket.Slot.MAIN_HAND);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemInOffHand() {
|
||||
return offHandItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInOffHand(@NotNull ItemStack itemStack) {
|
||||
this.offHandItem = itemStack;
|
||||
syncEquipment(EntityEquipmentPacket.Slot.OFF_HAND);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getHelmet() {
|
||||
return helmet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHelmet(@NotNull ItemStack itemStack) {
|
||||
this.helmet = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.HELMET);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.HELMET);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getChestplate() {
|
||||
return chestplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChestplate(@NotNull ItemStack itemStack) {
|
||||
this.chestplate = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.CHESTPLATE);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.CHESTPLATE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getLeggings() {
|
||||
return leggings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLeggings(@NotNull ItemStack itemStack) {
|
||||
this.leggings = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.LEGGINGS);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.LEGGINGS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getBoots() {
|
||||
return boots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoots(@NotNull ItemStack itemStack) {
|
||||
this.boots = getEquipmentItem(itemStack, ArmorEquipEvent.ArmorSlot.BOOTS);
|
||||
syncEquipment(EntityEquipmentPacket.Slot.BOOTS);
|
||||
}
|
||||
|
||||
private ItemStack getEquipmentItem(@NotNull ItemStack itemStack, @NotNull ArmorEquipEvent.ArmorSlot armorSlot) {
|
||||
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(this, itemStack, armorSlot);
|
||||
callEvent(ArmorEquipEvent.class, armorEquipEvent);
|
||||
return armorEquipEvent.getArmorItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(long time) {
|
||||
if (isOnFire()) {
|
||||
@ -429,6 +526,15 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
this.canPickupItem = canPickupItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer0(@NotNull Player player) {
|
||||
if (!super.addViewer0(player)) {
|
||||
return false;
|
||||
}
|
||||
syncEquipments(player.getPlayerConnection());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoundingBox(double x, double y, double z) {
|
||||
super.setBoundingBox(x, y, z);
|
||||
|
@ -626,13 +626,10 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(@NotNull Player player) {
|
||||
if (player == this)
|
||||
return false;
|
||||
|
||||
final boolean result = super.addViewer(player);
|
||||
if (!result)
|
||||
public boolean addViewer0(@NotNull Player player) {
|
||||
if (player == this || !super.addViewer0(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerConnection viewerConnection = player.getPlayerConnection();
|
||||
showPlayer(viewerConnection);
|
||||
@ -640,18 +637,19 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeViewer(@NotNull Player player) {
|
||||
if (player == this)
|
||||
public boolean removeViewer0(@NotNull Player player) {
|
||||
if (player == this || !super.removeViewer0(player)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = super.removeViewer(player);
|
||||
PlayerConnection viewerConnection = player.getPlayerConnection();
|
||||
viewerConnection.sendPacket(getRemovePlayerToList());
|
||||
|
||||
// Team
|
||||
if (this.getTeam() != null && this.getTeam().getMembers().size() == 1) // If team only contains "this" player
|
||||
if (this.getTeam() != null && this.getTeam().getMembers().size() == 1) {// If team only contains "this" player
|
||||
viewerConnection.sendPacket(this.getTeam().createTeamDestructionPacket());
|
||||
return result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,10 +52,12 @@ public class EntityArmorStand extends ObjectEntity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(@NotNull Player player) {
|
||||
final boolean result = super.addViewer(player);
|
||||
public boolean addViewer0(@NotNull Player player) {
|
||||
if (!super.addViewer0(player)) {
|
||||
return false;
|
||||
}
|
||||
syncEquipments(player.getPlayerConnection());
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user