-
-
Save Torins/eaa90300fd47c70404be to your computer and use it in GitHub Desktop.
Vazkii's Message using PacketBuffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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