Hey, I'm currently struggling a bit on the following;

I am basically trying to add the new 'HitSplat' System, where before everyone had the same 'Hit Splat ID', now players have separate IDs depending on the scenario, currently in HitsUpdates we send along the data of the Hit and capture the data. But the only issue is, that you can't filter between the Players receiving the data from send(OutBuffer out, boolean playerUpdate) and it just sends to everyone I assume?

Code:
package io.ruin.model.entity.shared.masks;

import io.ruin.GameServer;
import io.ruin.api.buffer.OutBuffer;
import io.ruin.model.combat.Hit;
import io.ruin.model.entity.Entity;
import io.ruin.model.entity.shared.UpdateMask;

import java.util.ArrayList;

public class HitsUpdate extends UpdateMask {

    /**
     * Ratio calc
     */

    private static final int[][] RATIO_DATA = {
            {30, 30},       //0
            {100, 100},     //1
            {120, 120},     //2
            {160, 160},     //3
            {120, 120},     //4
            {60, 60},       //5
            {100, 100},     //6
            {100, 100},     //7
            {120, 120},     //8
    };
    private final ArrayList<Splat> splats = new ArrayList<>(4);
    public int hpBarType;
    public int curHp, maxHp;

    public long removeAt;
    private int hpBarRatio;
    private boolean forceSend = false;

    private static int toRatio(int type, int min, int max) {
        int ratio = (Math.min(min, max) * RATIO_DATA[type][0]) / max;
        if (ratio == 0 && min > 0)
            ratio = 1;
        return ratio;
    }

    public void add(Hit hit, Entity attacker, Entity defender, boolean maxDamage, int curHp, int maxHp) {
        if (splats.size() < 6)
            splats.add(new Splat(hit.type.id, attacker, defender, maxDamage, hit.damage, 0));
        this.hpBarRatio = toRatio(hpBarType, curHp, maxHp);
        this.curHp = curHp;
        this.maxHp = maxHp;
        this.removeAt = GameServer.getEnd(10);
    }

    /**
     * For showing HP bar without any hits
     */
    public void forceSend(int curHp, int maxHp) {
        hpBarRatio = toRatio(hpBarType, curHp, maxHp);
        forceSend = true;
    }

    @Override
    public void reset() {
        splats.clear();
        forceSend = false;
    }

    @Override
    public boolean hasUpdate(boolean added) {
        return forceSend || !splats.isEmpty();
    }

    @Override
    public void send(OutBuffer out, boolean playerUpdate) {
        if (playerUpdate) {
            out.addByte(splats.size());
        } else {
            out.addByteA(splats.size());
        }

        for (Splat splat : splats) {
            out.addSmart(splat.type);
            out.addSmart(splat.damage);
            out.addSmart(splat.delay);
        }
        if (playerUpdate)
            out.addByteC(1); //hp bar count
        else
            out.addByte(1); //hp bar count

        out.addSmart(hpBarType);
        out.addSmart(0); //second bar type
        out.addSmart(0); //hp bar delay
        if (playerUpdate) {
            out.addByte(hpBarRatio);
        } else {
            out.addByteC(hpBarRatio);
        }
    }

    @Override
    public int get(boolean playerUpdate) {
        return playerUpdate ? 0x80 : 0x80;
    }

    private static final class Splat {

        private int type, damage, delay;
        Entity attacker, defender;
        private boolean maxDamage;

        public Splat(int type, Entity attacker, Entity defender, boolean maxDamage, int damage, int delay) {
            this.type = type;
            this.attacker = attacker;
            this.defender = defender;
            this.maxDamage = maxDamage;
            this.damage = damage;
            this.delay = delay;
        }

    }

}
Here is also the OutBuffer code

Code:
package io.ruin.api.buffer;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.ruin.api.utils.ISAACCipher;
import io.ruin.api.utils.ServerWrapper;

import java.math.BigInteger;
import java.util.Arrays;

public class OutBuffer {

    private static final byte FIXED_TYPE = 1, VAR_BYTE_TYPE = 2, VAR_SHORT_TYPE = 3, VAR_INT_TYPE = 4;

    private static final int[] BIT_MASK = new int[32];
    public static BigInteger RSA_EXPONENT = new BigInteger("65537");
    public static BigInteger RSA_MODULUS = new BigInteger(
            "94210824259843347324509385276594109263523823612210415282840685497179394322370180677069205378760490069724955139827325518162089726630921395369270393801925644637806226306156731189625154078707248525519618118185550146216513714101970726787284175941436804270501308516733103597242337227056455402809871503542425244523");

    static {
        for (int i = 0; i < 32; i++)
            BIT_MASK[i] = (1 << i) - 1;
    }
/*
    public byte[] toByteArray() {
        byte[] data = new byte[position];
        int length = Math.min(position, payload.length);
        for(int i = 0; i < length; i++)
            data[i] = payload[i];
        return data;
    }
*/

    /**
     * Separator
     */

    private byte[] payload;
    /**
     * Position
     */

    private int position;
    /**
     * Encryption
     */

    private int startEncryptPosition = -1;
    private int stopEncryptPosition = -1;
    /**
     * Packets
     */

    private int sizePosition;
    private int type;
    /**
     * Bit access
     */

    private int bitPosition;

    public OutBuffer(int size) {
        this.payload = new byte[size];
    }

    public byte[] toByteArray() {
        byte[] bytes = new byte[position];
        System.arraycopy(payload, 0, bytes, 0, bytes.length);

        byte[] bytes2 = new byte[position];
        int length = Math.min(position, payload.length);
        for (int i = 0; i < length; i++)
            bytes2[i] = payload[i];
        if (!Arrays.equals(bytes, bytes2))
            ServerWrapper.logError(new Throwable()); //I want to see if this happens lol..

        return bytes;
    }

    public ByteBuf toBuffer() {
        return Unpooled.wrappedBuffer(toByteArray());
    }

    public byte[] payload() {
        return payload;
    }

    public void position(int position) {
        this.position = position;
    }

    public OutBuffer skip(int skip) {
        resizeIfNeeded(position + skip);
        position += skip;
        return this;
    }

    public int position() {
        return position;
    }

    /**
     * Setting
     */

    public OutBuffer setByte(int position, int value) {
        resizeIfNeeded(position);
        payload[position] = (byte) value;
        return this;
    }

    public void resizeIfNeeded(int newLength) {
        if (newLength < payload.length)
            return;
        if (type == FIXED_TYPE) {
            int opcode = payload[0] & 0xff;
            //System.err.println("Increase packet size for: " + opcode);
            try {
                throw new Exception("Increase packet size for " + opcode);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        byte[] newBuffer = new byte[newLength * 2];
        System.arraycopy(payload, 0, newBuffer, 0, payload.length);
        payload = newBuffer;
    }

    public OutBuffer startEncrypt() {
        startEncryptPosition = position;
        return this;
    }

    public OutBuffer stopEncrypt() {
        stopEncryptPosition = position;
        return this;
    }

    public void encrypt(ISAACCipher cipher) {
        int length = stopEncryptPosition == -1 ? position : stopEncryptPosition;
        for (int i = startEncryptPosition; i < length; i++)
            payload[i] += (byte) cipher.readKey();
        startEncryptPosition = stopEncryptPosition = -1;
    }

    public OutBuffer sendFixedPacket(int opcode) {
        addByte(opcode);
        type = FIXED_TYPE;
        return this;
    }

    public OutBuffer sendVarBytePacket(int opcode) {
        addByte(opcode);
        type = VAR_BYTE_TYPE;
        sizePosition = position;
        addByte(0); //"byte" size
        return this;
    }

    public OutBuffer sendVarShortPacket(int opcode) {
        addByte(opcode);
        type = VAR_SHORT_TYPE;
        sizePosition = position;
        addShort(0); //"short" size
        return this;
    }

    public OutBuffer sendVarIntPacket(int opcode) {
        addByte(opcode);
        type = VAR_INT_TYPE;
        sizePosition = position;
        addInt(0); //"int" size
        return this;
    }

    public OutBuffer encode(ISAACCipher cipher) {
        if (cipher != null) {
            payload[0] += (byte) cipher.readKey();
        }
        if (type == VAR_BYTE_TYPE) {
            int size = position - (sizePosition + 1);
            setByte(sizePosition, size);
        } else if (type == VAR_SHORT_TYPE) {
            int size = position - (sizePosition + 2);
            setByte(sizePosition, size >> 8);
            setByte(sizePosition + 1, size);
        } else if (type == VAR_INT_TYPE) {
            int size = position - (sizePosition + 4);
            setByte(sizePosition, size >> 24);
            setByte(sizePosition + 1, size >> 16);
            setByte(sizePosition + 2, size >> 8);
            setByte(sizePosition + 3, size);
        }
        if (startEncryptPosition != -1) {
            if (cipher == null)
                throw new RuntimeException("Packet cannot be encrypted without cipher!");
            encrypt(cipher);
        }
        return this;
    }

    /**
     * Add methods
     */

    public OutBuffer addBytes(byte[] bytes) {
        return addBytes(bytes, 0, bytes.length);
    }

    public OutBuffer addBytes(byte[] bytes, int offset, int length) {
        resizeIfNeeded(position + (length - offset));
        for (int i = offset; i < length; i++)
            payload[position++] = bytes[i];
        return this;
    }

    public OutBuffer addBytesReverse(byte[] bytes, int offset, int length) {
        resizeIfNeeded(position + (length - offset));
        for(int i = length-1; i >= 0; i--)
            payload[position++] = bytes[i + offset];
        return this;
    }

    public OutBuffer addByte(int b) {
        return setByte(position++, b);
    }

    public OutBuffer addByteA(int b) {
        addByte(b + 128);
        return this;
    }

    public OutBuffer addByteC(int b) {
        addByte(-b);
        return this;
    }

    public OutBuffer addByteS(int b) {
        addByte(128 - b);
        return this;
    }

    public OutBuffer addShort(int s) {
        addByte(s >> 8);
        addByte(s);
        return this;
    }

    public OutBuffer addShortA(int s) {
        addByte(s >> 8);
        addByte(s + 128);
        return this;
    }

    public OutBuffer addLEShort(int s) {
        addByte(s);
        addByte(s >> 8);
        return this;
    }

    public OutBuffer addLEShortA(int s) {
        addByte(s + 128);
        addByte(s >> 8);
        return this;
    }

    public OutBuffer addMedium(int i) {
        addByte(i >> 16);
        addByte(i >> 8);
        addByte(i);
        return this;
    }

    public OutBuffer add24BitInt(int i) {
        addByte(i >> 16);
        addByte(i >> 8);
        addByte(i);
        return this;
    }

    public OutBuffer addInt(int i) {
        addByte(i >> 24);
        addByte(i >> 16);
        addByte(i >> 8);
        addByte(i);
        return this;
    }

    public OutBuffer addMInt(int i) {
        addByte(i >> 8);
        addByte(i);
        addByte(i >> 24);
        addByte(i >> 16);
        return this;
    }

    public OutBuffer addIMInt(int i) {
        addByte(i >> 16);
        addByte(i >> 24);
        addByte(i);
        addByte(i >> 8);
        return this;
    }

    public OutBuffer addLEInt(int i) {
        addByte(i);
        addByte(i >> 8);
        addByte(i >> 16);
        addByte(i >> 24);
        return this;
    }

    public OutBuffer addSmart(int i) {
        if (i >= 128)
            addShort(i + 32768);
        else
            addByte(i);
        return this;
    }

    public void addBigSmart(int i) {
        if (i >= Short.MAX_VALUE)
            addInt(i - Integer.MAX_VALUE - 1);
        else
            addShort(i >= 0 ? i : 32767);
    }

    public OutBuffer addLong(long l) {
        addByte((int) (l >> 56));
        addByte((int) (l >> 48));
        addByte((int) (l >> 40));
        addByte((int) (l >> 32));
        addByte((int) (l >> 24));
        addByte((int) (l >> 16));
        addByte((int) (l >> 8));
        addByte((int) l);
        return this;
    }

    public OutBuffer addString(String s) {
        byte[] bytes = s.getBytes();
        resizeIfNeeded(position + bytes.length + 1);
        for (byte b : bytes)
            payload[position++] = b;
        payload[position++] = 0;
        return this;
    }

    public OutBuffer initBitAccess() {
        bitPosition = position * 8;
        return this;
    }

    public OutBuffer addBits(int numBits, int value) {
        int bytePos = bitPosition >> 3;
        int bitOffset = 8 - (bitPosition & 7);
        bitPosition += numBits;
        for (; numBits > bitOffset; bitOffset = 8) {
            resizeIfNeeded(bytePos);
            payload[bytePos] &= ~BIT_MASK[bitOffset];
            payload[bytePos++] |= value >> numBits - bitOffset & BIT_MASK[bitOffset];
            numBits -= bitOffset;
        }
        resizeIfNeeded(bytePos);
        if (numBits == bitOffset) {
            payload[bytePos] &= ~BIT_MASK[bitOffset];
            payload[bytePos] |= value & BIT_MASK[bitOffset];
        } else {
            payload[bytePos] &= ~(BIT_MASK[numBits] << bitOffset - numBits);
            payload[bytePos] |= (value & BIT_MASK[numBits]) << bitOffset - numBits;
        }
        return this;
    }

    public OutBuffer finishBitAccess() {
        position = (bitPosition + 7) / 8;
        return this;
    }

    public void addBytesA(byte[] payload, int start, int length) {
        for (int i = start; i < length; i++) {
            addByteA(payload[i]);
        }
    }

    public void rsaEncrypt() {
        int var3 = this.position;
        this.position = 0;
        byte[] var4 = new byte[var3];
        System.arraycopy(payload, 0, var4, 0, var3);

        BigInteger var5 = new BigInteger(var4);
        BigInteger var6 = var5.modPow(RSA_EXPONENT, RSA_MODULUS);
        byte[] var7 = var6.toByteArray();
        this.position = 0;
        this.addShort(var7.length);
        this.addBytes(var7, 0, var7.length);
    }

    public byte readByte() {
        if (position >= payload.length)
            return 0;
        return payload[position++];
    }

    public int readUnsignedByte() {
        return readByte() & 0xff;
    }

    public int readInt() {
        return (readUnsignedByte() << 24) + (readUnsignedByte() << 16) + (readUnsignedByte() << 8) + readUnsignedByte();
    }

    public void tinyKeyEncrypt(int[] var1, int var2, int var3) {
        int var4 = this.position;
        this.position = var2;
        int var5 = (var3 - var2) / 8;

        for (int var6 = 0; var6 < var5; ++var6) {
            int var7 = this.readInt();
            int var8 = this.readInt();
            int var9 = 0;
            int var10 = -1640531527;

            for (int var11 = 32; var11-- > 0; var8 += var7 + (var7 << 4 ^ var7 >>> 5) ^ var1[var9 >>> 11 & 3] + var9) {
                var7 += var8 + (var8 << 4 ^ var8 >>> 5) ^ var9 + var1[var9 & 3];
                var9 += var10;
            }

            this.position -= 8;
            this.addInt(var7);
            this.addInt(var8);
        }

        this.position = var4;
    }

    public void putShortSize(int var1) {
        if (var1 >= 0 && var1 <= 65535) {
            this.payload[this.position - var1 - 2] = (byte) (var1 >> 8);
            this.payload[this.position - var1 - 1] = (byte) var1;
        } else {
            throw new IllegalArgumentException();
        }
    }
}
Would appreciate if someone could point me in the right direction or have a solution as I've been scratching my head at this one and just can't figure it out, thanks!