Noise definitions in data files
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
a44255060d
commit
3a9eb0591d
7
assets/Data/game/voxel/test1.json
Normal file
7
assets/Data/game/voxel/test1.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"name" : "test1",
|
||||
"sampler" : {
|
||||
"name" : "Invoke",
|
||||
"target" : "test2"
|
||||
}
|
||||
}
|
||||
36
assets/Data/game/voxel/test2.json
Normal file
36
assets/Data/game/voxel/test2.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name" : "test2",
|
||||
"sampler" :{
|
||||
"name" : "DomainWarp",
|
||||
"x" : {
|
||||
"name" : "Mul",
|
||||
"first" : {
|
||||
"name" : "Const",
|
||||
"value" : 0.02
|
||||
},
|
||||
"second" : {
|
||||
"name" : "OpenSimplex"
|
||||
}
|
||||
},
|
||||
"z" : {
|
||||
"name" : "Mul",
|
||||
"first" : {
|
||||
"name" : "Const",
|
||||
"value" : 0.02
|
||||
},
|
||||
"second" : {
|
||||
"name" : "OpenSimplex"
|
||||
}
|
||||
},
|
||||
"source" : {
|
||||
"name" : "Add",
|
||||
"first" : {
|
||||
"name" : "Const",
|
||||
"value" : 1.0
|
||||
},
|
||||
"second" : {
|
||||
"name" : "OpenSimplex"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1065,6 +1065,16 @@ Fix flickering chunks on unload
|
||||
Fix draw cell distance cache busting on far distances
|
||||
Fix skybox not updating position with player entity
|
||||
Add Scene shorthand for registering runnables as behavior trees
|
||||
Re-integrate frame time tracking
|
||||
Solve y last in chunkgen to optimize height calc
|
||||
|
||||
(11/18/2024)
|
||||
Defining noise functions in config files
|
||||
Invoking noise functions from noise functions
|
||||
Voxel and Heightmap generators based on noise functions in files
|
||||
Set all client terrain rigid bodies are kinematic
|
||||
Add caves
|
||||
Tweaking test2 noise definition
|
||||
|
||||
|
||||
|
||||
|
||||
4
pom.xml
4
pom.xml
@ -7,8 +7,8 @@
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<lwjgl.version>3.3.3</lwjgl.version>
|
||||
<joml.version>1.9.19</joml.version>
|
||||
<recast.version>1.5.7</recast.version>
|
||||
|
||||
@ -133,8 +133,8 @@ public class ClientTerrainManager {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(message.getchunkData());
|
||||
FloatBuffer floatBuffer = buffer.asFloatBuffer();
|
||||
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||
weights[x][y][z] = floatBuffer.get();
|
||||
}
|
||||
}
|
||||
@ -144,8 +144,8 @@ public class ClientTerrainManager {
|
||||
int firstType = -1;
|
||||
boolean homogenous = true;
|
||||
for(int x = 0; x < ChunkData.CHUNK_DATA_SIZE; x++){
|
||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||
for(int z = 0; z < ChunkData.CHUNK_DATA_SIZE; z++){
|
||||
for(int y = 0; y < ChunkData.CHUNK_DATA_SIZE; y++){
|
||||
values[x][y][z] = intView.get();
|
||||
if(firstType == -1){
|
||||
firstType = values[x][y][z];
|
||||
|
||||
@ -481,14 +481,12 @@ public class PhysicsEntityUtils {
|
||||
* @param data The terrain description
|
||||
* @return The rigid body created (note, attachment has already been performed)
|
||||
*/
|
||||
public static DBody clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
|
||||
public static void clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
|
||||
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data, Collidable.TYPE_STATIC_BIT);
|
||||
|
||||
|
||||
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN, false));
|
||||
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
||||
|
||||
return terrainBody;
|
||||
if(terrainBody != null){
|
||||
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN, false));
|
||||
PhysicsEntityUtils.setDBody(terrain,terrainBody);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -514,6 +512,9 @@ public class PhysicsEntityUtils {
|
||||
*/
|
||||
public static void serverRepositionEntities(CollisionEngine collisionEngine){
|
||||
List<Entity> toReposition = new LinkedList<Entity>();
|
||||
if(collisionEngine.getCollidables() == null){
|
||||
throw new Error("Collision engine collidables are null!");
|
||||
}
|
||||
for(Collidable collidable : collisionEngine.getCollidables()){
|
||||
Entity entity = collidable.getParent();
|
||||
DBody body = PhysicsEntityUtils.getDBody(entity);
|
||||
|
||||
@ -428,6 +428,12 @@ public class Main {
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// F R A M E T I M E T R A C K I NG
|
||||
///
|
||||
ImGuiWindowMacros.addGlobalFramerateDatapoint("totalframerate", Globals.timekeeper.getMostRecentRawFrametime());
|
||||
|
||||
|
||||
///
|
||||
/// E N D M A I N L O O P
|
||||
///
|
||||
|
||||
@ -20,6 +20,7 @@ import electrosphere.game.data.tutorial.HintDefinition;
|
||||
import electrosphere.game.data.units.UnitDefinitionFile;
|
||||
import electrosphere.game.data.units.UnitLoader;
|
||||
import electrosphere.game.data.voxel.VoxelData;
|
||||
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||
import electrosphere.game.server.race.model.RaceMap;
|
||||
import electrosphere.game.server.symbolism.model.SymbolMap;
|
||||
import electrosphere.util.FileUtils;
|
||||
@ -66,6 +67,11 @@ public class Config {
|
||||
* The biome map
|
||||
*/
|
||||
BiomeTypeMap biomeMap;
|
||||
|
||||
/**
|
||||
* The list of sampler definitions
|
||||
*/
|
||||
List<SamplerFile> samplerDefinitions;
|
||||
|
||||
/**
|
||||
* Loads the default data
|
||||
@ -87,6 +93,7 @@ public class Config {
|
||||
config.unitLoader = UnitLoader.create(FileUtils.loadObjectFromAssetPath("Data/game/units/units.json", UnitDefinitionFile.class));
|
||||
config.recipeMap = RecipeDataMap.loadRecipeFiles("Data/game/recipes.json");
|
||||
config.biomeMap = BiomeTypeMap.loadBiomeFile("Data/game/biomes.json");
|
||||
config.samplerDefinitions = SamplerFile.readSamplerDefinitionFiles("Data/game/voxel");
|
||||
|
||||
//create furniture items
|
||||
ItemDataMap.loadSpawnItems(config.itemMap, config.objectTypeLoader);
|
||||
@ -282,5 +289,13 @@ public class Config {
|
||||
public BiomeTypeMap getBiomeMap(){
|
||||
return biomeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of all sampler files
|
||||
* @return The list of all sampler files
|
||||
*/
|
||||
public List<SamplerFile> getSamplerFiles(){
|
||||
return this.samplerDefinitions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
package electrosphere.game.data.voxel.sampler;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperoatorInvoke;
|
||||
import electrosphere.util.FileUtils;
|
||||
|
||||
/**
|
||||
* A sampler definition file
|
||||
*/
|
||||
public class SamplerFile {
|
||||
|
||||
/**
|
||||
* The name of this sampler type
|
||||
*/
|
||||
String name;
|
||||
|
||||
/**
|
||||
* The sample to pull from
|
||||
*/
|
||||
NoiseSampler sampler;
|
||||
|
||||
/**
|
||||
* Gets the name of the file
|
||||
* @return The name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sampler for this file
|
||||
* @return The sampler
|
||||
*/
|
||||
public NoiseSampler getSampler() {
|
||||
return sampler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sampler definition files
|
||||
* @return The list of sampler definition files
|
||||
*/
|
||||
public static List<SamplerFile> readSamplerDefinitionFiles(String initialPath){
|
||||
File initialDirectory = FileUtils.getAssetFile(initialPath);
|
||||
List<SamplerFile> rVal = new LinkedList<SamplerFile>();
|
||||
|
||||
//read the files in
|
||||
SamplerFile.recursivelyReadSamplerDefinitionFiles(initialDirectory, rVal);
|
||||
|
||||
//link invoke targets
|
||||
for(SamplerFile file : rVal){
|
||||
SamplerFile.linkInvokeTargets(rVal, file.getSampler());
|
||||
}
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively reads from the root all sampler files
|
||||
* @param rootDir The root dir
|
||||
* @param appendTarget The list to add sampler files to
|
||||
*/
|
||||
private static void recursivelyReadSamplerDefinitionFiles(File rootDir, List<SamplerFile> appendTarget){
|
||||
if(rootDir == null || !rootDir.isDirectory()){
|
||||
throw new Error("Invalid path provided! " + rootDir.getAbsolutePath());
|
||||
}
|
||||
if(rootDir == null || !rootDir.exists() || rootDir.listFiles() == null){
|
||||
return;
|
||||
}
|
||||
for(File child : rootDir.listFiles()){
|
||||
if(child.isDirectory()){
|
||||
SamplerFile.recursivelyReadSamplerDefinitionFiles(child, appendTarget);
|
||||
} else {
|
||||
SamplerFile file = FileUtils.loadObjectFromFile(child, SamplerFile.class);
|
||||
appendTarget.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Links all invoke targets to their respective samplers
|
||||
* @param files The list of all sampler files
|
||||
* @param current The current sampler function to evaluate
|
||||
*/
|
||||
private static void linkInvokeTargets(List<SamplerFile> files, NoiseSampler current){
|
||||
if(current instanceof NoiseOperoatorInvoke){
|
||||
NoiseOperoatorInvoke invoker = (NoiseOperoatorInvoke)current;
|
||||
String target = invoker.getTarget();
|
||||
if(target.equals(current.getName())){
|
||||
throw new Error("Invoke module pointing at itself!");
|
||||
}
|
||||
for(SamplerFile file : files){
|
||||
if(file.getName().equals(target)){
|
||||
invoker.setInvokeSampler(file.getSampler());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(invoker.getInvokeSampler() == null){
|
||||
throw new Error("Failed to link " + target);
|
||||
}
|
||||
} else if(current instanceof NoiseContainer){
|
||||
for(NoiseSampler child : ((NoiseContainer)current).getChildren()){
|
||||
SamplerFile.linkInvokeTargets(files, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -229,8 +229,8 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
||||
FloatBuffer floatView = buffer.asFloatBuffer();
|
||||
|
||||
for(int x = 0; x < xWidth; x++){
|
||||
for(int y = 0; y < yWidth; y++){
|
||||
for(int z = 0; z < zWidth; z++){
|
||||
for(int z = 0; z < zWidth; z++){
|
||||
for(int y = 0; y < yWidth; y++){
|
||||
floatView.put(chunk.getWeights()[x][y][z]);
|
||||
}
|
||||
}
|
||||
@ -240,8 +240,8 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
|
||||
intView.position(floatView.position());
|
||||
|
||||
for(int x = 0; x < xWidth; x++){
|
||||
for(int y = 0; y < yWidth; y++){
|
||||
for(int z = 0; z < zWidth; z++){
|
||||
for(int z = 0; z < zWidth; z++){
|
||||
for(int y = 0; y < yWidth; y++){
|
||||
intView.put(chunk.getValues()[x][y][z]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package electrosphere.script;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.graalvm.polyglot.Context;
|
||||
@ -376,7 +377,15 @@ public class ScriptContext {
|
||||
* @param function The function
|
||||
*/
|
||||
public void executeSynchronously(Runnable function){
|
||||
lock.lock();
|
||||
boolean success = false;
|
||||
try {
|
||||
success = lock.tryLock(1, TimeUnit.MICROSECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
LoggerInterface.loggerScripts.ERROR(e);
|
||||
}
|
||||
if(!success){
|
||||
throw new Error("Failed to acquire lock!");
|
||||
}
|
||||
function.run();
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
/**
|
||||
* The number of frames without players that must pass before a server data cell is unloaded
|
||||
*/
|
||||
static final int UNLOAD_FRAME_THRESHOLD = 100;
|
||||
static final int UNLOAD_FRAME_THRESHOLD = 500;
|
||||
|
||||
/**
|
||||
* Tracks whether this manager has been flagged to unload cells or not
|
||||
|
||||
@ -0,0 +1,241 @@
|
||||
package electrosphere.server.terrain.generation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import electrosphere.client.terrain.cache.ChunkData;
|
||||
|
||||
import org.graalvm.polyglot.Value;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.game.data.biome.BiomeData;
|
||||
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
||||
import electrosphere.game.server.world.ServerWorldData;
|
||||
import electrosphere.server.terrain.generation.heightmap.EmptySkyGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
||||
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.MountainGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
||||
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.MountainVoxelGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.server.terrain.models.TerrainModel;
|
||||
|
||||
/**
|
||||
* Dedicated script-based chunk generator
|
||||
*/
|
||||
public class JSChunkGenerator implements ChunkGenerator {
|
||||
|
||||
/**
|
||||
* The size of the realm for testing generation
|
||||
*/
|
||||
public static final int GENERATOR_REALM_SIZE = 512;
|
||||
|
||||
/**
|
||||
* The default biome index
|
||||
*/
|
||||
public static final int DEFAULT_BIOME_INDEX = 1;
|
||||
|
||||
/**
|
||||
* The width of the surface in number of voxels
|
||||
*/
|
||||
public static final int SURFACE_VOXEL_WIDTH = 2;
|
||||
|
||||
/**
|
||||
* Tag for the test generator
|
||||
*/
|
||||
public static final String SCRIPT_GEN_TEST_TAG = "test";
|
||||
|
||||
/**
|
||||
* Controls the default setting for whether to use javascript or not
|
||||
*/
|
||||
public static final boolean DEFAULT_USE_JAVASCRIPT = false;
|
||||
|
||||
/**
|
||||
* The terreain model for the generator
|
||||
*/
|
||||
TerrainModel terrainModel;
|
||||
|
||||
/**
|
||||
* The server world data
|
||||
*/
|
||||
ServerWorldData serverWorldData;
|
||||
|
||||
/**
|
||||
* The map of generator tag to the heightmap generator
|
||||
*/
|
||||
Map<String,HeightmapGenerator> tagHeightmapMap = new HashMap<String,HeightmapGenerator>();
|
||||
|
||||
/**
|
||||
* The map of generator tag to voxel generator
|
||||
*/
|
||||
Map<String,VoxelGenerator> tagVoxelMap = new HashMap<String,VoxelGenerator>();
|
||||
|
||||
/**
|
||||
* Tracks whether to use javascript generation or not
|
||||
*/
|
||||
boolean useJavascript = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public JSChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||
this.serverWorldData = serverWorldData;
|
||||
this.registerHeightmapGenerator(new EmptySkyGen());
|
||||
this.registerHeightmapGenerator(new HillsGen());
|
||||
this.registerHeightmapGenerator(new PlainsGen());
|
||||
this.registerHeightmapGenerator(new MountainGen());
|
||||
this.registerVoxelGenerator(new HillsVoxelGen());
|
||||
this.registerVoxelGenerator(new AnimeMountainsGen());
|
||||
this.registerVoxelGenerator(new MountainVoxelGen());
|
||||
this.useJavascript = useJavascript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a heightmap generator
|
||||
* @param generator The heightmap generator
|
||||
*/
|
||||
private void registerHeightmapGenerator(HeightmapGenerator generator){
|
||||
tagHeightmapMap.put(generator.getTag(),generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a voxel generator
|
||||
* @param generator The voxel generator
|
||||
*/
|
||||
private void registerVoxelGenerator(VoxelGenerator generator){
|
||||
tagVoxelMap.put(generator.getTag(),generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerTerrainChunk generateChunk(int worldX, int worldY, int worldZ, int stride) {
|
||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.generateChunk");
|
||||
ServerTerrainChunk rVal = new ServerTerrainChunk(worldX, worldY, worldZ);
|
||||
float[][][] weights = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];;
|
||||
int[][][] values = new int[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||
|
||||
try {
|
||||
//biome of the current chunk
|
||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||
|
||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||
heightmapGen = this.tagHeightmapMap.get("hills");
|
||||
if(heightmapGen == null){
|
||||
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
||||
}
|
||||
|
||||
//stride value
|
||||
int strideValue = (int)Math.pow(2,stride);
|
||||
|
||||
//presolve heightfield
|
||||
float[][] heightfield = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
heightfield[x][z] = heightmapGen.getHeight(
|
||||
this.terrainModel.getSeed(),
|
||||
this.serverWorldData.convertVoxelToRealSpace(finalChunkX, finalWorldX),
|
||||
this.serverWorldData.convertVoxelToRealSpace(finalChunkZ, finalWorldZ)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
float[][] gradientField = new float[ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE][ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE];
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
float deltaX = 0;
|
||||
float deltaZ = 0;
|
||||
if(x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
|
||||
deltaX = Math.abs(heightfield[x][z] - heightfield[x+1][z]);
|
||||
} else {
|
||||
deltaX = Math.abs(heightfield[x][z] - heightfield[x-1][z]);
|
||||
}
|
||||
if(z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE - 1){
|
||||
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z+1]);
|
||||
} else {
|
||||
deltaX = Math.abs(heightfield[x][z] - heightfield[x][z-1]);
|
||||
}
|
||||
gradientField[x][z] = deltaX * deltaX + deltaZ * deltaZ;
|
||||
}
|
||||
}
|
||||
|
||||
Globals.scriptEngine.getScriptContext().executeSynchronously(() -> {
|
||||
int firstType = -2;
|
||||
boolean homogenous = true;
|
||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||
Value getVoxelFunc = Globals.scriptEngine.getScriptContext().invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
getVoxelFunc.execute(
|
||||
voxel,
|
||||
finalWorldX, finalWorldY, finalWorldZ,
|
||||
finalChunkX, finalChunkY, finalChunkZ,
|
||||
stride,
|
||||
heightfield[x][z],
|
||||
surfaceBiome
|
||||
);
|
||||
weights[x][y][z] = voxel.weight;
|
||||
values[x][y][z] = voxel.type;
|
||||
if(firstType == -2){
|
||||
firstType = values[x][y][z];
|
||||
} else if(homogenous && firstType != values[x][y][z]){
|
||||
homogenous = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
if(homogenous){
|
||||
rVal.setHomogenousValue(firstType);
|
||||
} else {
|
||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||
}
|
||||
rVal.setWeights(weights);
|
||||
rVal.setValues(values);
|
||||
});
|
||||
} catch(Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getElevation(int worldX, int worldZ, int chunkX, int chunkZ){
|
||||
BiomeData surfaceBiome = this.terrainModel.getSurfaceBiome(worldX, worldZ);
|
||||
|
||||
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
|
||||
HeightmapGenerator heightmapGen = this.tagHeightmapMap.get(surfaceParams.getSurfaceGenTag());
|
||||
if(heightmapGen == null){
|
||||
throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag());
|
||||
}
|
||||
double rVal = heightmapGen.getHeight(
|
||||
this.terrainModel.getSeed(),
|
||||
this.serverWorldData.convertVoxelToRealSpace(chunkX, worldX),
|
||||
this.serverWorldData.convertVoxelToRealSpace(chunkZ, worldZ)
|
||||
);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(TerrainModel model) {
|
||||
this.terrainModel = model;
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,14 +5,14 @@ import java.util.Map;
|
||||
|
||||
import electrosphere.client.terrain.cache.ChunkData;
|
||||
|
||||
import org.graalvm.polyglot.Value;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.game.data.biome.BiomeData;
|
||||
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
||||
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||
import electrosphere.game.server.world.ServerWorldData;
|
||||
import electrosphere.server.terrain.generation.heightmap.EmptySkyGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
||||
import electrosphere.server.terrain.generation.heightmap.HeightmapNoiseGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.MountainGen;
|
||||
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||
@ -22,6 +22,7 @@ import electrosphere.server.terrain.generation.interfaces.GenerationContext;
|
||||
import electrosphere.server.terrain.generation.voxelphase.AnimeMountainsGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.HillsVoxelGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.MountainVoxelGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.NoiseVoxelGen;
|
||||
import electrosphere.server.terrain.generation.voxelphase.VoxelGenerator;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.server.terrain.models.TerrainModel;
|
||||
@ -86,6 +87,16 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
||||
*/
|
||||
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||
this.serverWorldData = serverWorldData;
|
||||
this.registerAllGenerators();
|
||||
this.useJavascript = useJavascript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all generators
|
||||
*/
|
||||
public void registerAllGenerators(){
|
||||
tagHeightmapMap.clear();
|
||||
tagVoxelMap.clear();
|
||||
this.registerHeightmapGenerator(new EmptySkyGen());
|
||||
this.registerHeightmapGenerator(new HillsGen());
|
||||
this.registerHeightmapGenerator(new PlainsGen());
|
||||
@ -93,7 +104,10 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
||||
this.registerVoxelGenerator(new HillsVoxelGen());
|
||||
this.registerVoxelGenerator(new AnimeMountainsGen());
|
||||
this.registerVoxelGenerator(new MountainVoxelGen());
|
||||
this.useJavascript = useJavascript;
|
||||
for(SamplerFile samplerFile : Globals.gameConfigCurrent.getSamplerFiles()){
|
||||
this.registerHeightmapGenerator(new HeightmapNoiseGen(samplerFile));
|
||||
this.registerVoxelGenerator(new NoiseVoxelGen(samplerFile));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,95 +182,60 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("hills");
|
||||
VoxelGenerator voxelGenerator = this.tagVoxelMap.get("test1");
|
||||
|
||||
int firstType = -2;
|
||||
boolean homogenous = true;
|
||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||
GenerationContext generationContext = new GenerationContext();
|
||||
generationContext.setServerWorldData(serverWorldData);
|
||||
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkX,finalWorldX);
|
||||
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkZ,finalWorldZ);
|
||||
float surfaceHeight = heightfield[x][z];
|
||||
float gradient = gradientField[x][z];
|
||||
|
||||
if(this.useJavascript){
|
||||
Globals.scriptEngine.getScriptContext().executeSynchronously(() -> {
|
||||
int firstType = -2;
|
||||
boolean homogenous = true;
|
||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||
Value getVoxelFunc = Globals.scriptEngine.getScriptContext().invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
getVoxelFunc.execute(
|
||||
voxel,
|
||||
finalWorldX, finalWorldY, finalWorldZ,
|
||||
finalChunkX, finalChunkY, finalChunkZ,
|
||||
stride,
|
||||
heightfield[x][z],
|
||||
surfaceBiome
|
||||
);
|
||||
weights[x][y][z] = voxel.weight;
|
||||
values[x][y][z] = voxel.type;
|
||||
if(firstType == -2){
|
||||
firstType = values[x][y][z];
|
||||
} else if(homogenous && firstType != values[x][y][z]){
|
||||
homogenous = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Globals.profiler.endCpuSample();
|
||||
}
|
||||
if(homogenous){
|
||||
rVal.setHomogenousValue(firstType);
|
||||
} else {
|
||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||
}
|
||||
rVal.setWeights(weights);
|
||||
rVal.setValues(values);
|
||||
});
|
||||
} else {
|
||||
int firstType = -2;
|
||||
boolean homogenous = true;
|
||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||
GenerationContext generationContext = new GenerationContext();
|
||||
generationContext.setServerWorldData(serverWorldData);
|
||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; x++){
|
||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
|
||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; z++){
|
||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
voxelGenerator.getVoxel(
|
||||
voxel,
|
||||
finalWorldX, finalWorldY, finalWorldZ,
|
||||
finalChunkX, finalChunkY, finalChunkZ,
|
||||
stride,
|
||||
heightfield[x][z], gradientField[x][z],
|
||||
surfaceBiome,
|
||||
generationContext
|
||||
);
|
||||
if(voxel != null){
|
||||
weights[x][y][z] = voxel.weight;
|
||||
values[x][y][z] = voxel.type;
|
||||
}
|
||||
if(firstType == -2){
|
||||
firstType = values[x][y][z];
|
||||
} else if(homogenous && firstType != values[x][y][z]){
|
||||
homogenous = false;
|
||||
}
|
||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(finalChunkY,finalWorldY);
|
||||
|
||||
voxelGenerator.getVoxel(
|
||||
voxel,
|
||||
finalWorldX, finalWorldY, finalWorldZ,
|
||||
finalChunkX, finalChunkY, finalChunkZ,
|
||||
realX, realY, realZ,
|
||||
stride,
|
||||
surfaceHeight, gradient,
|
||||
surfaceBiome,
|
||||
generationContext
|
||||
);
|
||||
if(voxel != null){
|
||||
weights[x][y][z] = voxel.weight;
|
||||
values[x][y][z] = voxel.type;
|
||||
}
|
||||
if(firstType == -2){
|
||||
firstType = values[x][y][z];
|
||||
} else if(homogenous && firstType != values[x][y][z]){
|
||||
homogenous = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(homogenous){
|
||||
rVal.setHomogenousValue(firstType);
|
||||
} else {
|
||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||
}
|
||||
rVal.setWeights(weights);
|
||||
rVal.setValues(values);
|
||||
}
|
||||
if(homogenous){
|
||||
rVal.setHomogenousValue(firstType);
|
||||
} else {
|
||||
rVal.setHomogenousValue(ChunkData.NOT_HOMOGENOUS);
|
||||
}
|
||||
rVal.setWeights(weights);
|
||||
rVal.setValues(values);
|
||||
} catch(Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
package electrosphere.server.terrain.generation.heightmap;
|
||||
|
||||
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* Generates a heightmap using a noise definition
|
||||
*/
|
||||
public class HeightmapNoiseGen implements HeightmapGenerator {
|
||||
|
||||
/**
|
||||
* The tag for the noise function that generates
|
||||
*/
|
||||
String tag;
|
||||
|
||||
/**
|
||||
* The sampler to pull from when allocating voxels
|
||||
*/
|
||||
NoiseSampler sampler;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param sampler The sampler to pull from
|
||||
*/
|
||||
public HeightmapNoiseGen(SamplerFile samplerDefinitionFile){
|
||||
this.sampler = samplerDefinitionFile.getSampler();
|
||||
this.tag = samplerDefinitionFile.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getHeight(long SEED, double x, double y) {
|
||||
return (float)sampler.getValue(0, x, y, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package electrosphere.server.terrain.generation.noise;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A module that contains other modules
|
||||
*/
|
||||
public interface NoiseContainer extends NoiseSampler {
|
||||
|
||||
/**
|
||||
* Gets all child modules of this one
|
||||
* @return All child modules
|
||||
*/
|
||||
public Collection<NoiseSampler> getChildren();
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package electrosphere.server.terrain.generation.noise;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorAdd;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorClamp;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorConst;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorDomainWarp;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorMul;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorOpenSimplex;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperatorVoronoi;
|
||||
import electrosphere.server.terrain.generation.noise.operators.NoiseOperoatorInvoke;
|
||||
|
||||
/**
|
||||
* Deserializes noise modules
|
||||
*/
|
||||
public class NoiseModuleSerializer implements JsonDeserializer<NoiseSampler> {
|
||||
|
||||
@Override
|
||||
public NoiseSampler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
switch(json.getAsJsonObject().get("name").getAsString()){
|
||||
|
||||
//meta
|
||||
case NoiseOperoatorInvoke.NAME: {
|
||||
return context.deserialize(json, NoiseOperoatorInvoke.class);
|
||||
}
|
||||
|
||||
//warps
|
||||
case NoiseOperatorDomainWarp.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorDomainWarp.class);
|
||||
}
|
||||
|
||||
//actual noise sampling
|
||||
case NoiseOperatorOpenSimplex.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorOpenSimplex.class);
|
||||
}
|
||||
case NoiseOperatorVoronoi.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorVoronoi.class);
|
||||
}
|
||||
|
||||
//basic ops
|
||||
case NoiseOperatorConst.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorConst.class);
|
||||
}
|
||||
case NoiseOperatorAdd.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorAdd.class);
|
||||
}
|
||||
case NoiseOperatorMul.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorMul.class);
|
||||
}
|
||||
case NoiseOperatorClamp.NAME: {
|
||||
return context.deserialize(json, NoiseOperatorClamp.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package electrosphere.server.terrain.generation.noise;
|
||||
|
||||
/**
|
||||
* A noce function that can be sampled in octaves
|
||||
*/
|
||||
public interface NoiseOctaveSampler extends NoiseSampler {
|
||||
|
||||
/**
|
||||
* Sets the lacunarity of the sampler
|
||||
* @param lacunarity The lacunarity
|
||||
*/
|
||||
public void setLacunarity(double lacunarity);
|
||||
|
||||
/**
|
||||
* Gets the lacunarity of the sampler
|
||||
* @return The lacunarity
|
||||
*/
|
||||
public double getLacunarity();
|
||||
|
||||
/**
|
||||
* Sets the number of octaves to sample
|
||||
* @param octaveCount The number of octaves to sample
|
||||
*/
|
||||
public void setOctaveCount(int octaveCount);
|
||||
|
||||
/**
|
||||
* Gets the number of octaves to sample
|
||||
* @return The number of octaves to sample
|
||||
*/
|
||||
public int getOctaveCount();
|
||||
|
||||
/**
|
||||
* Sets the frequency to sample at
|
||||
* @param frequency The frequency
|
||||
*/
|
||||
public void setFrequency(double frequency);
|
||||
|
||||
/**
|
||||
* Gets the frequency of the function
|
||||
* @return The frequency
|
||||
*/
|
||||
public double getFrequency();
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package electrosphere.server.terrain.generation.noise;
|
||||
|
||||
/**
|
||||
* A noise module that can sample values
|
||||
*/
|
||||
public interface NoiseSampler {
|
||||
|
||||
/**
|
||||
* Gets the name of this noise module
|
||||
* @return The name of the module
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Samples the noise at a given position with a given seed
|
||||
* @param SEED The seed
|
||||
* @param x The x coordinate
|
||||
* @param y The y coordinate
|
||||
* @param z The z coordinate
|
||||
* @return The value of the noise at that position for the given seed
|
||||
*/
|
||||
public double getValue(double SEED, double x, double y, double z);
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
public class NoiseOperatorAdd implements NoiseContainer {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Add";
|
||||
|
||||
/**
|
||||
* The first value to pull from
|
||||
*/
|
||||
protected NoiseSampler first;
|
||||
|
||||
/**
|
||||
* The second value to pull from
|
||||
*/
|
||||
protected NoiseSampler second;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
return first.getValue(SEED, x, y, z) + second.getValue(SEED, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoiseSampler> getChildren(){
|
||||
return Arrays.asList(new NoiseSampler[]{
|
||||
first,
|
||||
second,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
import io.github.studiorailgun.MathUtils;
|
||||
|
||||
/**
|
||||
* Clamps a noise value
|
||||
*/
|
||||
public class NoiseOperatorClamp implements NoiseContainer {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Clamp";
|
||||
|
||||
/**
|
||||
* The minimum value to clamp to
|
||||
*/
|
||||
protected NoiseSampler min;
|
||||
|
||||
/**
|
||||
* The maximum value to clamp to
|
||||
*/
|
||||
protected NoiseSampler max;
|
||||
|
||||
/**
|
||||
* The source to clamp
|
||||
*/
|
||||
protected NoiseSampler source;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
return MathUtils.clamp(source.getValue(SEED, x, y, z), min.getValue(SEED, x, y, z), max.getValue(SEED, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoiseSampler> getChildren(){
|
||||
return Arrays.asList(new NoiseSampler[]{
|
||||
min,
|
||||
max,
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* Gets a constant value
|
||||
*/
|
||||
public class NoiseOperatorConst implements NoiseSampler {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Const";
|
||||
|
||||
/**
|
||||
* The value
|
||||
*/
|
||||
double value;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* The warp operator
|
||||
*/
|
||||
public class NoiseOperatorDomainWarp implements NoiseContainer {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "DomainWarp";
|
||||
|
||||
/**
|
||||
* The sampler to pull the x value from
|
||||
*/
|
||||
protected NoiseSampler x;
|
||||
|
||||
/**
|
||||
* The sampler to pull the y value from
|
||||
*/
|
||||
protected NoiseSampler y;
|
||||
|
||||
/**
|
||||
* The sampler to pull the z value from
|
||||
*/
|
||||
protected NoiseSampler z;
|
||||
|
||||
/**
|
||||
* The amplitude of the warp to apply
|
||||
*/
|
||||
protected double amplitude = 1.0f;
|
||||
|
||||
/**
|
||||
* The sampler to pull from for the final emitted value
|
||||
*/
|
||||
protected NoiseSampler source;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
double sampleX = x;
|
||||
if(this.x != null){
|
||||
sampleX = sampleX + this.x.getValue(SEED, x, y, z) * amplitude;
|
||||
}
|
||||
double sampleY = y;
|
||||
if(this.y != null){
|
||||
sampleY = sampleY + this.y.getValue(SEED, x, y, z) * amplitude;
|
||||
}
|
||||
double sampleZ = z;
|
||||
if(this.z != null){
|
||||
sampleZ = sampleZ + this.z.getValue(SEED, x, y, z) * amplitude;
|
||||
}
|
||||
return this.source.getValue(SEED, sampleX, sampleY, sampleZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoiseSampler> getChildren(){
|
||||
return Arrays.asList(new NoiseSampler[]{
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* Multiplies one noise source by another
|
||||
*/
|
||||
public class NoiseOperatorMul implements NoiseContainer {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Mul";
|
||||
|
||||
/**
|
||||
* First sample
|
||||
*/
|
||||
protected NoiseSampler first;
|
||||
|
||||
/**
|
||||
* Second sample
|
||||
*/
|
||||
protected NoiseSampler second;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
return first.getValue(SEED, x, y, z) * second.getValue(SEED, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoiseSampler> getChildren(){
|
||||
return Arrays.asList(new NoiseSampler[]{
|
||||
first,
|
||||
second,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseOctaveSampler;
|
||||
import electrosphere.util.noise.OpenSimplex2S;
|
||||
|
||||
/**
|
||||
* Samples open simplex noise
|
||||
*/
|
||||
public class NoiseOperatorOpenSimplex implements NoiseOctaveSampler {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "OpenSimplex";
|
||||
|
||||
/**
|
||||
* The frequency to sample at
|
||||
*/
|
||||
double frequency = 0.02;
|
||||
|
||||
/**
|
||||
* The lacunarity (the amount to change the frequency each octave)
|
||||
*/
|
||||
double lacunarity = 0.02;
|
||||
|
||||
/**
|
||||
* The number of octaves to sample
|
||||
*/
|
||||
int octaveCount = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
double rVal = 0;
|
||||
double sampleFreq = frequency;
|
||||
for(int i = 0; i < octaveCount; i++){
|
||||
rVal = rVal + OpenSimplex2S.noise3_ImproveXZ((long)SEED, x * sampleFreq, y * sampleFreq, z * sampleFreq);
|
||||
sampleFreq = sampleFreq + lacunarity;
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLacunarity(double lacunarity) {
|
||||
this.lacunarity = lacunarity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLacunarity() {
|
||||
return this.lacunarity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOctaveCount(int octaveCount) {
|
||||
this.octaveCount = octaveCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOctaveCount() {
|
||||
return this.octaveCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequency() {
|
||||
return this.frequency;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseOctaveSampler;
|
||||
import io.github.studiorailgun.NoiseUtils;
|
||||
|
||||
/**
|
||||
* Samples voronoi noise
|
||||
*/
|
||||
public class NoiseOperatorVoronoi implements NoiseOctaveSampler {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Voronoi";
|
||||
|
||||
/**
|
||||
* The frequency to sample at
|
||||
*/
|
||||
double frequency = 0.02;
|
||||
|
||||
/**
|
||||
* The lacunarity (the amount to change the frequency each octave)
|
||||
*/
|
||||
double lacunarity = 0.02;
|
||||
|
||||
/**
|
||||
* The number of octaves to sample
|
||||
*/
|
||||
int octaveCount = 1;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
double rVal = 0;
|
||||
double sampleFreq = frequency;
|
||||
for(int i = 0; i < octaveCount; i++){
|
||||
rVal = rVal + NoiseUtils.voronoi(x * sampleFreq, y * sampleFreq, z * sampleFreq);
|
||||
sampleFreq = sampleFreq + lacunarity;
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLacunarity(double lacunarity) {
|
||||
this.lacunarity = lacunarity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLacunarity() {
|
||||
return this.lacunarity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOctaveCount(int octaveCount) {
|
||||
this.octaveCount = octaveCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOctaveCount() {
|
||||
return this.octaveCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFrequency() {
|
||||
return this.frequency;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package electrosphere.server.terrain.generation.noise.operators;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import electrosphere.server.terrain.generation.noise.NoiseContainer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
|
||||
/**
|
||||
* Invokes another sample definition file
|
||||
*/
|
||||
public class NoiseOperoatorInvoke implements NoiseContainer {
|
||||
|
||||
/**
|
||||
* The name of this module
|
||||
*/
|
||||
public static final String NAME = "Invoke";
|
||||
|
||||
/**
|
||||
* The sampler to invoke
|
||||
*/
|
||||
NoiseSampler invokeSampler;
|
||||
|
||||
/**
|
||||
* The name of the sampler definition file to invoke
|
||||
*/
|
||||
String target;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue(double SEED, double x, double y, double z) {
|
||||
if(invokeSampler != null){
|
||||
return invokeSampler.getValue(SEED, x, y, z);
|
||||
} else {
|
||||
throw new Error("Invoke sampler undefined for " + target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sampler to invoke
|
||||
* @param invokeSampler The sampler
|
||||
*/
|
||||
public void setInvokeSampler(NoiseSampler invokeSampler){
|
||||
this.invokeSampler = invokeSampler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the invoke sampler
|
||||
* @return The sampler
|
||||
*/
|
||||
public NoiseSampler getInvokeSampler(){
|
||||
return invokeSampler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target this operator wants to invoke
|
||||
* @return The target
|
||||
*/
|
||||
public String getTarget(){
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NoiseSampler> getChildren(){
|
||||
return Arrays.asList(new NoiseSampler[]{
|
||||
invokeSampler
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -67,16 +67,13 @@ public class AnimeMountainsGen implements VoxelGenerator {
|
||||
GeneratedVoxel voxel,
|
||||
int worldX, int worldY, int worldZ,
|
||||
int chunkX, int chunkY, int chunkZ,
|
||||
double realX, double realY, double realZ,
|
||||
int stride, float surfaceHeight, float surfaceGradient,
|
||||
BiomeData surfaceBiome,
|
||||
GenerationContext generationContext
|
||||
) {
|
||||
Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel");
|
||||
|
||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
||||
|
||||
double strideMultiplier = Math.pow(2,stride);
|
||||
double heightDiff = realY - surfaceHeight;
|
||||
double surfacePercent = AnimeMountainsGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||
|
||||
@ -26,6 +26,7 @@ public class HillsVoxelGen implements VoxelGenerator {
|
||||
GeneratedVoxel voxel,
|
||||
int worldX, int worldY, int worldZ,
|
||||
int chunkX, int chunkY, int chunkZ,
|
||||
double realX, double realY, double realZ,
|
||||
int stride,
|
||||
float surfaceHeight, float surfaceGradient,
|
||||
BiomeData surfaceBiome,
|
||||
@ -33,10 +34,6 @@ public class HillsVoxelGen implements VoxelGenerator {
|
||||
){
|
||||
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
||||
|
||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
||||
|
||||
double strideMultiplier = Math.pow(2,stride);
|
||||
double heightDiff = realY - surfaceHeight;
|
||||
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||
|
||||
@ -33,6 +33,7 @@ public class MountainVoxelGen implements VoxelGenerator {
|
||||
GeneratedVoxel voxel,
|
||||
int worldX, int worldY, int worldZ,
|
||||
int chunkX, int chunkY, int chunkZ,
|
||||
double realX, double realY, double realZ,
|
||||
int stride,
|
||||
float surfaceHeight, float surfaceGradient,
|
||||
BiomeData surfaceBiome,
|
||||
@ -40,10 +41,6 @@ public class MountainVoxelGen implements VoxelGenerator {
|
||||
){
|
||||
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");
|
||||
|
||||
double realX = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkX,worldX);
|
||||
double realY = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkY,worldY);
|
||||
double realZ = generationContext.getServerWorldData().convertVoxelToRealSpace(chunkZ,worldZ);
|
||||
|
||||
double strideMultiplier = Math.pow(2,stride);
|
||||
double heightDiff = realY - surfaceHeight;
|
||||
double surfacePercent = HillsVoxelGen.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
package electrosphere.server.terrain.generation.voxelphase;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.game.data.biome.BiomeData;
|
||||
import electrosphere.game.data.voxel.sampler.SamplerFile;
|
||||
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
||||
import electrosphere.server.terrain.generation.interfaces.GenerationContext;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
import io.github.studiorailgun.MathUtils;
|
||||
|
||||
/**
|
||||
* Generates voxels based on a noise config
|
||||
*/
|
||||
public class NoiseVoxelGen implements VoxelGenerator {
|
||||
|
||||
/**
|
||||
* The width of the surface in number of voxels
|
||||
*/
|
||||
public static final int SURFACE_VOXEL_WIDTH = 2;
|
||||
|
||||
/**
|
||||
* The tag for the noise function that generates
|
||||
*/
|
||||
String tag;
|
||||
|
||||
/**
|
||||
* The sampler to pull from when allocating voxels
|
||||
*/
|
||||
NoiseSampler sampler;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param samplerDefinitionFile The file to model this generator off of
|
||||
*/
|
||||
public NoiseVoxelGen(SamplerFile samplerDefinitionFile){
|
||||
this.sampler = samplerDefinitionFile.getSampler();
|
||||
this.tag = samplerDefinitionFile.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getVoxel(
|
||||
GeneratedVoxel voxel,
|
||||
int worldX, int worldY, int worldZ,
|
||||
int chunkX, int chunkY, int chunkZ,
|
||||
double realX, double realY, double realZ,
|
||||
int stride, float surfaceHeight, float surfaceGradient,
|
||||
BiomeData surfaceBiome, GenerationContext generationContext
|
||||
) {
|
||||
double strideMultiplier = Math.pow(2,stride);
|
||||
double heightDiff = realY - surfaceHeight;
|
||||
Globals.profiler.endCpuSample();
|
||||
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
|
||||
//below surface
|
||||
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||
if(sample > 0){
|
||||
double finalSurface = MathUtils.clamp(sample,0,1);
|
||||
voxel.weight = (float)finalSurface * 2 - 1;
|
||||
voxel.type = 1;
|
||||
} else {
|
||||
voxel.weight = -1.0f;
|
||||
voxel.type = 0;
|
||||
}
|
||||
} else if(heightDiff > 0) {
|
||||
//above surface
|
||||
voxel.weight = -1.0f;
|
||||
voxel.type = 0;
|
||||
} else if(heightDiff < -strideMultiplier){
|
||||
//generate full-size surface-type voxel
|
||||
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||
if(sample > 0){
|
||||
double finalHeight = MathUtils.clamp(sample,0,1);
|
||||
voxel.weight = (float)finalHeight * 2 - 1;
|
||||
voxel.type = 2;
|
||||
} else {
|
||||
voxel.weight = -1.0f;
|
||||
voxel.type = 0;
|
||||
}
|
||||
} else {
|
||||
//surface
|
||||
double sample = this.sampler.getValue(0, realX, realY, realZ);
|
||||
if(sample > 0){
|
||||
double surfacePercent = heightDiff / -strideMultiplier;
|
||||
double finalHeight = MathUtils.clamp(sample,0,1) * MathUtils.clamp(surfacePercent,0,1);
|
||||
voxel.weight = (float)finalHeight * 2 - 1;
|
||||
voxel.type = 2;
|
||||
} else {
|
||||
voxel.weight = -1.0f;
|
||||
voxel.type = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the weight of a voxel on the surface based on the surface height, the position of the voxel, and the stride multiplier
|
||||
* @param surfaceHeight The surface height
|
||||
* @param realPosY The position of the voxel
|
||||
* @param strideMultiplier The stride multiplier
|
||||
* @return The weight of the voxel
|
||||
*/
|
||||
protected static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
|
||||
return ((surfaceHeight - realPosY) / strideMultiplier);
|
||||
}
|
||||
|
||||
}
|
||||
@ -37,6 +37,7 @@ public interface VoxelGenerator {
|
||||
GeneratedVoxel voxel,
|
||||
int worldX, int worldY, int worldZ,
|
||||
int chunkX, int chunkY, int chunkZ,
|
||||
double realX, double realY, double realZ,
|
||||
int stride,
|
||||
float surfaceHeight, float surfaceGradient,
|
||||
BiomeData surfaceBiome,
|
||||
|
||||
@ -8,6 +8,8 @@ import electrosphere.game.data.creature.type.ai.AITreeDataSerializer;
|
||||
import electrosphere.game.data.creature.type.movement.MovementSystem;
|
||||
import electrosphere.game.data.creature.type.movement.MovementSystemSerializer;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseModuleSerializer;
|
||||
import electrosphere.server.terrain.generation.noise.NoiseSampler;
|
||||
import electrosphere.util.annotation.AnnotationExclusionStrategy;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -43,6 +45,7 @@ public class FileUtils {
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder.registerTypeAdapter(MovementSystem.class, new MovementSystemSerializer());
|
||||
gsonBuilder.registerTypeAdapter(AITreeData.class, new AITreeDataSerializer());
|
||||
gsonBuilder.registerTypeAdapter(NoiseSampler.class, new NoiseModuleSerializer());
|
||||
gsonBuilder.addDeserializationExclusionStrategy(new AnnotationExclusionStrategy());
|
||||
gsonBuilder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
|
||||
gson = gsonBuilder.create();
|
||||
@ -248,6 +251,23 @@ public class FileUtils {
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an object from the assets folder
|
||||
* @param <T> The type of object
|
||||
* @param file The file to load from
|
||||
* @param className The class of the object inside the file
|
||||
* @return The file
|
||||
*/
|
||||
public static <T>T loadObjectFromFile(File file, Class<T> className){
|
||||
T rVal = null;
|
||||
try {
|
||||
rVal = gson.fromJson(Files.newBufferedReader(file.toPath()), className);
|
||||
} catch (IOException ex) {
|
||||
LoggerInterface.loggerFileIO.ERROR(ex);
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an sql script file as a string
|
||||
|
||||
Loading…
Reference in New Issue
Block a user