Skip to content

Instantly share code, notes, and snippets.

@Torins
Created January 12, 2016 15:10
Show Gist options
  • Save Torins/eaa90300fd47c70404be to your computer and use it in GitHub Desktop.
Save Torins/eaa90300fd47c70404be to your computer and use it in GitHub Desktop.
Vazkii's Message using PacketBuffer
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Psi Mod. Get the Source Code in github:
* https://github.com/Vazkii/Psi
*
* Psi is Open Source and distributed under the
* CC-BY-NC-SA 3.0 License: https://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB
*
* File Created @ [11/01/2016, 22:00:30 (GMT)]
*/
package vazkii.psi.common.network;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import net.minecraft.network.PacketBuffer;
import org.apache.commons.lang3.tuple.Pair;
import io.netty.buffer.ByteBuf;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.BlockPos;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
public class Message<REQ extends Message> implements Serializable, IMessage, IMessageHandler<REQ, IMessage> {
private static final HashMap<Class, Pair<Reader, Writer>> handlers = new HashMap<>();
static {
map(byte.class, PacketBuffer::readByte, (buf, data) -> buf.writeByte((int) data));
map(short.class, PacketBuffer::readShort, (buf, data) -> buf.writeShort((int) data));
map(int.class, PacketBuffer::readVarIntFromBuffer, PacketBuffer::writeVarIntToBuffer);
map(long.class, PacketBuffer::readVarLong, PacketBuffer::writeVarLong);
map(float.class, PacketBuffer::readFloat, PacketBuffer::writeFloat);
map(double.class, PacketBuffer::readDouble, PacketBuffer::writeDouble);
map(boolean.class, PacketBuffer::readBoolean, PacketBuffer::writeBoolean);
map(char.class, PacketBuffer::readChar, (buf, data) -> buf.writeChar((int) data));
map(String.class, (buf) -> buf.readStringFromBuffer(32767), PacketBuffer::writeString);
map(NBTTagCompound.class, PacketBuffer::readNBTTagCompoundFromBuffer, PacketBuffer::writeNBTTagCompoundToBuffer);
map(ItemStack.class, PacketBuffer::readItemStackFromBuffer, PacketBuffer::writeItemStackToBuffer);
map(BlockPos.class, PacketBuffer::readBlockPos, PacketBuffer::writeBlockPos);
}
// The thing you override!
public IMessage handleMessage(MessageContext context) {
return null;
}
@Override
public final IMessage onMessage(REQ message, MessageContext context) {
return message.handleMessage(context);
}
@Override
public final void fromBytes(ByteBuf buf) {
try {
PacketBuffer packetBuffer = new PacketBuffer(buf);
Class<?> clazz = getClass();
for(Field f : clazz.getDeclaredFields()) {
Class<?> type = f.getType();
if(acceptField(f, type))
readField(f, type, packetBuffer);
}
} catch(Exception e) {
throw new RuntimeException("Error at reading packet " + this, e);
}
}
@Override
public final void toBytes(ByteBuf buf) {
try {
PacketBuffer packetBuffer = new PacketBuffer(buf);
Class<?> clazz = getClass();
for(Field f : clazz.getDeclaredFields()) {
Class<?> type = f.getType();
if(acceptField(f, type))
writeField(f, type, packetBuffer);
}
} catch(Exception e) {
throw new RuntimeException("Error at writing packet " + this, e);
}
}
private final void writeField(Field f, Class clazz, PacketBuffer buf) throws IllegalArgumentException, IllegalAccessException {
Pair<Reader, Writer> handler = getHandler(clazz);
handler.getRight().write(buf, f.get(this));
}
private final void readField(Field f, Class clazz, PacketBuffer buf) throws IllegalArgumentException, IllegalAccessException, IOException {
Pair<Reader, Writer> handler = getHandler(clazz);
f.set(this, handler.getLeft().read(buf));
}
private static Pair<Reader, Writer> getHandler(Class<?> clazz) {
Pair<Reader, Writer> pair = handlers.get(clazz);
if(pair == null)
throw new RuntimeException("No R/W handler for " + clazz);
return pair;
}
private static boolean acceptField(Field f, Class<?> type) {
int mods = f.getModifiers();
if(Modifier.isFinal(mods) || Modifier.isStatic(mods) || Modifier.isTransient(mods))
return false;
return handlers.containsKey(type);
}
private static <T extends Object>void map(Class<T> type, Reader<T> reader, Writer<T> writer) {
handlers.put(type, Pair.of(reader, writer));
}
public interface Writer<T extends Object> {
void write(PacketBuffer buf, T t);
}
public interface Reader<T extends Object> {
T read(PacketBuffer buf) throws IOException;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment