Skip to content

Commit 33d41a9

Browse files
committed
rework syncing so inactive screens can still receive packets
1 parent 558eaea commit 33d41a9

9 files changed

Lines changed: 149 additions & 72 deletions

File tree

src/main/java/com/cleanroommc/modularui/factory/GuiManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.cleanroommc.modularui.api.MCHelper;
55
import com.cleanroommc.modularui.api.RecipeViewerSettings;
66
import com.cleanroommc.modularui.api.UIFactory;
7+
import com.cleanroommc.modularui.network.ModularNetwork;
78
import com.cleanroommc.modularui.network.NetworkHandler;
89
import com.cleanroommc.modularui.network.packets.OpenGuiPacket;
910
import com.cleanroommc.modularui.screen.GuiContainerWrapper;
@@ -87,6 +88,7 @@ public static <T extends GuiData> void open(@NotNull UIFactory<T> factory, @NotN
8788
int windowId = player.currentWindowId;
8889
PacketBuffer buffer = new PacketBuffer(Unpooled.buffer());
8990
factory.writeGuiData(guiData, buffer);
91+
ModularNetwork.SERVER.activate(windowId, msm);
9092
NetworkHandler.sendToPlayer(new OpenGuiPacket<>(windowId, factory, buffer), player);
9193
// open container // this mimics forge behaviour
9294
player.openContainer = container;
@@ -116,6 +118,7 @@ public static <T extends GuiData> void openFromClient(int windowId, @NotNull UIF
116118
}
117119
if (guiContainer.inventorySlots != container) throw new IllegalStateException("Custom Containers are not yet allowed!");
118120
guiContainer.inventorySlots.windowId = windowId;
121+
ModularNetwork.CLIENT.activate(windowId, msm);
119122
MCHelper.displayScreen(wrapper.getGuiScreen());
120123
player.openContainer = guiContainer.inventorySlots;
121124
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.cleanroommc.modularui.network;
2+
3+
import com.cleanroommc.modularui.ModularUI;
4+
import com.cleanroommc.modularui.network.packets.PacketSyncHandler;
5+
import com.cleanroommc.modularui.value.sync.ModularSyncManager;
6+
import com.cleanroommc.modularui.value.sync.SyncHandler;
7+
8+
import net.minecraft.entity.player.EntityPlayer;
9+
import net.minecraft.entity.player.EntityPlayerMP;
10+
import net.minecraft.network.PacketBuffer;
11+
import net.minecraftforge.fml.relauncher.Side;
12+
import net.minecraftforge.fml.relauncher.SideOnly;
13+
14+
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
15+
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
16+
17+
import java.io.IOException;
18+
19+
public abstract class ModularNetwork {
20+
21+
// These need to be separate instances, otherwise they would access the same maps in singleplayer.
22+
@SideOnly(Side.CLIENT)
23+
public static final ModularNetwork CLIENT = new ModularNetwork(true) {
24+
@Override
25+
protected void sendPacket(IPacket packet, EntityPlayer player) {
26+
NetworkHandler.sendToServer(packet);
27+
}
28+
};
29+
public static final ModularNetwork SERVER = new ModularNetwork(false) {
30+
@Override
31+
protected void sendPacket(IPacket packet, EntityPlayer player) {
32+
NetworkHandler.sendToPlayer(packet, (EntityPlayerMP) player);
33+
}
34+
};
35+
36+
public static ModularNetwork get(boolean client) {
37+
return client ? CLIENT : SERVER;
38+
}
39+
40+
public static ModularNetwork get(Side side) {
41+
return side.isClient() ? CLIENT : SERVER;
42+
}
43+
44+
public static ModularNetwork get(EntityPlayer player) {
45+
return get(NetworkUtils.isClient(player));
46+
}
47+
48+
private final boolean client;
49+
private final Int2ReferenceOpenHashMap<ModularSyncManager> activeScreens = new Int2ReferenceOpenHashMap<>();
50+
private final Reference2IntOpenHashMap<ModularSyncManager> inverseActiveScreens = new Reference2IntOpenHashMap<>();
51+
52+
private ModularNetwork(boolean client) {
53+
this.client = client;
54+
}
55+
56+
public boolean isClient() {
57+
return client;
58+
}
59+
60+
protected abstract void sendPacket(IPacket packet, EntityPlayer player);
61+
62+
public void activate(int networkId, ModularSyncManager manager) {
63+
if (activeScreens.containsKey(networkId)) throw new IllegalStateException("Network ID " + networkId + " is already active.");
64+
activeScreens.put(networkId, manager);
65+
inverseActiveScreens.put(manager, networkId);
66+
}
67+
68+
public void deactivate(ModularSyncManager manager) {
69+
int id = inverseActiveScreens.removeInt(manager);
70+
activeScreens.remove(id);
71+
}
72+
73+
public void receivePacket(PacketSyncHandler packet) {
74+
ModularSyncManager msm = activeScreens.get(packet.networkId);
75+
if (msm == null) return; // silently discard packets for inactive screens
76+
try {
77+
int id = packet.action ? 0 : packet.packet.readVarInt();
78+
msm.receiveWidgetUpdate(packet.panel, packet.key, packet.action, id, packet.packet);
79+
} catch (IndexOutOfBoundsException e) {
80+
ModularUI.LOGGER.error("Failed to read packet for sync handler {} in panel {}", packet.key, packet.panel);
81+
} catch (IOException e) {
82+
ModularUI.LOGGER.throwing(e);
83+
}
84+
}
85+
86+
public void sendSyncHandlerPacket(String panel, SyncHandler syncHandler, PacketBuffer buffer, EntityPlayer player) {
87+
ModularSyncManager msm = syncHandler.getSyncManager().getModularSyncManager();
88+
if (!inverseActiveScreens.containsKey(msm)) return;
89+
int id = inverseActiveScreens.getInt(msm);
90+
sendPacket(new PacketSyncHandler(id, panel, syncHandler.getKey(), false, buffer), player);
91+
}
92+
93+
public void sendActionPacket(ModularSyncManager msm, String panel, String key, PacketBuffer buffer, EntityPlayer player) {
94+
if (!inverseActiveScreens.containsKey(msm)) return;
95+
int id = inverseActiveScreens.getInt(msm);
96+
sendPacket(new PacketSyncHandler(id, panel, key, true, buffer), player);
97+
}
98+
}

src/main/java/com/cleanroommc/modularui/network/NetworkUtils.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import io.netty.buffer.ByteBuf;
1414
import io.netty.buffer.Unpooled;
15+
import org.apache.commons.lang3.StringUtils;
1516
import org.jetbrains.annotations.Nullable;
1617

1718
import java.io.IOException;
@@ -107,6 +108,10 @@ public static void writeStringSafe(PacketBuffer buffer, @Nullable String string,
107108
buffer.writeVarInt(Short.MAX_VALUE + 1);
108109
return;
109110
}
111+
if (string.isEmpty()) {
112+
buffer.writeVarInt(0);
113+
return;
114+
}
110115
byte[] bytesTest = string.getBytes(StandardCharsets.UTF_8);
111116
byte[] bytes;
112117

@@ -126,9 +131,8 @@ public static void writeStringSafe(PacketBuffer buffer, @Nullable String string,
126131

127132
public static String readStringSafe(PacketBuffer buffer) {
128133
int length = buffer.readVarInt();
129-
if (length > Short.MAX_VALUE) {
130-
return null;
131-
}
134+
if (length > Short.MAX_VALUE) return null;
135+
if (length == 0) return StringUtils.EMPTY;
132136
String s = buffer.toString(buffer.readerIndex(), length, StandardCharsets.UTF_8);
133137
buffer.readerIndex(buffer.readerIndex() + length);
134138
return s;

src/main/java/com/cleanroommc/modularui/network/packets/OpenGuiPacket.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,36 @@
1919

2020
public class OpenGuiPacket<T extends GuiData> implements IPacket {
2121

22-
private int windowId;
22+
private int networkId;
2323
private UIFactory<T> factory;
2424
private PacketBuffer data;
2525

2626
public OpenGuiPacket() {}
2727

28-
public OpenGuiPacket(int windowId, UIFactory<T> factory, PacketBuffer data) {
29-
this.windowId = windowId;
28+
public OpenGuiPacket(int networkId, UIFactory<T> factory, PacketBuffer data) {
29+
this.networkId = networkId;
3030
this.factory = factory;
3131
this.data = data;
3232
}
3333

3434
@Override
3535
public void write(PacketBuffer buf) throws IOException {
36-
buf.writeVarInt(this.windowId);
36+
buf.writeVarInt(this.networkId);
3737
buf.writeString(this.factory.getFactoryName());
3838
NetworkUtils.writeByteBuf(buf, this.data);
3939
}
4040

4141
@Override
4242
public void read(PacketBuffer buf) {
43-
this.windowId = buf.readVarInt();
43+
this.networkId = buf.readVarInt();
4444
this.factory = (UIFactory<T>) GuiManager.getFactory(buf.readString(32));
4545
this.data = NetworkUtils.readPacketBuffer(buf);
4646
}
4747

4848
@SideOnly(Side.CLIENT)
4949
@Override
5050
public @Nullable IPacket executeClient(NetHandlerPlayClient handler) {
51-
GuiManager.openFromClient(this.windowId, this.factory, this.data, Platform.getClientPlayer());
51+
GuiManager.openFromClient(this.networkId, this.factory, this.data, Platform.getClientPlayer());
5252
return null;
5353
}
5454

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
package com.cleanroommc.modularui.network.packets;
22

3-
import com.cleanroommc.modularui.ModularUI;
43
import com.cleanroommc.modularui.network.IPacket;
4+
import com.cleanroommc.modularui.network.ModularNetwork;
55
import com.cleanroommc.modularui.network.NetworkUtils;
6-
import com.cleanroommc.modularui.screen.ModularContainer;
7-
import com.cleanroommc.modularui.screen.ModularScreen;
8-
9-
import com.cleanroommc.modularui.value.sync.ModularSyncManager;
106

117
import net.minecraft.client.network.NetHandlerPlayClient;
12-
import net.minecraft.inventory.Container;
138
import net.minecraft.network.NetHandlerPlayServer;
149
import net.minecraft.network.PacketBuffer;
1510

11+
import org.jetbrains.annotations.ApiStatus;
1612
import org.jetbrains.annotations.Nullable;
1713

18-
import java.io.IOException;
19-
14+
@ApiStatus.Internal
2015
public class PacketSyncHandler implements IPacket {
2116

22-
private String panel;
23-
private String key;
24-
private boolean action;
25-
private PacketBuffer packet;
17+
public int networkId;
18+
public String panel;
19+
public String key;
20+
public boolean action;
21+
public PacketBuffer packet;
2622

2723
public PacketSyncHandler() {}
2824

29-
public PacketSyncHandler(String panel, String key, boolean action, PacketBuffer packet) {
25+
public PacketSyncHandler(int networkId, String panel, String key, boolean action, PacketBuffer packet) {
26+
this.networkId = networkId;
3027
this.panel = panel;
3128
this.key = key;
3229
this.action = action;
@@ -35,14 +32,16 @@ public PacketSyncHandler(String panel, String key, boolean action, PacketBuffer
3532

3633
@Override
3734
public void write(PacketBuffer buf) {
38-
NetworkUtils.writeStringSafe(buf, this.panel);
39-
NetworkUtils.writeStringSafe(buf, this.key, 64, true);
35+
buf.writeVarInt(this.networkId);
36+
NetworkUtils.writeStringSafe(buf, this.panel, 256, true);
37+
NetworkUtils.writeStringSafe(buf, this.key, 256, true);
4038
buf.writeBoolean(this.action);
4139
NetworkUtils.writeByteBuf(buf, this.packet);
4240
}
4341

4442
@Override
4543
public void read(PacketBuffer buf) {
44+
this.networkId = buf.readVarInt();
4645
this.panel = NetworkUtils.readStringSafe(buf);
4746
this.key = NetworkUtils.readStringSafe(buf);
4847
this.action = buf.readBoolean();
@@ -51,30 +50,13 @@ public void read(PacketBuffer buf) {
5150

5251
@Override
5352
public @Nullable IPacket executeClient(NetHandlerPlayClient handler) {
54-
ModularScreen screen = ModularScreen.getCurrent();
55-
if (screen != null) {
56-
execute(screen.getSyncManager());
57-
}
53+
ModularNetwork.CLIENT.receivePacket(this);
5854
return null;
5955
}
6056

6157
@Override
6258
public @Nullable IPacket executeServer(NetHandlerPlayServer handler) {
63-
Container container = handler.player.openContainer;
64-
if (container instanceof ModularContainer modularContainer) {
65-
execute(modularContainer.getSyncManager());
66-
}
59+
ModularNetwork.SERVER.receivePacket(this);
6760
return null;
6861
}
69-
70-
private void execute(ModularSyncManager syncManager) {
71-
try {
72-
int id = this.action ? 0 : this.packet.readVarInt();
73-
syncManager.receiveWidgetUpdate(this.panel, this.key, this.action, id, this.packet);
74-
} catch (IndexOutOfBoundsException e) {
75-
ModularUI.LOGGER.error("Failed to read packet for sync handler {} in panel {}", this.key, this.panel);
76-
} catch (IOException e) {
77-
ModularUI.LOGGER.throwing(e);
78-
}
79-
}
8062
}

src/main/java/com/cleanroommc/modularui/screen/ModularContainer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.cleanroommc.modularui.ModularUI;
44
import com.cleanroommc.modularui.core.mixins.early.minecraft.ContainerAccessor;
55
import com.cleanroommc.modularui.factory.GuiData;
6+
import com.cleanroommc.modularui.network.ModularNetwork;
67
import com.cleanroommc.modularui.network.NetworkUtils;
78
import com.cleanroommc.modularui.utils.Platform;
89
import com.cleanroommc.modularui.value.sync.ModularSyncManager;
@@ -113,6 +114,7 @@ public void onModularContainerOpened() {
113114
public void onModularContainerClosed() {
114115
if (this.syncManager != null) {
115116
this.syncManager.dispose();
117+
ModularNetwork.get(this.player).deactivate(this.syncManager);
116118
}
117119
}
118120

src/main/java/com/cleanroommc/modularui/value/sync/ModularSyncManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.cleanroommc.modularui.api.IPanelHandler;
55
import com.cleanroommc.modularui.api.ISyncedAction;
66
import com.cleanroommc.modularui.screen.ModularContainer;
7+
import com.cleanroommc.modularui.widgets.slot.PlayerSlotGroup;
78
import com.cleanroommc.modularui.widgets.slot.SlotGroup;
89
import com.cleanroommc.bogosorter.api.ISortingContextBuilder;
910

@@ -31,7 +32,7 @@
3132
public class ModularSyncManager implements ISyncRegistrar<ModularSyncManager> {
3233

3334
public static final String AUTO_SYNC_PREFIX = "auto_sync:";
34-
protected static final String PLAYER_INVENTORY = "player_inventory";
35+
3536
private static final String CURSOR_KEY = ISyncRegistrar.makeSyncKey("cursor_slot", 255255);
3637

3738
private final Map<String, PanelSyncManager> panelSyncManagerMap = new Object2ObjectOpenHashMap<>();
@@ -54,7 +55,7 @@ void setMainPSM(PanelSyncManager mainPSM) {
5455
@ApiStatus.Internal
5556
public void construct(ModularContainer container, String mainPanelName) {
5657
this.container = container;
57-
if (this.mainPSM.getSlotGroup(PLAYER_INVENTORY) == null) {
58+
if (this.mainPSM.getSlotGroup(PlayerSlotGroup.NAME) == null) {
5859
this.mainPSM.bindPlayerInventory(getPlayer());
5960
}
6061
this.mainPSM.syncValue(CURSOR_KEY, this.cursorSlotSyncHandler);

src/main/java/com/cleanroommc/modularui/value/sync/PanelSyncManager.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
import com.cleanroommc.modularui.ModularUI;
44
import com.cleanroommc.modularui.api.IPanelHandler;
55
import com.cleanroommc.modularui.api.ISyncedAction;
6-
import com.cleanroommc.modularui.network.NetworkHandler;
7-
import com.cleanroommc.modularui.network.packets.PacketSyncHandler;
6+
import com.cleanroommc.modularui.network.ModularNetwork;
87
import com.cleanroommc.modularui.screen.ModularContainer;
98
import com.cleanroommc.modularui.widgets.slot.ModularSlot;
109
import com.cleanroommc.modularui.widgets.slot.SlotGroup;
1110

1211
import net.minecraft.entity.player.EntityPlayer;
13-
import net.minecraft.entity.player.EntityPlayerMP;
1412
import net.minecraft.item.ItemStack;
1513
import net.minecraft.network.PacketBuffer;
1614
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
@@ -316,12 +314,7 @@ public PanelSyncManager registerSyncedAction(String mapKey, boolean executeClien
316314

317315
public void callSyncedAction(String mapKey, PacketBuffer packet) {
318316
if (invokeSyncedAction(mapKey, packet)) {
319-
PacketSyncHandler packetSyncHandler = new PacketSyncHandler(this.panelName, mapKey, true, packet);
320-
if (isClient()) {
321-
NetworkHandler.sendToServer(packetSyncHandler);
322-
} else {
323-
NetworkHandler.sendToPlayer(packetSyncHandler, (EntityPlayerMP) getPlayer());
324-
}
317+
ModularNetwork.get(isClient()).sendActionPacket(getModularSyncManager(), this.panelName, mapKey, packet, getPlayer());
325318
}
326319
}
327320

0 commit comments

Comments
 (0)