Yes, my title sounds like I'm insane, but bear with me.
I'm trying to log everything a Minecraft Forge mod sends via its SimpleNetworkWrapper instance. To do this, I'm wrapping the instance in a dummy class and inserting the dummy instance into the mod via reflection.
Dummy class:
package net.benjaminurquhart.decimated;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.Packet;
public class FakeNetworkWrapper extends SimpleNetworkWrapper {
private SimpleNetworkWrapper real;
public FakeNetworkWrapper() {
super("ctx");
}
protected void setChannel(SimpleNetworkWrapper channel) {
this.real = channel;
}
@Override
public Packet getPacketFrom(IMessage message) {
return real.getPacketFrom(message);
}
@Override
public void sendToAll(IMessage message) {
real.sendToAll(message);
}
@Override
public void sendTo(IMessage message, EntityPlayerMP player) {
real.sendTo(message, player);
}
@Override
public void sendToServer(IMessage message) {
// Intercept messages here, do logging stuff
real.sendToServer(message);
}
}
The problem is, the superclass constructor creates a new packet channel with the given name (in this case, ctx). This breaks the real channel, since I'm creating a new channel with the same name. I can't omit the super call since there's no default constructor, and I prefer not to make a new unused channel with a different name.
Currently, I'm getting around the constructor by using Unsafe:
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
unsafe = (Unsafe) unsafeField.get(null);
FakeNetworkWrapper wrapper = (FakeNetworkWrapper) unsafe.allocateInstance(FakeNetworkWrapper.class);
wrapper.setChannel(mod.getPacketChannel());
Obviously, I'd like to not use internal classes.
A quick google search shows that I can use serialization or ReflectionFactory instead of Unsafe. ReflectionFactory is also an internal class and serialization seems overkill. I'd also like to not include dependencies not provided by Forge (like this answer suggests).
Is there a way to somehow bypass a call to the superclass constructor without using internal methods or serialization? Again, I understand this is something I shouldn't be doing, but I don't see another way.
Aucun commentaire:
Enregistrer un commentaire