TrackingDebugSynchronizer.java
net.minecraft.util.debug.TrackingDebugSynchronizer
信息
- 全限定名:net.minecraft.util.debug.TrackingDebugSynchronizer
- 类型:public abstract class
- 包:net.minecraft.util.debug
- 源码路径:src/main/java/net/minecraft/util/debug/TrackingDebugSynchronizer.java
- 起始行号:L28
- 职责:
TODO
字段/常量
-
subscription- 类型:
DebugSubscription<T> - 修饰符:
protected final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
subscribedPlayers- 类型:
Set<UUID> - 修饰符:
private final - 源码定位:
L30 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.util.debug.TrackingDebugSynchronizer.PoiSynchronizer- 类型:
class - 修饰符:
public static - 源码定位:
L104 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.PoiSynchronizer.->- 类型:
record - 修饰符:
package-private - 源码定位:
L115 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.PoiSynchronizer.)- 类型:
record - 修饰符:
public - 源码定位:
L120 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.PoiSynchronizer.)..- 类型:
record - 修饰符:
package-private - 源码定位:
L123 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.SourceSynchronizer- 类型:
class - 修饰符:
public static - 源码定位:
L141 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.ValueSource- 类型:
class - 修饰符:
private static - 源码定位:
L241 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.VillageSectionSynchronizer- 类型:
class - 修饰符:
public static - 源码定位:
L260 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.VillageSectionSynchronizer.->- 类型:
record - 修饰符:
package-private - 源码定位:
L271 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.VillageSectionSynchronizer.->..- 类型:
record - 修饰符:
package-private - 源码定位:
L272 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.VillageSectionSynchronizer.)- 类型:
record - 修饰符:
public - 源码定位:
L286 - 说明:
TODO
- 类型:
-
net.minecraft.util.debug.TrackingDebugSynchronizer.VillageSectionSynchronizer.)..- 类型:
record - 修饰符:
package-private - 源码定位:
L287 - 说明:
TODO
- 类型:
构造器
public TrackingDebugSynchronizer(DebugSubscription<T> subscription) @ L32
- 构造器名:TrackingDebugSynchronizer
- 源码定位:L32
- 修饰符:public
参数:
- subscription: DebugSubscription
说明:
TODO
方法
下面的方法块按源码顺序生成。
public final void tick(ServerLevel level) @ L36
- 方法名:tick
- 源码定位:L36
- 返回类型:void
- 修饰符:public final
参数:
- level: ServerLevel
说明:
TODO
private void addSubscriber(ServerPlayer player) @ L55
- 方法名:addSubscriber
- 源码定位:L55
- 返回类型:void
- 修饰符:private
参数:
- player: ServerPlayer
说明:
TODO
protected final void sendToPlayersTrackingChunk(ServerLevel level, ChunkPos trackedChunk, Packet<?super ClientGamePacketListener> packet) @ L65
- 方法名:sendToPlayersTrackingChunk
- 源码定位:L65
- 返回类型:void
- 修饰符:protected final
参数:
- level: ServerLevel
- trackedChunk: ChunkPos
- packet: Packet<?super ClientGamePacketListener>
说明:
TODO
protected final void sendToPlayersTrackingEntity(ServerLevel level, Entity trackedEntity, Packet<?super ClientGamePacketListener> packet) @ L75
- 方法名:sendToPlayersTrackingEntity
- 源码定位:L75
- 返回类型:void
- 修饰符:protected final
参数:
- level: ServerLevel
- trackedEntity: Entity
- packet: Packet<?super ClientGamePacketListener>
说明:
TODO
public final void startTrackingChunk(ServerPlayer player, ChunkPos chunkPos) @ L80
- 方法名:startTrackingChunk
- 源码定位:L80
- 返回类型:void
- 修饰符:public final
参数:
- player: ServerPlayer
- chunkPos: ChunkPos
说明:
TODO
public final void startTrackingEntity(ServerPlayer player, Entity entity) @ L86
- 方法名:startTrackingEntity
- 源码定位:L86
- 返回类型:void
- 修饰符:public final
参数:
- player: ServerPlayer
- entity: Entity
说明:
TODO
protected void clear() @ L92
- 方法名:clear
- 源码定位:L92
- 返回类型:void
- 修饰符:protected
参数:
- 无
说明:
TODO
protected void pollAndSendUpdates(ServerLevel level) @ L95
- 方法名:pollAndSendUpdates
- 源码定位:L95
- 返回类型:void
- 修饰符:protected
参数:
- level: ServerLevel
说明:
TODO
protected void sendInitialChunk(ServerPlayer player, ChunkPos chunkPos) @ L98
- 方法名:sendInitialChunk
- 源码定位:L98
- 返回类型:void
- 修饰符:protected
参数:
- player: ServerPlayer
- chunkPos: ChunkPos
说明:
TODO
protected void sendInitialEntity(ServerPlayer player, Entity entity) @ L101
- 方法名:sendInitialEntity
- 源码定位:L101
- 返回类型:void
- 修饰符:protected
参数:
- player: ServerPlayer
- entity: Entity
说明:
TODO
代码
public abstract class TrackingDebugSynchronizer<T> {
protected final DebugSubscription<T> subscription;
private final Set<UUID> subscribedPlayers = new ObjectOpenHashSet<>();
public TrackingDebugSynchronizer(DebugSubscription<T> subscription) {
this.subscription = subscription;
}
public final void tick(ServerLevel level) {
for (ServerPlayer player : level.players()) {
boolean wasSubscribed = this.subscribedPlayers.contains(player.getUUID());
boolean isSubscribed = player.debugSubscriptions().contains(this.subscription);
if (isSubscribed != wasSubscribed) {
if (isSubscribed) {
this.addSubscriber(player);
} else {
this.subscribedPlayers.remove(player.getUUID());
}
}
}
this.subscribedPlayers.removeIf(id -> level.getPlayerByUUID(id) == null);
if (!this.subscribedPlayers.isEmpty()) {
this.pollAndSendUpdates(level);
}
}
private void addSubscriber(ServerPlayer player) {
this.subscribedPlayers.add(player.getUUID());
player.getChunkTrackingView().forEach(chunkPos -> {
if (!player.connection.chunkSender.isPending(chunkPos.pack())) {
this.startTrackingChunk(player, chunkPos);
}
});
player.level().getChunkSource().chunkMap.forEachEntityTrackedBy(player, entity -> this.startTrackingEntity(player, entity));
}
protected final void sendToPlayersTrackingChunk(ServerLevel level, ChunkPos trackedChunk, Packet<? super ClientGamePacketListener> packet) {
ChunkMap chunkMap = level.getChunkSource().chunkMap;
for (UUID playerId : this.subscribedPlayers) {
if (level.getPlayerByUUID(playerId) instanceof ServerPlayer player && chunkMap.isChunkTracked(player, trackedChunk.x(), trackedChunk.z())) {
player.connection.send(packet);
}
}
}
protected final void sendToPlayersTrackingEntity(ServerLevel level, Entity trackedEntity, Packet<? super ClientGamePacketListener> packet) {
ChunkMap chunkMap = level.getChunkSource().chunkMap;
chunkMap.sendToTrackingPlayersFiltered(trackedEntity, packet, player -> this.subscribedPlayers.contains(player.getUUID()));
}
public final void startTrackingChunk(ServerPlayer player, ChunkPos chunkPos) {
if (this.subscribedPlayers.contains(player.getUUID())) {
this.sendInitialChunk(player, chunkPos);
}
}
public final void startTrackingEntity(ServerPlayer player, Entity entity) {
if (this.subscribedPlayers.contains(player.getUUID())) {
this.sendInitialEntity(player, entity);
}
}
protected void clear() {
}
protected void pollAndSendUpdates(ServerLevel level) {
}
protected void sendInitialChunk(ServerPlayer player, ChunkPos chunkPos) {
}
protected void sendInitialEntity(ServerPlayer player, Entity entity) {
}
public static class PoiSynchronizer extends TrackingDebugSynchronizer<DebugPoiInfo> {
public PoiSynchronizer() {
super(DebugSubscriptions.POIS);
}
@Override
protected void sendInitialChunk(ServerPlayer player, ChunkPos chunkPos) {
ServerLevel level = player.level();
PoiManager poiManager = level.getPoiManager();
poiManager.getInChunk(t -> true, chunkPos, PoiManager.Occupancy.ANY)
.forEach(
record -> player.connection
.send(new ClientboundDebugBlockValuePacket(record.getPos(), this.subscription.packUpdate(new DebugPoiInfo(record))))
);
}
public void onPoiAdded(ServerLevel level, PoiRecord record) {
this.sendToPlayersTrackingChunk(
level,
ChunkPos.containing(record.getPos()),
new ClientboundDebugBlockValuePacket(record.getPos(), this.subscription.packUpdate(new DebugPoiInfo(record)))
);
}
public void onPoiRemoved(ServerLevel level, BlockPos poiPos) {
this.sendToPlayersTrackingChunk(level, ChunkPos.containing(poiPos), new ClientboundDebugBlockValuePacket(poiPos, this.subscription.emptyUpdate()));
}
public void onPoiTicketCountChanged(ServerLevel level, BlockPos poiPos) {
this.sendToPlayersTrackingChunk(
level,
ChunkPos.containing(poiPos),
new ClientboundDebugBlockValuePacket(poiPos, this.subscription.packUpdate(level.getPoiManager().getDebugPoiInfo(poiPos)))
);
}
}
public static class SourceSynchronizer<T> extends TrackingDebugSynchronizer<T> {
private final Map<ChunkPos, TrackingDebugSynchronizer.ValueSource<T>> chunkSources = new HashMap<>();
private final Map<BlockPos, TrackingDebugSynchronizer.ValueSource<T>> blockEntitySources = new HashMap<>();
private final Map<UUID, TrackingDebugSynchronizer.ValueSource<T>> entitySources = new HashMap<>();
public SourceSynchronizer(DebugSubscription<T> subscription) {
super(subscription);
}
@Override
protected void clear() {
this.chunkSources.clear();
this.blockEntitySources.clear();
this.entitySources.clear();
}
@Override
protected void pollAndSendUpdates(ServerLevel level) {
for (Entry<ChunkPos, TrackingDebugSynchronizer.ValueSource<T>> entry : this.chunkSources.entrySet()) {
DebugSubscription.Update<T> update = entry.getValue().pollUpdate(this.subscription);
if (update != null) {
ChunkPos chunkPos = entry.getKey();
this.sendToPlayersTrackingChunk(level, chunkPos, new ClientboundDebugChunkValuePacket(chunkPos, update));
}
}
for (Entry<BlockPos, TrackingDebugSynchronizer.ValueSource<T>> entryx : this.blockEntitySources.entrySet()) {
DebugSubscription.Update<T> update = entryx.getValue().pollUpdate(this.subscription);
if (update != null) {
BlockPos blockPos = entryx.getKey();
ChunkPos chunkPos = ChunkPos.containing(blockPos);
this.sendToPlayersTrackingChunk(level, chunkPos, new ClientboundDebugBlockValuePacket(blockPos, update));
}
}
for (Entry<UUID, TrackingDebugSynchronizer.ValueSource<T>> entryxx : this.entitySources.entrySet()) {
DebugSubscription.Update<T> update = entryxx.getValue().pollUpdate(this.subscription);
if (update != null) {
Entity entity = Objects.requireNonNull(level.getEntity(entryxx.getKey()));
this.sendToPlayersTrackingEntity(level, entity, new ClientboundDebugEntityValuePacket(entity.getId(), update));
}
}
}
public void registerChunk(ChunkPos chunkPos, DebugValueSource.ValueGetter<T> getter) {
this.chunkSources.put(chunkPos, new TrackingDebugSynchronizer.ValueSource<>(getter));
}
public void registerBlockEntity(BlockPos blockPos, DebugValueSource.ValueGetter<T> getter) {
this.blockEntitySources.put(blockPos, new TrackingDebugSynchronizer.ValueSource<>(getter));
}
public void registerEntity(UUID entityId, DebugValueSource.ValueGetter<T> getter) {
this.entitySources.put(entityId, new TrackingDebugSynchronizer.ValueSource<>(getter));
}
public void dropChunk(ChunkPos chunkPos) {
this.chunkSources.remove(chunkPos);
this.blockEntitySources.keySet().removeIf(chunkPos::contains);
}
public void dropBlockEntity(ServerLevel level, BlockPos blockPos) {
TrackingDebugSynchronizer.ValueSource<T> source = this.blockEntitySources.remove(blockPos);
if (source != null) {
ChunkPos chunkPos = ChunkPos.containing(blockPos);
this.sendToPlayersTrackingChunk(level, chunkPos, new ClientboundDebugBlockValuePacket(blockPos, this.subscription.emptyUpdate()));
}
}
public void dropEntity(Entity entity) {
this.entitySources.remove(entity.getUUID());
}
@Override
protected void sendInitialChunk(ServerPlayer player, ChunkPos chunkPos) {
TrackingDebugSynchronizer.ValueSource<T> chunkSource = this.chunkSources.get(chunkPos);
if (chunkSource != null && chunkSource.lastSyncedValue != null) {
player.connection.send(new ClientboundDebugChunkValuePacket(chunkPos, this.subscription.packUpdate(chunkSource.lastSyncedValue)));
}
for (Entry<BlockPos, TrackingDebugSynchronizer.ValueSource<T>> entry : this.blockEntitySources.entrySet()) {
T lastValue = entry.getValue().lastSyncedValue;
if (lastValue != null) {
BlockPos blockPos = entry.getKey();
if (chunkPos.contains(blockPos)) {
player.connection.send(new ClientboundDebugBlockValuePacket(blockPos, this.subscription.packUpdate(lastValue)));
}
}
}
}
@Override
protected void sendInitialEntity(ServerPlayer player, Entity entity) {
TrackingDebugSynchronizer.ValueSource<T> source = this.entitySources.get(entity.getUUID());
if (source != null && source.lastSyncedValue != null) {
player.connection.send(new ClientboundDebugEntityValuePacket(entity.getId(), this.subscription.packUpdate(source.lastSyncedValue)));
}
}
}
private static class ValueSource<T> {
private final DebugValueSource.ValueGetter<T> getter;
private @Nullable T lastSyncedValue;
private ValueSource(DebugValueSource.ValueGetter<T> getter) {
this.getter = getter;
}
public DebugSubscription.@Nullable Update<T> pollUpdate(DebugSubscription<T> subscription) {
T newValue = this.getter.get();
if (!Objects.equals(newValue, this.lastSyncedValue)) {
this.lastSyncedValue = newValue;
return subscription.packUpdate(newValue);
} else {
return null;
}
}
}
public static class VillageSectionSynchronizer extends TrackingDebugSynchronizer<Unit> {
public VillageSectionSynchronizer() {
super(DebugSubscriptions.VILLAGE_SECTIONS);
}
@Override
protected void sendInitialChunk(ServerPlayer player, ChunkPos chunkPos) {
ServerLevel level = player.level();
PoiManager poiManager = level.getPoiManager();
poiManager.getInChunk(t -> true, chunkPos, PoiManager.Occupancy.ANY)
.forEach(
record -> {
SectionPos centerSection = SectionPos.of(record.getPos());
forEachVillageSectionUpdate(
level,
centerSection,
(sectionPos, isVillage) -> {
BlockPos sectionBlockPos = sectionPos.center();
player.connection
.send(new ClientboundDebugBlockValuePacket(sectionBlockPos, this.subscription.packUpdate(isVillage ? Unit.INSTANCE : null)));
}
);
}
);
}
public void onPoiAdded(ServerLevel level, PoiRecord record) {
this.sendVillageSectionsPacket(level, record.getPos());
}
public void onPoiRemoved(ServerLevel level, BlockPos poiPos) {
this.sendVillageSectionsPacket(level, poiPos);
}
private void sendVillageSectionsPacket(ServerLevel level, BlockPos poiPos) {
forEachVillageSectionUpdate(
level,
SectionPos.of(poiPos),
(sectionPos, isVillage) -> {
BlockPos sectionBlockPos = sectionPos.center();
if (isVillage) {
this.sendToPlayersTrackingChunk(
level,
ChunkPos.containing(sectionBlockPos),
new ClientboundDebugBlockValuePacket(sectionBlockPos, this.subscription.packUpdate(Unit.INSTANCE))
);
} else {
this.sendToPlayersTrackingChunk(
level, ChunkPos.containing(sectionBlockPos), new ClientboundDebugBlockValuePacket(sectionBlockPos, this.subscription.emptyUpdate())
);
}
}
);
}
private static void forEachVillageSectionUpdate(ServerLevel level, SectionPos centerSection, BiConsumer<SectionPos, Boolean> consumer) {
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
for (int offsetX = -1; offsetX <= 1; offsetX++) {
for (int offsetY = -1; offsetY <= 1; offsetY++) {
SectionPos sectionPos = centerSection.offset(offsetX, offsetY, offsetZ);
if (level.isVillage(sectionPos.center())) {
consumer.accept(sectionPos, true);
} else {
consumer.accept(sectionPos, false);
}
}
}
}
}
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
SectionPos.of()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
ClientboundDebugBlockValuePacket
- 引用位置:
构造调用 - 关联成员:
ClientboundDebugBlockValuePacket()
- 引用位置:
-
ClientboundDebugChunkValuePacket
- 引用位置:
构造调用 - 关联成员:
ClientboundDebugChunkValuePacket()
- 引用位置:
-
ClientboundDebugEntityValuePacket
- 引用位置:
构造调用 - 关联成员:
ClientboundDebugEntityValuePacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
DebugPoiInfo()
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
ChunkPos.containing()
- 引用位置: