Added Entity#isAutoViewable & making Viewable#addViewer and Viewable#removeViewer return boolean

This commit is contained in:
Felix Cravic 2020-05-23 17:57:56 +02:00
parent a4b530c1dc
commit 883e7eb80f
16 changed files with 160 additions and 86 deletions

View File

@ -8,6 +8,7 @@ import net.minestom.server.benchmark.BenchmarkManager;
import net.minestom.server.benchmark.ThreadResult; import net.minestom.server.benchmark.ThreadResult;
import net.minestom.server.entity.*; import net.minestom.server.entity.*;
import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.type.EntityBoat;
import net.minestom.server.event.entity.EntityAttackEvent; import net.minestom.server.event.entity.EntityAttackEvent;
import net.minestom.server.event.item.ItemDropEvent; import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.ItemUpdateStateEvent; import net.minestom.server.event.item.ItemUpdateStateEvent;
@ -19,11 +20,12 @@ import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType; import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.Enchantment;
import net.minestom.server.item.ItemFlag;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.ConnectionManager;
import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.scoreboard.Sidebar;
import net.minestom.server.timer.TaskRunnable; import net.minestom.server.timer.TaskRunnable;
import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.Position; import net.minestom.server.utils.Position;
@ -40,6 +42,8 @@ public class PlayerInit {
private static volatile InstanceContainer instanceContainer; private static volatile InstanceContainer instanceContainer;
private static volatile InstanceContainer netherTest; private static volatile InstanceContainer netherTest;
private static volatile Inventory inventory;
static { static {
//StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("chunk_data"); //StorageFolder storageFolder = MinecraftServer.getStorageManager().getFolder("chunk_data");
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo(); ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
@ -61,6 +65,15 @@ public class PlayerInit {
instanceContainer.loadChunk(x, z); instanceContainer.loadChunk(x, z);
netherTest.loadChunk(x, z); netherTest.loadChunk(x, z);
} }
inventory = new Inventory(InventoryType.CHEST_1_ROW, "Test inventory");
inventory.addInventoryCondition((p, slot, clickType, inventoryConditionResult) -> {
p.sendMessage("click type inventory: " + clickType);
System.out.println("slot inv: " + slot);
inventoryConditionResult.setCancel(false);
});
inventory.setItemStack(0, new ItemStack(Material.DIAMOND, (byte) 34));
} }
public static void init() { public static void init() {
@ -157,9 +170,9 @@ public class PlayerInit {
player.addEventCallback(ItemDropEvent.class, event -> { player.addEventCallback(ItemDropEvent.class, event -> {
ItemStack droppedItem = event.getItemStack(); ItemStack droppedItem = event.getItemStack();
ItemEntity itemEntity = new ItemEntity(droppedItem); Position position = player.getPosition().clone().add(0, 1.5f, 0);
itemEntity.setPickupDelay(500); ItemEntity itemEntity = new ItemEntity(droppedItem, position);
itemEntity.refreshPosition(player.getPosition().clone().add(0, 1.5f, 0)); itemEntity.setPickupDelay(500, TimeUnit.MILLISECOND);
itemEntity.setInstance(player.getInstance()); itemEntity.setInstance(player.getInstance());
Vector velocity = player.getPosition().clone().getDirection().multiply(6); Vector velocity = player.getPosition().clone().getDirection().multiply(6);
itemEntity.setVelocity(velocity); itemEntity.setVelocity(velocity);
@ -179,38 +192,36 @@ public class PlayerInit {
System.out.println("slot player: " + slot); System.out.println("slot player: " + slot);
}); });
Sidebar scoreboard = new Sidebar("Scoreboard Title"); /*Sidebar scoreboard = new Sidebar("Scoreboard Title");
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
scoreboard.createLine(new Sidebar.ScoreboardLine("id" + i, "Hey guys " + i, i)); scoreboard.createLine(new Sidebar.ScoreboardLine("id" + i, "Hey guys " + i, i));
} }
scoreboard.addViewer(player); scoreboard.addViewer(player);
scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED"); scoreboard.updateLineContent("id3", "I HAVE BEEN UPDATED");
scoreboard.setTitle("test"); scoreboard.setTitle("test");*/
}); });
player.addEventCallback(PlayerSpawnEvent.class, event -> { player.addEventCallback(PlayerSpawnEvent.class, event -> {
player.setGameMode(GameMode.SURVIVAL); player.setGameMode(GameMode.SURVIVAL);
player.teleport(new Position(0, 75, 0)); player.teleport(new Position(0, 70, 0));
ItemStack item = new ItemStack(Material.STONE, (byte) 43); ItemStack item = new ItemStack(Material.STONE_SWORD, (byte) 1);
item.setDisplayName("Item name"); item.setDisplayName("Item name");
item.getLore().add("a lore line"); item.getLore().add("a lore line");
//item.setEnchantment(Enchantment.SHARPNESS, 2); item.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
item.setEnchantment(Enchantment.SHARPNESS, (short) 2);
player.getInventory().addItemStack(item); player.getInventory().addItemStack(item);
Inventory inventory = new Inventory(InventoryType.CHEST_1_ROW, "Test inventory");
inventory.addInventoryCondition((p, slot, clickType, inventoryConditionResult) -> {
player.sendMessage("click type inventory: " + clickType);
System.out.println("slot inv: " + slot);
inventoryConditionResult.setCancel(false);
});
inventory.setItemStack(0, item.clone());
player.openInventory(inventory); player.openInventory(inventory);
player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100)); player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 100));
player.getInventory().addItemStack(new ItemStack(Material.DIAMOND_CHESTPLATE, (byte) 1));
EntityBoat entityBoat = new EntityBoat(player.getPosition());
entityBoat.setInstance(player.getInstance());
//entityBoat.addPassenger(player);
//player.getInventory().addItemStack(new ItemStack(Material.DIAMOND_CHESTPLATE, (byte) 1));
/*TeamManager teamManager = Main.getTeamManager(); /*TeamManager teamManager = Main.getTeamManager();
Team team = teamManager.createTeam(getUsername()); Team team = teamManager.createTeam(getUsername());

View File

@ -14,6 +14,9 @@ public class ChickenCreature extends EntityCreature {
public ChickenCreature(Position defaultPosition) { public ChickenCreature(Position defaultPosition) {
super(EntityType.SKELETON, defaultPosition); super(EntityType.SKELETON, defaultPosition);
setAutoViewable(true);
setBoundingBox(0.4f, 0.7f, 0.4f); setBoundingBox(0.4f, 0.7f, 0.4f);
setHelmet(new ItemStack(Material.DIAMOND_HELMET, (byte) 1)); setHelmet(new ItemStack(Material.DIAMOND_HELMET, (byte) 1));
} }

View File

@ -9,9 +9,17 @@ import java.util.Set;
public interface Viewable { public interface Viewable {
void addViewer(Player player); /**
* @param player the viewer to add
* @return true if the player has been added, false otherwise (could be because he is already a viewer)
*/
boolean addViewer(Player player);
void removeViewer(Player player); /**
* @param player the viewer to remove
* @return true if the player has been removed, false otherwise (could be because he was not a viewer)
*/
boolean removeViewer(Player player);
Set<Player> getViewers(); Set<Player> getViewers();

View File

@ -27,17 +27,19 @@ public class BossBar implements Viewable {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
player.refreshAddBossbar(this); player.refreshAddBossbar(this);
addToPlayer(player); addToPlayer(player);
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
this.viewers.remove(player); boolean result = this.viewers.remove(player);
player.refreshRemoveBossbar(this); player.refreshRemoveBossbar(this);
removeToPlayer(player); removeToPlayer(player);
return result;
} }
@Override @Override

View File

@ -61,6 +61,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
protected float gravityDragPerTick; protected float gravityDragPerTick;
protected float eyeHeight; protected float eyeHeight;
private boolean autoViewable;
private Set<Player> viewers = new CopyOnWriteArraySet<>(); private Set<Player> viewers = new CopyOnWriteArraySet<>();
private Data data; private Data data;
private Set<Entity> passengers = new CopyOnWriteArraySet<>(); private Set<Entity> passengers = new CopyOnWriteArraySet<>();
@ -110,6 +111,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
setBoundingBox(0, 0, 0); setBoundingBox(0, 0, 0);
setAutoViewable(true);
entityById.put(id, this); entityById.put(id, this);
setVelocityUpdatePeriod(5); setVelocityUpdatePeriod(5);
} }
@ -204,27 +207,54 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
teleport(position, null); teleport(position, null);
} }
/**
* When set to true, the entity will automatically get new viewers when they come too close
* This can be use to complete control over which player can see it, without having to deal with
* raw packets
* <p>
* True by default for all entities
* When set to false, it is important to mention that the players will not be removed automatically from its viewers
* list, you would have to do that manually when being too far
*
* @return true if the entity is automatically viewable for close players, false otherwise
*/
public boolean isAutoViewable() {
return autoViewable;
}
/**
* @param autoViewable should the entity be automatically viewable for close players
*/
public void setAutoViewable(boolean autoViewable) {
this.autoViewable = autoViewable;
}
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
player.viewableEntities.add(this); player.viewableEntities.add(this);
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
playerConnection.sendPacket(getVelocityPacket()); playerConnection.sendPacket(getVelocityPacket());
playerConnection.sendPacket(getPassengersPacket()); playerConnection.sendPacket(getPassengersPacket());
playerConnection.sendPacket(getMetadataPacket()); playerConnection.sendPacket(getMetadataPacket());
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
boolean result;
synchronized (viewers) { synchronized (viewers) {
if (!viewers.contains(player)) result = viewers.remove(player);
return; if (!result)
this.viewers.remove(player); return false;
DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket(); DestroyEntitiesPacket destroyEntitiesPacket = new DestroyEntitiesPacket();
destroyEntitiesPacket.entityIds = new int[]{getEntityId()}; destroyEntitiesPacket.entityIds = new int[]{getEntityId()};
player.getPlayerConnection().sendPacket(destroyEntitiesPacket); player.getPlayerConnection().sendPacket(destroyEntitiesPacket);
} }
player.viewableEntities.remove(this); player.viewableEntities.remove(this);
return result;
} }
@Override @Override
@ -571,7 +601,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
instance.removeEntityFromChunk(this, lastChunk); instance.removeEntityFromChunk(this, lastChunk);
instance.addEntityToChunk(this, newChunk); instance.addEntityToChunk(this, newChunk);
} }
updateView(this, lastChunk, newChunk); updateView(lastChunk, newChunk);
} }
} }
} }
@ -580,16 +610,16 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
refreshPosition(position.getX(), position.getY(), position.getZ()); refreshPosition(position.getX(), position.getY(), position.getZ());
} }
private void updateView(Entity entity, Chunk lastChunk, Chunk newChunk) { private void updateView(Chunk lastChunk, Chunk newChunk) {
if (entity instanceof Player) boolean isPlayer = this instanceof Player;
((Player) entity).onChunkChange(lastChunk, newChunk); // Refresh loaded chunk
if (isPlayer)
((Player) this).onChunkChange(lastChunk, newChunk); // Refresh loaded chunk
// Refresh entity viewable list // Refresh entity viewable list
long[] lastVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * lastChunk.getChunkX(), 0, 16 * lastChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE); long[] lastVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * lastChunk.getChunkX(), 0, 16 * lastChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE);
long[] updatedVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE); long[] updatedVisibleChunksEntity = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), MinecraftServer.ENTITY_VIEW_DISTANCE);
boolean isPlayer = entity instanceof Player;
int[] oldChunksEntity = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunksEntity, updatedVisibleChunksEntity); int[] oldChunksEntity = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunksEntity, updatedVisibleChunksEntity);
for (int index : oldChunksEntity) { for (int index : oldChunksEntity) {
int[] chunkPos = ChunkUtils.getChunkCoord(lastVisibleChunksEntity[index]); int[] chunkPos = ChunkUtils.getChunkCoord(lastVisibleChunksEntity[index]);
@ -599,12 +629,13 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
instance.getChunkEntities(chunk).forEach(ent -> { instance.getChunkEntities(chunk).forEach(ent -> {
if (ent instanceof Player) { if (ent instanceof Player) {
Player player = (Player) ent; Player player = (Player) ent;
removeViewer(player); if (isAutoViewable())
removeViewer(player);
if (isPlayer) { if (isPlayer) {
player.removeViewer((Player) entity); player.removeViewer((Player) this);
} }
} else if (isPlayer) { } else if (isPlayer) {
ent.removeViewer((Player) entity); ent.removeViewer((Player) this);
} }
}); });
} }
@ -618,12 +649,13 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
instance.getChunkEntities(chunk).forEach(ent -> { instance.getChunkEntities(chunk).forEach(ent -> {
if (ent instanceof Player) { if (ent instanceof Player) {
Player player = (Player) ent; Player player = (Player) ent;
addViewer(player); if (isAutoViewable())
if (entity instanceof Player) { addViewer(player);
player.addViewer((Player) entity); if (this instanceof Player) {
player.addViewer((Player) this);
} }
} else if (isPlayer) { } else if (isPlayer) {
ent.addViewer((Player) entity); ent.addViewer((Player) this);
} }
}); });
} }

View File

@ -133,8 +133,8 @@ public abstract class EntityCreature extends LivingEntity {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
super.addViewer(player); boolean result = super.addViewer(player);
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
EntityPacket entityPacket = new EntityPacket(); EntityPacket entityPacket = new EntityPacket();
@ -150,6 +150,7 @@ public abstract class EntityCreature extends LivingEntity {
playerConnection.sendPacket(entityPacket); playerConnection.sendPacket(entityPacket);
playerConnection.sendPacket(spawnLivingEntityPacket); playerConnection.sendPacket(spawnLivingEntityPacket);
playerConnection.sendPacket(getMetadataPacket()); playerConnection.sendPacket(getMetadataPacket());
return result;
} }
@Override @Override

View File

@ -25,7 +25,7 @@ public class ExperienceOrb extends Entity {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
SpawnExperienceOrbPacket experienceOrbPacket = new SpawnExperienceOrbPacket(); SpawnExperienceOrbPacket experienceOrbPacket = new SpawnExperienceOrbPacket();
@ -33,7 +33,7 @@ public class ExperienceOrb extends Entity {
experienceOrbPacket.position = getPosition(); experienceOrbPacket.position = getPosition();
experienceOrbPacket.expCount = experienceCount; experienceOrbPacket.expCount = experienceCount;
playerConnection.sendPacket(experienceOrbPacket); playerConnection.sendPacket(experienceOrbPacket);
super.addViewer(player); // Add player to viewers list and send velocity packet return super.addViewer(player); // Add player to viewers list and send velocity packet
} }
public short getExperienceCount() { public short getExperienceCount() {

View File

@ -6,6 +6,7 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.item.StackingRule; import net.minestom.server.item.StackingRule;
import net.minestom.server.network.packet.PacketWriter; import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.utils.Position; import net.minestom.server.utils.Position;
import net.minestom.server.utils.time.TimeUnit;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -83,11 +84,6 @@ public class ItemEntity extends ObjectEntity {
this.spawnTime = System.currentTimeMillis(); this.spawnTime = System.currentTimeMillis();
} }
@Override
public void addViewer(Player player) {
super.addViewer(player);
}
@Override @Override
public Consumer<PacketWriter> getMetadataConsumer() { public Consumer<PacketWriter> getMetadataConsumer() {
return packet -> { return packet -> {
@ -118,7 +114,7 @@ public class ItemEntity extends ObjectEntity {
public void setItemStack(ItemStack itemStack) { public void setItemStack(ItemStack itemStack) {
this.itemStack = itemStack; this.itemStack = itemStack;
sendMetadataIndex(7); // Refresh itemstack for viewers sendMetadataIndex(7); // Refresh the ItemStack for viewers
} }
public boolean isPickable() { public boolean isPickable() {
@ -141,8 +137,8 @@ public class ItemEntity extends ObjectEntity {
return pickupDelay; return pickupDelay;
} }
public void setPickupDelay(long pickupDelay) { public void setPickupDelay(long delay, TimeUnit timeUnit) {
this.pickupDelay = pickupDelay; this.pickupDelay = timeUnit.toMilliseconds(delay);
} }
public long getSpawnTime() { public long getSpawnTime() {

View File

@ -81,6 +81,11 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
BoundingBox livingBoundingBox = expandedBoundingBox; BoundingBox livingBoundingBox = expandedBoundingBox;
for (Entity entity : entities) { for (Entity entity : entities) {
if (entity instanceof ItemEntity) { if (entity instanceof ItemEntity) {
// Do not pickup if not visible
if (this instanceof Player && !entity.isViewer((Player) this))
continue;
ItemEntity itemEntity = (ItemEntity) entity; ItemEntity itemEntity = (ItemEntity) entity;
if (!itemEntity.isPickable()) if (!itemEntity.isPickable())
continue; continue;
@ -135,11 +140,12 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
super.addViewer(player); boolean result = super.addViewer(player);
// Equipments synchronization // Equipments synchronization
syncEquipments(); syncEquipments();
return result;
} }
/** /**

View File

@ -14,7 +14,7 @@ public abstract class ObjectEntity extends Entity {
public abstract int getObjectData(); public abstract int getObjectData();
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
SpawnEntityPacket spawnEntityPacket = new SpawnEntityPacket(); SpawnEntityPacket spawnEntityPacket = new SpawnEntityPacket();
@ -25,12 +25,12 @@ public abstract class ObjectEntity extends Entity {
spawnEntityPacket.data = getObjectData(); spawnEntityPacket.data = getObjectData();
playerConnection.sendPacket(spawnEntityPacket); playerConnection.sendPacket(spawnEntityPacket);
playerConnection.sendPacket(getMetadataPacket()); playerConnection.sendPacket(getMetadataPacket());
super.addViewer(player); // Add player to viewers list and send velocity packet return super.addViewer(player); // Add player to viewers list and send velocity packet
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
super.removeViewer(player); return super.removeViewer(player);
} }
} }

View File

@ -333,10 +333,11 @@ public class Player extends LivingEntity {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
if (player == this) if (player == this)
return; return false;
super.addViewer(player);
boolean result = super.addViewer(player);
PlayerConnection viewerConnection = player.getPlayerConnection(); PlayerConnection viewerConnection = player.getPlayerConnection();
String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19"; String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19";
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket(); SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
@ -356,13 +357,15 @@ public class Player extends LivingEntity {
// Team // Team
if (team != null) if (team != null)
viewerConnection.sendPacket(team.getTeamsCreationPacket()); viewerConnection.sendPacket(team.getTeamsCreationPacket());
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
if (player == this) if (player == this)
return; return false;
super.removeViewer(player);
boolean result = super.removeViewer(player);
PlayerConnection viewerConnection = player.getPlayerConnection(); PlayerConnection viewerConnection = player.getPlayerConnection();
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER); PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid())); playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
@ -371,6 +374,7 @@ public class Player extends LivingEntity {
// Team // Team
if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player if (team != null && team.getPlayers().size() == 1) // If team only contains "this" player
viewerConnection.sendPacket(team.createTeamDestructionPacket()); viewerConnection.sendPacket(team.createTeamDestructionPacket());
return result;
} }
@Override @Override

View File

@ -374,20 +374,22 @@ public class Chunk implements Viewable {
// UNSAFE // UNSAFE
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
PlayerChunkLoadEvent playerChunkLoadEvent = new PlayerChunkLoadEvent(player, chunkX, chunkZ); PlayerChunkLoadEvent playerChunkLoadEvent = new PlayerChunkLoadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkLoadEvent.class, playerChunkLoadEvent); player.callEvent(PlayerChunkLoadEvent.class, playerChunkLoadEvent);
return result;
} }
// UNSAFE // UNSAFE
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
this.viewers.remove(player); boolean result = this.viewers.remove(player);
PlayerChunkUnloadEvent playerChunkUnloadEvent = new PlayerChunkUnloadEvent(player, chunkX, chunkZ); PlayerChunkUnloadEvent playerChunkUnloadEvent = new PlayerChunkUnloadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkUnloadEvent.class, playerChunkUnloadEvent); player.callEvent(PlayerChunkUnloadEvent.class, playerChunkUnloadEvent);
return result;
} }
@Override @Override

View File

@ -315,7 +315,8 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
} }
if (ent instanceof Player) { if (ent instanceof Player) {
entity.addViewer((Player) ent); if (entity.isAutoViewable())
entity.addViewer((Player) ent);
} }
}); });
} }
@ -332,7 +333,10 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
RemoveEntityFromInstanceEvent event = new RemoveEntityFromInstanceEvent(this, entity); RemoveEntityFromInstanceEvent event = new RemoveEntityFromInstanceEvent(this, entity);
callCancellableEvent(RemoveEntityFromInstanceEvent.class, event, () -> { callCancellableEvent(RemoveEntityFromInstanceEvent.class, event, () -> {
entity.getViewers().forEach(p -> entity.removeViewer(p)); // Remove this entity from players viewable list and send delete entities packet if (entity.isAutoViewable()) {
// Remove this entity from players viewable list and send delete entities packet
entity.getViewers().forEach(p -> entity.removeViewer(p));
}
Chunk chunk = getChunkAt(entity.getPosition()); Chunk chunk = getChunkAt(entity.getPosition());
removeEntityFromChunk(entity, chunk); removeEntityFromChunk(entity, chunk);

View File

@ -133,7 +133,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
public void update(Player player) { public void update(Player player) {
if (!getViewers().contains(player)) if (!getViewers().contains(player))
return; return;
PacketWriterUtils.writeAndSend(player, getWindowItemsPacket()); PacketWriterUtils.writeAndSend(player, getWindowItemsPacket());
} }
@ -143,17 +143,19 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
WindowItemsPacket windowItemsPacket = getWindowItemsPacket(); WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
player.getPlayerConnection().sendPacket(windowItemsPacket); player.getPlayerConnection().sendPacket(windowItemsPacket);
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
this.viewers.remove(player); boolean result = this.viewers.remove(player);
this.cursorPlayersItem.remove(player); this.cursorPlayersItem.remove(player);
this.clickProcessor.clearCache(player); this.clickProcessor.clearCache(player);
return result;
} }
public ItemStack getCursorItem(Player player) { public ItemStack getCursorItem(Player player) {

View File

@ -53,15 +53,16 @@ public class BelowNameScoreboard implements Viewable {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
playerConnection.sendPacket(scoreboardObjectivePacket); playerConnection.sendPacket(scoreboardObjectivePacket);
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
this.viewers.remove(player); return this.viewers.remove(player);
} }
@Override @Override

View File

@ -124,8 +124,8 @@ public class Sidebar implements Viewable {
} }
@Override @Override
public void addViewer(Player player) { public boolean addViewer(Player player) {
this.viewers.add(player); boolean result = this.viewers.add(player);
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket(); ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket();
@ -145,11 +145,12 @@ public class Sidebar implements Viewable {
playerConnection.sendPacket(line.sidebarTeam.getCreationPacket()); playerConnection.sendPacket(line.sidebarTeam.getCreationPacket());
playerConnection.sendPacket(line.getScoreCreationPacket(objectiveName)); playerConnection.sendPacket(line.getScoreCreationPacket(objectiveName));
} }
return result;
} }
@Override @Override
public void removeViewer(Player player) { public boolean removeViewer(Player player) {
this.viewers.remove(player); boolean result = this.viewers.remove(player);
PlayerConnection playerConnection = player.getPlayerConnection(); PlayerConnection playerConnection = player.getPlayerConnection();
ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket(); ScoreboardObjectivePacket scoreboardObjectivePacket = new ScoreboardObjectivePacket();
scoreboardObjectivePacket.objectiveName = objectiveName; scoreboardObjectivePacket.objectiveName = objectiveName;
@ -160,6 +161,7 @@ public class Sidebar implements Viewable {
playerConnection.sendPacket(line.getScoreDestructionPacket(objectiveName)); // Is it necessary? playerConnection.sendPacket(line.getScoreDestructionPacket(objectiveName)); // Is it necessary?
playerConnection.sendPacket(line.sidebarTeam.getDestructionPacket()); playerConnection.sendPacket(line.sidebarTeam.getDestructionPacket());
} }
return result;
} }
@Override @Override