diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index b5af1d32..7be26d70 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1406,7 +1406,10 @@ HillsGen visuals work Falling min frames to activate increased Reorganizing world creation ui file UI panel work +World creation options work +(04/02/2025) +Homogenous worlds actually generate-able diff --git a/src/main/java/electrosphere/client/ui/menu/mainmenu/worldgen/MenuWorldSelect.java b/src/main/java/electrosphere/client/ui/menu/mainmenu/worldgen/MenuWorldSelect.java index 41fa2aaa..d9683004 100644 --- a/src/main/java/electrosphere/client/ui/menu/mainmenu/worldgen/MenuWorldSelect.java +++ b/src/main/java/electrosphere/client/ui/menu/mainmenu/worldgen/MenuWorldSelect.java @@ -11,6 +11,8 @@ import electrosphere.engine.Globals; import electrosphere.engine.loadingthreads.LoadingThread; import electrosphere.engine.loadingthreads.LoadingThread.LoadingThreadType; import electrosphere.engine.signal.Signal.SignalType; +import electrosphere.entity.scene.RealmDescriptor; +import electrosphere.entity.scene.SceneFile; import electrosphere.entity.scene.SceneGenerator; import electrosphere.renderer.ui.elements.Button; import electrosphere.renderer.ui.elements.Div; @@ -113,7 +115,10 @@ public class MenuWorldSelect { TextInput worldNameInput = TextInput.createTextInput(); worldNameInput.setMinWidth(150); worldNameInput.setMaxWidthPercent(50); - worldNameInput.setText("World name"); + worldNameInput.setText(params.name); + worldNameInput.setOnValueChangeCallback((value) -> { + params.name = value.getAsString(); + }); worldNameInputContainer.addChild(worldNameInput); //text entry (world seed) @@ -124,7 +129,10 @@ public class MenuWorldSelect { TextInput worldSeedInput = TextInput.createTextInput(); worldSeedInput.setMinWidth(150); worldSeedInput.setMaxWidthPercent(50); - worldSeedInput.setText(System.currentTimeMillis() + ""); + worldSeedInput.setText(params.seed); + worldSeedInput.setOnValueChangeCallback((value) -> { + params.seed = value.getAsString(); + }); worldSeedInputContainer.addChild(worldSeedInput); Div worldTypeMenuButtonContainer = Div.createRow(); @@ -140,10 +148,29 @@ public class MenuWorldSelect { Div createButtonContainer = Div.createCol(); createButtonContainer.setMarginTop(20); createButtonContainer.addChild(Button.createButton("Create", () -> { - String saveName = worldNameInput.getText(); - String seed = worldSeedInput.getText(); + String saveName = params.name; + String seed = params.seed; + //create scene file + SceneFile sceneFile = SceneGenerator.createProceduralSceneFile(saveName, seed); + switch(params.worldType){ + case 0: { + sceneFile.getRealmDescriptor().setWorldType(RealmDescriptor.PROCEDURAL_TYPE_DEFAULT); + } break; + case 1: { + sceneFile.getRealmDescriptor().setWorldType(RealmDescriptor.PROCEDURAL_TYPE_HOMOGENOUS); + + //set biome as well + List biomes = Globals.gameConfigCurrent.getBiomeMap().getSurfaceBiomes().stream().map((biome) -> { + return biome.getId(); + }).collect(Collectors.toList()); + sceneFile.getRealmDescriptor().setBiomeType(biomes.get(params.biomeType)); + } break; + default: { + throw new Error("Unhandled world type!"); + } + } //create save dir - SaveUtils.createOrOverwriteSave(saveName, SceneGenerator.createProceduralSceneFile(saveName, seed)); + SaveUtils.createOrOverwriteSave(saveName, sceneFile); WindowUtils.replaceMainMenuContents(MenuWorldSelect.createWorldSelectMenu()); })); @@ -270,6 +297,8 @@ public class MenuWorldSelect { static class WorldGenUIParams { int worldType = 0; int biomeType = 0; + String name = "World name"; + String seed = System.currentTimeMillis() + ""; } } diff --git a/src/main/java/electrosphere/entity/scene/RealmDescriptor.java b/src/main/java/electrosphere/entity/scene/RealmDescriptor.java index 7547a8b5..8b93a877 100644 --- a/src/main/java/electrosphere/entity/scene/RealmDescriptor.java +++ b/src/main/java/electrosphere/entity/scene/RealmDescriptor.java @@ -12,6 +12,12 @@ public class RealmDescriptor { public static final String REALM_DESCRIPTOR_PROCEDURAL = "procedural"; public static final String REALM_DESCRIPTOR_GENERATION_TESTING = "generationTesting"; + /** + * Types of procedural world terrain + */ + public static final String PROCEDURAL_TYPE_DEFAULT = "proceduralTypeDefault"; + public static final String PROCEDURAL_TYPE_HOMOGENOUS = "proceduralTypeHomogenous"; + /** * The dirt voxel type's id */ @@ -32,6 +38,16 @@ public class RealmDescriptor { */ Integer baseVoxel = VOXEL_DIRT_ID; + /** + * The type of world + */ + String worldType = PROCEDURAL_TYPE_DEFAULT; + + /** + * The type of biome for a homogenous world type + */ + String biomeType = ""; + /** * Gets the type of realm @@ -81,4 +97,38 @@ public class RealmDescriptor { this.baseVoxel = voxelId; } + /** + * Gets the type of the world + * @return The type of the world + */ + public String getWorldType() { + return worldType; + } + + /** + * Sets the type of the world + * @param worldType The type of the world + */ + public void setWorldType(String worldType) { + this.worldType = worldType; + } + + /** + * Gets the type of biome for a homogenous world + * @return The biome + */ + public String getBiomeType() { + return biomeType; + } + + /** + * Sets the biome type for a homogenous world + * @param biomeType The biome type + */ + public void setBiomeType(String biomeType) { + this.biomeType = biomeType; + } + + + } diff --git a/src/main/java/electrosphere/game/data/biome/BiomeTypeMap.java b/src/main/java/electrosphere/game/data/biome/BiomeTypeMap.java index f4a4baa2..1ab50b56 100644 --- a/src/main/java/electrosphere/game/data/biome/BiomeTypeMap.java +++ b/src/main/java/electrosphere/game/data/biome/BiomeTypeMap.java @@ -24,6 +24,11 @@ public class BiomeTypeMap { */ Map indexBiomeMap = new HashMap(); + /** + * The map of biome data -> index + */ + Map biomeIndexMap = new HashMap(); + /** * The list of surface biomes */ @@ -57,6 +62,7 @@ public class BiomeTypeMap { this.subterraneanBiomes.add(biome); } indexBiomeMap.put(indexBiomeMap.size(),biome); + biomeIndexMap.put(biome,indexBiomeMap.size()); } /** @@ -153,4 +159,13 @@ public class BiomeTypeMap { return indexBiomeMap.get(index); } + /** + * Gets the index of a given biome + * @param biome The biome + * @return The index of the biome + */ + public Integer getIndexOfBiome(BiomeData biome){ + return biomeIndexMap.get(biome); + } + } diff --git a/src/main/java/electrosphere/server/saves/SaveUtils.java b/src/main/java/electrosphere/server/saves/SaveUtils.java index 83a7af31..e628b3ea 100644 --- a/src/main/java/electrosphere/server/saves/SaveUtils.java +++ b/src/main/java/electrosphere/server/saves/SaveUtils.java @@ -116,7 +116,7 @@ public class SaveUtils { FileUtils.serializeObjectToSavePath(saveName, "./world.json", serverWorldData); //terrain manager ServerTerrainManager serverTerrainManager = new ServerTerrainManager(serverWorldData, sceneFile.getSeed(), new TestGenerationChunkGenerator(serverWorldData, false)); - serverTerrainManager.generate(); + serverTerrainManager.generate(sceneFile.getRealmDescriptor()); serverTerrainManager.save(saveName); //fluid manager ServerFluidManager serverFluidManager = new ServerFluidManager(serverWorldData, serverTerrainManager, 0, new DefaultFluidGenerator()); diff --git a/src/main/java/electrosphere/server/terrain/generation/macro/HomogenousMacroGenerator.java b/src/main/java/electrosphere/server/terrain/generation/macro/HomogenousMacroGenerator.java new file mode 100644 index 00000000..8575aa2f --- /dev/null +++ b/src/main/java/electrosphere/server/terrain/generation/macro/HomogenousMacroGenerator.java @@ -0,0 +1,45 @@ +package electrosphere.server.terrain.generation.macro; + +import electrosphere.engine.Globals; +import electrosphere.game.data.biome.BiomeData; +import electrosphere.game.data.biome.BiomeTypeMap; +import electrosphere.server.terrain.models.TerrainModel; + +/** + * Generates a world that is a single biome + */ +public class HomogenousMacroGenerator implements MacroGenerator { + + /** + * ID of the biome to generate with + */ + int biomeId = 0; + + /** + * Constructor + * @param biomeId The biome to use when creating the world + */ + public HomogenousMacroGenerator(String biomeId){ + BiomeTypeMap biomeTypeMap = Globals.gameConfigCurrent.getBiomeMap(); + BiomeData biomeData = biomeTypeMap.getType(biomeId); + this.biomeId = biomeTypeMap.getIndexOfBiome(biomeData); + } + + @Override + public void generate(TerrainModel model) { + int DIM = model.getDiscreteArrayDimension(); + float[][] elevation = model.getElevation(); + short[][] biome = model.getBiome(); + + for(int x = 0; x < DIM; x++){ + for(int y = 0; y < DIM; y++){ + elevation[x][y] = 1; + biome[x][y] = (short)this.biomeId; + } + } + + model.setElevationArray(elevation); + model.setBiome(biome); + } + +} diff --git a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java index c5728471..b7591804 100644 --- a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java @@ -2,11 +2,14 @@ package electrosphere.server.terrain.manager; import electrosphere.client.terrain.cache.ChunkData; import electrosphere.engine.Globals; +import electrosphere.entity.scene.RealmDescriptor; import electrosphere.game.server.world.ServerWorldData; import electrosphere.server.terrain.diskmap.ChunkDiskMap; import electrosphere.server.terrain.generation.TestGenerationChunkGenerator; import electrosphere.server.terrain.generation.interfaces.ChunkGenerator; import electrosphere.server.terrain.generation.macro.DefaultMacroGenerator; +import electrosphere.server.terrain.generation.macro.HomogenousMacroGenerator; +import electrosphere.server.terrain.generation.macro.MacroGenerator; import electrosphere.server.terrain.models.TerrainModel; import electrosphere.server.terrain.models.TerrainModification; import electrosphere.util.FileUtils; @@ -106,6 +109,21 @@ public class ServerTerrainManager { this.chunkGenerator.setModel(this.model); this.chunkDiskMap = ChunkDiskMap.init(); } + + /** + * Generates a terrain model for the manager + * @param realmDescriptor The realm description to draw parameters from while generating + */ + public void generate(RealmDescriptor realmDescriptor){ + this.model = TerrainModel.create(this.seed); + MacroGenerator generator = new DefaultMacroGenerator(); + if(realmDescriptor.getWorldType().equals(RealmDescriptor.PROCEDURAL_TYPE_HOMOGENOUS)){ + generator = new HomogenousMacroGenerator(realmDescriptor.getBiomeType()); + } + generator.generate(this.model); + this.chunkGenerator.setModel(this.model); + this.chunkDiskMap = ChunkDiskMap.init(); + } /** * Saves the terrain model backing this manager to a save file