mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Make net code more multi-loader friendly
NetworkMessage follows vanilla's Packet much more closely now: the handler takes a context argument, which varies between the client and server. - The server handler just returns the ServerPlayer who sent the message. - The client context provides handleXyz(...) methods for each clientbound packet. Our packet subclasses call the appropriate method - the implementation of which contains the actual implementation. Doing this allows us to move a whole bunch of client-specific code into the main client package, dropping several @OnlyIn annotations and generally reducing the risk of accidentally loading client classes on the server. We also abstract out some packet sending and general networking code to make it easier to use in a multi-loader context.
This commit is contained in:
parent
564752c8dd
commit
53abe5e56e
@ -14,12 +14,12 @@ import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.shared.Config;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.FluidData;
|
||||
import dan200.computercraft.shared.peripheral.generic.methods.EnergyMethods;
|
||||
import dan200.computercraft.shared.peripheral.generic.methods.FluidMethods;
|
||||
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import dan200.computercraft.shared.platform.NetworkHandler;
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
@ -5,9 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import dan200.computercraft.client.platform.ClientPlatformHelper;
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.server.ComputerActionServerMessage;
|
||||
import dan200.computercraft.shared.network.server.KeyEventServerMessage;
|
||||
import dan200.computercraft.shared.network.server.MouseEventServerMessage;
|
||||
@ -30,51 +30,51 @@ public final class ClientInputHandler implements InputHandler {
|
||||
|
||||
@Override
|
||||
public void turnOn() {
|
||||
NetworkHandler.sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.TURN_ON));
|
||||
ClientPlatformHelper.get().sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.TURN_ON));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
NetworkHandler.sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.SHUTDOWN));
|
||||
ClientPlatformHelper.get().sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.SHUTDOWN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reboot() {
|
||||
NetworkHandler.sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.REBOOT));
|
||||
ClientPlatformHelper.get().sendToServer(new ComputerActionServerMessage(menu, ComputerActionServerMessage.Action.REBOOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueEvent(String event, @Nullable Object[] arguments) {
|
||||
NetworkHandler.sendToServer(new QueueEventServerMessage(menu, event, arguments));
|
||||
ClientPlatformHelper.get().sendToServer(new QueueEventServerMessage(menu, event, arguments));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown(int key, boolean repeat) {
|
||||
NetworkHandler.sendToServer(new KeyEventServerMessage(menu, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key));
|
||||
ClientPlatformHelper.get().sendToServer(new KeyEventServerMessage(menu, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyUp(int key) {
|
||||
NetworkHandler.sendToServer(new KeyEventServerMessage(menu, KeyEventServerMessage.TYPE_UP, key));
|
||||
ClientPlatformHelper.get().sendToServer(new KeyEventServerMessage(menu, KeyEventServerMessage.TYPE_UP, key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClick(int button, int x, int y) {
|
||||
NetworkHandler.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_CLICK, button, x, y));
|
||||
ClientPlatformHelper.get().sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_CLICK, button, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int button, int x, int y) {
|
||||
NetworkHandler.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_UP, button, x, y));
|
||||
ClientPlatformHelper.get().sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_UP, button, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDrag(int button, int x, int y) {
|
||||
NetworkHandler.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_DRAG, button, x, y));
|
||||
ClientPlatformHelper.get().sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_DRAG, button, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseScroll(int direction, int x, int y) {
|
||||
NetworkHandler.sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_SCROLL, direction, x, y));
|
||||
ClientPlatformHelper.get().sendToServer(new MouseEventServerMessage(menu, MouseEventServerMessage.TYPE_SCROLL, direction, x, y));
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,13 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.platform.ClientPlatformHelper;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.server.UploadFileMessage;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.Util;
|
||||
@ -182,7 +182,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
return;
|
||||
}
|
||||
|
||||
if (toUpload.size() > 0) UploadFileMessage.send(menu, toUpload, NetworkHandler::sendToServer);
|
||||
if (toUpload.size() > 0) UploadFileMessage.send(menu, toUpload, ClientPlatformHelper.get()::sendToServer);
|
||||
}
|
||||
|
||||
public void uploadResult(UploadResult result, @Nullable Component message) {
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.platform;
|
||||
|
||||
import dan200.computercraft.client.ClientTableFormatter;
|
||||
import dan200.computercraft.client.gui.ComputerScreenBase;
|
||||
import dan200.computercraft.client.gui.OptionScreen;
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The base implementation of {@link ClientNetworkContext}.
|
||||
* <p>
|
||||
* This should be extended by mod loader specific modules with the remaining abstract methods.
|
||||
*/
|
||||
public abstract class AbstractClientNetworkContext implements ClientNetworkContext {
|
||||
@Override
|
||||
public final void handleChatTable(TableBuilder table) {
|
||||
ClientTableFormatter.INSTANCE.display(table);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleComputerTerminal(int containerId, TerminalState terminal) {
|
||||
Player player = Minecraft.getInstance().player;
|
||||
if (player != null && player.containerMenu.containerId == containerId && player.containerMenu instanceof ComputerMenu menu) {
|
||||
menu.updateTerminal(terminal);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleMonitorData(BlockPos pos, TerminalState terminal) {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player == null) return;
|
||||
|
||||
var te = player.level.getBlockEntity(pos);
|
||||
if (!(te instanceof TileMonitor monitor)) return;
|
||||
|
||||
monitor.read(terminal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePocketComputerData(int instanceId, ComputerState state, int lightState, TerminalState terminal) {
|
||||
var computer = ClientPocketComputers.get(instanceId, terminal.colour);
|
||||
computer.setState(state, lightState);
|
||||
if (terminal.hasTerminal()) computer.setTerminal(terminal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePocketComputerDeleted(int instanceId) {
|
||||
ClientPocketComputers.remove(instanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleSpeakerAudio(UUID source, SpeakerPosition.Message position, float volume) {
|
||||
SpeakerManager.getSound(source).playAudio(reifyPosition(position), volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleSpeakerAudioPush(UUID source, ByteBuf buffer) {
|
||||
SpeakerManager.getSound(source).pushAudio(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleSpeakerMove(UUID source, SpeakerPosition.Message position) {
|
||||
SpeakerManager.moveSound(source, reifyPosition(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleSpeakerPlay(UUID source, SpeakerPosition.Message position, ResourceLocation sound, float volume, float pitch) {
|
||||
SpeakerManager.getSound(source).playSound(reifyPosition(position), sound, volume, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleSpeakerStop(UUID source) {
|
||||
SpeakerManager.stopSound(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleUploadResult(int containerId, UploadResult result, Component errorMessage) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
|
||||
var screen = OptionScreen.unwrap(minecraft.screen);
|
||||
if (screen instanceof ComputerScreenBase<?> && ((ComputerScreenBase<?>) screen).getMenu().containerId == containerId) {
|
||||
((ComputerScreenBase<?>) screen).uploadResult(result, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private static SpeakerPosition reifyPosition(SpeakerPosition.Message pos) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
Level level = minecraft.level;
|
||||
if (level != null && !level.dimension().location().equals(pos.level())) level = null;
|
||||
|
||||
return new SpeakerPosition(
|
||||
level, pos.position(),
|
||||
level != null && pos.entity().isPresent() ? level.getEntity(pos.entity().getAsInt()) : null
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.platform;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@AutoService(ClientNetworkContext.class)
|
||||
public class ClientNetworkContextImpl extends AbstractClientNetworkContext {
|
||||
@Override
|
||||
public void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name) {
|
||||
var mc = Minecraft.getInstance();
|
||||
mc.levelRenderer.playStreamingMusic(sound, pos, null);
|
||||
if (name != null) mc.gui.setNowPlaying(Component.literal(name));
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.platform;
|
||||
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.server.ServerNetworkContext;
|
||||
|
||||
public interface ClientPlatformHelper extends dan200.computercraft.impl.client.ClientPlatformHelper {
|
||||
static ClientPlatformHelper get() {
|
||||
return (ClientPlatformHelper) dan200.computercraft.impl.client.ClientPlatformHelper.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a network message to the server.
|
||||
*
|
||||
* @param message The message to send.
|
||||
*/
|
||||
void sendToServer(NetworkMessage<ServerNetworkContext> message);
|
||||
}
|
@ -6,15 +6,23 @@
|
||||
package dan200.computercraft.client.platform;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.server.ServerNetworkContext;
|
||||
import dan200.computercraft.shared.platform.NetworkHandler;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
@AutoService(ClientPlatformHelper.class)
|
||||
@AutoService(dan200.computercraft.impl.client.ClientPlatformHelper.class)
|
||||
public class ClientPlatformHelperImpl implements ClientPlatformHelper {
|
||||
@Override
|
||||
public BakedModel getModel(ModelManager manager, ResourceLocation location) {
|
||||
return manager.getModel(location);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendToServer(NetworkMessage<ServerNetworkContext> message) {
|
||||
NetworkHandler.sendToServer(message);
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ResourceMount;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.computer.metrics.ComputerMBean;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.UpgradesLoadedMessage;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
@ -116,9 +116,9 @@ public final class CommonHooks {
|
||||
public static void onDatapackSync(OnDatapackSyncEvent event) {
|
||||
var packet = new UpgradesLoadedMessage();
|
||||
if (event.getPlayer() == null) {
|
||||
NetworkHandler.sendToAllPlayers(packet);
|
||||
PlatformHelper.get().sendToAllPlayers(packet, event.getPlayerList().getServer());
|
||||
} else {
|
||||
NetworkHandler.sendToPlayer(event.getPlayer(), packet);
|
||||
PlatformHelper.get().sendToPlayer(packet, event.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,13 +275,13 @@ public final class ModRegistry {
|
||||
static final RegistrationHelper<MenuType<?>> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registry.MENU_REGISTRY);
|
||||
|
||||
public static final RegistryEntry<MenuType<ContainerComputerBase>> COMPUTER = REGISTRY.register("computer",
|
||||
() -> ContainerData.toType(ComputerContainerData::new, ComputerMenuWithoutInventory::new));
|
||||
() -> ContainerData.toType(ComputerContainerData::new, (id, inv, data) -> new ComputerMenuWithoutInventory(Menus.COMPUTER.get(), id, inv, data)));
|
||||
|
||||
public static final RegistryEntry<MenuType<ContainerComputerBase>> POCKET_COMPUTER = REGISTRY.register("pocket_computer",
|
||||
() -> ContainerData.toType(ComputerContainerData::new, ComputerMenuWithoutInventory::new));
|
||||
() -> ContainerData.toType(ComputerContainerData::new, (id, inv, data) -> new ComputerMenuWithoutInventory(Menus.POCKET_COMPUTER.get(), id, inv, data)));
|
||||
|
||||
public static final RegistryEntry<MenuType<ContainerComputerBase>> POCKET_COMPUTER_NO_TERM = REGISTRY.register("pocket_computer_no_term",
|
||||
() -> ContainerData.toType(ComputerContainerData::new, ComputerMenuWithoutInventory::new));
|
||||
() -> ContainerData.toType(ComputerContainerData::new, (id, inv, data) -> new ComputerMenuWithoutInventory(Menus.POCKET_COMPUTER_NO_TERM.get(), id, inv, data)));
|
||||
|
||||
public static final RegistryEntry<MenuType<ContainerTurtle>> TURTLE = REGISTRY.register("turtle",
|
||||
() -> ContainerData.toType(ComputerContainerData::new, ContainerTurtle::ofMenuData));
|
||||
|
@ -6,8 +6,8 @@
|
||||
package dan200.computercraft.shared.command.text;
|
||||
|
||||
import dan200.computercraft.shared.command.CommandUtils;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.ChatTableClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@ -106,7 +106,7 @@ public class TableBuilder {
|
||||
public void display(CommandSourceStack source) {
|
||||
if (CommandUtils.isPlayer(source)) {
|
||||
trim(18);
|
||||
NetworkHandler.sendToPlayer((ServerPlayer) source.getEntity(), new ChatTableClientMessage(this));
|
||||
PlatformHelper.get().sendToPlayer(new ChatTableClientMessage(this), (ServerPlayer) source.getEntity());
|
||||
} else {
|
||||
trim(100);
|
||||
new ServerTableFormatter(source).display(this);
|
||||
|
@ -18,9 +18,9 @@ import dan200.computercraft.core.metrics.MetricsObserver;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
@ -138,7 +138,7 @@ public class ServerComputer implements InputHandler, ComputerEnvironment {
|
||||
|
||||
for (var player : server.getPlayerList().getPlayers()) {
|
||||
if (player.containerMenu instanceof ComputerMenu && ((ComputerMenu) player.containerMenu).getComputer() == this) {
|
||||
NetworkHandler.sendToPlayer(player, createPacket.apply(player.containerMenu));
|
||||
PlatformHelper.get().sendToPlayer(createPacket.apply(player.containerMenu), player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ package dan200.computercraft.shared.computer.menu;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.upload.*;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.UploadResultMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@ -133,8 +132,7 @@ public class ServerInputState<T extends AbstractContainerMenu & ComputerMenu> im
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkMessage message = finishUpload(uploader);
|
||||
NetworkHandler.sendToPlayer(uploader, message);
|
||||
PlatformHelper.get().sendToPlayer(finishUpload(uploader), uploader);
|
||||
}
|
||||
|
||||
private UploadResultMessage finishUpload(ServerPlayer player) {
|
||||
|
@ -6,8 +6,8 @@
|
||||
package dan200.computercraft.shared.computer.upload;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.UploadResultMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
|
||||
@ -47,7 +47,7 @@ public class TransferredFiles {
|
||||
if (consumed.getAndSet(true)) return;
|
||||
|
||||
if (player.isAlive() && player.containerMenu == container) {
|
||||
NetworkHandler.sendToPlayer(player, UploadResultMessage.consumed(container));
|
||||
PlatformHelper.get().sendToPlayer(UploadResultMessage.consumed(container), player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.network;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.network.client.*;
|
||||
import dan200.computercraft.shared.network.server.*;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class NetworkHandler {
|
||||
private static SimpleChannel network;
|
||||
private static final IntSet usedIds = new IntOpenHashSet();
|
||||
|
||||
private NetworkHandler() {
|
||||
}
|
||||
|
||||
public static void setup() {
|
||||
var version = ComputerCraftAPI.getInstalledVersion();
|
||||
network = NetworkRegistry.ChannelBuilder.named(new ResourceLocation(ComputerCraft.MOD_ID, "network"))
|
||||
.networkProtocolVersion(() -> version)
|
||||
.clientAcceptedVersions(version::equals).serverAcceptedVersions(version::equals)
|
||||
.simpleChannel();
|
||||
|
||||
// Server messages
|
||||
registerMainThread(0, NetworkDirection.PLAY_TO_SERVER, ComputerActionServerMessage.class, ComputerActionServerMessage::new);
|
||||
registerMainThread(1, NetworkDirection.PLAY_TO_SERVER, QueueEventServerMessage.class, QueueEventServerMessage::new);
|
||||
registerMainThread(2, NetworkDirection.PLAY_TO_SERVER, KeyEventServerMessage.class, KeyEventServerMessage::new);
|
||||
registerMainThread(3, NetworkDirection.PLAY_TO_SERVER, MouseEventServerMessage.class, MouseEventServerMessage::new);
|
||||
registerMainThread(4, NetworkDirection.PLAY_TO_SERVER, UploadFileMessage.class, UploadFileMessage::new);
|
||||
|
||||
// Client messages
|
||||
registerMainThread(10, NetworkDirection.PLAY_TO_CLIENT, ChatTableClientMessage.class, ChatTableClientMessage::new);
|
||||
registerMainThread(11, NetworkDirection.PLAY_TO_CLIENT, PocketComputerDataMessage.class, PocketComputerDataMessage::new);
|
||||
registerMainThread(12, NetworkDirection.PLAY_TO_CLIENT, PocketComputerDeletedClientMessage.class, PocketComputerDeletedClientMessage::new);
|
||||
registerMainThread(13, NetworkDirection.PLAY_TO_CLIENT, ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new);
|
||||
registerMainThread(14, NetworkDirection.PLAY_TO_CLIENT, PlayRecordClientMessage.class, PlayRecordClientMessage::new);
|
||||
registerMainThread(15, NetworkDirection.PLAY_TO_CLIENT, MonitorClientMessage.class, MonitorClientMessage::new);
|
||||
registerMainThread(16, NetworkDirection.PLAY_TO_CLIENT, SpeakerAudioClientMessage.class, SpeakerAudioClientMessage::new);
|
||||
registerMainThread(17, NetworkDirection.PLAY_TO_CLIENT, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new);
|
||||
registerMainThread(18, NetworkDirection.PLAY_TO_CLIENT, SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new);
|
||||
registerMainThread(19, NetworkDirection.PLAY_TO_CLIENT, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new);
|
||||
registerMainThread(20, NetworkDirection.PLAY_TO_CLIENT, UploadResultMessage.class, UploadResultMessage::new);
|
||||
registerMainThread(21, NetworkDirection.PLAY_TO_CLIENT, UpgradesLoadedMessage.class, UpgradesLoadedMessage::new);
|
||||
}
|
||||
|
||||
public static void sendToPlayer(ServerPlayer player, NetworkMessage packet) {
|
||||
network.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
||||
}
|
||||
|
||||
public static void sendToAllPlayers(NetworkMessage packet) {
|
||||
network.send(PacketDistributor.ALL.noArg(), packet);
|
||||
}
|
||||
|
||||
public static void sendToServer(NetworkMessage packet) {
|
||||
network.sendToServer(packet);
|
||||
}
|
||||
|
||||
public static void sendToAllAround(NetworkMessage packet, Level world, Vec3 pos, double range) {
|
||||
var target = new PacketDistributor.TargetPoint(pos.x, pos.y, pos.z, range, world.dimension());
|
||||
network.send(PacketDistributor.NEAR.with(() -> target), packet);
|
||||
}
|
||||
|
||||
public static void sendToAllTracking(NetworkMessage packet, LevelChunk chunk) {
|
||||
network.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), packet);
|
||||
}
|
||||
|
||||
public static void sendToPlayers(NetworkMessage packet, Collection<ServerPlayer> players) {
|
||||
if (players.isEmpty()) return;
|
||||
|
||||
var vanillaPacket = network.toVanillaPacket(packet, NetworkDirection.PLAY_TO_CLIENT);
|
||||
for (var player : players) player.connection.send(vanillaPacket);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register packet, and a thread-unsafe handler for it.
|
||||
*
|
||||
* @param <T> The type of the packet to send.
|
||||
* @param type The class of the type of packet to send.
|
||||
* @param id The identifier for this packet type.
|
||||
* @param direction A network direction which will be asserted before any processing of this message occurs
|
||||
* @param decoder The factory for this type of packet.
|
||||
*/
|
||||
private static <T extends NetworkMessage> void registerMainThread(int id, NetworkDirection direction, Class<T> type, Function<FriendlyByteBuf, T> decoder) {
|
||||
if (!usedIds.add(id)) throw new IllegalStateException("Duplicate message kind for for id " + id);
|
||||
network.messageBuilder(type, id, direction)
|
||||
.encoder(NetworkMessage::toBytes)
|
||||
.decoder(decoder)
|
||||
.consumerMainThread((packet, contextSup) -> {
|
||||
var context = contextSup.get();
|
||||
context.enqueueWork(() -> packet.handle(context));
|
||||
context.setPacketHandled(true);
|
||||
})
|
||||
.add();
|
||||
}
|
||||
}
|
@ -5,18 +5,20 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network;
|
||||
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.server.ServerNetworkContext;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* The base interface for any message which will be sent to the client or server.
|
||||
*
|
||||
* @see dan200.computercraft.shared.network.client
|
||||
* @see dan200.computercraft.shared.network.server
|
||||
* @param <T> The context under which packets are evaluated.
|
||||
* @see ClientNetworkContext
|
||||
* @see ServerNetworkContext
|
||||
*/
|
||||
public interface NetworkMessage {
|
||||
public interface NetworkMessage<T> {
|
||||
/**
|
||||
* Write this packet to a buffer.
|
||||
* <p>
|
||||
@ -31,5 +33,5 @@ public interface NetworkMessage {
|
||||
*
|
||||
* @param context The context with which to handle this message
|
||||
*/
|
||||
void handle(NetworkEvent.Context context);
|
||||
void handle(T context);
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.network;
|
||||
|
||||
import dan200.computercraft.shared.network.client.*;
|
||||
import dan200.computercraft.shared.network.server.*;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Registry for all packets provided by CC: Tweaked.
|
||||
*
|
||||
* @see PlatformHelper The platform helper is used to send packets.
|
||||
*/
|
||||
public final class NetworkMessages {
|
||||
private NetworkMessages() {
|
||||
}
|
||||
|
||||
public interface PacketRegistry {
|
||||
<T extends NetworkMessage<ClientNetworkContext>> void registerClientbound(int id, Class<T> type, Function<FriendlyByteBuf, T> decoder);
|
||||
|
||||
<T extends NetworkMessage<ServerNetworkContext>> void registerServerbound(int id, Class<T> type, Function<FriendlyByteBuf, T> decoder);
|
||||
}
|
||||
|
||||
public static void register(PacketRegistry registry) {
|
||||
// Server messages
|
||||
registry.registerServerbound(0, ComputerActionServerMessage.class, ComputerActionServerMessage::new);
|
||||
registry.registerServerbound(1, QueueEventServerMessage.class, QueueEventServerMessage::new);
|
||||
registry.registerServerbound(2, KeyEventServerMessage.class, KeyEventServerMessage::new);
|
||||
registry.registerServerbound(3, MouseEventServerMessage.class, MouseEventServerMessage::new);
|
||||
registry.registerServerbound(4, UploadFileMessage.class, UploadFileMessage::new);
|
||||
|
||||
// Client messages
|
||||
registry.registerClientbound(10, ChatTableClientMessage.class, ChatTableClientMessage::new);
|
||||
registry.registerClientbound(11, PocketComputerDataMessage.class, PocketComputerDataMessage::new);
|
||||
registry.registerClientbound(12, PocketComputerDeletedClientMessage.class, PocketComputerDeletedClientMessage::new);
|
||||
registry.registerClientbound(13, ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new);
|
||||
registry.registerClientbound(14, PlayRecordClientMessage.class, PlayRecordClientMessage::new);
|
||||
registry.registerClientbound(15, MonitorClientMessage.class, MonitorClientMessage::new);
|
||||
registry.registerClientbound(16, SpeakerAudioClientMessage.class, SpeakerAudioClientMessage::new);
|
||||
registry.registerClientbound(17, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new);
|
||||
registry.registerClientbound(18, SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new);
|
||||
registry.registerClientbound(19, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new);
|
||||
registry.registerClientbound(20, UploadResultMessage.class, UploadResultMessage::new);
|
||||
registry.registerClientbound(21, UpgradesLoadedMessage.class, UpgradesLoadedMessage::new);
|
||||
}
|
||||
}
|
@ -5,16 +5,14 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.ClientTableFormatter;
|
||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ChatTableClientMessage implements NetworkMessage {
|
||||
public class ChatTableClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private static final int MAX_LEN = 16;
|
||||
private final TableBuilder table;
|
||||
|
||||
@ -64,7 +62,7 @@ public class ChatTableClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
ClientTableFormatter.INSTANCE.display(table);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleChatTable(table);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.impl.Services;
|
||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* The context under which clientbound packets are evaluated.
|
||||
*/
|
||||
public interface ClientNetworkContext {
|
||||
static ClientNetworkContext get() {
|
||||
var instance = Instance.INSTANCE;
|
||||
return instance == null ? Services.raise(ClientNetworkContext.class, Instance.ERROR) : instance;
|
||||
}
|
||||
|
||||
void handleChatTable(TableBuilder table);
|
||||
|
||||
void handleComputerTerminal(int containerId, TerminalState terminal);
|
||||
|
||||
void handleMonitorData(BlockPos pos, TerminalState terminal);
|
||||
|
||||
void handlePlayRecord(BlockPos pos, @Nullable SoundEvent sound, @Nullable String name);
|
||||
|
||||
void handlePocketComputerData(int instanceId, ComputerState state, int lightState, TerminalState terminal);
|
||||
|
||||
void handlePocketComputerDeleted(int instanceId);
|
||||
|
||||
void handleSpeakerAudio(UUID source, SpeakerPosition.Message position, float volume);
|
||||
|
||||
void handleSpeakerAudioPush(UUID source, ByteBuf buffer);
|
||||
|
||||
void handleSpeakerMove(UUID source, SpeakerPosition.Message position);
|
||||
|
||||
void handleSpeakerPlay(UUID source, SpeakerPosition.Message position, ResourceLocation sound, float volume, float pitch);
|
||||
|
||||
void handleSpeakerStop(UUID source);
|
||||
|
||||
void handleUploadResult(int containerId, UploadResult result, Component errorMessage);
|
||||
|
||||
final class Instance {
|
||||
static final @Nullable ClientNetworkContext INSTANCE;
|
||||
static final @Nullable Throwable ERROR;
|
||||
|
||||
static {
|
||||
var helper = Services.tryLoad(ClientNetworkContext.class);
|
||||
INSTANCE = helper.instance();
|
||||
ERROR = helper.error();
|
||||
}
|
||||
|
||||
private Instance() {
|
||||
}
|
||||
}
|
||||
}
|
@ -5,20 +5,14 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ComputerTerminalClientMessage implements NetworkMessage {
|
||||
public class ComputerTerminalClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final int containerId;
|
||||
private final TerminalState terminal;
|
||||
|
||||
@ -39,11 +33,7 @@ public class ComputerTerminalClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
Player player = Minecraft.getInstance().player;
|
||||
if (player != null && player.containerMenu.containerId == containerId && player.containerMenu instanceof ComputerMenu menu) {
|
||||
menu.updateTerminal(terminal);
|
||||
}
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleComputerTerminal(containerId, terminal);
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,12 @@ package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class MonitorClientMessage implements NetworkMessage {
|
||||
public class MonitorClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final BlockPos pos;
|
||||
private final TerminalState state;
|
||||
|
||||
@ -38,14 +33,7 @@ public class MonitorClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
var player = Minecraft.getInstance().player;
|
||||
if (player == null || player.level == null) return;
|
||||
|
||||
var te = player.level.getBlockEntity(pos);
|
||||
if (!(te instanceof TileMonitor)) return;
|
||||
|
||||
((TileMonitor) te).read(state);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleMonitorData(pos, state);
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,9 @@ package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.platform.Registries;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -25,7 +20,7 @@ import javax.annotation.Nonnull;
|
||||
*
|
||||
* @see dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive
|
||||
*/
|
||||
public class PlayRecordClientMessage implements NetworkMessage {
|
||||
public class PlayRecordClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final BlockPos pos;
|
||||
private final String name;
|
||||
private final SoundEvent soundEvent;
|
||||
@ -66,10 +61,7 @@ public class PlayRecordClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
var mc = Minecraft.getInstance();
|
||||
mc.levelRenderer.playStreamingMusic(soundEvent, pos, null);
|
||||
if (name != null) mc.gui.setNowPlaying(Component.literal(name));
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handlePlayRecord(pos, soundEvent, name);
|
||||
}
|
||||
}
|
||||
|
@ -5,19 +5,17 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
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.NetworkMessage;
|
||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
/**
|
||||
* Provides additional data about a client computer, such as its ID and current state.
|
||||
*/
|
||||
public class PocketComputerDataMessage implements NetworkMessage {
|
||||
public class PocketComputerDataMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final int instanceId;
|
||||
private final ComputerState state;
|
||||
private final int lightState;
|
||||
@ -46,9 +44,7 @@ public class PocketComputerDataMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
var computer = ClientPocketComputers.get(instanceId, terminal.colour);
|
||||
computer.setState(state, lightState);
|
||||
if (terminal.hasTerminal()) computer.setTerminal(terminal);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handlePocketComputerData(instanceId, state, lightState, terminal);
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,12 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class PocketComputerDeletedClientMessage implements NetworkMessage {
|
||||
public class PocketComputerDeletedClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final int instanceId;
|
||||
|
||||
public PocketComputerDeletedClientMessage(int instanceId) {
|
||||
@ -29,7 +27,7 @@ public class PocketComputerDeletedClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
ClientPocketComputers.remove(instanceId);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handlePocketComputerDeleted(instanceId);
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -24,7 +20,7 @@ import java.util.UUID;
|
||||
*
|
||||
* @see dan200.computercraft.shared.peripheral.speaker.TileSpeaker
|
||||
*/
|
||||
public class SpeakerAudioClientMessage implements NetworkMessage {
|
||||
public class SpeakerAudioClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final UUID source;
|
||||
private final SpeakerPosition.Message pos;
|
||||
private final ByteBuffer content;
|
||||
@ -42,7 +38,9 @@ public class SpeakerAudioClientMessage implements NetworkMessage {
|
||||
pos = SpeakerPosition.Message.read(buf);
|
||||
volume = buf.readFloat();
|
||||
|
||||
SpeakerManager.getSound(source).pushAudio(buf);
|
||||
// TODO: Remove this, so we no longer need a getter for ClientNetworkContext. However, doing so without
|
||||
// leaking or redundantly copying the buffer is hard.
|
||||
ClientNetworkContext.get().handleSpeakerAudioPush(source, buf);
|
||||
content = null;
|
||||
}
|
||||
|
||||
@ -55,8 +53,7 @@ public class SpeakerAudioClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
SpeakerManager.getSound(source).playAudio(pos.reify(), volume);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleSpeakerAudio(source, pos, volume);
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
@ -23,7 +19,7 @@ import java.util.UUID;
|
||||
*
|
||||
* @see dan200.computercraft.shared.peripheral.speaker.TileSpeaker
|
||||
*/
|
||||
public class SpeakerMoveClientMessage implements NetworkMessage {
|
||||
public class SpeakerMoveClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final UUID source;
|
||||
private final SpeakerPosition.Message pos;
|
||||
|
||||
@ -44,8 +40,7 @@ public class SpeakerMoveClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
SpeakerManager.moveSound(source, pos.reify());
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleSpeakerMove(source, pos);
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,10 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
@ -24,7 +20,7 @@ import java.util.UUID;
|
||||
*
|
||||
* @see dan200.computercraft.shared.peripheral.speaker.TileSpeaker
|
||||
*/
|
||||
public class SpeakerPlayClientMessage implements NetworkMessage {
|
||||
public class SpeakerPlayClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final UUID source;
|
||||
private final SpeakerPosition.Message pos;
|
||||
private final ResourceLocation sound;
|
||||
@ -57,8 +53,7 @@ public class SpeakerPlayClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
SpeakerManager.getSound(source).playSound(pos.reify(), sound, volume, pitch);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleSpeakerPlay(source, pos, sound, volume, pitch);
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,8 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
@ -22,7 +18,7 @@ import java.util.UUID;
|
||||
*
|
||||
* @see dan200.computercraft.shared.peripheral.speaker.TileSpeaker
|
||||
*/
|
||||
public class SpeakerStopClientMessage implements NetworkMessage {
|
||||
public class SpeakerStopClientMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final UUID source;
|
||||
|
||||
public SpeakerStopClientMessage(UUID source) {
|
||||
@ -39,8 +35,7 @@ public class SpeakerStopClientMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
SpeakerManager.stopSound(source);
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleSpeakerStop(source);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashMap;
|
||||
@ -30,7 +29,7 @@ import java.util.Objects;
|
||||
/**
|
||||
* Syncs turtle and pocket upgrades to the client.
|
||||
*/
|
||||
public class UpgradesLoadedMessage implements NetworkMessage {
|
||||
public class UpgradesLoadedMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final Map<String, UpgradeManager.UpgradeWrapper<TurtleUpgradeSerialiser<?>, ITurtleUpgrade>> turtleUpgrades;
|
||||
private final Map<String, UpgradeManager.UpgradeWrapper<PocketUpgradeSerialiser<?>, IPocketUpgrade>> pocketUpgrades;
|
||||
|
||||
@ -94,7 +93,7 @@ public class UpgradesLoadedMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
public void handle(ClientNetworkContext context) {
|
||||
TurtleUpgrades.instance().loadFromNetwork(turtleUpgrades);
|
||||
PocketUpgrades.instance().loadFromNetwork(pocketUpgrades);
|
||||
}
|
||||
|
@ -5,20 +5,16 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.client.gui.ComputerScreenBase;
|
||||
import dan200.computercraft.client.gui.OptionScreen;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class UploadResultMessage implements NetworkMessage {
|
||||
public class UploadResultMessage implements NetworkMessage<ClientNetworkContext> {
|
||||
private final int containerId;
|
||||
private final UploadResult result;
|
||||
private final Component errorMessage;
|
||||
@ -55,12 +51,7 @@ public class UploadResultMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
|
||||
var screen = OptionScreen.unwrap(minecraft.screen);
|
||||
if (screen instanceof ComputerScreenBase<?> && ((ComputerScreenBase<?>) screen).getMenu().containerId == containerId) {
|
||||
((ComputerScreenBase<?>) screen).uploadResult(result, errorMessage);
|
||||
}
|
||||
public void handle(ClientNetworkContext context) {
|
||||
context.handleUploadResult(containerId, result, errorMessage);
|
||||
}
|
||||
}
|
||||
|
@ -5,60 +5,39 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.network.container;
|
||||
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraftforge.common.extensions.IForgeMenuType;
|
||||
import net.minecraftforge.network.IContainerFactory;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* An extension over the basic {@link IForgeMenuType}/{@link NetworkHooks#openGui(ServerPlayer, MenuProvider, Consumer)}
|
||||
* hooks, with a more convenient way of reading and writing data.
|
||||
* Additional data to send when opening a menu. Like {@link NetworkMessage}, this should be immutable.
|
||||
*/
|
||||
public interface ContainerData {
|
||||
void toBytes(FriendlyByteBuf buf);
|
||||
|
||||
default void open(Player player, MenuProvider owner) {
|
||||
NetworkHooks.openScreen((ServerPlayer) player, owner, this::toBytes);
|
||||
/**
|
||||
* Open a menu for a specific player using this data.
|
||||
*
|
||||
* @param player The player to open the menu for.
|
||||
* @param menu The underlying menu provider.
|
||||
*/
|
||||
default void open(Player player, MenuProvider menu) {
|
||||
PlatformHelper.get().openMenu(player, menu, this);
|
||||
}
|
||||
|
||||
static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType(Function<FriendlyByteBuf, T> reader, Factory<C, T> factory) {
|
||||
return IForgeMenuType.create((id, player, data) -> factory.create(id, player, reader.apply(data)));
|
||||
}
|
||||
|
||||
static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType(Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory) {
|
||||
return new FixedPointContainerFactory<>(reader, factory).type;
|
||||
return PlatformHelper.get().createMenuType(reader, factory);
|
||||
}
|
||||
|
||||
interface Factory<C extends AbstractContainerMenu, T extends ContainerData> {
|
||||
C create(int id, @Nonnull Inventory inventory, T data);
|
||||
}
|
||||
|
||||
interface FixedFactory<C extends AbstractContainerMenu, T extends ContainerData> {
|
||||
C create(MenuType<C> type, int id, @Nonnull Inventory inventory, T data);
|
||||
}
|
||||
|
||||
final class FixedPointContainerFactory<C extends AbstractContainerMenu, T extends ContainerData> implements IContainerFactory<C> {
|
||||
private final IContainerFactory<C> impl;
|
||||
private final MenuType<C> type;
|
||||
|
||||
private FixedPointContainerFactory(Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory) {
|
||||
var type = this.type = IForgeMenuType.create(this);
|
||||
impl = (id, player, data) -> factory.create(type, id, player, reader.apply(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public C create(int windowId, Inventory inv, FriendlyByteBuf data) {
|
||||
return impl.create(windowId, inv, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -32,7 +31,7 @@ public class ComputerActionServerMessage extends ComputerServerMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container) {
|
||||
protected void handle(ServerNetworkContext context, @Nonnull ComputerMenu container) {
|
||||
switch (action) {
|
||||
case TURN_ON -> container.getInput().turnOn();
|
||||
case REBOOT -> container.getInput().reboot();
|
||||
|
@ -10,7 +10,6 @@ import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
@ -18,7 +17,7 @@ import javax.annotation.OverridingMethodsMustInvokeSuper;
|
||||
/**
|
||||
* A packet, which performs an action on the currently open {@link ComputerMenu}.
|
||||
*/
|
||||
public abstract class ComputerServerMessage implements NetworkMessage {
|
||||
public abstract class ComputerServerMessage implements NetworkMessage<ServerNetworkContext> {
|
||||
private final int containerId;
|
||||
|
||||
protected ComputerServerMessage(AbstractContainerMenu menu) {
|
||||
@ -36,12 +35,12 @@ public abstract class ComputerServerMessage implements NetworkMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(NetworkEvent.Context context) {
|
||||
public void handle(ServerNetworkContext context) {
|
||||
Player player = context.getSender();
|
||||
if (player.containerMenu.containerId == containerId && player.containerMenu instanceof ComputerMenu) {
|
||||
handle(context, (ComputerMenu) player.containerMenu);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container);
|
||||
protected abstract void handle(ServerNetworkContext context, @Nonnull ComputerMenu container);
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -40,7 +39,7 @@ public class KeyEventServerMessage extends ComputerServerMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container) {
|
||||
protected void handle(ServerNetworkContext context, @Nonnull ComputerMenu container) {
|
||||
var input = container.getInput();
|
||||
if (type == TYPE_UP) {
|
||||
input.keyUp(key);
|
||||
|
@ -8,7 +8,6 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -49,7 +48,7 @@ public class MouseEventServerMessage extends ComputerServerMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container) {
|
||||
protected void handle(ServerNetworkContext context, @Nonnull ComputerMenu container) {
|
||||
var input = container.getInput();
|
||||
switch (type) {
|
||||
case TYPE_CLICK -> input.mouseClick(arg, x, y);
|
||||
|
@ -11,7 +11,6 @@ import dan200.computercraft.shared.computer.menu.ServerInputHandler;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -47,7 +46,7 @@ public class QueueEventServerMessage extends ComputerServerMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container) {
|
||||
protected void handle(ServerNetworkContext context, @Nonnull ComputerMenu container) {
|
||||
container.getInput().queueEvent(event, args);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.network.server;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
/**
|
||||
* The context under which serverbound packets are evaluated.
|
||||
*/
|
||||
public interface ServerNetworkContext {
|
||||
/**
|
||||
* Get the player who sent this packet.
|
||||
*
|
||||
* @return The sending player.
|
||||
*/
|
||||
ServerPlayer getSender();
|
||||
}
|
@ -12,7 +12,6 @@ import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -155,7 +154,7 @@ public class UploadFileMessage extends ComputerServerMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(NetworkEvent.Context context, @Nonnull ComputerMenu container) {
|
||||
protected void handle(ServerNetworkContext context, @Nonnull ComputerMenu container) {
|
||||
var player = context.getSender();
|
||||
if (player != null) {
|
||||
var input = container.getInput();
|
||||
|
@ -20,7 +20,6 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
@ -36,7 +35,6 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -105,9 +103,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
// Open the GUI
|
||||
if (!getLevel().isClientSide && isUsable(player)) {
|
||||
NetworkHooks.openScreen((ServerPlayer) player, this);
|
||||
}
|
||||
if (!getLevel().isClientSide && isUsable(player)) player.openMenu(this);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.peripheral.monitor;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.MonitorClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.level.ChunkWatchEvent;
|
||||
@ -44,7 +44,7 @@ public final class MonitorWatcher {
|
||||
if (serverMonitor == null || monitor.enqueued) continue;
|
||||
|
||||
var state = getState(monitor, serverMonitor);
|
||||
NetworkHandler.sendToPlayer(event.getPlayer(), new MonitorClientMessage(monitor.getBlockPos(), state));
|
||||
PlatformHelper.get().sendToPlayer(new MonitorClientMessage(monitor.getBlockPos(), state), event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public final class MonitorWatcher {
|
||||
}
|
||||
|
||||
var state = getState(tile, monitor);
|
||||
NetworkHandler.sendToAllTracking(new MonitorClientMessage(pos, state), chunk);
|
||||
PlatformHelper.get().sendToAllTracking(new MonitorClientMessage(pos, state), chunk);
|
||||
|
||||
limit -= state.size();
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.*;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@ -34,7 +33,6 @@ import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -90,9 +88,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
public InteractionResult onActivate(Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
if (player.isCrouching()) return InteractionResult.PASS;
|
||||
|
||||
if (!getLevel().isClientSide && isUsable(player)) {
|
||||
NetworkHooks.openScreen((ServerPlayer) player, this);
|
||||
}
|
||||
if (!getLevel().isClientSide && isUsable(player)) player.openMenu(this);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -12,17 +12,18 @@ import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.lua.LuaTable;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.SpeakerAudioClientMessage;
|
||||
import dan200.computercraft.shared.network.client.SpeakerMoveClientMessage;
|
||||
import dan200.computercraft.shared.network.client.SpeakerPlayClientMessage;
|
||||
import dan200.computercraft.shared.network.client.SpeakerStopClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.platform.Registries;
|
||||
import dan200.computercraft.shared.util.PauseAwareTimer;
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.protocol.game.ClientboundCustomSoundPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
|
||||
|
||||
@ -112,22 +113,22 @@ public abstract class SpeakerPeripheral implements IPeripheral {
|
||||
// Stop the speaker and nuke the position, so we don't update it again.
|
||||
if (shouldStop && lastPosition != null) {
|
||||
lastPosition = null;
|
||||
NetworkHandler.sendToAllPlayers(new SpeakerStopClientMessage(getSource()));
|
||||
PlatformHelper.get().sendToAllPlayers(new SpeakerStopClientMessage(getSource()), level.getServer());
|
||||
return;
|
||||
}
|
||||
|
||||
var now = PauseAwareTimer.getTime();
|
||||
if (sound != null) {
|
||||
lastPlayTime = clock;
|
||||
NetworkHandler.sendToAllAround(
|
||||
PlatformHelper.get().sendToAllAround(
|
||||
new SpeakerPlayClientMessage(getSource(), position, sound.location, sound.volume, sound.pitch),
|
||||
level, pos, sound.volume * 16
|
||||
(ServerLevel) level, pos, sound.volume * 16
|
||||
);
|
||||
syncedPosition(position);
|
||||
} else if (dfpwmState != null && dfpwmState.shouldSendPending(now)) {
|
||||
// If clients need to receive another batch of audio, send it and then notify computers our internal buffer is
|
||||
// free again.
|
||||
NetworkHandler.sendToAllTracking(
|
||||
PlatformHelper.get().sendToAllTracking(
|
||||
new SpeakerAudioClientMessage(getSource(), position, dfpwmState.getVolume(), dfpwmState.pullPending(now)),
|
||||
level.getChunkAt(new BlockPos(pos))
|
||||
);
|
||||
@ -146,7 +147,7 @@ public abstract class SpeakerPeripheral implements IPeripheral {
|
||||
// in the last second.
|
||||
if (lastPosition != null && (clock - lastPositionTime) >= 20 && !lastPosition.withinDistance(position, 0.1)) {
|
||||
// TODO: What to do when entities move away? How do we notify people left behind that they're gone.
|
||||
NetworkHandler.sendToAllTracking(
|
||||
PlatformHelper.get().sendToAllTracking(
|
||||
new SpeakerMoveClientMessage(getSource(), position),
|
||||
level.getChunkAt(new BlockPos(pos))
|
||||
);
|
||||
|
@ -5,14 +5,11 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.peripheral.speaker;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -36,25 +33,19 @@ public record SpeakerPosition(@Nullable Level level, @Nonnull Vec3 position, @Nu
|
||||
return new Message(level.dimension().location(), position, entity == null ? OptionalInt.empty() : OptionalInt.of(entity.getId()));
|
||||
}
|
||||
|
||||
public static final class Message {
|
||||
private final ResourceLocation level;
|
||||
private final Vec3 position;
|
||||
private final OptionalInt entity;
|
||||
|
||||
private Message(ResourceLocation level, Vec3 position, OptionalInt entity) {
|
||||
this.level = level;
|
||||
this.position = position;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
public static Message read(@Nonnull FriendlyByteBuf buffer) {
|
||||
public record Message(
|
||||
ResourceLocation level,
|
||||
Vec3 position,
|
||||
OptionalInt entity
|
||||
) {
|
||||
public static Message read(FriendlyByteBuf buffer) {
|
||||
var level = buffer.readResourceLocation();
|
||||
var position = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble());
|
||||
var entity = buffer.readBoolean() ? OptionalInt.of(buffer.readInt()) : OptionalInt.empty();
|
||||
return new Message(level, position, entity);
|
||||
}
|
||||
|
||||
public void write(@Nonnull FriendlyByteBuf buffer) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeResourceLocation(level);
|
||||
|
||||
buffer.writeDouble(position.x);
|
||||
@ -64,18 +55,5 @@ public record SpeakerPosition(@Nullable Level level, @Nonnull Vec3 position, @Nu
|
||||
buffer.writeBoolean(entity.isPresent());
|
||||
if (entity.isPresent()) buffer.writeInt(entity.getAsInt());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public SpeakerPosition reify() {
|
||||
var minecraft = Minecraft.getInstance();
|
||||
Level level = minecraft.level;
|
||||
if (level != null && !level.dimension().location().equals(this.level)) level = null;
|
||||
|
||||
return new SpeakerPosition(
|
||||
level, position,
|
||||
level != null && entity.isPresent() ? level.getEntity(entity.getAsInt()) : null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.peripheral.speaker;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.SpeakerStopClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@ -40,7 +40,7 @@ public class TileSpeaker extends TileGeneric {
|
||||
public void setRemoved() {
|
||||
super.setRemoved();
|
||||
if (level != null && !level.isClientSide) {
|
||||
NetworkHandler.sendToAllPlayers(new SpeakerStopClientMessage(peripheral.getSource()));
|
||||
PlatformHelper.get().sendToAllPlayers(new SpeakerStopClientMessage(peripheral.getSource()), getLevel().getServer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,8 @@
|
||||
package dan200.computercraft.shared.peripheral.speaker;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.SpeakerStopClientMessage;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@ -23,9 +22,11 @@ public abstract class UpgradeSpeakerPeripheral extends SpeakerPeripheral {
|
||||
super.detach(computer);
|
||||
|
||||
// We could be in the process of shutting down the server, so we can't send packets in this case.
|
||||
var server = ServerLifecycleHooks.getCurrentServer();
|
||||
var level = getPosition().level();
|
||||
if (level == null) return;
|
||||
var server = level.getServer();
|
||||
if (server == null || server.isStopped()) return;
|
||||
|
||||
NetworkHandler.sendToAllPlayers(new SpeakerStopClientMessage(getSource()));
|
||||
PlatformHelper.get().sendToAllPlayers(new SpeakerStopClientMessage(getSource()), server);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.platform;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.NetworkMessages;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.server.ServerNetworkContext;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class NetworkHandler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NetworkHandler.class);
|
||||
|
||||
private static final SimpleChannel network;
|
||||
|
||||
static {
|
||||
var version = ComputerCraftAPI.getInstalledVersion();
|
||||
network = NetworkRegistry.ChannelBuilder.named(new ResourceLocation(ComputerCraftAPI.MOD_ID, "network"))
|
||||
.networkProtocolVersion(() -> version)
|
||||
.clientAcceptedVersions(version::equals).serverAcceptedVersions(version::equals)
|
||||
.simpleChannel();
|
||||
}
|
||||
|
||||
private NetworkHandler() {
|
||||
}
|
||||
|
||||
public static void setup() {
|
||||
IntSet usedIds = new IntOpenHashSet();
|
||||
NetworkMessages.register(new NetworkMessages.PacketRegistry() {
|
||||
@Override
|
||||
public <T extends NetworkMessage<ClientNetworkContext>> void registerClientbound(int id, Class<T> type, Function<FriendlyByteBuf, T> decoder) {
|
||||
if (!usedIds.add(id)) throw new IllegalArgumentException("Already have a packet with id " + id);
|
||||
registerMainThread(id, NetworkDirection.PLAY_TO_CLIENT, type, decoder, x -> ClientNetworkContext.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NetworkMessage<ServerNetworkContext>> void registerServerbound(int id, Class<T> type, Function<FriendlyByteBuf, T> decoder) {
|
||||
if (!usedIds.add(id)) throw new IllegalArgumentException("Already have a packet with id " + id);
|
||||
registerMainThread(id, NetworkDirection.PLAY_TO_SERVER, type, decoder, c -> () -> c.getSender());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void sendToPlayer(NetworkMessage<ClientNetworkContext> packet, ServerPlayer player) {
|
||||
network.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
||||
}
|
||||
|
||||
static void sendToPlayers(NetworkMessage<ClientNetworkContext> packet, Collection<ServerPlayer> players) {
|
||||
if (players.isEmpty()) return;
|
||||
|
||||
var vanillaPacket = network.toVanillaPacket(packet, NetworkDirection.PLAY_TO_CLIENT);
|
||||
for (var player : players) player.connection.send(vanillaPacket);
|
||||
}
|
||||
|
||||
static void sendToAllPlayers(NetworkMessage<ClientNetworkContext> packet) {
|
||||
network.send(PacketDistributor.ALL.noArg(), packet);
|
||||
}
|
||||
|
||||
static void sendToAllAround(NetworkMessage<ClientNetworkContext> packet, Level world, Vec3 pos, double range) {
|
||||
var target = new PacketDistributor.TargetPoint(pos.x, pos.y, pos.z, range, world.dimension());
|
||||
network.send(PacketDistributor.NEAR.with(() -> target), packet);
|
||||
}
|
||||
|
||||
static void sendToAllTracking(NetworkMessage<ClientNetworkContext> packet, LevelChunk chunk) {
|
||||
network.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), packet);
|
||||
}
|
||||
|
||||
public static void sendToServer(NetworkMessage<ServerNetworkContext> packet) {
|
||||
network.sendToServer(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register packet, and a thread-unsafe handler for it.
|
||||
*
|
||||
* @param <T> The type of the packet to send.
|
||||
* @param <H> The context this packet is evaluated under.
|
||||
* @param type The class of the type of packet to send.
|
||||
* @param id The identifier for this packet type.
|
||||
* @param direction A network direction which will be asserted before any processing of this message occurs
|
||||
* @param decoder The factory for this type of packet.
|
||||
* @param handler Gets or constructs the handler for this packet.
|
||||
*/
|
||||
static <H, T extends NetworkMessage<H>> void registerMainThread(
|
||||
int id, NetworkDirection direction, Class<T> type, Function<FriendlyByteBuf, T> decoder,
|
||||
Function<NetworkEvent.Context, H> handler
|
||||
) {
|
||||
network.messageBuilder(type, id, direction)
|
||||
.encoder(NetworkMessage::toBytes)
|
||||
.decoder(decoder)
|
||||
.consumerMainThread((packet, contextSup) -> {
|
||||
try {
|
||||
packet.handle(handler.apply(contextSup.get()));
|
||||
} catch (RuntimeException | Error e) {
|
||||
LOG.error("Failed handling packet", e);
|
||||
throw e;
|
||||
}
|
||||
})
|
||||
.add();
|
||||
}
|
||||
}
|
@ -5,17 +5,32 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.platform;
|
||||
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This extends {@linkplain dan200.computercraft.impl.PlatformHelper the API's loader abstraction layer}, adding
|
||||
@ -69,4 +84,66 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
|
||||
* @return The new block entity type.
|
||||
*/
|
||||
<T extends BlockEntity> BlockEntityType<T> createBlockEntityType(BiFunction<BlockPos, BlockState, T> factory, Block block);
|
||||
|
||||
/**
|
||||
* Create a menu type which sends additional data when opened.
|
||||
*
|
||||
* @param reader Parse the additional container data into a usable type.
|
||||
* @param factory The factory to create the new menu.
|
||||
* @param <C> The menu/container than we open.
|
||||
* @param <T> The data that we send to the client.
|
||||
* @return The menu type for this container.
|
||||
*/
|
||||
<C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> createMenuType(Function<FriendlyByteBuf, T> reader, ContainerData.Factory<C, T> factory);
|
||||
|
||||
/**
|
||||
* Open a container using a specific {@link ContainerData}.
|
||||
*
|
||||
* @param player The player to open the menu for.
|
||||
* @param owner The underlying menu provider.
|
||||
* @param menu The menu data.
|
||||
*/
|
||||
void openMenu(Player player, MenuProvider owner, ContainerData menu);
|
||||
|
||||
/**
|
||||
* Send a message to a specific player.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param player The player to send it to.
|
||||
*/
|
||||
void sendToPlayer(NetworkMessage<ClientNetworkContext> message, ServerPlayer player);
|
||||
|
||||
/**
|
||||
* Send a message to a set of players.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param players The players to send it to.
|
||||
*/
|
||||
void sendToPlayers(NetworkMessage<ClientNetworkContext> message, Collection<ServerPlayer> players);
|
||||
|
||||
/**
|
||||
* Send a message to all players.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param server The current server.
|
||||
*/
|
||||
void sendToAllPlayers(NetworkMessage<ClientNetworkContext> message, MinecraftServer server);
|
||||
|
||||
/**
|
||||
* Send a message to all players around a point.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param level The level the point is in.
|
||||
* @param pos The centre position.
|
||||
* @param distance The distance to the centre players must be within.
|
||||
*/
|
||||
void sendToAllAround(NetworkMessage<ClientNetworkContext> message, ServerLevel level, Vec3 pos, float distance);
|
||||
|
||||
/**
|
||||
* Send a message to all players tracking a chunk.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @param chunk The chunk players must be tracking.
|
||||
*/
|
||||
void sendToAllTracking(NetworkMessage<ClientNetworkContext> message, LevelChunk chunk);
|
||||
}
|
||||
|
@ -7,26 +7,43 @@ package dan200.computercraft.shared.platform;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.ClientNetworkContext;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.extensions.IForgeMenuType;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@AutoService(dan200.computercraft.impl.PlatformHelper.class)
|
||||
@ -66,6 +83,41 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
return new BlockEntityType<>(factory::apply, Set.of(block), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> createMenuType(Function<FriendlyByteBuf, T> reader, ContainerData.Factory<C, T> factory) {
|
||||
return IForgeMenuType.create((id, player, data) -> factory.create(id, player, reader.apply(data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openMenu(Player player, MenuProvider owner, ContainerData menu) {
|
||||
NetworkHooks.openScreen((ServerPlayer) player, owner, menu::toBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToPlayer(NetworkMessage<ClientNetworkContext> message, ServerPlayer player) {
|
||||
NetworkHandler.sendToPlayer(message, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToPlayers(NetworkMessage<ClientNetworkContext> message, Collection<ServerPlayer> players) {
|
||||
NetworkHandler.sendToPlayers(message, players);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToAllPlayers(NetworkMessage<ClientNetworkContext> message, MinecraftServer server) {
|
||||
NetworkHandler.sendToAllPlayers(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToAllAround(NetworkMessage<ClientNetworkContext> message, ServerLevel level, Vec3 pos, float distance) {
|
||||
NetworkHandler.sendToAllAround(message, level, pos, distance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToAllTracking(NetworkMessage<ClientNetworkContext> message, LevelChunk chunk) {
|
||||
NetworkHandler.sendToAllTracking(message, chunk);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CompoundTag getShareTag(ItemStack item) {
|
||||
|
@ -13,9 +13,9 @@ import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.client.PocketComputerDataMessage;
|
||||
import dan200.computercraft.shared.network.client.PocketComputerDeletedClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@ -164,7 +164,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
|
||||
if (sendState) {
|
||||
// Broadcast the state to all players
|
||||
tracking.addAll(getLevel().players());
|
||||
NetworkHandler.sendToPlayers(new PocketComputerDataMessage(this, false), tracking);
|
||||
PlatformHelper.get().sendToPlayers(new PocketComputerDataMessage(this, false), tracking);
|
||||
} else {
|
||||
// Broadcast the state to new players.
|
||||
List<ServerPlayer> added = new ArrayList<>();
|
||||
@ -172,7 +172,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
|
||||
if (tracking.add(player)) added.add(player);
|
||||
}
|
||||
if (!added.isEmpty()) {
|
||||
NetworkHandler.sendToPlayers(new PocketComputerDataMessage(this, false), added);
|
||||
PlatformHelper.get().sendToPlayers(new PocketComputerDataMessage(this, false), added);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,13 +183,13 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
|
||||
|
||||
if (entity instanceof ServerPlayer player && entity.isAlive()) {
|
||||
// Broadcast the terminal to the current player.
|
||||
NetworkHandler.sendToPlayer(player, new PocketComputerDataMessage(this, true));
|
||||
PlatformHelper.get().sendToPlayer(new PocketComputerDataMessage(this, true), player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemoved() {
|
||||
super.onRemoved();
|
||||
NetworkHandler.sendToAllPlayers(new PocketComputerDeletedClientMessage(getInstanceID()));
|
||||
PlatformHelper.get().sendToAllPlayers(new PocketComputerDeletedClientMessage(getInstanceID()), getLevel().getServer());
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,11 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.NetworkMessage;
|
||||
import dan200.computercraft.shared.network.client.PlayRecordClientMessage;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@ -19,6 +20,6 @@ public final class RecordUtil {
|
||||
|
||||
public static void playRecord(SoundEvent record, String recordInfo, Level world, BlockPos pos) {
|
||||
NetworkMessage packet = record != null ? new PlayRecordClientMessage(pos, record, recordInfo) : new PlayRecordClientMessage(pos);
|
||||
NetworkHandler.sendToAllAround(packet, world, Vec3.atCenterOf(pos), 64);
|
||||
PlatformHelper.get().sendToAllAround(packet, (ServerLevel) world, Vec3.atCenterOf(pos), 64);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user