gt:         int pOffsetY = (gameController.getMapOffsetY() / BLOCK_HEIGHT);
context: package com.weem.epicinventor.world.block;
  
  import com.weem.epicinventor.*;
  import com.weem.epicinventor.utility.*;
  import com.weem.epicinventor.world.*;
  
  import java.awt.*;
  import java.util.*;
  import java.io.*;
  import java.awt.image.*;
  import javax.imageio.*;
  
  public class BlockManager implements Serializable, Cloneable {
  
      protected static final long serialVersionUID = 10000L;
      private int pCols, pRows, mapCols, mapRows;
      private int mapWidth, mapHeight;
      private HashMap blockTypes;
      private HashMap blockTypeIdMap;
      private short[][] blocks;
      transient private int[] xPos;
      private int mapSurfaceMin;
      private int mapSurfaceMax;
      private int mapLevelStart;
      private int mapLevelHeight;
      transient private HashMap<String, Integer> minimapColors;
      transient private BufferedImage minimapImage;
      transient private Registry registry;
      transient private GameController gameController;
      transient private final static int BLOCK_WIDTH = 16;
      transient private final static int BLOCK_HEIGHT = 16;
      transient private final static int TILES_PER_LEVEL = 3;
      transient private final static String CONFIG_FILE = "Blocks.dat";
      public String name = "";
  
      public BlockManager(GameController gc, Registry rg) {
          gameController = gc;
  
          registry = rg;
  
          pCols = (gameController.getPWidth() / BLOCK_WIDTH) + 1;
          pRows = (gameController.getPHeight() / BLOCK_HEIGHT) + 1;
  
          blockTypes = new HashMap();
          blockTypeIdMap = new HashMap();
  
          loadBlockTypes("Blocks.dat");
  
          loadBlocks();
          xPos = new int[2];
  
          int xMove = (int) (BLOCK_WIDTH * gameController.getMoveFactor());
          if (xMove == 0) {
              xMove = 1;
          }
  
          int yMove = (int) (BLOCK_HEIGHT * gameController.getMoveFactor());
          if (yMove == 0) {
              xMove = 1;
          }
  
          gameController.setXMoveSize(xMove);
          gameController.setYMoveSize(yMove);
      }
  
      public BlockManager() {
          blockTypes = new HashMap();
          blockTypeIdMap = new HashMap();
  
          loadBlockTypes("Blocks.dat");
      }
  
      public void updateResolution() {
          pCols = (gameController.getPWidth() / BLOCK_WIDTH) + 1;
          pRows = (gameController.getPHeight() / BLOCK_HEIGHT) + 1;
      }
  
      public void setTransient(Registry rg) {
          registry = rg;
          gameController = rg.getGameController();
          xPos = new int[2];
  
          Iterator it = blockTypes.entrySet().iterator();
          while (it.hasNext()) {
              ArrayList blockTypeList = (ArrayList) (((Map.Entry) it.next()).getValue());
              Iterator itr = blockTypeList.iterator();
              while (itr.hasNext()) {
                  BlockType blockType = (BlockType) itr.next();
                  blockType.setTransient(rg);
              }
          }
          loadMinimapColors();
  
          Thread thread = new Thread(new Runnable() {
  
              public void run() {
                  minimapImage = getMiniMapImage();
              }
          });
          thread.start();
      }
  
      private void loadMinimapColors() {
          int i = 0;
          String line;
          String parts[];
          minimapColors = new HashMap<String, Integer>();
          Integer color = null;
  
          try {
              InputStream in = getClass().getResourceAsStream(GameController.CONFIG_DIR + "MinimapColors.dat");
              BufferedReader br = new BufferedReader(new InputStreamReader(in));
  
              while ((line = br.readLine()) != null) {
                  if (line.length() == 0) {
                      continue;
                  }
                  if (line.startsWith("//")) {
                      continue;
                  }
  
                  i++;
  
                  parts = line.split(" ");
                  if (parts.length != 2) {
                      System.out.println("Error in MinimapColors.dat");
                  }
                  if (!minimapColors.containsKey(parts[0])) {
                      color = Integer.parseInt(parts[1], 16);
                      minimapColors.put(parts[0], color);
                  }
              }
              in.close();
          } catch (Exception e) {
              System.err.println("Error: " + e.getMessage());
          }
      }
  
      private void loadBlockTypes(String fn) {
          int i = 0;
          String line;
          String parts[];
          ArrayList blockTypeList;
          BlockType blockType;
  
          try {
              InputStream in = getClass().getResourceAsStream(GameController.CONFIG_DIR + fn);
              BufferedReader br = new BufferedReader(new InputStreamReader(in));
  
              while ((line = br.readLine()) != null) {
                  if (line.length() == 0) {
                      continue;
                  }
                  if (line.startsWith("//")) {
                      continue;
                  }
  
                  i++;
  
                  parts = line.split(" ");
                  if (parts.length != 5) {
                      System.out.println("Error in " + fn);
                  }
  
                  blockType = new BlockType(registry,
                          i,
                          parts[0],
                          parts[1],
                          Integer.parseInt(parts[2]),
                          Boolean.parseBoolean(parts[3]),
                          Boolean.parseBoolean(parts[4]));
  
                  blockTypeIdMap.put(new Integer(i), blockType);
  
                  if (blockTypes.containsKey(parts[1])) {
                      blockTypeList = null;
                      blockTypeList = (ArrayList) blockTypes.get(parts[1]);
                      blockTypeList.add(blockType);
                      blockTypes.put(parts[1], blockTypeList);
                  } else {
                      blockTypeList = null;
                      blockTypeList = new ArrayList();
                      blockTypeList.add(blockType);
                      blockTypes.put(parts[1], blockTypeList);
                  }
              }
              in.close();
          } catch (Exception e) {
              System.err.println("Error: " + e.getMessage());
          }
      }
  
      public int getRandomIdByGroup(String g) {
          int id = 0;
  
          if (g.equals("Dirt") && Rand.getRange(0, 1200) < 5) {
              g = "DirtAccent";
          } else if (g.equals("Stone") && Rand.getRange(0, 1200) < 5) {
              g = "StoneAccent";
          }
          if (blockTypes.containsKey(g)) {
              ArrayList blockTypeList;
  
              blockTypeList = (ArrayList) blockTypes.get(g);
  
              BlockType bt = (BlockType) blockTypeList.get(Rand.getRange(0, blockTypeList.size() - 1));
  
              id = bt.getType();
          } else {
              id = 0;
          }
  
          return id;
      }
  
      public BlockType getRandomBlockTypeByGroup(String g) {
          int id = 0;
  
          if (blockTypes.containsKey(g)) {
              ArrayList blockTypeList;
  
              blockTypeList = (ArrayList) blockTypes.get(g);
  
              BlockType bt = (BlockType) blockTypeList.get(Rand.getRange(0, blockTypeList.size() - 1));
  
              return bt;
          } else {
              return null;
          }
      }
  
      public int getBlockTypeIdByName(String name) {
          int id = 0;
          Iterator it = blockTypes.entrySet().iterator();
          while (it.hasNext() && id == 0) {
              ArrayList blockTypeList = (ArrayList) (((Map.Entry) it.next()).getValue());
              Iterator itr = blockTypeList.iterator();
              while (itr.hasNext() && id == 0) {
                  BlockType blockType = (BlockType) itr.next();
                  if (blockType.getName().equals(name)) {
                      id = blockType.getType();
                  }
              }
          }
          return id;
      }
  
      public int getMapWidth() {
          return mapWidth;
      }
  
      public int getMapHeight() {
          return mapHeight;
      }
  
      public boolean isIdInGroup(int id, String g) {
          if (id == 0 && g.equals("None")) {
              return true;
          }
  
          if (blockTypes.containsKey(g)) {
              ArrayList blockTypeList;
  
              blockTypeList = (ArrayList) blockTypes.get(g);
  
              for (int i = 0; i < blockTypeList.size(); i++) {
                  BlockType bt = (BlockType) blockTypeList.get(i);
                  if (bt.getType() == id) {
                      return true;
                  }
              }
          }
  
          return false;
      }
  
      public static int getBlockWidth() {
          return BLOCK_WIDTH;
      }
  
      public static int getBlockHeight() {
          return BLOCK_HEIGHT;
      }
  
      public int getPWidth() {
          return gameController.getPWidth();
      }
  
      public int getPHeight() {
          return gameController.getPHeight();
      }
  
      public int getMapOffsetX() {
          return gameController.getMapOffsetX();
      }
  
      public int getMapOffsetY() {
          return gameController.getMapOffsetY();
      }
  
      public int findFloor(int xWorld) {
          int xCol = (xWorld / BLOCK_WIDTH);
          if (xCol == -1) {
              int i = 0;
          } else {
              if (xCol < blocks.length && xCol >= 0) {
                  for (int y = (blocks[xCol].length - 1); y >= 0; y--) {
                      if (!isIdInGroup(blocks[xCol][y], "None")) {
                          BlockType bt = getBlockTypeById(blocks[xCol][y]);
                          if (bt != null && !bt.isBackground()) {
                              return (y * BLOCK_HEIGHT) + BLOCK_HEIGHT;
                          }
                      }
                  }
              }
          }
  
          return 0;
      }
  
      public short[] blocksUnder(int xStartPix, int xEndPix, int yPix) {
          int xStart = xStartPix / BLOCK_WIDTH;
          int xEnd = xEndPix / BLOCK_WIDTH;
          int numberOfBlocks = xEnd - xStart + 1;
          short[] underBlocks = new short[numberOfBlocks];
  
          for (int i = 0; i < numberOfBlocks; i++) {
              underBlocks[i] = -1;
          }
          underBlocks[0] = blocks[xStart][(yPix - 1) / BLOCK_HEIGHT];
          for (int xCol = xStart; xCol - xStart < underBlocks.length; xCol++) {
              if (blocks.length > xCol && blocks[xCol].length > (yPix - 1) / BLOCK_HEIGHT) {
                  underBlocks[xCol - xStart] = blocks[xCol][(yPix - 1) / BLOCK_HEIGHT];
              }
          }
          return underBlocks;
      }
  
      public int[] getTownStartEnd(int x, int y) {
          boolean isTown = false;
          BlockType bt = null;
  
          xPos[0] = xPos[1] = -1;
          int xCurrent = (x - 1) / BLOCK_WIDTH;
          int yCurrent = (y - 1) / BLOCK_HEIGHT;
          short b = blocks[xCurrent][yCurrent];
          if (isIdInGroup(b, "Town")) {
              boolean keepLooping = true;
              while (keepLooping) {
                  xPos[0] = xCurrent * BLOCK_WIDTH;
                  xCurrent--;
                  if (xCurrent < 0) {
                      break;
                  }
                  b = blocks[xCurrent][yCurrent];
                  if (!isIdInGroup(b, "Town")) {
                      keepLooping = false;
                  }
                  bt = getBlockTypeById(blocks[xCurrent][yCurrent + 1]);
                  if (bt != null && !bt.isBackground()) {
                      keepLooping = false;
                  }
              }
              xCurrent++;
              b = blocks[xCurrent][yCurrent];
              isTown = false;
              if (isIdInGroup(b, "Town")) {
                  isTown = true;
              }
              while (isTown) {
                  xPos[1] = (xCurrent + 1) * BLOCK_WIDTH;
                  xCurrent++;
                  if (xCurrent > blocks.length - 1) {
                      break;
                  }
                  b = blocks[xCurrent][yCurrent];
  
                  isTown = isIdInGroup(b, "Town");
                  bt = getBlockTypeById(blocks[xCurrent][yCurrent + 1]);
                  if (bt != null && !bt.isBackground()) {
                      isTown = false;
                  }
              }
          }
          return xPos;
      }
  
      public int findNextFloor(int xWorld, int yWorld, int height) {
          int xCol = (xWorld / BLOCK_WIDTH);
          int yCol = (yWorld / BLOCK_HEIGHT);
  
          int blockSpaceFound = 0;
  
          int blockSpaceNeeded = (int) Math.ceil((float) height / (float) BLOCK_HEIGHT);
          if (blockSpaceNeeded < 1) {
              blockSpaceNeeded = 1;
          }
          if (xCol > 0 && xCol < blocks.length && yCol < blocks[xCol].length) {
              for (int y = yCol; y >= 0; y--) {
                  if (!isIdInGroup(blocks[xCol][y], "None")) {
                      BlockType bt = getBlockTypeById(blocks[xCol][y]);
                      if (bt != null && !bt.isBackground()) {
                          if (blockSpaceFound >= blockSpaceNeeded) {
                              return ((y + 1) * BLOCK_HEIGHT) + BLOCK_HEIGHT;
                          }
                          blockSpaceFound = 0;
                      } else {
                          blockSpaceFound++;
                      }
                  } else {
                      blockSpaceFound++;
                  }
              }
          } else {
              int i = 0;
          }
          return 0;
      }
  
      public boolean doesRectContainBlocks(int mapX, int mapY, int width, int height) {
          int xStart = mapX / BLOCK_WIDTH;
          int xEnd = (mapX + width) / BLOCK_WIDTH;
  
          int yStart = mapY / BLOCK_HEIGHT;
          int yEnd = (mapY + height) / BLOCK_HEIGHT;
  
          for (int xCol = xStart; xCol <= xEnd; xCol++) {
              for (int yCol = yStart; yCol <= yEnd; yCol++) {
                  if (xCol < blocks.length && xCol >= 0) {
                      if (yCol < blocks[xCol].length && yCol > 0) {
                          if (blocks[xCol][yCol] != 0) {
                              BlockType bt = getBlockTypeById(blocks[xCol][yCol]);
                              if (bt != null && !bt.isBackground()) {
                                  return true;
                              }
                          }
                      }
                  }
              }
          }
  
          return false;
      }
  
      public void setBlockByGroup(int mapX, int mapY, String g) {
          setBlock(mapX, mapY, (short) getRandomIdByGroup(g));
      }
  
      public void setBlock(int mapX, int mapY, short blockId) {
          int x = mapX / BLOCK_WIDTH;
          int y = mapY / BLOCK_HEIGHT;
  
          blocks[x][y] = blockId;
      }
  
      public String getBlockGroup(int mapX, int mapY) {
          String group = "None";
          short blockId = getBlockFromPoint(new Point(mapX, mapY));
          BlockType bt = getBlockTypeById(blockId);
          if (bt != null) {
              group = bt.getGroup();
          }
          return group;
      }
  
      public BlockType getBlockTypeById(short id) {
          Integer i = new Integer(id);
          BlockType bt = null;
          if (blockTypeIdMap.containsKey(i)) {
              bt = (BlockType) blockTypeIdMap.get(i);
          }
          return bt;
      }
  
      public short getBlockFromPoint(Point p) {
          int xIndex = (p.x / BLOCK_WIDTH);
          int yIndex = (p.y / BLOCK_HEIGHT);
  
          if (xIndex >= 0 && xIndex <= (mapCols - 1) && yIndex >= 0 && yIndex <= (mapRows - 1)) {
              return blocks[xIndex][yIndex];
          }
  
          return 0;
      }
  
      public int mapToPanelX(int x) {
          return x - gameController.getMapOffsetX();
      }
  
      public int mapToPanelY(int y) {
          return y - gameController.getMapOffsetY();
      }
  
      public void update() {
      }
  
      public void render(Graphics g) {
          //render only the blocks that are in the view port
  
          int pOffsetX = (gameController.getMapOffsetX() / BLOCK_WIDTH);
  