forked from MagicBane/Server
Partial refactor.
This commit is contained in:
@@ -8,185 +8,32 @@
|
|||||||
|
|
||||||
package engine.InterestManagement;
|
package engine.InterestManagement;
|
||||||
|
|
||||||
import engine.Enum;
|
|
||||||
import engine.gameManager.ConfigManager;
|
|
||||||
import engine.gameManager.DbManager;
|
|
||||||
import engine.gameManager.ZoneManager;
|
import engine.gameManager.ZoneManager;
|
||||||
import engine.math.Vector2f;
|
import engine.math.Vector2f;
|
||||||
import engine.math.Vector3fImmutable;
|
import engine.math.Vector3fImmutable;
|
||||||
import engine.objects.Zone;
|
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.HashMap;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class Terrain {
|
public class Terrain {
|
||||||
|
|
||||||
// Class variables
|
// Class variables
|
||||||
|
|
||||||
public static final HashMap<Integer, Terrain> heightmapByLoadNum = new HashMap<>();
|
public static final HashMap<Integer, short[][]> _heightmap_pixel_cache = new HashMap<>();
|
||||||
|
|
||||||
public static final HashMap<Integer, short[][]> _pixelData = new HashMap<>();
|
|
||||||
|
|
||||||
// Bootstrap Tracking
|
public int template;
|
||||||
public static int heightMapsCreated = 0;
|
public short[][] terrain_pixel_data;
|
||||||
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 Vector2f terrain_size = new Vector2f();
|
||||||
|
public Vector2f cell_size = new Vector2f();
|
||||||
|
public Vector2f cell_count = new Vector2f();
|
||||||
public float terrain_scale;
|
public float terrain_scale;
|
||||||
|
|
||||||
public Terrain(ResultSet rs) throws SQLException {
|
public static int heightMapsCreated;
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Created for PlayerCities
|
|
||||||
public Terrain() {
|
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<Path> 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) {
|
public Vector2f getTerrainCell(Vector2f terrainLoc) {
|
||||||
|
|
||||||
float terrainCell_x = terrainLoc.x / this.cell_size_x;
|
Vector2f terrain_cell = new Vector2f(terrainLoc.x / this.cell_size.x, terrainLoc.y / this.cell_size.y);
|
||||||
float terrainCell_y = terrainLoc.y / this.cell_size_y;
|
|
||||||
|
|
||||||
// Clamp values when standing directly on max pole
|
// Clamp values when standing directly on max pole
|
||||||
|
|
||||||
if (terrainCell_x >= this.cell_count_x)
|
if (terrain_cell.x >= this.cell_count.x)
|
||||||
terrainCell_x = terrainCell_x - 1;
|
terrain_cell.x = terrain_cell.x - 1;
|
||||||
|
|
||||||
if (terrainCell_y >= this.cell_count_y)
|
if (terrain_cell.x >= this.cell_count.y)
|
||||||
terrainCell_y = terrainCell_x - 1;
|
terrain_cell.y = terrain_cell.y - 1;
|
||||||
|
|
||||||
return new Vector2f(terrainCell_x, terrainCell_y);
|
return terrain_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) {
|
public float getInterpolatedTerrainHeight(Vector2f terrainLoc) {
|
||||||
@@ -351,10 +126,10 @@ public class Terrain {
|
|||||||
float bottomLeftHeight;
|
float bottomLeftHeight;
|
||||||
float bottomRightHeight;
|
float bottomRightHeight;
|
||||||
|
|
||||||
topLeftHeight = pixelColorValues[gridX][gridY];
|
topLeftHeight = terrain_pixel_data[gridX][gridY];
|
||||||
topRightHeight = pixelColorValues[gridX + 1][gridY];
|
topRightHeight = terrain_pixel_data[gridX + 1][gridY];
|
||||||
bottomLeftHeight = pixelColorValues[gridX][gridY + 1];
|
bottomLeftHeight = terrain_pixel_data[gridX][gridY + 1];
|
||||||
bottomRightHeight = pixelColorValues[gridX + 1][gridY + 1];
|
bottomRightHeight = terrain_pixel_data[gridX + 1][gridY + 1];
|
||||||
|
|
||||||
// Interpolate between the 4 vertices
|
// Interpolate between the 4 vertices
|
||||||
|
|
||||||
@@ -367,5 +142,4 @@ public class Terrain {
|
|||||||
|
|
||||||
return interpolatedHeight;
|
return interpolatedHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ package engine.objects;
|
|||||||
import engine.Enum;
|
import engine.Enum;
|
||||||
import engine.Enum.*;
|
import engine.Enum.*;
|
||||||
import engine.InterestManagement.RealmMap;
|
import engine.InterestManagement.RealmMap;
|
||||||
import engine.InterestManagement.Terrain;
|
|
||||||
import engine.InterestManagement.WorldGrid;
|
import engine.InterestManagement.WorldGrid;
|
||||||
import engine.db.archive.CityRecord;
|
import engine.db.archive.CityRecord;
|
||||||
import engine.db.archive.DataWarehouse;
|
import engine.db.archive.DataWarehouse;
|
||||||
@@ -587,10 +586,6 @@ public class City extends AbstractWorldObject {
|
|||||||
0.0f);
|
0.0f);
|
||||||
this.setBounds(cityBounds);
|
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) {
|
} catch (Exception e) {
|
||||||
Logger.error(e);
|
Logger.error(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public class Zone extends AbstractGameObject {
|
|||||||
public float terrain_max_y;
|
public float terrain_max_y;
|
||||||
public int terrain_image;
|
public int terrain_image;
|
||||||
|
|
||||||
|
public Terrain terrain = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResultSet Constructor
|
* ResultSet Constructor
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import engine.Enum.DispatchChannel;
|
|||||||
import engine.Enum.MinionType;
|
import engine.Enum.MinionType;
|
||||||
import engine.Enum.SupportMsgType;
|
import engine.Enum.SupportMsgType;
|
||||||
import engine.InterestManagement.RealmMap;
|
import engine.InterestManagement.RealmMap;
|
||||||
import engine.InterestManagement.Terrain;
|
|
||||||
import engine.InterestManagement.WorldGrid;
|
import engine.InterestManagement.WorldGrid;
|
||||||
import engine.db.archive.DataWarehouse;
|
import engine.db.archive.DataWarehouse;
|
||||||
import engine.db.handlers.dbRuneBaseHandler;
|
import engine.db.handlers.dbRuneBaseHandler;
|
||||||
@@ -39,6 +38,7 @@ import engine.net.client.msg.UpdateStateMsg;
|
|||||||
import engine.net.client.msg.chat.ChatSystemMsg;
|
import engine.net.client.msg.chat.ChatSystemMsg;
|
||||||
import engine.objects.*;
|
import engine.objects.*;
|
||||||
import engine.server.MBServerStatics;
|
import engine.server.MBServerStatics;
|
||||||
|
import engine.util.MapLoader;
|
||||||
import engine.util.ThreadUtils;
|
import engine.util.ThreadUtils;
|
||||||
import engine.workthreads.DisconnectTrashTask;
|
import engine.workthreads.DisconnectTrashTask;
|
||||||
import engine.workthreads.HourlyJobThread;
|
import engine.workthreads.HourlyJobThread;
|
||||||
@@ -385,7 +385,7 @@ public class WorldServer {
|
|||||||
Blueprint.loadAllBlueprints();
|
Blueprint.loadAllBlueprints();
|
||||||
|
|
||||||
Logger.info("Initializing Heightmap data");
|
Logger.info("Initializing Heightmap data");
|
||||||
Terrain.loadAlHeightMaps();
|
MapLoader.loadAlHeightMaps();
|
||||||
|
|
||||||
Logger.info("Loading Race data");
|
Logger.info("Loading Race data");
|
||||||
Enum.RaceType.initRaceTypeTables();
|
Enum.RaceType.initRaceTypeTables();
|
||||||
@@ -466,14 +466,6 @@ public class WorldServer {
|
|||||||
Logger.info("Starting Mob AI Thread");
|
Logger.info("Starting Mob AI Thread");
|
||||||
MobAIThread.startAIThread();
|
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.");
|
Logger.info("World data loaded.");
|
||||||
|
|
||||||
//set default accesslevel for server *** Refactor who two separate variables?
|
//set default accesslevel for server *** Refactor who two separate variables?
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package engine.util;
|
package engine.util;
|
||||||
|
|
||||||
import engine.InterestManagement.RealmMap;
|
import engine.InterestManagement.RealmMap;
|
||||||
|
import engine.InterestManagement.Terrain;
|
||||||
import engine.gameManager.ConfigManager;
|
import engine.gameManager.ConfigManager;
|
||||||
import engine.server.MBServerStatics;
|
import engine.server.MBServerStatics;
|
||||||
import org.pmw.tinylog.Logger;
|
import org.pmw.tinylog.Logger;
|
||||||
@@ -14,6 +15,10 @@ import java.awt.*;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
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 {
|
public enum MapLoader {
|
||||||
|
|
||||||
@@ -87,4 +92,47 @@ public enum MapLoader {
|
|||||||
g.dispose();
|
g.dispose();
|
||||||
return dimg;
|
return dimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadAlHeightMaps() {
|
||||||
|
|
||||||
|
// Load pixel data for heightmaps
|
||||||
|
|
||||||
|
try (Stream<Path> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user