js chunkgen + fixes + scriptengine work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
86e61b7a0e
commit
cc60818e35
@ -4,6 +4,7 @@ import { HookManager } from '/Scripts/engine/hooks/hook-manager'
|
|||||||
import { SceneLoader } from '/Scripts/engine/scene/scene-loader'
|
import { SceneLoader } from '/Scripts/engine/scene/scene-loader'
|
||||||
import { Engine } from '/Scripts/types/engine'
|
import { Engine } from '/Scripts/types/engine'
|
||||||
import { clientHooks } from '/Scripts/client/clienthooks'
|
import { clientHooks } from '/Scripts/client/clienthooks'
|
||||||
|
import { ChunkGeneratorManager } from '/Scripts/server/chunk/chunkgeneratormanager'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The core engine values
|
* The core engine values
|
||||||
@ -13,6 +14,7 @@ export const engine: Engine = {
|
|||||||
singletons: {},
|
singletons: {},
|
||||||
hookManager: new HookManager(),
|
hookManager: new HookManager(),
|
||||||
sceneLoader: new SceneLoader(),
|
sceneLoader: new SceneLoader(),
|
||||||
|
chunkGeneratorManager: new ChunkGeneratorManager(),
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,6 +27,7 @@ export const ENGINE_onInit = () => {
|
|||||||
let client: NamespaceClient = Client
|
let client: NamespaceClient = Client
|
||||||
engine.sceneLoader.engine = engine
|
engine.sceneLoader.engine = engine
|
||||||
engine.hookManager.engine = engine
|
engine.hookManager.engine = engine
|
||||||
|
engine.chunkGeneratorManager.engine = engine
|
||||||
|
|
||||||
//load global hooks
|
//load global hooks
|
||||||
clientHooks.forEach(hook => {
|
clientHooks.forEach(hook => {
|
||||||
|
|||||||
39
assets/Scripts/server/chunk/chunkgeneratormanager.ts
Normal file
39
assets/Scripts/server/chunk/chunkgeneratormanager.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { TestGen } from "/Scripts/server/chunk/generators/testgen"
|
||||||
|
import { Engine } from "/Scripts/types/engine"
|
||||||
|
import { ChunkGenerator, VoxelFunction } from "/Scripts/types/host/server/chunk/chunkgenerator"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages all the chunk generators defined script-side
|
||||||
|
*/
|
||||||
|
export class ChunkGeneratorManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent engine object
|
||||||
|
*/
|
||||||
|
engine: Engine
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of registered chunk generators
|
||||||
|
*/
|
||||||
|
readonly registeredGenerators: ChunkGenerator[] = [
|
||||||
|
TestGen,
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the voxel function for the tag
|
||||||
|
* @param tag The tag
|
||||||
|
* @returns The voxel function if it exists, null otherwise
|
||||||
|
*/
|
||||||
|
readonly getVoxelFunction = (tag: string): VoxelFunction => {
|
||||||
|
let rVal: VoxelFunction = null
|
||||||
|
this.registeredGenerators.forEach(generator => {
|
||||||
|
if(generator.getTag() === tag){
|
||||||
|
rVal = generator.getVoxelFunction(this.engine)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rVal
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
159
assets/Scripts/server/chunk/generators/testgen.ts
Normal file
159
assets/Scripts/server/chunk/generators/testgen.ts
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import { Engine } from "/Scripts/types/engine";
|
||||||
|
import { CHUNK_WIDTH, ChunkGenerator, GeneratedVoxel, VoxelFunction } from "/Scripts/types/host/server/chunk/chunkgenerator";
|
||||||
|
import { BiomeData } from "/Scripts/types/host/server/data/biomedata";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a chunk coordinate to a real coordinate
|
||||||
|
* @param chunk The chunk pos
|
||||||
|
* @param world The world pos
|
||||||
|
* @returns The real pos
|
||||||
|
*/
|
||||||
|
const voxelToReal = (chunk: number, world: number) => {
|
||||||
|
return world * CHUNK_WIDTH + chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the voxel on the surface
|
||||||
|
* @return The voxel
|
||||||
|
*/
|
||||||
|
const getSurfaceVoxel = (
|
||||||
|
voxel: GeneratedVoxel,
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
realX: number, realY: number, realZ: number,
|
||||||
|
surfacePercent: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
) => {
|
||||||
|
voxel.weight = surfacePercent * 2 - 1;
|
||||||
|
voxel.type = 2;
|
||||||
|
return voxel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the voxel below the surface
|
||||||
|
* @return The voxel
|
||||||
|
*/
|
||||||
|
const getSubsurfaceVoxel = (
|
||||||
|
voxel: GeneratedVoxel,
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
realX: number, realY: number, realZ: number,
|
||||||
|
surfacePercent: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
) => {
|
||||||
|
if(realY < surfaceHeight - 5){
|
||||||
|
voxel.weight = 1;
|
||||||
|
voxel.type = 6;
|
||||||
|
} else {
|
||||||
|
voxel.weight = 1;
|
||||||
|
voxel.type = 1;
|
||||||
|
}
|
||||||
|
return voxel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the voxel above the service
|
||||||
|
* @return The voxel
|
||||||
|
*/
|
||||||
|
const getOverSurfaceVoxel = (
|
||||||
|
voxel: GeneratedVoxel,
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
realX: number, realY: number, realZ: number,
|
||||||
|
surfacePercent: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
) => {
|
||||||
|
voxel.weight = -1;
|
||||||
|
voxel.type = 0;
|
||||||
|
return voxel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test generator
|
||||||
|
*/
|
||||||
|
export const TestGen: ChunkGenerator = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag for this generator
|
||||||
|
* @returns The tag
|
||||||
|
*/
|
||||||
|
getTag: () => "test",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The elevation function
|
||||||
|
* @param worldX The world x coordinate
|
||||||
|
* @param worldZ The world z coordinate
|
||||||
|
* @param chunkX The chunk x coordinate
|
||||||
|
* @param chunkZ The chunk z coordinate
|
||||||
|
*/
|
||||||
|
getElevation: (worldX: number, worldZ: number, chunkX: number, chunkZ: number): number => {
|
||||||
|
return 1
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the function to actually get voxels
|
||||||
|
* @param engine The engine reference
|
||||||
|
*/
|
||||||
|
getVoxelFunction: (
|
||||||
|
engine: Engine
|
||||||
|
): VoxelFunction => {
|
||||||
|
const rVal = (
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
stride: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
): GeneratedVoxel => {
|
||||||
|
let rVal: GeneratedVoxel = {
|
||||||
|
type: 0,
|
||||||
|
weight: -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
const realX = voxelToReal(chunkX,worldX)
|
||||||
|
const realY = voxelToReal(chunkY,worldY)
|
||||||
|
const realZ = voxelToReal(chunkZ,worldZ)
|
||||||
|
const strideMultiplier = engine.classes.math.static.pow(2,stride)
|
||||||
|
// const strideMultiplier = 1
|
||||||
|
const heightDiff = realY - surfaceHeight
|
||||||
|
const surfacePercent = (surfaceHeight - realY) / strideMultiplier
|
||||||
|
|
||||||
|
if(heightDiff < -strideMultiplier){
|
||||||
|
return getSubsurfaceVoxel(
|
||||||
|
rVal,
|
||||||
|
worldX, worldY, worldZ,
|
||||||
|
chunkX, chunkY, chunkZ,
|
||||||
|
realX, realY, realZ,
|
||||||
|
surfacePercent,
|
||||||
|
surfaceHeight,
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
} else if(heightDiff > 0) {
|
||||||
|
return getOverSurfaceVoxel(
|
||||||
|
rVal,
|
||||||
|
worldX, worldY, worldZ,
|
||||||
|
chunkX, chunkY, chunkZ,
|
||||||
|
realX, realY, realZ,-
|
||||||
|
surfacePercent,
|
||||||
|
surfaceHeight,
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return getSurfaceVoxel(
|
||||||
|
rVal,
|
||||||
|
worldX, worldY, worldZ,
|
||||||
|
chunkX, chunkY, chunkZ,
|
||||||
|
realX, realY, realZ,
|
||||||
|
surfacePercent,
|
||||||
|
surfaceHeight,
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rVal
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { HookManager } from "/Scripts/engine/hooks/hook-manager";
|
import { HookManager } from "/Scripts/engine/hooks/hook-manager";
|
||||||
import { SceneLoader } from "/Scripts/engine/scene/scene-loader";
|
import { SceneLoader } from "/Scripts/engine/scene/scene-loader";
|
||||||
|
import { ChunkGeneratorManager } from "/Scripts/server/chunk/chunkgeneratormanager";
|
||||||
import { SingletonsMap } from "/Scripts/types/host/singletons";
|
import { SingletonsMap } from "/Scripts/types/host/singletons";
|
||||||
import { StaticClasses } from "/Scripts/types/host/static-classes";
|
import { StaticClasses } from "/Scripts/types/host/static-classes";
|
||||||
|
|
||||||
@ -29,5 +30,10 @@ export interface Engine {
|
|||||||
*/
|
*/
|
||||||
readonly sceneLoader: SceneLoader,
|
readonly sceneLoader: SceneLoader,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The chunk generator manager
|
||||||
|
*/
|
||||||
|
readonly chunkGeneratorManager: ChunkGeneratorManager,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
95
assets/Scripts/types/host/server/chunk/chunkgenerator.ts
Normal file
95
assets/Scripts/types/host/server/chunk/chunkgenerator.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { Engine } from "/Scripts/types/engine";
|
||||||
|
import { BiomeData } from "/Scripts/types/host/server/data/biomedata";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of a chunk
|
||||||
|
*/
|
||||||
|
export const CHUNK_WIDTH = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A voxel generated by a ChunkGenerator
|
||||||
|
*/
|
||||||
|
export interface GeneratedVoxel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the voxel type
|
||||||
|
*/
|
||||||
|
type: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The weight of the voxel
|
||||||
|
*/
|
||||||
|
weight: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a voxel for a given position
|
||||||
|
* @param worldX The world x coordinate of the chunk
|
||||||
|
* @param worldY The world y coordinate of the chunk
|
||||||
|
* @param worldZ The world z coordinate of the chunk
|
||||||
|
* @param chunkX The chunk x coordinate
|
||||||
|
* @param chunkY The chunk y coordinate
|
||||||
|
* @param chunkZ The chunk z coordinate
|
||||||
|
* @param stride The stride of the data (this is used for LOD, it ranges 0->4 with 0 being the highest level of detail and 4 being the lowest)
|
||||||
|
* @param surfaceHeight The height of the surface at the given x,z coordinate
|
||||||
|
* @param terrainModel The terrain model
|
||||||
|
* @param surfaceBiome The surface biome
|
||||||
|
* @returns The voxel at the provided position
|
||||||
|
*/
|
||||||
|
export type VoxelFunction = (
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
stride: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
) => GeneratedVoxel;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a chunk for a given world position
|
||||||
|
* @param worldX The world x coordinate of the chunk
|
||||||
|
* @param worldY The world y coordinate of the chunk
|
||||||
|
* @param worldZ The world z coordinate of the chunk
|
||||||
|
* @param stride The stride of the data (this is used for LOD, it ranges 0->4 with 0 being the highest level of detail and 4 being the lowest)
|
||||||
|
* @param surfaceHeight The height of the surface at the given x,z coordinate
|
||||||
|
* @param terrainModel The terrain model
|
||||||
|
* @param surfaceBiome The surface biome
|
||||||
|
* @returns The voxel at the provided position
|
||||||
|
*/
|
||||||
|
export type ChunkFunction = (
|
||||||
|
worldX: number, worldY: number, worldZ: number,
|
||||||
|
chunkX: number, chunkY: number, chunkZ: number,
|
||||||
|
stride: number,
|
||||||
|
surfaceHeight: number,
|
||||||
|
surfaceBiome: BiomeData
|
||||||
|
) => number[][][];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chunk generator
|
||||||
|
*/
|
||||||
|
export interface ChunkGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag for this generator
|
||||||
|
* @returns The tag
|
||||||
|
*/
|
||||||
|
getTag: () => string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the elevation for the world at a given x,z coordinate
|
||||||
|
* @param worldX The world x coordinate
|
||||||
|
* @param worldZ The world z coordinate
|
||||||
|
* @param chunkX The x coordinate of the chunk within the specified world coordinate
|
||||||
|
* @param chunkZ The z coordinate of the chunk within the specified world coordinate
|
||||||
|
* @returns The elevation at that specific position
|
||||||
|
*/
|
||||||
|
getElevation: (worldX: number, worldZ: number, chunkX: number, chunkZ: number) => number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to get a voxel for a given position
|
||||||
|
*/
|
||||||
|
getVoxelFunction: (engine: Engine) => VoxelFunction
|
||||||
|
|
||||||
|
}
|
||||||
95
assets/Scripts/types/host/server/data/biomedata.ts
Normal file
95
assets/Scripts/types/host/server/data/biomedata.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a type of foliage that can be generated in a biome
|
||||||
|
*/
|
||||||
|
export interface BiomeFoliageDescription {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of entity IDs in the type
|
||||||
|
*/
|
||||||
|
entityIDs: string[],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How regular the placement of the foliage is.
|
||||||
|
* Low values make the placement more random.
|
||||||
|
* High values make the placement more orderly (aligned with a grid).
|
||||||
|
*/
|
||||||
|
regularity: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The percentage of the ground to cover with foliage
|
||||||
|
*/
|
||||||
|
threshold: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The priority of this type in particular
|
||||||
|
*/
|
||||||
|
priority: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The scale of the noise used to place foliage
|
||||||
|
*/
|
||||||
|
scale: number,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters for generating the surface of a biome
|
||||||
|
*/
|
||||||
|
export interface BiomeSurfaceGenerationParams {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tag for the generation algorithm to generate the surface of the biome
|
||||||
|
*/
|
||||||
|
surfaceGenTag: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offset added to the generated heightfield to get the final height of the surface at a given position.
|
||||||
|
* This is most useful for cases like plateaus where you really want to put the surface noise higher than its surroundings.
|
||||||
|
*/
|
||||||
|
heightOffset: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The different foliage types that can be generated on this surface
|
||||||
|
*/
|
||||||
|
foliageDescriptions: BiomeFoliageDescription[],
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Biome data
|
||||||
|
*/
|
||||||
|
export interface BiomeData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the biome type
|
||||||
|
*/
|
||||||
|
id: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display name of the biome
|
||||||
|
*/
|
||||||
|
displayName: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this is an aerial biome
|
||||||
|
*/
|
||||||
|
isAerial: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this is a surface biome
|
||||||
|
*/
|
||||||
|
isSurface: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this is a subterranean biome
|
||||||
|
*/
|
||||||
|
isSubterranean: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameters for generating the surface of this biome
|
||||||
|
*/
|
||||||
|
surfaceGenerationParams: BiomeSurfaceGenerationParams,
|
||||||
|
|
||||||
|
}
|
||||||
@ -46,6 +46,11 @@ export interface StaticClasses {
|
|||||||
*/
|
*/
|
||||||
readonly levelEditorUtils?: Class<ClientLevelEditorUtils>,
|
readonly levelEditorUtils?: Class<ClientLevelEditorUtils>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Math functions
|
||||||
|
*/
|
||||||
|
readonly math?: Class<Math>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
14
assets/Scripts/types/host/util/mathutils.ts
Normal file
14
assets/Scripts/types/host/util/mathutils.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Math functions
|
||||||
|
*/
|
||||||
|
export interface Math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes an arbitrary power of a number
|
||||||
|
* @param num1 The number
|
||||||
|
* @param num2 The power
|
||||||
|
* @returns The result of the power
|
||||||
|
*/
|
||||||
|
readonly pow: (num1: number, num2: number) => number
|
||||||
|
|
||||||
|
}
|
||||||
@ -963,6 +963,15 @@ Fix foliage rendering
|
|||||||
Fix async physics gen on client
|
Fix async physics gen on client
|
||||||
Convert volumetric + shadow pass to entity tags
|
Convert volumetric + shadow pass to entity tags
|
||||||
|
|
||||||
|
(11/09/2024)
|
||||||
|
Fix eighth res chunk radius
|
||||||
|
Fix chunk gen debug ui regenerate button
|
||||||
|
Script-defined chunk generators
|
||||||
|
Script engine synchronization utility
|
||||||
|
Convert ScriptEngine to service
|
||||||
|
ScriptEngine full re-initialization signal
|
||||||
|
Add surface width to test generator
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
|||||||
@ -14,9 +14,11 @@ public class ClientScriptUtils {
|
|||||||
* @param args The arguments provided alongside the signal
|
* @param args The arguments provided alongside the signal
|
||||||
*/
|
*/
|
||||||
public static void fireSignal(String signalName, Object ... args){
|
public static void fireSignal(String signalName, Object ... args){
|
||||||
if(Globals.scriptEngine != null && Globals.scriptEngine.isInitialized()){
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
Globals.scriptEngine.fireSignal(signalName, ScriptEngine.GLOBAL_SCENE, args);
|
if(Globals.scriptEngine != null && Globals.scriptEngine.isInitialized()){
|
||||||
}
|
Globals.scriptEngine.fireSignal(signalName, ScriptEngine.GLOBAL_SCENE, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,6 +97,9 @@ public class ClientTerrainCache {
|
|||||||
this.cacheList.clear();
|
this.cacheList.clear();
|
||||||
this.cacheMapFullRes.clear();
|
this.cacheMapFullRes.clear();
|
||||||
this.cacheMapHalfRes.clear();
|
this.cacheMapHalfRes.clear();
|
||||||
|
this.cacheMapQuarterRes.clear();
|
||||||
|
this.cacheMapEighthRes.clear();
|
||||||
|
this.cacheMapSixteenthRes.clear();
|
||||||
this.chunkPositionMap.clear();
|
this.chunkPositionMap.clear();
|
||||||
lock.release();
|
lock.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,6 +98,11 @@ public class ClientDrawCellManager {
|
|||||||
*/
|
*/
|
||||||
Map<FloatingChunkTreeNode<DrawCell>,Boolean> evaluationMap = new HashMap<FloatingChunkTreeNode<DrawCell>,Boolean>();
|
Map<FloatingChunkTreeNode<DrawCell>,Boolean> evaluationMap = new HashMap<FloatingChunkTreeNode<DrawCell>,Boolean>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All draw cells currently tracked
|
||||||
|
*/
|
||||||
|
List<DrawCell> activeCells = new LinkedList<DrawCell>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks whether the cell manager updated last frame or not
|
* Tracks whether the cell manager updated last frame or not
|
||||||
*/
|
*/
|
||||||
@ -227,6 +232,7 @@ public class ClientDrawCellManager {
|
|||||||
child.getMinBound().z
|
child.getMinBound().z
|
||||||
);
|
);
|
||||||
DrawCell drawCell = DrawCell.generateTerrainCell(cellWorldPos);
|
DrawCell drawCell = DrawCell.generateTerrainCell(cellWorldPos);
|
||||||
|
activeCells.add(drawCell);
|
||||||
child.convertToLeaf(drawCell);
|
child.convertToLeaf(drawCell);
|
||||||
evaluationMap.put(child,true);
|
evaluationMap.put(child,true);
|
||||||
});
|
});
|
||||||
@ -246,6 +252,7 @@ public class ClientDrawCellManager {
|
|||||||
|
|
||||||
//do creations
|
//do creations
|
||||||
DrawCell drawCell = DrawCell.generateTerrainCell(node.getMinBound());
|
DrawCell drawCell = DrawCell.generateTerrainCell(node.getMinBound());
|
||||||
|
activeCells.add(drawCell);
|
||||||
newLeaf.convertToLeaf(drawCell);
|
newLeaf.convertToLeaf(drawCell);
|
||||||
|
|
||||||
//update neighbors
|
//update neighbors
|
||||||
@ -544,7 +551,7 @@ public class ClientDrawCellManager {
|
|||||||
(
|
(
|
||||||
node.getLevel() == this.chunkTree.getMaxLevel() - EIGHTH_RES_LOD
|
node.getLevel() == this.chunkTree.getMaxLevel() - EIGHTH_RES_LOD
|
||||||
&&
|
&&
|
||||||
this.getMinDistance(pos, node) <= EIGHTH_RES_DIST
|
this.getMinDistance(pos, node) <= SIXTEENTH_RES_DIST
|
||||||
)
|
)
|
||||||
||
|
||
|
||||||
(
|
(
|
||||||
@ -591,7 +598,7 @@ public class ClientDrawCellManager {
|
|||||||
(
|
(
|
||||||
node.getLevel() == this.chunkTree.getMaxLevel() - EIGHTH_RES_LOD
|
node.getLevel() == this.chunkTree.getMaxLevel() - EIGHTH_RES_LOD
|
||||||
&&
|
&&
|
||||||
this.getMinDistance(pos, node) <= EIGHTH_RES_DIST
|
this.getMinDistance(pos, node) <= SIXTEENTH_RES_DIST
|
||||||
)
|
)
|
||||||
||
|
||
|
||||||
(
|
(
|
||||||
@ -631,6 +638,7 @@ public class ClientDrawCellManager {
|
|||||||
node.getChildren().forEach(child -> recursivelyDestroy(child));
|
node.getChildren().forEach(child -> recursivelyDestroy(child));
|
||||||
}
|
}
|
||||||
if(node.getData() != null){
|
if(node.getData() != null){
|
||||||
|
activeCells.remove(node.getData());
|
||||||
node.getData().destroy();
|
node.getData().destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -659,6 +667,7 @@ public class ClientDrawCellManager {
|
|||||||
* Evicts all cells
|
* Evicts all cells
|
||||||
*/
|
*/
|
||||||
public void evictAll(){
|
public void evictAll(){
|
||||||
|
this.recursivelyDestroy(this.chunkTree.getRoot());
|
||||||
this.chunkTree.clear();
|
this.chunkTree.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package electrosphere.client.ui.menu.debug;
|
package electrosphere.client.ui.menu.debug;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.engine.signal.Signal.SignalType;
|
||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow;
|
||||||
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback;
|
||||||
import electrosphere.server.datacell.GriddedDataCellManager;
|
import electrosphere.server.datacell.GriddedDataCellManager;
|
||||||
@ -45,10 +46,19 @@ public class ImGuiTestGen {
|
|||||||
|
|
||||||
//regenerate the test area
|
//regenerate the test area
|
||||||
if(ImGui.button("Regenerate")){
|
if(ImGui.button("Regenerate")){
|
||||||
GriddedDataCellManager gridManager = (GriddedDataCellManager)Globals.realmManager.first().getDataCellManager();
|
//recompile script engine
|
||||||
gridManager.evictAll();
|
Globals.signalSystem.post(SignalType.SCRIPT_RECOMPILE, () -> {
|
||||||
Globals.clientDrawCellManager.evictAll();
|
|
||||||
Globals.clientTerrainManager.evictAll();
|
//run once script recompilation has completed
|
||||||
|
|
||||||
|
//clear server
|
||||||
|
GriddedDataCellManager gridManager = (GriddedDataCellManager)Globals.realmManager.first().getDataCellManager();
|
||||||
|
gridManager.evictAll();
|
||||||
|
|
||||||
|
//clear client
|
||||||
|
Globals.clientDrawCellManager.evictAll();
|
||||||
|
Globals.clientTerrainManager.evictAll();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//set macro data scale in terrain model
|
//set macro data scale in terrain model
|
||||||
@ -82,7 +92,7 @@ public class ImGuiTestGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Toggles whether the client draws cell manager should update or not
|
//Toggles whether the client draws cell manager should update or not
|
||||||
if(ImGui.button("Toggle ClientDrawCellManager updates")){
|
if(ImGui.button("Toggle ClientDrawCellManager updates " + (Globals.clientDrawCellManager.getShouldUpdate() ? "off" : "on"))){
|
||||||
Globals.clientDrawCellManager.setShouldUpdate(!Globals.clientDrawCellManager.getShouldUpdate());
|
Globals.clientDrawCellManager.setShouldUpdate(!Globals.clientDrawCellManager.getShouldUpdate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -481,8 +481,6 @@ public class Globals {
|
|||||||
skyboxColors = new ArrayList<Vector3f>();
|
skyboxColors = new ArrayList<Vector3f>();
|
||||||
//load asset manager
|
//load asset manager
|
||||||
assetManager = new AssetManager();
|
assetManager = new AssetManager();
|
||||||
//script engine
|
|
||||||
scriptEngine = new ScriptEngine();
|
|
||||||
//ai manager
|
//ai manager
|
||||||
aiManager = new AIManager(0);
|
aiManager = new AIManager(0);
|
||||||
//realm & data cell manager
|
//realm & data cell manager
|
||||||
@ -526,6 +524,7 @@ public class Globals {
|
|||||||
Globals.signalSystem = (SignalSystem)serviceManager.registerService(new SignalSystem());
|
Globals.signalSystem = (SignalSystem)serviceManager.registerService(new SignalSystem());
|
||||||
Globals.elementService = (ElementService)serviceManager.registerService(new ElementService());
|
Globals.elementService = (ElementService)serviceManager.registerService(new ElementService());
|
||||||
Globals.particleService = (ParticleService)serviceManager.registerService(new ParticleService());
|
Globals.particleService = (ParticleService)serviceManager.registerService(new ParticleService());
|
||||||
|
Globals.scriptEngine = (ScriptEngine)serviceManager.registerService(new ScriptEngine());
|
||||||
serviceManager.instantiate();
|
serviceManager.instantiate();
|
||||||
//
|
//
|
||||||
//End service manager
|
//End service manager
|
||||||
@ -537,6 +536,7 @@ public class Globals {
|
|||||||
Globals.signalSystem.registerService(SignalType.YOGA_DESTROY, Globals.elementService);
|
Globals.signalSystem.registerService(SignalType.YOGA_DESTROY, Globals.elementService);
|
||||||
Globals.signalSystem.registerService(SignalType.UI_MODIFICATION, Globals.elementService);
|
Globals.signalSystem.registerService(SignalType.UI_MODIFICATION, Globals.elementService);
|
||||||
Globals.signalSystem.registerService(SignalType.RENDERING_ENGINE_READY, Globals.particleService);
|
Globals.signalSystem.registerService(SignalType.RENDERING_ENGINE_READY, Globals.particleService);
|
||||||
|
Globals.signalSystem.registerService(SignalType.SCRIPT_RECOMPILE, Globals.scriptEngine);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -291,7 +291,13 @@ public class Main {
|
|||||||
RenderingEngine.recaptureIfNecessary();
|
RenderingEngine.recaptureIfNecessary();
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// S Y N C H R O N O U S S I G N A L H A N D L I N G
|
||||||
|
///
|
||||||
|
Globals.scriptEngine.handleAllSignals();
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import electrosphere.net.parser.net.message.TerrainMessage;
|
|||||||
import electrosphere.net.server.ServerConnectionHandler;
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
import electrosphere.renderer.ui.elements.Window;
|
import electrosphere.renderer.ui.elements.Window;
|
||||||
import electrosphere.server.saves.SaveUtils;
|
import electrosphere.server.saves.SaveUtils;
|
||||||
|
import electrosphere.server.terrain.generation.TestGenerationChunkGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the chunk generation testing realm
|
* Loads the chunk generation testing realm
|
||||||
@ -42,6 +43,17 @@ public class ChunkGenerationTestLoading {
|
|||||||
loadingWindow.setVisible(true);
|
loadingWindow.setVisible(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//wait on script engine to load
|
||||||
|
if(TestGenerationChunkGenerator.DEFAULT_USE_JAVASCRIPT){
|
||||||
|
WindowUtils.updateLoadingWindow("Waiting on scripting engine");
|
||||||
|
while(!Globals.scriptEngine.isInitialized()){
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(1);
|
||||||
|
} catch (InterruptedException ex) {}
|
||||||
|
}
|
||||||
|
WindowUtils.updateLoadingWindow("LOADING");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
String saveName = "generation_testing";
|
String saveName = "generation_testing";
|
||||||
|
|||||||
@ -11,7 +11,7 @@ public class EngineInitLoading {
|
|||||||
* Loads the core assets of the scripting engine from disk and initializes the engine
|
* Loads the core assets of the scripting engine from disk and initializes the engine
|
||||||
*/
|
*/
|
||||||
protected static void loadScriptingEngine(Object[] params){
|
protected static void loadScriptingEngine(Object[] params){
|
||||||
Globals.scriptEngine.init();
|
Globals.scriptEngine.initScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,11 @@ public class Signal {
|
|||||||
REQUEST_CHUNK_EDIT,
|
REQUEST_CHUNK_EDIT,
|
||||||
CHUNK_EDITED,
|
CHUNK_EDITED,
|
||||||
|
|
||||||
|
//
|
||||||
|
//Script
|
||||||
|
//
|
||||||
|
SCRIPT_RECOMPILE,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -124,8 +124,11 @@ public class SceneLoader {
|
|||||||
}
|
}
|
||||||
//load scripts
|
//load scripts
|
||||||
if(!isLevelEditor && file.getInitScriptPath() != null){
|
if(!isLevelEditor && file.getInitScriptPath() != null){
|
||||||
int sceneInstanceId = Globals.scriptEngine.initScene(file.getInitScriptPath());
|
Realm finalRealm = realm;
|
||||||
realm.setSceneInstanceId(sceneInstanceId);
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
|
int sceneInstanceId = Globals.scriptEngine.initScene(file.getInitScriptPath());
|
||||||
|
finalRealm.setSceneInstanceId(sceneInstanceId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
//TODO: integrate scripts for client side of scenes
|
//TODO: integrate scripts for client side of scenes
|
||||||
// for(String scriptPath : file.getScriptPaths()){
|
// for(String scriptPath : file.getScriptPaths()){
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package electrosphere.game.data.biome;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data about a given biome
|
* Data about a given biome
|
||||||
*/
|
*/
|
||||||
@ -10,11 +12,13 @@ public class BiomeData {
|
|||||||
/**
|
/**
|
||||||
* The id of the biome
|
* The id of the biome
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
String id;
|
String id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The display name of the biome
|
* The display name of the biome
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
String displayName;
|
String displayName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,21 +29,25 @@ public class BiomeData {
|
|||||||
/**
|
/**
|
||||||
* True if this region applies above the surface
|
* True if this region applies above the surface
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Boolean isAerial;
|
Boolean isAerial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if this region applies to the surface
|
* True if this region applies to the surface
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Boolean isSurface;
|
Boolean isSurface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if this region applies below the surface
|
* True if this region applies below the surface
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Boolean isSubterranean;
|
Boolean isSubterranean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The surface generation params
|
* The surface generation params
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
BiomeSurfaceGenerationParams surfaceGenerationParams;
|
BiomeSurfaceGenerationParams surfaceGenerationParams;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,34 +2,41 @@ package electrosphere.game.data.biome;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes behavior for spawning a specific type of foliage in the biome
|
* Describes behavior for spawning a specific type of foliage in the biome
|
||||||
*/
|
*/
|
||||||
public class BiomeFoliageDescription {
|
public class BiomeFoliageDescription {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The liust of entity IDs of this foliage type in particular
|
* The list of entity IDs of this foliage type in particular
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
List<String> entityIDs;
|
List<String> entityIDs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How regular the placement of foliage is. Low values will create very uneven foliage, while high values will place them along a grid.
|
* How regular the placement of foliage is. Low values will create very uneven foliage, while high values will place them along a grid.
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Double regularity;
|
Double regularity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The percentage of the ground to cover with foliage
|
* The percentage of the ground to cover with foliage
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Double threshold;
|
Double threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The priority of this floor element in particular
|
* The priority of this floor element in particular
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Double priority;
|
Double priority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The scale of the noise used to place foliage
|
* The scale of the noise used to place foliage
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Double scale;
|
Double scale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package electrosphere.game.data.biome;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Params for the surface generation algorithm
|
* Params for the surface generation algorithm
|
||||||
*/
|
*/
|
||||||
@ -10,11 +12,13 @@ public class BiomeSurfaceGenerationParams {
|
|||||||
/**
|
/**
|
||||||
* The tag for the generation algorithm for generating the surface
|
* The tag for the generation algorithm for generating the surface
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
String surfaceGenTag;
|
String surfaceGenTag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset from baseline for height generation with this biome
|
* The offset from baseline for height generation with this biome
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
Float heightOffset;
|
Float heightOffset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,6 +29,7 @@ public class BiomeSurfaceGenerationParams {
|
|||||||
/**
|
/**
|
||||||
* The list of foliage descriptions available to this biome type
|
* The list of foliage descriptions available to this biome type
|
||||||
*/
|
*/
|
||||||
|
@Export
|
||||||
List<BiomeFoliageDescription> foliageDescriptions;
|
List<BiomeFoliageDescription> foliageDescriptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -153,7 +153,7 @@ public class ServerWorldData {
|
|||||||
|
|
||||||
//test terrain gen
|
//test terrain gen
|
||||||
{
|
{
|
||||||
TestGenerationChunkGenerator chunkGen = new TestGenerationChunkGenerator(serverWorldData);
|
TestGenerationChunkGenerator chunkGen = new TestGenerationChunkGenerator(serverWorldData, TestGenerationChunkGenerator.DEFAULT_USE_JAVASCRIPT);
|
||||||
serverTerrainManager = new ServerTerrainManager(serverWorldData, 0, chunkGen);
|
serverTerrainManager = new ServerTerrainManager(serverWorldData, 0, chunkGen);
|
||||||
serverTerrainManager.genTestData(chunkGen);
|
serverTerrainManager.genTestData(chunkGen);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import org.graalvm.polyglot.Context;
|
import org.graalvm.polyglot.Context;
|
||||||
import org.graalvm.polyglot.Engine;
|
import org.graalvm.polyglot.Engine;
|
||||||
@ -19,15 +20,18 @@ import electrosphere.client.ui.menu.script.ScriptMenuUtils;
|
|||||||
import electrosphere.client.ui.menu.tutorial.TutorialMenus;
|
import electrosphere.client.ui.menu.tutorial.TutorialMenus;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.engine.Main;
|
import electrosphere.engine.Main;
|
||||||
|
import electrosphere.engine.signal.Signal;
|
||||||
|
import electrosphere.engine.signal.SignalServiceImpl;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.script.translation.JSServerUtils;
|
import electrosphere.script.translation.JSServerUtils;
|
||||||
|
import electrosphere.script.utils.ScriptMathInterface;
|
||||||
import electrosphere.util.FileUtils;
|
import electrosphere.util.FileUtils;
|
||||||
import electrosphere.util.math.SpatialMathUtils;
|
import electrosphere.util.math.SpatialMathUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for executing scripts in the game engine
|
* Interface for executing scripts in the game engine
|
||||||
*/
|
*/
|
||||||
public class ScriptEngine {
|
public class ScriptEngine extends SignalServiceImpl {
|
||||||
|
|
||||||
//the default namespaces for
|
//the default namespaces for
|
||||||
public static String SCRIPT_NAMESPACE_ENGINE = "engine"; //namespace for the engine functions exposed to the script engine
|
public static String SCRIPT_NAMESPACE_ENGINE = "engine"; //namespace for the engine functions exposed to the script engine
|
||||||
@ -67,6 +71,11 @@ public class ScriptEngine {
|
|||||||
*/
|
*/
|
||||||
boolean initialized = false;
|
boolean initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locks the script engine to enforce synchronization
|
||||||
|
*/
|
||||||
|
ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
//The files that are loaded on init to bootstrap the script engine
|
//The files that are loaded on init to bootstrap the script engine
|
||||||
static final String[] filesToLoadOnInit = new String[]{
|
static final String[] filesToLoadOnInit = new String[]{
|
||||||
//polyfills
|
//polyfills
|
||||||
@ -98,6 +107,7 @@ public class ScriptEngine {
|
|||||||
{"menuUtils",ScriptMenuUtils.class},
|
{"menuUtils",ScriptMenuUtils.class},
|
||||||
{"voxelUtils",ScriptClientVoxelUtils.class},
|
{"voxelUtils",ScriptClientVoxelUtils.class},
|
||||||
{"levelEditorUtils",ScriptLevelEditorUtils.class},
|
{"levelEditorUtils",ScriptLevelEditorUtils.class},
|
||||||
|
{"math",ScriptMathInterface.class},
|
||||||
};
|
};
|
||||||
|
|
||||||
//singletons from the host that are provided to the javascript context
|
//singletons from the host that are provided to the javascript context
|
||||||
@ -107,10 +117,18 @@ public class ScriptEngine {
|
|||||||
{"loggerScripts",LoggerInterface.loggerScripts},
|
{"loggerScripts",LoggerInterface.loggerScripts},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public ScriptEngine(){
|
||||||
|
super("ScriptEngine");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the engine
|
* Initializes the engine
|
||||||
*/
|
*/
|
||||||
public void init(){
|
public void initScripts(){
|
||||||
//init datastructures
|
//init datastructures
|
||||||
sourceMap = new HashMap<String,Source>();
|
sourceMap = new HashMap<String,Source>();
|
||||||
initialized = false;
|
initialized = false;
|
||||||
@ -320,6 +338,22 @@ public class ScriptEngine {
|
|||||||
invokeMemberFunction("COMPILER", "run");
|
invokeMemberFunction("COMPILER", "run");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recompiles the scripting engine
|
||||||
|
*/
|
||||||
|
private void recompile(Runnable onCompletion){
|
||||||
|
Thread recompileThread = new Thread(() -> {
|
||||||
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
|
this.initScripts();
|
||||||
|
});
|
||||||
|
if(onCompletion != null){
|
||||||
|
onCompletion.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
recompileThread.setName("Recompile Script Engine");
|
||||||
|
recompileThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a scene script
|
* Initializes a scene script
|
||||||
* @param scenePath The scene's init script path
|
* @param scenePath The scene's init script path
|
||||||
@ -398,6 +432,40 @@ public class ScriptEngine {
|
|||||||
invokeFunction("require", filePath);
|
invokeFunction("require", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes a function on a member of arbitrary depth on the engine object
|
||||||
|
* @param memberName The member name
|
||||||
|
* @param functionName The function's name
|
||||||
|
* @param className The class of the expected return value
|
||||||
|
* @param args The args to pass to the function
|
||||||
|
* @return The results of the invocation or null if there was no result
|
||||||
|
*/
|
||||||
|
public Value invokeEngineMember(String memberName, String functionName, Object ... args){
|
||||||
|
Value member = this.engineObject.getMember(memberName);
|
||||||
|
if(member == null){
|
||||||
|
throw new Error("Member is null!");
|
||||||
|
}
|
||||||
|
Value function = member.getMember(functionName);
|
||||||
|
if(function == null || !function.canExecute()){
|
||||||
|
throw new Error("Function is not executable! " + function);
|
||||||
|
}
|
||||||
|
Value executionResult = function.execute(args);
|
||||||
|
if(executionResult == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return executionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes some code synchronously that requires script engine access
|
||||||
|
* @param function The function
|
||||||
|
*/
|
||||||
|
public void executeSynchronously(Runnable function){
|
||||||
|
lock.lock();
|
||||||
|
function.run();
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines host members within javascript context
|
* Defines host members within javascript context
|
||||||
*/
|
*/
|
||||||
@ -431,5 +499,23 @@ public class ScriptEngine {
|
|||||||
return this.initialized;
|
return this.initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(Signal signal){
|
||||||
|
boolean rVal = false;
|
||||||
|
switch(signal.getType()){
|
||||||
|
case SCRIPT_RECOMPILE: {
|
||||||
|
if(signal.getData() != null && signal.getData() instanceof Runnable){
|
||||||
|
this.recompile((Runnable)signal.getData());
|
||||||
|
} else {
|
||||||
|
this.recompile(null);
|
||||||
|
}
|
||||||
|
rVal = true;
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package electrosphere.script.utils;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script access to specific math functions
|
||||||
|
*/
|
||||||
|
public class ScriptMathInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power function
|
||||||
|
* @param val1 The number
|
||||||
|
* @param val2 The exponent
|
||||||
|
* @return The power
|
||||||
|
*/
|
||||||
|
@Export
|
||||||
|
public static double pow(double val1, double val2){
|
||||||
|
return Math.pow(val1,val2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -421,9 +421,6 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Evicts all loaded chunks.
|
* Evicts all loaded chunks.
|
||||||
* <p>
|
|
||||||
* Note: Does not save to disk.
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
public void evictAll(){
|
public void evictAll(){
|
||||||
//TODO: improve to make have less performance impact
|
//TODO: improve to make have less performance impact
|
||||||
|
|||||||
@ -274,11 +274,13 @@ public class Realm {
|
|||||||
*/
|
*/
|
||||||
public void fireSignal(String signalName, Object ... args){
|
public void fireSignal(String signalName, Object ... args){
|
||||||
if(Globals.scriptEngine != null && Globals.scriptEngine.isInitialized()){
|
if(Globals.scriptEngine != null && Globals.scriptEngine.isInitialized()){
|
||||||
if(this.sceneInstanceId != NO_SCENE_INSTANCE){
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
Globals.scriptEngine.fireSignal(signalName, sceneInstanceId, args);
|
if(this.sceneInstanceId != NO_SCENE_INSTANCE){
|
||||||
} else {
|
Globals.scriptEngine.fireSignal(signalName, sceneInstanceId, args);
|
||||||
Globals.scriptEngine.fireSignal(signalName, ScriptEngine.GLOBAL_SCENE, args);
|
} else {
|
||||||
}
|
Globals.scriptEngine.fireSignal(signalName, ScriptEngine.GLOBAL_SCENE, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package electrosphere.server.terrain.generation;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.Value;
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.game.data.biome.BiomeData;
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
|
||||||
@ -12,6 +14,7 @@ import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator;
|
|||||||
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
import electrosphere.server.terrain.generation.heightmap.HillsGen;
|
||||||
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
import electrosphere.server.terrain.generation.heightmap.PlainsGen;
|
||||||
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
import electrosphere.server.terrain.generation.interfaces.ChunkGenerator;
|
||||||
|
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
|
||||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||||
import electrosphere.server.terrain.models.TerrainModel;
|
import electrosphere.server.terrain.models.TerrainModel;
|
||||||
|
|
||||||
@ -29,6 +32,21 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
* The default biome index
|
* The default biome index
|
||||||
*/
|
*/
|
||||||
public static final int DEFAULT_BIOME_INDEX = 1;
|
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
|
* The terreain model for the generator
|
||||||
@ -45,14 +63,20 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
*/
|
*/
|
||||||
Map<String,HeightmapGenerator> tagGeneratorMap = new HashMap<String,HeightmapGenerator>();
|
Map<String,HeightmapGenerator> tagGeneratorMap = new HashMap<String,HeightmapGenerator>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks whether to use javascript generation or not
|
||||||
|
*/
|
||||||
|
boolean useJavascript = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public TestGenerationChunkGenerator(ServerWorldData serverWorldData){
|
public TestGenerationChunkGenerator(ServerWorldData serverWorldData, boolean useJavascript){
|
||||||
this.serverWorldData = serverWorldData;
|
this.serverWorldData = serverWorldData;
|
||||||
registerGenerator(new EmptySkyGen());
|
registerGenerator(new EmptySkyGen());
|
||||||
registerGenerator(new HillsGen());
|
registerGenerator(new HillsGen());
|
||||||
registerGenerator(new PlainsGen());
|
registerGenerator(new PlainsGen());
|
||||||
|
this.useJavascript = useJavascript;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,22 +125,61 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
if(this.useJavascript){
|
||||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
Globals.scriptEngine.executeSynchronously(() -> {
|
||||||
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
Value getVoxelFunc = Globals.scriptEngine.invokeEngineMember("chunkGeneratorManager", "getVoxelFunction", SCRIPT_GEN_TEST_TAG);
|
||||||
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||||
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||||
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
||||||
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; z++){
|
||||||
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldX = worldX + ((x * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
int finalWorldZ = worldZ + ((z * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
|
||||||
GeneratedVoxel voxel = this.getVoxel(finalWorldX, finalWorldY, finalWorldZ, finalChunkX, finalChunkY, finalChunkZ, heightfield[x][z], this.terrainModel, surfaceBiome);
|
int finalChunkX = (x * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
weights[x][y][z] = voxel.weight;
|
int finalChunkY = (y * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
values[x][y][z] = voxel.type;
|
int finalChunkZ = (z * strideValue) % ServerTerrainChunk.CHUNK_DIMENSION;
|
||||||
|
Value result = getVoxelFunc.execute(
|
||||||
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
|
stride,
|
||||||
|
heightfield[x][z],
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
if(result != null){
|
||||||
|
weights[x][y][z] = result.getMember("weight").asFloat();
|
||||||
|
values[x][y][z] = result.getMember("type").asInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for(int x = 0; x < ServerTerrainChunk.CHUNK_DIMENSION; x++){
|
||||||
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator - Generate slice");
|
||||||
|
for(int y = 0; y < ServerTerrainChunk.CHUNK_DIMENSION; y++){
|
||||||
|
for(int z = 0; z < ServerTerrainChunk.CHUNK_DIMENSION; 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;
|
||||||
|
GeneratedVoxel voxel = this.getVoxel(
|
||||||
|
finalWorldX, finalWorldY, finalWorldZ,
|
||||||
|
finalChunkX, finalChunkY, finalChunkZ,
|
||||||
|
stride,
|
||||||
|
heightfield[x][z],
|
||||||
|
surfaceBiome
|
||||||
|
);
|
||||||
|
if(voxel != null){
|
||||||
|
weights[x][y][z] = voxel.weight;
|
||||||
|
values[x][y][z] = voxel.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
Globals.profiler.endCpuSample();
|
|
||||||
}
|
}
|
||||||
} catch(Exception ex){
|
} catch(Exception ex){
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
@ -156,16 +219,16 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
* @param chunkX The chunk x pos
|
* @param chunkX The chunk x pos
|
||||||
* @param chunkY The chunk y pos
|
* @param chunkY The chunk y pos
|
||||||
* @param chunkZ The chunk z pos
|
* @param chunkZ The chunk z pos
|
||||||
|
* @param stride The stride of the data
|
||||||
* @param surfaceHeight The height of the surface at x,z
|
* @param surfaceHeight The height of the surface at x,z
|
||||||
* @param terrainModel The terrain model
|
|
||||||
* @param surfaceBiome The surface biome of the chunk
|
* @param surfaceBiome The surface biome of the chunk
|
||||||
* @return The value of the chunk
|
* @return The value of the chunk
|
||||||
*/
|
*/
|
||||||
private GeneratedVoxel getVoxel(
|
private GeneratedVoxel getVoxel(
|
||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
int stride,
|
||||||
float surfaceHeight,
|
float surfaceHeight,
|
||||||
TerrainModel terrainModel,
|
|
||||||
BiomeData surfaceBiome
|
BiomeData surfaceBiome
|
||||||
){
|
){
|
||||||
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.getChunkValue");
|
Globals.profiler.beginAggregateCpuSample("TestGenerationChunkGenerator.getChunkValue");
|
||||||
@ -179,24 +242,26 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
double realY = this.serverWorldData.convertVoxelToRealSpace(chunkY,worldY);
|
double realY = this.serverWorldData.convertVoxelToRealSpace(chunkY,worldY);
|
||||||
double realZ = this.serverWorldData.convertVoxelToRealSpace(chunkZ,worldZ);
|
double realZ = this.serverWorldData.convertVoxelToRealSpace(chunkZ,worldZ);
|
||||||
|
|
||||||
double flooredSurfaceHeight = Math.floor(surfaceHeight);
|
double strideMultiplier = Math.pow(2,stride);
|
||||||
|
double heightDiff = realY - surfaceHeight;
|
||||||
|
double surfacePercent = TestGenerationChunkGenerator.getSurfaceWeight(surfaceHeight,realY,strideMultiplier);
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
if(realY < surfaceHeight - 1){
|
if(heightDiff < -strideMultiplier * SURFACE_VOXEL_WIDTH){
|
||||||
return getSubsurfaceVoxel(
|
return getSubsurfaceVoxel(
|
||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,
|
realX, realY, realZ,
|
||||||
surfaceHeight, flooredSurfaceHeight,
|
surfacePercent,
|
||||||
terrainModel,
|
surfaceHeight,
|
||||||
surfaceBiome
|
surfaceBiome
|
||||||
);
|
);
|
||||||
} else if(realY > flooredSurfaceHeight) {
|
} else if(heightDiff > 0) {
|
||||||
return getOverSurfaceVoxel(
|
return getOverSurfaceVoxel(
|
||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,
|
realX, realY, realZ,-
|
||||||
surfaceHeight, flooredSurfaceHeight,
|
surfacePercent,
|
||||||
terrainModel,
|
surfaceHeight,
|
||||||
surfaceBiome
|
surfaceBiome
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -204,8 +269,8 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
worldX, worldY, worldZ,
|
worldX, worldY, worldZ,
|
||||||
chunkX, chunkY, chunkZ,
|
chunkX, chunkY, chunkZ,
|
||||||
realX, realY, realZ,
|
realX, realY, realZ,
|
||||||
surfaceHeight, flooredSurfaceHeight,
|
surfacePercent,
|
||||||
terrainModel,
|
surfaceHeight,
|
||||||
surfaceBiome
|
surfaceBiome
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -219,12 +284,12 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
double realX, double realY, double realZ,
|
double realX, double realY, double realZ,
|
||||||
float surfaceHeight, double flooredSurfaceHeight,
|
double surfacePercent,
|
||||||
TerrainModel terrainModel,
|
float surfaceHeight,
|
||||||
BiomeData surfaceBiome
|
BiomeData surfaceBiome
|
||||||
){
|
){
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
voxel.weight = (float)(surfaceHeight - flooredSurfaceHeight) * 2 - 1;
|
voxel.weight = (float)surfacePercent * 2 - 1;
|
||||||
voxel.type = 2;
|
voxel.type = 2;
|
||||||
return voxel;
|
return voxel;
|
||||||
}
|
}
|
||||||
@ -237,8 +302,8 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
double realX, double realY, double realZ,
|
double realX, double realY, double realZ,
|
||||||
float surfaceHeight, double flooredSurfaceHeight,
|
double surfacePercent,
|
||||||
TerrainModel terrainModel,
|
float surfaceHeight,
|
||||||
BiomeData surfaceBiome
|
BiomeData surfaceBiome
|
||||||
){
|
){
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
@ -260,8 +325,8 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
int worldX, int worldY, int worldZ,
|
int worldX, int worldY, int worldZ,
|
||||||
int chunkX, int chunkY, int chunkZ,
|
int chunkX, int chunkY, int chunkZ,
|
||||||
double realX, double realY, double realZ,
|
double realX, double realY, double realZ,
|
||||||
float surfaceHeight, double flooredSurfaceHeight,
|
double surfacePercent,
|
||||||
TerrainModel terrainModel,
|
float surfaceHeight,
|
||||||
BiomeData surfaceBiome
|
BiomeData surfaceBiome
|
||||||
){
|
){
|
||||||
GeneratedVoxel voxel = new GeneratedVoxel();
|
GeneratedVoxel voxel = new GeneratedVoxel();
|
||||||
@ -271,17 +336,14 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A voxel that was generated
|
* 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
|
||||||
*/
|
*/
|
||||||
static class GeneratedVoxel {
|
protected static double getSurfaceWeight(double surfaceHeight, double realPosY, double strideMultiplier){
|
||||||
/**
|
return ((surfaceHeight - realPosY) / strideMultiplier);
|
||||||
* The type of the voxel
|
|
||||||
*/
|
|
||||||
int type;
|
|
||||||
/**
|
|
||||||
* The weight of the voxel
|
|
||||||
*/
|
|
||||||
float weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package electrosphere.server.terrain.generation.interfaces;
|
||||||
|
|
||||||
|
import org.graalvm.polyglot.HostAccess.Export;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A voxel generated by a chunk generator
|
||||||
|
*/
|
||||||
|
public class GeneratedVoxel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the voxel
|
||||||
|
*/
|
||||||
|
@Export
|
||||||
|
public int type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The weight of the voxel
|
||||||
|
*/
|
||||||
|
@Export
|
||||||
|
public float weight;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package electrosphere.server.terrain.generation.interfaces;
|
||||||
|
|
||||||
|
import electrosphere.game.data.biome.BiomeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A script-defined chunk generator
|
||||||
|
*/
|
||||||
|
public interface JSChunkGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag for this generator
|
||||||
|
* @returns The tag
|
||||||
|
*/
|
||||||
|
public String getTag();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the elevation for the world at a given x,z coordinate
|
||||||
|
* @param worldX The world x coordinate
|
||||||
|
* @param worldZ The world z coordinate
|
||||||
|
* @param chunkX The x coordinate of the chunk within the specified world coordinate
|
||||||
|
* @param chunkZ The z coordinate of the chunk within the specified world coordinate
|
||||||
|
* @returns The elevation at that specific position
|
||||||
|
*/
|
||||||
|
public float getElevation(int worldX, int worldZ, int chunkX, int chunkZ);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to get a voxel for a given position
|
||||||
|
*/
|
||||||
|
public GeneratedVoxel getVoxel(
|
||||||
|
int worldX, int worldY, int worldZ,
|
||||||
|
int chunkX, int chunkY, int chunkZ,
|
||||||
|
int stride,
|
||||||
|
double surfaceHeight,
|
||||||
|
BiomeData surfaceBiome
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
@ -84,6 +84,9 @@ public class ServerChunkCache {
|
|||||||
lock.acquireUninterruptibly();
|
lock.acquireUninterruptibly();
|
||||||
cacheMapFullRes.clear();
|
cacheMapFullRes.clear();
|
||||||
cacheMapHalfRes.clear();
|
cacheMapHalfRes.clear();
|
||||||
|
cacheMapQuarterRes.clear();
|
||||||
|
cacheMapEighthRes.clear();
|
||||||
|
cacheMapSixteenthRes.clear();
|
||||||
lock.release();
|
lock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package electrosphere.server.terrain.generation;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import electrosphere.test.annotations.FastTest;
|
||||||
|
import electrosphere.test.annotations.UnitTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the test generation chunk generator
|
||||||
|
*/
|
||||||
|
public class TestGenerationChunkGeneratorTests {
|
||||||
|
|
||||||
|
@UnitTest
|
||||||
|
@FastTest
|
||||||
|
public void getSurfaceWeight_ValueTests(){
|
||||||
|
assertEquals(0.5,TestGenerationChunkGenerator.getSurfaceWeight(0.5, 0, 1));
|
||||||
|
assertEquals(0.1,TestGenerationChunkGenerator.getSurfaceWeight(0.1, 0, 1));
|
||||||
|
assertEquals(0.9,TestGenerationChunkGenerator.getSurfaceWeight(0.9, 0, 1));
|
||||||
|
assertEquals(0.95,TestGenerationChunkGenerator.getSurfaceWeight(1.9, 0, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user