@Override
  public void decodePacketdata(ByteBuf buffer) {
    if (this.fieldCacheClient == null || this.fieldCacheServer == null) {
      try {
        this.initFieldCache();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    if (this.worldObj.isRemote && this.fieldCacheClient.size() == 0) {
      return;
    } else if (!this.worldObj.isRemote && this.fieldCacheServer.size() == 0) {
      return;
    }

    Set<Field> fieldSet = null;

    if (this.worldObj.isRemote) {
      fieldSet = this.fieldCacheClient;
    } else {
      fieldSet = this.fieldCacheServer;
    }

    for (Field field : fieldSet) {
      try {
        Object obj = NetworkUtil.getFieldValueFromStream(field, buffer, this.worldObj);
        field.set(this, obj);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    this.readExtraNetworkedData(buffer);
  }
  @Override
  public void getNetworkedData(ArrayList<Object> sendData) {
    Set<Field> fieldList = null;
    boolean changed = false;

    if (this.worldObj.isRemote) {
      fieldList = this.fieldCacheServer;
    } else {
      fieldList = this.fieldCacheClient;
    }

    for (Field f : fieldList) {
      boolean fieldChanged = false;
      try {
        Object data = f.get(this);
        Object lastData = lastSentData.get(f);

        if (!NetworkUtil.fuzzyEquals(lastData, data)) {
          fieldChanged = true;
        }

        sendData.add(data);

        if (fieldChanged) {
          lastSentData.put(f, NetworkUtil.cloneNetworkedObject(data));
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

      changed |= fieldChanged;
    }

    if (changed) {
      this.addExtraNetworkedData(sendData);
    } else {
      ArrayList<Object> prevSendData = new ArrayList<Object>(sendData);

      this.addExtraNetworkedData(sendData);

      if (!prevSendData.equals(sendData)) {
        changed = true;
      }
    }

    networkDataChanged = changed;
  }