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); int pOffsetY = (gameController.getMapOffsetY() / BLOCK_HEIGHT); BlockType blockType = null; int xPos, yPos; xPos = 0; int yRange = pRows + pOffsetY; int xRange; yPos = mapToPanelY(pOffsetY * BLOCK_HEIGHT); yPos = getPHeight() - yPos; yPos -= BLOCK_HEIGHT; for (int y = pOffsetY; y <= yRange; y++) { xRange = pCols + pOffsetX; xPos = mapToPanelX(pOffsetX * BLOCK_WIDTH); for (int x = pOffsetX; x <= xRange; x++) { if (x <= (mapCols - 1) && y <= (mapRows - 1)) { blockType = getBlockTypeById(blocks[x][y]); if (blockType != null) { g.drawImage(blockType.getImage(), xPos, yPos, null); } } xPos += BLOCK_WIDTH; } yPos -= BLOCK_HEIGHT; } /* * System.out.println("Surface Min: " + mapSurfaceMin); int yPos = * this.mapToPanelY(mapSurfaceMin); yPos = this.getPHeight() - yPos; * yPos -= 1; g.setColor(Color.red); g.drawLine(0, yPos, 10000, yPos); */ } private BufferedImage getMiniMapImage() { BufferedImage image = new BufferedImage(blocks.length, blocks[0].length, BufferedImage.TYPE_INT_RGB); WritableRaster raster = image.getRaster(); int[] colorArray = new int[3]; Integer color = null; int c = 0; for (int x = 0; x < blocks.length; x++) { for (int y = 0; y < blocks[0].length; y++) { colorArray[0] = 0; if (x >= 0 && y >= 0 && x < blocks.length && y < blocks[0].length) { color = minimapColors.get(getBlockGroup(x * BLOCK_WIDTH, (blocks[0].length - y - 1) * BLOCK_HEIGHT)); if (color != null) { c = color.intValue(); colorArray[0] = (c >> 16) & 0xff; colorArray[1] = (c >> 8) & 0xff; colorArray[2] = c & 0xff; } else { colorArray[0] = 0; colorArray[1] = 0; colorArray[2] = 0; } } raster.setPixel(x, y, colorArray); } } return image; } public boolean renderMiniMap(Graphics g, int x, int y, int w, int h, String resourceName) { boolean hasImage = false; if (minimapImage != null) { int playerX = registry.getPlayerManager().getCurrentPlayer().getMapX(); int playerY = registry.getPlayerManager().getCurrentPlayer().getMapY(); int pOffsetX = playerX / BLOCK_WIDTH; int pOffsetY = playerY / BLOCK_HEIGHT; int x1 = pOffsetX - w / 2; int y1 = pOffsetY + h / 2; if (x1 < 0) { x1 = 0; } else if (x1 > minimapImage.getWidth() - w) { x1 = minimapImage.getWidth() - w; } if (y1 < 0) { y1 = 0; } else if (y1 > minimapImage.getHeight() - h) { y1 = minimapImage.getHeight() - h; } int cy = y1; y1 = minimapImage.getHeight() - y1; try { BufferedImage image = minimapImage.getSubimage(x1, y1, w, h); g.drawImage(image, x, y, null); registry.getResourceManager().renderMiniMapResources(g, x, y, x1 + w / 2, cy - h / 2, w, h, pOffsetX, pOffsetY, resourceName); int[] xy = getMiniMapPosition(x, y, x1 + w / 2, cy - h / 2, w, h, pOffsetX, pOffsetY); registry.getPlayerManager().renderMiniMapPlayers(g, x, y, x1 + w / 2, cy - h / 2, w, h, pOffsetX, pOffsetY); } catch (Exception e) { //part of image is off screen } // image = registry.getImageLoader().changeTransperancy(image, 0.5f); hasImage = true; } return hasImage; } public int[] getMiniMapPosition(int mx, int my, int cx, int cy, int w, int h, int x, int y) { int[] xy = new int[2]; xy[0] = x; xy[1] = y; if (xy[0] < cx - w / 2) { xy[0] = 0; } else if (xy[0] > cx + w / 2) { xy[0] = w; } else { xy[0] -= cx - w / 2; } if (xy[1] < cy - h / 2) { xy[1] = 0; } else if (xy[1] > cy + h / 2) { xy[1] = h; } else { xy[1] -= cy - h / 2; } xy[0] += mx; xy[1] += my; xy[1] = h - xy[1] + 21; return xy; } public void loadBlocks() { World newWorld = new World(""); loadBlocks(newWorld); } public void loadBlocks(World newWorld) { BlockType bt = null; int[] size = newWorld.getWorldSize(); mapCols = size[0]; mapRows = size[1]; mapWidth = BLOCK_WIDTH * mapCols; mapHeight = BLOCK_HEIGHT * mapRows; mapSurfaceMin = newWorld.getWorldGroundMin() * BLOCK_HEIGHT; mapSurfaceMax = newWorld.getWorldGroundMax() * BLOCK_HEIGHT; mapLevelStart = newWorld.getWipZMin() * BLOCK_HEIGHT; mapLevelHeight = newWorld.getWipHeight() * BLOCK_HEIGHT * TILES_PER_LEVEL; blocks = new short[size[0]][size[1]]; for (int x = 0; x < size[0]; x++) { for (int y = size[1] - 1; y > -1; y--) { blocks[x][y] = (short) newWorld.blockArray[x][y]; } } } public int getMapSurfaceMin() { return mapSurfaceMin; } public int getMapSurfaceMax() { return mapSurfaceMax; } public int getLevelByY(int y) { int level = 0; if (y >= mapSurfaceMin) { return 0; } int distanceFromSurface = mapSurfaceMin - y; level = (int) Math.ceil((float) distanceFromSurface / (float) mapLevelHeight); return level; } public int getLevelTop(int level) { int y = 0; if (level <= 0) { return mapHeight; } return mapSurfaceMin - ((level - 1) * mapLevelHeight) - 1; } public int getLevelBottom(int level) { int y = 0; if (level <= 0) { return mapSurfaceMin; } return mapSurfaceMin - (level * mapLevelHeight); } public short[][] getBlockCollumns(int startColumn, int endColumn) { short[][] retBlocks = null; if (endColumn >= blocks.length) { endColumn = blocks.length - 1; } if (startColumn >= blocks.length) { endColumn = blocks.length - 1; } int numColumns = endColumn - startColumn + 1; if (numColumns > 0) { retBlocks = new short[numColumns][blocks[0].length]; retBlocks = java.util.Arrays.copyOfRange(blocks, startColumn, endColumn); } return retBlocks; } public void setBlockCollumns(short[][] setBlocks, int startColumn, int endColumn) { for (int x = 0; x < setBlocks.length; x++) { for (int y = 0; y < setBlocks[0].length; y++) { if (x + startColumn < blocks.length && y < blocks[0].length) { blocks[x + startColumn][y] = setBlocks[x][y]; } } } } public void clearBlockArray() { blocks = new short[1][1]; } public void resetBlockArray(int w, int h) { blocks = new short[w][h]; } public int getMapCols() { return mapCols; } public int getMapRows() { return mapRows; } public BufferedImage getAsGif() { BufferedImage image = null; try { image = new BufferedImage(mapCols, mapRows, BufferedImage.TYPE_INT_RGB); WritableRaster raster = image.getRaster(); int[] colorArray = new int[3]; for (int i = 0; i < mapCols; i++) { for (int j = 0; j < mapRows; j++) { colorArray[0] = blocks[i][mapRows - j - 1]; colorArray[1] = 0; colorArray[2] = 0; raster.setPixel(i, j, colorArray); } } } catch (Exception e) { } return image; } public void writeOutGif() { try { BufferedImage image = getAsGif(); ImageIO.write(image, "gif", new File("CardImage.gif")); } catch (Exception e) { } } private void readObject(ObjectInputStream aInputStream) throws Exception { aInputStream.defaultReadObject(); } private void writeObject(ObjectOutputStream aOutputStream) throws Exception { aOutputStream.defaultWriteObject(); } @Override public Object clone() { Object ret = null; try { ret = super.clone(); } catch (CloneNotSupportedException e) { } return ret; } }