minecraft_25w45a_unobfuscated/net/minecraft/util/debug/LevelDebugSynchronizers.java
2025-11-24 22:52:51 +03:00

240 lines
10 KiB
Java

/*
* Decompiled with CFR 0.152.
*/
package net.minecraft.util.debug;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundDebugBlockValuePacket;
import net.minecraft.network.protocol.game.ClientboundDebugEntityValuePacket;
import net.minecraft.network.protocol.game.ClientboundDebugEventPacket;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.debug.DebugSubscription;
import net.minecraft.util.debug.DebugValueSource;
import net.minecraft.util.debug.ServerDebugSubscribers;
import net.minecraft.util.debug.TrackingDebugSynchronizer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.ai.village.poi.PoiRecord;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
public class LevelDebugSynchronizers {
private final ServerLevel level;
private final List<TrackingDebugSynchronizer<?>> allSynchronizers = new ArrayList();
private final Map<DebugSubscription<?>, TrackingDebugSynchronizer.SourceSynchronizer<?>> sourceSynchronizers = new HashMap();
private final TrackingDebugSynchronizer.PoiSynchronizer poiSynchronizer = new TrackingDebugSynchronizer.PoiSynchronizer();
private final TrackingDebugSynchronizer.VillageSectionSynchronizer villageSectionSynchronizer = new TrackingDebugSynchronizer.VillageSectionSynchronizer();
private boolean sleeping = true;
private Set<DebugSubscription<?>> enabledSubscriptions = Set.of();
public LevelDebugSynchronizers(ServerLevel level) {
this.level = level;
for (DebugSubscription debugSubscription : BuiltInRegistries.DEBUG_SUBSCRIPTION) {
if (debugSubscription.valueStreamCodec() == null) continue;
this.sourceSynchronizers.put(debugSubscription, new TrackingDebugSynchronizer.SourceSynchronizer(debugSubscription));
}
this.allSynchronizers.addAll(this.sourceSynchronizers.values());
this.allSynchronizers.add(this.poiSynchronizer);
this.allSynchronizers.add(this.villageSectionSynchronizer);
}
public void tick(ServerDebugSubscribers serverSubscribers) {
this.enabledSubscriptions = serverSubscribers.enabledSubscriptions();
boolean shouldSleep = this.enabledSubscriptions.isEmpty();
if (this.sleeping != shouldSleep) {
if (shouldSleep) {
for (TrackingDebugSynchronizer<?> synchronizer : this.allSynchronizers) {
synchronizer.clear();
}
} else {
this.wakeUp();
}
this.sleeping = shouldSleep;
}
if (!this.sleeping) {
for (TrackingDebugSynchronizer<?> synchronizer : this.allSynchronizers) {
synchronizer.tick(this.level);
}
}
}
private void wakeUp() {
ChunkMap chunkMap = this.level.getChunkSource().chunkMap;
chunkMap.forEachReadyToSendChunk(this::registerChunk);
for (Entity entity : this.level.getAllEntities()) {
if (!chunkMap.isTrackedByAnyPlayer(entity)) continue;
this.registerEntity(entity);
}
}
private <T> TrackingDebugSynchronizer.SourceSynchronizer<T> getSourceSynchronizer(DebugSubscription<T> subscription) {
return this.sourceSynchronizers.get(subscription);
}
public void registerChunk(final LevelChunk chunk) {
if (this.sleeping) {
return;
}
chunk.registerDebugValues(this.level, new DebugValueSource.Registration(){
@Override
public <T> void register(DebugSubscription<T> subscription, DebugValueSource.ValueGetter<T> getter) {
LevelDebugSynchronizers.this.getSourceSynchronizer(subscription).registerChunk(chunk.getPos(), getter);
}
});
chunk.getBlockEntities().values().forEach(this::registerBlockEntity);
}
public void dropChunk(ChunkPos chunkPos) {
if (this.sleeping) {
return;
}
for (TrackingDebugSynchronizer.SourceSynchronizer<?> synchronizer : this.sourceSynchronizers.values()) {
synchronizer.dropChunk(chunkPos);
}
}
public void registerBlockEntity(final BlockEntity blockEntity) {
if (this.sleeping) {
return;
}
blockEntity.registerDebugValues(this.level, new DebugValueSource.Registration(){
@Override
public <T> void register(DebugSubscription<T> subscription, DebugValueSource.ValueGetter<T> getter) {
LevelDebugSynchronizers.this.getSourceSynchronizer(subscription).registerBlockEntity(blockEntity.getBlockPos(), getter);
}
});
}
public void dropBlockEntity(BlockPos blockPos) {
if (this.sleeping) {
return;
}
for (TrackingDebugSynchronizer.SourceSynchronizer<?> synchronizer : this.sourceSynchronizers.values()) {
synchronizer.dropBlockEntity(this.level, blockPos);
}
}
public void registerEntity(final Entity entity) {
if (this.sleeping) {
return;
}
entity.registerDebugValues(this.level, new DebugValueSource.Registration(){
@Override
public <T> void register(DebugSubscription<T> subscription, DebugValueSource.ValueGetter<T> getter) {
LevelDebugSynchronizers.this.getSourceSynchronizer(subscription).registerEntity(entity.getUUID(), getter);
}
});
}
public void dropEntity(Entity entity) {
if (this.sleeping) {
return;
}
for (TrackingDebugSynchronizer.SourceSynchronizer<?> synchronizer : this.sourceSynchronizers.values()) {
synchronizer.dropEntity(entity);
}
}
public void startTrackingChunk(ServerPlayer player, ChunkPos chunkPos) {
if (this.sleeping) {
return;
}
for (TrackingDebugSynchronizer<?> synchronizer : this.allSynchronizers) {
synchronizer.startTrackingChunk(player, chunkPos);
}
}
public void startTrackingEntity(ServerPlayer player, Entity entity) {
if (this.sleeping) {
return;
}
for (TrackingDebugSynchronizer<?> synchronizer : this.allSynchronizers) {
synchronizer.startTrackingEntity(player, entity);
}
}
public void registerPoi(PoiRecord poi) {
if (this.sleeping) {
return;
}
this.poiSynchronizer.onPoiAdded(this.level, poi);
this.villageSectionSynchronizer.onPoiAdded(this.level, poi);
}
public void updatePoi(BlockPos pos) {
if (this.sleeping) {
return;
}
this.poiSynchronizer.onPoiTicketCountChanged(this.level, pos);
}
public void dropPoi(BlockPos pos) {
if (this.sleeping) {
return;
}
this.poiSynchronizer.onPoiRemoved(this.level, pos);
this.villageSectionSynchronizer.onPoiRemoved(this.level, pos);
}
public boolean hasAnySubscriberFor(DebugSubscription<?> subscription) {
return this.enabledSubscriptions.contains(subscription);
}
public <T> void sendBlockValue(BlockPos blockPos, DebugSubscription<T> subscription, T value) {
if (this.hasAnySubscriberFor(subscription)) {
this.broadcastToTracking(new ChunkPos(blockPos), subscription, (Packet<? super ClientGamePacketListener>)new ClientboundDebugBlockValuePacket(blockPos, subscription.packUpdate(value)));
}
}
public <T> void clearBlockValue(BlockPos blockPos, DebugSubscription<T> subscription) {
if (this.hasAnySubscriberFor(subscription)) {
this.broadcastToTracking(new ChunkPos(blockPos), subscription, (Packet<? super ClientGamePacketListener>)new ClientboundDebugBlockValuePacket(blockPos, subscription.emptyUpdate()));
}
}
public <T> void sendEntityValue(Entity entity, DebugSubscription<T> subscription, T value) {
if (this.hasAnySubscriberFor(subscription)) {
this.broadcastToTracking(entity, subscription, (Packet<? super ClientGamePacketListener>)new ClientboundDebugEntityValuePacket(entity.getId(), subscription.packUpdate(value)));
}
}
public <T> void clearEntityValue(Entity entity, DebugSubscription<T> subscription) {
if (this.hasAnySubscriberFor(subscription)) {
this.broadcastToTracking(entity, subscription, (Packet<? super ClientGamePacketListener>)new ClientboundDebugEntityValuePacket(entity.getId(), subscription.emptyUpdate()));
}
}
public <T> void broadcastEventToTracking(BlockPos blockPos, DebugSubscription<T> subscription, T value) {
if (this.hasAnySubscriberFor(subscription)) {
this.broadcastToTracking(new ChunkPos(blockPos), subscription, (Packet<? super ClientGamePacketListener>)new ClientboundDebugEventPacket(subscription.packEvent(value)));
}
}
private void broadcastToTracking(ChunkPos trackedChunk, DebugSubscription<?> subscription, Packet<? super ClientGamePacketListener> packet) {
ChunkMap chunkMap = this.level.getChunkSource().chunkMap;
for (ServerPlayer player : chunkMap.getPlayers(trackedChunk, false)) {
if (!player.debugSubscriptions().contains(subscription)) continue;
player.connection.send(packet);
}
}
private void broadcastToTracking(Entity trackedEntity, DebugSubscription<?> subscription, Packet<? super ClientGamePacketListener> packet) {
ChunkMap chunkMap = this.level.getChunkSource().chunkMap;
chunkMap.sendToTrackingPlayersFiltered(trackedEntity, packet, player -> player.debugSubscriptions().contains(subscription));
}
}