mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-24 09:01:54 +01:00
send individual section updates when less than half of the sections are updated.
This commit is contained in:
parent
5bedee2795
commit
d0163ae749
@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
// TODO light data & API
|
// TODO light data & API
|
||||||
|
|
||||||
@ -546,6 +547,23 @@ public abstract class Chunk implements Viewable, DataContainer {
|
|||||||
PacketUtils.sendGroupedPacket(getViewers(), getFreshFullDataPacket());
|
PacketUtils.sendGroupedPacket(getViewers(), getFreshFullDataPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a single section {@link ChunkDataPacket} to all chunk viewers.
|
||||||
|
*
|
||||||
|
* @param section The section to send.
|
||||||
|
*/
|
||||||
|
public synchronized void sendChunkSectionUpdate(int section) {
|
||||||
|
Check.argCondition(!MathUtils.isBetween(section, 0, CHUNK_SECTION_COUNT),
|
||||||
|
"The chunk section " + section + " does not exist");
|
||||||
|
PacketUtils.sendGroupedPacket(
|
||||||
|
//todo An option to filter out non-netty clients in sendGroupedPacket would be nice.
|
||||||
|
getViewers()
|
||||||
|
.stream()
|
||||||
|
.filter(PlayerUtils::isNettyClient)
|
||||||
|
.collect(Collectors.toUnmodifiableList()),
|
||||||
|
createChunkSectionUpdatePacket(section));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a chunk section update packet to {@code player}.
|
* Sends a chunk section update packet to {@code player}.
|
||||||
*
|
*
|
||||||
|
@ -2,6 +2,8 @@ package net.minestom.server.instance.batch;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArraySet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
import it.unimi.dsi.fastutil.longs.LongList;
|
import it.unimi.dsi.fastutil.longs.LongList;
|
||||||
import net.minestom.server.data.Data;
|
import net.minestom.server.data.Data;
|
||||||
@ -18,6 +20,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Batch used when all of the block changed are contained inside a single chunk.
|
* A Batch used when all of the block changed are contained inside a single chunk.
|
||||||
@ -32,8 +35,10 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
* @see Batch
|
* @see Batch
|
||||||
*/
|
*/
|
||||||
public class ChunkBatch implements Batch<ChunkCallback> {
|
public class ChunkBatch implements Batch<ChunkCallback> {
|
||||||
|
private static final int CHUNK_SECTION_THRESHOLD = Chunk.CHUNK_SECTION_COUNT / 2;
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChunkBatch.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ChunkBatch.class);
|
||||||
|
|
||||||
|
|
||||||
// Need to be synchronized manually
|
// Need to be synchronized manually
|
||||||
// Format: blockIndex/blockStateId/customBlockId (32/16/16 bits)
|
// Format: blockIndex/blockStateId/customBlockId (32/16/16 bits)
|
||||||
private final LongList blocks;
|
private final LongList blocks;
|
||||||
@ -199,14 +204,16 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final IntSet sections = new IntArraySet();
|
||||||
synchronized (blocks) {
|
synchronized (blocks) {
|
||||||
for (long block : blocks) {
|
for (long block : blocks) {
|
||||||
apply(chunk, block, inverse);
|
final int section = apply(chunk, block, inverse);
|
||||||
|
sections.add(section);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inverse != null) inverse.readyLatch.countDown();
|
if (inverse != null) inverse.readyLatch.countDown();
|
||||||
updateChunk(instance, chunk, callback, safeCallback);
|
updateChunk(instance, chunk, sections, callback, safeCallback);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -217,8 +224,9 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
|||||||
*
|
*
|
||||||
* @param chunk The chunk to apply the change
|
* @param chunk The chunk to apply the change
|
||||||
* @param value block index|state id|custom block id (32|16|16 bits)
|
* @param value block index|state id|custom block id (32|16|16 bits)
|
||||||
|
* @return The chunk section which the block was placed
|
||||||
*/
|
*/
|
||||||
private void apply(@NotNull Chunk chunk, long value, @Nullable ChunkBatch inverse) {
|
private int apply(@NotNull Chunk chunk, long value, @Nullable ChunkBatch inverse) {
|
||||||
final short customBlockId = (short) (value & 0xFFFF);
|
final short customBlockId = (short) (value & 0xFFFF);
|
||||||
final short blockId = (short) ((value >> 16) & 0xFFFF);
|
final short blockId = (short) ((value >> 16) & 0xFFFF);
|
||||||
final int index = (int) ((value >> 32) & 0xFFFFFFFFL);
|
final int index = (int) ((value >> 32) & 0xFFFFFFFFL);
|
||||||
@ -238,18 +246,21 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
|||||||
inverse.setSeparateBlocks(x, y, z, chunk.getBlockStateId(x, y, z), chunk.getCustomBlockId(x, y, z), chunk.getBlockData(index));
|
inverse.setSeparateBlocks(x, y, z, chunk.getBlockStateId(x, y, z), chunk.getCustomBlockId(x, y, z), chunk.getBlockData(index));
|
||||||
|
|
||||||
chunk.UNSAFE_setBlock(x, y, z, blockId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
|
chunk.UNSAFE_setBlock(x, y, z, blockId, customBlockId, data, CustomBlockUtils.hasUpdate(customBlockId));
|
||||||
|
return ChunkUtils.getSectionAt(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the given chunk for all of its viewers, and executes the callback.
|
* Updates the given chunk for all of its viewers, and executes the callback.
|
||||||
*/
|
*/
|
||||||
private void updateChunk(@NotNull Instance instance, Chunk chunk, @Nullable ChunkCallback callback, boolean safeCallback) {
|
private void updateChunk(@NotNull Instance instance, Chunk chunk, IntSet sections, @Nullable ChunkCallback callback, boolean safeCallback) {
|
||||||
// Refresh chunk for viewers
|
// Refresh chunk for viewers
|
||||||
|
if (sections.size() <= CHUNK_SECTION_THRESHOLD) {
|
||||||
// Formerly this had an option to do a Chunk#sendChunkUpdate
|
// Update only a few sections of the chunk
|
||||||
// however Chunk#sendChunk does the same including a light update
|
sections.forEach((IntConsumer) chunk::sendChunkSectionUpdate);
|
||||||
chunk.sendChunkUpdate();
|
} else {
|
||||||
//chunk.sendChunk();
|
// Update the entire chunk
|
||||||
|
chunk.sendChunk();
|
||||||
|
}
|
||||||
|
|
||||||
if (instance instanceof InstanceContainer) {
|
if (instance instanceof InstanceContainer) {
|
||||||
// FIXME: put method in Instance instead
|
// FIXME: put method in Instance instead
|
||||||
|
@ -37,8 +37,8 @@ public class CubeBatchCommand extends Command {
|
|||||||
Player player = sender.asPlayer();
|
Player player = sender.asPlayer();
|
||||||
InstanceContainer instance = (InstanceContainer) player.getInstance();
|
InstanceContainer instance = (InstanceContainer) player.getInstance();
|
||||||
|
|
||||||
// applyChunkShape(instance);
|
applyChunkShape(instance);
|
||||||
applyBlockShape(instance);
|
// applyBlockShape(instance);
|
||||||
|
|
||||||
// AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
// AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||||
//
|
//
|
||||||
|
Loading…
Reference in New Issue
Block a user