package net.scapeemulator.game.model.pathfinding; import static net.scapeemulator.game.model.object.ObjectOrientation.EAST; import static net.scapeemulator.game.model.object.ObjectOrientation.NORTH; import static net.scapeemulator.game.model.object.ObjectOrientation.SOUTH; import static net.scapeemulator.game.model.object.ObjectOrientation.WEST; import static net.scapeemulator.game.model.pathfinding.Tile.BLOCKED; import static net.scapeemulator.game.model.pathfinding.Tile.BRIDGE; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_OCCUPANT; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_NORTH; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_NORTH_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_NORTH_WEST; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_SOUTH; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_SOUTH_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_SOUTH_WEST; import static net.scapeemulator.game.model.pathfinding.Tile.IMPENETRABLE_WALL_WEST; import static net.scapeemulator.game.model.pathfinding.Tile.OCCUPANT; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_NORTH; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_NORTH_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_NORTH_WEST; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_SOUTH; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_SOUTH_EAST; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_SOUTH_WEST; import static net.scapeemulator.game.model.pathfinding.Tile.WALL_WEST; import net.scapeemulator.game.model.Position; import net.scapeemulator.game.model.mob.Direction; import net.scapeemulator.game.model.mob.Mob; import net.scapeemulator.game.model.object.ObjectType; /** * @author Hadyn Richard */ public final class TraversalMap { /** * The size of one side of the region array. */ public static final int SIZE = 256; /** * The size of a region. */ public static final int REGION_SIZE = 64; /** * The maximum plane. */ public static final int MAXIMUM_PLANE = 4; /** * The regions for the traversal data. */ private final Region[] regions = new Region[SIZE * SIZE]; /** * Created by Hadyn Richard */ private class Region { /** * The flags within the region. */ private Tile[][] tiles; /** * Constructs a new {@link Region}; */ public Region() { tiles = new Tile[MAXIMUM_PLANE][REGION_SIZE * REGION_SIZE]; for (int i = 0; i < MAXIMUM_PLANE; i++) { for (int j = 0; j < REGION_SIZE * REGION_SIZE; j++) { tiles[i][j] = new Tile(); } } } public Tile getTile(int plane, int x, int y) { return tiles[plane][x + y * REGION_SIZE]; } } /** * Constructs a new {@link TraversalMap}; */ public TraversalMap() { } /** * Initializes the region at the specified coordinates. */ public void initializeRegion(int x, int y) { /* Calculate the coordinates */ int regionX = x >> 6, regionY = y >> 6; regions[regionX + regionY * SIZE] = new Region(); } /** * Gets if the set contains a region for the specified coordinates. */ public boolean regionInitialized(int x, int y) { /* Calculate the coordinates */ int regionX = x >> 6, regionY = y >> 6; /* Get if the region is not null */ return regions[regionX + regionY * SIZE] != null; } public void markWall(int rotation, int plane, int x, int y, ObjectType type, boolean impenetrable) { switch (type) { case STRAIGHT_WALL: if (rotation == WEST) { set(plane, x, y, WALL_WEST); set(plane, x - 1, y, WALL_EAST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_WEST); set(plane, x - 1, y, IMPENETRABLE_WALL_EAST); } } if (rotation == NORTH) { set(plane, x, y, WALL_NORTH); set(plane, x, y + 1, WALL_SOUTH); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_NORTH); set(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); } } if (rotation == EAST) { set(plane, x, y, WALL_EAST); set(plane, x + 1, y, WALL_WEST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_EAST); set(plane, x + 1, y, IMPENETRABLE_WALL_WEST); } } if (rotation == SOUTH) { set(plane, x, y, WALL_SOUTH); set(plane, x, y - 1, WALL_NORTH); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_SOUTH); set(plane, x, y - 1, IMPENETRABLE_WALL_NORTH); } } break; // Corners case TYPE_2: if (rotation == WEST) { set(plane, x, y, WALL_WEST | WALL_NORTH); set(plane, x - 1, y, WALL_EAST); set(plane, x, y + 1, WALL_SOUTH); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_WEST | IMPENETRABLE_WALL_NORTH); set(plane, x - 1, y, IMPENETRABLE_WALL_EAST); set(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); } } if (rotation == NORTH) { set(plane, x, y, WALL_EAST | WALL_NORTH); set(plane, x, y + 1, WALL_SOUTH); set(plane, x + 1, y, WALL_WEST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_NORTH); set(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); set(plane, x + 1, y, IMPENETRABLE_WALL_WEST); } } if (rotation == EAST) { set(plane, x, y, WALL_EAST | WALL_SOUTH); set(plane, x + 1, y, WALL_WEST); set(plane, x, y - 1, WALL_NORTH); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_SOUTH); set(plane, x + 1, y, IMPENETRABLE_WALL_WEST); set(plane, x, y - 1, IMPENETRABLE_WALL_NORTH); } } if (rotation == SOUTH) { set(plane, x, y, WALL_WEST | WALL_SOUTH); set(plane, x - 1, y, WALL_EAST); set(plane, x, y - 1, WALL_NORTH); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_WEST | IMPENETRABLE_WALL_SOUTH); set(plane, x - 1, y, IMPENETRABLE_WALL_EAST); set(plane, x, y - 1, IMPENETRABLE_WALL_NORTH); } } break; case TYPE_1: case TYPE_3: if (rotation == WEST) { set(plane, x, y, WALL_NORTH_WEST); set(plane, x - 1, y + 1, WALL_SOUTH_EAST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_NORTH_WEST); set(plane, x - 1, y + 1, IMPENETRABLE_WALL_SOUTH_EAST); } } if (rotation == NORTH) { set(plane, x, y, WALL_NORTH_EAST); set(plane, x + 1, y + 1, WALL_SOUTH_WEST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_NORTH_EAST); set(plane, x + 1, y + 1, IMPENETRABLE_WALL_SOUTH_WEST); } } if (rotation == EAST) { set(plane, x, y, WALL_SOUTH_EAST); set(plane, x + 1, y - 1, WALL_NORTH_WEST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_SOUTH_EAST); set(plane, x + 1, y - 1, IMPENETRABLE_WALL_NORTH_WEST); } } if (rotation == SOUTH) { set(plane, x, y, WALL_SOUTH_WEST); set(plane, x - 1, y - 1, WALL_NORTH_EAST); if (impenetrable) { set(plane, x, y, IMPENETRABLE_WALL_SOUTH_WEST); set(plane, x - 1, y - 1, IMPENETRABLE_WALL_NORTH_EAST); } } break; default: break; } } public void unmarkWall(int rotation, int plane, int x, int y, ObjectType type, boolean impenetrable) { switch (type) { case STRAIGHT_WALL: if (rotation == WEST) { unset(plane, x, y, WALL_WEST); unset(plane, x - 1, y, WALL_EAST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_WEST); unset(plane, x - 1, y, IMPENETRABLE_WALL_EAST); } } if (rotation == NORTH) { unset(plane, x, y, WALL_NORTH); unset(plane, x, y + 1, WALL_SOUTH); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_NORTH); unset(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); } } if (rotation == EAST) { unset(plane, x, y, WALL_EAST); unset(plane, x + 1, y, WALL_WEST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_EAST); unset(plane, x + 1, y, IMPENETRABLE_WALL_WEST); } } if (rotation == SOUTH) { unset(plane, x, y, WALL_SOUTH); unset(plane, x, y - 1, WALL_NORTH); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_SOUTH); unset(plane, x, y - 1, IMPENETRABLE_WALL_NORTH); } } break; case TYPE_2: if (rotation == WEST) { unset(plane, x, y, WALL_WEST | WALL_NORTH); unset(plane, x - 1, y, WALL_EAST); unset(plane, x, y + 1, WALL_SOUTH); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_WEST | IMPENETRABLE_WALL_NORTH); unset(plane, x - 1, y, IMPENETRABLE_WALL_EAST); unset(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); } } if (rotation == NORTH) { unset(plane, x, y, WALL_EAST | WALL_NORTH); unset(plane, x, y + 1, WALL_SOUTH); unset(plane, x + 1, y, WALL_WEST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_NORTH); unset(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH); unset(plane, x + 1, y, IMPENETRABLE_WALL_WEST); } } if (rotation == EAST) { unset(plane, x, y, WALL_EAST | WALL_SOUTH); unset(plane, x + 1, y, WALL_WEST); unset(plane, x, y - 1, WALL_NORTH); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_SOUTH); unset(plane, x + 1, y, IMPENETRABLE_WALL_WEST); unset(plane, x, y - 1, IMPENETRABLE_WALL_NORTH); } } if (rotation == SOUTH) { unset(plane, x, y, WALL_EAST | WALL_SOUTH); unset(plane, x, y - 1, WALL_WEST); unset(plane, x - 1, y, WALL_NORTH); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_SOUTH); unset(plane, x, y - 1, IMPENETRABLE_WALL_WEST); unset(plane, x - 1, y, IMPENETRABLE_WALL_NORTH); } } break; case TYPE_1: case TYPE_3: if (rotation == WEST) { unset(plane, x, y, WALL_NORTH_WEST); unset(plane, x - 1, y + 1, WALL_SOUTH_EAST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_NORTH_WEST); unset(plane, x - 1, y + 1, IMPENETRABLE_WALL_SOUTH_EAST); } } if (rotation == NORTH) { unset(plane, x, y, WALL_NORTH_EAST); unset(plane, x + 1, y + 1, WALL_SOUTH_WEST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_NORTH_EAST); unset(plane, x + 1, y + 1, IMPENETRABLE_WALL_SOUTH_WEST); } } if (rotation == EAST) { unset(plane, x, y, WALL_SOUTH_EAST); unset(plane, x + 1, y - 1, WALL_NORTH_WEST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_SOUTH_EAST); unset(plane, x + 1, y - 1, IMPENETRABLE_WALL_NORTH_WEST); } } if (rotation == SOUTH) { unset(plane, x, y, WALL_SOUTH_WEST); unset(plane, x - 1, y - 1, WALL_NORTH_EAST); if (impenetrable) { unset(plane, x, y, IMPENETRABLE_WALL_SOUTH_WEST); unset(plane, x - 1, y - 1, IMPENETRABLE_WALL_NORTH_EAST); } } break; default: break; } } public void markBlocked(int plane, int x, int y) { /* Calculate the coordinates */ int regionX = x >> 6, regionY = y >> 6; /* Calculate the local coordinates */ int localX = x & 0x3f, localY = y & 0x3f; Region region = regions[regionX + regionY * SIZE]; if (region == null) { return; } int modifiedPlane = plane; if ((region.getTile(1, localX, localY).flags() & BRIDGE) != 0) { modifiedPlane = plane - 1; } region.getTile(modifiedPlane, x & 0x3f, y & 0x3f).set(BLOCKED); } public void markOccupant(int plane, int x, int y, int width, int length, boolean impenetrable) { for (int offsetX = 0; offsetX < width; offsetX++) { for (int offsetY = 0; offsetY < length; offsetY++) { set(plane, x + offsetX, y + offsetY, OCCUPANT); if (impenetrable) { set(plane, x + offsetX, y + offsetY, IMPENETRABLE_OCCUPANT); } } } } public void unmarkOccupant(int plane, int x, int y, int width, int length, boolean impenetrable) { for (int offsetX = 0; offsetX < width; offsetX++) { for (int offsetY = 0; offsetY < length; offsetY++) { unset(plane, x + offsetX, y + offsetY, OCCUPANT); if (impenetrable) { unset(plane, x + offsetX, y + offsetY, IMPENETRABLE_OCCUPANT); } } } } public void markBridge(int plane, int x, int y) { set(plane, x, y, BRIDGE); } public boolean isTraversableNorth(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableNorth(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableNorth(int plane, int x, int y) { return isTraversableNorth(plane, x, y, false); } /** * Tests if from the specified position it can be traversed north. */ public boolean isTraversableNorth(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x, y + 1, IMPENETRABLE_OCCUPANT | IMPENETRABLE_WALL_SOUTH); } return isInactive(plane, x, y + 1, WALL_SOUTH | OCCUPANT | BLOCKED); } public boolean isTraversableSouth(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableSouth(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableSouth(int plane, int x, int y) { return isTraversableSouth(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableSouth(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x, y - 1, IMPENETRABLE_OCCUPANT | IMPENETRABLE_WALL_NORTH); } return isInactive(plane, x, y - 1, WALL_NORTH | OCCUPANT | BLOCKED); } public boolean isTraversableEast(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableEast(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableEast(int plane, int x, int y) { return isTraversableEast(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableEast(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x + 1, y, IMPENETRABLE_OCCUPANT | IMPENETRABLE_WALL_WEST); } return isInactive(plane, x + 1, y, WALL_WEST | OCCUPANT | BLOCKED); } public boolean isTraversableWest(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableWest(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableWest(int plane, int x, int y) { return isTraversableWest(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableWest(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x - 1, y, IMPENETRABLE_OCCUPANT | IMPENETRABLE_WALL_EAST); } return isInactive(plane, x - 1, y, WALL_EAST | OCCUPANT | BLOCKED); } public boolean isTraversableNorthEast(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableNorthEast(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableNorthEast(int plane, int x, int y) { return isTraversableNorthEast(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableNorthEast(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x + 1, y + 1, IMPENETRABLE_WALL_WEST | IMPENETRABLE_WALL_SOUTH | IMPENETRABLE_WALL_SOUTH_WEST | OCCUPANT) && isInactive(plane, x + 1, y, IMPENETRABLE_WALL_WEST | IMPENETRABLE_OCCUPANT) && isInactive(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH | IMPENETRABLE_OCCUPANT); } return isInactive(plane, x + 1, y + 1, WALL_WEST | WALL_SOUTH | WALL_SOUTH_WEST | OCCUPANT | BLOCKED) && isInactive(plane, x + 1, y, WALL_WEST | OCCUPANT | BLOCKED) && isInactive(plane, x, y + 1, WALL_SOUTH | OCCUPANT | BLOCKED); } public boolean isTraversableNorthWest(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableNorthWest(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableNorthWest(int plane, int x, int y) { return isTraversableNorthWest(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableNorthWest(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x - 1, y + 1, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_SOUTH | IMPENETRABLE_WALL_SOUTH_EAST | OCCUPANT) && isInactive(plane, x - 1, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_OCCUPANT) && isInactive(plane, x, y + 1, IMPENETRABLE_WALL_SOUTH | IMPENETRABLE_OCCUPANT); } return isInactive(plane, x - 1, y + 1, WALL_EAST | WALL_SOUTH | WALL_SOUTH_EAST | OCCUPANT | BLOCKED) && isInactive(plane, x - 1, y, WALL_EAST | OCCUPANT | BLOCKED) && isInactive(plane, x, y + 1, WALL_SOUTH | OCCUPANT | BLOCKED); } public boolean isTraversableSouthEast(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableSouthEast(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableSouthEast(int plane, int x, int y) { return isTraversableSouthEast(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableSouthEast(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x + 1, y - 1, IMPENETRABLE_WALL_WEST | IMPENETRABLE_WALL_NORTH | IMPENETRABLE_WALL_NORTH_WEST | OCCUPANT) && isInactive(plane, x + 1, y, IMPENETRABLE_WALL_WEST | IMPENETRABLE_OCCUPANT) && isInactive(plane, x, y - 1, IMPENETRABLE_WALL_NORTH | IMPENETRABLE_OCCUPANT); } return isInactive(plane, x + 1, y - 1, WALL_WEST | WALL_NORTH | WALL_NORTH_WEST | OCCUPANT | BLOCKED) && isInactive(plane, x + 1, y, WALL_WEST | OCCUPANT | BLOCKED) && isInactive(plane, x, y - 1, WALL_NORTH | OCCUPANT | BLOCKED); } public boolean isTraversableSouthWest(int plane, int x, int y, int size) { for (int offsetX = 0; offsetX < size; offsetX++) { for (int offsetY = 0; offsetY < size; offsetY++) { if (!isTraversableSouthWest(plane, x + offsetX, y + offsetY)) { return false; } } } return true; } public boolean isTraversableSouthWest(int plane, int x, int y) { return isTraversableSouthWest(plane, x, y, false); } /** * Tests if from the specified position it can be traversed south. */ public boolean isTraversableSouthWest(int plane, int x, int y, boolean impenetrable) { if (impenetrable) { return isInactive(plane, x - 1, y - 1, IMPENETRABLE_WALL_EAST | IMPENETRABLE_WALL_NORTH | IMPENETRABLE_WALL_NORTH_EAST | OCCUPANT) && isInactive(plane, x - 1, y, IMPENETRABLE_WALL_EAST | IMPENETRABLE_OCCUPANT) && isInactive(plane, x, y - 1, IMPENETRABLE_WALL_NORTH | IMPENETRABLE_OCCUPANT); } return isInactive(plane, x - 1, y - 1, WALL_EAST | WALL_NORTH | WALL_NORTH_EAST | OCCUPANT | BLOCKED) && isInactive(plane, x - 1, y, WALL_EAST | OCCUPANT | BLOCKED) && isInactive(plane, x, y - 1, WALL_NORTH | OCCUPANT | BLOCKED); } public void set(int plane, int x, int y, int flag) { /* Calculate the coordinates */ int regionX = x >> 6, regionY = y >> 6; Region region = regions[regionX + regionY * SIZE]; if (region == null) { return; } region.getTile(plane, x & 0x3f, y & 0x3f).set(flag); } public boolean attackPathClear(Mob source, Position dest, boolean projectile) { if (projectile) { Path path = ProjectilePathFinder.find(source.getPosition(), dest); if (path.isEmpty()) { return true; } Position prev = source.getPosition(); while (!path.isEmpty()) { Position next = path.poll(); if (!Direction.projectileClipping(prev, next)) { return false; } prev = next; } return true; } else { return Direction.isTraversable(source.getPosition(), Direction.between(source.getPosition(), dest), source.getSize()); } } public boolean isInactive(int plane, int x, int y, int flag) { /* Calculate the region coordinates */ int regionX = x >> 6, regionY = y >> 6; /* Calculate the local region coordinates */ int localX = x & 0x3f, localY = y & 0x3f; Region region = regions[regionX + regionY * SIZE]; if (region == null) { return false; } int modifiedPlane = plane; if (region.getTile(1, localX, localY).isActive(BRIDGE)) { modifiedPlane = plane + 1; } return region.getTile(modifiedPlane, localX, localY).isInactive(flag); } public boolean shouldModifyPlane(int x, int y) { /* Calculate the region coordinates */ int regionX = x >> 6, regionY = y >> 6; /* Calculate the local region coordinates */ int localX = x & 0x3f, localY = y & 0x3f; Region region = regions[regionX + regionY * SIZE]; if (region != null) { if (region.getTile(1, localX, localY).isActive(BRIDGE)) { return true; } } return false; } public void unset(int plane, int x, int y, int flag) { /* Calculate the coordinates */ int regionX = x >> 6, regionY = y >> 6; Region region = regions[regionX + regionY * SIZE]; if (region == null) { return; } region.getTile(plane, x & 0x3f, y & 0x3f).unset(flag); } }