use of io.xol.chunkstories.api.server.RemotePlayer in project chunkstories by Hugobros3.
the class HeightmapImplementation method setSummaryData.
public void setSummaryData(int[] heightData, int[] voxelData) {
// texturesUpToDate.set(false);
// 512kb per summary, use of max mipmaps for heights
heights = new int[(int) Math.ceil(256 * 256 * (1 + 1 / 3D))];
ids = new int[(int) Math.ceil(256 * 256 * (1 + 1 / 3D))];
System.arraycopy(heightData, 0, heights, 0, 256 * 256);
System.arraycopy(voxelData, 0, ids, 0, 256 * 256);
recomputeMetadata();
summaryLoaded.set(true);
if (world instanceof WorldClient) {
((WorldClient) world).getWorldRenderer().getSummariesTexturesHolder().warnDataHasArrived(regionX, regionZ);
}
// Already have clients waiting for it ? Satisfy these messieurs
usersLock.lock();
for (RemotePlayer user : usersWaitingForIntialData) {
user.pushPacket(new PacketHeightmap(this));
}
usersWaitingForIntialData.clear();
usersLock.unlock();
}
use of io.xol.chunkstories.api.server.RemotePlayer in project chunkstories-api by Hugobros3.
the class PacketEntity method process.
public void process(PacketSender sender, DataInputStream in, PacketReceptionContext processor) throws IOException, UnknownComponentException {
long entityUUID = in.readLong();
short entityTypeID = in.readShort();
if (entityTypeID == -1)
return;
World world = processor.getWorld();
if (world == null)
return;
Entity entity = world.getEntityByUUID(entityUUID);
boolean addToWorld = false;
// Create an entity if the servers tells you to do so
if (entity == null) {
if (world instanceof WorldMaster && sender instanceof RemotePlayer) {
((Player) sender).sendMessage("You are sending packets to the server about a removed entity. Ignoring those.");
return;
} else {
entity = processor.getWorld().getContentTranslator().getEntityForId(entityTypeID).create(// This is technically wrong
new Location(world, 0, 0, 0));
entity.setUUID(entityUUID);
addToWorld = true;
}
}
int componentId = in.readInt();
// Loop throught all components
while (componentId != 0) {
try {
entity.getComponents().tryPullComponentInStream(componentId, sender, in);
} catch (UnknownComponentException e) {
processor.logger().warn(e.getMessage());
}
componentId = in.readInt();
}
// Add to world if it was missing and we didn't receive the despawn flag
if (addToWorld && entity.exists()) {
// Only the WorldMaster is allowed to spawn new entities in the world
if (processor instanceof ClientPacketsProcessor)
processor.getWorld().addEntity(entity);
}
}
use of io.xol.chunkstories.api.server.RemotePlayer in project chunkstories by Hugobros3.
the class ChunkHolderImplementation method registerUser.
@Override
public boolean registerUser(WorldUser user) {
try {
usersLock.lock();
/*boolean ok = */
users.add(user);
// if(!ok)
// System.out.println("warn: adding twice user to ch");
// TODO lock
CubicChunk chunk = this.chunk;
// Chunk already loaded ? Compress and send it immediately
if (user instanceof RemotePlayer) {
RemotePlayer player = (RemotePlayer) user;
if (chunk != null) {
// TODO recompress chunk data each tick it's needed
player.pushPacket(new PacketChunkCompressedData(chunk, this.getCompressedData()));
} else {
usersWaitingForIntialData.add(player);
}
}
// This runs under a lock so we can afford to be lazy about thread safety
if (chunk == null && loadChunkTask == null) {
// We create a task only if one isn't already ongoing.
loadChunkTask = getRegion().getWorld().ioHandler.requestChunkLoad(this);
}
return true;
} finally {
usersLock.unlock();
}
}
use of io.xol.chunkstories.api.server.RemotePlayer in project chunkstories by Hugobros3.
the class ChunkHolderImplementation method createChunk.
public CubicChunk createChunk(CompressedData data) {
this.chunkLock.writeLock().lock();
if (this.chunk != null) {
System.out.println("Warning: creating a chunk but the chunkholder already had one, ignoring");
this.chunkLock.writeLock().unlock();
return this.chunk;
}
CubicChunk chunk;
if (region.world instanceof WorldClient) {
chunk = createClientChunk(this, x, y, z, data);
// chunk = data == null ? new ClientChunk(this, x, y, z) : new ClientChunk(this, x, y, z, data);
} else
chunk = data == null ? new CubicChunk(this, x, y, z) : new CubicChunk(this, x, y, z, data);
if (this.chunk == null && chunk != null)
regionLoadedChunks.add(chunk);
this.chunk = chunk;
if (region.getWorld() instanceof WorldClient)
((WorldClient) region.getWorld()).getWorldRenderer().flagChunksModified();
this.chunkLock.writeLock().unlock();
// Already have clients waiting for it ? Satisfy these messieurs
usersLock.lock();
for (RemotePlayer user : usersWaitingForIntialData) {
user.pushPacket(new PacketChunkCompressedData(chunk, data));
}
usersWaitingForIntialData.clear();
usersLock.unlock();
return chunk;
}
use of io.xol.chunkstories.api.server.RemotePlayer in project chunkstories by Hugobros3.
the class CubicChunk method pokeInternal.
/**
* The 'core' of the core, this private function is responsible for placing and
* keeping everyone up to snuff on block modifications. It all comes back to this really.
*/
private ActualChunkVoxelContext pokeInternal(final int worldX, final int worldY, final int worldZ, Voxel newVoxel, final int sunlight, final int blocklight, final int metadata, int raw_data, final boolean use_raw_data, final boolean update, final boolean return_context, final WorldModificationCause cause) {
int x = sanitizeCoordinate(worldX);
int y = sanitizeCoordinate(worldY);
int z = sanitizeCoordinate(worldZ);
ActualChunkVoxelContext cell_pre = peek(x, y, z);
Voxel formerVoxel = cell_pre.getVoxel();
assert formerVoxel != null;
FreshFutureCell future = new FreshFutureCell(cell_pre);
if (use_raw_data) {
// We need this for voxel placement logic
newVoxel = world.getContentTranslator().getVoxelForId(VoxelFormat.id(raw_data));
// Build the future from parsing the raw data
future.setVoxel(newVoxel);
future.setSunlight(VoxelFormat.sunlight(raw_data));
future.setBlocklight(VoxelFormat.blocklight(raw_data));
future.setMetaData(VoxelFormat.meta(raw_data));
} else {
// Build the raw data from the set parameters by editing the in-place data
// (because we allow only editing some aspects of the cell data)
raw_data = cell_pre.getData();
if (newVoxel != null) {
raw_data = VoxelFormat.changeId(raw_data, world.getContentTranslator().getIdForVoxel(newVoxel));
future.setVoxel(newVoxel);
}
if (sunlight >= 0) {
raw_data = VoxelFormat.changeSunlight(raw_data, sunlight);
future.setSunlight(sunlight);
}
if (blocklight >= 0) {
raw_data = VoxelFormat.changeBlocklight(raw_data, blocklight);
future.setBlocklight(blocklight);
}
if (metadata >= 0) {
raw_data = VoxelFormat.changeMeta(raw_data, metadata);
future.setMetaData(metadata);
}
}
try {
if (newVoxel == null || formerVoxel.equals(newVoxel)) {
formerVoxel.onModification(cell_pre, future, cause);
} else {
formerVoxel.onRemove(cell_pre, cause);
newVoxel.onPlace(future, cause);
}
} catch (WorldException e) {
// Abort !
if (return_context)
return cell_pre;
else
return null;
}
// Allocate if it makes sense
if (chunkVoxelData == null)
chunkVoxelData = atomicalyCreateInternalData();
chunkVoxelData[x * 32 * 32 + y * 32 + z] = raw_data;
if (newVoxel != null && !formerVoxel.equals(newVoxel))
newVoxel.whenPlaced(future);
// Update lightning
if (update)
lightBaker.computeLightSpread(x, y, z, cell_pre.raw_data, raw_data);
// Increment the modifications counter
compr_uncomittedBlockModifications.incrementAndGet();
// Don't spam the thread creation spawn
occlusion.unbakedUpdates.incrementAndGet();
// Update related summary
if (update)
world.getRegionsSummariesHolder().updateOnBlockPlaced(x, y, z, future);
// Mark the nearby chunks to be re-rendered
if (update) {
int sx = chunkX;
int ex = sx;
int sy = chunkY;
int ey = sy;
int sz = chunkZ;
int ez = sz;
if (x == 0)
sx--;
else if (x == 31)
ex++;
if (y == 0)
sy--;
else if (y == 31)
ey++;
if (z == 0)
sz--;
else if (z == 31)
ez++;
for (int ix = sx; ix <= ex; ix++) for (int iy = sy; iy <= ey; iy++) for (int iz = sz; iz <= ez; iz++) {
Chunk chunk = world.getChunk(ix, iy, iz);
if (chunk != null && chunk instanceof ChunkRenderable)
((ChunkRenderable) chunk).meshUpdater().requestMeshUpdate();
}
}
// If this is a 'master' world, notify remote users of the change !
if (update && world instanceof WorldMaster && !(world instanceof WorldTool)) {
PacketVoxelUpdate packet = new PacketVoxelUpdate(new ActualChunkVoxelContext(chunkX * 32 + x, chunkY * 32 + y, chunkZ * 32 + z, raw_data));
Iterator<WorldUser> pi = this.chunkHolder.users.iterator();
while (pi.hasNext()) {
WorldUser user = pi.next();
if (!(user instanceof RemotePlayer))
continue;
RemotePlayer player = (RemotePlayer) user;
Entity clientEntity = player.getControlledEntity();
if (clientEntity == null)
// Ignore clients that aren't playing
continue;
player.pushPacket(packet);
}
}
if (return_context)
return new ActualChunkVoxelContext(chunkX * 32 + x, chunkY * 32 + y, chunkZ * 32 + z, raw_data);
else
return null;
}
Aggregations