use of net.glowstone.chunk.GlowChunk.Key in project Glowstone by GlowstoneMC.
the class GlowNoteBlock method play.
////////////////////////////////////////////////////////////////////////////
// Internals
@Override
public boolean play(Instrument instrument, Note note) {
if (getBlock().getType() != Material.NOTE_BLOCK) {
return false;
}
NotePlayEvent event = EventFactory.callEvent(new NotePlayEvent(getBlock(), instrument, note));
if (event.isCancelled()) {
return false;
}
Location location = getBlock().getLocation();
Key key = new Key(getX() >> 4, getZ() >> 4);
getWorld().getRawPlayers().stream().filter(player -> player.canSeeChunk(key)).forEach(player -> player.playNote(location, instrument, note));
return true;
}
use of net.glowstone.chunk.GlowChunk.Key in project Glowstone by GlowstoneMC.
the class ChunkManager method isChunkInUse.
/**
* Check whether a chunk has locks on it preventing it from being unloaded.
*
* @param x The X coordinate.
* @param z The Z coordinate.
* @return Whether the chunk is in use.
*/
public boolean isChunkInUse(int x, int z) {
Key key = new Key(x, z);
Set<ChunkLock> lockSet = locks.get(key);
return lockSet != null && !lockSet.isEmpty();
}
use of net.glowstone.chunk.GlowChunk.Key in project Glowstone by GlowstoneMC.
the class ChunkManager method getChunk.
/**
* Gets a chunk object representing the specified coordinates, which might
* not yet be loaded.
*
* @param x The X coordinate.
* @param z The Z coordinate.
* @return The chunk.
*/
public GlowChunk getChunk(int x, int z) {
Key key = new Key(x, z);
if (chunks.containsKey(key)) {
return chunks.get(key);
} else {
// only create chunk if it's not in the map already
GlowChunk chunk = new GlowChunk(world, x, z);
chunks.put(key, chunk);
return chunk;
}
}
use of net.glowstone.chunk.GlowChunk.Key in project Glowstone by GlowstoneMC.
the class GlowPlayer method processBlockChanges.
/**
* Process and send pending BlockChangeMessages.
*/
private void processBlockChanges() {
synchronized (blockChanges) {
List<BlockChangeMessage> messages = new ArrayList<>(blockChanges);
blockChanges.clear();
// separate messages by chunk
// inner map is used to only send one entry for same coordinates
Map<Key, Map<BlockVector, BlockChangeMessage>> chunks = new HashMap<>();
for (BlockChangeMessage message : messages) {
if (message != null) {
Key key = new Key(message.getX() >> 4, message.getZ() >> 4);
if (canSeeChunk(key)) {
Map<BlockVector, BlockChangeMessage> map = chunks.computeIfAbsent(key, k -> new HashMap<>());
map.put(new BlockVector(message.getX(), message.getY(), message.getZ()), message);
}
}
}
// send away
for (Map.Entry<Key, Map<BlockVector, BlockChangeMessage>> entry : chunks.entrySet()) {
Key key = entry.getKey();
List<BlockChangeMessage> value = new ArrayList<>(entry.getValue().values());
if (value.size() == 1) {
session.send(value.get(0));
} else if (value.size() > 1) {
session.send(new MultiBlockChangeMessage(key.getX(), key.getZ(), value));
}
}
// now send post-block-change messages
List<Message> postMessages = new ArrayList<>(afterBlockChanges);
afterBlockChanges.clear();
postMessages.forEach(session::send);
}
}
use of net.glowstone.chunk.GlowChunk.Key in project Glowstone by GlowstoneMC.
the class GlowPlayer method streamBlocks.
/**
* Streams chunks to the player's client.
*/
private void streamBlocks() {
Set<Key> previousChunks = new HashSet<>(knownChunks);
ArrayList<Key> newChunks = new ArrayList<>();
int centralX = location.getBlockX() >> 4;
int centralZ = location.getBlockZ() >> 4;
int radius = Math.min(server.getViewDistance(), 1 + settings.getViewDistance());
for (int x = centralX - radius; x <= centralX + radius; x++) {
for (int z = centralZ - radius; z <= centralZ + radius; z++) {
Key key = new Key(x, z);
if (knownChunks.contains(key)) {
previousChunks.remove(key);
} else {
newChunks.add(key);
}
}
}
// early end if there's no changes
if (newChunks.isEmpty() && previousChunks.isEmpty()) {
return;
}
// sort chunks by distance from player - closer chunks sent first
newChunks.sort((a, b) -> {
double dx = 16 * a.getX() + 8 - location.getX();
double dz = 16 * a.getZ() + 8 - location.getZ();
double da = dx * dx + dz * dz;
dx = 16 * b.getX() + 8 - location.getX();
dz = 16 * b.getZ() + 8 - location.getZ();
double db = dx * dx + dz * dz;
return Double.compare(da, db);
});
// first step: force population then acquire lock on each chunk
for (Key key : newChunks) {
world.getChunkManager().forcePopulation(key.getX(), key.getZ());
knownChunks.add(key);
chunkLock.acquire(key);
}
boolean skylight = world.getEnvironment() == Environment.NORMAL;
for (Key key : newChunks) {
GlowChunk chunk = world.getChunkAt(key.getX(), key.getZ());
session.send(chunk.toMessage(skylight));
}
// send visible block entity data
for (Key key : newChunks) {
GlowChunk chunk = world.getChunkAt(key.getX(), key.getZ());
for (BlockEntity entity : chunk.getRawBlockEntities()) {
entity.update(this);
}
}
// and remove old chunks
for (Key key : previousChunks) {
session.send(new UnloadChunkMessage(key.getX(), key.getZ()));
knownChunks.remove(key);
chunkLock.release(key);
}
previousChunks.clear();
}
Aggregations