diff --git a/src/engine/InterestManagement/Terrain.java b/src/engine/InterestManagement/Terrain.java index 63ea58f6..73c7aa9e 100644 --- a/src/engine/InterestManagement/Terrain.java +++ b/src/engine/InterestManagement/Terrain.java @@ -8,185 +8,32 @@ package engine.InterestManagement; -import engine.Enum; -import engine.gameManager.ConfigManager; -import engine.gameManager.DbManager; import engine.gameManager.ZoneManager; import engine.math.Vector2f; import engine.math.Vector3fImmutable; import engine.objects.Zone; -import org.pmw.tinylog.Logger; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.sql.ResultSet; -import java.sql.SQLException; + import java.util.HashMap; -import java.util.stream.Stream; public class Terrain { // Class variables - public static final HashMap heightmapByLoadNum = new HashMap<>(); - - public static final HashMap _pixelData = new HashMap<>(); + public static final HashMap _heightmap_pixel_cache = new HashMap<>(); - // Bootstrap Tracking - public static int heightMapsCreated = 0; - public static Terrain playerCityTerrain; - // Heightmap data for this heightmap - public final int heightMapID; - public final int maxHeight; - public final int fullExtentsX; - public final int fullExtentsY; - public final int zoneLoadID; - public BufferedImage heightmapImage; - public float cell_size_x; - public float cell_size_y; - public float seaLevel = 0; - public short[][] pixelColorValues; - public int cell_count_x; - public int cell_count_y; + public int template; + public short[][] terrain_pixel_data; + public Vector2f terrain_size = new Vector2f(); + public Vector2f cell_size = new Vector2f(); + public Vector2f cell_count = new Vector2f(); public float terrain_scale; - public Terrain(ResultSet rs) throws SQLException { - - this.heightMapID = rs.getInt("heightMapID"); - this.maxHeight = rs.getInt("maxHeight"); - int halfExtentsX = rs.getInt("xRadius"); - int halfExtentsY = rs.getInt("zRadius"); - this.zoneLoadID = rs.getInt("zoneLoadID"); - this.seaLevel = rs.getFloat("seaLevel"); - - // Cache the full extents to avoid the calculation - - this.fullExtentsX = halfExtentsX * 2; - this.fullExtentsY = halfExtentsY * 2; - - this.heightmapImage = null; - File imageFile = new File(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/" + this.heightMapID + ".bmp"); - - // early exit if no image file was found. Will log in caller. - - if (!imageFile.exists()) - return; - - // load the heightmap image. - - try { - this.heightmapImage = ImageIO.read(imageFile); - } catch (IOException e) { - Logger.error("***Error loading heightmap data for heightmap " + this.heightMapID + e); - } - - // Calculate the data we do not load from table - - this.cell_count_x = this.heightmapImage.getWidth() - 1; - this.cell_size_x = this.fullExtentsX / (float) cell_count_x; - - this.cell_count_y = this.heightmapImage.getHeight() - 1; - this.cell_size_y = this.fullExtentsY / (float) cell_count_y; - - this.terrain_scale = this.maxHeight / 255f; - - // Generate pixel array from image data - - generatePixelData(this); - - Terrain.heightmapByLoadNum.put(this.zoneLoadID, this); - - heightMapsCreated++; - } + public static int heightMapsCreated; - //Created for PlayerCities public Terrain() { - this.heightMapID = 999999; - this.maxHeight = 5; // for real... - int halfExtentsX = (int) Enum.CityBoundsType.ZONE.halfExtents; - int halfExtentsY = (int) Enum.CityBoundsType.ZONE.halfExtents; - this.zoneLoadID = 0; - this.seaLevel = 0; - - // Cache the full extents to avoid the calculation - - this.fullExtentsX = halfExtentsX * 2; - this.fullExtentsY = halfExtentsY * 2; - - this.heightmapImage = null; - - // Calculate the data we do not load from table - - this.cell_size_x = halfExtentsX; - this.cell_size_y = halfExtentsY; - - this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY]; - - for (int y = 0; y < this.fullExtentsY; y++) { - for (int x = 0; x < this.fullExtentsX; x++) { - pixelColorValues[x][y] = 255; - } - } - - cell_count_x = this.pixelColorValues.length - 1; - cell_count_y = this.pixelColorValues[0].length - 1; - this.terrain_scale = this.maxHeight / 255f; - } - - public Terrain(Zone zone) { - - this.heightMapID = 999999; - this.maxHeight = 0; - int halfExtentsX = (int) zone.bounds.getHalfExtents().x; - int halfExtentsY = (int) zone.bounds.getHalfExtents().y; - this.zoneLoadID = 0; - this.seaLevel = 0; - - // Cache the full extents to avoid the calculation - - this.fullExtentsX = halfExtentsX * 2; - this.fullExtentsY = halfExtentsY * 2; - - this.heightmapImage = null; - - // Calculate the data we do not load from table - - this.cell_size_x = halfExtentsX; - this.cell_size_y = halfExtentsY; - - this.pixelColorValues = new short[this.fullExtentsX][this.fullExtentsY]; - - for (int y = 0; y < this.fullExtentsY; y++) { - for (int x = 0; x < this.fullExtentsX; x++) { - pixelColorValues[x][y] = 0; - } - } - - cell_count_x = this.pixelColorValues.length - 1; - cell_count_y = this.pixelColorValues[0].length - 1; - this.terrain_scale = this.maxHeight / 255f; - } - - public static void GeneratePlayerCityHeightMap() { - - Terrain.playerCityTerrain = new Terrain(); - - } - - public static void GenerateCustomHeightMap(Zone zone) { - - Terrain heightMap = new Terrain(zone); - - Terrain.heightmapByLoadNum.put(zone.template, heightMap); } @@ -245,91 +92,19 @@ public class Terrain { } - public static void loadAlHeightMaps() { - - // Load the heightmaps into staging hashmap keyed by HashMapID - - DbManager.HeightMapQueries.LOAD_ALL_HEIGHTMAPS(); - - //generate static player city heightmap. - - Terrain.GeneratePlayerCityHeightMap(); - - Logger.info(Terrain.heightmapByLoadNum.size() + " Heightmaps cached."); - - // Load pixel data for heightmaps - - try (Stream filePathStream = Files.walk(Paths.get(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/TARGA/"))) { - filePathStream.forEach(filePath -> { - - if (Files.isRegularFile(filePath)) { - File imageFile = filePath.toFile(); - - try { - BufferedImage heightmapImage = ImageIO.read(imageFile); - - // Generate pixel data for this heightmap. RPG channels are all the same - // in this greyscale TGA heightmap. We will choose red. - - short[][] colorData = new short[heightmapImage.getWidth()][heightmapImage.getHeight()]; - - for (int y = 0; y < heightmapImage.getHeight(); y++) - for (int x = 0; x < heightmapImage.getWidth(); x++) { - - Color color = new Color(heightmapImage.getRGB(x, y)); - colorData[x][y] = (short) color.getRed(); - } - - // Insert color data into lookup table - - int heightMapID = Integer.parseInt(imageFile.getName().substring(0, imageFile.getName().lastIndexOf("."))); - _pixelData.put(heightMapID, colorData); - - } catch (IOException e) { - Logger.error(e); - } - - } - }); // Try with resources block - - } catch (IOException e) { - Logger.error(e); - } - - } - - private static void generatePixelData(Terrain terrain) { - - Color color; - - // Generate altitude lookup table for this heightmap - - terrain.pixelColorValues = new short[terrain.heightmapImage.getWidth()][terrain.heightmapImage.getHeight()]; - - for (int y = 0; y < terrain.heightmapImage.getHeight(); y++) { - for (int x = 0; x < terrain.heightmapImage.getWidth(); x++) { - - color = new Color(terrain.heightmapImage.getRGB(x, y)); - terrain.pixelColorValues[x][y] = (short) color.getRed(); - } - } - - } - public Vector2f getTerrainCell(Vector2f terrainLoc) { - float terrainCell_x = terrainLoc.x / this.cell_size_x; - float terrainCell_y = terrainLoc.y / this.cell_size_y; + Vector2f terrain_cell = new Vector2f(terrainLoc.x / this.cell_size.x, terrainLoc.y / this.cell_size.y); // Clamp values when standing directly on max pole - if (terrainCell_x >= this.cell_count_x) - terrainCell_x = terrainCell_x - 1; + if (terrain_cell.x >= this.cell_count.x) + terrain_cell.x = terrain_cell.x - 1; - if (terrainCell_y >= this.cell_count_y) - terrainCell_y = terrainCell_x - 1; + if (terrain_cell.x >= this.cell_count.y) + terrain_cell.y = terrain_cell.y - 1; - return new Vector2f(terrainCell_x, terrainCell_y); + return terrain_cell; } public float getInterpolatedTerrainHeight(Vector2f terrainLoc) { @@ -351,10 +126,10 @@ public class Terrain { float bottomLeftHeight; float bottomRightHeight; - topLeftHeight = pixelColorValues[gridX][gridY]; - topRightHeight = pixelColorValues[gridX + 1][gridY]; - bottomLeftHeight = pixelColorValues[gridX][gridY + 1]; - bottomRightHeight = pixelColorValues[gridX + 1][gridY + 1]; + topLeftHeight = terrain_pixel_data[gridX][gridY]; + topRightHeight = terrain_pixel_data[gridX + 1][gridY]; + bottomLeftHeight = terrain_pixel_data[gridX][gridY + 1]; + bottomRightHeight = terrain_pixel_data[gridX + 1][gridY + 1]; // Interpolate between the 4 vertices @@ -367,5 +142,4 @@ public class Terrain { return interpolatedHeight; } - } diff --git a/src/engine/objects/City.java b/src/engine/objects/City.java index 10f0204f..69ab5aba 100644 --- a/src/engine/objects/City.java +++ b/src/engine/objects/City.java @@ -12,7 +12,6 @@ package engine.objects; import engine.Enum; import engine.Enum.*; import engine.InterestManagement.RealmMap; -import engine.InterestManagement.Terrain; import engine.InterestManagement.WorldGrid; import engine.db.archive.CityRecord; import engine.db.archive.DataWarehouse; @@ -587,10 +586,6 @@ public class City extends AbstractWorldObject { 0.0f); this.setBounds(cityBounds); - if (zone.getHeightMap() == null && this.isNpc == 1 && this.getObjectUUID() != 1213) { - Terrain.GenerateCustomHeightMap(zone); - Logger.info(zone.zoneName + " created custom heightmap"); - } } catch (Exception e) { Logger.error(e); } diff --git a/src/engine/objects/Zone.java b/src/engine/objects/Zone.java index 85a6d85b..bbcafdd1 100644 --- a/src/engine/objects/Zone.java +++ b/src/engine/objects/Zone.java @@ -70,6 +70,8 @@ public class Zone extends AbstractGameObject { public float terrain_max_y; public int terrain_image; + public Terrain terrain = null; + /** * ResultSet Constructor */ diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index 595d91c8..275925d6 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -14,7 +14,6 @@ import engine.Enum.DispatchChannel; import engine.Enum.MinionType; import engine.Enum.SupportMsgType; import engine.InterestManagement.RealmMap; -import engine.InterestManagement.Terrain; import engine.InterestManagement.WorldGrid; import engine.db.archive.DataWarehouse; import engine.db.handlers.dbRuneBaseHandler; @@ -39,6 +38,7 @@ import engine.net.client.msg.UpdateStateMsg; import engine.net.client.msg.chat.ChatSystemMsg; import engine.objects.*; import engine.server.MBServerStatics; +import engine.util.MapLoader; import engine.util.ThreadUtils; import engine.workthreads.DisconnectTrashTask; import engine.workthreads.HourlyJobThread; @@ -385,7 +385,7 @@ public class WorldServer { Blueprint.loadAllBlueprints(); Logger.info("Initializing Heightmap data"); - Terrain.loadAlHeightMaps(); + MapLoader.loadAlHeightMaps(); Logger.info("Loading Race data"); Enum.RaceType.initRaceTypeTables(); @@ -466,14 +466,6 @@ public class WorldServer { Logger.info("Starting Mob AI Thread"); MobAIThread.startAIThread(); - for (Zone zone : ZoneManager.getAllZones()) { - if (zone.getHeightMap() != null) { - if (zone.getHeightMap().cell_size_x == 0) { - System.out.println("Zone load num: " + zone.template + " has no bucket width"); - } - } - } - Logger.info("World data loaded."); //set default accesslevel for server *** Refactor who two separate variables? diff --git a/src/engine/util/MapLoader.java b/src/engine/util/MapLoader.java index a8f14ae6..ce187965 100644 --- a/src/engine/util/MapLoader.java +++ b/src/engine/util/MapLoader.java @@ -5,6 +5,7 @@ package engine.util; import engine.InterestManagement.RealmMap; +import engine.InterestManagement.Terrain; import engine.gameManager.ConfigManager; import engine.server.MBServerStatics; import org.pmw.tinylog.Logger; @@ -14,6 +15,10 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Stream; public enum MapLoader { @@ -87,4 +92,47 @@ public enum MapLoader { g.dispose(); return dimg; } + + public static void loadAlHeightMaps() { + + // Load pixel data for heightmaps + + try (Stream filePathStream = Files.walk(Paths.get(ConfigManager.DEFAULT_DATA_DIR + "heightmaps/TARGA/"))) { + filePathStream.forEach(filePath -> { + + if (Files.isRegularFile(filePath)) { + File imageFile = filePath.toFile(); + + try { + BufferedImage heightmapImage = ImageIO.read(imageFile); + + // Generate pixel data for this heightmap. RPG channels are all the same + // in this greyscale TGA heightmap. We will choose red. + + short[][] colorData = new short[heightmapImage.getWidth()][heightmapImage.getHeight()]; + + for (int y = 0; y < heightmapImage.getHeight(); y++) + for (int x = 0; x < heightmapImage.getWidth(); x++) { + + Color color = new Color(heightmapImage.getRGB(x, y)); + colorData[x][y] = (short) color.getRed(); + } + + // Insert color data into lookup table + + int heightMapID = Integer.parseInt(imageFile.getName().substring(0, imageFile.getName().lastIndexOf("."))); + Terrain._heightmap_pixel_cache.put(heightMapID, colorData); + + } catch (IOException e) { + Logger.error(e); + } + + } + }); // Try with resources block + + } catch (IOException e) { + Logger.error(e); + } + + } }