public final class Network {
private static final ResourceLocation CHANNEL = new ResourceLocation(MODID, "channel");
@SubscribeEvent
public static void init() { // я вызываю это из FMLCommonSetupEvent, вроде ок
String version = JarVersionLookupHandler.getImplementationVersion(MyMod.class).orElse("DEBUG");
// ^ это версия протокола, можете ставить свою строку, но менять её тогда когда отсылаемые вами пакеты меняются
NetworkRegistry.newEventChannel(
CHANNEL,
() -> version, // собственно тут эту версию фордж получает динамически, неясно нафига конечно
version::equals, // проверка версии на клиенте, можно какие-то условия в лябмде описать
version::equals // аналогично, на сервене
).registerObject(Network.class); // регистрируем объект в котором будут @SubscribeEvent методы
}
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void on(ServerCustomPayloadEvent e) { // не ведитесь на тупое название класса, этот метод вызывается когда клиент получает пакет от сервера
PacketBuffer payload = e.getPayload();
Context ctx = e.getSource().get();
switch (payload.readByte()) { //наш "айди" пакета
case 0:
float a = payload.readFloat();
int b = payload.readInt();
// этот код выполняется в сетевых потоках, с игрой из него взаимодействовать нежелательно
// но желательно из PacketBuffer'a тут считывать инфу
ctx.enqueueWork(() -> {
// а вот этот enqueueWork выполнит код уже в потоке игры, тут можно блоки сеттить и так далее, взаимодействовать с игрой
PlayerEntity player = Minecraft.getInstance().player;
if (player != null) {
// чего-то делаем с клиенским плеером, это всё пример
} else {
// опять же, куски моего кода, у вас как вы напрогаете то так и будет
LogManager.getLogger(MyMod.class).warn("Clientside player was null on sync!");
}
});
ctx.setPacketHandled(true);
break;
case 1:
// etc
}
@SubscribeEvent
public static void on(ClientCustomPayloadEvent e) {
PacketBuffer payload = e.getPayload();
Context ctx = e.getSource().get();
ServerPlayerEntity player = ctx.getSender();
if (player == null) { // это моя проверка, вы себе уже как хотите прогайте
return;
}
switch (payload.readByte()) {
case 0:
// точно то же самое что и в методе выше
ctx.enqueueWork(() -> {...});
ctx.setPacketHandled(true);
break;
case 1:
// etc
}
}
public static void sendPacket1ToClient(ServerPlayerEntity player, float a, int b) {
PacketBuffer payload = new PacketBuffer(Unpooled.buffer());
payload.writeByte(0); // наш "айди", так-то мы просто шлём любые наборы байт по нашему каналу туда-сюда, вы можете слать что хотите, "айди" это я для вас расжёвываю прост
payload.writeFloat(a);
payload.writeInt(b);
player.connection.sendPacket(new SCustomPayloadPlayPacket(CHANNEL, payload));
}
@OnlyIn(Dist.CLIENT)
public static void sendSomePacketToServer(..data) {
PacketBuffer payload = new PacketBuffer(Unpooled.buffer());
payload.writeByte(123); // id
payload.writeSomething(..data);
ClientPlayNetHandler connection = Minecraft.getInstance().getConnection();
if (connection == null) {
// на меня идея ругалась что может быть null, делаем ошибку со своим текстом чтобы из крашлога было ясно что за бред, так-то null оно быть не должно по идее крч
throw new IllegalStateException("No client-to-server connection");
}
connection.sendPacket(new CCustomPayloadPacket(CHANNEL, payload));
}
// и больше таких методов пишите для своих пакетов, можете попробовать найти как там слать всем трекающим игрокам, или всем игрокам в радиусе/мире, мне это было не нужно