package skadistats.clarity.model.state;

import skadistats.clarity.model.DTClass;
import skadistats.clarity.model.EngineType;

public class ClientFrame {

    private final EngineType engineType;
    private final int tick;
    private final boolean[] valid;
    private final DTClass[] dtClass;
    private final int[] serial;
    private final boolean[] active;
    private final CloneableEntityState[] state;

    public ClientFrame(EngineType engineType, int tick) {
        this.engineType = engineType;
        this.tick = tick;
        int n = 1 << engineType.getIndexBits();
        this.valid = new boolean[n];
        this.dtClass = new DTClass[n];
        this.serial = new int[n];
        this.active = new boolean[n];
        this.state = new CloneableEntityState[n];
    }

    public void copyFromOtherFrame(ClientFrame otherFrame, int idx, int length) {
        System.arraycopy(otherFrame.valid, idx, valid, idx, length);
        System.arraycopy(otherFrame.dtClass, idx, dtClass, idx, length);
        System.arraycopy(otherFrame.serial, idx, serial, idx, length);
        System.arraycopy(otherFrame.active, idx, active, idx, length);
        System.arraycopy(otherFrame.state, idx, state, idx, length);
    }

    public void createNewEntity(int eIdx, DTClass dtClass, int serial, CloneableEntityState state) {
        this.valid[eIdx] = true;
        this.dtClass[eIdx] = dtClass;
        this.serial[eIdx] = serial;
        this.active[eIdx] = true;
        this.state[eIdx] = state.clone();
    }

    public void updateExistingEntity(ClientFrame oldFrame, int eIdx) {
        this.valid[eIdx] = oldFrame.valid[eIdx];
        this.dtClass[eIdx] = oldFrame.dtClass[eIdx];
        this.serial[eIdx] = oldFrame.serial[eIdx];
        this.active[eIdx] = oldFrame.active[eIdx];
        this.state[eIdx] = oldFrame.state[eIdx].clone();
    }

    public void deleteEntity(int eIdx) {
        this.valid[eIdx] = false;
        this.dtClass[eIdx] = null;
        this.serial[eIdx] = 0;
        this.active[eIdx] = false;
        this.state[eIdx] = null;
    }

    public void setActive(int eIdx, boolean active) {
        this.active[eIdx] = active;
    }

    public int getTick() {
        return tick;
    }

    public int getSize() {
        return state.length;
    }

    public boolean isValid(int idx) {
        return valid[idx];
    }

    public DTClass getDtClass(int idx) {
        return dtClass[idx];
    }

    public int getSerial(int idx) {
        return serial[idx];
    }

    public boolean isActive(int idx) {
        return active[idx];
    }

    public CloneableEntityState getState(int idx) {
        return state[idx];
    }

    public int getHandle(int idx) {
        return engineType.handleForIndexAndSerial(idx, getSerial(idx));
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("ClientFrame{");
        sb.append("tick=").append(tick);
        sb.append('}');
        return sb.toString();
    }

}

@@ -353,24 +353,65 @@
 n%5B%5D active;%0A
+    private final int%5B%5D lastChangedTick;%0A
     private 
@@ -446,16 +446,16 @@
  state;%0A
-
 %0A    pub
@@ -757,32 +757,75 @@
 new boolean%5Bn%5D;%0A
+        this.lastChangedTick = new int%5Bn%5D;%0A
         this.sta
@@ -1223,32 +1223,121 @@
 , idx, length);%0A
+        System.arraycopy(otherFrame.lastChangedTick, idx, lastChangedTick, idx, length);%0A
         System.a
@@ -1630,32 +1630,75 @@
 e%5BeIdx%5D = true;%0A
+        this.lastChangedTick%5BeIdx%5D = tick;%0A
         this.sta
@@ -1997,32 +1997,75 @@
 e.active%5BeIdx%5D;%0A
+        this.lastChangedTick%5BeIdx%5D = tick;%0A
         this.sta
@@ -2280,32 +2280,75 @@
 %5BeIdx%5D = false;%0A
+        this.lastChangedTick%5BeIdx%5D = tick;%0A
         this.sta
@@ -2837,32 +2837,32 @@
 tive(int idx) %7B%0A
-
         return a
@@ -2872,32 +2872,121 @@
 ve%5Bidx%5D;%0A    %7D%0A%0A
+    public int getLastChangedTick(int idx) %7B%0A        return lastChangedTick%5Bidx%5D;%0A    %7D%0A%0A
     public Clone

add field to remember the tick an entity was last changed