Compare commits

...

2 Commits

Author SHA1 Message Date
Jonathan Coates 00e2e2bd2d
Switch to vanilla's stillValid implementation 2024-04-25 18:21:23 +01:00
Jonathan Coates 7c1f40031b
Some cleanup to network messages
- Use enums for key and mouse actions, rather than integer ids.
 - Change TerminalState to always contain a terminal. We now make
   TerminalState nullable when we want to skip sending anything.
2024-04-25 18:19:34 +01:00
18 changed files with 86 additions and 131 deletions

View File

@ -49,31 +49,31 @@ public void queueEvent(String event, @Nullable Object[] arguments) {
@Override
public void keyDown(int key, boolean repeat) {
ClientNetworking.sendToServer(new KeyEventServerMessage(menu, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key));
ClientNetworking.sendToServer(new KeyEventServerMessage(menu, repeat ? KeyEventServerMessage.Action.REPEAT : KeyEventServerMessage.Action.DOWN, key));
}
@Override
public void keyUp(int key) {
ClientNetworking.sendToServer(new KeyEventServerMessage(menu, KeyEventServerMessage.TYPE_UP, key));
ClientNetworking.sendToServer(new KeyEventServerMessage(menu, KeyEventServerMessage.Action.UP, key));
}
@Override
public void mouseClick(int button, int x, int y) {
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_CLICK, button, x, y));
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.Action.CLICK, button, x, y));
}
@Override
public void mouseUp(int button, int x, int y) {
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_UP, button, x, y));
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.Action.UP, button, x, y));
}
@Override
public void mouseDrag(int button, int x, int y) {
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_DRAG, button, x, y));
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.Action.DRAG, button, x, y));
}
@Override
public void mouseScroll(int direction, int x, int y) {
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_SCROLL, direction, x, y));
ClientNetworking.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.Action.SCROLL, direction, x, y));
}
}

View File

@ -49,7 +49,7 @@ public void handleComputerTerminal(int containerId, TerminalState terminal) {
}
@Override
public void handleMonitorData(BlockPos pos, TerminalState terminal) {
public void handleMonitorData(BlockPos pos, @Nullable TerminalState terminal) {
var player = Minecraft.getInstance().player;
if (player == null) return;
@ -67,7 +67,7 @@ public void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable
}
@Override
public void handlePocketComputerData(UUID instanceId, ComputerState state, int lightState, TerminalState terminal) {
public void handlePocketComputerData(UUID instanceId, ComputerState state, int lightState, @Nullable TerminalState terminal) {
ClientPocketComputers.setState(instanceId, state, lightState, terminal);
}

View File

@ -43,7 +43,7 @@ public static void remove(UUID id) {
* @param lightColour The current colour of the modem light.
* @param terminalData The current terminal contents.
*/
public static void setState(UUID instanceId, ComputerState state, int lightColour, TerminalState terminalData) {
public static void setState(UUID instanceId, ComputerState state, int lightColour, @Nullable TerminalState terminalData) {
var computer = instances.get(instanceId);
if (computer == null) {
instances.put(instanceId, new PocketComputerData(state, lightColour, terminalData));

View File

@ -26,10 +26,10 @@ public final class PocketComputerData {
private ComputerState state;
private int lightColour;
PocketComputerData(ComputerState state, int lightColour, TerminalState terminalData) {
PocketComputerData(ComputerState state, int lightColour, @Nullable TerminalState terminalData) {
this.state = state;
this.lightColour = lightColour;
if (terminalData.hasTerminal()) terminal = terminalData.create();
if (terminalData != null) terminal = terminalData.create();
}
public int getLightState() {
@ -44,11 +44,11 @@ public ComputerState getState() {
return state;
}
void setState(ComputerState state, int lightColour, TerminalState terminalData) {
void setState(ComputerState state, int lightColour, @Nullable TerminalState terminalData) {
this.state = state;
this.lightColour = lightColour;
if (terminalData.hasTerminal()) {
if (terminalData != null) {
if (terminal == null) {
terminal = terminalData.create();
} else {

View File

@ -5,9 +5,9 @@
package dan200.computercraft.shared.common;
import dan200.computercraft.shared.container.BasicContainer;
import dan200.computercraft.shared.util.BlockEntityHelpers;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -29,6 +29,6 @@ protected final Component getDefaultName() {
@Override
public boolean stillValid(Player player) {
return BlockEntityHelpers.isUsable(this, player, BlockEntityHelpers.DEFAULT_INTERACT_RANGE);
return Container.stillValidBlockEntity(this, player);
}
}

View File

@ -24,6 +24,7 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.Container;
import net.minecraft.world.LockCode;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.Nameable;
@ -75,13 +76,13 @@ public void setRemoved() {
unload();
}
protected double getInteractRange() {
return BlockEntityHelpers.DEFAULT_INTERACT_RANGE;
protected int getInteractRange() {
return Container.DEFAULT_DISTANCE_LIMIT;
}
public boolean isUsable(Player player) {
return BaseContainerBlockEntity.canUnlock(player, lockCode, getDisplayName())
&& BlockEntityHelpers.isUsable(this, player, getInteractRange());
&& Container.stillValidBlockEntity(this, player, getInteractRange());
}
protected void serverTick() {

View File

@ -7,6 +7,7 @@
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import org.jetbrains.annotations.Contract;
import javax.annotation.Nullable;
@ -21,68 +22,49 @@ public class TerminalState {
private final boolean colour;
private final int width;
private final int height;
@Nullable
private final ByteBuf buffer;
public TerminalState(@Nullable NetworkedTerminal terminal) {
if (terminal == null) {
colour = false;
width = height = 0;
buffer = null;
} else {
colour = terminal.isColour();
width = terminal.getWidth();
height = terminal.getHeight();
public TerminalState(NetworkedTerminal terminal) {
colour = terminal.isColour();
width = terminal.getWidth();
height = terminal.getHeight();
var buf = buffer = Unpooled.buffer();
terminal.write(new FriendlyByteBuf(buf));
}
var buf = buffer = Unpooled.buffer();
terminal.write(new FriendlyByteBuf(buf));
}
@Contract("null -> null; !null -> !null")
public static @Nullable TerminalState create(@Nullable NetworkedTerminal terminal) {
return terminal == null ? null : new TerminalState(terminal);
}
public TerminalState(FriendlyByteBuf buf) {
colour = buf.readBoolean();
width = buf.readVarInt();
height = buf.readVarInt();
if (buf.readBoolean()) {
width = buf.readVarInt();
height = buf.readVarInt();
var length = buf.readVarInt();
buffer = buf.readBytes(length);
} else {
width = height = 0;
buffer = null;
}
var length = buf.readVarInt();
buffer = buf.readBytes(length);
}
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(colour);
buf.writeBoolean(buffer != null);
if (buffer != null) {
buf.writeVarInt(width);
buf.writeVarInt(height);
buf.writeVarInt(buffer.readableBytes());
buf.writeBytes(buffer, buffer.readerIndex(), buffer.readableBytes());
}
}
public boolean hasTerminal() {
return buffer != null;
buf.writeVarInt(width);
buf.writeVarInt(height);
buf.writeVarInt(buffer.readableBytes());
buf.writeBytes(buffer, buffer.readerIndex(), buffer.readableBytes());
}
public int size() {
return buffer == null ? 0 : buffer.readableBytes();
return buffer.readableBytes();
}
public void apply(NetworkedTerminal terminal) {
if (buffer == null) throw new NullPointerException("buffer");
terminal.resize(width, height);
terminal.read(new FriendlyByteBuf(buffer));
}
public NetworkedTerminal create() {
if (buffer == null) throw new NullPointerException("Terminal does not exist");
var terminal = new NetworkedTerminal(width, height, colour);
terminal.read(new FriendlyByteBuf(buffer));
return terminal;

View File

@ -26,11 +26,11 @@ public interface ClientNetworkContext {
void handleComputerTerminal(int containerId, TerminalState terminal);
void handleMonitorData(BlockPos pos, TerminalState terminal);
void handleMonitorData(BlockPos pos, @Nullable TerminalState terminal);
void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name);
void handlePocketComputerData(UUID instanceId, ComputerState state, int lightState, TerminalState terminal);
void handlePocketComputerData(UUID instanceId, ComputerState state, int lightState, @Nullable TerminalState terminal);
void handlePocketComputerDeleted(UUID instanceId);

View File

@ -11,25 +11,26 @@
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import javax.annotation.Nullable;
public class MonitorClientMessage implements NetworkMessage<ClientNetworkContext> {
private final BlockPos pos;
private final TerminalState state;
private final @Nullable TerminalState state;
public MonitorClientMessage(BlockPos pos, TerminalState state) {
public MonitorClientMessage(BlockPos pos, @Nullable TerminalState state) {
this.pos = pos;
this.state = state;
}
public MonitorClientMessage(FriendlyByteBuf buf) {
pos = buf.readBlockPos();
state = new TerminalState(buf);
state = buf.readNullable(TerminalState::new);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBlockPos(pos);
state.write(buf);
buf.writeNullable(state, (b, t) -> t.write(b));
}
@Override

View File

@ -5,7 +5,6 @@
package dan200.computercraft.shared.network.client;
import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
import dan200.computercraft.shared.computer.terminal.TerminalState;
import dan200.computercraft.shared.network.MessageType;
import dan200.computercraft.shared.network.NetworkMessage;
@ -13,6 +12,7 @@
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
import net.minecraft.network.FriendlyByteBuf;
import javax.annotation.Nullable;
import java.util.UUID;
/**
@ -22,20 +22,20 @@ public class PocketComputerDataMessage implements NetworkMessage<ClientNetworkCo
private final UUID clientId;
private final ComputerState state;
private final int lightState;
private final TerminalState terminal;
private final @Nullable TerminalState terminal;
public PocketComputerDataMessage(PocketServerComputer computer, boolean sendTerminal) {
clientId = computer.getInstanceUUID();
state = computer.getState();
lightState = computer.getLight();
terminal = sendTerminal ? computer.getTerminalState() : new TerminalState((NetworkedTerminal) null);
terminal = sendTerminal ? computer.getTerminalState() : null;
}
public PocketComputerDataMessage(FriendlyByteBuf buf) {
clientId = buf.readUUID();
state = buf.readEnum(ComputerState.class);
lightState = buf.readVarInt();
terminal = new TerminalState(buf);
terminal = buf.readNullable(TerminalState::new);
}
@Override
@ -43,7 +43,7 @@ public void write(FriendlyByteBuf buf) {
buf.writeUUID(clientId);
buf.writeEnum(state);
buf.writeVarInt(lightState);
terminal.write(buf);
buf.writeNullable(terminal, (b, t) -> t.write(b));
}
@Override

View File

@ -12,14 +12,10 @@
public class KeyEventServerMessage extends ComputerServerMessage {
public static final int TYPE_DOWN = 0;
public static final int TYPE_REPEAT = 1;
public static final int TYPE_UP = 2;
private final int type;
private final Action type;
private final int key;
public KeyEventServerMessage(AbstractContainerMenu menu, int type, int key) {
public KeyEventServerMessage(AbstractContainerMenu menu, Action type, int key) {
super(menu);
this.type = type;
this.key = key;
@ -27,24 +23,24 @@ public KeyEventServerMessage(AbstractContainerMenu menu, int type, int key) {
public KeyEventServerMessage(FriendlyByteBuf buf) {
super(buf);
type = buf.readByte();
type = buf.readEnum(Action.class);
key = buf.readVarInt();
}
@Override
public void write(FriendlyByteBuf buf) {
super.write(buf);
buf.writeByte(type);
buf.writeEnum(type);
buf.writeVarInt(key);
}
@Override
protected void handle(ServerNetworkContext context, ComputerMenu container) {
var input = container.getInput();
if (type == TYPE_UP) {
if (type == Action.UP) {
input.keyUp(key);
} else {
input.keyDown(key, type == TYPE_REPEAT);
input.keyDown(key, type == Action.REPEAT);
}
}
@ -52,4 +48,8 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) {
public MessageType<KeyEventServerMessage> type() {
return NetworkMessages.KEY_EVENT;
}
public enum Action {
DOWN, REPEAT, UP
}
}

View File

@ -12,17 +12,12 @@
public class MouseEventServerMessage extends ComputerServerMessage {
public static final int TYPE_CLICK = 0;
public static final int TYPE_DRAG = 1;
public static final int TYPE_UP = 2;
public static final int TYPE_SCROLL = 3;
private final int type;
private final Action type;
private final int x;
private final int y;
private final int arg;
public MouseEventServerMessage(AbstractContainerMenu menu, int type, int arg, int x, int y) {
public MouseEventServerMessage(AbstractContainerMenu menu, Action type, int arg, int x, int y) {
super(menu);
this.type = type;
this.arg = arg;
@ -32,7 +27,7 @@ public MouseEventServerMessage(AbstractContainerMenu menu, int type, int arg, in
public MouseEventServerMessage(FriendlyByteBuf buf) {
super(buf);
type = buf.readByte();
type = buf.readEnum(Action.class);
arg = buf.readVarInt();
x = buf.readVarInt();
y = buf.readVarInt();
@ -41,7 +36,7 @@ public MouseEventServerMessage(FriendlyByteBuf buf) {
@Override
public void write(FriendlyByteBuf buf) {
super.write(buf);
buf.writeByte(type);
buf.writeEnum(type);
buf.writeVarInt(arg);
buf.writeVarInt(x);
buf.writeVarInt(y);
@ -51,10 +46,10 @@ public void write(FriendlyByteBuf buf) {
protected void handle(ServerNetworkContext context, ComputerMenu container) {
var input = container.getInput();
switch (type) {
case TYPE_CLICK -> input.mouseClick(arg, x, y);
case TYPE_DRAG -> input.mouseDrag(arg, x, y);
case TYPE_UP -> input.mouseUp(arg, x, y);
case TYPE_SCROLL -> input.mouseScroll(arg, x, y);
case CLICK -> input.mouseClick(arg, x, y);
case DRAG -> input.mouseDrag(arg, x, y);
case UP -> input.mouseUp(arg, x, y);
case SCROLL -> input.mouseScroll(arg, x, y);
}
}
@ -62,4 +57,8 @@ protected void handle(ServerNetworkContext context, ComputerMenu container) {
public MessageType<MouseEventServerMessage> type() {
return NetworkMessages.MOUSE_EVENT;
}
public enum Action {
CLICK, DRAG, UP, SCROLL,
}
}

View File

@ -54,8 +54,8 @@ public boolean pollTerminalChanged() {
return terminal;
}
void read(TerminalState state) {
if (state.hasTerminal()) {
void read(@Nullable TerminalState state) {
if (state != null) {
if (terminal == null) {
terminal = state.create();
} else {

View File

@ -223,7 +223,7 @@ private void onClientLoad(int oldXIndex, int oldYIndex) {
if (xIndex == 0 && yIndex == 0 && clientMonitor == null) clientMonitor = new ClientMonitor(this);
}
public final void read(TerminalState state) {
public final void read(@Nullable TerminalState state) {
if (xIndex != 0 || yIndex != 0) {
LOG.warn("Receiving monitor state for non-origin terminal at {}", getBlockPos());
return;

View File

@ -68,7 +68,7 @@ public static void onTick() {
var state = getState(tile, monitor);
ServerNetworking.sendToAllTracking(new MonitorClientMessage(pos, state), chunk);
limit -= state.size();
limit -= state == null ? 0 : state.size();
}
}
@ -76,9 +76,9 @@ public static void onTick() {
return !monitor.isRemoved() && monitor.getXIndex() == 0 && monitor.getYIndex() == 0 ? monitor.getCachedServerMonitor() : null;
}
private static TerminalState getState(MonitorBlockEntity tile, ServerMonitor monitor) {
private static @Nullable TerminalState getState(MonitorBlockEntity tile, ServerMonitor monitor) {
var state = tile.cached;
if (state == null) state = tile.cached = new TerminalState(monitor.getTerminal());
if (state == null) state = tile.cached = TerminalState.create(monitor.getTerminal());
return state;
}
}

View File

@ -21,6 +21,7 @@ public void write(FriendlyByteBuf buf) {
buf.writeVarInt(charge());
buf.writeVarInt(strength());
buf.writeBoolean(previousBit());
buf.writeVarInt(audio.remaining());
buf.writeBytes(audio().duplicate());
}
@ -29,7 +30,8 @@ public static EncodedAudio read(FriendlyByteBuf buf) {
var strength = buf.readVarInt();
var previousBit = buf.readBoolean();
var bytes = new byte[buf.readableBytes()];
var length = buf.readVarInt();
var bytes = new byte[length];
buf.readBytes(bytes);
return new EncodedAudio(charge, strength, previousBit, ByteBuffer.wrap(bytes));

View File

@ -26,6 +26,7 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Container;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
@ -88,8 +89,8 @@ protected void unload() {
}
@Override
protected double getInteractRange() {
return 12.0;
protected int getInteractRange() {
return Container.DEFAULT_DISTANCE_LIMIT + 4;
}
@Override

View File

@ -4,24 +4,14 @@
package dan200.computercraft.shared.util;
import dan200.computercraft.shared.platform.PlatformHelper;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
public final class BlockEntityHelpers {
/**
* The maximum limit a player can be away from a block to still have its UI open.
*
* @see #isUsable(BlockEntity, Player, double)
*/
public static final double DEFAULT_INTERACT_RANGE = 8.0;
private BlockEntityHelpers() {
}
@ -33,27 +23,6 @@ public static <E extends BlockEntity, A extends BlockEntity> BlockEntityTicker<A
return actualType == expectedType ? (BlockEntityTicker<A>) ticker : null;
}
/**
* Determine if a block entity is "usable" by a player.
*
* @param blockEntity The current block entity.
* @param player The player who is trying to interact with the block.
* @param range The default distance the player can be away. This typically defaults to {@link #DEFAULT_INTERACT_RANGE},
* but a custom value may be used. If {@link PlatformHelper#getReachDistance(Player)} is larger,
* that will be used instead.
* @return Whether this block entity is usable.
*/
public static boolean isUsable(BlockEntity blockEntity, Player player, double range) {
var level = blockEntity.getLevel();
var pos = blockEntity.getBlockPos();
range = Math.max(range, PlatformHelper.get().getReachDistance(player));
return player.isAlive() && player.getCommandSenderWorld() == level &&
!blockEntity.isRemoved() && level.getBlockEntity(pos) == blockEntity &&
player.distanceToSqr(Vec3.atCenterOf(pos)) <= range * range;
}
/**
* Update a block entity, marking it as changed and propagating changes to the client.
*