PlayerChunkSender.java
net.minecraft.server.network.PlayerChunkSender
信息
- 全限定名:net.minecraft.server.network.PlayerChunkSender
- 类型:public class
- 包:net.minecraft.server.network
- 源码路径:src/main/java/net/minecraft/server/network/PlayerChunkSender.java
- 起始行号:L23
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L24 - 说明:
TODO
- 类型:
-
MIN_CHUNKS_PER_TICK- 类型:
float - 修饰符:
public static final - 源码定位:
L25 - 说明:
TODO
- 类型:
-
MAX_CHUNKS_PER_TICK- 类型:
float - 修饰符:
public static final - 源码定位:
L26 - 说明:
TODO
- 类型:
-
START_CHUNKS_PER_TICK- 类型:
float - 修饰符:
private static final - 源码定位:
L27 - 说明:
TODO
- 类型:
-
MAX_UNACKNOWLEDGED_BATCHES- 类型:
int - 修饰符:
private static final - 源码定位:
L28 - 说明:
TODO
- 类型:
-
pendingChunks- 类型:
LongSet - 修饰符:
private final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
memoryConnection- 类型:
boolean - 修饰符:
private final - 源码定位:
L30 - 说明:
TODO
- 类型:
-
desiredChunksPerTick- 类型:
float - 修饰符:
private - 源码定位:
L31 - 说明:
TODO
- 类型:
-
batchQuota- 类型:
float - 修饰符:
private - 源码定位:
L32 - 说明:
TODO
- 类型:
-
unacknowledgedBatches- 类型:
int - 修饰符:
private - 源码定位:
L33 - 说明:
TODO
- 类型:
-
maxUnacknowledgedBatches- 类型:
int - 修饰符:
private - 源码定位:
L34 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public PlayerChunkSender(boolean memoryConnection) @ L36
- 构造器名:PlayerChunkSender
- 源码定位:L36
- 修饰符:public
参数:
- memoryConnection: boolean
说明:
TODO
方法
下面的方法块按源码顺序生成。
public void markChunkPendingToSend(LevelChunk chunk) @ L40
- 方法名:markChunkPendingToSend
- 源码定位:L40
- 返回类型:void
- 修饰符:public
参数:
- chunk: LevelChunk
说明:
TODO
public void dropChunk(ServerPlayer player, ChunkPos pos) @ L44
- 方法名:dropChunk
- 源码定位:L44
- 返回类型:void
- 修饰符:public
参数:
- player: ServerPlayer
- pos: ChunkPos
说明:
TODO
public void sendNextChunks(ServerPlayer player) @ L50
- 方法名:sendNextChunks
- 源码定位:L50
- 返回类型:void
- 修饰符:public
参数:
- player: ServerPlayer
说明:
TODO
private static void sendChunk(ServerGamePacketListenerImpl connection, ServerLevel level, LevelChunk chunk) @ L76
- 方法名:sendChunk
- 源码定位:L76
- 返回类型:void
- 修饰符:private static
参数:
- connection: ServerGamePacketListenerImpl
- level: ServerLevel
- chunk: LevelChunk
说明:
TODO
private List<LevelChunk> collectChunksToSend(ChunkMap chunkMap, ChunkPos playerPos) @ L86
- 方法名:collectChunksToSend
- 源码定位:L86
- 返回类型:List
- 修饰符:private
参数:
- chunkMap: ChunkMap
- playerPos: ChunkPos
说明:
TODO
public void onChunkBatchReceivedByClient(float desiredChunksPerTick) @ L114
- 方法名:onChunkBatchReceivedByClient
- 源码定位:L114
- 返回类型:void
- 修饰符:public
参数:
- desiredChunksPerTick: float
说明:
TODO
public boolean isPending(long pos) @ L124
- 方法名:isPending
- 源码定位:L124
- 返回类型:boolean
- 修饰符:public
参数:
- pos: long
说明:
TODO
代码
public class PlayerChunkSender {
private static final Logger LOGGER = LogUtils.getLogger();
public static final float MIN_CHUNKS_PER_TICK = 0.01F;
public static final float MAX_CHUNKS_PER_TICK = 64.0F;
private static final float START_CHUNKS_PER_TICK = 9.0F;
private static final int MAX_UNACKNOWLEDGED_BATCHES = 10;
private final LongSet pendingChunks = new LongOpenHashSet();
private final boolean memoryConnection;
private float desiredChunksPerTick = 9.0F;
private float batchQuota;
private int unacknowledgedBatches;
private int maxUnacknowledgedBatches = 1;
public PlayerChunkSender(boolean memoryConnection) {
this.memoryConnection = memoryConnection;
}
public void markChunkPendingToSend(LevelChunk chunk) {
this.pendingChunks.add(chunk.getPos().pack());
}
public void dropChunk(ServerPlayer player, ChunkPos pos) {
if (!this.pendingChunks.remove(pos.pack()) && player.isAlive()) {
player.connection.send(new ClientboundForgetLevelChunkPacket(pos));
}
}
public void sendNextChunks(ServerPlayer player) {
if (this.unacknowledgedBatches < this.maxUnacknowledgedBatches) {
float maxBatchSize = Math.max(1.0F, this.desiredChunksPerTick);
this.batchQuota = Math.min(this.batchQuota + this.desiredChunksPerTick, maxBatchSize);
if (!(this.batchQuota < 1.0F)) {
if (!this.pendingChunks.isEmpty()) {
ServerLevel level = player.level();
ChunkMap chunkMap = level.getChunkSource().chunkMap;
List<LevelChunk> chunksToSend = this.collectChunksToSend(chunkMap, player.chunkPosition());
if (!chunksToSend.isEmpty()) {
ServerGamePacketListenerImpl connection = player.connection;
this.unacknowledgedBatches++;
connection.send(ClientboundChunkBatchStartPacket.INSTANCE);
for (LevelChunk chunk : chunksToSend) {
sendChunk(connection, level, chunk);
}
connection.send(new ClientboundChunkBatchFinishedPacket(chunksToSend.size()));
this.batchQuota = this.batchQuota - chunksToSend.size();
}
}
}
}
}
private static void sendChunk(ServerGamePacketListenerImpl connection, ServerLevel level, LevelChunk chunk) {
connection.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null));
ChunkPos pos = chunk.getPos();
if (SharedConstants.DEBUG_VERBOSE_SERVER_EVENTS) {
LOGGER.debug("SEN {}", pos);
}
level.debugSynchronizers().startTrackingChunk(connection.player, chunk.getPos());
}
private List<LevelChunk> collectChunksToSend(ChunkMap chunkMap, ChunkPos playerPos) {
int maxBatchSize = Mth.floor(this.batchQuota);
List<LevelChunk> chunks;
if (!this.memoryConnection && this.pendingChunks.size() > maxBatchSize) {
chunks = this.pendingChunks
.stream()
.collect(Comparators.least(maxBatchSize, Comparator.comparingInt(playerPos::distanceSquared)))
.stream()
.mapToLong(Long::longValue)
.mapToObj(chunkMap::getChunkToSend)
.filter(Objects::nonNull)
.toList();
} else {
chunks = this.pendingChunks
.longStream()
.mapToObj(chunkMap::getChunkToSend)
.filter(Objects::nonNull)
.sorted(Comparator.comparingInt(chunkx -> playerPos.distanceSquared(chunkx.getPos())))
.toList();
}
for (LevelChunk chunk : chunks) {
this.pendingChunks.remove(chunk.getPos().pack());
}
return chunks;
}
public void onChunkBatchReceivedByClient(float desiredChunksPerTick) {
this.unacknowledgedBatches--;
this.desiredChunksPerTick = Double.isNaN(desiredChunksPerTick) ? 0.01F : Mth.clamp(desiredChunksPerTick, 0.01F, 64.0F);
if (this.unacknowledgedBatches == 0) {
this.batchQuota = 1.0F;
}
this.maxUnacknowledgedBatches = 10;
}
public boolean isPending(long pos) {
return this.pendingChunks.contains(pos);
}
}引用的其他类
-
ClientboundChunkBatchFinishedPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundChunkBatchFinishedPacket()
- 引用位置:
-
ClientboundForgetLevelChunkPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundForgetLevelChunkPacket()
- 引用位置:
-
ClientboundLevelChunkWithLightPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundLevelChunkWithLightPacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.clamp(), Mth.floor()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置: