Last active
August 29, 2015 14:09
-
-
Save socram8888/3769ee88a0a54232b0dd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BlockAreaSet implements Set<Block> { | |
private final World world; | |
private final int baseX; | |
private final int baseY; | |
private final int baseZ; | |
private final int sizeX; | |
private final int sizeY; | |
private final int sizeZ; | |
private final int[] data; | |
private int count; | |
private int hashCode; | |
public BlockAreaSet(Block b1, Block b2) { | |
world = b1.getWorld(); | |
if (!world.equals(b2.getWorld())) { | |
throw new IllegalArgumentException("Both blocks must be in the same world"); | |
} | |
baseX = Math.min(b1.getX(), b2.getX()); | |
baseY = Math.min(b1.getY(), b2.getY()); | |
baseZ = Math.min(b1.getZ(), b2.getZ()); | |
sizeX = Math.max(b1.getX(), b2.getX()) - baseX + 1; | |
sizeY = Math.max(b1.getY(), b2.getY()) - baseY + 1; | |
sizeZ = Math.max(b1.getZ(), b2.getZ()) - baseZ + 1; | |
initData(); | |
} | |
public BlockAreaSet(Block center, int radius) { | |
world = center.getWorld(); | |
baseX = center.getX() - radius; | |
baseY = center.getY() - radius; | |
baseZ = center.getZ() - radius; | |
sizeX = sizeY = sizeZ = 2 * radius; | |
initData(); | |
} | |
private void initData() { | |
hashCode = (sizeX << 20 | sizeY << 16 | sizeZ) ^ baseX ^ baseY ^ baseZ; | |
data = new int[(sizeX * sizeY * sizeZ >>> 5) + 1]; | |
} | |
private int calculateBitPos(Block block) { | |
if (!world.equals(block.getWorld())) { | |
throw new IllegalArgumentException("Block world is not valid"); | |
} | |
int x = block.getX() - baseX; | |
int y = block.getY() - baseY; | |
int z = block.getZ() - baseZ; | |
if (x < 0 || x > sizeX || y < 0 || y > sizeY || z < 0 || z > sizeZ) { | |
throw new IllegalArgumentException("Block is outside the valid area"); | |
} | |
return (z * sizeY + y) * sizeX + x; | |
} | |
@Override | |
public boolean contains(Object object) { | |
int pos; | |
try { | |
pos = calculateBitPos((Block) object); | |
} catch (IllegalArgumentException e) { | |
return false; | |
} | |
int index = pos >> 5; | |
int mask = 1 << (pos & 0x1F); | |
return (data[index] & mask) != 0; | |
} | |
@Override | |
public boolean add(Block block) { | |
pos = calculateBitPos(block); | |
int index = pos >> 5; | |
int mask = 1 << (pos & 0x1F); | |
if ((data[index] & mask) != 0) { | |
return false; | |
} | |
int v = data[index]; | |
hashCode = hashCode ^ v ^ count; | |
v |= mask; | |
count++; | |
hashCode = hashCode ^ v ^ count; | |
data[index] = v; | |
return true; | |
} | |
@Override | |
public boolean addAll(Collection<? extends Block> blocks) { | |
boolean modified = false; | |
for (Block block : blocks) { | |
if (add(block)) { | |
modified = true; | |
} | |
} | |
return modified; | |
} | |
@Override | |
public void clear() { | |
count = 0; | |
Array.fill(data, 0); | |
} | |
@Override | |
public boolean containsAll(Collection<?> objects) { | |
for (Object object : objects) { | |
if (!contains(object)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
@Override | |
public boolean equals(Object object) { | |
if (object == null) { | |
return false; | |
} | |
if (this == object) { | |
return true; | |
} | |
try { | |
Set set = (Set) object; | |
if (size() != set.size()) { | |
return false; | |
} | |
for (Object setObject : set) { | |
if (!contains(setObject)) { | |
return false; | |
} | |
} | |
return true; | |
} catch (Exception e) { } | |
return false; | |
} | |
@Override | |
public int hashCode() { | |
return hashCode; | |
} | |
@Override | |
public boolean isEmpty() { | |
return count == 0; | |
} | |
@Override | |
public Iterator<Block> iterator() { | |
throw new UnsupportedOperationException("Not yet implemented"); | |
} | |
@Override | |
public boolean remove(Object obj) { | |
pos = calculateBitPos((Block) obj); | |
int index = pos >> 5; | |
int mask = 1 << (pos & 0x1F); | |
if ((data[index] & mask) == 0) { | |
return false; | |
} | |
int v = data[index]; | |
hashCode = hashCode ^ v ^ count; | |
v &= ~mask; | |
count--; | |
hashCode = hashCode ^ v ^ count; | |
data[index] = v; | |
return true; | |
} | |
@Override | |
public boolean removeAll(Collection<?> objects) { | |
boolean modified = false; | |
for (Object object : objects) { | |
if (remove(object)) { | |
modified = true; | |
} | |
} | |
return modified; | |
} | |
@Override | |
public boolean retainAll(Collection<?> objects) { | |
throw new UnsupportedOperationException("Not yet implemented"); | |
} | |
@Override | |
public int size() { | |
return count; | |
} | |
@Override | |
public Object[] toArray() { | |
throw new UnsupportedOperationException("Not yet implemented"); | |
} | |
@Override | |
public <T> T[] toArray(T[] array) { | |
throw new UnsupportedOperationException("Not yet implemented"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment