Replaced player viewableChunks set interaction to the Chunk class (Viewable support)

This commit is contained in:
themode 2020-08-16 19:18:34 +02:00
parent 737cf24ace
commit 97a1141583
3 changed files with 49 additions and 62 deletions

View File

@ -40,8 +40,8 @@ import java.util.function.Consumer;
public abstract class Entity implements Viewable, EventHandler, DataContainer {
private static Map<Integer, Entity> entityById = new ConcurrentHashMap<>();
private static AtomicInteger lastEntityId = new AtomicInteger();
private static final Map<Integer, Entity> entityById = new ConcurrentHashMap<>();
private static final AtomicInteger lastEntityId = new AtomicInteger();
// Metadata
protected static final byte METADATA_BYTE = 0;
@ -63,7 +63,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
protected float cacheX, cacheY, cacheZ; // Used to synchronize with #getPosition
protected float lastYaw, lastPitch;
protected float cacheYaw, cachePitch;
private int id;
// Synchronization
private static final long SYNCHRONIZATION_DELAY = 1500; // In ms
private BoundingBox boundingBox;
@ -74,22 +75,20 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
protected float eyeHeight;
private boolean autoViewable;
private Set<Player> viewers = new CopyOnWriteArraySet<>();
private final int id;
private Data data;
private Set<Entity> passengers = new CopyOnWriteArraySet<>();
private final Set<Player> viewers = new CopyOnWriteArraySet<>();
protected UUID uuid;
private boolean isActive; // False if entity has only been instanced without being added somewhere
private boolean removed;
private boolean shouldRemove;
private long scheduledRemoveTime;
private EntityType entityType;
private final Set<Entity> passengers = new CopyOnWriteArraySet<>();
private long lastUpdate;
private Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
private final EntityType entityType;
protected long lastVelocityUpdateTime; // Reset velocity to 0 after countdown
// Synchronization
private long synchronizationDelay = 1500; // In ms
private final Map<Class<? extends Event>, List<EventCallback>> eventCallbacks = new ConcurrentHashMap<>();
private long lastSynchronizationTime;
// Metadata
@ -215,9 +214,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
};
if (instance.hasEnabledAutoChunkLoad()) {
instance.loadChunk(position, chunk -> {
runnable.run();
});
instance.loadChunk(position, chunk -> runnable.run());
} else {
runnable.run();
}
@ -289,7 +286,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
if (!result)
return false;
player.viewableEntities.add(this);
return result;
return true;
}
@Override
@ -497,7 +494,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
}
// Scheduled synchronization
if (time - lastSynchronizationTime >= synchronizationDelay) {
if (time - lastSynchronizationTime >= SYNCHRONIZATION_DELAY) {
lastSynchronizationTime = time;
sendSynchronization();
}
@ -1210,9 +1207,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
protected void sendMetadataIndex(int index) {
EntityMetaDataPacket metaDataPacket = new EntityMetaDataPacket();
metaDataPacket.entityId = getEntityId();
metaDataPacket.consumer = packet -> {
fillMetadataIndex(packet, index);
};
metaDataPacket.consumer = packet -> fillMetadataIndex(packet, index);
sendPacketToViewersAndSelf(metaDataPacket);
}

View File

@ -61,7 +61,7 @@ public class Player extends LivingEntity implements CommandSender {
private String username;
protected PlayerConnection playerConnection;
private ConcurrentLinkedQueue<ClientPlayPacket> packets = new ConcurrentLinkedQueue<>();
protected final Set<Entity> viewableEntities = new CopyOnWriteArraySet<>();
private int latency;
private ColoredText displayName;
@ -69,19 +69,17 @@ public class Player extends LivingEntity implements CommandSender {
private DimensionType dimensionType;
private GameMode gameMode;
private LevelType levelType;
protected final Set<Chunk> viewableChunks = new CopyOnWriteArraySet<>();
private int teleportId = 0;
protected boolean onGround;
protected Set<Entity> viewableEntities = new CopyOnWriteArraySet<>();
protected Set<Chunk> viewableChunks = new CopyOnWriteArraySet<>();
private PlayerSettings settings;
private final ConcurrentLinkedQueue<ClientPlayPacket> packets = new ConcurrentLinkedQueue<>();
private final LevelType levelType;
private final PlayerSettings settings;
private float exp;
private int level;
private PlayerInventory inventory;
private final PlayerInventory inventory;
private Inventory openInventory;
// Used internally to allow the closing of inventory within the inventory listener
private boolean didCloseInventory;
@ -128,10 +126,10 @@ public class Player extends LivingEntity implements CommandSender {
private float walkingSpeed = 0.1f;
// Statistics
private Map<PlayerStatistic, Integer> statisticValueMap = new Hashtable<>();
private final Map<PlayerStatistic, Integer> statisticValueMap = new Hashtable<>();
// Vehicle
private PlayerVehicleInformation vehicleInformation = new PlayerVehicleInformation();
private final PlayerVehicleInformation vehicleInformation = new PlayerVehicleInformation();
// Tick related
private final PlayerTickEvent playerTickEvent = new PlayerTickEvent(this);
@ -364,7 +362,7 @@ public class Player extends LivingEntity implements CommandSender {
final boolean positionChanged = position.getX() != lastX || position.getY() != lastY || position.getZ() != lastZ;
final boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch;
if (!getViewers().isEmpty() && (positionChanged || viewChanged)) {
ServerPacket updatePacket = null;
ServerPacket updatePacket;
ServerPacket optionalUpdatePacket = null;
if (positionChanged && viewChanged) {
EntityPositionAndRotationPacket entityPositionAndRotationPacket = new EntityPositionAndRotationPacket();
@ -393,7 +391,8 @@ public class Player extends LivingEntity implements CommandSender {
lastY = position.getY();
lastZ = position.getZ();
updatePacket = entityPositionPacket;
} else if (viewChanged) {
} else {
// View changed
EntityRotationPacket entityRotationPacket = new EntityRotationPacket();
entityRotationPacket.entityId = getEntityId();
entityRotationPacket.yaw = position.getYaw();
@ -412,13 +411,13 @@ public class Player extends LivingEntity implements CommandSender {
optionalUpdatePacket = entityHeadLookPacket;
}
if (updatePacket != null) {
if (optionalUpdatePacket != null) {
sendPacketsToViewers(updatePacket, optionalUpdatePacket);
} else {
sendPacketToViewers(updatePacket);
}
// Send the update packet
if (optionalUpdatePacket != null) {
sendPacketsToViewers(updatePacket, optionalUpdatePacket);
} else {
sendPacketToViewers(updatePacket);
}
}
}
@ -513,7 +512,7 @@ public class Player extends LivingEntity implements CommandSender {
PlayerConnection viewerConnection = player.getPlayerConnection();
showPlayer(viewerConnection);
return result;
return true;
}
@Override
@ -540,7 +539,6 @@ public class Player extends LivingEntity implements CommandSender {
for (Chunk viewableChunk : viewableChunks) {
viewableChunk.removeViewer(this);
}
viewableChunks.clear();
if (this.instance != null) {
final DimensionType instanceDimensionType = instance.getDimensionType();
@ -552,13 +550,12 @@ public class Player extends LivingEntity implements CommandSender {
final int length = visibleChunks.length;
AtomicInteger counter = new AtomicInteger(0);
for (int i = 0; i < length; i++) {
final int[] chunkPos = ChunkUtils.getChunkCoord(visibleChunks[i]);
for (long visibleChunk : visibleChunks) {
final int[] chunkPos = ChunkUtils.getChunkCoord(visibleChunk);
final int chunkX = chunkPos[0];
final int chunkZ = chunkPos[1];
Consumer<Chunk> callback = (chunk) -> {
if (chunk != null) {
viewableChunks.add(chunk);
chunk.addViewer(this);
if (chunk.getChunkX() == Math.floorDiv((int) getPosition().getX(), 16) && chunk.getChunkZ() == Math.floorDiv((int) getPosition().getZ(), 16))
updateViewPosition(chunk);
@ -827,7 +824,7 @@ public class Player extends LivingEntity implements CommandSender {
/**
* Update the internal field and send the appropriate {@link EntityMetaDataPacket}
*
* @param additionalHearts the count of additional heartss
* @param additionalHearts the count of additional hearts
*/
public void setAdditionalHearts(float additionalHearts) {
this.additionalHearts = additionalHearts;
@ -958,7 +955,7 @@ public class Player extends LivingEntity implements CommandSender {
playerConnection.sendPacket(addPlayerPacket);
for (Player viewer : getViewers()) {
PlayerConnection connection = viewer.getPlayerConnection();
final PlayerConnection connection = viewer.getPlayerConnection();
connection.sendPacket(removePlayerPacket);
connection.sendPacket(destroyEntitiesPacket);
@ -970,16 +967,6 @@ public class Player extends LivingEntity implements CommandSender {
teleport(getPosition());
}
/**
* Used to update the internal skin field
*
* @param skin the player skin
* @see #setSkin(PlayerSkin) instead
*/
protected void refreshSkin(PlayerSkin skin) {
this.skin = skin;
}
/**
* Get if the player has the respawn screen enabled or disabled
*
@ -1202,9 +1189,9 @@ public class Player extends LivingEntity implements CommandSender {
*/
protected void onChunkChange(Chunk newChunk) {
final long[] lastVisibleChunks = new long[viewableChunks.size()];
Chunk[] lastViewableChunks = viewableChunks.toArray(new Chunk[0]);
final Chunk[] lastViewableChunks = viewableChunks.toArray(new Chunk[0]);
for (int i = 0; i < lastViewableChunks.length; i++) {
Chunk lastViewableChunk = lastViewableChunks[i];
final Chunk lastViewableChunk = lastViewableChunks[i];
lastVisibleChunks[i] = ChunkUtils.getChunkIndex(lastViewableChunk.getChunkX(), lastViewableChunk.getChunkZ());
}
final long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), getChunkRange());
@ -1219,8 +1206,7 @@ public class Player extends LivingEntity implements CommandSender {
unloadChunkPacket.chunkZ = chunkPos[1];
playerConnection.sendPacket(unloadChunkPacket);
Chunk chunk = instance.getChunk(chunkPos[0], chunkPos[1]);
viewableChunks.remove(chunk);
final Chunk chunk = instance.getChunk(chunkPos[0], chunkPos[1]);
if (chunk != null)
chunk.removeViewer(this);
}
@ -1228,15 +1214,13 @@ public class Player extends LivingEntity implements CommandSender {
updateViewPosition(newChunk);
// Load new chunks
for (int i = 0; i < newChunks.length; i++) {
final int index = newChunks[i];
for (int index : newChunks) {
final int[] chunkPos = ChunkUtils.getChunkCoord(updatedVisibleChunks[index]);
instance.loadOptionalChunk(chunkPos[0], chunkPos[1], chunk -> {
if (chunk == null) {
// Cannot load chunk (auto load is not enabled)
return;
}
this.viewableChunks.add(chunk);
chunk.addViewer(this);
});
}
@ -1541,11 +1525,14 @@ public class Player extends LivingEntity implements CommandSender {
/**
* Get the player viewable chunks
* <p>
* WARNING: adding or removing a chunk there will not load/unload it,
* use {@link Chunk#addViewer(Player)} or {@link Chunk#removeViewer(Player)}
*
* @return an unmodifiable {@link Set} containing all the chunks that the player sees
* @return a {@link Set} containing all the chunks that the player sees
*/
public Set<Chunk> getViewableChunks() {
return Collections.unmodifiableSet(viewableChunks);
return viewableChunks;
}
/**

View File

@ -286,6 +286,8 @@ public abstract class Chunk implements Viewable {
// Send the chunk data & light packets to the player
sendChunk(player);
// Add to the viewable chunks set
player.getViewableChunks().add(this);
PlayerChunkLoadEvent playerChunkLoadEvent = new PlayerChunkLoadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkLoadEvent.class, playerChunkLoadEvent);
@ -297,6 +299,9 @@ public abstract class Chunk implements Viewable {
public boolean removeViewer(Player player) {
final boolean result = this.viewers.remove(player);
// Remove from the viewable chunks set
player.getViewableChunks().remove(this);
PlayerChunkUnloadEvent playerChunkUnloadEvent = new PlayerChunkUnloadEvent(player, chunkX, chunkZ);
player.callEvent(PlayerChunkUnloadEvent.class, playerChunkUnloadEvent);
return result;