ClientDebugSubscriber.java
net.minecraft.client.multiplayer.ClientDebugSubscriber
信息
- 全限定名:net.minecraft.client.multiplayer.ClientDebugSubscriber
- 类型:public class
- 包:net.minecraft.client.multiplayer
- 源码路径:src/main/java/net/minecraft/client/multiplayer/ClientDebugSubscriber.java
- 起始行号:L29
- 职责:
TODO
字段/常量
-
connection- 类型:
ClientPacketListener - 修饰符:
private final - 源码定位:
L30 - 说明:
TODO
- 类型:
-
debugScreenOverlay- 类型:
DebugScreenOverlay - 修饰符:
private final - 源码定位:
L31 - 说明:
TODO
- 类型:
-
remoteSubscriptions- 类型:
Set<DebugSubscription<?>> - 修饰符:
private - 源码定位:
L32 - 说明:
TODO
- 类型:
-
valuesBySubscription- 类型:
Map<DebugSubscription<?>,ClientDebugSubscriber.ValueMaps<?>> - 修饰符:
private final - 源码定位:
L33 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.client.multiplayer.ClientDebugSubscriber.ValueMap- 类型:
class - 修饰符:
private static - 源码定位:
L241 - 说明:
TODO
- 类型:
-
net.minecraft.client.multiplayer.ClientDebugSubscriber.ValueMapType- 类型:
interface - 修饰符:
private - 源码定位:
L276 - 说明:
TODO
- 类型:
-
net.minecraft.client.multiplayer.ClientDebugSubscriber.ValueMaps- 类型:
class - 修饰符:
private static - 源码定位:
L281 - 说明:
TODO
- 类型:
-
net.minecraft.client.multiplayer.ClientDebugSubscriber.ValueWrapper- 类型:
record - 修饰符:
private - 源码定位:
L302 - 说明:
TODO
- 类型:
构造器
public ClientDebugSubscriber(ClientPacketListener connection, DebugScreenOverlay debugScreenOverlay) @ L35
- 构造器名:ClientDebugSubscriber
- 源码定位:L35
- 修饰符:public
参数:
- connection: ClientPacketListener
- debugScreenOverlay: DebugScreenOverlay
说明:
TODO
方法
下面的方法块按源码顺序生成。
private static void addFlag(Set<DebugSubscription<?>> output, DebugSubscription<?> subscription, boolean flag) @ L40
- 方法名:addFlag
- 源码定位:L40
- 返回类型:void
- 修饰符:private static
参数:
- output: Set<DebugSubscription<?>>
- subscription: DebugSubscription<?>
- flag: boolean
说明:
TODO
private Set<DebugSubscription<?>> requestedSubscriptions() @ L46
- 方法名:requestedSubscriptions
- 源码定位:L46
- 返回类型:Set<DebugSubscription<?>>
- 修饰符:private
参数:
- 无
说明:
TODO
public void clear() @ L70
- 方法名:clear
- 源码定位:L70
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void tick(long gameTime) @ L75
- 方法名:tick
- 源码定位:L75
- 返回类型:void
- 修饰符:public
参数:
- gameTime: long
说明:
TODO
private void onSubscriptionsChanged(Set<DebugSubscription<?>> newSubscriptions) @ L89
- 方法名:onSubscriptionsChanged
- 源码定位:L89
- 返回类型:void
- 修饰符:private
参数:
- newSubscriptions: Set<DebugSubscription<?>>
说明:
TODO
private void initializeSubscriptions(Set<DebugSubscription<?>> newSubscriptions) @ L95
- 方法名:initializeSubscriptions
- 源码定位:L95
- 返回类型:void
- 修饰符:private
参数:
- newSubscriptions: Set<DebugSubscription<?>>
说明:
TODO
private <V> ClientDebugSubscriber.ValueMaps<V> getValueMaps(DebugSubscription<V> subscription) @ L101
- 方法名:getValueMaps
- 源码定位:L101
- 返回类型:
ClientDebugSubscriber.ValueMaps - 修饰符:private
参数:
- subscription: DebugSubscription
说明:
TODO
private <K,V> ClientDebugSubscriber.ValueMap<K,V> getValueMap(DebugSubscription<V> subscription, ClientDebugSubscriber.ValueMapType<K,V> mapType) @ L105
- 方法名:getValueMap
- 源码定位:L105
- 返回类型:<K,V> ClientDebugSubscriber.ValueMap<K,V>
- 修饰符:private
参数:
- subscription: DebugSubscription
- mapType: ClientDebugSubscriber.ValueMapType<K,V>
说明:
TODO
private <K,V> V getValue(DebugSubscription<V> subscription, K key, ClientDebugSubscriber.ValueMapType<K,V> type) @ L112
- 方法名:getValue
- 源码定位:L112
- 返回类型:<K,V> V
- 修饰符:private
参数:
- subscription: DebugSubscription
- key: K
- type: ClientDebugSubscriber.ValueMapType<K,V>
说明:
TODO
public DebugValueAccess createDebugValueAccess(Level level) @ L117
- 方法名:createDebugValueAccess
- 源码定位:L117
- 返回类型:DebugValueAccess
- 修饰符:public
参数:
- level: Level
说明:
TODO
public <T> void updateChunk(long gameTime, ChunkPos chunkPos, DebugSubscription.Update<T> update) @ L174
- 方法名:updateChunk
- 源码定位:L174
- 返回类型:
void - 修饰符:public
参数:
- gameTime: long
- chunkPos: ChunkPos
- update: DebugSubscription.Update
说明:
TODO
public <T> void updateBlock(long gameTime, BlockPos blockPos, DebugSubscription.Update<T> update) @ L178
- 方法名:updateBlock
- 源码定位:L178
- 返回类型:
void - 修饰符:public
参数:
- gameTime: long
- blockPos: BlockPos
- update: DebugSubscription.Update
说明:
TODO
public <T> void updateEntity(long gameTime, Entity entity, DebugSubscription.Update<T> update) @ L182
- 方法名:updateEntity
- 源码定位:L182
- 返回类型:
void - 修饰符:public
参数:
- gameTime: long
- entity: Entity
- update: DebugSubscription.Update
说明:
TODO
public <T> void pushEvent(long gameTime, DebugSubscription.Event<T> event) @ L186
- 方法名:pushEvent
- 源码定位:L186
- 返回类型:
void - 修饰符:public
参数:
- gameTime: long
- event: DebugSubscription.Event
说明:
TODO
private <K,V> void updateMap(long gameTime, K key, DebugSubscription.Update<V> update, ClientDebugSubscriber.ValueMapType<K,V> type) @ L193
- 方法名:updateMap
- 源码定位:L193
- 返回类型:<K,V> void
- 修饰符:private
参数:
- gameTime: long
- key: K
- update: DebugSubscription.Update
- type: ClientDebugSubscriber.ValueMapType<K,V>
说明:
TODO
private <K,V> void forEachValue(DebugSubscription<V> subscription, ClientDebugSubscriber.ValueMapType<K,V> type, BiConsumer<K,V> consumer) @ L200
- 方法名:forEachValue
- 源码定位:L200
- 返回类型:<K,V> void
- 修饰符:private
参数:
- subscription: DebugSubscription
- type: ClientDebugSubscriber.ValueMapType<K,V>
- consumer: BiConsumer<K,V>
说明:
TODO
public void dropLevel() @ L207
- 方法名:dropLevel
- 源码定位:L207
- 返回类型:void
- 修饰符:public
参数:
- 无
说明:
TODO
public void dropChunk(ChunkPos chunkPos) @ L212
- 方法名:dropChunk
- 源码定位:L212
- 返回类型:void
- 修饰符:public
参数:
- chunkPos: ChunkPos
说明:
TODO
public void dropEntity(Entity entity) @ L220
- 方法名:dropEntity
- 源码定位:L220
- 返回类型:void
- 修饰符:public
参数:
- entity: Entity
说明:
TODO
private static <T> ClientDebugSubscriber.ValueMapType<UUID,T> entities() @ L228
- 方法名:entities
- 源码定位:L228
- 返回类型:
ClientDebugSubscriber.ValueMapType<UUID,T> - 修饰符:private static
参数:
- 无
说明:
TODO
private static <T> ClientDebugSubscriber.ValueMapType<BlockPos,T> blocks() @ L232
- 方法名:blocks
- 源码定位:L232
- 返回类型:
ClientDebugSubscriber.ValueMapType<BlockPos,T> - 修饰符:private static
参数:
- 无
说明:
TODO
private static <T> ClientDebugSubscriber.ValueMapType<ChunkPos,T> chunks() @ L236
- 方法名:chunks
- 源码定位:L236
- 返回类型:
ClientDebugSubscriber.ValueMapType<ChunkPos,T> - 修饰符:private static
参数:
- 无
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class ClientDebugSubscriber {
private final ClientPacketListener connection;
private final DebugScreenOverlay debugScreenOverlay;
private Set<DebugSubscription<?>> remoteSubscriptions = Set.of();
private final Map<DebugSubscription<?>, ClientDebugSubscriber.ValueMaps<?>> valuesBySubscription = new HashMap<>();
public ClientDebugSubscriber(ClientPacketListener connection, DebugScreenOverlay debugScreenOverlay) {
this.debugScreenOverlay = debugScreenOverlay;
this.connection = connection;
}
private static void addFlag(Set<DebugSubscription<?>> output, DebugSubscription<?> subscription, boolean flag) {
if (flag) {
output.add(subscription);
}
}
private Set<DebugSubscription<?>> requestedSubscriptions() {
Set<DebugSubscription<?>> subscriptions = new ReferenceOpenHashSet<>();
addFlag(subscriptions, RemoteDebugSampleType.TICK_TIME.subscription(), this.debugScreenOverlay.showFpsCharts());
if (SharedConstants.DEBUG_ENABLED) {
addFlag(subscriptions, DebugSubscriptions.BEES, SharedConstants.DEBUG_BEES);
addFlag(subscriptions, DebugSubscriptions.BEE_HIVES, SharedConstants.DEBUG_BEES);
addFlag(subscriptions, DebugSubscriptions.BRAINS, SharedConstants.DEBUG_BRAIN);
addFlag(subscriptions, DebugSubscriptions.BREEZES, SharedConstants.DEBUG_BREEZE_MOB);
addFlag(subscriptions, DebugSubscriptions.ENTITY_BLOCK_INTERSECTIONS, SharedConstants.DEBUG_ENTITY_BLOCK_INTERSECTION);
addFlag(subscriptions, DebugSubscriptions.ENTITY_PATHS, SharedConstants.DEBUG_PATHFINDING);
addFlag(subscriptions, DebugSubscriptions.GAME_EVENTS, SharedConstants.DEBUG_GAME_EVENT_LISTENERS);
addFlag(subscriptions, DebugSubscriptions.GAME_EVENT_LISTENERS, SharedConstants.DEBUG_GAME_EVENT_LISTENERS);
addFlag(subscriptions, DebugSubscriptions.GOAL_SELECTORS, SharedConstants.DEBUG_GOAL_SELECTOR || SharedConstants.DEBUG_BEES);
addFlag(subscriptions, DebugSubscriptions.NEIGHBOR_UPDATES, SharedConstants.DEBUG_NEIGHBORSUPDATE);
addFlag(subscriptions, DebugSubscriptions.POIS, SharedConstants.DEBUG_POI);
addFlag(subscriptions, DebugSubscriptions.RAIDS, SharedConstants.DEBUG_RAIDS);
addFlag(subscriptions, DebugSubscriptions.REDSTONE_WIRE_ORIENTATIONS, SharedConstants.DEBUG_EXPERIMENTAL_REDSTONEWIRE_UPDATE_ORDER);
addFlag(subscriptions, DebugSubscriptions.STRUCTURES, SharedConstants.DEBUG_STRUCTURES);
addFlag(subscriptions, DebugSubscriptions.VILLAGE_SECTIONS, SharedConstants.DEBUG_VILLAGE_SECTIONS);
}
return subscriptions;
}
public void clear() {
this.remoteSubscriptions = Set.of();
this.dropLevel();
}
public void tick(long gameTime) {
Set<DebugSubscription<?>> newSubscriptions = this.requestedSubscriptions();
if (!newSubscriptions.equals(this.remoteSubscriptions)) {
this.remoteSubscriptions = newSubscriptions;
this.onSubscriptionsChanged(newSubscriptions);
}
this.valuesBySubscription.forEach((subscription, valueMaps) -> {
if (subscription.expireAfterTicks() != 0) {
valueMaps.purgeExpired(gameTime);
}
});
}
private void onSubscriptionsChanged(Set<DebugSubscription<?>> newSubscriptions) {
this.valuesBySubscription.keySet().retainAll(newSubscriptions);
this.initializeSubscriptions(newSubscriptions);
this.connection.send(new ServerboundDebugSubscriptionRequestPacket(newSubscriptions));
}
private void initializeSubscriptions(Set<DebugSubscription<?>> newSubscriptions) {
for (DebugSubscription<?> subscription : newSubscriptions) {
this.valuesBySubscription.computeIfAbsent(subscription, s -> new ClientDebugSubscriber.ValueMaps());
}
}
private <V> ClientDebugSubscriber.@Nullable ValueMaps<V> getValueMaps(DebugSubscription<V> subscription) {
return (ClientDebugSubscriber.ValueMaps<V>)this.valuesBySubscription.get(subscription);
}
private <K, V> ClientDebugSubscriber.@Nullable ValueMap<K, V> getValueMap(
DebugSubscription<V> subscription, ClientDebugSubscriber.ValueMapType<K, V> mapType
) {
ClientDebugSubscriber.ValueMaps<V> maps = this.getValueMaps(subscription);
return maps != null ? mapType.get(maps) : null;
}
private <K, V> @Nullable V getValue(DebugSubscription<V> subscription, K key, ClientDebugSubscriber.ValueMapType<K, V> type) {
ClientDebugSubscriber.ValueMap<K, V> values = this.getValueMap(subscription, type);
return values != null ? values.getValue(key) : null;
}
public DebugValueAccess createDebugValueAccess(Level level) {
return new DebugValueAccess() {
{
Objects.requireNonNull(ClientDebugSubscriber.this);
}
@Override
public <T> void forEachChunk(DebugSubscription<T> subscription, BiConsumer<ChunkPos, T> consumer) {
ClientDebugSubscriber.this.forEachValue(subscription, ClientDebugSubscriber.chunks(), consumer);
}
@Override
public <T> @Nullable T getChunkValue(DebugSubscription<T> subscription, ChunkPos chunkPos) {
return ClientDebugSubscriber.this.getValue(subscription, chunkPos, ClientDebugSubscriber.chunks());
}
@Override
public <T> void forEachBlock(DebugSubscription<T> subscription, BiConsumer<BlockPos, T> consumer) {
ClientDebugSubscriber.this.forEachValue(subscription, ClientDebugSubscriber.blocks(), consumer);
}
@Override
public <T> @Nullable T getBlockValue(DebugSubscription<T> subscription, BlockPos blockPos) {
return ClientDebugSubscriber.this.getValue(subscription, blockPos, ClientDebugSubscriber.blocks());
}
@Override
public <T> void forEachEntity(DebugSubscription<T> subscription, BiConsumer<Entity, T> consumer) {
ClientDebugSubscriber.this.forEachValue(subscription, ClientDebugSubscriber.entities(), (entityId, value) -> {
Entity entity = level.getEntity(entityId);
if (entity != null) {
consumer.accept(entity, value);
}
});
}
@Override
public <T> @Nullable T getEntityValue(DebugSubscription<T> subscription, Entity entity) {
return ClientDebugSubscriber.this.getValue(subscription, entity.getUUID(), ClientDebugSubscriber.entities());
}
@Override
public <T> void forEachEvent(DebugSubscription<T> subscription, DebugValueAccess.EventVisitor<T> visitor) {
ClientDebugSubscriber.ValueMaps<T> values = ClientDebugSubscriber.this.getValueMaps(subscription);
if (values != null) {
long gameTime = level.getGameTime();
for (ClientDebugSubscriber.ValueWrapper<T> event : values.events) {
int remainingTicks = (int)(event.expiresAfterTime() - gameTime);
int totalLifetime = subscription.expireAfterTicks();
visitor.accept(event.value(), remainingTicks, totalLifetime);
}
}
}
};
}
public <T> void updateChunk(long gameTime, ChunkPos chunkPos, DebugSubscription.Update<T> update) {
this.updateMap(gameTime, chunkPos, update, chunks());
}
public <T> void updateBlock(long gameTime, BlockPos blockPos, DebugSubscription.Update<T> update) {
this.updateMap(gameTime, blockPos, update, blocks());
}
public <T> void updateEntity(long gameTime, Entity entity, DebugSubscription.Update<T> update) {
this.updateMap(gameTime, entity.getUUID(), update, entities());
}
public <T> void pushEvent(long gameTime, DebugSubscription.Event<T> event) {
ClientDebugSubscriber.ValueMaps<T> values = this.getValueMaps(event.subscription());
if (values != null) {
values.events.add(new ClientDebugSubscriber.ValueWrapper<>(event.value(), gameTime + event.subscription().expireAfterTicks()));
}
}
private <K, V> void updateMap(long gameTime, K key, DebugSubscription.Update<V> update, ClientDebugSubscriber.ValueMapType<K, V> type) {
ClientDebugSubscriber.ValueMap<K, V> values = this.getValueMap(update.subscription(), type);
if (values != null) {
values.apply(gameTime, key, update);
}
}
private <K, V> void forEachValue(DebugSubscription<V> subscription, ClientDebugSubscriber.ValueMapType<K, V> type, BiConsumer<K, V> consumer) {
ClientDebugSubscriber.ValueMap<K, V> values = this.getValueMap(subscription, type);
if (values != null) {
values.forEach(consumer);
}
}
public void dropLevel() {
this.valuesBySubscription.clear();
this.initializeSubscriptions(this.remoteSubscriptions);
}
public void dropChunk(ChunkPos chunkPos) {
if (!this.valuesBySubscription.isEmpty()) {
for (ClientDebugSubscriber.ValueMaps<?> values : this.valuesBySubscription.values()) {
values.dropChunkAndBlocks(chunkPos);
}
}
}
public void dropEntity(Entity entity) {
if (!this.valuesBySubscription.isEmpty()) {
for (ClientDebugSubscriber.ValueMaps<?> values : this.valuesBySubscription.values()) {
values.entityValues.removeKey(entity.getUUID());
}
}
}
private static <T> ClientDebugSubscriber.ValueMapType<UUID, T> entities() {
return v -> v.entityValues;
}
private static <T> ClientDebugSubscriber.ValueMapType<BlockPos, T> blocks() {
return v -> v.blockValues;
}
private static <T> ClientDebugSubscriber.ValueMapType<ChunkPos, T> chunks() {
return v -> v.chunkValues;
}
@OnlyIn(Dist.CLIENT)
private static class ValueMap<K, V> {
private final Map<K, ClientDebugSubscriber.ValueWrapper<V>> values = new HashMap<>();
public void removeValues(Predicate<ClientDebugSubscriber.ValueWrapper<V>> predicate) {
this.values.values().removeIf(predicate);
}
public void removeKey(K key) {
this.values.remove(key);
}
public void removeKeys(Predicate<K> predicate) {
this.values.keySet().removeIf(predicate);
}
public @Nullable V getValue(K key) {
ClientDebugSubscriber.ValueWrapper<V> result = this.values.get(key);
return result != null ? result.value() : null;
}
public void apply(long gameTime, K key, DebugSubscription.Update<V> update) {
if (update.value().isPresent()) {
this.values.put(key, new ClientDebugSubscriber.ValueWrapper<>(update.value().get(), gameTime + update.subscription().expireAfterTicks()));
} else {
this.values.remove(key);
}
}
public void forEach(BiConsumer<K, V> output) {
this.values.forEach((k, v) -> output.accept((K)k, v.value()));
}
}
@FunctionalInterface
@OnlyIn(Dist.CLIENT)
private interface ValueMapType<K, V> {
ClientDebugSubscriber.ValueMap<K, V> get(ClientDebugSubscriber.ValueMaps<V> maps);
}
@OnlyIn(Dist.CLIENT)
private static class ValueMaps<V> {
private final ClientDebugSubscriber.ValueMap<ChunkPos, V> chunkValues = new ClientDebugSubscriber.ValueMap<>();
private final ClientDebugSubscriber.ValueMap<BlockPos, V> blockValues = new ClientDebugSubscriber.ValueMap<>();
private final ClientDebugSubscriber.ValueMap<UUID, V> entityValues = new ClientDebugSubscriber.ValueMap<>();
private final List<ClientDebugSubscriber.ValueWrapper<V>> events = new ArrayList<>();
public void purgeExpired(long gameTime) {
Predicate<ClientDebugSubscriber.ValueWrapper<V>> expiredPredicate = v -> v.hasExpired(gameTime);
this.chunkValues.removeValues(expiredPredicate);
this.blockValues.removeValues(expiredPredicate);
this.entityValues.removeValues(expiredPredicate);
this.events.removeIf(expiredPredicate);
}
public void dropChunkAndBlocks(ChunkPos chunkPos) {
this.chunkValues.removeKey(chunkPos);
this.blockValues.removeKeys(chunkPos::contains);
}
}
@OnlyIn(Dist.CLIENT)
private record ValueWrapper<T>(T value, long expiresAfterTime) {
private static final long NO_EXPIRY = -1L;
public boolean hasExpired(long gameTime) {
return this.expiresAfterTime == -1L ? false : gameTime >= this.expiresAfterTime;
}
}
}引用的其他类
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/字段
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
ServerboundDebugSubscriptionRequestPacket
- 引用位置:
构造调用 - 关联成员:
ServerboundDebugSubscriptionRequestPacket()
- 引用位置:
-
- 引用位置:
参数/字段/返回值
- 引用位置:
-
- 引用位置:
构造调用/返回值 - 关联成员:
DebugValueAccess()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
参数
- 引用位置: