private void fireTilesChangedIncludeBorder(Set<Tile> tiles) { if (showBorder && (tileProvider instanceof Dimension) && (((Dimension) tileProvider).getDim() == DIM_NORMAL) && (((Dimension) tileProvider).getBorder() != null)) { final Set<Point> coordSet = new HashSet<>(); for (Tile tile : tiles) { final int tileX = tile.getX(), tileY = tile.getY(), borderSize = ((Dimension) tileProvider).getBorderSize(); for (int dx = -borderSize; dx <= borderSize; dx++) { for (int dy = -borderSize; dy <= borderSize; dy++) { coordSet.add(getTileCoordinates(tileX + dx, tileY + dy)); } } } for (TileListener listener : listeners) { listener.tilesChanged(this, coordSet); } } else { Set<Point> coords = tiles.stream().map(this::getTileCoordinates).collect(Collectors.toSet()); for (TileListener listener : listeners) { listener.tilesChanged(this, coords); } } }
@Override public void tilesRemoved(Dimension dimension, Set<Tile> tiles) { for (Tile tile : tiles) { tile.removeListener(this); } fireTilesChangedIncludeBorder(tiles); }
@Override public void removeTileListener(TileListener tileListener) { listeners.remove(tileListener); if (active && listeners.isEmpty()) { for (Tile tile : ((Dimension) tileProvider).getTiles()) { tile.removeListener(this); } ((Dimension) tileProvider).removeDimensionListener(this); } }
@Override public void addTileListener(TileListener tileListener) { if (active && listeners.isEmpty()) { ((Dimension) tileProvider).addDimensionListener(this); for (Tile tile : ((Dimension) tileProvider).getTiles()) { tile.addListener(this); } } if (!listeners.contains(tileListener)) { listeners.add(tileListener); } }
/** * Convert the actual tile coordinates to zoom-corrected (tile provider coordinate system) * coordinates. * * @param tile The tile of which to convert the coordinates. * @return The coordinates of the tile in the tile provider coordinate system (corrected for * zoom). */ private Point getTileCoordinates(Tile tile) { return getTileCoordinates(tile.getX(), tile.getY()); }
private void paintUnzoomedTile( final Image tileImage, final int x, final int y, final int dx, final int dy) { TileType tileType = getUnzoomedTileType(x, y); switch (tileType) { case WORLD: Tile tile = tileProvider.getTile(x, y); if (tile.hasLayer(NotPresent.INSTANCE) && (surroundingTileProvider != null)) { surroundingTileProvider.paintTile(tileImage, x, y, dx, dy); } TileRenderer tileRenderer = tileRendererRef.get(); tileRenderer.setTile(tile); tileRenderer.renderTile(tileImage, dx, dy); break; case BORDER: int colour; switch (((Dimension) tileProvider).getBorder()) { case WATER: colour = colourScheme.getColour(BLK_WATER); break; case LAVA: colour = colourScheme.getColour(BLK_LAVA); break; case VOID: colour = VoidRenderer.getColour(); break; default: throw new InternalError(); } Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); try { g2.setColor(new Color(colour)); g2.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); // Draw border lines g2.setColor(Color.BLACK); g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[] {4.0f, 4.0f}, 0.0f)); if (tileProvider.isTilePresent(x, y - 1)) { g2.drawLine(dx + 1, dy + 1, dx + TILE_SIZE - 1, dy + 1); } if (tileProvider.isTilePresent(x + 1, y)) { g2.drawLine(dx + TILE_SIZE - 1, dy + 1, dx + TILE_SIZE - 1, dy + TILE_SIZE - 1); } if (tileProvider.isTilePresent(x, y + 1)) { g2.drawLine(dx + 1, dy + TILE_SIZE - 1, dx + TILE_SIZE - 1, dy + TILE_SIZE - 1); } if (tileProvider.isTilePresent(x - 1, y)) { g2.drawLine(dx + 1, dy + 1, dx + 1, dy + TILE_SIZE - 1); } } finally { g2.dispose(); } break; case WALL: if (surroundingTileProvider != null) { surroundingTileProvider.paintTile(tileImage, x, y, dx, dy); } g2 = (Graphics2D) tileImage.getGraphics(); try { if (surroundingTileProvider == null) { // A surrounding tile provider would have completely // filled the image, but since there isn't one we have // to make sure of that ourselves g2.setColor(new Color(VoidRenderer.getColour())); g2.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); } g2.setColor(new Color(colourScheme.getColour(BLK_BEDROCK))); TileType neighbourType = getUnzoomedTileType(x, y - 1); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(dx, dy, TILE_SIZE, 16); } neighbourType = getUnzoomedTileType(x + 1, y); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(dx + TILE_SIZE - 16, dy, 16, TILE_SIZE); } neighbourType = getUnzoomedTileType(x, y + 1); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(dx, dy + TILE_SIZE - 16, TILE_SIZE, 16); } neighbourType = getUnzoomedTileType(x - 1, y); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(dx, dy, 16, TILE_SIZE); } } finally { g2.dispose(); } break; case SURROUNDS: if (surroundingTileProvider != null) { surroundingTileProvider.paintTile(tileImage, x, y, dx, dy); } break; default: throw new InternalError(); } }
@Override public void paintTile( final Image tileImage, final int x, final int y, final int imageX, final int imageY) { try { if (zoom == 0) { paintUnzoomedTile(tileImage, x, y, imageX, imageY); } else { Graphics2D g2 = (Graphics2D) tileImage.getGraphics(); try { BufferedImage surroundingTileImage = null; final Color waterColour = new Color(colourScheme.getColour(BLK_WATER)); final Color lavaColour = new Color(colourScheme.getColour(BLK_LAVA)); final Color voidColour = new Color(VoidRenderer.getColour()); final Color bedrockColour = new Color(colourScheme.getColour(BLK_BEDROCK)); final int scale = 1 << -zoom; final int subSize = TILE_SIZE / scale; for (int dx = 0; dx < scale; dx++) { for (int dy = 0; dy < scale; dy++) { TileType tileType = getUnzoomedTileType(x * scale + dx, y * scale + dy); switch (tileType) { case WORLD: Tile tile = tileProvider.getTile(x * scale + dx, y * scale + dy); if (tile.hasLayer(NotPresent.INSTANCE)) { if (surroundingTileProvider != null) { if (surroundingTileImage == null) { surroundingTileImage = new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_ARGB); surroundingTileProvider.paintTile(surroundingTileImage, x, y, 0, 0); } g2.drawImage( surroundingTileImage, imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, null); } else { g2.setColor(voidColour); g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, subSize); } } TileRenderer tileRenderer = tileRendererRef.get(); tileRenderer.setTile(tile); tileRenderer.renderTile(tileImage, dx * subSize, dy * subSize); break; case BORDER: Color colour; switch (((Dimension) tileProvider).getBorder()) { case WATER: colour = waterColour; break; case LAVA: colour = lavaColour; break; case VOID: colour = voidColour; break; default: throw new InternalError(); } g2.setColor(colour); g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, subSize); // Draw border lines g2.setColor(Color.BLACK); g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[] {4.0f, 4.0f}, 0.0f)); if (tileProvider.isTilePresent(x * scale + dx, y * scale + dy - 1)) { g2.drawLine( imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize - 1, imageY + dy * subSize); } if (tileProvider.isTilePresent(x * scale + dx + 1, y * scale + dy)) { g2.drawLine( imageX + (dx + 1) * subSize - 1, imageY + dy * subSize, imageX + (dx + 1) * subSize - 1, imageY + (dy + 1) * subSize - 1); } if (tileProvider.isTilePresent(x * scale + dx, y * scale + dy + 1)) { g2.drawLine( imageX + dx * subSize, imageY + (dy + 1) * subSize - 1, imageX + (dx + 1) * subSize - 1, imageY + (dy + 1) * subSize - 1); } if (tileProvider.isTilePresent(x * scale + dx - 1, y * scale + dy)) { g2.drawLine( imageX + dx * subSize, imageY + dy * subSize, imageX + dx * subSize, imageY + (dy + 1) * subSize - 1); } break; case SURROUNDS: case WALL: if (surroundingTileProvider != null) { if (surroundingTileImage == null) { surroundingTileImage = new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_ARGB); surroundingTileProvider.paintTile(surroundingTileImage, x, y, 0, 0); } g2.drawImage( surroundingTileImage, imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, imageX + dx * subSize, imageY + dy * subSize, imageX + (dx + 1) * subSize, imageY + (dy + 1) * subSize, null); } else { g2.setColor(voidColour); g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, subSize); } if (tileType == TileType.WALL) { g2.setColor(bedrockColour); TileType neighbourType = getUnzoomedTileType(x * scale + dx, y * scale + dy - 1); int wallWidth = Math.max(subSize / 8, 1); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, subSize, wallWidth); } neighbourType = getUnzoomedTileType(x * scale + dx + 1, y * scale + dy); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect( imageX + (dx + 1) * subSize - wallWidth, imageY + dy * subSize, wallWidth, subSize); } neighbourType = getUnzoomedTileType(x * scale + dx, y * scale + dy + 1); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect( imageX + dx * subSize, imageY + (dy + 1) * subSize - wallWidth, subSize, wallWidth); } neighbourType = getUnzoomedTileType(x * scale + dx - 1, y * scale + dy); if ((neighbourType == TileType.WORLD) || (neighbourType == TileType.BORDER)) { g2.fillRect(imageX + dx * subSize, imageY + dy * subSize, wallWidth, subSize); } } break; } } } } finally { g2.dispose(); } } } catch (Throwable e) { // Log at debug level because this tends to happen when zooming in // and out, probably due to some state getting out of sync. It // doesn't so far appear to have any visible consequences. logger.error("Exception while generating image for tile at " + x + ", " + y, e); } }