• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / CyclopsCore / #479033853

06 Nov 2026 12:50PM UTC coverage: 23.052% (+0.005%) from 23.047%
#479033853

Pull #259

github

claude
Log packet encoding and decoding errors

When a packet fails to encode or decode, vanilla disconnects with
"Internal Exception" but only logs the cause at debug level, so it is
missing from latest.log. Log the full stack trace at error level, so
these disconnects can be diagnosed from regular logs.

The decoding error now names the packet class instead of a fresh
instance's toString, which also avoids an NPE when construction failed.

Related to #258

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UeSuG8Sp4V22VPUqWFGwM7
Pull Request #259: Fix packets failing to decode when a map is modified while encoding, and log codec errors

2 of 6 new or added lines in 2 files covered. (33.33%)

28 existing lines in 1 file now uncovered.

2444 of 10602 relevant lines covered (23.05%)

0.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/org/cyclops/cyclopscore/network/PacketHandler.java
1
package org.cyclops.cyclopscore.network;
2

3
import com.google.common.base.Predicates;
4
import io.netty.channel.ChannelHandler.Sharable;
5
import net.minecraft.client.Minecraft;
6
import net.minecraft.client.player.LocalPlayer;
7
import net.minecraft.resources.ResourceKey;
8
import net.minecraft.resources.ResourceLocation;
9
import net.minecraft.server.level.ServerPlayer;
10
import net.minecraft.world.level.Level;
11
import net.minecraftforge.api.distmarker.Dist;
12
import net.minecraftforge.api.distmarker.OnlyIn;
13
import net.minecraftforge.network.NetworkDirection;
14
import net.minecraftforge.network.NetworkEvent;
15
import net.minecraftforge.network.NetworkRegistry;
16
import net.minecraftforge.network.PacketDistributor;
17
import net.minecraftforge.network.simple.SimpleChannel;
18
import org.cyclops.cyclopscore.CyclopsCore;
19
import org.cyclops.cyclopscore.helper.Helpers;
20
import org.cyclops.cyclopscore.helper.Helpers.IDType;
21
import org.cyclops.cyclopscore.init.ModBase;
22

23
import java.lang.reflect.Constructor;
24
import java.lang.reflect.InvocationTargetException;
25

26
/**
27
 * Advanced packet handler of {@link PacketBase} instances.
28
 * An alternative would be {@link SimpleChannel}.
29
 * @author rubensworks
30
 */
31
@Sharable
32
public final class PacketHandler {
33

34
    private final ModBase mod;
35

36
    private SimpleChannel networkChannel = null;
×
37

38
    public PacketHandler(ModBase mod) {
×
39
        this.mod = mod;
×
40
    }
×
41

42
    public void init() {
43
        if(networkChannel == null) {
×
44
            networkChannel = NetworkRegistry.newSimpleChannel(
×
45
                    new ResourceLocation(mod.getModId(), "channel_main"), () -> "1.0.0",
×
46
                    Predicates.alwaysTrue(), Predicates.alwaysTrue());
×
47
        }
48
    }
×
49

50
    /**
51
     * Register a new packet.
52
     * @param packetType The class of the packet.
53
     * @param <P> The packet type.
54
     */
55
    public <P extends PacketBase> void register(Class<P> packetType) {
56
        int discriminator = Helpers.getNewId(mod, IDType.PACKET);
×
57
        try {
58
            Constructor<P> constructor = packetType.getConstructor();
×
59
            networkChannel.registerMessage(discriminator, packetType,
×
60
                    (packet, packetBuffer) -> {
61
                        try {
62
                            packet.encode(packetBuffer);
×
63
                        } catch (Throwable e) {
×
NEW
64
                            throw logCodecException("An exception occurred during encoding of packet " + packet.toString(), e);
×
65
                        }
×
66
                    },
×
67
                    (packetBuffer) -> {
68
                        P packet = null;
×
69
                        try {
70
                            packet = constructor.newInstance();
×
71
                        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
×
72
                            e.printStackTrace();
×
73
                        }
×
74
                        try {
75
                            packet.decode(packetBuffer);
×
76
                        } catch (Throwable e) {
×
NEW
77
                            throw logCodecException("An exception occurred during decoding of packet " + packetType.getName(), e);
×
78
                        }
×
79
                        return packet;
×
80
                    },
81
                    (packet, contextSupplier) -> {
82
                        NetworkEvent.Context context = contextSupplier.get();
×
83
                        if (context.getDirection().getReceptionSide().isClient()) {
×
84
                            if (packet.isAsync()) {
×
85
                                handlePacketClient(context, packet);
×
86
                            } else {
87
                                context.enqueueWork(() -> handlePacketClient(context, packet));
×
88
                            }
89
                        } else {
90
                            if (packet.isAsync()) {
×
91
                                handlePacketServer(context, packet);
×
92
                            } else {
93
                                context.enqueueWork(() -> handlePacketServer(context, packet));
×
94
                            }
95
                        }
96
                        context.setPacketHandled(true);
×
97
                    });
×
98
        } catch (NoSuchMethodException e) {
×
99
            e.printStackTrace();
×
100
            CyclopsCore.clog(org.apache.logging.log4j.Level.ERROR, "Could not find a default constructor for packet " + packetType.getName());
×
101
        }
×
102
    }
×
103

104
    // Vanilla only logs the cause at debug level when disconnecting, so log it here.
105
    private PacketCodecException logCodecException(String message, Throwable cause) {
NEW
106
        mod.getLoggerHelper().getLogger().error(message, cause);
×
NEW
107
        return new PacketCodecException(message, cause);
×
108
    }
109

110
    @OnlyIn(Dist.CLIENT)
111
    public void handlePacketClient(NetworkEvent.Context context, PacketBase packet) {
112
        LocalPlayer player = Minecraft.getInstance().player;
×
113
        packet.actionClient(player != null ? player.level() : null, player);
×
114
    }
×
115

116
    public void handlePacketServer(NetworkEvent.Context context, PacketBase packet) {
117
        packet.actionServer(context.getSender().level(), context.getSender());
×
118
    }
×
119

120
    /**
121
     * Send a packet to the server.
122
     * @param packet The packet.
123
     */
124
    public void sendToServer(PacketBase packet) {
125
        networkChannel.sendToServer(packet);
×
126
    }
×
127

128
    /**
129
     * Send a packet to the player.
130
     * @param packet The packet.
131
     * @param player The player.
132
     */
133
    public void sendToPlayer(PacketBase packet, ServerPlayer player) {
134
        networkChannel.sendTo(packet, player.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
×
135
    }
×
136

137
    /**
138
     * Send a packet to all in the target range.
139
     * @param packet The packet.
140
     * @param point The area to send to.
141
     */
142
    public void sendToAllAround(PacketBase packet, PacketDistributor.TargetPoint point) {
143
        PacketDistributor.PacketTarget target = PacketDistributor.NEAR.with(() -> point);
×
144
        target.send(networkChannel.toVanillaPacket(packet, target.getDirection()));
×
145
    }
×
146

147
    /**
148
     * Send a packet to everything in the given dimension.
149
     * @param packet The packet.
150
     * @param dimension The dimension to send to.
151
     */
152
    public void sendToDimension(PacketBase packet, ResourceKey<Level> dimension) {
153
        PacketDistributor.PacketTarget target = PacketDistributor.DIMENSION.with(() -> dimension);
×
154
        target.send(networkChannel.toVanillaPacket(packet, target.getDirection()));
×
155
    }
×
156

157
    /**
158
     * Send a packet to everything.
159
     * @param packet The packet.
160
     */
161
    public void sendToAll(PacketBase packet) {
162
        PacketDistributor.PacketTarget target = PacketDistributor.ALL.with(() -> null);
×
163
        target.send(networkChannel.toVanillaPacket(packet, target.getDirection()));
×
164
    }
×
165

166
    public static class PacketCodecException extends RuntimeException {
167
        public PacketCodecException(String message, Throwable cause) {
168
            super(message, cause);
×
169
        }
×
170
    }
171

172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc