package speedytools.common.network.multipart; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.relauncher.Side; import io.netty.buffer.ByteBuf; import speedytools.SpeedyToolsMod; import speedytools.common.network.Packet250Base; import speedytools.common.network.Packet250Types; import speedytools.common.network.PacketHandlerRegistry; import speedytools.common.utilities.ErrorLog; import java.util.BitSet; import java.util.HashMap; import java.util.Map; /** * This class is used by the server to acknowledge a multipart segment from the sender */ public class Packet250MultipartSegmentAcknowledge extends Packet250Base { /** * The packet returns information to the sender about the progress of the multipacket segments */ public Packet250MultipartSegmentAcknowledge(Packet250Types i_packet250Type, Acknowledgement i_acknowledgement, int i_uniquePacketID, BitSet i_segmentsNotReceivedYet) { acknowledgement = i_acknowledgement; segmentsNotReceivedYet = i_segmentsNotReceivedYet; packet250Type = i_packet250Type; uniqueMultipartID = i_uniquePacketID; packetIsValid = true; } public Packet250MultipartSegmentAcknowledge() // used by Netty to create packet; invalid until populated by packet handler { // default constructor sets packet invalid, does nothing else } public Packet250Types getPacket250Type() { return packet250Type; } public int getUniqueID() { return uniqueMultipartID; } public Acknowledgement getAcknowledgement() { return acknowledgement; } public BitSet getSegmentsNotReceivedYet() { return segmentsNotReceivedYet; } @Override public void readFromBuffer(ByteBuf buf) { try { packetIsValid = false; packet250Type = Packet250Types.byteToPacket250Type(buf.readByte()); uniqueMultipartID = buf.readInt(); acknowledgement = Acknowledgement.byteToAcknowledgement(buf.readByte()); short ackDataLength = buf.readShort(); if (ackDataLength < 0) { ErrorLog.defaultLog().info("Invalid data length on incoming Packet250MultipartSegmentAcknowledge: " + ackDataLength); return; } byte [] rawBuffer = new byte[ackDataLength]; if (ackDataLength != 0) { buf.readBytes(rawBuffer); if (buf.readableBytes() != 0) { ErrorLog.defaultLog().info("still had " + buf.readableBytes() + " left after reading " + ackDataLength + " bytes from Packet250MultipartSegmentAcknowledge"); return; } } segmentsNotReceivedYet = BitSet.valueOf(rawBuffer); } catch (IndexOutOfBoundsException ioe) { ErrorLog.defaultLog().info("Exception while reading Packet250MultipartSegmentAcknowledge: " + ioe); return; } if (!checkInvariants()) return; packetIsValid = true; } @Override public void writeToBuffer(ByteBuf buf) { checkInvariants(); if (!isPacketIsValid()) return; buf.writeByte(packet250Type.getPacketTypeID()); buf.writeInt(uniqueMultipartID); buf.writeByte(acknowledgement.getID()); if (segmentsNotReceivedYet == null) { buf.writeShort(0); } else { byte [] rawBytes = segmentsNotReceivedYet.toByteArray(); buf.writeShort(rawBytes.length); buf.writeBytes(rawBytes); } } /** * checks this class to see if it is internally consistent * @return true if ok, false if bad. */ private boolean checkInvariants() { if (acknowledgement == null) return false; if (acknowledgement == Acknowledgement.ABORT && segmentsNotReceivedYet != null) return false; return true; } /** * Register the handler for this packet * @param packetHandlerRegistry * @param packetHandlerMethod * @param side */ public static void registerHandler(PacketHandlerRegistry packetHandlerRegistry, PacketHandlerMethod packetHandlerMethod, Side side, Packet250Types packet250Type) { if (packetHandlerMethod == null) { ErrorLog.defaultLog().severe("tried to register a null PacketHandlerMethod"); return; } switch (side) { case CLIENT: { clientSideHandlers.put(packet250Type, packetHandlerMethod); break; } case SERVER: { serverSideHandlers.put(packet250Type, packetHandlerMethod); break; } default: { assert false : "Tried to register Packet250MultipartSegmentAcknowledge on side " + side; } } SimpleNetworkWrapper simpleNetworkWrapper = packetHandlerRegistry.getSimpleNetworkWrapper(); if (simpleNetworkWrapper != null) { // might be null for testing simpleNetworkWrapper.registerMessage(CommonMessageHandler.class, Packet250MultipartSegmentAcknowledge.class, packet250Type.getPacketTypeID(), side); } } public interface PacketHandlerMethod { public boolean handlePacket(Packet250MultipartSegmentAcknowledge packet250CloneToolAcknowledge, MessageContext ctx); } public static class CommonMessageHandler implements IMessageHandler<Packet250MultipartSegmentAcknowledge, IMessage> { /** * Called when a message is received of the appropriate type. You can optionally return a reply message, or null if no reply * is needed. * * @param message The message * @return an optional return message */ public IMessage onMessage(final Packet250MultipartSegmentAcknowledge message, final MessageContext ctx) { Packet250Types packet250Type = message.getPacket250Type(); PacketHandlerMethod handlerMethod = null; switch (ctx.side) { case CLIENT: { handlerMethod = clientSideHandlers.get(packet250Type); break; } case SERVER: { handlerMethod = serverSideHandlers.get(packet250Type); break; } default: assert false : "Received message on invalid side: " + ctx.side; } if (handlerMethod == null) { ErrorLog.defaultLog().severe("Packet250MultipartSegmentAcknowledge for packet type " + packet250Type + " received but not registered on side " + ctx.side); } else { final PacketHandlerMethod handlerMethodFinal = handlerMethod; Runnable messageProcessor = new Runnable() { @Override public void run() { handlerMethodFinal.handlePacket(message, ctx); } }; boolean success = SpeedyToolsMod.proxy.enqueueMessageOnCorrectThread(ctx, messageProcessor); if (!success) { ErrorLog.defaultLog().severe("Packet250MultipartSegmentAcknowledge failed to handle Packet"); } } return null; } } public enum Acknowledgement { ACKNOWLEDGEMENT(200), ACKNOWLEDGE_ALL(201), ABORT(202); public byte getID() {return rawID;} public static Acknowledgement byteToAcknowledgement(byte value) { for (Acknowledgement acknowledgement : Acknowledgement.values()) { if (value == acknowledgement.getID()) return acknowledgement; } return null; } private Acknowledgement(int i_rawID) { rawID = (byte)i_rawID; } private final byte rawID; } private static Map<Packet250Types, PacketHandlerMethod> serverSideHandlers = new HashMap<Packet250Types, PacketHandlerMethod>(); private static Map<Packet250Types, PacketHandlerMethod> clientSideHandlers = new HashMap<Packet250Types, PacketHandlerMethod>(); private Packet250Types packet250Type; private int uniqueMultipartID; private Acknowledgement acknowledgement; private BitSet segmentsNotReceivedYet; }