Jump to content

Forge client mod and Bukkit plugin networking problem 1.19


liponex

Recommended Posts

Hello, I've got one problem, while I have worked on my new project. This is first time when I tried to use networking in Forge, and also wanted to connect mod with bukkit plugin over PluginMessages.

I've spent a few days to make me understand how can I do this. Used SimpleChannel, and already can handle packets forge-to-forge, but this is useless for my project where server must be vanilla only(Paper/Spigot/Bukkit).

I will be glad if someone will give me some code examples for actual 1.19+ Minecraft versions, where forge mod communicates with bukkit plugins using networking.

This is my Forge code

Main.class

Spoiler
package io.github.liponex.customtasksmod;

import com.mojang.logging.LogUtils;
import io.github.liponex.customtasksmod.events.IsInstalledPacketEvents;
import io.github.liponex.customtasksmod.networking.PluginMessages;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;

@Mod(CustomTasks.MODID)
public class CustomTasks {

    public static final String MODID = "customtasksmod";
    private static final Logger LOGGER = LogUtils.getLogger();

    public CustomTasks() {
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
        IEventBus forgeEventBus = MinecraftForge.EVENT_BUS;

        modEventBus.addListener(this::commonSetup);
        forgeEventBus.addListener(IsInstalledPacketEvents::onPacketReceive);

        MinecraftForge.EVENT_BUS.register(this);
        MinecraftForge.EVENT_BUS.register(new IsInstalledPacketEvents());
    }

    private void commonSetup(final FMLCommonSetupEvent event) {
        LOGGER.info("CustomTasksMod Setup");

        PluginMessages.register();
    }

    // You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
    @Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
    public static class ClientModEvents {
        @SubscribeEvent
        public static void onClientSetup(FMLClientSetupEvent event)
        {
            LOGGER.info("CLIENT SETUP");
            LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
        }
    }
}

 

Class that must handle packet IsInstalled

Spoiler
package io.github.liponex.customtasksmod.events;

import io.github.liponex.customtasksmod.CustomTasks;
import io.github.liponex.customtasksmod.networking.PluginMessages;
import io.github.liponex.customtasksmod.networking.packets.IsInstalledC2SPacket;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.NetworkEvent;

@Mod.EventBusSubscriber(modid = CustomTasks.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class IsInstalledPacketEvents {
    @SubscribeEvent
    public static void onPacketReceive(NetworkEvent.ClientCustomPayloadEvent event) {
        NetworkEvent.ClientCustomPayloadEvent e = event;
        PluginMessages.send(IsInstalledC2SPacket.isInstalled);
    }

}

 

Class PluginMessages that must prepare all for networking

Spoiler
package io.github.liponex.customtasksmod.networking;

import io.github.liponex.customtasksmod.CustomTasks;
import io.github.liponex.customtasksmod.networking.packets.IsInstalledC2SPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;

public class PluginMessages {

    private static int packetId = 0;
    private static int id() {
        return packetId++;
    }

    private static final String PROTOCOL_VERSION = "1.0";
    public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
            new ResourceLocation("custom_tasks_mod", "messages"),
            () -> PROTOCOL_VERSION,
            (s) -> true,
            (s) -> true
    );

    public static void register() {
        INSTANCE.messageBuilder(IsInstalledC2SPacket.class, id(), NetworkDirection.PLAY_TO_SERVER)
                .decoder(IsInstalledC2SPacket::new)
                .encoder(IsInstalledC2SPacket::toBytes)
                .consumerMainThread(IsInstalledC2SPacket::handle)
                .add();
    }

    public static <MSG> void send(MSG message) {
        INSTANCE.sendToServer(
            INSTANCE.toVanillaPacket(message, NetworkDirection.PLAY_TO_SERVER));
    }
}

 

Class of IsInstalled packet

Spoiler
package io.github.liponex.customtasksmod.networking.packets;

import com.mojang.logging.LogUtils;
import io.github.liponex.customtasksmod.CustomTasks;
import io.netty.buffer.ByteBufUtil;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import org.slf4j.Logger;

import java.util.function.Supplier;

public class IsInstalledC2SPacket {
    private static final Logger LOGGER = LogUtils.getLogger();

    public static final boolean isInstalled = true;

    public String text;

    public IsInstalledC2SPacket() {

    }

    public IsInstalledC2SPacket(FriendlyByteBuf buf) {
        text = buf.toString();
    }

    public void fromBytes(FriendlyByteBuf buf) {
        text = buf.toString();
    }

    public void toBytes(FriendlyByteBuf buf) {
        ByteBufUtil.writeUtf8(buf, text);
    }

    public boolean handle(Supplier<NetworkEvent.Context> supplier) {
        NetworkEvent.Context context = supplier.get();
        context.enqueueWork(() -> {
            LOGGER.info(context.toString());
        });
        context.setPacketHandled(true);
        return true;
    }
}

 

My Bukkit code, that I use for sending (ProtocolLib used)

Spoiler
@EventHandler
public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
    getServer().getConsoleSender().sendMessage("Player join detected!");

    PacketContainer packet = protocolManager.
            createPacket(PacketType.Play.Server.CUSTOM_PAYLOAD);
    packet.getModifier().writeDefaults();

    byte[] bytesTask = "IsInstalled".getBytes(StandardCharsets.UTF_8);

    MinecraftKey channel = new MinecraftKey("custom_tasks_mod", "messages");
    packet.getMinecraftKeys().write(0, channel);

    Object actualData = MinecraftReflection.getPacketDataSerializer(Unpooled.wrappedBuffer(bytesTask));
    packet.getModifier().withType(actualData.getClass()).write(0, actualData);

    try {
        protocolManager.sendServerPacket(event.getPlayer(), packet, false);
    } catch (InvocationTargetException e) {
        getServer().getConsoleSender().sendMessage(e.toString());
    }
}

 

Log from client console

Spoiler
[Netty Client IO #0/DEBUG] [ne.mi.ne.NetworkRegistry/NETREGISTRY]: Channel 'custom_tasks_mod:messages' : Vanilla acceptance test: ACCEPTED
[Netty Client IO #0/DEBUG] [ne.mi.ne.NetworkRegistry/NETREGISTRY]: Accepting channel list from vanilla
[Render thread/INFO] [minecraft/ConnectScreen]: Connecting to 127.0.0.1, 25565
[Netty Client IO #1/DEBUG] [ne.mi.ne.HandshakeHandler/FMLHANDSHAKE]: Starting new vanilla impl connection.
[Netty Client IO #1/INFO] [ne.mi.ne.NetworkHooks/]: Connected to a vanilla server. Catching up missing behaviour.
[Netty Client IO #1/DEBUG] [ne.mi.co.ForgeConfig/FORGEMOD]: Loaded forge config file forge-server.toml
[Netty Client IO #1/ERROR] [ne.mi.ne.si.IndexedMessageCodec/SIMPLENET]: Received invalid discriminator byte 208 on channel custom_tasks_mod:messages
[Render thread/DEBUG] [ne.mi.ne.fi.NetworkFilters/]: Injected net.minecraftforge.network.filters.VanillaConnectionNetworkFilter@40db6136 into net.minecraft.network.Connection@5ced0537
[Render thread/DEBUG] [io.ne.ut.in.ThreadLocalRandom/]: -Dio.netty.initialSeedUniquifier: 0x854db3e7da8e9393
[Render thread/WARN] [minecraft/ClientPacketListener]: Unknown custom packet identifier: custom_tasks_mod:messages

 

  • Like 1
Link to comment
Share on other sites

I've solved this it was easier then that ways I've used.

Sources that were changed (if someone fold have the same problem):

For PluginMessages you must use

Spoiler
private static final String PROTOCOL_VERSION = "1.0";

public static final EventNetworkChannel EVENT_NETWORK_CHANNEL = NetworkRegistry.newEventChannel(
    new ResourceLocation("your_channel", "your_subchannel"),
    () -> PROTOCOL_VERSION,
    (s) -> true,
    (s) -> true
);

public static void register() {
    EVENT_NETWORK_CHANNEL.addListener(IsInstalledPacketEvents::onPacketReceive);
}

For IsInstalledPacketEvents

Spoiler
@Mod.EventBusSubscriber(modid = CustomTasks.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class IsInstalledPacketEvents {
    private static final Logger LOGGER = LogUtils.getLogger();

    @SubscribeEvent
    public static void onPacketReceive(NetworkEvent.ServerCustomPayloadEvent event) {
        NetworkEvent.ServerCustomPayloadEvent e = event;
        LOGGER.info(event.getPayload().toString(StandardCharsets.UTF_8));
    }

}

 

Then you can handle it as you want. Good luck for everyone!

  • Like 1
Link to comment
Share on other sites

  • 3 months later...
On 11/14/2022 at 1:49 PM, liponex said:

I've solved this it was easier then that ways I've used.

Sources that were changed (if someone fold have the same problem):

For PluginMessages you must use

  Hide contents
private static final String PROTOCOL_VERSION = "1.0";

public static final EventNetworkChannel EVENT_NETWORK_CHANNEL = NetworkRegistry.newEventChannel(
    new ResourceLocation("your_channel", "your_subchannel"),
    () -> PROTOCOL_VERSION,
    (s) -> true,
    (s) -> true
);

public static void register() {
    EVENT_NETWORK_CHANNEL.addListener(IsInstalledPacketEvents::onPacketReceive);
}

For IsInstalledPacketEvents

  Hide contents
@Mod.EventBusSubscriber(modid = CustomTasks.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class IsInstalledPacketEvents {
    private static final Logger LOGGER = LogUtils.getLogger();

    @SubscribeEvent
    public static void onPacketReceive(NetworkEvent.ServerCustomPayloadEvent event) {
        NetworkEvent.ServerCustomPayloadEvent e = event;
        LOGGER.info(event.getPayload().toString(StandardCharsets.UTF_8));
    }

}

 

Then you can handle it as you want. Good luck for everyone!

Very cool, how about forge client send custom packet to (Paper/Spigot/Bukkit) server?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • i tried to open the modpack with multimc by importing it from Ftb and it gave me an error https://paste.ee/p/YDqWN
    • Hi, I'm trying to render a single quad in the world. I'm mixing into the ChestRenderer class. If I understand correctly, BufferSource#getBuffer opens a buffer according to the supplied RenderType (Quads with POSITION_COLOR in my case). Then, I can supply my vertices (a simple 1-block plane along the Z Axis) and close the buffer using BufferSource#endBatch for rendering. This is the code I'm using: @Inject(at = @At("TAIL"), method = "render(...)V") public void render(T blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource multiBufferSource, int packedLight, int packedOverlay, CallbackInfo ci) { BlockPos pos = blockEntity.getBlockPos(); AABB box = new AABB(pos, pos.offset(1, 1, 1)); BufferSource buffer = Minecraft.getInstance().renderBuffers().bufferSource(); VertexConsumer consumer = buffer.getBuffer(RenderType.guiOverlay()); poseStack.pushPose(); poseStack.translate(-pos.getX(), -pos.getY(), -pos.getZ()); consumer.vertex(box.minX, box.maxY, box.minZ).color(1, 1, 1, 1).endVertex(); consumer.vertex(box.minX, box.maxY, box.maxZ).color(1, 1, 1, 1).endVertex(); consumer.vertex(box.minX, box.minY, box.maxZ).color(1, 1, 1, 1).endVertex(); consumer.vertex(box.minX, box.minY, box.minZ).color(1, 1, 1, 1).endVertex(); buffer.endBatch(RenderType.guiOverlay()); poseStack.popPose(); } However, the plane does not get rendered. However, if I replace those 4 vertices with a call to LevelRenderer#renderLineBox and set the RenderType to LINES, it works. Do I need something else to render planes other than the 4 edges of the quad? I used QUADS back in 1.8 where it was still the raw OpenGL type and it worked then. Or am I missing something else entirely? Thanks!
    • The Essential Role of Brunoe Quick Hack in Bitcoin Recovery Efforts The Brunoe Quick Hack has emerged as a vital tool in the ongoing efforts to recover lost or stolen Bitcoin. As the cryptocurrency landscape has evolved, the need for reliable and effective methods to regain access to misplaced or compromised digital assets has become increasingly pressing. The Brunoe Quick Hack, a specialized software solution, has stepped in to fill this critical void, offering Bitcoin users a lifeline when faced with the devastating prospect of permanently losing their hard-earned cryptocurrency holdings. At the core of this innovative technique lies a deep understanding of the underlying blockchain technology that powers Bitcoin, combined with a meticulous, methodical approach to identifying and exploiting vulnerabilities in the system. Through a series of carefully orchestrated steps, the Brunoe Quick Hack is able to bypass security measures, recover private keys, and restore access to Bitcoin wallets that were previously thought to be irretrievable. This process, while highly technical and requiring a skilled hand, has proven to be a game-changer for countless individuals and businesses who have fallen victim to the inherent risks of the cryptocurrency ecosystem. As the adoption of Bitcoin continues to grow, the Brunoe Quick Hack has emerged as an essential safeguard, providing a crucial safety net for those navigating the complex and ever-evolving world of digital finance. Contact this experts through: WhtasApp: + 170-"578-42"-635 Website: brunoequickhack.COM Email: brunoequickhack (AT) GMAIL (DOT) COM Thanks.
    • it doesnt let me import the zip that i use with curseforge
    • it doesnt let me import the zip that i use with curseforge
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.