Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit 86a4d5e

Browse files
committed
Basic container synchronization
1 parent 1bc34ce commit 86a4d5e

6 files changed

Lines changed: 250 additions & 1 deletion

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.impl.networking;
21+
22+
public interface ContainerSyncAccess {
23+
int patchwork$getNewContainerSyncId();
24+
}

patchwork-networking-messages/src/main/java/com/patchworkmc/impl/networking/PatchworkPlayNetworkingMessages.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,20 @@
1919

2020
package com.patchworkmc.impl.networking;
2121

22+
import java.util.function.Consumer;
23+
2224
import io.netty.buffer.Unpooled;
2325
import net.minecraftforge.fml.network.FMLPlayMessages;
2426
import org.apache.logging.log4j.LogManager;
2527
import org.apache.logging.log4j.Logger;
2628

29+
import net.minecraft.container.Container;
30+
import net.minecraft.container.ContainerType;
31+
import net.minecraft.container.NameableContainerProvider;
2732
import net.minecraft.entity.Entity;
2833
import net.minecraft.network.Packet;
34+
import net.minecraft.server.network.ServerPlayerEntity;
35+
import net.minecraft.text.LiteralText;
2936
import net.minecraft.util.Identifier;
3037
import net.minecraft.util.PacketByteBuf;
3138

@@ -38,22 +45,35 @@ public class PatchworkPlayNetworkingMessages implements ModInitializer, MessageF
3845
private static final Identifier IDENTIFIER = new Identifier("fml", "play");
3946
private static final NetworkChannelVersion VERSION = new NetworkChannelVersion("FML2", version -> true, version -> true);
4047
private static final short SPAWN_ENTITY = 0;
48+
private static final short OPEN_CONTAINER = 1;
4149

4250
@Override
4351
public void onInitialize() {
4452
PatchworkNetworking.getVersionManager().createChannel(IDENTIFIER, VERSION);
4553
PatchworkNetworking.setFactory(this);
4654

55+
// TODO: Move to client initializer
4756
ClientSidePacketRegistry.INSTANCE.register(IDENTIFIER, (context, buf) -> {
4857
int id = buf.readUnsignedByte();
4958

5059
if (id == SPAWN_ENTITY) {
5160
FMLPlayMessages.SpawnEntity spawn = FMLPlayMessages.SpawnEntity.decode(buf);
5261
FMLPlayMessages.SpawnEntity.handle(spawn, context);
62+
} else if (id == OPEN_CONTAINER) {
63+
FMLPlayMessages.OpenContainer open = FMLPlayMessages.OpenContainer.decode(buf);
64+
FMLPlayMessages.OpenContainer.handle(open, context);
5365
} else {
5466
LOGGER.warn("Received an unknown fml:play message with an id of {} and a payload of {} bytes", id, buf.readableBytes());
5567
}
5668
});
69+
70+
ServerSidePacketRegistry.INSTANCE.register(IDENTIFIER, (context, buf) -> {
71+
LOGGER.warn("Received an fml:play on the server, this should not happen! Kicking the offending client.");
72+
73+
ServerPlayerEntity entity = (ServerPlayerEntity) context.getPlayer();
74+
75+
entity.networkHandler.disconnect(new LiteralText("fml:play messages should only be sent to the client!"));
76+
});
5777
}
5878

5979
@Override
@@ -66,4 +86,51 @@ public Packet<?> getEntitySpawningPacket(Entity entity) {
6686

6787
return ServerSidePacketRegistry.INSTANCE.toPacket(IDENTIFIER, buf);
6888
}
89+
90+
@Override
91+
public void sendContainerOpenPacket(ServerPlayerEntity player, NameableContainerProvider provider, Consumer<PacketByteBuf> extraDataWriter) {
92+
if (player.world.isClient) {
93+
return;
94+
}
95+
96+
player.method_14247();
97+
98+
ContainerSyncAccess access = (ContainerSyncAccess) player;
99+
int openContainerId = access.patchwork$getNewContainerSyncId();
100+
101+
PacketByteBuf extraData = new PacketByteBuf(Unpooled.buffer());
102+
extraDataWriter.accept(extraData);
103+
104+
// reset to beginning in case modders read for whatever reason
105+
extraData.readerIndex(0);
106+
107+
PacketByteBuf output = new PacketByteBuf(Unpooled.buffer());
108+
output.writeVarInt(extraData.readableBytes());
109+
output.writeBytes(extraData);
110+
111+
if (output.readableBytes() > 32600 || output.readableBytes() < 1) {
112+
throw new IllegalArgumentException("Invalid PacketByteBuf for openGui, found " + output.readableBytes() + " bytes");
113+
}
114+
115+
Container c = provider.createMenu(openContainerId, player.inventory, player);
116+
ContainerType<?> type = c.getType();
117+
118+
FMLPlayMessages.OpenContainer msg = new FMLPlayMessages.OpenContainer(type, openContainerId, provider.getDisplayName(), output);
119+
Packet<?> packet = PatchworkPlayNetworkingMessages.getOpenContainerPacket(msg);
120+
121+
player.networkHandler.sendPacket(packet);
122+
player.container = c;
123+
player.container.addListener(player);
124+
125+
// TODO MinecraftForge.EVENT_BUS.post(new PlayerContainerEvent.Open(player, c));
126+
}
127+
128+
private static Packet<?> getOpenContainerPacket(FMLPlayMessages.OpenContainer message) {
129+
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
130+
131+
buf.writeByte(OPEN_CONTAINER);
132+
FMLPlayMessages.OpenContainer.encode(message, buf);
133+
134+
return ServerSidePacketRegistry.INSTANCE.toPacket(IDENTIFIER, buf);
135+
}
69136
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Minecraft Forge, Patchwork Project
3+
* Copyright (c) 2016-2020, 2019-2020
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation version 2.1
8+
* of the License.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
package com.patchworkmc.mixin.networking;
21+
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.gen.Accessor;
24+
import org.spongepowered.asm.mixin.gen.Invoker;
25+
26+
import net.minecraft.server.network.ServerPlayerEntity;
27+
28+
import com.patchworkmc.impl.networking.ContainerSyncAccess;
29+
30+
@Mixin(ServerPlayerEntity.class)
31+
public class MixinServerPlayerEntity implements ContainerSyncAccess {
32+
@Accessor
33+
private int getContainerSyncId() {
34+
throw new AssertionError("Mixin not applied");
35+
}
36+
37+
@Invoker
38+
private void invokeIncrementContainerSyncId() {
39+
throw new AssertionError("Mixin not applied");
40+
}
41+
42+
@Override
43+
public int patchwork$getNewContainerSyncId() {
44+
invokeIncrementContainerSyncId();
45+
46+
return getContainerSyncId();
47+
}
48+
}

patchwork-networking-messages/src/main/java/net/minecraftforge/fml/network/FMLPlayMessages.java

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
import java.util.UUID;
2323
import java.util.function.Supplier;
2424

25+
import io.netty.buffer.Unpooled;
2526
import net.minecraftforge.fml.LogicalSide;
2627
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
2728

2829
import net.minecraft.client.MinecraftClient;
2930
import net.minecraft.client.world.ClientWorld;
31+
import net.minecraft.container.ContainerType;
3032
import net.minecraft.entity.Entity;
3133
import net.minecraft.entity.EntityType;
34+
import net.minecraft.text.Text;
3235
import net.minecraft.util.PacketByteBuf;
3336
import net.minecraft.util.math.MathHelper;
3437
import net.minecraft.util.math.Vec3d;
@@ -225,6 +228,80 @@ public PacketByteBuf getAdditionalData() {
225228
}
226229
}
227230

228-
// TODO: OpenContainer
231+
public static class OpenContainer {
232+
private final int id;
233+
private final int windowId;
234+
private final Text name;
235+
private final PacketByteBuf additionalData;
236+
237+
// Note: package-private on Forge
238+
public OpenContainer(ContainerType<?> id, int windowId, Text name, PacketByteBuf additionalData) {
239+
this(Registry.CONTAINER.getRawId(id), windowId, name, additionalData);
240+
}
241+
242+
private OpenContainer(int id, int windowId, Text name, PacketByteBuf additionalData) {
243+
this.id = id;
244+
this.windowId = windowId;
245+
this.name = name;
246+
this.additionalData = additionalData;
247+
}
248+
249+
public static void encode(OpenContainer msg, PacketByteBuf buf) {
250+
buf.writeVarInt(msg.id);
251+
buf.writeVarInt(msg.windowId);
252+
buf.writeText(msg.name);
253+
buf.writeByteArray(msg.additionalData.readByteArray());
254+
}
255+
256+
public static OpenContainer decode(PacketByteBuf buf) {
257+
return new OpenContainer(buf.readVarInt(), buf.readVarInt(), buf.readText(), new PacketByteBuf(Unpooled.wrappedBuffer(buf.readByteArray(32600))));
258+
}
259+
260+
public static void handle(OpenContainer msg, PacketContext context) {
261+
// TODO: IForgeContainerType
262+
263+
throw new UnsupportedOperationException("Cannot yet handle custom OpenContainer packets");
264+
265+
/*PatchworkNetworking.enqueueWork(context.getTaskQueue(), () -> {
266+
Screens.getScreenFactory(msg.getType(), MinecraftClient.getInstance(), msg.getWindowId(), msg.getName())
267+
.ifPresent(f -> {
268+
Container c = msg.getType().create(msg.getWindowId(), MinecraftClient.getInstance().player.inventory, msg.getAdditionalData());
269+
@SuppressWarnings("unchecked")
270+
Screen s = ((Screens.Provider<Container, ?>) f).create(c, MinecraftClient.getInstance().player.inventory, msg.getName());
271+
MinecraftClient.getInstance().player.container = ((ContainerProvider<?>) s).getContainer();
272+
MinecraftClient.getInstance().openScreen(s);
273+
});
274+
});*/
275+
}
276+
277+
public static void handle(OpenContainer msg, Supplier<NetworkEvent.Context> contextSupplier) {
278+
NetworkEvent.Context context = contextSupplier.get();
279+
280+
if (context.getDirection().getReceptionSide() != LogicalSide.CLIENT) {
281+
return;
282+
}
283+
284+
handle(msg, context);
285+
286+
context.setPacketHandled(true);
287+
}
288+
289+
public final ContainerType<?> getType() {
290+
return Registry.CONTAINER.get(this.id);
291+
}
292+
293+
public int getWindowId() {
294+
return windowId;
295+
}
296+
297+
public Text getName() {
298+
return name;
299+
}
300+
301+
public PacketByteBuf getAdditionalData() {
302+
return additionalData;
303+
}
304+
}
305+
229306
// TODO: DimensionInfoMessage
230307
}

patchwork-networking/src/main/java/com/patchworkmc/impl/networking/MessageFactory.java

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

2020
package com.patchworkmc.impl.networking;
2121

22+
import java.util.function.Consumer;
23+
24+
import net.minecraft.container.NameableContainerProvider;
2225
import net.minecraft.entity.Entity;
2326
import net.minecraft.network.Packet;
27+
import net.minecraft.server.network.ServerPlayerEntity;
28+
import net.minecraft.util.PacketByteBuf;
2429

2530
public interface MessageFactory {
2631
Packet<?> getEntitySpawningPacket(Entity entity);
32+
void sendContainerOpenPacket(ServerPlayerEntity player, NameableContainerProvider provider, Consumer<PacketByteBuf> extraDataWriter);
2733
}

patchwork-networking/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
package net.minecraftforge.fml.network;
2121

22+
import net.minecraft.container.ContainerType;
23+
import net.minecraft.container.NameableContainerProvider;
2224
import net.minecraft.entity.Entity;
2325
import net.minecraft.network.ClientConnection;
2426
import net.minecraft.network.Packet;
27+
import net.minecraft.server.network.ServerPlayerEntity;
2528

2629
import com.patchworkmc.impl.networking.ListenableChannel;
2730
import com.patchworkmc.impl.networking.MessageFactory;
@@ -47,4 +50,28 @@ public static Packet<?> getEntitySpawningPacket(Entity entity) {
4750

4851
return factory.getEntitySpawningPacket(entity);
4952
}
53+
54+
/**
55+
* Request to open a GUI on the client, from the server
56+
*
57+
* <p>The {@link ContainerType} for the container must be registered on both sides, it handles the creation of the container on the client.
58+
*
59+
* @param player The player to open the GUI for
60+
* @param provider Provides the container name and allows creation of new container instances
61+
*/
62+
public static void openGui(ServerPlayerEntity player, NameableContainerProvider provider) {
63+
// TODO: IForgeContainerType
64+
player.openContainer(provider);
65+
}
66+
67+
/*TODO
68+
public static void openGui(ServerPlayerEntity player, NameableContainerProvider provider, BlockPos pos) {
69+
openGui(player, provider, buf -> buf.writeBlockPos(pos));
70+
}
71+
72+
public static void openGui(ServerPlayerEntity player, NameableContainerProvider provider, Consumer<PacketByteBuf> extraDataWriter) {
73+
MessageFactory factory = PatchworkNetworking.getMessageFactory();
74+
75+
factory.sendContainerOpenPacket(player, provider, extraDataWriter);
76+
}*/
5077
}

0 commit comments

Comments
 (0)