@Override
  public Set<org.getspout.spoutapi.material.Block> getModifiedBlocks() {
    // hit cache first
    if (cachedBlockData != null) {
      return cachedBlockData;
    }
    Set<org.getspout.spoutapi.material.Block> modified =
        new HashSet<org.getspout.spoutapi.material.Block>();
    TLongFloatIterator i = originalFriction.iterator();
    while (i.hasNext()) {
      i.advance();
      int id = TIntPairHashSet.longToKey1(i.key());
      int data = TIntPairHashSet.longToKey2(i.key());

      org.getspout.spoutapi.material.Block block = MaterialData.getBlock(id, (short) data);
      if (block != null) {
        modified.add(block);
      }
    }

    i = originalHardness.iterator();
    while (i.hasNext()) {
      i.advance();
      int id = TIntPairHashSet.longToKey1(i.key());
      int data = TIntPairHashSet.longToKey2(i.key());
      org.getspout.spoutapi.material.Block block = MaterialData.getBlock(id, (short) data);
      if (block != null) {
        modified.add(block);
      }
    }

    TIntIntIterator j = originalLight.iterator();
    while (j.hasNext()) {
      j.advance();
      org.getspout.spoutapi.material.Block block = MaterialData.getBlock(j.key());
      if (block != null) {
        modified.add(block);
      }
    }

    TIntByteIterator k = originalOpacity.iterator();
    while (k.hasNext()) {
      k.advance();
      org.getspout.spoutapi.material.Block block = MaterialData.getBlock(k.key());
      if (block != null) {
        modified.add(block);
      }
    }
    cachedBlockData = modified; // save to cache
    return modified;
  }