85 lines
3.0 KiB
Java
85 lines
3.0 KiB
Java
// SPDX-FileCopyrightText: 2020 The CC: Tweaked Developers
|
|
//
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package dan200.computercraft.shared.peripheral.monitor;
|
|
|
|
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
|
import dan200.computercraft.shared.config.Config;
|
|
import dan200.computercraft.shared.network.client.MonitorClientMessage;
|
|
import dan200.computercraft.shared.network.server.ServerNetworking;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.world.level.chunk.LevelChunk;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.ArrayDeque;
|
|
import java.util.Queue;
|
|
|
|
public final class MonitorWatcher {
|
|
private static final Queue<MonitorBlockEntity> watching = new ArrayDeque<>();
|
|
|
|
private MonitorWatcher() {
|
|
}
|
|
|
|
static void enqueue(MonitorBlockEntity monitor) {
|
|
if (monitor.enqueued) return;
|
|
|
|
monitor.enqueued = true;
|
|
monitor.cached = null;
|
|
watching.add(monitor);
|
|
}
|
|
|
|
public static void onWatch(LevelChunk chunk, ServerPlayer player) {
|
|
// Find all origin monitors who are not already on the queue and send the
|
|
// monitor data to the player.
|
|
for (var te : chunk.getBlockEntities().values()) {
|
|
if (!(te instanceof MonitorBlockEntity monitor)) continue;
|
|
|
|
var serverMonitor = getMonitor(monitor);
|
|
if (serverMonitor == null || monitor.enqueued) continue;
|
|
|
|
var state = getState(monitor, serverMonitor);
|
|
ServerNetworking.sendToPlayer(new MonitorClientMessage(monitor.getBlockPos(), state), player);
|
|
}
|
|
}
|
|
|
|
public static void onTick() {
|
|
// Find all enqueued monitors and send their contents to all nearby players.
|
|
|
|
var limit = Config.monitorBandwidth;
|
|
var obeyLimit = limit > 0;
|
|
|
|
MonitorBlockEntity tile;
|
|
while ((!obeyLimit || limit > 0) && (tile = watching.poll()) != null) {
|
|
tile.enqueued = false;
|
|
var monitor = getMonitor(tile);
|
|
if (monitor == null) continue;
|
|
|
|
var pos = tile.getBlockPos();
|
|
var world = tile.getLevel();
|
|
if (!(world instanceof ServerLevel)) continue;
|
|
|
|
var chunk = world.getChunkAt(pos);
|
|
if (((ServerLevel) world).getChunkSource().chunkMap.getPlayers(chunk.getPos(), false).isEmpty()) {
|
|
continue;
|
|
}
|
|
|
|
var state = getState(tile, monitor);
|
|
ServerNetworking.sendToAllTracking(new MonitorClientMessage(pos, state), chunk);
|
|
|
|
limit -= state == null ? 0 : state.size();
|
|
}
|
|
}
|
|
|
|
private static @Nullable ServerMonitor getMonitor(MonitorBlockEntity monitor) {
|
|
return !monitor.isRemoved() && monitor.getXIndex() == 0 && monitor.getYIndex() == 0 ? monitor.getCachedServerMonitor() : null;
|
|
}
|
|
|
|
private static @Nullable TerminalState getState(MonitorBlockEntity tile, ServerMonitor monitor) {
|
|
var state = tile.cached;
|
|
if (state == null) state = tile.cached = TerminalState.create(monitor.getTerminal());
|
|
return state;
|
|
}
|
|
}
|