public static Packet parse(TYPES[] struct, byte[] raw) { //create a queue to store the TYPES to pair with the raw bytes Queue<TYPES> queue = new LinkedList<TYPES>(); //populate the queue for (int i = 0; i < struct.length; i++) { queue.offer(struct[i]); } // Variables for keeping track of the byte array ByteBuffer bb = ByteBuffer.wrap(raw); //bytebuffer from which currentBytes is gotten byte[] currentBytes; //current raw bytes of the Object int currentSize; //size (in bytes) of the current object int offset = 0; //offset of our current position MODE mode = MODE.NONE; //ya. List objects = new LinkedList(); //final objects for the packet List<TYPES> repeated = new LinkedList<TYPES>(); boolean dynamic = false; int len = raw.length - 2; int dynamicSize = 0; //size (in bytes) of the repeated part of the packet // Read the first 2 bytes (short) off the ByteBuffer byte[] IDbytes = new byte[2]; bb.get(IDbytes); int ID = IDbytes[0] & 0x0FF; //TODO: Make this word for packets > 256 (currently none). // The first two bytes are always the packet ID. while(queue.peek() != null) { TYPES currentType = queue.poll(); currentSize = TYPES.sizeof(currentType); currentBytes = new byte[currentSize]; bb.get(currentBytes); //read currentBytes from the bytebuffer switch (mode) { case NONE: switch (currentType) { case SPECIAL_DYNAMIC_PACKET: dynamic = true; break; case SPECIAL_MARK_REPEAT: mode = MODE.COUNT; bb.mark(); break; //SPECIAL_DO_REPEAT is in COUNT case SPECIAL_LEN: len = (Integer)TYPES.convert(currentType, currentBytes); default: objects.add(TYPES.convert(currentType, currentBytes)); break; } //increment the offset for the next read offset += currentSize; break; case COUNT: if (currentType == TYPES.SPECIAL_DO_REPEAT) { mode = MODE.REPEAT; bb.reset(); //Reset ByteBuffer because the last things were counted, not read. //Do initial repeat adding things: for (TYPES t: repeated) { if (!queue.offer(t)) { System.err.println("Oh shit!! :("); } else { //VERBOSE: System.out.println("Added: "+t); } } } else { repeated.add(currentType); dynamicSize += currentSize; } break; case REPEAT: objects.add(TYPES.convert(currentType, currentBytes)); offset += currentSize; if (queue.peek() != null) { } else { if (offset + dynamicSize < len) { //Is there enough room for another dynamic part? //if there's still shit in the packet, repeat for (TYPES t: repeated) { if (!queue.offer(t)) { System.err.println("Oh shit :("); } else { //VERBOSE: System.out.println("Added: "+t); } } } } } System.out.println(currentType + " ["+currentSize+ "] " + TYPES.convert(currentType, currentBytes) + " Offset: " + offset + "/" + len + " " +openro.StringUtil.byteArrayToHexString(currentBytes)); } return new Packet(ID, raw.length, objects.toArray(), raw, dynamic); }