From e81b7612d7a5ec7cffe6b6ea225663d835181b8b Mon Sep 17 00:00:00 2001 From: dags- Date: Wed, 13 May 2020 17:22:34 +0100 Subject: [PATCH] break everything part 2 --- Engine | 2 +- FeatureManager | 2 +- TerraEngine | 1 - TerraForgedAPI/README.md | 23 - TerraForgedAPI/build.gradle | 70 -- .../api/material/state/StateTagPredicate.java | 21 - TerraForgedApp/build.gradle | 23 - .../main/java/com/terraforged/app/Applet.java | 161 ---- .../main/java/com/terraforged/app/Cache.java | 123 --- .../java/com/terraforged/app/Controller.java | 236 ------ .../main/java/com/terraforged/app/Main.java | 264 ------ .../com/terraforged/app/biome/BiomeColor.java | 59 -- .../terraforged/app/biome/BiomeProvider.java | 140 ---- .../java/com/terraforged/app/mesh/Mesh.java | 141 ---- .../com/terraforged/app/mesh/NoiseMesh.java | 67 -- .../terraforged/app/mesh/TestRenderer.java | 58 -- .../app/renderer/MeshRenderer.java | 75 -- .../terraforged/app/renderer/Renderer.java | 133 --- .../app/renderer/VoxelRenderer.java | 155 ---- .../com/terraforged/app/util/JsonReader.java | 63 -- .../java/com/terraforged/app/util/Loader.java | 28 - .../src/main/resources/biome_data.json | 764 ------------------ .../src/main/resources/biome_groups.json | 168 ---- TerraForgedApp/src/main/resources/grass.png | Bin 7146 -> 0 bytes TerraForgedApp/src/main/resources/license.txt | 21 - TerraForgedCore/build.gradle | 31 - .../java/com/terraforged/core/cell/Cell.java | 136 ---- .../com/terraforged/core/cell/Extent.java | 33 - .../com/terraforged/core/cell/Populator.java | 45 -- .../java/com/terraforged/core/cell/Tag.java | 31 - .../com/terraforged/core/filter/Erosion.java | 291 ------- .../com/terraforged/core/filter/Filter.java | 47 -- .../terraforged/core/filter/Filterable.java | 39 - .../com/terraforged/core/filter/Modifier.java | 61 -- .../terraforged/core/filter/Smoothing.java | 90 --- .../terraforged/core/filter/Steepness.java | 79 -- .../com/terraforged/core/module/Blender.java | 116 --- .../terraforged/core/module/MultiBlender.java | 122 --- .../com/terraforged/core/module/Select.java | 43 - .../com/terraforged/core/region/Region.java | 404 --------- .../core/region/RegionFactory.java | 8 - .../com/terraforged/core/region/Size.java | 75 -- .../core/region/chunk/ChunkGenTask.java | 48 -- .../core/region/chunk/ChunkHolder.java | 40 - .../core/region/chunk/ChunkReader.java | 76 -- .../core/region/chunk/ChunkWriter.java | 42 - .../core/region/chunk/ChunkZoomTask.java | 51 -- .../core/region/gen/FutureRegion.java | 57 -- .../core/region/gen/FutureRegionZoom.java | 61 -- .../core/region/gen/GenContext.java | 21 - .../core/region/gen/RegionCache.java | 105 --- .../core/region/gen/RegionCacheFactory.java | 33 - .../core/region/gen/RegionGenerator.java | 204 ----- .../core/region/legacy/LegacyRegion.java | 27 - .../core/settings/BiomeSettings.java | 104 --- .../core/settings/ClimateSettings.java | 54 -- .../core/settings/FilterSettings.java | 70 -- .../core/settings/GeneratorSettings.java | 136 ---- .../core/settings/RiverSettings.java | 128 --- .../terraforged/core/settings/Settings.java | 44 - .../core/settings/TerrainSettings.java | 91 --- .../terraforged/core/util/PosIterator.java | 156 ---- .../java/com/terraforged/core/util/Seed.java | 67 -- .../core/util/VariablePredicate.java | 56 -- .../core/util/concurrent/Disposable.java | 11 - .../core/util/concurrent/ObjectPool.java | 103 --- .../core/util/concurrent/ThreadPool.java | 114 --- .../core/util/concurrent/WorkerFactory.java | 42 - .../util/concurrent/batcher/AsyncBatcher.java | 67 -- .../core/util/concurrent/batcher/Batcher.java | 38 - .../util/concurrent/batcher/SyncBatcher.java | 50 -- .../core/util/concurrent/cache/Cache.java | 46 -- .../util/concurrent/cache/CacheEntry.java | 48 -- .../util/concurrent/cache/ExpiringEntry.java | 6 - .../concurrent/cache/SynchronizedLongMap.java | 54 -- .../terraforged/core/util/grid/FixedGrid.java | 163 ---- .../terraforged/core/util/grid/FixedList.java | 96 --- .../core/util/grid/MappedList.java | 50 -- .../terraforged/core/util/points/Poisson.java | 76 -- .../serialization/annotation/Comment.java | 38 - .../util/serialization/annotation/Name.java | 38 - .../util/serialization/annotation/Option.java | 37 - .../util/serialization/annotation/Range.java | 40 - .../annotation/Serializable.java | 36 - .../serializer/Deserializer.java | 116 --- .../util/serialization/serializer/Reader.java | 83 -- .../serialization/serializer/Serializer.java | 191 ----- .../util/serialization/serializer/Writer.java | 49 -- .../core/world/GeneratorContext.java | 66 -- .../core/world/WorldDecorators.java | 51 -- .../terraforged/core/world/WorldFilters.java | 57 -- .../core/world/WorldGenerator.java | 53 -- .../core/world/WorldGeneratorFactory.java | 73 -- .../core/world/biome/BiomeData.java | 159 ---- .../core/world/biome/BiomeManager.java | 35 - .../core/world/biome/BiomeType.java | 140 ---- .../core/world/biome/BiomeTypeColors.java | 75 -- .../core/world/biome/BiomeTypeLoader.java | 204 ----- .../core/world/climate/Climate.java | 111 --- .../core/world/climate/ClimateModule.java | 166 ---- .../core/world/climate/Compressor.java | 81 -- .../world/continent/ContinentLerper2.java | 103 --- .../world/continent/ContinentLerper3.java | 120 --- .../core/world/continent/ContinentModule.java | 166 ---- .../core/world/decorator/Decorator.java | 34 - .../core/world/decorator/DesertDunes.java | 78 -- .../core/world/decorator/DesertStacks.java | 84 -- .../core/world/decorator/Wetlands.java | 106 --- .../core/world/geology/DepthBuffer.java | 31 - .../core/world/geology/Geology.java | 62 -- .../core/world/geology/Strata.java | 128 --- .../core/world/geology/Stratum.java | 65 -- .../core/world/heightmap/Heightmap.java | 82 -- .../core/world/heightmap/Levels.java | 89 -- .../core/world/heightmap/RegionConfig.java | 45 -- .../core/world/heightmap/RegionExtent.java | 82 -- .../core/world/heightmap/WorldHeightmap.java | 235 ------ .../core/world/heightmap/WorldLookup.java | 46 -- .../core/world/rivermap/PosGenerator.java | 227 ------ .../core/world/rivermap/RiverMap.java | 139 ---- .../core/world/rivermap/RiverMapConfig.java | 21 - .../core/world/rivermap/RiverRegionList.java | 35 - .../core/world/rivermap/lake/Lake.java | 106 --- .../core/world/rivermap/lake/LakeConfig.java | 76 -- .../core/world/rivermap/river/River.java | 201 ----- .../world/rivermap/river/RiverBounds.java | 91 --- .../world/rivermap/river/RiverConfig.java | 142 ---- .../core/world/rivermap/river/RiverNode.java | 73 -- .../world/rivermap/river/RiverRegion.java | 311 ------- .../core/world/terrain/LandForms.java | 264 ------ .../core/world/terrain/Terrain.java | 201 ----- .../core/world/terrain/TerrainPopulator.java | 67 -- .../core/world/terrain/Terrains.java | 144 ---- .../core/world/terrain/VolcanoPopulator.java | 141 ---- .../provider/StandardTerrainProvider.java | 167 ---- .../terrain/provider/TerrainProvider.java | 86 -- .../provider/TerrainProviderFactory.java | 35 - .../world/terrain/region/RegionLerper.java | 73 -- .../world/terrain/region/RegionModule.java | 135 ---- .../world/terrain/region/RegionSelector.java | 103 --- TerraForgedCore/src/main/resources/biomes.png | Bin 14615 -> 0 bytes TerraForgedCore/src/main/resources/biomes.txt | 13 - .../src/main/resources/license.txt | 21 - .../src/main/resources/terraforged.png | Bin 27685 -> 0 bytes TerraForgedMod/README.md | 56 -- TerraForgedMod/build.gradle | 103 --- TerraForgedMod/gradlew | 172 ---- TerraForgedMod/gradlew.bat | 84 -- TerraForgedMod/psd/biomes.psd | Bin 179445 -> 0 bytes TerraForgedMod/psd/icon.png | Bin 27685 -> 0 bytes TerraForgedMod/psd/terraforged.psd | Bin 307313 -> 0 bytes .../biome/provider/TerraBiomeRegistry.java | 58 -- .../terraforged/mod/chunk/ChunkProcessor.java | 12 - .../mod/chunk/ObfHelperChunkGenerator.java | 155 ---- .../mod/chunk/TerraChunkGenerator.java | 407 ---------- .../mod/chunk/TerraGenSettings.java | 42 - .../terraforged/mod/command/Permissions.java | 10 - .../mod/data/WorldGenFeatures.java | 133 --- .../feature/decorator/poisson/Poisson.java | 173 ---- .../decorator/poisson/PoissonContext.java | 25 - .../mod/feature/tree/SaplingConfig.java | 122 --- .../mod/feature/tree/SaplingFeature.java | 66 -- .../mod/feature/tree/SaplingListener.java | 154 ---- .../mod/feature/tree/SaplingManager.java | 90 --- .../mod/feature/tree/SaplingPlacer.java | 149 ---- .../mod/feature/tree/TreeGrowBuffer.java | 126 --- .../mod/gui/page/DimensionsPage.java | 68 -- .../terraforged/mod/gui/page/FilterPage.java | 67 -- .../mod/gui/page/GeneratorPage.java | 66 -- .../terraforged/mod/util/nbt/NBTWriter.java | 132 --- .../assets/terraforged/lang/en_us.json | 12 - .../terraforged/features/trees/birch_oak.json | 57 -- .../features/trees/flower_forest.json | 55 -- .../features/trees/jungle_edge.json | 45 -- .../features/trees/oak_forest.json | 45 -- .../terraforged/features/trees/redwood.json | 49 -- .../mushrooms/brown/brown_mushroom_1.nbt | Bin 275 -> 0 bytes .../mushrooms/brown/brown_mushroom_2.nbt | Bin 360 -> 0 bytes .../mushrooms/brown/brown_mushroom_3.nbt | Bin 350 -> 0 bytes .../mushrooms/brown/brown_mushroom_4.nbt | Bin 309 -> 0 bytes .../mushrooms/brown/brown_mushroom_5.nbt | Bin 378 -> 0 bytes .../mushrooms/brown/brown_mushroom_7.nbt | Bin 300 -> 0 bytes .../mushrooms/brown/brown_musroom_6.nbt | Bin 273 -> 0 bytes .../mushrooms/red/red_mushroom_1.nbt | Bin 367 -> 0 bytes .../mushrooms/red/red_mushroom_2.nbt | Bin 316 -> 0 bytes .../mushrooms/red/red_mushroom_3.nbt | Bin 366 -> 0 bytes .../mushrooms/red/red_mushroom_4.nbt | Bin 286 -> 0 bytes .../mushrooms/red/red_mushroom_5.nbt | Bin 413 -> 0 bytes .../trees/acacia/bush/acacia_bush_1.nbt | Bin 684 -> 0 bytes .../trees/acacia/bush/acacia_bush_2.nbt | Bin 684 -> 0 bytes .../trees/acacia/large/acacia_1.nbt | Bin 500 -> 0 bytes .../trees/acacia/large/acacia_2.nbt | Bin 567 -> 0 bytes .../trees/acacia/small/acacia_small_1.nbt | Bin 530 -> 0 bytes .../trees/acacia/small/acacia_small_2.nbt | Bin 510 -> 0 bytes .../trees/birch/forest/forest_birch_1.nbt | Bin 627 -> 0 bytes .../trees/birch/forest/forest_birch_2.nbt | Bin 550 -> 0 bytes .../trees/birch/forest/forest_birch_3.nbt | Bin 577 -> 0 bytes .../trees/birch/forest/forest_birch_4.nbt | Bin 798 -> 0 bytes .../structures/trees/birch/large/birch_1.nbt | Bin 351 -> 0 bytes .../structures/trees/birch/large/birch_2.nbt | Bin 298 -> 0 bytes .../structures/trees/birch/large/birch_3.nbt | Bin 608 -> 0 bytes .../trees/birch/small/birch_bush_1.nbt | Bin 302 -> 0 bytes .../trees/birch/small/birch_bush_2.nbt | Bin 316 -> 0 bytes .../trees/birch/small/birch_small_1.nbt | Bin 439 -> 0 bytes .../trees/birch/small/birch_small_2.nbt | Bin 435 -> 0 bytes .../trees/dark_oak/large/dark_oak_tall_1.nbt | Bin 651 -> 0 bytes .../trees/dark_oak/large/dark_oak_tall_2.nbt | Bin 711 -> 0 bytes .../trees/dark_oak/large/dark_oak_tall_3.nbt | Bin 581 -> 0 bytes .../trees/dark_oak/large/dark_oak_tall_4.nbt | Bin 904 -> 0 bytes .../trees/dark_oak/large/dark_oak_tall_5.nbt | Bin 798 -> 0 bytes .../trees/dark_oak/small/dark_oak_1.nbt | Bin 759 -> 0 bytes .../trees/dark_oak/small/dark_oak_2.nbt | Bin 696 -> 0 bytes .../trees/dark_oak/small/dark_oak_3.nbt | Bin 744 -> 0 bytes .../trees/dark_oak/small/dark_oak_bush_1.nbt | Bin 390 -> 0 bytes .../trees/dark_oak/small/dark_oak_bush_2.nbt | Bin 401 -> 0 bytes .../trees/jungle/huge/jungle_massive_1.nbt | Bin 2227 -> 0 bytes .../trees/jungle/huge/jungle_massive_2.nbt | Bin 1804 -> 0 bytes .../trees/jungle/huge/jungle_massive_3.nbt | Bin 2371 -> 0 bytes .../trees/jungle/huge/jungle_massive_4.nbt | Bin 2543 -> 0 bytes .../trees/jungle/huge/jungle_massive_5.nbt | Bin 2213 -> 0 bytes .../trees/jungle/huge/jungle_massive_6.nbt | Bin 2505 -> 0 bytes .../trees/jungle/large/jungle_tall_1.nbt | Bin 1595 -> 0 bytes .../trees/jungle/large/jungle_tall_2.nbt | Bin 1801 -> 0 bytes .../trees/jungle/large/jungle_tall_3.nbt | Bin 1873 -> 0 bytes .../trees/jungle/large/jungle_tall_4.nbt | Bin 1721 -> 0 bytes .../trees/jungle/small/jungle_small_1.nbt | Bin 844 -> 0 bytes .../trees/jungle/small/jungle_small_2.nbt | Bin 704 -> 0 bytes .../trees/jungle/small/jungle_small_3.nbt | Bin 734 -> 0 bytes .../trees/oak/forest/forest_oak_1.nbt | Bin 585 -> 0 bytes .../trees/oak/forest/forest_oak_2.nbt | Bin 582 -> 0 bytes .../structures/trees/oak/huge/oak_big_1.nbt | Bin 1699 -> 0 bytes .../structures/trees/oak/huge/oak_big_2.nbt | Bin 1267 -> 0 bytes .../structures/trees/oak/large/oak_1.nbt | Bin 530 -> 0 bytes .../structures/trees/oak/large/oak_2.nbt | Bin 530 -> 0 bytes .../structures/trees/oak/large/oak_3.nbt | Bin 772 -> 0 bytes .../structures/trees/oak/large/oak_4.nbt | Bin 579 -> 0 bytes .../structures/trees/oak/large/oak_5.nbt | Bin 1089 -> 0 bytes .../structures/trees/oak/small/oak_bush_1.nbt | Bin 298 -> 0 bytes .../structures/trees/oak/small/oak_bush_2.nbt | Bin 314 -> 0 bytes .../trees/oak/small/oak_small_1.nbt | Bin 336 -> 0 bytes .../trees/oak/small/oak_small_2.nbt | Bin 327 -> 0 bytes .../trees/oak/small/oak_small_3.nbt | Bin 337 -> 0 bytes .../trees/oak/small/oak_small_4.nbt | Bin 354 -> 0 bytes .../trees/pine/huangshan_pine_1.nbt | Bin 567 -> 0 bytes .../trees/pine/huangshan_pine_2.nbt | Bin 446 -> 0 bytes .../trees/pine/huangshan_pine_3.nbt | Bin 478 -> 0 bytes .../structures/trees/pine/scots_pine_1.nbt | Bin 654 -> 0 bytes .../structures/trees/pine/scots_pine_2.nbt | Bin 705 -> 0 bytes .../trees/pine/scots_pine_small_1.nbt | Bin 651 -> 0 bytes .../trees/pine/scots_pine_small_2.nbt | Bin 622 -> 0 bytes .../structures/trees/pine/stone_pine_1.nbt | Bin 618 -> 0 bytes .../structures/trees/pine/stone_pine_2.nbt | Bin 671 -> 0 bytes .../trees/redwood/huge/redwood_massive_1.nbt | Bin 1059 -> 0 bytes .../trees/redwood/huge/redwood_massive_2.nbt | Bin 1290 -> 0 bytes .../trees/redwood/huge/redwood_massive_3.nbt | Bin 1320 -> 0 bytes .../trees/redwood/huge/redwood_massive_4.nbt | Bin 999 -> 0 bytes .../trees/redwood/huge/redwood_massive_5.nbt | Bin 950 -> 0 bytes .../trees/redwood/huge/redwood_massive_6.nbt | Bin 1579 -> 0 bytes .../trees/redwood/large/redwood_tall_1.nbt | Bin 927 -> 0 bytes .../trees/redwood/large/redwood_tall_2.nbt | Bin 921 -> 0 bytes .../trees/redwood/large/redwood_tall_3.nbt | Bin 1097 -> 0 bytes .../trees/redwood/large/redwood_tall_4.nbt | Bin 631 -> 0 bytes .../trees/spruce/bush/spruce_bush_1.nbt | Bin 316 -> 0 bytes .../trees/spruce/bush/spruce_bush_2.nbt | Bin 279 -> 0 bytes .../trees/spruce/large/spruce_1.nbt | Bin 720 -> 0 bytes .../trees/spruce/large/spruce_2.nbt | Bin 409 -> 0 bytes .../trees/spruce/large/spruce_3.nbt | Bin 398 -> 0 bytes .../trees/spruce/large/spruce_4.nbt | Bin 384 -> 0 bytes .../trees/spruce/large/spruce_5.nbt | Bin 347 -> 0 bytes .../trees/spruce/small/spruce_small_1.nbt | Bin 308 -> 0 bytes .../trees/spruce/small/spruce_small_2.nbt | Bin 409 -> 0 bytes .../trees/spruce/small/spruce_small_3.nbt | Bin 337 -> 0 bytes .../trees/spruce/small/spruce_small_4.nbt | Bin 402 -> 0 bytes .../willow/large/weeping_willow_big_1.nbt | Bin 1419 -> 0 bytes .../willow/large/weeping_willow_big_2.nbt | Bin 1233 -> 0 bytes .../willow/small/weeping_willow_small_1.nbt | Bin 863 -> 0 bytes .../willow/small/weeping_willow_small_2.nbt | Bin 867 -> 0 bytes .../templates/trees/birch_forest.json | 13 - .../templates/trees/birch_large.json | 13 - .../templates/trees/oak_forest.json | 13 - .../terraforged/templates/trees/oak_huge.json | 13 - .../templates/trees/oak_large.json | 13 - TerraForgedMod/src/main/resources/license.txt | 21 - .../src/main/resources/terraforged.png | Bin 35748 -> 0 bytes build.gradle | 116 ++- gradle.properties | 2 +- settings.gradle | 3 +- .../com/terraforged/api/biome/BiomeTags.java | 2 +- .../terraforged/api/biome/BiomeVariant.java | 6 + .../modifier/AbstractMaxHeightModifier.java | 9 +- .../modifier/AbstractOffsetModifier.java | 7 +- .../api/biome/modifier/BiomeModifier.java | 3 +- .../api/biome/modifier/ModifierManager.java | 0 .../terraforged/api/chunk/ChunkContext.java | 0 .../terraforged/api/chunk/ChunkDelegate.java | 0 .../api/chunk/column/ColumnDecorator.java | 0 .../api/chunk/column/DecoratorContext.java | 11 +- .../api/chunk/column/DecoratorManager.java | 0 .../api/chunk/surface/CachedSurface.java | 0 .../api/chunk/surface/ChunkSurfaceBuffer.java | 0 .../api/chunk/surface/Surface.java | 0 .../api/chunk/surface/SurfaceContext.java | 6 +- .../api/chunk/surface/SurfaceManager.java | 30 +- .../api/chunk/surface/builder/Combiner.java | 0 .../api/chunk/surface/builder/Delegate.java | 0 .../com/terraforged/api/event/SetupEvent.java | 6 +- .../com/terraforged/api/material/WGTags.java | 7 +- .../api/material/geology/GeologyManager.java | 4 +- .../api/material/geology/StrataConfig.java | 0 .../api/material/geology/StrataGenerator.java | 2 +- .../api/material/layer/LayerManager.java | 0 .../api/material/layer/LayerMaterial.java | 0 .../api/material/state/CachedState.java | 0 .../api/material/state/DefaultState.java | 0 .../api/material/state/StateSupplier.java | 0 .../api/material/state/States.java | 0 .../main/java/com/terraforged/mod/Log.java | 0 .../com/terraforged/mod/TerraForgedMod.java | 13 +- .../java/com/terraforged/mod/TerraWorld.java | 21 +- .../com/terraforged/mod/biome/ColdSteppe.java | 19 +- .../java/com/terraforged/mod/biome/Dunes.java | 54 ++ .../com/terraforged/mod/biome/FirForest.java | 0 .../terraforged/mod/biome/FlowerPlains.java | 0 .../com/terraforged/mod/biome/FrozenLake.java | 75 ++ .../java/com/terraforged/mod/biome/Lake.java | 80 ++ .../com/terraforged/mod/biome/Marshland.java | 0 .../com/terraforged/mod/biome/ModBiomes.java | 10 +- .../terraforged/mod/biome/SavannaScrub.java | 2 +- .../mod/biome/ShatteredSavannaScrub.java | 2 + .../terraforged/mod/biome/SnowyFirForest.java | 60 ++ .../mod/biome/SnowyTaigaScrub.java | 0 .../com/terraforged/mod/biome/Steppe.java | 22 +- .../com/terraforged/mod/biome/TaigaScrub.java | 0 .../com/terraforged/mod/biome/WarmBeach.java | 0 .../mod/biome/map/AbstractBiomeMap.java | 17 +- .../mod/biome/map/BasicBiomeMap.java | 2 +- .../terraforged/mod/biome/map/BiomeGroup.java | 0 .../terraforged/mod/biome/map/BiomeMap.java | 9 +- .../mod/biome/map/BiomeMapBuilder.java | 16 +- .../mod/biome/map/BiomePredicate.java | 18 +- .../mod/biome/map/DefaultBiome.java | 0 .../mod/biome/map/GridBiomeMap.java | 2 +- .../modifier/AbstractMaxHeightModifier.java | 9 +- .../modifier/AbstractOffsetModifier.java | 7 +- .../mod/biome/modifier/BeachModifier.java | 18 +- .../biome/modifier/BiomeModifierManager.java | 7 +- .../biome/modifier/DesertColorModifier.java | 3 +- .../mod/biome/modifier/SandBiomeModifier.java | 9 +- .../biome/provider/AbstractBiomeProvider.java | 16 +- .../mod/biome/provider/BiomeHelper.java | 67 +- .../mod/biome/provider/BiomeProvider.java | 74 +- .../mod/biome/provider/BiomeWeights.java | 51 ++ .../mod/biome/provider/DesertBiomes.java | 4 +- .../mod/biome/spawn/SpawnHandler.java | 13 +- .../mod/biome/spawn/SpawnSearch.java | 9 +- .../mod/biome/surface/DunesSurface.java | 25 +- .../mod/biome/surface/IcebergsSurface.java | 10 +- .../mod/biome/surface/SteppeSurface.java | 30 + .../mod/biome/surface/SwampSurface.java | 34 + .../mod/biome/tag/BiomeTagManager.java | 0 .../mod/chunk/ChunkGeneratorFactory.java | 0 .../mod/chunk/TerraChunkGenerator.java | 240 ++++++ .../terraforged/mod/chunk/TerraContext.java | 37 +- .../mod/chunk/TerraGenSettings.java | 92 +++ .../mod/chunk/TerraTerrainProvider.java | 6 +- .../mod/chunk/component/BiomeGenerator.java | 39 + .../mod/chunk/component/MobGenerator.java | 69 ++ .../chunk/component/StructureGenerator.java | 85 ++ .../mod/chunk/component/TerrainCarver.java | 57 ++ .../mod/chunk/component/TerrainGenerator.java | 143 ++++ .../mod/chunk/fix/ChunkCarverFix.java | 0 .../mod/chunk/fix/RegionDelegate.java | 32 +- .../terraforged/mod/chunk/fix/RegionFix.java | 0 .../terraforged/mod/chunk/fix/SpawnFix.java | 0 .../com/terraforged/mod/chunk/test/Test.java | 10 +- .../mod/chunk/test/TestBiomeProvider.java | 3 +- .../mod/chunk/test/TestChunkGenerator.java | 25 +- .../mod/chunk/test/TestHeightMap.java | 27 + .../mod/chunk/test/TestTerraContext.java | 17 + .../mod/chunk/util}/FastChunk.java | 2 +- .../mod/chunk/util}/TerraContainer.java | 5 +- .../mod/chunk/util/TerraHooks.java | 122 +++ .../terraforged/mod/command/TerraCommand.java | 93 +-- .../mod/command/arg/BiomeArgType.java | 47 +- .../mod/command/arg/TerrainArgType.java | 31 +- .../mod/command/search/BiomeSearchTask.java | 0 .../mod/command/search/BothSearchTask.java | 0 .../mod/command/search/Search.java | 16 +- .../mod/command/search/TerrainSearchTask.java | 8 +- .../com/terraforged/mod/data/DataGen.java | 0 .../terraforged/mod/data/DataGenerator.java | 92 +++ .../terraforged/mod/data/WorldGenBiomes.java | 2 +- .../terraforged/mod/data/WorldGenBlocks.java | 0 .../mod/data/WorldGenFeatures.java | 68 ++ .../mod/decorator/ChunkPopulator.java | 2 +- .../mod/decorator/feature/LayerDecorator.java | 4 +- .../mod/decorator/feature/SnowEroder.java | 4 +- .../decorator/terrain}/BedrockDecorator.java | 8 +- .../decorator/terrain}/CoastDecorator.java | 6 +- .../decorator/terrain}/ErosionDecorator.java | 10 +- .../decorator/terrain}/GeologyDecorator.java | 2 +- .../mod/feature/BlockDataConfig.java | 16 + .../mod/feature/BlockDataManager.java | 35 + .../com/terraforged/mod/feature/Matchers.java | 13 +- .../mod/feature/TerrainHelper.java | 0 .../mod/feature/context/ChanceContext.java | 83 ++ .../context/ContextSelectorConfig.java | 28 + .../context/ContextSelectorFeature.java | 45 ++ .../feature/context/ContextualFeature.java | 81 ++ .../mod/feature/context/modifier/Biome.java | 29 + .../context/modifier/ContextModifier.java | 34 + .../feature/context/modifier/Elevation.java | 28 + .../mod/feature/context/modifier/None.java | 24 + .../modifier/RangeContextModifier.java | 30 + .../decorator/poisson/BiomeVariance.java | 4 +- .../decorator/poisson/PoissonAtSurface.java | 0 .../decorator/poisson/PoissonConfig.java | 0 .../decorator/poisson/PoissonDecorator.java | 2 + .../decorator/poisson/PoissonVisitor.java | 7 +- .../mod/feature/feature/DiskFeature.java | 0 .../mod/feature/predicate/TreeLine.java | 4 +- .../mod/feature/sapling/SaplingConfig.java | 103 +++ .../mod/feature/sapling/SaplingListener.java | 208 +++++ .../terraforged/mod/gui/OverlayRenderer.java | 0 .../terraforged/mod/gui/OverlayScreen.java | 0 .../com/terraforged/mod/gui/ScrollPane.java | 10 - .../terraforged/mod/gui/SettingsScreen.java | 62 +- .../terraforged/mod/gui/element/CheckBox.java | 0 .../terraforged/mod/gui/element/Element.java | 31 +- .../mod/gui/element/TerraButton.java | 0 .../mod/gui/element/TerraLabel.java | 8 - .../mod/gui/element/TerraSlider.java | 34 +- .../mod/gui/element/TerraTextInput.java | 10 +- .../mod/gui/element/TerraToggle.java | 19 +- .../terraforged/mod/gui/page/BasePage.java | 0 .../terraforged/mod/gui/page/ClimatePage.java | 2 +- .../terraforged/mod/gui/page/MiscPage.java | 15 +- .../com/terraforged/mod/gui/page/Page.java | 25 +- .../terraforged/mod/gui/page/PresetPage.java | 16 + .../terraforged/mod/gui/page/PresetsPage.java | 21 + .../terraforged/mod/gui/page/RiverPage.java | 2 +- .../mod/gui/page/StructurePage.java | 2 +- .../terraforged/mod/gui/page/TerrainPage.java | 2 +- .../terraforged/mod/gui/page/WorldPage.java | 105 +++ .../terraforged/mod/gui/preview/Preview.java | 56 +- .../mod/gui/preview/PreviewPage.java | 2 +- .../mod/gui/preview/PreviewSettings.java | 7 +- .../mod/gui/preview/RenderMode.java | 19 +- .../mod/material/MaterialHelper.java | 2 +- .../terraforged/mod/material/Materials.java | 0 .../mod/material/geology/GeoGenerator.java | 2 +- .../mod/material/geology/GeoManager.java | 8 +- .../mod/settings/DimesionSettings.java | 10 +- .../mod/settings/Miscellaneous.java | 6 +- .../mod/settings/SettingsHelper.java | 29 +- .../mod/settings/StructureSettings.java | 55 +- .../mod/settings/TerraSettings.java | 6 +- .../terraforged/mod/util/DataPackFinder.java | 0 .../mod/util/DummyBlockReader.java | 2 +- .../com/terraforged/mod/util/Environment.java | 0 .../com/terraforged/mod/util/ListUtils.java | 0 .../terraforged/mod/util/NBTLeavesFixer.java | 0 .../terraforged/mod/util/RangeModifier.java | 35 + .../terraforged/mod/util/annotation/Name.java | 0 .../terraforged/mod/util/annotation/Ref.java | 0 .../terraforged/mod/util/nbt/NBTHelper.java | 19 +- .../terraforged/mod/util/nbt/NBTReader.java | 2 +- .../terraforged/mod/util/nbt/NBTWriter.java | 66 ++ .../mod/util/setup/SetupDebug.java | 0 .../mod/util/setup/SetupHooks.java | 6 +- .../main/resources/META-INF/mods.toml | 0 .../src => src}/main/resources/biomes.txt | 0 .../data/forge/tags/blocks/wg_clay.json | 0 .../data/forge/tags/blocks/wg_dirt.json | 0 .../data/forge/tags/blocks/wg_erodible.json | 0 .../data/forge/tags/blocks/wg_sediment.json | 0 .../data/forge/tags/blocks/wg_stone.json | 0 .../blocks/saplings/birch_sapling.json | 12 + .../blocks/saplings/jungle_sapling.json | 17 + .../blocks/saplings/oak_sapling.json | 12 + .../data/terraforged/features/ores/coal.json | 0 .../terraforged/features/ores/diamond.json | 0 .../data/terraforged/features/ores/gold.json | 0 .../terraforged/features/ores/gold_extra.json | 0 .../data/terraforged/features/ores/iron.json | 0 .../data/terraforged/features/ores/lapis.json | 0 .../terraforged/features/ores/redstone.json | 0 .../terraforged/features/sediments/clay.json | 0 .../terraforged/features/sediments/dirt.json | 0 .../features/sediments/gravel.json | 0 .../features/shrubs/dead_bush.json | 0 .../features/shrubs/forest_grass.json | 0 .../terraforged/features/trees/acacia.json | 18 +- .../terraforged/features/trees/birch.json | 28 +- .../terraforged/features/trees/birch_oak.json | 69 ++ .../terraforged/features/trees/dark_oak.json | 40 +- .../features/trees/fir_foreset.json | 65 ++ .../features/trees/flower_forest.json | 69 ++ .../terraforged/features/trees/jungle.json | 34 +- .../features/trees/jungle_edge.json | 53 ++ .../features/trees/jungle_hills.json | 44 +- .../features/trees/oak_badlands.json | 12 +- .../features/trees/oak_forest.json | 52 ++ .../features/trees/oak_plains.json | 34 +- .../data/terraforged/features/trees/pine.json | 22 +- .../terraforged/features/trees/redwood.json | 59 ++ .../terraforged/features/trees/spruce.json | 22 +- .../features/trees/spruce_tundra.json | 12 +- .../terraforged/features/trees/willow.json | 18 +- .../mushrooms/brown/brown_mushroom_1.nbt | 0 .../mushrooms/brown/brown_mushroom_2.nbt | 0 .../mushrooms/brown/brown_mushroom_3.nbt | 0 .../mushrooms/brown/brown_mushroom_4.nbt | 0 .../mushrooms/brown/brown_mushroom_5.nbt | 0 .../mushrooms/brown/brown_mushroom_7.nbt | 0 .../mushrooms/brown/brown_musroom_6.nbt | 0 .../mushrooms/red/red_mushroom_1.nbt | 0 .../mushrooms/red/red_mushroom_2.nbt | 0 .../mushrooms/red/red_mushroom_3.nbt | 0 .../mushrooms/red/red_mushroom_4.nbt | 0 .../mushrooms/red/red_mushroom_5.nbt | 0 .../trees/acacia/bush/acacia_bush_1.nbt | 0 .../trees/acacia/bush/acacia_bush_2.nbt | 0 .../trees/acacia/large/acacia_1.nbt | 0 .../trees/acacia/large/acacia_2.nbt | 0 .../trees/acacia/small/acacia_small_1.nbt | 0 .../trees/acacia/small/acacia_small_2.nbt | 0 .../trees/birch/forest/forest_birch_1.nbt | 0 .../trees/birch/forest/forest_birch_2.nbt | 0 .../trees/birch/forest/forest_birch_3.nbt | 0 .../trees/birch/forest/forest_birch_4.nbt | 0 .../structures/trees/birch/large/birch_1.nbt | 0 .../structures/trees/birch/large/birch_2.nbt | 0 .../structures/trees/birch/large/birch_3.nbt | 0 .../trees/birch/small/birch_bush_1.nbt | 0 .../trees/birch/small/birch_bush_2.nbt | 0 .../trees/birch/small/birch_small_1.nbt | 0 .../trees/birch/small/birch_small_2.nbt | 0 .../trees/dark_oak/large/dark_oak_tall_1.nbt | 0 .../trees/dark_oak/large/dark_oak_tall_2.nbt | 0 .../trees/dark_oak/large/dark_oak_tall_3.nbt | 0 .../trees/dark_oak/large/dark_oak_tall_4.nbt | 0 .../trees/dark_oak/large/dark_oak_tall_5.nbt | 0 .../trees/dark_oak/small/dark_oak_1.nbt | 0 .../trees/dark_oak/small/dark_oak_2.nbt | 0 .../trees/dark_oak/small/dark_oak_3.nbt | 0 .../trees/dark_oak/small/dark_oak_bush_1.nbt | 0 .../trees/dark_oak/small/dark_oak_bush_2.nbt | 0 .../trees/jungle/huge/jungle_massive_1.nbt | 0 .../trees/jungle/huge/jungle_massive_2.nbt | 0 .../trees/jungle/huge/jungle_massive_3.nbt | 0 .../trees/jungle/huge/jungle_massive_4.nbt | 0 .../trees/jungle/huge/jungle_massive_5.nbt | 0 .../trees/jungle/huge/jungle_massive_6.nbt | 0 .../trees/jungle/large/jungle_tall_1.nbt | 0 .../trees/jungle/large/jungle_tall_2.nbt | 0 .../trees/jungle/large/jungle_tall_3.nbt | 0 .../trees/jungle/large/jungle_tall_4.nbt | 0 .../trees/jungle/small/jungle_small_1.nbt | 0 .../trees/jungle/small/jungle_small_2.nbt | 0 .../trees/jungle/small/jungle_small_3.nbt | 0 .../trees/oak/forest/forest_oak_1.nbt | 0 .../trees/oak/forest/forest_oak_2.nbt | 0 .../structures/trees/oak/huge/oak_big_1.nbt | 0 .../structures/trees/oak/huge/oak_big_2.nbt | 0 .../structures/trees/oak/large/oak_1.nbt | 0 .../structures/trees/oak/large/oak_2.nbt | 0 .../structures/trees/oak/large/oak_3.nbt | 0 .../structures/trees/oak/large/oak_4.nbt | 0 .../structures/trees/oak/large/oak_5.nbt | 0 .../structures/trees/oak/small/oak_bush_1.nbt | 0 .../structures/trees/oak/small/oak_bush_2.nbt | 0 .../trees/oak/small/oak_small_1.nbt | 0 .../trees/oak/small/oak_small_2.nbt | 0 .../trees/oak/small/oak_small_3.nbt | 0 .../trees/oak/small/oak_small_4.nbt | 0 .../trees/pine/huangshan_pine_1.nbt | 0 .../trees/pine/huangshan_pine_2.nbt | 0 .../trees/pine/huangshan_pine_3.nbt | 0 .../structures/trees/pine/scots_pine_1.nbt | 0 .../structures/trees/pine/scots_pine_2.nbt | 0 .../trees/pine/scots_pine_small_1.nbt | 0 .../trees/pine/scots_pine_small_2.nbt | 0 .../structures/trees/pine/stone_pine_1.nbt | 0 .../structures/trees/pine/stone_pine_2.nbt | 0 .../trees/redwood/huge/redwood_massive_1.nbt | 0 .../trees/redwood/huge/redwood_massive_2.nbt | 0 .../trees/redwood/huge/redwood_massive_3.nbt | 0 .../trees/redwood/huge/redwood_massive_4.nbt | 0 .../trees/redwood/huge/redwood_massive_5.nbt | 0 .../trees/redwood/huge/redwood_massive_6.nbt | 0 .../trees/redwood/large/redwood_tall_1.nbt | 0 .../trees/redwood/large/redwood_tall_2.nbt | 0 .../trees/redwood/large/redwood_tall_3.nbt | 0 .../trees/redwood/large/redwood_tall_4.nbt | 0 .../trees/spruce/bush/spruce_bush_1.nbt | 0 .../trees/spruce/bush/spruce_bush_2.nbt | 0 .../trees/spruce/large/spruce_1.nbt | 0 .../trees/spruce/large/spruce_2.nbt | 0 .../trees/spruce/large/spruce_3.nbt | 0 .../trees/spruce/large/spruce_4.nbt | 0 .../trees/spruce/large/spruce_5.nbt | 0 .../trees/spruce/small/spruce_small_1.nbt | 0 .../trees/spruce/small/spruce_small_2.nbt | 0 .../trees/spruce/small/spruce_small_3.nbt | 0 .../trees/spruce/small/spruce_small_4.nbt | 0 .../willow/large/weeping_willow_big_1.nbt | 0 .../willow/large/weeping_willow_big_2.nbt | 0 .../willow/small/weeping_willow_small_1.nbt | 0 .../willow/small/weeping_willow_small_2.nbt | 0 .../data/terraforged/tags/biomes/alpine.json | 0 .../terraforged/tags/biomes/cold_steppe.json | 0 .../data/terraforged/tags/biomes/desert.json | 0 .../terraforged/tags/biomes/grassland.json | 0 .../data/terraforged/tags/biomes/savanna.json | 0 .../data/terraforged/tags/biomes/steppe.json | 0 .../data/terraforged/tags/biomes/taiga.json | 0 .../tags/biomes/temperate_forest.json | 0 .../tags/biomes/temperate_rainforest.json | 0 .../tags/biomes/tropical_rainforest.json | 0 .../data/terraforged/tags/biomes/tundra.json | 0 .../templates/trees/acacia_large.json | 7 +- .../templates/trees/acacia_small.json | 7 +- .../templates/trees/birch_forest.json | 23 + .../templates/trees/birch_large.json | 23 + .../templates/trees/birch_small.json | 7 +- .../templates/trees/brown_mushroom.json | 6 +- .../templates/trees/dark_oak_large.json | 7 +- .../templates/trees/dark_oak_small.json | 7 +- .../templates/trees/jungle_huge.json | 7 +- .../templates/trees/jungle_large.json | 7 +- .../templates/trees/jungle_small.json | 7 +- .../templates/trees/oak_forest.json | 23 + .../terraforged/templates/trees/oak_huge.json | 23 + .../templates/trees/oak_large.json | 23 + .../templates/trees/oak_small.json | 7 +- .../terraforged/templates/trees/pine.json | 7 +- .../templates/trees/red_mushroom.json | 7 +- .../templates/trees/redwood_huge.json | 5 +- .../templates/trees/redwood_large.json | 7 +- .../templates/trees/spruce_large.json | 7 +- .../templates/trees/spruce_small.json | 7 +- .../templates/trees/willow_large.json | 7 +- .../templates/trees/willow_small.json | 7 +- .../src => src}/main/resources/license.txt | 0 .../src => src}/main/resources/pack.mcmeta | 0 .../main/resources}/terraforged.png | Bin 647 files changed, 3936 insertions(+), 17120 deletions(-) delete mode 160000 TerraEngine delete mode 100644 TerraForgedAPI/README.md delete mode 100644 TerraForgedAPI/build.gradle delete mode 100644 TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateTagPredicate.java delete mode 100644 TerraForgedApp/build.gradle delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/Applet.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/Cache.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/Controller.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/Main.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeColor.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeProvider.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/mesh/Mesh.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/mesh/NoiseMesh.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/mesh/TestRenderer.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/renderer/MeshRenderer.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/renderer/Renderer.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/renderer/VoxelRenderer.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/util/JsonReader.java delete mode 100644 TerraForgedApp/src/main/java/com/terraforged/app/util/Loader.java delete mode 100644 TerraForgedApp/src/main/resources/biome_data.json delete mode 100644 TerraForgedApp/src/main/resources/biome_groups.json delete mode 100644 TerraForgedApp/src/main/resources/grass.png delete mode 100644 TerraForgedApp/src/main/resources/license.txt delete mode 100644 TerraForgedCore/build.gradle delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/cell/Cell.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/cell/Extent.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/cell/Populator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/cell/Tag.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Erosion.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Filter.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Filterable.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Modifier.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Smoothing.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/module/Blender.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/module/MultiBlender.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/module/Select.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/RegionFactory.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/Size.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkGenTask.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkHolder.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkReader.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkWriter.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkZoomTask.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegion.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegionZoom.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/GenContext.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCache.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCacheFactory.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionGenerator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/region/legacy/LegacyRegion.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/BiomeSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/ClimateSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/FilterSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/GeneratorSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/RiverSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/Settings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/settings/TerrainSettings.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/PosIterator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/Seed.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/VariablePredicate.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/Disposable.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ObjectPool.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ThreadPool.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/WorkerFactory.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/AsyncBatcher.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/Batcher.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/SyncBatcher.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/Cache.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/CacheEntry.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/ExpiringEntry.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/SynchronizedLongMap.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedGrid.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedList.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/grid/MappedList.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/points/Poisson.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Comment.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Name.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Option.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Range.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Serializable.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Deserializer.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Reader.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Serializer.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Writer.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/GeneratorContext.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/WorldDecorators.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGenerator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeData.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeManager.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeType.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeColors.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeLoader.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Climate.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/climate/ClimateModule.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Compressor.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper2.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper3.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentModule.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Decorator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertDunes.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertStacks.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Wetlands.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/geology/DepthBuffer.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Geology.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Strata.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Stratum.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Heightmap.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Levels.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionConfig.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionExtent.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldHeightmap.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/PosGenerator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMap.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMapConfig.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverRegionList.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/Lake.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/LakeConfig.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/River.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverBounds.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverConfig.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverNode.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverRegion.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/LandForms.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrain.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/TerrainPopulator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrains.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/VolcanoPopulator.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/StandardTerrainProvider.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProvider.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProviderFactory.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionLerper.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionModule.java delete mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionSelector.java delete mode 100644 TerraForgedCore/src/main/resources/biomes.png delete mode 100644 TerraForgedCore/src/main/resources/biomes.txt delete mode 100644 TerraForgedCore/src/main/resources/license.txt delete mode 100644 TerraForgedCore/src/main/resources/terraforged.png delete mode 100644 TerraForgedMod/README.md delete mode 100644 TerraForgedMod/build.gradle delete mode 100644 TerraForgedMod/gradlew delete mode 100644 TerraForgedMod/gradlew.bat delete mode 100644 TerraForgedMod/psd/biomes.psd delete mode 100644 TerraForgedMod/psd/icon.png delete mode 100644 TerraForgedMod/psd/terraforged.psd delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/TerraBiomeRegistry.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkProcessor.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ObfHelperChunkGenerator.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonContext.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingConfig.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingFeature.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingManager.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingPlacer.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/TreeGrowBuffer.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/DimensionsPage.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FilterPage.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/GeneratorPage.java delete mode 100644 TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java delete mode 100644 TerraForgedMod/src/main/resources/assets/terraforged/lang/en_us.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch_oak.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/features/trees/flower_forest.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_edge.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_forest.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/features/trees/redwood.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_7.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_musroom_6.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_6.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_6.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_3.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/templates/trees/birch_forest.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/templates/trees/birch_large.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_forest.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_huge.json delete mode 100644 TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_large.json delete mode 100644 TerraForgedMod/src/main/resources/license.txt delete mode 100644 TerraForgedMod/src/main/resources/terraforged.png rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/BiomeTags.java (98%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/BiomeVariant.java (86%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java (86%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java (85%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java (93%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/biome/modifier/ModifierManager.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/ChunkContext.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/ChunkDelegate.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/column/ColumnDecorator.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/column/DecoratorContext.java (86%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/column/DecoratorManager.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/CachedSurface.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/ChunkSurfaceBuffer.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/Surface.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java (92%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java (70%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/builder/Combiner.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/chunk/surface/builder/Delegate.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/event/SetupEvent.java (95%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/WGTags.java (91%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/geology/GeologyManager.java (95%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/geology/StrataConfig.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/geology/StrataGenerator.java (96%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/layer/LayerManager.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/layer/LayerMaterial.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/state/CachedState.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/state/DefaultState.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/state/StateSupplier.java (100%) rename {TerraForgedAPI/src => src}/main/java/com/terraforged/api/material/state/States.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/Log.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/TerraForgedMod.java (91%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/TerraWorld.java (91%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/ColdSteppe.java (92%) create mode 100644 src/main/java/com/terraforged/mod/biome/Dunes.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/FirForest.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/FlowerPlains.java (100%) create mode 100644 src/main/java/com/terraforged/mod/biome/FrozenLake.java create mode 100644 src/main/java/com/terraforged/mod/biome/Lake.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/Marshland.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/ModBiomes.java (87%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/SavannaScrub.java (99%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java (98%) create mode 100644 src/main/java/com/terraforged/mod/biome/SnowyFirForest.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/SnowyTaigaScrub.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/Steppe.java (89%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/TaigaScrub.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/WarmBeach.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java (93%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/BiomeGroup.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/BiomeMap.java (92%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java (93%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/BiomePredicate.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/DefaultBiome.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java (86%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java (86%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java (75%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java (92%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java (94%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java (88%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java (77%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java (80%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java (75%) create mode 100644 src/main/java/com/terraforged/mod/biome/provider/BiomeWeights.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java (96%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java (77%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java (79%) rename TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/DesertDunes.java => src/main/java/com/terraforged/mod/biome/surface/DunesSurface.java (80%) rename TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/FrozenOcean.java => src/main/java/com/terraforged/mod/biome/surface/IcebergsSurface.java (94%) create mode 100644 src/main/java/com/terraforged/mod/biome/surface/SteppeSurface.java create mode 100644 src/main/java/com/terraforged/mod/biome/surface/SwampSurface.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/biome/tag/BiomeTagManager.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/ChunkGeneratorFactory.java (100%) create mode 100644 src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/TerraContext.java (68%) create mode 100644 src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java (89%) create mode 100644 src/main/java/com/terraforged/mod/chunk/component/BiomeGenerator.java create mode 100644 src/main/java/com/terraforged/mod/chunk/component/MobGenerator.java create mode 100644 src/main/java/com/terraforged/mod/chunk/component/StructureGenerator.java create mode 100644 src/main/java/com/terraforged/mod/chunk/component/TerrainCarver.java create mode 100644 src/main/java/com/terraforged/mod/chunk/component/TerrainGenerator.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/fix/ChunkCarverFix.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java (93%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/fix/RegionFix.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/fix/SpawnFix.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/test/Test.java (87%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java (93%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java (71%) create mode 100644 src/main/java/com/terraforged/mod/chunk/test/TestHeightMap.java create mode 100644 src/main/java/com/terraforged/mod/chunk/test/TestTerraContext.java rename {TerraForgedMod/src/main/java/com/terraforged/mod/chunk => src/main/java/com/terraforged/mod/chunk/util}/FastChunk.java (99%) rename {TerraForgedMod/src/main/java/com/terraforged/mod/chunk => src/main/java/com/terraforged/mod/chunk/util}/TerraContainer.java (96%) create mode 100644 src/main/java/com/terraforged/mod/chunk/util/TerraHooks.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/TerraCommand.java (79%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/arg/BiomeArgType.java (66%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/arg/TerrainArgType.java (78%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/search/BiomeSearchTask.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/search/BothSearchTask.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/search/Search.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java (77%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/data/DataGen.java (100%) create mode 100644 src/main/java/com/terraforged/mod/data/DataGenerator.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/data/WorldGenBiomes.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/data/WorldGenBlocks.java (100%) create mode 100644 src/main/java/com/terraforged/mod/data/WorldGenFeatures.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/decorator/ChunkPopulator.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java (96%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java (96%) rename {TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base => src/main/java/com/terraforged/mod/decorator/terrain}/BedrockDecorator.java (90%) rename {TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base => src/main/java/com/terraforged/mod/decorator/terrain}/CoastDecorator.java (94%) rename {TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base => src/main/java/com/terraforged/mod/decorator/terrain}/ErosionDecorator.java (95%) rename {TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base => src/main/java/com/terraforged/mod/decorator/terrain}/GeologyDecorator.java (97%) create mode 100644 src/main/java/com/terraforged/mod/feature/BlockDataConfig.java create mode 100644 src/main/java/com/terraforged/mod/feature/BlockDataManager.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/Matchers.java (84%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/TerrainHelper.java (100%) create mode 100644 src/main/java/com/terraforged/mod/feature/context/ChanceContext.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/ContextSelectorConfig.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/ContextSelectorFeature.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/ContextualFeature.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/modifier/Biome.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/modifier/ContextModifier.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/modifier/Elevation.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/modifier/None.java create mode 100644 src/main/java/com/terraforged/mod/feature/context/modifier/RangeContextModifier.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java (93%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonAtSurface.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java (84%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/feature/DiskFeature.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/feature/predicate/TreeLine.java (94%) create mode 100644 src/main/java/com/terraforged/mod/feature/sapling/SaplingConfig.java create mode 100644 src/main/java/com/terraforged/mod/feature/sapling/SaplingListener.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/OverlayRenderer.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/OverlayScreen.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/ScrollPane.java (94%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/SettingsScreen.java (80%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/CheckBox.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/Element.java (68%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/TerraButton.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/TerraLabel.java (87%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/TerraSlider.java (72%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/TerraTextInput.java (85%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/element/TerraToggle.java (83%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/BasePage.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/ClimatePage.java (96%) rename TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FeaturePage.java => src/main/java/com/terraforged/mod/gui/page/MiscPage.java (74%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/Page.java (89%) create mode 100644 src/main/java/com/terraforged/mod/gui/page/PresetPage.java create mode 100644 src/main/java/com/terraforged/mod/gui/page/PresetsPage.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/RiverPage.java (96%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/StructurePage.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/page/TerrainPage.java (96%) create mode 100644 src/main/java/com/terraforged/mod/gui/page/WorldPage.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/preview/Preview.java (85%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/preview/PreviewPage.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java (80%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/gui/preview/RenderMode.java (83%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/material/MaterialHelper.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/material/Materials.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/material/geology/GeoGenerator.java (98%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/material/geology/GeoManager.java (95%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/settings/DimesionSettings.java (86%) rename TerraForgedMod/src/main/java/com/terraforged/mod/settings/FeatureSettings.java => src/main/java/com/terraforged/mod/settings/Miscellaneous.java (91%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/settings/SettingsHelper.java (78%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/settings/StructureSettings.java (52%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/settings/TerraSettings.java (89%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/DataPackFinder.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/DummyBlockReader.java (97%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/Environment.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/ListUtils.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/NBTLeavesFixer.java (100%) create mode 100644 src/main/java/com/terraforged/mod/util/RangeModifier.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/annotation/Name.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/annotation/Ref.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/nbt/NBTHelper.java (88%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/nbt/NBTReader.java (97%) create mode 100644 src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/setup/SetupDebug.java (100%) rename {TerraForgedMod/src => src}/main/java/com/terraforged/mod/util/setup/SetupHooks.java (94%) rename {TerraForgedMod/src => src}/main/resources/META-INF/mods.toml (100%) rename {TerraForgedMod/src => src}/main/resources/biomes.txt (100%) rename {TerraForgedMod/src => src}/main/resources/data/forge/tags/blocks/wg_clay.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/forge/tags/blocks/wg_dirt.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/forge/tags/blocks/wg_erodible.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/forge/tags/blocks/wg_sediment.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/forge/tags/blocks/wg_stone.json (100%) create mode 100644 src/main/resources/data/terraforged/blocks/saplings/birch_sapling.json create mode 100644 src/main/resources/data/terraforged/blocks/saplings/jungle_sapling.json create mode 100644 src/main/resources/data/terraforged/blocks/saplings/oak_sapling.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/coal.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/diamond.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/gold.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/gold_extra.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/iron.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/lapis.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/ores/redstone.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/sediments/clay.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/sediments/dirt.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/sediments/gravel.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/shrubs/dead_bush.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/shrubs/forest_grass.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/acacia.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/birch.json (50%) create mode 100644 src/main/resources/data/terraforged/features/trees/birch_oak.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/dark_oak.json (78%) create mode 100644 src/main/resources/data/terraforged/features/trees/fir_foreset.json create mode 100644 src/main/resources/data/terraforged/features/trees/flower_forest.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/jungle.json (67%) create mode 100644 src/main/resources/data/terraforged/features/trees/jungle_edge.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/jungle_hills.json (66%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/oak_badlands.json (73%) create mode 100644 src/main/resources/data/terraforged/features/trees/oak_forest.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/oak_plains.json (52%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/pine.json (58%) create mode 100644 src/main/resources/data/terraforged/features/trees/redwood.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/spruce.json (58%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/spruce_tundra.json (72%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/features/trees/willow.json (64%) create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_7.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/brown/brown_musroom_6.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/large/birch_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_6.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/large/oak_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/large/oak_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/large/oak_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/large/oak_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/scots_pine_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/stone_pine_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_6.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_3.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt create mode 100644 src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/alpine.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/cold_steppe.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/desert.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/grassland.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/savanna.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/steppe.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/taiga.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/temperate_forest.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/temperate_rainforest.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/tropical_rainforest.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/tags/biomes/tundra.json (100%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/acacia_large.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/acacia_small.json (67%) create mode 100644 src/main/resources/data/terraforged/templates/trees/birch_forest.json create mode 100644 src/main/resources/data/terraforged/templates/trees/birch_large.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/birch_small.json (59%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/brown_mushroom.json (68%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/dark_oak_large.json (61%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/dark_oak_small.json (61%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/jungle_huge.json (59%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/jungle_large.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/jungle_small.json (60%) create mode 100644 src/main/resources/data/terraforged/templates/trees/oak_forest.json create mode 100644 src/main/resources/data/terraforged/templates/trees/oak_huge.json create mode 100644 src/main/resources/data/terraforged/templates/trees/oak_large.json rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/oak_small.json (58%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/pine.json (56%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/red_mushroom.json (59%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/redwood_huge.json (85%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/redwood_large.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/spruce_large.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/spruce_small.json (67%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/willow_large.json (60%) rename {TerraForgedMod/src => src}/main/resources/data/terraforged/templates/trees/willow_small.json (60%) rename {TerraForgedAPI/src => src}/main/resources/license.txt (100%) rename {TerraForgedMod/src => src}/main/resources/pack.mcmeta (100%) rename {TerraForgedMod/psd => src/main/resources}/terraforged.png (100%) diff --git a/Engine b/Engine index 6babefb..7cda523 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit 6babefb3017d33a78c914eda21fd1fa3b53dc9e3 +Subproject commit 7cda523891ce81b36dd5f09f5573e1f258f92923 diff --git a/FeatureManager b/FeatureManager index 0da0d13..fceeea1 160000 --- a/FeatureManager +++ b/FeatureManager @@ -1 +1 @@ -Subproject commit 0da0d13c3dc8426b18a55107b42986e9d66387f1 +Subproject commit fceeea1cac7174f873834fa12b5d78952710a516 diff --git a/TerraEngine b/TerraEngine deleted file mode 160000 index c369779..0000000 --- a/TerraEngine +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c36977964d2f203fe9a940df908d1b7c2fac264b diff --git a/TerraForgedAPI/README.md b/TerraForgedAPI/README.md deleted file mode 100644 index 2d5f64e..0000000 --- a/TerraForgedAPI/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# TerraForgedAPI - -### Dependency -```groovy -repositories { - maven { - url "https://io.terraforged.com/repository/maven/" - } -} - -dependencies { - implementation "com.terraforged:TerraForgedAPI:1.15.2-0.0.1" -} -``` - -### Usage - -TerraForged fires a number of setup events each time its chunk generator is created. These events expose certain -components of the generator allowing for world-gen content to be configured, modified, or added to. - -See the `com.terraforged.api.TerraEvent` class for the available events. - -All events are fired on the `FORGE` event bus. \ No newline at end of file diff --git a/TerraForgedAPI/build.gradle b/TerraForgedAPI/build.gradle deleted file mode 100644 index cf77135..0000000 --- a/TerraForgedAPI/build.gradle +++ /dev/null @@ -1,70 +0,0 @@ -buildscript { - repositories { - maven { url "https://files.minecraftforge.net/maven" } - jcenter() - mavenCentral() - } - dependencies { - classpath group: "net.minecraftforge.gradle", name: "ForgeGradle", version: "3.+", changing: true - } -} - -apply plugin: "net.minecraftforge.gradle" -apply plugin: "maven-publish" -apply plugin: "eclipse" - -version = "${mc_version}-${mod_version}" -archivesBaseName = "TerraForgedAPI" - -repositories { - jcenter() - mavenCentral() -} - -dependencies { - minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" - compile project(":FeatureManager") - compile project(":TerraForgedCore") -} - -minecraft { - mappings channel: mcp_channel, version: mcp_version -} - -task sourceJar(type: Jar) { - classifier = "sources" - from("$projectDir/src/main/java") - from(project(":Noise2D").projectDir.getPath() + "/src/main/java") - from(project(":FeatureManager").projectDir.getPath() + "/src/main/java") - from(project(":TerraForgedCore").projectDir.getPath() + "/src/main/java") -} - -jar { - dependsOn(sourceJar) - from("$buildDir/classes/java/main") - from(project(":Noise2D").buildDir.getPath() + "/classes/java/main") - from(project(":FeatureManager").buildDir.getPath() + "/classes/java/main") - from(project(":TerraForgedCore").buildDir.getPath() + "/classes/java/main") -} - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - artifact sourceJar - } - } - - if (System.getenv("MAVEN_USER") != null && System.getenv("MAVEN_PASS") != null) { - repositories { - maven { - credentials { - username System.getenv("MAVEN_USER") - password System.getenv("MAVEN_PASS") - } - name = "nexus" - url = "https://io.terraforged.com/repository/maven/" - } - } - } -} \ No newline at end of file diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateTagPredicate.java b/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateTagPredicate.java deleted file mode 100644 index 87f0d5f..0000000 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateTagPredicate.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.terraforged.api.material.state; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.tags.Tag; - -import java.util.function.Predicate; - -public class StateTagPredicate implements Predicate { - - private final Tag tag; - - public StateTagPredicate(Tag tag) { - this.tag = tag; - } - - @Override - public boolean test(BlockState state) { - return tag.contains(state.getBlock()); - } -} diff --git a/TerraForgedApp/build.gradle b/TerraForgedApp/build.gradle deleted file mode 100644 index dfefdc8..0000000 --- a/TerraForgedApp/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -apply plugin: "maven-publish" -apply plugin: "java" - -repositories { - mavenCentral() - jcenter() -} - -dependencies { - compile "com.google.code.gson:gson:2.8.0" - compile "org.processing:core:3.3.7" - compile "it.unimi.dsi:fastutil:8.2.1" - compile project(":TerraForgedCore") -} - -jar { - manifest { attributes "Main-Class": "com.terraforged.app.Main" } - from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } -} - -publish { - dependsOn(jar) -} \ No newline at end of file diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/Applet.java b/TerraForgedApp/src/main/java/com/terraforged/app/Applet.java deleted file mode 100644 index 9945daf..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/Applet.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app; - -import com.terraforged.app.renderer.MeshRenderer; -import com.terraforged.app.renderer.Renderer; -import com.terraforged.app.renderer.VoxelRenderer; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; -import processing.core.PApplet; -import processing.event.KeyEvent; -import processing.event.MouseEvent; - -public abstract class Applet extends PApplet { - - public static final int ELEVATION = 1; - public static final int BIOME_TYPE = 2; - public static final int TEMPERATURE = 3; - public static final int MOISTURE = 4; - public static final int BIOME = 5; - public static final int STEEPNESS = 6; - public static final int TERRAIN_TYPE = 7; - public static final int EROSION = 8; - public static final int CONTINENT = 9; - - protected Renderer mesh = new MeshRenderer(this); - protected Renderer voxel = new VoxelRenderer(this); - - public final Controller controller = new Controller(); - - public abstract Cache getCache(); - - public abstract float color(Cell cell); - - @Override - public void settings() { - size(800, 800, P3D); - } - - @Override - public void mousePressed(MouseEvent event) { - controller.mousePress(event); - } - - @Override - public void mouseReleased(MouseEvent event) { - controller.mouseRelease(event); - } - - @Override - public void mouseDragged(MouseEvent event) { - controller.mouseDrag(event); - } - - @Override - public void mouseWheel(MouseEvent event) { - controller.mouseWheel(event); - } - - @Override - public void keyPressed(KeyEvent event) { - controller.keyPress(event); - } - - @Override - public void keyReleased(KeyEvent event) { - controller.keyRelease(event); - } - - public void leftAlignText(int margin, int top, int lineHeight, String... lines) { - noLights(); - fill(0, 0, 100); - for (int i = 0; i < lines.length; i++) { - int y = top + (i * lineHeight); - text(lines[i], margin, y); - } - } - - - public void drawTerrain(float zoom) { - if (controller.getRenderMode() == 0) { - voxel.render(zoom); - } else { - mesh.render(zoom); - } - } - - public String colorModeName() { - switch (controller.getColorMode()) { - case STEEPNESS: - return "GRADIENT"; - case TEMPERATURE: - return "TEMPERATURE"; - case MOISTURE: - return "MOISTURE"; - case TERRAIN_TYPE: - return "TERRAIN TYPE"; - case ELEVATION: - return "ELEVATION"; - case BIOME_TYPE: - return "BIOME TYPE"; - case BIOME: - return "BIOME"; - case EROSION: - return "EROSION"; - case CONTINENT: - return "CONTINENT"; - default: - return "-"; - } - } - - public static float hue(float value, int steps, int max) { - value = Math.round(value * (steps - 1)); - value /= (steps - 1); - return value * max; - } - - public void drawCompass() { - pushStyle(); - pushMatrix(); - textSize(200); - fill(100, 0, 100); - - char[] chars = {'N', 'E', 'S', 'W'}; - for (int r = 0; r < 4; r++) { - char c = chars[r]; - float x = -textWidth(c) / 2; - float y = -width * 1.2F; - text(c, x, y); - rotateZ(0.5F * PI); - } - - popMatrix(); - popStyle(); - textSize(16); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/Cache.java b/TerraForgedApp/src/main/java/com/terraforged/app/Cache.java deleted file mode 100644 index 17aff83..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/Cache.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.region.Region; -import com.terraforged.core.region.gen.RegionGenerator; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; - -public class Cache { - - private float offsetX = 0; - private float offsetZ = 0; - private float zoom = 0F; - private boolean filter = true; - private Terrains terrain; - private Settings settings; - private GeneratorContext context; - private Region region; - private RegionGenerator renderer; - - public Cache(int seed) { - Settings settings = new Settings(); - settings.generator.seed = seed; - this.settings = settings; - this.terrain = Terrains.create(settings); - this.context = new GeneratorContext(terrain, settings); - this.renderer = RegionGenerator.builder() - .factory(new WorldGeneratorFactory(context)) - .pool(ThreadPool.getPool()) - .size(3, 2) - .build(); - } - - public Settings getSettings() { - return settings; - } - - public Terrains getTerrain() { - return terrain; - } - - public Terrain getCenterTerrain() { - Terrain tag = getCenterCell().tag; - return tag == null ? terrain.ocean : tag; - } - - public BiomeType getCenterBiomeType() { - return getCenterCell().biomeType; - } - - public int getCenterHeight() { - return (int) (context.levels.worldHeight * getCenterCell().value); - } - - public Cell getCenterCell() { - int center = region.getBlockSize().size / 2; - return region.getCell(center, center); - } - - public Region getRegion() { - return region; - } - - public void update(float offsetX, float offsetZ, float zoom, boolean filters) { - if (region == null) { - record(offsetX, offsetZ, zoom, filters); - return; - } - if (this.offsetX != offsetX || this.offsetZ != offsetZ) { - record(offsetX, offsetZ, zoom, filters); - return; - } - if (this.zoom != zoom) { - record(offsetX, offsetZ, zoom, filters); - return; - } - if (this.filter != filters) { - record(offsetX, offsetZ, zoom, filters); - } - } - - private void record(float offsetX, float offsetZ, float zoom, boolean filters) { - this.zoom = zoom; - this.filter = filters; - this.offsetX = offsetX; - this.offsetZ = offsetZ; - try { - this.region = renderer.generateRegion(offsetX, offsetZ, zoom, filters); - } catch (Throwable t) { - t.printStackTrace(); - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/Controller.java b/TerraForgedApp/src/main/java/com/terraforged/app/Controller.java deleted file mode 100644 index b5ee022..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/Controller.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app; - -import processing.core.PApplet; -import processing.event.KeyEvent; -import processing.event.MouseEvent; - -import java.awt.*; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; - -public class Controller { - - private static final int BUTTON_NONE = -1; - private static final int BUTTON_1 = 37; - private static final int BUTTON_2 = 39; - private static final int BUTTON_3 = 3; - - private static final float cameraSpeed = 100F; - private static final float zoomSpeed = 0.01F; - private static final float rotateSpeed = 0.002F; - private static final float translateSpeed = 2F; - private static final float moveSpeed = 10F; - - private int mouseButton = BUTTON_NONE; - private int lastX = 0; - private int lastY = 0; - - private float yaw = -0.2F; - private float pitch = 0.85F; - private float translateX = 0F; - private float translateY = 0F; - private float translateZ = -800; - private float velocityX = 0F; - private float velocityY = 0F; - - private int colorMode = 1; - private int renderMode = 0; - private int newSeed = 0; - private int left = 0; - private int right = 0; - private int up = 0; - private int down = 0; - private float zoom = 16; - private boolean filters = true; - - public void apply(PApplet applet) { - applet.translate(translateX, translateY, translateZ); - applet.translate(applet.width / 2, applet.height / 2, 0); - applet.rotateX(pitch); - applet.rotateZ(yaw); - update(); - } - - public void update() { - float forward = up + down; - float strafe = left + right; - velocityX = forward * (float) Math.sin(yaw); - velocityY = forward * (float) Math.cos(yaw); - velocityX += strafe * (float) Math.sin(yaw + Math.toRadians(90)); - velocityY += strafe * (float) Math.cos(yaw + Math.toRadians(90)); - if (velocityX != 0 || velocityY != 0) { - float magnitude = (float) Math.sqrt(velocityX * velocityX + velocityY * velocityY); - velocityX /= magnitude; - velocityY /= magnitude; - } - } - - public int getColorMode() { - return colorMode; - } - - public int getRenderMode() { - return renderMode; - } - - public float velocityX() { - return velocityX * moveSpeed / zoom; - } - - public float velocityY() { - return velocityY * moveSpeed / zoom; - } - - public float zoomLevel() { - return zoom; - } - - public boolean filters() { - return filters; - } - - public int getNewSeed() { - if (newSeed == 1) { - newSeed = 0; - return 1; - } - if (newSeed != 0) { - int val = newSeed; - newSeed = 0; - return val; - } - return 0; - } - - public void keyPress(KeyEvent event) { - switch (event.getKey()) { - case 'w': - up = -1; - break; - case 'a': - left = -1; - break; - case 's': - down = 1; - break; - case 'd': - right = 1; - break; - } - } - - public void keyRelease(KeyEvent event) { - switch (event.getKey()) { - case 'w': - up = 0; - return; - case 'a': - left = 0; - return; - case 's': - down = 0; - return; - case 'd': - right = 0; - return; - case 'r': - renderMode = renderMode == 0 ? 1 : 0; - return; - case 'n': - newSeed = 1; - return; - case 'm': - newSeed = Main.seed; - return; - case 'f': - filters = !filters; - return; - case 'c': - StringSelection selection = new StringSelection("" + Main.seed); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, null); - return; - case 'v': - try { - Object data = Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); - newSeed = (int) Long.parseLong(data.toString()); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - if (event.getKey() >= '1' && event.getKey() <= '9') { - colorMode = event.getKey() - '0'; - return; - } - } - - public void mousePress(MouseEvent event) { - if (mouseButton == BUTTON_NONE) { - lastX = event.getX(); - lastY = event.getY(); - mouseButton = event.getButton(); - } - } - - public void mouseRelease(MouseEvent event) { - mouseButton = BUTTON_NONE; - } - - public void mouseWheel(MouseEvent event) { - translateZ -= event.getCount() * cameraSpeed; - } - - public void mouseDrag(MouseEvent event) { - int dx = event.getX() - lastX; - int dy = event.getY() - lastY; - boolean ctrl = (event.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; - - lastX = event.getX(); - lastY = event.getY(); - - if (mouseButton == BUTTON_1) { - yaw -= dx * rotateSpeed; - pitch -= dy * rotateSpeed; - } - - if (mouseButton == BUTTON_2) { - translateX += dx * translateSpeed; - translateY += dy * translateSpeed; - } - - if (mouseButton == BUTTON_3) { - if (ctrl) { - zoom += (dy - dx) * zoom * zoomSpeed; - zoom = Math.max(1F, zoom); - } else { - translateZ -= (dy - dx) * cameraSpeed * 0.1F; - } - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/Main.java b/TerraForgedApp/src/main/java/com/terraforged/app/Main.java deleted file mode 100644 index b1627ff..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/Main.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app; - -import com.terraforged.app.biome.BiomeProvider; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.biome.BiomeData; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.util.NoiseUtil; - -import java.awt.*; -import java.util.Random; - -public class Main extends Applet { - - public static void main(String[] args) { - Main.start(-1); - } - - public static void start(long seed) { - Main.seed = (int) seed; - Main.random = seed == -1; - main(Main.class.getName()); - } - - private static boolean random = false; - public static int seed = -1; - - private Cache cache; - private float offsetX = 0; - private float offsetZ = 0; - private final String bits = System.getProperty("sun.arch.data.model"); - private final BiomeProvider biomeProvider = new BiomeProvider(); - - @Override - public Cache getCache() { - return cache; - } - - @Override - public void setup() { - super.setup(); - if (random) { - setSeed(new Random(System.currentTimeMillis()).nextInt()); - offsetX = 0; - offsetZ = 0; - } - setSeed(seed); - } - - public void setSeed(int seed) { - Main.seed = seed; - cache = new Cache(seed); - System.out.println(seed); - } - - @Override - public float color(Cell cell) { - switch (controller.getColorMode()) { - case STEEPNESS: - return hue(1 - cell.steepness, 64, 70); - case TEMPERATURE: - return hue(1 - cell.temperature, 64, 70); - case MOISTURE: - return hue(cell.moisture, 64, 70); - case TERRAIN_TYPE: - if (cell.tag == getCache().getTerrain().volcano) { - return 0F; - } - return 20 + (cell.tag.getHue() * 80); - case ELEVATION: - float value = (cell.value - 0.245F) / 0.65F; - return (1 - value) * 30; - case BIOME: - BiomeData biome = biomeProvider.getBiome(cell); - if (biome == null) { - return 0F; - } - return cell.biome * 70; - case CONTINENT: - return cell.continent * 70; - default: - return 50; - } - } - - @Override - public void draw() { - int nextSeed = controller.getNewSeed(); - if (nextSeed == 1) { - setup(); - } else if (nextSeed != 0) { - setSeed(nextSeed); - } - - offsetX += controller.velocityX() * controller.zoomLevel() * controller.zoomLevel(); - offsetZ += controller.velocityY() * controller.zoomLevel() * controller.zoomLevel(); - cache.update(offsetX, offsetZ, controller.zoomLevel(), controller.filters()); - - // color stuff - noStroke(); - background(0); - colorMode(HSB, 100); - - // lighting - ambientLight(0, 0, 75, width / 2, -height, height / 2); - pointLight(0, 0, 50, width / 2, -height * 100, height / 2); - - // render - pushMatrix(); - controller.apply(this); -// translate(-width / 2F, -height / 2F); - drawTerrain(controller.zoomLevel()); - drawCompass(); -// translate(0, 0, 255 * (width / (float) controller.resolution()) / controller.zoomLevel()); -// mesh.renderWind(controller.resolution(), controller.zoomLevel()); - popMatrix(); - - pushMatrix(); - translate(0, 0, -1); -// drawGradient(0, height - 150, 100F, width, 150); - popMatrix(); - - drawStats(); - drawBiomeKey(); - drawControls(); - } - - private void drawGradient(int x, int y, float d, float w, float h) { - noFill(); - for (int dy = 0; dy <= h; dy++) { - float dist = Math.min(1, dy / d); - stroke(0, 0, 0, dist * 100F); - line(x, y + dy, x + w, y + dy); - } - noStroke(); - } - - private void drawStats() { - int resolution = cache.getRegion().getBlockSize().size; - int blocks = NoiseUtil.round(resolution * controller.zoomLevel()); - - String[][] info = { - {"Java:", String.format("x%s", bits)}, - {"Fps: ", String.format("%.3f", frameRate)}, - {"Seed:", String.format("%s", seed)}, - {"Zoom: ", String.format("%.2f", controller.zoomLevel())}, - {"Area: ", String.format("%sx%s [%sx%s]", blocks, blocks, resolution, resolution)}, - {"Center: ", String.format("x=%.0f, y=%s, z=%.0f", offsetX, cache.getCenterHeight(), offsetZ)}, - {"Terrain: ", cache.getCenterTerrain().getName()}, - {"BiomeType:", cache.getCenterBiomeType().name()}, -// {"Biome: ", String.format("%s", biomeProvider.getBiome(cache.getCenterCell()).name)}, - {"Overlay: ", colorModeName()}, - }; - - int widest = 0; - for (String[] s : info) { - widest = Math.max(widest, (int) textWidth(s[0])); - } - - int top = 20; - int lineHeight = 15; - for (String[] s : info) { - leftAlignText(10, top, 0, s[0]); - top += lineHeight; - } - - top = 20; - for (String[] s : info) { - if (s.length == 2) { - leftAlignText(12 + widest, top, 0, s[1]); - top += lineHeight; - } - } - } - - private void drawBiomeKey() { - int top = 20; - int lineHeight = 15; - int widest = 0; - for (BiomeType type : BiomeType.values()) { - widest = Math.max(widest, (int) textWidth(type.name())); - } - - int left = width - widest - lineHeight - 15; - for (BiomeType type : BiomeType.values()) { - leftAlignText(left, top, 0, type.name()); - float[] hsb = Color.RGBtoHSB(type.getColor().getRed(), type.getColor().getGreen(), - type.getColor().getBlue(), null); - fill(0, 0, 100); - rect(width - lineHeight - 11, top - lineHeight + 1, lineHeight + 2, lineHeight + 2); - - fill(hsb[0] * 100, hsb[1] * 100, hsb[2] * 100); - rect(width - lineHeight - 10, top - lineHeight + 2, lineHeight, lineHeight); - top += lineHeight; - } - } - - private void drawControls() { - String[][][] columns = { - { - {"Mouse-Left + Move", " - Rotate terrain"}, - {"Mouse-Right + Move", " - Pan terrain"}, - {"Mouse-Scroll + Move", " - Zoom camera"}, - {"Mouse-Scroll + LCTRL + Move", " - Zoom terrain"}, - {"WASD", "- Move terrain"} - }, { - {"Key 1-8", "- Select overlay"}, - {"Key R", "- Toggle mesh renderer"}, - {"Key F", "- Toggle filters"}, - {"Key N", "- Generate new world"}, - {"Key C", "- Copy seed to clipboard"}, - {"Key V", "- Paste seed from clipboard"}, - }}; - - int lineHeight = 15; - int rows = 0; - for (String[][] column : columns) { - rows = Math.max(rows, column.length); - } - - int left = 10; - int widest = 0; - for (String[][] column : columns) { - int top = (height - 10) - ((rows - 1) * lineHeight); - - for (String[] row : column) { - int width = 0; - for (String cell : row) { - leftAlignText(left + width, top, 0, cell); - width += (int) textWidth(cell); - } - top += lineHeight; - widest = Math.max(widest, width); - } - - left += widest + 10; - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeColor.java b/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeColor.java deleted file mode 100644 index 7deaa3e..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeColor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.biome; - -import me.dags.noise.util.NoiseUtil; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; - -public class BiomeColor { - - private static final BufferedImage image = load(); - private static final int width = image.getWidth() - 1; - private static final int height = image.getHeight() - 1; - - public static int getRGB(float temp, float moist) { - float humidity = temp * moist; - temp = 1 - temp; - humidity = 1 - humidity; - int x = NoiseUtil.round(temp * width); - int y = NoiseUtil.round(humidity * height); - return image.getRGB(x, y); - } - - - private static BufferedImage load() { - try (InputStream inputStream = BiomeColor.class.getResourceAsStream("/grass.png")) { - return ImageIO.read(inputStream); - } catch (IOException e) { - e.printStackTrace(); - return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeProvider.java b/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeProvider.java deleted file mode 100644 index d5b82ba..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/biome/BiomeProvider.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.biome; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.grid.FixedGrid; -import com.terraforged.core.world.biome.BiomeData; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; -import processing.data.JSONArray; -import processing.data.JSONObject; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class BiomeProvider { - - private final List> biomes; - - public BiomeProvider() { - biomes = getBiomes(5); - } - - public BiomeData getBiome(Cell cell) { - FixedGrid grid = biomes.get(cell.biomeType.ordinal()); - if (grid == null) { - return null; - } - return grid.get(cell.moisture, cell.temperature, cell.biome); - } - - private static List> getBiomes(int gridSize) { - List> data = new ArrayList<>(); - for (BiomeType type : BiomeType.values()) { - data.add(type.ordinal(), null); - } - - Map biomes = loadBiomes(); - Map> types = loadBiomeTypes(); - for (Map.Entry> e : types.entrySet()) { - List list = new LinkedList<>(); - for (String id : e.getValue()) { - BiomeData biome = biomes.get(id); - if (biome != null) { - list.add(biome); - } - } - FixedGrid grid = FixedGrid.generate(gridSize, list, b -> b.rainfall, b -> b.temperature); - data.set(e.getKey().ordinal(), grid); - } - - return data; - } - - private static Map loadBiomes() { - try (InputStream inputStream = BiomeProvider.class.getResourceAsStream("/biome_data.json")) { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - StringBuilder sb = new StringBuilder(); - reader.lines().forEach(sb::append); - JSONArray array = JSONArray.parse(sb.toString()); - Map biomes = new HashMap<>(); - for (int i = 0; i < array.size(); i++) { - JSONObject object = array.getJSONObject(i); - String name = object.getString("id"); - float moisture = object.getFloat("moisture"); - float temperature = object.getFloat("temperature"); - int color = BiomeColor.getRGB(temperature, moisture); - BiomeData biome = new BiomeData(name, null, color, moisture, temperature); - biomes.put(name, biome); - } - return biomes; - } catch (IOException e) { - e.printStackTrace(); - return Collections.emptyMap(); - } - } - - private static Map> loadBiomeTypes() { - try (InputStream inputStream = BiomeProvider.class.getResourceAsStream("/biome_groups.json")) { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - StringBuilder sb = new StringBuilder(); - reader.lines().forEach(sb::append); - JSONObject object = JSONObject.parse(sb.toString()); - Iterator iterator = object.keyIterator(); - Map> biomes = new HashMap<>(); - while (iterator.hasNext()) { - String key = "" + iterator.next(); - if (key.contains("rivers")) { - continue; - } - if (key.contains("oceans")) { - continue; - } - BiomeType type = BiomeType.valueOf(key); - List group = new LinkedList<>(); - JSONArray array = object.getJSONArray(key); - for (int i = 0; i < array.size(); i++) { - group.add(array.getString(i)); - } - biomes.put(type, group); - } - return biomes; - } catch (IOException e) { - e.printStackTrace(); - return Collections.emptyMap(); - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/Mesh.java b/TerraForgedApp/src/main/java/com/terraforged/app/mesh/Mesh.java deleted file mode 100644 index 2696c06..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/Mesh.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.mesh; - -public class Mesh { - - private final Mesh inner; - private final float x0; - private final float y0; - private final float x1; - private final float y1; - private final float quality; - - public Mesh(Mesh inner, float x0, float y0, float x1, float y1, float quality) { - this.inner = inner; - this.x0 = x0; - this.y0 = y0; - this.x1 = x1; - this.y1 = y1; - this.quality = quality; - } - - public Mesh expand(float scale) { - return expand(scale, scale); - } - - public Mesh expand(float scale, float quality) { - float width0 = getWidth(); - float height0 = getHeight(); - float width1 = width0 * scale; - float height1 = height0 * scale; - float deltaX = (width1 - width0) / 2F; - float deltaY = (height1 - height0) / 2F; - float newQuality = this.quality * quality; - return new Mesh(this, x0 - deltaX, y0 - deltaY, x1 + deltaX, y1 + deltaY, newQuality); - } - - public float getWidth() { - return x1 - x0; - } - - public float getHeight() { - return y1 - y0; - } - - public void start(float width, float height) { - if (inner != null) { - inner.start(width, height); - } - } - - public void render() { - if (inner == null) { - renderNormal(); - } else { - renderCutout(); - inner.render(); - } - } - - public void beginStrip() { - if (inner != null) { - inner.beginStrip(); - } - } - - public void endStrip() { - if (inner != null) { - inner.endStrip(); - } - } - - public void visit(float x, float y) { - if (inner != null) { - inner.visit(x, y); - } - } - - private void renderNormal() { - beginStrip(); - iterate(x0, y0, x1, y1); - endStrip(); - } - - private void renderCutout() { - beginStrip(); - iterate(x0, y0, inner.x1, inner.y0); - endStrip(); - - beginStrip(); - iterate(inner.x1, y0, x1, inner.y1); - endStrip(); - - beginStrip(); - iterate(inner.x0, inner.y1, x1, y1); - endStrip(); - - beginStrip(); - iterate(x0, inner.y0, inner.x0, y1); - endStrip(); - } - - private void iterate(float minX, float minY, float maxX, float maxY) { - float x = minX - quality; - float y = minY - quality; - while (y < maxY) { - y = Math.min(y + quality, maxY); - beginStrip(); - while (x < maxX) { - x = Math.min(x + quality, maxX); - visit(x, y); - visit(x, y + quality); - } - x = minX - quality; - endStrip(); - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/NoiseMesh.java b/TerraForgedApp/src/main/java/com/terraforged/app/mesh/NoiseMesh.java deleted file mode 100644 index 021e846..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/NoiseMesh.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.mesh; - -import com.terraforged.app.Applet; -import com.terraforged.app.renderer.Renderer; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; -import processing.core.PApplet; - -public class NoiseMesh extends Mesh { - - private final Applet applet; - private final Renderer renderer; - private final Cell cell = new Cell<>(); - - public NoiseMesh(Applet applet, Renderer renderer, float x0, float y0, float x1, float y1) { - super(null, x0, y0, x1, y1, 1F); - this.applet = applet; - this.renderer = renderer; - } - - @Override - public void start(float width, float height) { - applet.noStroke(); - } - - @Override - public void beginStrip() { - applet.beginShape(PApplet.TRIANGLE_STRIP); - } - - @Override - public void endStrip() { - applet.endShape(); - } - - @Override - public void visit(float x, float y) { - float height = cell.value * 255; - float surface = renderer.getSurface(cell, height, 63, 10F); - applet.vertex(x * 10F, y * 10F, (int) surface); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/TestRenderer.java b/TerraForgedApp/src/main/java/com/terraforged/app/mesh/TestRenderer.java deleted file mode 100644 index 4c82c08..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/mesh/TestRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.mesh; - -import com.terraforged.app.Applet; -import com.terraforged.app.renderer.Renderer; - -public class TestRenderer extends Renderer { - - private static boolean printed = false; - - public TestRenderer(Applet visualizer) { - super(visualizer); - } - - @Override - public void render(float zoom) { - Mesh mesh = new NoiseMesh(applet, this, -64, -64, 64, 64); - for (int i = 0; i < 1; i++) { -// mesh = mesh.expand(4); - } - - float width = mesh.getWidth(); - float height = mesh.getHeight(); - if (!printed) { - printed = true; - System.out.println(width + "x" + height); - } - - applet.pushMatrix(); - mesh.start(mesh.getWidth(), mesh.getHeight()); - mesh.render(); - applet.popMatrix(); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/MeshRenderer.java b/TerraForgedApp/src/main/java/com/terraforged/app/renderer/MeshRenderer.java deleted file mode 100644 index f76ce76..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/MeshRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.renderer; - -import com.terraforged.app.Applet; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import processing.core.PApplet; - -public class MeshRenderer extends Renderer { - - public MeshRenderer(Applet visualizer) { - super(visualizer); - } - - @Override - public void render(float zoom) { - float seaLevel = new Levels(applet.getCache().getSettings().generator).water; - int worldHeight = applet.getCache().getSettings().generator.world.worldHeight; - int waterLevel = (int) (seaLevel * worldHeight); - int seabedLevel = (int) ((seaLevel - 0.04) * worldHeight); - int resolution = applet.getCache().getRegion().getBlockSize().size; - - float w = applet.width / (float) (resolution - 1); - float h = applet.width / (float) (resolution - 1); - - applet.noStroke(); - applet.pushMatrix(); - applet.translate(-applet.width / 2F, -applet.width / 2F); - - for (int dy = 0; dy < resolution - 1; dy++) { - applet.beginShape(PApplet.TRIANGLE_STRIP); - for (int dx = 0; dx < resolution; dx++) { - draw(dx, dy, w, h, zoom, worldHeight, waterLevel, seabedLevel); - draw(dx, dy + 1, w, h, zoom, worldHeight, waterLevel, resolution / 2); - } - applet.endShape(); - } - - applet.popMatrix(); - } - - private void draw(int dx, int dz, float w, float h, float zoom, int worldHeight, int waterLevel, int center) { - Cell cell = applet.getCache().getRegion().getCell(dx, dz); - float height = (cell.value * worldHeight); - float x = dx * w; - float z = dz * h; - float y = (int) getSurface(cell, height, waterLevel, 1); - applet.vertex(x, z, y / (zoom * 0.2F)); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/Renderer.java b/TerraForgedApp/src/main/java/com/terraforged/app/renderer/Renderer.java deleted file mode 100644 index c2472f0..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/Renderer.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.renderer; - -import com.terraforged.app.Applet; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; - -import java.awt.*; - -public abstract class Renderer { - - protected final Applet applet; - - protected Renderer(Applet visualizer) { - this.applet = visualizer; - } - - public float getSurface(Cell cell, float height, int waterLevel, float el) { - if (cell.tag == applet.getCache().getTerrain().volcanoPipe) { - applet.fill(2, 80, 64); - return height * 0.95F * el; - } - if (height < waterLevel) { - float temp = cell.temperature; - float tempDelta = temp > 0.5 ? temp - 0.5F : -(0.5F - temp); - float tempAlpha = (tempDelta / 0.5F); - float hueMod = 4 * tempAlpha; - - float depth = (waterLevel - height) / (float) (90); - float darkness = (1 - depth); - float darknessMod = 0.5F + (darkness * 0.5F); - - applet.fill(60 - hueMod, 65, 90 * darknessMod); - return height * el; - } else if (applet.controller.getColorMode() == Applet.ELEVATION) { - float hei = Math.min(1, Math.max(0, height - waterLevel) / (255F - waterLevel)); - float temp = cell.temperature; - float moist = Math.min(temp, cell.moisture); - - float hue = 35 - (temp * (1 - moist)) * 25; - float sat = 75 * (1 - hei); - float bri = 50 + 40 * hei; - applet.fill(hue, sat, bri); - return height * el; - } else if (applet.controller.getColorMode() == Applet.BIOME_TYPE) { - Color c = cell.biomeType.getColor(); - if (cell.riverMask < 0.025) { - c = Color.white; - } - float[] hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null); - float bri = 90 + cell.biomeTypeMask * 10; - applet.fill(hsb[0] * 100, hsb[1] * 100, hsb[2] * bri); - return height * el; - } else if (applet.controller.getColorMode() == Applet.BIOME) { - float hue = applet.color(cell); - float sat = 70; - float bright = 50 + 50 * cell.riverMask; - applet.fill(hue, sat, bright); - return height * el; - } else if(applet.controller.getColorMode() == Applet.TERRAIN_TYPE) { - float hue = applet.color(cell); - if (cell.tag == applet.getCache().getTerrain().coast) { - hue = 15; - } - float modifier = cell.mask(0.4F, 0.5F, 0F, 1F); - float modAlpha = 0.1F; - float mod = (1 - modAlpha) + (modifier * modAlpha); - float sat = 70; - float bri = 70; - applet.fill(hue, 65, 70); - return height * el; - } else if(applet.controller.getColorMode() == Applet.EROSION) { - float change = cell.sediment + cell.erosion; - float value = Math.abs(cell.sediment * 250); - value = Math.max(0, Math.min(1, value)); - float hue = value * 70; - float sat = 70; - float bri = 70; - applet.fill(hue, sat, bri); - return height * el; - } else { - float hue = applet.color(cell); - float sat = 70; - float bri = 70; - applet.fill(hue, sat, bri); - return height * el; - } - } - - public abstract void render(float zoom); - - private void renderGradLine(int steps, float x1, float y1, float x2, float y2, float hue1, float hue2, float sat, float bright) { - float dx = x2 - x1; - float dy = y2 - y1; - float fx = dx / steps; - float fy = dy / steps; - float dhue = hue2 - hue1; - float fhue = dhue / steps; - for (int i = 0; i < steps; i++) { - float px1 = x1 + (i * fx); - float py1 = y1 + (i * fy); - float px2 = x2 + ((i + 1) * fx); - float py2 = y2 + ((i + 1) * fy); - float hue = (i + 1) * fhue; - applet.stroke(hue1 + hue, sat, bright); - applet.line(px1, py1, px2, py2); - } - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/VoxelRenderer.java b/TerraForgedApp/src/main/java/com/terraforged/app/renderer/VoxelRenderer.java deleted file mode 100644 index cb42b96..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/renderer/VoxelRenderer.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.app.renderer; - -import com.terraforged.app.Applet; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import processing.core.PApplet; - -public class VoxelRenderer extends Renderer { - - public VoxelRenderer(Applet visualizer) { - super(visualizer); - } - - @Override - public void render(float zoom) { - Levels levels = new Levels(applet.getCache().getSettings().generator); - int worldHeight = applet.getCache().getSettings().generator.world.worldHeight; - int waterLevel = levels.waterY; - int resolution = applet.getCache().getRegion().getBlockSize().size; - int center = resolution / 2; - - float w = applet.width / (float) resolution; - float h = applet.width / (float) resolution; - float el = w / zoom; - - applet.pushMatrix(); - applet.translate(-applet.width / 2F, -applet.width / 2F); - - int difX = Math.max(0, applet.getCache().getRegion().getBlockSize().size - resolution); - int difY = Math.max(0, applet.getCache().getRegion().getBlockSize().size - resolution); - int offsetX = difX / 2; - int offsetZ = difY / 2; - - for (int dy = 0; dy < resolution; dy++) { - for (int dx = 0; dx < resolution; dx++) { - Cell cell = applet.getCache().getRegion().getCell(dx + offsetX, dy + offsetZ); - - float cellHeight = cell.value * worldHeight; - int height = Math.min(worldHeight, Math.max(0, (int) cellHeight)); - - if (height < 0) { - continue; - } - - float x0 = dx * w; - float x1 = (dx + 1) * w; - float z0 = dy * h; - float z1 = (dy + 1) * h; - float y = getSurface(cell, height, waterLevel, el); - - if ((dx == center && (dy == center || dy - 1 == center || dy + 1 == center)) - || (dy == center && (dx - 1 == center || dx + 1 == center))) { - applet.fill(100F, 100F, 100F); - } - - drawColumn(x0, z0, 0, x1, z1, y); - } - } - - drawRulers(16, worldHeight, resolution, h, el); - - applet.popMatrix(); - } - - private void drawRulers(int step, int max, int resolution, float unit, float height) { - float width = (resolution + 1) * unit; - int doubleStep = step * 2; - - for (int dz = 0; dz <= 1; dz++) { - for (int dx = 0; dx <= 1; dx++) { - float x0 = dx * width; - float x1 = x0 - unit; - float z0 = dz * width; - float z1 = z0 - unit; - for (int dy = 0; dy < max; dy += step) { - float y0 = dy * height; - float y1 = y0 + (step * height); - float h = 100, s = 100, b = 100; - if ((dy % doubleStep) != step) { - s = 0; - } - applet.fill(h, s, b); - drawColumn(x0, z0, y0, x1, z1, y1); - } - } - } - } - - private void drawColumn(float x0, float y0, float z0, float x1, float y1, float z1) { - applet.beginShape(PApplet.QUADS); - // +Z "front" face - applet.vertex(x0, y0, z1); - applet.vertex(x1, y0, z1); - applet.vertex(x1, y1, z1); - applet.vertex(x0, y1, z1); - - // -Z "back" face - applet.vertex(x1, y0, z0); - applet.vertex(x0, y0, z0); - applet.vertex(x0, y1, z0); - applet.vertex(x1, y1, z0); - - // +Y "bottom" face - applet.vertex(x0, y1, z1); - applet.vertex(x1, y1, z1); - applet.vertex(x1, y1, z0); - applet.vertex(x0, y1, z0); - - // -Y "top" face - applet.vertex(x0, y0, z0); - applet.vertex(x1, y0, z0); - applet.vertex(x1, y0, z1); - applet.vertex(x0, y0, z1); - - // +X "right" face - applet.vertex(x1, y0, z1); - applet.vertex(x1, y0, z0); - applet.vertex(x1, y1, z0); - applet.vertex(x1, y1, z1); - - // -X "left" face - applet.vertex(x0, y0, z0); - applet.vertex(x0, y0, z1); - applet.vertex(x0, y1, z1); - applet.vertex(x0, y1, z0); - - applet.endShape(); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/util/JsonReader.java b/TerraForgedApp/src/main/java/com/terraforged/app/util/JsonReader.java deleted file mode 100644 index 7592af2..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/util/JsonReader.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.terraforged.app.util; - -import com.google.gson.JsonElement; -import com.terraforged.core.util.serialization.serializer.Reader; - -import java.util.Collection; -import java.util.Map; -import java.util.stream.Collectors; - -public class JsonReader implements Reader { - - private final JsonElement element; - - public JsonReader(JsonElement element) { - this.element = element; - } - - @Override - public int getSize() { - if (element.isJsonObject()) { - return element.getAsJsonObject().size(); - } - if (element.isJsonArray()) { - return element.getAsJsonArray().size(); - } - return 0; - } - - @Override - public Reader getChild(String key) { - return new JsonReader(element.getAsJsonObject().get(key)); - } - - @Override - public Reader getChild(int index) { - return new JsonReader(element.getAsJsonArray().get(index)); - } - - @Override - public Collection getKeys() { - return element.getAsJsonObject().entrySet().stream().map(Map.Entry::getKey).collect(Collectors.toList()); - } - - @Override - public String getString() { - return element.getAsString(); - } - - @Override - public boolean getBool() { - return element.getAsBoolean(); - } - - @Override - public float getFloat() { - return element.getAsFloat(); - } - - @Override - public int getInt() { - return element.getAsInt(); - } -} diff --git a/TerraForgedApp/src/main/java/com/terraforged/app/util/Loader.java b/TerraForgedApp/src/main/java/com/terraforged/app/util/Loader.java deleted file mode 100644 index 510a23f..0000000 --- a/TerraForgedApp/src/main/java/com/terraforged/app/util/Loader.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.terraforged.app.util; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.serialization.serializer.Deserializer; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.Reader; - -public class Loader { - - public static Settings load() { - Settings settings = new Settings(); - load(settings); - return settings; - } - - private static void load(Settings settings) { - try (Reader reader = new BufferedReader(new FileReader("terraforged-generator.json"))) { - JsonElement json = new JsonParser().parse(reader); - new Deserializer().deserialize(new JsonReader(json), settings); - } catch (Throwable e) { - e.printStackTrace(); - } - } -} diff --git a/TerraForgedApp/src/main/resources/biome_data.json b/TerraForgedApp/src/main/resources/biome_data.json deleted file mode 100644 index 1de2bf8..0000000 --- a/TerraForgedApp/src/main/resources/biome_data.json +++ /dev/null @@ -1,764 +0,0 @@ -[ - { - "id": "biomesoplenty:alps", - "moisture": 0.2, - "temperature": 0.1, - "color": -2302756 - }, - { - "id": "biomesoplenty:alps_foothills", - "moisture": 0.2, - "temperature": 0.1, - "color": -10461088 - }, - { - "id": "biomesoplenty:bayou", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "biomesoplenty:bog", - "moisture": 0.59999996, - "temperature": 0.42, - "color": -13592211 - }, - { - "id": "biomesoplenty:boreal_forest", - "moisture": 0.4, - "temperature": 0.32, - "color": -13592211 - }, - { - "id": "biomesoplenty:brushland", - "moisture": 0.06666667, - "temperature": 0.8, - "color": -13592211 - }, - { - "id": "biomesoplenty:chaparral", - "moisture": 0.29999998, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:cherry_blossom_grove", - "moisture": 0.59999996, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:cold_desert", - "moisture": 0.0, - "temperature": 0.3, - "color": -6034953 - }, - { - "id": "biomesoplenty:coniferous_forest", - "moisture": 0.33333334, - "temperature": 0.38, - "color": -13592211 - }, - { - "id": "biomesoplenty:dead_forest", - "moisture": 0.2, - "temperature": 0.32, - "color": -13592211 - }, - { - "id": "biomesoplenty:fir_clearing", - "moisture": 0.33333334, - "temperature": 0.38, - "color": -13592211 - }, - { - "id": "biomesoplenty:floodplain", - "moisture": 0.8, - "temperature": 0.56, - "color": -13592211 - }, - { - "id": "biomesoplenty:flower_meadow", - "moisture": 0.46666667, - "temperature": 0.35999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:grassland", - "moisture": 0.46666667, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:gravel_beach", - "moisture": 0.33333334, - "temperature": 0.44, - "color": -6034953 - }, - { - "id": "biomesoplenty:grove", - "moisture": 0.18333334, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:highland", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:highland_moor", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:lavender_field", - "moisture": 0.46666667, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:lush_grassland", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "biomesoplenty:lush_swamp", - "moisture": 0.6666667, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "biomesoplenty:mangrove", - "moisture": 0.46666667, - "temperature": 0.524, - "color": -13592211 - }, - { - "id": "biomesoplenty:maple_woods", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "biomesoplenty:marsh", - "moisture": 0.46666667, - "temperature": 0.45999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:meadow", - "moisture": 0.46666667, - "temperature": 0.35999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:mire", - "moisture": 0.59999996, - "temperature": 0.42, - "color": -13592211 - }, - { - "id": "biomesoplenty:mystic_grove", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "biomesoplenty:oasis", - "moisture": 0.33333334, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "biomesoplenty:ominous_woods", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:orchard", - "moisture": 0.26666668, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:outback", - "moisture": 0.033333335, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "biomesoplenty:overgrown_cliffs", - "moisture": 0.53333336, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "biomesoplenty:pasture", - "moisture": 0.2, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:prairie", - "moisture": 0.2, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:pumpkin_patch", - "moisture": 0.53333336, - "temperature": 0.35999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:rainforest", - "moisture": 1.0, - "temperature": 0.54, - "color": -13592211 - }, - { - "id": "biomesoplenty:redwood_forest", - "moisture": 0.4, - "temperature": 0.52, - "color": -12427646 - }, - { - "id": "biomesoplenty:redwood_forest_edge", - "moisture": 0.4, - "temperature": 0.52, - "color": -12427646 - }, - { - "id": "biomesoplenty:scrubland", - "moisture": 0.06666667, - "temperature": 0.64, - "color": -13592211 - }, - { - "id": "biomesoplenty:seasonal_forest", - "moisture": 0.53333336, - "temperature": 0.35999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:shield", - "moisture": 0.53333336, - "temperature": 0.35999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:shrubland", - "moisture": 0.033333335, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:silkglade", - "moisture": 0.13333334, - "temperature": 0.5, - "color": -13592211 - }, - { - "id": "biomesoplenty:snowy_coniferous_forest", - "moisture": 0.33333334, - "temperature": 0.1, - "color": -13592211 - }, - { - "id": "biomesoplenty:snowy_fir_clearing", - "moisture": 0.33333334, - "temperature": 0.1, - "color": -13592211 - }, - { - "id": "biomesoplenty:snowy_forest", - "moisture": 0.33333334, - "temperature": 0.1, - "color": -13592211 - }, - { - "id": "biomesoplenty:steppe", - "moisture": 0.033333335, - "temperature": 0.51, - "color": -13592211 - }, - { - "id": "biomesoplenty:temperate_rainforest", - "moisture": 0.8, - "temperature": 0.45999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:temperate_rainforest_hills", - "moisture": 0.8, - "temperature": 0.45999998, - "color": -13592211 - }, - { - "id": "biomesoplenty:tropical_rainforest", - "moisture": 0.6666667, - "temperature": 0.6, - "color": -13592211 - }, - { - "id": "biomesoplenty:tundra", - "moisture": 0.33333334, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "biomesoplenty:wasteland", - "moisture": 0.0, - "temperature": 1.0, - "color": -12427646 - }, - { - "id": "biomesoplenty:wetland", - "moisture": 0.46666667, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "biomesoplenty:white_beach", - "moisture": 0.6666667, - "temperature": 0.58000004, - "color": -6034953 - }, - { - "id": "biomesoplenty:woodland", - "moisture": 0.33333334, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "biomesoplenty:xeric_shrubland", - "moisture": 0.06666667, - "temperature": 0.9, - "color": -6034953 - }, - { - "id": "minecraft:badlands", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:badlands_plateau", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:bamboo_jungle", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "minecraft:bamboo_jungle_hills", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "minecraft:beach", - "moisture": 0.26666668, - "temperature": 0.52, - "color": -6034953 - }, - { - "id": "minecraft:birch_forest", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "minecraft:birch_forest_hills", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "minecraft:cold_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:dark_forest", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "minecraft:dark_forest_hills", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "minecraft:deep_cold_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:deep_frozen_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:deep_lukewarm_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:deep_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:deep_warm_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -6034953 - }, - { - "id": "minecraft:desert", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:desert_hills", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:desert_lakes", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:eroded_badlands", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:flower_forest", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "minecraft:forest", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "minecraft:frozen_ocean", - "moisture": 0.33333334, - "temperature": 0.2, - "color": -13592211 - }, - { - "id": "minecraft:frozen_river", - "moisture": 0.33333334, - "temperature": 0.2, - "color": -13592211 - }, - { - "id": "minecraft:giant_spruce_taiga", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "minecraft:giant_spruce_taiga_hills", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "minecraft:giant_tree_taiga", - "moisture": 0.53333336, - "temperature": 0.32, - "color": -13592211 - }, - { - "id": "minecraft:giant_tree_taiga_hills", - "moisture": 0.53333336, - "temperature": 0.32, - "color": -13592211 - }, - { - "id": "minecraft:gravelly_mountains", - "moisture": 0.2, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "minecraft:ice_spikes", - "moisture": 0.33333334, - "temperature": 0.2, - "color": -2302756 - }, - { - "id": "minecraft:jungle", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "minecraft:jungle_hills", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "minecraft:lukewarm_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:modified_badlands_plateau", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:modified_gravelly_mountains", - "moisture": 0.2, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "minecraft:modified_jungle", - "moisture": 0.59999996, - "temperature": 0.58000004, - "color": -13592211 - }, - { - "id": "minecraft:modified_wooded_badlands_plateau", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:mountains", - "moisture": 0.2, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "minecraft:mushroom_field_shore", - "moisture": 0.6666667, - "temperature": 0.56, - "color": -13592211 - }, - { - "id": "minecraft:mushroom_fields", - "moisture": 0.6666667, - "temperature": 0.56, - "color": -13592211 - }, - { - "id": "minecraft:ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:plains", - "moisture": 0.26666668, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "minecraft:river", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -13592211 - }, - { - "id": "minecraft:savanna", - "moisture": 0.0, - "temperature": 0.68, - "color": -13592211 - }, - { - "id": "minecraft:savanna_plateau", - "moisture": 0.0, - "temperature": 0.6, - "color": -13592211 - }, - { - "id": "minecraft:shattered_savanna", - "moisture": 0.0, - "temperature": 0.64, - "color": -13592211 - }, - { - "id": "minecraft:shattered_savanna_plateau", - "moisture": 0.0, - "temperature": 0.6, - "color": -13592211 - }, - { - "id": "minecraft:snowy_beach", - "moisture": 0.2, - "temperature": 0.22, - "color": -6034953 - }, - { - "id": "minecraft:snowy_mountains", - "moisture": 0.33333334, - "temperature": 0.2, - "color": -13592211 - }, - { - "id": "minecraft:snowy_taiga", - "moisture": 0.26666668, - "temperature": 0.0, - "color": -13592211 - }, - { - "id": "minecraft:snowy_taiga_hills", - "moisture": 0.26666668, - "temperature": 0.0, - "color": -13592211 - }, - { - "id": "minecraft:snowy_taiga_mountains", - "moisture": 0.26666668, - "temperature": 0.0, - "color": -13592211 - }, - { - "id": "minecraft:snowy_tundra", - "moisture": 0.33333334, - "temperature": 0.2, - "color": -13592211 - }, - { - "id": "minecraft:sunflower_plains", - "moisture": 0.26666668, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "minecraft:swamp", - "moisture": 0.59999996, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "minecraft:swamp_hills", - "moisture": 0.59999996, - "temperature": 0.52, - "color": -13592211 - }, - { - "id": "minecraft:taiga", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "minecraft:taiga_hills", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "minecraft:taiga_mountains", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - }, - { - "id": "minecraft:tall_birch_forest", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "minecraft:tall_birch_hills", - "moisture": 0.4, - "temperature": 0.44, - "color": -13592211 - }, - { - "id": "minecraft:warm_ocean", - "moisture": 0.33333334, - "temperature": 0.4, - "color": -6034953 - }, - { - "id": "minecraft:wooded_badlands_plateau", - "moisture": 0.0, - "temperature": 1.0, - "color": -6034953 - }, - { - "id": "minecraft:wooded_hills", - "moisture": 0.53333336, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "minecraft:wooded_mountains", - "moisture": 0.2, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "terraforged:cold_steppe", - "moisture": 0.06666667, - "temperature": 0.28, - "color": -13592211 - }, - { - "id": "terraforged:savanna_scrub", - "moisture": 0.0, - "temperature": 0.68, - "color": -13592211 - }, - { - "id": "terraforged:shattered_savanna_scrub", - "moisture": 0.0, - "temperature": 0.64, - "color": -13592211 - }, - { - "id": "terraforged:snowy_taiga_scrub", - "moisture": 0.26666668, - "temperature": 0.0, - "color": -13592211 - }, - { - "id": "terraforged:steppe", - "moisture": 0.06666667, - "temperature": 0.48000002, - "color": -13592211 - }, - { - "id": "terraforged:taiga_scrub", - "moisture": 0.53333336, - "temperature": 0.3, - "color": -13592211 - } -] \ No newline at end of file diff --git a/TerraForgedApp/src/main/resources/biome_groups.json b/TerraForgedApp/src/main/resources/biome_groups.json deleted file mode 100644 index 5eed0dd..0000000 --- a/TerraForgedApp/src/main/resources/biome_groups.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "TROPICAL_RAINFOREST": [ - "biomesoplenty:overgrown_cliffs", - "biomesoplenty:tropical_rainforest", - "minecraft:bamboo_jungle", - "minecraft:bamboo_jungle_hills", - "minecraft:jungle", - "minecraft:jungle_hills", - "minecraft:modified_jungle" - ], - "SAVANNA": [ - "biomesoplenty:brushland", - "biomesoplenty:scrubland", - "biomesoplenty:xeric_shrubland", - "minecraft:savanna", - "minecraft:savanna_plateau", - "minecraft:shattered_savanna", - "minecraft:shattered_savanna_plateau", - "terraforged:savanna_scrub", - "terraforged:shattered_savanna_scrub" - ], - "DESERT": [ - "biomesoplenty:oasis", - "biomesoplenty:outback", - "biomesoplenty:wasteland", - "minecraft:badlands", - "minecraft:badlands_plateau", - "minecraft:desert", - "minecraft:desert_hills", - "minecraft:desert_lakes", - "minecraft:eroded_badlands", - "minecraft:modified_badlands_plateau", - "minecraft:modified_wooded_badlands_plateau", - "minecraft:wooded_badlands_plateau" - ], - "TEMPERATE_RAINFOREST": [ - "biomesoplenty:rainforest", - "biomesoplenty:temperate_rainforest", - "biomesoplenty:temperate_rainforest_hills", - "minecraft:plains" - ], - "TEMPERATE_FOREST": [ - "biomesoplenty:cherry_blossom_grove", - "biomesoplenty:grove", - "biomesoplenty:mystic_grove", - "biomesoplenty:orchard", - "biomesoplenty:pumpkin_patch", - "biomesoplenty:redwood_forest", - "biomesoplenty:redwood_forest_edge", - "biomesoplenty:seasonal_forest", - "biomesoplenty:silkglade", - "biomesoplenty:temperate_rainforest", - "biomesoplenty:temperate_rainforest_hills", - "biomesoplenty:woodland", - "minecraft:birch_forest", - "minecraft:birch_forest_hills", - "minecraft:dark_forest", - "minecraft:flower_forest", - "minecraft:forest", - "minecraft:plains", - "minecraft:tall_birch_forest", - "minecraft:wooded_hills" - ], - "GRASSLAND": [ - "biomesoplenty:bayou", - "biomesoplenty:bog", - "biomesoplenty:chaparral", - "biomesoplenty:floodplain", - "biomesoplenty:grassland", - "biomesoplenty:highland_moor", - "biomesoplenty:lavender_field", - "biomesoplenty:lush_grassland", - "biomesoplenty:lush_swamp", - "biomesoplenty:mangrove", - "biomesoplenty:marsh", - "biomesoplenty:mire", - "biomesoplenty:pasture", - "biomesoplenty:prairie", - "biomesoplenty:shrubland", - "biomesoplenty:steppe", - "biomesoplenty:wetland", - "minecraft:plains", - "minecraft:sunflower_plains", - "minecraft:swamp" - ], - "COLD_STEPPE": [ - "terraforged:cold_steppe" - ], - "STEPPE": [ - "biomesoplenty:steppe", - "terraforged:steppe" - ], - "TAIGA": [ - "biomesoplenty:boreal_forest", - "biomesoplenty:coniferous_forest", - "biomesoplenty:dead_forest", - "biomesoplenty:fir_clearing", - "biomesoplenty:flower_meadow", - "biomesoplenty:maple_woods", - "biomesoplenty:meadow", - "biomesoplenty:ominous_woods", - "biomesoplenty:shield", - "biomesoplenty:tundra", - "minecraft:giant_spruce_taiga", - "minecraft:giant_tree_taiga", - "minecraft:giant_tree_taiga_hills", - "minecraft:taiga", - "minecraft:taiga_hills", - "terraforged:taiga_scrub" - ], - "TUNDRA": [ - "biomesoplenty:alps", - "biomesoplenty:alps_foothills", - "biomesoplenty:snowy_coniferous_forest", - "biomesoplenty:snowy_fir_clearing", - "biomesoplenty:snowy_forest", - "minecraft:ice_spikes", - "minecraft:snowy_taiga", - "minecraft:snowy_taiga_hills", - "minecraft:snowy_tundra", - "terraforged:snowy_taiga_scrub" - ], - "ALPINE": [ - "biomesoplenty:highland", - "minecraft:gravelly_mountains", - "minecraft:modified_gravelly_mountains", - "minecraft:mountains", - "minecraft:snowy_mountains", - "minecraft:snowy_taiga_mountains", - "minecraft:taiga_mountains", - "minecraft:wooded_mountains" - ], - "rivers": { - "COLD": [ - "minecraft:frozen_river" - ], - "MEDIUM": [ - "minecraft:river" - ], - "WARM": [] - }, - "oceans": { - "COLD": [ - "minecraft:cold_ocean", - "minecraft:frozen_ocean" - ], - "MEDIUM": [ - "minecraft:ocean" - ], - "WARM": [ - "minecraft:lukewarm_ocean", - "minecraft:warm_ocean" - ] - }, - "deep_oceans": { - "COLD": [ - "minecraft:deep_cold_ocean", - "minecraft:deep_frozen_ocean" - ], - "MEDIUM": [ - "minecraft:deep_ocean" - ], - "WARM": [ - "minecraft:deep_lukewarm_ocean", - "minecraft:deep_warm_ocean" - ] - } -} \ No newline at end of file diff --git a/TerraForgedApp/src/main/resources/grass.png b/TerraForgedApp/src/main/resources/grass.png deleted file mode 100644 index f59dd38b3942f844f952cd1fbd63176df4beba65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7146 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

GMq3D5LC4$OZ952(rH$x}`Qe54X6n-JY1*tu`jG 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 bP!ew$x|6b$Cp?o}+5k;8UDdKXR)PNq_#Qy4 diff --git a/TerraForgedApp/src/main/resources/license.txt b/TerraForgedApp/src/main/resources/license.txt deleted file mode 100644 index 0b31935..0000000 --- a/TerraForgedApp/src/main/resources/license.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 TerraForged - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/TerraForgedCore/build.gradle b/TerraForgedCore/build.gradle deleted file mode 100644 index f68ce7d..0000000 --- a/TerraForgedCore/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -apply plugin: "maven-publish" - -repositories { - mavenCentral() -} - -dependencies { - compile project(":Noise2D") - compile "it.unimi.dsi:fastutil:8.2.1" -} - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - - if (System.getenv("MAVEN_USER") != null && System.getenv("MAVEN_PASS") != null) { - repositories { - maven { - credentials { - username System.getenv("MAVEN_USER") - password System.getenv("MAVEN_PASS") - } - name = "nexus" - url = "https://io.terraforged.com/repository/maven/" - } - } - } -} \ No newline at end of file diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Cell.java b/TerraForgedCore/src/main/java/com/terraforged/core/cell/Cell.java deleted file mode 100644 index f1b99fe..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Cell.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.cell; - -import com.terraforged.core.util.concurrent.ObjectPool; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.util.NoiseUtil; - -public class Cell { - - private static final Cell EMPTY = new Cell() { - @Override - public boolean isAbsent() { - return true; - } - }; - - private static final ObjectPool> POOL = new ObjectPool<>(100, Cell::new); - - public float continent; - public float continentEdge; - public float region; - public float regionEdge; - public float biome; - public float biomeEdge = 1F; - public float riverMask = 1F; - - public float value; - public float biomeMoisture; - public float biomeTemperature; - public float moisture; - public float temperature; - public float steepness; - public float erosion; - public float sediment; - public float biomeTypeMask = 1F; - public BiomeType biomeType = BiomeType.GRASSLAND; - - public T tag = null; - - public void copy(Cell other) { - value = other.value; - - continent = other.continent; - continentEdge = other.continentEdge; - - region = other.region; - regionEdge = other.regionEdge; - - biome = other.biome; - biomeEdge = other.biomeEdge; - - riverMask = other.riverMask; - - moisture = other.moisture; - temperature = other.temperature; - biomeMoisture = other.biomeMoisture; - biomeTemperature = other.biomeTemperature; - - steepness = other.steepness; - erosion = other.erosion; - sediment = other.sediment; - biomeType = other.biomeType; - biomeTypeMask = other.biomeTypeMask; - - tag = other.tag; - } - - public float continentMask(float min, float max) { - return NoiseUtil.map(continentEdge, min, max, max - min); - } - - public float regionMask(float min, float max) { - return NoiseUtil.map(regionEdge, min, max, max - min); - } - - public float biomeMask(float min, float max) { - return NoiseUtil.map(biomeEdge, min, max, max - min); - } - - public float mask(float cmin, float cmax, float rmin, float rmax) { - return riverMask * continentMask(cmin, cmax) * regionMask(rmin, rmax); - } - - public boolean isAbsent() { - return false; - } - - @SuppressWarnings("unchecked") - public static Cell empty() { - return EMPTY; - } - - public static ObjectPool.Item> pooled() { - return POOL.get(); - } - - public interface Visitor { - - void visit(Cell cell, int dx, int dz); - } - - public interface ContextVisitor { - - void visit(Cell cell, int dx, int dz, C ctx); - } - - public interface ZoomVisitor { - - void visit(Cell cell, float x, float z); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Extent.java b/TerraForgedCore/src/main/java/com/terraforged/core/cell/Extent.java deleted file mode 100644 index 0d8af1e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Extent.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.cell; - -import com.terraforged.core.world.terrain.Terrain; - -public interface Extent { - - void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor visitor); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Populator.java b/TerraForgedCore/src/main/java/com/terraforged/core/cell/Populator.java deleted file mode 100644 index 60fc88d..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Populator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.cell; - -import com.terraforged.core.util.concurrent.ObjectPool; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; - -public interface Populator extends Module { - - void apply(Cell cell, float x, float y); - - void tag(Cell cell, float x, float y); - - @Override - default float getValue(float x, float z) { - try (ObjectPool.Item> cell = Cell.pooled()) { - apply(cell.getValue(), x, z); - return cell.getValue().value; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Tag.java b/TerraForgedCore/src/main/java/com/terraforged/core/cell/Tag.java deleted file mode 100644 index 5cf6ad8..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/cell/Tag.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.cell; - -public interface Tag { - - String getName(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Erosion.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Erosion.java deleted file mode 100644 index b6228c1..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Erosion.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.region.Size; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.world.heightmap.Levels; -import me.dags.noise.util.NoiseUtil; - -import java.util.Random; - -/* - * This class in an adaption of the work by Sebastian Lague which is also licensed under MIT. - * Reference: - * https://github.com/SebLague/Hydraulic-Erosion/blob/Coding-Adventure-E01/Assets/Scripts/Erosion.cs - * https://github.com/SebLague/Hydraulic-Erosion/blob/Coding-Adventure-E01/LICENSE - * - * License In Full: - * MIT License - * - * Copyright (c) 2019 Sebastian Lague - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -public class Erosion implements Filter { - - private int erosionRadius = 3; - private float inertia = 0.05f; - private float sedimentCapacityFactor = 4; - private float minSedimentCapacity = 0.01f; - private float erodeSpeed = 0.3f; - private float depositSpeed = 0.3f; - private float evaporateSpeed = 0.01f; - private float gravity = 8; - private int maxDropletLifetime = 30; - private float initialWaterVolume = 1; - private float initialSpeed = 1; - private final TerrainPos gradient = new TerrainPos(); - private int[][] erosionBrushIndices = new int[0][]; - private float[][] erosionBrushWeights = new float[0][]; - - private final Modifier modifier; - private final Random random = new Random(); - - public Erosion(Settings settings, Levels levels) { - erodeSpeed = settings.filters.erosion.erosionRate; - depositSpeed = settings.filters.erosion.depositeRate; - modifier = Modifier.range(levels.ground, levels.ground(15)); - } - - @Override - public void apply(Filterable map, int seedX, int seedZ, int iterations) { - if (erosionBrushIndices.length != map.getSize().total) { - init(map.getSize().total, erosionRadius); - } - - applyMain(map, seedX, seedZ, iterations, random); - -// applyNeighbours(map, seedX, seedZ, iterations, random); - } - - private int nextCoord(Size size, Random random) { - return random.nextInt(size.total - 1); - } - - private void applyMain(Filterable map, int seedX, int seedZ, int iterations, Random random) { - random.setSeed(NoiseUtil.seed(seedX, seedZ)); - while (iterations-- > 0) { - int posX = nextCoord(map.getSize(), random); - int posZ = nextCoord(map.getSize(), random); - apply(map.getBacking(), posX, posZ, map.getSize().total); - } - } - - private void apply(Cell[] cells, float posX, float posY, int size) { - float dirX = 0; - float dirY = 0; - float speed = initialSpeed; - float water = initialWaterVolume; - float sediment = 0; - - for (int lifetime = 0; lifetime < maxDropletLifetime; lifetime++) { - int nodeX = (int) posX; - int nodeY = (int) posY; - int dropletIndex = nodeY * size + nodeX; - // Calculate droplet's offset inside the cell (0,0) = at NW node, (1,1) = at SE node - float cellOffsetX = posX - nodeX; - float cellOffsetY = posY - nodeY; - - // Calculate droplet's height and direction of flow with bilinear interpolation of surrounding heights - gradient.update(cells, size, posX, posY); - - // Update the droplet's direction and position (move position 1 unit regardless of speed) - dirX = (dirX * inertia - gradient.gradientX * (1 - inertia)); - dirY = (dirY * inertia - gradient.gradientY * (1 - inertia)); - - // Normalize direction - float len = (float) Math.sqrt(dirX * dirX + dirY * dirY); - if (Float.isNaN(len)) { - len = 0; - } - - if (len != 0) { - dirX /= len; - dirY /= len; - } - - posX += dirX; - posY += dirY; - - // Stop simulating droplet if it's not moving or has flowed over edge of map - if ((dirX == 0 && dirY == 0) || posX < 0 || posX >= size - 1 || posY < 0 || posY >= size - 1) { - break; - } - - // Find the droplet's new height and calculate the deltaHeight - float oldHeight = gradient.height; - float newHeight = gradient.update(cells, size, posX, posY).height; - float deltaHeight = newHeight - oldHeight; - - // Calculate the droplet's sediment capacity (higher when moving fast down a slope and contains lots of water) - float sedimentCapacity = Math.max(-deltaHeight * speed * water * sedimentCapacityFactor, minSedimentCapacity); - - // If carrying more sediment than capacity, or if flowing uphill: - if (sediment > sedimentCapacity || deltaHeight > 0) { - // If moving uphill (deltaHeight > 0) try fill up to the current height, otherwise deposit a fraction of the excess sediment - float amountToDeposit = (deltaHeight > 0) ? Math.min(deltaHeight, sediment) : (sediment - sedimentCapacity) * depositSpeed; - sediment -= amountToDeposit; - - // Add the sediment to the four nodes of the current cell using bilinear interpolation - // Deposition is not distributed over a radius (like erosion) so that it can fill small pits - deposit(cells[dropletIndex], amountToDeposit * (1 - cellOffsetX) * (1 - cellOffsetY)); - deposit(cells[dropletIndex + 1], amountToDeposit * cellOffsetX * (1 - cellOffsetY)); - deposit(cells[dropletIndex + size], amountToDeposit * (1 - cellOffsetX) * cellOffsetY); - deposit(cells[dropletIndex + size + 1], amountToDeposit * cellOffsetX * cellOffsetY); - } else { - // Erode a fraction of the droplet's current carry capacity. - // Clamp the erosion to the change in height so that it doesn't dig a hole in the terrain behind the droplet - float amountToErode = Math.min((sedimentCapacity - sediment) * erodeSpeed, -deltaHeight); - - // Use erosion brush to erode from all nodes inside the droplet's erosion radius - for (int brushPointIndex = 0; brushPointIndex < erosionBrushIndices[dropletIndex].length; brushPointIndex++) { - int nodeIndex = erosionBrushIndices[dropletIndex][brushPointIndex]; - Cell cell = cells[nodeIndex]; - float brushWeight = erosionBrushWeights[dropletIndex][brushPointIndex]; - float weighedErodeAmount = amountToErode * brushWeight; - float deltaSediment = Math.min(cell.value, weighedErodeAmount);//cell.value < weighedErodeAmount) ? cell.value : weighedErodeAmount; - erode(cell, deltaSediment); - sediment += deltaSediment; - } - } - - // Update droplet's speed and water content - speed = (float) Math.sqrt(speed * speed + deltaHeight * gravity); - water *= (1 - evaporateSpeed); - - if (Float.isNaN(speed)) { - speed = 0; - } - } - } - - private void init(int size, int radius) { - erosionBrushIndices = new int[size * size][]; - erosionBrushWeights = new float[size * size][]; - - int[] xOffsets = new int[radius * radius * 4]; - int[] yOffsets = new int[radius * radius * 4]; - float[] weights = new float[radius * radius * 4]; - float weightSum = 0; - int addIndex = 0; - - for (int i = 0; i < erosionBrushIndices.length; i++) { - int centreX = i % size; - int centreY = i / size; - - if (centreY <= radius || centreY >= size - radius || centreX <= radius + 1 || centreX >= size - radius) { - weightSum = 0; - addIndex = 0; - for (int y = -radius; y <= radius; y++) { - for (int x = -radius; x <= radius; x++) { - float sqrDst = x * x + y * y; - if (sqrDst < radius * radius) { - int coordX = centreX + x; - int coordY = centreY + y; - - if (coordX >= 0 && coordX < size && coordY >= 0 && coordY < size) { - float weight = 1 - (float) Math.sqrt(sqrDst) / radius; - weightSum += weight; - weights[addIndex] = weight; - xOffsets[addIndex] = x; - yOffsets[addIndex] = y; - addIndex++; - } - } - } - } - } - - int numEntries = addIndex; - erosionBrushIndices[i] = new int[numEntries]; - erosionBrushWeights[i] = new float[numEntries]; - - for (int j = 0; j < numEntries; j++) { - erosionBrushIndices[i][j] = (yOffsets[j] + centreY) * size + xOffsets[j] + centreX; - erosionBrushWeights[i][j] = weights[j] / weightSum; - } - } - } - - private void deposit(Cell cell, float amount) { - float change = modifier.modify(cell, amount); - cell.value += change; - cell.sediment += change; - } - - private void erode(Cell cell, float amount) { - float change = modifier.modify(cell, amount); - cell.value -= change; - cell.erosion -= change; - } - - private static class TerrainPos { - private float height; - private float gradientX; - private float gradientY; - - private TerrainPos update(Cell[] nodes, int mapSize, float posX, float posY) { - int coordX = (int) posX; - int coordY = (int) posY; - - // Calculate droplet's offset inside the cell (0,0) = at NW node, (1,1) = at SE node - float x = posX - coordX; - float y = posY - coordY; - - // Calculate heights of the four nodes of the droplet's cell - int nodeIndexNW = coordY * mapSize + coordX; - float heightNW = nodes[nodeIndexNW].value; - float heightNE = nodes[nodeIndexNW + 1].value; - float heightSW = nodes[nodeIndexNW + mapSize].value; - float heightSE = nodes[nodeIndexNW + mapSize + 1].value; - - // Calculate droplet's direction of flow with bilinear interpolation of height difference along the edges - this.gradientX = (heightNE - heightNW) * (1 - y) + (heightSE - heightSW) * y; - this.gradientY = (heightSW - heightNW) * (1 - x) + (heightSE - heightNE) * x; - // Calculate height with bilinear interpolation of the heights of the nodes of the cell - this.height = heightNW * (1 - x) * (1 - y) + heightNE * x * (1 - y) + heightSW * (1 - x) * y + heightSE * x * y; - return this; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filter.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filter.java deleted file mode 100644 index 483ba90..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filter.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; - -public interface Filter { - - void apply(Filterable map, int seedX, int seedZ, int iterations); - - default void iterate(Filterable map, Visitor visitor) { - for (int dz = 0; dz < map.getSize().total; dz++) { - for (int dx = 0; dx < map.getSize().total; dx++) { - Cell cell = map.getCellRaw(dx, dz); - visitor.visit(map, cell, dx, dz); - } - } - } - - interface Visitor { - - void visit(Filterable cellMap, Cell cell, int dx, int dz); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filterable.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filterable.java deleted file mode 100644 index bc11e86..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Filterable.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Tag; -import com.terraforged.core.region.Size; - -public interface Filterable { - - Size getSize(); - - Cell[] getBacking(); - - Cell getCellRaw(int x, int z); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Modifier.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Modifier.java deleted file mode 100644 index bfb9f22..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Modifier.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; - -public interface Modifier { - - float getModifier(float value); - - default float modify(Cell cell, float value) { - return value * getModifier(cell.value); - } - - default Modifier invert() { - return v -> 1 - getModifier(v); - } - - static Modifier range(float minValue, float maxValue) { - return new Modifier() { - - private final float min = minValue; - private final float max = maxValue; - private final float range = maxValue - minValue; - - @Override - public float getModifier(float value) { - if (value > max) { - return 1F; - } - if (value < min) { - return 0F; - } - return (value - min) / range; - } - }; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Smoothing.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Smoothing.java deleted file mode 100644 index 7e7e462..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Smoothing.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.world.heightmap.Levels; -import me.dags.noise.util.NoiseUtil; - -public class Smoothing implements Filter { - - private final int radius; - private final float rad2; - private final float strength; - private final Modifier modifier; - - public Smoothing(Settings settings, Levels levels) { - this.radius = NoiseUtil.round(settings.filters.smoothing.smoothingRadius + 0.5F); - this.rad2 = settings.filters.smoothing.smoothingRadius * settings.filters.smoothing.smoothingRadius; - this.strength = settings.filters.smoothing.smoothingRate; - this.modifier = Modifier.range(levels.ground(1), levels.ground(120)).invert(); - } - - @Override - public void apply(Filterable map, int seedX, int seedZ, int iterations) { - while (iterations-- > 0) { - apply(map); - } - } - - private void apply(Filterable cellMap) { - int maxZ = cellMap.getSize().total - radius; - int maxX = cellMap.getSize().total - radius; - for (int z = radius; z < maxZ; z++) { - for (int x = radius; x < maxX; x++) { - Cell cell = cellMap.getCellRaw(x, z); - - float total = 0; - float weights = 0; - - for (int dz = -radius; dz <= radius; dz++) { - for (int dx = -radius; dx <= radius; dx++) { - float dist2 = dx * dx + dz * dz; - if (dist2 > rad2) { - continue; - } - int px = x + dx; - int pz = z + dz; - Cell neighbour = cellMap.getCellRaw(px, pz); - if (neighbour.isAbsent()) { - continue; - } - float value = neighbour.value; - float weight = 1F - (dist2 / rad2); - total += (value * weight); - weights += weight; - } - } - - if (weights > 0) { - float dif = cell.value - (total / weights); - cell.value -= modifier.modify(cell, dif * strength); - } - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java deleted file mode 100644 index dc16467..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.filter; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrains; - -public class Steepness implements Filter, Filter.Visitor { - - private final int radius; - private final float scaler; - private final float waterLevel; - private final float maxBeachLevel; - private final Terrains terrains; - - public Steepness(int radius, float scaler, Terrains terrains, Levels levels) { - this.radius = radius; - this.scaler = scaler; - this.terrains = terrains; - this.waterLevel = levels.water; - this.maxBeachLevel = levels.water(6); - } - - @Override - public void apply(Filterable cellMap, int seedX, int seedZ, int iterations) { - iterate(cellMap, this); - } - - @Override - public void visit(Filterable cellMap, Cell cell, int cx, int cz) { - float totalHeightDif = 0F; - for (int dz = -1; dz <= 2; dz++) { - for (int dx = -1; dx <= 2; dx++) { - if (dx == 0 && dz == 0) { - continue; - } - - int x = cx + dx * radius; - int z = cz + dz * radius; - Cell neighbour = cellMap.getCellRaw(x, z); - if (neighbour.isAbsent()) { - continue; - } - - float height = Math.max(neighbour.value, waterLevel); - - totalHeightDif += (Math.abs(cell.value - height) / radius); - } - } - cell.steepness = Math.min(1, totalHeightDif * scaler); - if (cell.tag == terrains.coast && cell.steepness < 0.225F && cell.value < maxBeachLevel) { - cell.tag = terrains.beach; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/module/Blender.java b/TerraForgedCore/src/main/java/com/terraforged/core/module/Blender.java deleted file mode 100644 index 2cd17d2..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/module/Blender.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.module; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.func.Interpolation; -import me.dags.noise.util.NoiseUtil; - -public class Blender extends Select implements Populator { - - private final Populator lower; - private final Populator upper; - - private final float blendLower; - private final float blendUpper; - private final float blendRange; - private final float midpoint; - private final float tagThreshold; - - public Blender(Module control, Populator lower, Populator upper, float min, float max, float split) { - super(control); - this.lower = lower; - this.upper = upper; - this.blendLower = min; - this.blendUpper = max; - this.blendRange = blendUpper - blendLower; - this.midpoint = blendLower + (blendRange * split); - this.tagThreshold = midpoint; - } - - public Blender(Populator control, Populator lower, Populator upper, float min, float max, float split, float tagThreshold) { - super(control); - this.lower = lower; - this.upper = upper; - this.blendLower = min; - this.blendUpper = max; - this.blendRange = blendUpper - blendLower; - this.midpoint = blendLower + (blendRange * split); - this.tagThreshold = tagThreshold; - } - - @Override - public void apply(Cell cell, float x, float y) { - float select = getSelect(cell, x, y); - - if (select < blendLower) { - lower.apply(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.apply(cell, x, y); - return; - } - - float alpha = Interpolation.LINEAR.apply((select - blendLower) / blendRange); - lower.apply(cell, x, y); - - float lowerVal = cell.value; - Terrain lowerType = cell.tag; - - upper.apply(cell, x, y); - float upperVal = cell.value; - - cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha); - if (select < midpoint) { - cell.tag = lowerType; - } - } - - @Override - public void tag(Cell cell, float x, float y) { - float select = getSelect(cell, x, y); - if (select < blendLower) { - lower.tag(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.tag(cell, x, y); - return; - } - - if (select < tagThreshold) { - lower.tag(cell, x, y); - } else { - upper.tag(cell, x, y); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/module/MultiBlender.java b/TerraForgedCore/src/main/java/com/terraforged/core/module/MultiBlender.java deleted file mode 100644 index 121015d..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/module/MultiBlender.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.module; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.func.Interpolation; -import me.dags.noise.util.NoiseUtil; - -public class MultiBlender extends Select implements Populator { - - private final Climate climate; - private final Populator lower; - private final Populator middle; - private final Populator upper; - private final float midpoint; - - private final float blendLower; - private final float blendUpper; - - private final float lowerRange; - private final float upperRange; - - public MultiBlender(Climate climate, Populator control, Populator lower, Populator middle, Populator upper, float min, float mid, float max) { - super(control); - this.climate = climate; - this.lower = lower; - this.upper = upper; - this.middle = middle; - - this.midpoint = mid; - this.blendLower = min; - this.blendUpper = max; - - this.lowerRange = midpoint - blendLower; - this.upperRange = blendUpper - midpoint; - } - - @Override - public void apply(Cell cell, float x, float y) { - float select = getSelect(cell, x, y); - if (select < blendLower) { - lower.apply(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.apply(cell, x, y); - return; - } - - if (select < midpoint) { - float alpha = Interpolation.CURVE3.apply((select - blendLower) / lowerRange); - - lower.apply(cell, x, y); - float lowerVal = cell.value; - Terrain lowerType = cell.tag; - - middle.apply(cell, x, y); - float upperVal = cell.value; - - cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha); - } else { - float alpha = Interpolation.CURVE3.apply((select - midpoint) / upperRange); - - middle.apply(cell, x, y); - float lowerVal = cell.value; - - upper.apply(cell, x, y); - cell.value = NoiseUtil.lerp(lowerVal, cell.value, alpha); - } - } - - @Override - public void tag(Cell cell, float x, float y) { - float select = getSelect(cell, x, y); - if (select < blendLower) { - lower.tag(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.tag(cell, x, y); - return; - } - - if (select < midpoint) { - lower.tag(cell, x, y); -// upper.tag(cell, x, y); - if (cell.value > cell.tag.getMax(climate.getRand().getValue(x, y))) { - upper.tag(cell, x, y); - } - } else { - upper.tag(cell, x, y); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/module/Select.java b/TerraForgedCore/src/main/java/com/terraforged/core/module/Select.java deleted file mode 100644 index c77fcf9..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/module/Select.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.module; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; - -public class Select { - - private final Module control; - - public Select(Module control) { - this.control = control; - } - - public float getSelect(Cell cell, float x, float y) { - return control.getValue(x, y); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java deleted file mode 100644 index b4a145f..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Extent; -import com.terraforged.core.filter.Filterable; -import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.core.region.chunk.ChunkWriter; -import com.terraforged.core.util.concurrent.Disposable; -import com.terraforged.core.world.decorator.Decorator; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.rivermap.RiverRegionList; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.util.NoiseUtil; - -import java.util.Collection; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -public class Region implements Extent, Disposable { - - private final int regionX; - private final int regionZ; - private final int chunkX; - private final int chunkZ; - private final int blockX; - private final int blockZ; - private final int border; - private final Size blockSize; - private final Size chunkSize; - private final GenCell[] blocks; - private final GenChunk[] chunks; - private final int disposableChunks; - private final Disposable.Listener disposalListener; - private final AtomicInteger disposedChunks = new AtomicInteger(); - - public Region(int regionX, int regionZ, int size, int borderChunks) { - this(regionX, regionZ, size, borderChunks, region -> {}); - } - - public Region(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener disposalListener) { - this.regionX = regionX; - this.regionZ = regionZ; - this.chunkX = regionX << size; - this.chunkZ = regionZ << size; - this.blockX = Size.chunkToBlock(chunkX); - this.blockZ = Size.chunkToBlock(chunkZ); - this.border = borderChunks; - this.chunkSize = Size.chunks(size, borderChunks); - this.blockSize = Size.blocks(size, borderChunks); - this.disposalListener = disposalListener; - this.disposableChunks = chunkSize.size * chunkSize.size; - this.blocks = new GenCell[blockSize.total * blockSize.total]; - this.chunks = new GenChunk[chunkSize.total * chunkSize.total]; - } - - @Override - public void dispose() { - int disposed = disposedChunks.incrementAndGet(); - if (disposed < disposableChunks) { - return; - } - disposalListener.onDispose(this); - } - - public long getRegionId() { - return NoiseUtil.seed(getRegionX(), getRegionZ()); - } - - public int getRegionX() { - return regionX; - } - - public int getRegionZ() { - return regionZ; - } - - public int getBlockX() { - return blockX; - } - - public int getBlockZ() { - return blockZ; - } - - public int getOffsetChunks() { - return border; - } - - public int getChunkCount() { - return chunks.length; - } - - public int getBlockCount() { - return blocks.length; - } - - public Size getChunkSize() { - return chunkSize; - } - - public Size getBlockSize() { - return blockSize; - } - - public Filterable filterable() { - return new FilterRegion(); - } - - public Cell getCell(int blockX, int blockZ) { - int relBlockX = blockSize.border + blockSize.mask(blockX); - int relBlockZ = blockSize.border + blockSize.mask(blockZ); - int index = blockSize.indexOf(relBlockX, relBlockZ); - return blocks[index]; - } - - public Cell getRawCell(int blockX, int blockZ) { - int index = blockSize.indexOf(blockX, blockZ); - return blocks[index]; - } - - public ChunkReader getChunk(int chunkX, int chunkZ) { - int relChunkX = chunkSize.border + chunkSize.mask(chunkX); - int relChunkZ = chunkSize.border + chunkSize.mask(chunkZ); - int index = chunkSize.indexOf(relChunkX, relChunkZ); - return chunks[index]; - } - - public void generate(Consumer consumer) { - for (int cz = 0; cz < chunkSize.total; cz++) { - for (int cx = 0; cx < chunkSize.total; cx++) { - int index = chunkSize.indexOf(cx, cz); - GenChunk chunk = computeChunk(index, cx, cz); - consumer.accept(chunk); - } - } - } - - public void generateBase(Heightmap heightmap) { - for (int cz = 0; cz < chunkSize.total; cz++) { - for (int cx = 0; cx < chunkSize.total; cx++) { - int index = chunkSize.indexOf(cx, cz); - GenChunk chunk = computeChunk(index, cx, cz); - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - float x = chunk.getBlockX() + dx; - float z = chunk.getBlockZ() + dz; - Cell cell = chunk.genCell(dx, dz); - heightmap.applyBase(cell, x, z); - } - } - } - } - } - - public void generateRivers(Heightmap heightmap, RiverRegionList rivers) { - for (int cz = 0; cz < chunkSize.total; cz++) { - for (int cx = 0; cx < chunkSize.total; cx++) { - int index = chunkSize.indexOf(cx, cz); - GenChunk chunk = computeChunk(index, cx, cz); - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - float x = chunk.getBlockX() + dx; - float z = chunk.getBlockZ() + dz; - Cell cell = chunk.genCell(dx, dz); - heightmap.applyRivers(cell, x, z, rivers); - heightmap.applyClimate(cell, x, z); - } - } - } - } - } - - public void generateZoom(Heightmap heightmap, float offsetX, float offsetZ, float zoom) { - float translateX = offsetX - ((blockSize.size * zoom) / 2F); - float translateZ = offsetZ - ((blockSize.size * zoom) / 2F); - for (int cz = 0; cz < chunkSize.total; cz++) { - for (int cx = 0; cx < chunkSize.total; cx++) { - int index = chunkSize.indexOf(cx, cz); - GenChunk chunk = computeChunk(index, cx, cz); - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - float x = ((chunk.getBlockX() + dx) * zoom) + translateX; - float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ; - Cell cell = chunk.genCell(dx, dz); - heightmap.apply(cell, x, z); - } - } - } - } - } - - public void decorate(Collection decorators) { - for (int dz = 0; dz < blockSize.total; dz++) { - for (int dx = 0; dx < blockSize.total; dx++) { - int index = blockSize.indexOf(dx, dz); - GenCell cell = blocks[index]; - for (Decorator decorator : decorators) { - if (decorator.apply(cell, getBlockX() + dx, getBlockZ() + dz)) { - break; - } - } - } - } - } - - public void decorateZoom(Collection decorators, float offsetX, float offsetZ, float zoom) { - float translateX = offsetX - ((blockSize.size * zoom) / 2F); - float translateZ = offsetZ - ((blockSize.size * zoom) / 2F); - for (int cz = 0; cz < chunkSize.total; cz++) { - for (int cx = 0; cx < chunkSize.total; cx++) { - int index = chunkSize.indexOf(cx, cz); - GenChunk chunk = computeChunk(index, cx, cz); - chunk.iterate((cell, dx, dz) -> { - float x = ((chunk.getBlockX() + dx) * zoom) + translateX; - float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ; - for (Decorator decorator : decorators) { - decorator.apply(cell, x, z); - } - }); - } - } - } - - public void iterate(Consumer consumer) { - for (int cz = 0; cz < chunkSize.size; cz++) { - int chunkZ = chunkSize.border + cz; - for (int cx = 0; cx < chunkSize.size; cx++) { - int chunkX = chunkSize.border + cx; - int index = chunkSize.indexOf(chunkX, chunkZ); - GenChunk chunk = chunks[index]; - consumer.accept(chunk); - } - } - } - - public void iterate(Cell.Visitor visitor) { - for (int dz = 0; dz < blockSize.size; dz++) { - int z = blockSize.border + dz; - for (int dx = 0; dx < blockSize.size; dx++) { - int x = blockSize.border + dx; - int index = blockSize.indexOf(x, z); - GenCell cell = blocks[index]; - visitor.visit(cell, dx, dz); - } - } - } - - @Override - public void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor visitor) { - int regionMinX = getBlockX(); - int regionMinZ = getBlockZ(); - if (maxX < regionMinX || maxZ < regionMinZ) { - return; - } - - int regionMaxX = getBlockX() + getBlockSize().size - 1; - int regionMaxZ = getBlockZ() + getBlockSize().size - 1; - if (minX > regionMaxX || maxZ > regionMaxZ) { - return; - } - - minX = Math.max(minX, regionMinX); - minZ = Math.max(minZ, regionMinZ); - maxX = Math.min(maxX, regionMaxX); - maxZ = Math.min(maxZ, regionMaxZ); - - for (int z = minZ; z <= maxX; z++) { - for (int x = minX; x <= maxZ; x++) { - visitor.visit(getCell(x, z), x, z); - } - } - } - - private GenChunk computeChunk(int index, int chunkX, int chunkZ) { - GenChunk chunk = chunks[index]; - if (chunk == null) { - chunk = new GenChunk(chunkX, chunkZ); - chunks[index] = chunk; - } - return chunk; - } - - private GenCell computeCell(int index) { - GenCell cell = blocks[index]; - if (cell == null) { - cell = new GenCell(); - blocks[index] = cell; - } - return cell; - } - - private static class GenCell extends Cell {} - - private class GenChunk implements ChunkReader, ChunkWriter { - - private final int chunkX; - private final int chunkZ; - private final int blockX; - private final int blockZ; - private final int regionBlockX; - private final int regionBlockZ; - - // the coordinate of the chunk within this region (relative to 0,0) - private GenChunk(int regionChunkX, int regionChunkZ) { - // the block coordinate of this chunk within this region (relative 0,0) - this.regionBlockX = regionChunkX << 4; - this.regionBlockZ = regionChunkZ << 4; - // the real coordinate of this chunk within the world - this.chunkX = Region.this.chunkX + regionChunkX - getOffsetChunks(); - this.chunkZ = Region.this.chunkZ + regionChunkZ - getOffsetChunks(); - // the real block coordinate of this chunk within the world - this.blockX = chunkX << 4; - this.blockZ = chunkZ << 4; - } - - @Override - public int getChunkX() { - return chunkX; - } - - @Override - public int getChunkZ() { - return chunkZ; - } - - @Override - public int getBlockX() { - return blockX; - } - - @Override - public int getBlockZ() { - return blockZ; - } - - @Override - public void dispose() { - Region.this.dispose(); - } - - @Override - public Cell getCell(int blockX, int blockZ) { - int relX = regionBlockX + (blockX & 15); - int relZ = regionBlockZ + (blockZ & 15); - int index = blockSize.indexOf(relX, relZ); - return blocks[index]; - } - - @Override - public Cell genCell(int blockX, int blockZ) { - int relX = regionBlockX + (blockX & 15); - int relZ = regionBlockZ + (blockZ & 15); - int index = blockSize.indexOf(relX, relZ); - return computeCell(index); - } - } - - private class FilterRegion implements Filterable { - - @Override - public Size getSize() { - return blockSize; - } - - @Override - public Cell[] getBacking() { - return blocks; - } - - @Override - public Cell getCellRaw(int x, int z) { - int index = blockSize.indexOf(x, z); - if (index < 0 || index >= blocks.length) { - return Cell.empty(); - } - return blocks[index]; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/RegionFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/RegionFactory.java deleted file mode 100644 index 83c927e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/RegionFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.terraforged.core.region; - -import com.terraforged.core.util.concurrent.Disposable; - -public interface RegionFactory { - - Region create(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener listener); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/Size.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/Size.java deleted file mode 100644 index c9f9d34..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/Size.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region; - -public class Size { - - public final int size; - public final int total; - public final int border; - private final int mask; - - public Size(int size, int border) { - this.size = size; - this.mask = size - 1; - this.border = border; - this.total = size + (2 * border); - } - - public int mask(int i) { - return i & mask; - } - - public int indexOf(int x, int z) { - return (z * total) + x; - } - - public static int chunkToBlock(int i) { - return i << 4; - } - - public static int blockToChunk(int i) { - return i >> 4; - } - - public static int count(int minX, int minZ, int maxX, int maxZ) { - int dx = maxX - minX; - int dz = maxZ - minZ; - return dx * dz; - } - - public static Size chunks(int factor, int borderChunks) { - int chunks = 1 << factor; - return new Size(chunks, borderChunks); - } - - public static Size blocks(int factor, int borderChunks) { - int chunks = 1 << factor; - int blocks = chunks << 4; - int borderBlocks = borderChunks << 4; - return new Size(blocks, borderBlocks); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkGenTask.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkGenTask.java deleted file mode 100644 index 51cba50..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkGenTask.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.chunk; - -import com.terraforged.core.world.heightmap.Heightmap; - -public class ChunkGenTask implements Runnable { - - protected final ChunkWriter chunk; - protected final Heightmap heightmap; - - public ChunkGenTask(ChunkWriter chunk, Heightmap heightmap) { - this.chunk = chunk; - this.heightmap = heightmap; - } - - @Override - public void run() { - chunk.generate((cell, dx, dz) -> { - float x = chunk.getBlockX() + dx; - float z = chunk.getBlockZ() + dz; - heightmap.apply(cell, x, z); - }); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkHolder.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkHolder.java deleted file mode 100644 index 8d417d7..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkHolder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.chunk; - -import com.terraforged.core.cell.Extent; -import com.terraforged.core.util.concurrent.Disposable; - -public interface ChunkHolder extends Extent, Disposable { - - int getChunkX(); - - int getChunkZ(); - - int getBlockX(); - - int getBlockZ(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkReader.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkReader.java deleted file mode 100644 index 11e39b8..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkReader.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.chunk; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; - -public interface ChunkReader extends ChunkHolder { - - Cell getCell(int dx, int dz); - - @Override - default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor visitor) { - int regionMinX = getBlockX(); - int regionMinZ = getBlockZ(); - if (maxX < regionMinX || maxZ < regionMinZ) { - return; - } - - int regionMaxX = getBlockX() + 15; - int regionMaxZ = getBlockZ() + 15; - if (minX > regionMaxX || maxZ > regionMaxZ) { - return; - } - - minX = Math.max(minX, regionMinX); - minZ = Math.max(minZ, regionMinZ); - maxX = Math.min(maxX, regionMaxX); - maxZ = Math.min(maxZ, regionMaxZ); - - for (int z = minZ; z <= maxX; z++) { - for (int x = minX; x <= maxZ; x++) { - visitor.visit(getCell(x, z), x, z); - } - } - } - - default void iterate(Cell.Visitor visitor) { - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - visitor.visit(getCell(dx, dz), dx, dz); - } - } - } - - default void iterate(C context, Cell.ContextVisitor visitor) { - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - visitor.visit(getCell(dx, dz), dx, dz, context); - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkWriter.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkWriter.java deleted file mode 100644 index d581910..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkWriter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.chunk; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; - -public interface ChunkWriter extends ChunkHolder { - - Cell genCell(int dx, int dz); - - default void generate(Cell.Visitor visitor) { - for (int dz = 0; dz < 16; dz++) { - for (int dx = 0; dx < 16; dx++) { - visitor.visit(genCell(dx, dz), dx, dz); - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkZoomTask.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkZoomTask.java deleted file mode 100644 index f089d3b..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/chunk/ChunkZoomTask.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.chunk; - -import com.terraforged.core.world.heightmap.Heightmap; - -public class ChunkZoomTask extends ChunkGenTask { - - private final float translateX; - private final float translateZ; - private final float zoom; - - public ChunkZoomTask(ChunkWriter chunk, Heightmap heightmap, float translateX, float translateZ, float zoom) { - super(chunk, heightmap); - this.translateX = translateX; - this.translateZ = translateZ; - this.zoom = zoom; - } - - @Override - public void run() { - chunk.generate((cell, dx, dz) -> { - float x = ((chunk.getBlockX() + dx) * zoom) + translateX; - float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ; - heightmap.apply(cell, x, z); - }); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegion.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegion.java deleted file mode 100644 index 5ddfb3b..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegion.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.terraforged.core.region.gen; - -import com.terraforged.core.region.Region; - -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class FutureRegion implements Future, Callable { - - private final int rx; - private final int rz; - private final RegionGenerator generator; - - private volatile Region result; - - public FutureRegion(int rx, int rz, RegionGenerator generator) { - this.rx = rx; - this.rz = rz; - this.generator = generator; - } - - @Override - public Region call() { - Region region = result; - if (region == null) { - region = generator.generateRegion(rx, rz); - result = region; - } - return region; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return result != null; - } - - @Override - public Region get() { - return call(); - } - - @Override - public Region get(long timeout, TimeUnit unit) { - return get(); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegionZoom.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegionZoom.java deleted file mode 100644 index 039f638..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/FutureRegionZoom.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.terraforged.core.region.gen; - -import com.terraforged.core.region.Region; - -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class FutureRegionZoom implements Future, Callable { - - private final float cx; - private final float cz; - private final float zoom; - private final boolean filters; - private final RegionGenerator generator; - - private volatile Region result; - - public FutureRegionZoom(float cx, float cz, float zoom, boolean filters, RegionGenerator generator) { - this.cx = cx; - this.cz = cz; - this.zoom = zoom; - this.filters = filters; - this.generator = generator; - } - - @Override - public Region call() { - Region region = result; - if (region == null) { - region = generator.generateRegion(cx, cz, zoom, filters); - result = region; - } - return region; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return result != null; - } - - @Override - public Region get() { - return call(); - } - - @Override - public Region get(long timeout, TimeUnit unit) { - return get(); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/GenContext.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/GenContext.java deleted file mode 100644 index 7b60433..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/GenContext.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.terraforged.core.region.gen; - -import com.terraforged.core.world.WorldGenerator; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.rivermap.RiverRegionList; - -import java.util.function.Supplier; - -public class GenContext { - - public final WorldGenerator generator; - public final RiverRegionList rivers = new RiverRegionList(); - - public GenContext(WorldGenerator generator) { - this.generator = generator; - } - - public static Supplier supplier(WorldGeneratorFactory factory) { - return () -> new GenContext(factory.get()); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCache.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCache.java deleted file mode 100644 index 323417f..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCache.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.gen; - -import com.terraforged.core.region.Region; -import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.core.util.concurrent.Disposable; -import com.terraforged.core.util.concurrent.cache.Cache; -import com.terraforged.core.util.concurrent.cache.CacheEntry; -import com.terraforged.core.world.heightmap.RegionExtent; -import me.dags.noise.util.NoiseUtil; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -public class RegionCache implements RegionExtent, Disposable.Listener { - - private final boolean queuing; - private final RegionGenerator generator; - private final Cache> cache; - - public RegionCache(boolean queueNeighbours, RegionGenerator generator) { - this.queuing = queueNeighbours; - this.generator = new RegionGenerator(generator, this); - this.cache = new Cache<>(60, 30, TimeUnit.SECONDS); - } - - @Override - public void onDispose(Region region) { - cache.remove(region.getRegionId()); - } - - @Override - public int chunkToRegion(int coord) { - return generator.chunkToRegion(coord); - } - - @Override - public CompletableFuture getRegionAsync(int regionX, int regionZ) { - return generator.generate(regionX, regionZ); - } - - @Override - public ChunkReader getChunk(int chunkX, int chunkZ) { - int regionX = generator.chunkToRegion(chunkX); - int regionZ = generator.chunkToRegion(chunkZ); - Region region = getRegion(regionX, regionZ); - return region.getChunk(chunkX, chunkZ); - } - - @Override - public Region getRegion(int regionX, int regionZ) { - Region region = computeRegion(regionX, regionZ).get(); - - if (queuing) { - queueNeighbours(regionX, regionZ); - } - - return region; - } - - private CacheEntry computeRegion(int regionX, int regionZ) { - long id = NoiseUtil.seed(regionX, regionZ); - return cache.computeIfAbsent(id, l -> generator.compute(regionX, regionZ)); - } - - public CacheEntry queueRegion(int regionX, int regionZ) { - long id = NoiseUtil.seed(regionX, regionZ); - return cache.computeIfAbsent(id, l -> generator.queue(regionX, regionZ)); - } - - private void queueNeighbours(int regionX, int regionZ) { - for (int z = -1; z <= 1; z++) { - for (int x = -1; x <= 1; x++){ - if (x == 0 && z == 0) { - continue; - } - queueRegion(regionX + x, regionZ + z); - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCacheFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCacheFactory.java deleted file mode 100644 index 27c2c58..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionCacheFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.gen; - -import com.terraforged.core.world.WorldGeneratorFactory; - -public interface RegionCacheFactory { - - RegionCache create(WorldGeneratorFactory factory); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionGenerator.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionGenerator.java deleted file mode 100644 index 83fc3ea..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/gen/RegionGenerator.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.region.gen; - -import com.terraforged.core.region.Region; -import com.terraforged.core.region.RegionFactory; -import com.terraforged.core.region.legacy.LegacyRegion; -import com.terraforged.core.util.concurrent.Disposable; -import com.terraforged.core.util.concurrent.ObjectPool; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.util.concurrent.cache.CacheEntry; -import com.terraforged.core.world.WorldGenerator; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.heightmap.RegionExtent; -import com.terraforged.core.world.rivermap.RiverRegionList; - -import java.util.concurrent.CompletableFuture; - -public class RegionGenerator implements RegionExtent { - - private final int factor; - private final int border; - private final RegionFactory regions; - private final ThreadPool threadPool; - private final ObjectPool genPool; - private final Disposable.Listener disposalListener; - - private RegionGenerator(Builder builder) { - this.factor = builder.factor; - this.border = builder.border; - this.threadPool = builder.threadPool; - this.regions = builder.regionFactory; - this.genPool = new ObjectPool<>(6, GenContext.supplier(builder.factory)); - this.disposalListener = region -> {}; - } - - protected RegionGenerator(RegionGenerator from, Disposable.Listener listener) { - this.factor = from.factor; - this.border = from.border; - this.threadPool = from.threadPool; - this.regions = from.regions; - this.genPool = from.genPool; - this.disposalListener = listener; - } - - public RegionCache toCache() { - return toCache(true); - } - - public RegionCache toCache(boolean queueNeighbours) { - return new RegionCache(queueNeighbours, this); - } - - @Override - public int chunkToRegion(int i) { - return i >> factor; - } - - @Override - public Region getRegion(int regionX, int regionZ) { - return generateRegion(regionX, regionZ); - } - - @Override - public CompletableFuture getRegionAsync(int regionX, int regionZ) { - return generate(regionX, regionZ); - } - - public CompletableFuture generate(int regionX, int regionZ) { - return CompletableFuture.supplyAsync(() -> generateRegion(regionX, regionZ), threadPool); - } - - public CompletableFuture generate(float centerX, float centerZ, float zoom, boolean filter) { - return CompletableFuture.supplyAsync(() -> generateRegion(centerX, centerZ, zoom, filter), threadPool); - } - - public CacheEntry compute(int regionX, int regionZ) { - return CacheEntry.supply(new FutureRegion(regionX, regionZ, this)); - } - - public CacheEntry compute(float centerX, float centerZ, float zoom, boolean filter) { - return CacheEntry.supply(new FutureRegionZoom(centerX, centerZ, zoom, filter, this)); - } - - public CacheEntry queue(int regionX, int regionZ) { - return CacheEntry.supplyAsync(new FutureRegion(regionX, regionZ, this), threadPool); - } - - public CacheEntry queue(float centerX, float centerZ, float zoom, boolean filter) { - return CacheEntry.supplyAsync(new FutureRegionZoom(centerX, centerZ, zoom, filter, this), threadPool); - } - - public Region generateRegion(int regionX, int regionZ) { - try (ObjectPool.Item item = genPool.get()) { - RiverRegionList rivers = item.getValue().rivers; - WorldGenerator generator = item.getValue().generator; - Region region = regions.create(regionX, regionZ, factor, border, disposalListener); - generator.getHeightmap().getRiverMap().getRivers(region, rivers); - region.generateBase(generator.getHeightmap()); - region.generateRivers(generator.getHeightmap(), rivers); - postProcess(region, generator); - rivers.clear(); - return region; - } - } - - private void postProcess(Region region, WorldGenerator generator) { - generator.getFilters().apply(region); - region.decorate(generator.getDecorators().getDecorators()); - } - - public Region generateRegion(float centerX, float centerZ, float zoom, boolean filter) { - try (ObjectPool.Item item = genPool.get()) { - WorldGenerator generator = item.getValue().generator; - Region region = regions.create(0, 0, factor, border, disposalListener); - region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom); - postProcess(region, generator, centerX, centerZ, zoom, filter); - return region; - } - } - - private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom, boolean filter) { - if (filter) { - generator.getFilters().apply(region); - } - region.decorateZoom(generator.getDecorators().getDecorators(), centerX, centerZ, zoom); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - - private int factor = 0; - private int border = 0; - private ThreadPool threadPool; - private WorldGeneratorFactory factory; - private RegionFactory regionFactory = Region::new; - - public Builder size(int factor, int border) { - return factor(factor).border(border); - } - - public Builder factor(int factor) { - this.factor = factor; - return this; - } - - public Builder border(int border) { - this.border = border; - return this; - } - - public Builder pool(ThreadPool threadPool) { - this.threadPool = threadPool; - return this; - } - - public Builder regions(RegionFactory factory) { - this.regionFactory = factory; - return this; - } - - public Builder legacy(boolean legacy) { - if (legacy) { - return regions(LegacyRegion::new); - } - return this; - } - - public Builder factory(WorldGeneratorFactory factory) { - this.factory = factory; - return this; - } - - public RegionGenerator build() { - return new RegionGenerator(this); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/legacy/LegacyRegion.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/legacy/LegacyRegion.java deleted file mode 100644 index 34d77dc..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/legacy/LegacyRegion.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.terraforged.core.region.legacy; - -import com.terraforged.core.region.Region; -import com.terraforged.core.util.concurrent.Disposable; - -/** - * This is here to provide compatibility for versions 0.0.2 and below which contained a - * bug where Regions generated with an x,z offset equal to the size of the chunk border - * around the region (x16) ie 32 blocks - */ -public class LegacyRegion extends Region { - - public LegacyRegion(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener listener) { - super(regionX, regionZ, size, borderChunks, listener); - } - - /** - * This is used when calculating the 'real world' chunk position of the chunk-view - * and subsequently the 'real world' block start position. In versions 0.0.2 and - * below, no offset was being deducted, so return 0 here to maintain that broken - * behaviour... RIP :/ - */ - @Override - public int getOffsetChunks() { - return 0; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/BiomeSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/BiomeSettings.java deleted file mode 100644 index 8b27fcb..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/BiomeSettings.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; -import com.terraforged.core.world.biome.BiomeType; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class BiomeSettings { - - public BiomeGroup desert = new BiomeGroup(BiomeType.DESERT); - public BiomeGroup steppe = new BiomeGroup(BiomeType.STEPPE); - public BiomeGroup coldSteppe = new BiomeGroup(BiomeType.COLD_STEPPE); - public BiomeGroup grassland = new BiomeGroup(BiomeType.GRASSLAND); - public BiomeGroup savanna = new BiomeGroup(BiomeType.SAVANNA); - public BiomeGroup taiga = new BiomeGroup(BiomeType.TAIGA); - public BiomeGroup temperateForest = new BiomeGroup(BiomeType.TEMPERATE_FOREST); - public BiomeGroup temperateRainForest = new BiomeGroup(BiomeType.TEMPERATE_RAINFOREST); - public BiomeGroup tropicalRainForest = new BiomeGroup(BiomeType.TROPICAL_RAINFOREST); - public BiomeGroup tundra = new BiomeGroup(BiomeType.TUNDRA); - - public List asList() { - return Arrays.asList( - desert, - steppe, - coldSteppe, - grassland, - savanna, - taiga, - temperateForest, - temperateRainForest, - tropicalRainForest, - tundra - ); - } - - public Map asMap() { - return asList().stream().collect(Collectors.toMap(g -> g.type, g -> g)); - } - - @Serializable - public static class BiomeGroup { - - public BiomeType type; - - public BiomeWeight[] biomes = new BiomeWeight[0]; - - public BiomeGroup() { - - } - - public BiomeGroup(BiomeType biomeType) { - this.type = biomeType; - } - } - - @Serializable - public static class BiomeWeight { - - public String id; - - @Range(min = 0, max = 50) - @Comment("Controls how common this biome type is") - public int weight; - - public BiomeWeight() { - - } - - public BiomeWeight(String id, int weight) { - this.id = id; - this.weight = weight; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/ClimateSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/ClimateSettings.java deleted file mode 100644 index b6619c4..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/ClimateSettings.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; -import me.dags.noise.Module; -import me.dags.noise.Source; - -@Serializable -public class ClimateSettings { - - public RangeValue moisture = new RangeValue(0, 1F); - - public RangeValue temperature = new RangeValue(0, 1F); - - @Serializable - public static class RangeValue { - - @Range(min = 0F, max = 1F) - @Comment("The lower limit of the range") - public float min; - - @Range(min = 0F, max = 1F) - @Comment("The upper limit of the range") - public float max; - - public RangeValue() { - this(0, 1); - } - - public RangeValue(float min, float max) { - this.min = min; - this.max = max; - } - - public float getMin() { - return Math.min(min, max); - } - - public float getMax() { - return Math.max(min, max); - } - - public Module clamp(Module module) { - float min = getMin(); - float max = getMax(); - float range = max - min; - if (range == 0) { - return Source.constant(min); - } - return module.scale(range).bias(min); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/FilterSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/FilterSettings.java deleted file mode 100644 index 198826b..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/FilterSettings.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; - -@Serializable -public class FilterSettings { - - public Erosion erosion = new Erosion(); - - public Smoothing smoothing = new Smoothing(); - - @Serializable - public static class Erosion { - - @Range(min = 1000, max = 50000) - @Comment("Controls the number of erosion iterations") - public int iterations = 12000; - - @Range(min = 0F, max = 1F) - @Comment("Controls how quickly material dissolves (during erosion)") - public float erosionRate = 0.5F; - - @Range(min = 0F, max = 1F) - @Comment("Controls how quickly material is deposited (during erosion)") - public float depositeRate = 0.2F; - } - - @Serializable - public static class Smoothing { - - @Range(min = 0, max = 5) - @Comment("Controls the number of smoothing iterations") - public int iterations = 1; - - @Range(min = 0, max = 5) - @Comment("Controls the smoothing radius") - public float smoothingRadius = 1.75F; - - @Range(min = 0, max = 1) - @Comment("Controls how strongly smoothing is applied") - public float smoothingRate = 0.85F; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/GeneratorSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/GeneratorSettings.java deleted file mode 100644 index 9d6e660..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/GeneratorSettings.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Name; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; -import me.dags.noise.Module; -import me.dags.noise.Source; - -@Serializable -public class GeneratorSettings { - - public transient long seed = 0L; - - /** - * WORLD PROPERTIES - */ - public World world = new World(); - - /** - * TERRAIN PROPERTIES - */ - public Land land = new Land(); - - /** - * BIOME PROPERTIES - */ - public Biome biome = new Biome(); - - public BiomeNoise biomeEdgeNoise = new BiomeNoise(); - - @Serializable - public static class World { - - @Range(min = 0, max = 256) - @Comment("Controls the world height") - public int worldHeight = 256; - - @Range(min = 0, max = 255) - @Comment("Controls the sea level") - public int seaLevel = 63; - - @Range(min = 0F, max = 1F) - @Comment("Controls the amount of ocean between continents") - public float oceanSize = 0.25F; - } - - @Serializable - public static class Land { - - @Range(min = 100, max = 10000) - @Comment("Controls the size of continents") - public int continentScale = 4000; - - @Range(min = 250, max = 5000) - @Name("Mountain Range Scale") - @Comment("Controls the size of mountain ranges") - public int mountainScale = 950; - - @Range(min = 125, max = 5000) - @Comment("Controls the size of terrain regions") - public int regionSize = 1000; - } - - @Serializable - public static class Biome { - - @Range(min = 50, max = 1000) - @Comment("Controls the size of individual biomes") - public int biomeSize = 200; - - @Range(min = 1, max = 500) - @Comment("Controls the scale of shape distortion for biomes") - public int biomeWarpScale = 35; - - @Range(min = 1, max = 500) - @Comment("Controls the strength of shape distortion for biomes") - public int biomeWarpStrength = 70; - } - - @Serializable - public static class BiomeNoise { - - @Comment("The noise type") - public Source type = Source.PERLIN; - - @Range(min = 1, max = 500) - @Comment("Controls the scale of the noise") - public int scale = 8; - - @Range(min = 1, max = 5) - @Comment("Controls the number of noise octaves") - public int octaves = 2; - - @Range(min = 0F, max = 5.5F) - @Comment("Controls the gain subsequent noise octaves") - public float gain = 0.5F; - - @Range(min = 0F, max = 10.5F) - @Comment("Controls the lacunarity of subsequent noise octaves") - public float lacunarity = 2.5F; - - @Range(min = 1, max = 500) - @Comment("Controls the strength of the noise") - public int strength = 24; - - public Module build(int seed) { - return Source.build(seed, scale, octaves).gain(gain).lacunarity(lacunarity).build(type).bias(-0.5); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/RiverSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/RiverSettings.java deleted file mode 100644 index 04d8d77..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/RiverSettings.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; - -@Serializable -public class RiverSettings { - - /** - * RIVER PROPERTIES - */ - @Range(min = 0.0F, max = 5F) - @Comment("Controls how frequently rivers generate") - public float riverFrequency = 1; - - public River primaryRivers = new River(5, 2, 8, 25, 8, 0.75F); - - public River secondaryRiver = new River(4, 1, 6, 15, 5, 0.75F); - - public River tertiaryRivers = new River(3, 0, 4, 10, 4, 0.75F); - - public Lake lake = new Lake(); - - @Serializable - public static class River { - - @Range(min = 1, max = 10) - @Comment("Controls the depth of the river") - public int bedDepth; - - @Range(min = 0, max = 10) - @Comment("Controls the height of river banks") - public int minBankHeight; - - @Range(min = 1, max = 10) - @Comment("Controls the height of river banks") - public int maxBankHeight; - - @Range(min = 1, max = 20) - @Comment("Controls the river-bed width") - public int bedWidth; - - @Range(min = 1, max = 50) - @Comment("Controls the river-banks width") - public int bankWidth; - - @Range(min = 0.0F, max = 1.0F) - @Comment("Controls how much rivers taper") - public float fade; - - public River() { - } - - public River(int depth, int minBank, int maxBank, int outer, int inner, float fade) { - this.minBankHeight = minBank; - this.maxBankHeight = maxBank; - this.bankWidth = outer; - this.bedWidth = inner; - this.bedDepth = depth; - this.fade = fade; - } - } - - public static class Lake { - - @Range(min = 0.0F, max = 1.0F) - @Comment("Controls the chance of a lake spawning") - public float chance = 0.2F; - - @Range(min = 0F, max = 1F) - @Comment("The minimum distance along a river that a lake will spawn") - public float minStartDistance = 0.03F; - - @Range(min = 0F, max = 1F) - @Comment("The maximum distance along a river that a lake will spawn") - public float maxStartDistance = 0.07F; - - @Range(min = 1, max = 20) - @Comment("The max depth of the lake") - public int depth = 10; - - @Range(min = 10, max = 50) - @Comment("The minimum size of the lake") - public int sizeMin = 50; - - @Range(min = 50, max = 150) - @Comment("The maximum size of the lake") - public int sizeMax = 100; - - @Range(min = 1, max = 10) - @Comment("The minimum bank height") - public int minBankHeight = 2; - - @Range(min = 1, max = 10) - @Comment("The maximum bank height") - public int maxBankHeight = 10; - - public Lake() { - - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/Settings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/Settings.java deleted file mode 100644 index d768788..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/Settings.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Serializable; - -@Serializable -public class Settings { - - public GeneratorSettings generator = new GeneratorSettings(); - - public ClimateSettings climate = new ClimateSettings(); - - public RiverSettings rivers = new RiverSettings(); - - public FilterSettings filters = new FilterSettings(); - - public TerrainSettings terrain = new TerrainSettings(); - - public BiomeSettings biomes = new BiomeSettings(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/settings/TerrainSettings.java b/TerraForgedCore/src/main/java/com/terraforged/core/settings/TerrainSettings.java deleted file mode 100644 index 91cc0ae..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/settings/TerrainSettings.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.settings; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; -import com.terraforged.core.world.terrain.TerrainPopulator; -import me.dags.noise.Module; - -@Serializable -public class TerrainSettings { - - @Range(min = 0, max = 1) - @Comment("Globally controls the vertical scaling of terrain") - public float globalVerticalScale = 0.985F; - - @Range(min = 0, max = 5) - @Comment("Globally controls the horizontal scaling of terrain") - public float globalHorizontalScale = 1.0F; - - public Terrain steppe = new Terrain(5F, 1F, 1F); - public Terrain plains = new Terrain(5F, 1F, 1F); - public Terrain hills = new Terrain(2F, 1F, 1F); - public Terrain dales = new Terrain(2F, 1F, 1F); - public Terrain plateau = new Terrain(2F, 1F, 1F); - public Terrain badlands = new Terrain(2F, 1F, 1F); - public Terrain torridonian = new Terrain(0.5F, 1F, 1F); - public Terrain mountains = new Terrain(0.5F, 1F, 1F); - public Terrain volcano = new Terrain(1F, 1F, 1F); - - @Serializable - public static class Terrain { - - @Range(min = 0, max = 10) - @Comment("Controls how common this terrain type is") - public float weight = 1F; - - @Range(min = 0, max = 2) - @Comment("Controls the base height of this terrain") - public float baseScale = 1F; - - @Range(min = 0F, max = 10F) - @Comment("Stretches or compresses the terrain vertically") - public float verticalScale = 1F; - - @Range(min = 0F, max = 10F) - @Comment("Stretches or compresses the terrain horizontally") - public float horizontalScale = 1F; - - public Terrain() { - - } - - public Terrain(float weight, float vertical, float horizontal) { - this.weight = weight; - this.verticalScale = vertical; - this.horizontalScale = horizontal; - } - - public Module apply(double bias, double scale, Module module) { - double moduleBias = bias * baseScale; - double moduleScale = scale * verticalScale; - Module outputModule = module.scale(moduleScale).bias(moduleBias); - return TerrainPopulator.clamp(outputModule); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/PosIterator.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/PosIterator.java deleted file mode 100644 index d2fce85..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/PosIterator.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util; - -public class PosIterator { - - private final int minX; - private final int minZ; - private final int maxX; - private final int maxY; - private final int maxZ; - private final int size; - - private int x; - private int y; - private int z; - private int index = -1; - - public PosIterator(int x, int y, int z, int width, int height, int length) { - this.x = x - 1; - this.y = y; - this.z = z; - this.minX = x; - this.minZ = z; - this.maxX = x + width; - this.maxY = y + height; - this.maxZ = z + length; - this.size = (width * height * length) - 1; - } - - /** - * Steps the iterator forward one position if there there is a new position within it's x/y/z bounds. - * - * @return true if the an increment was made, false if the maximum x,y,z coord has been reached - */ - public boolean next() { - if (x + 1 < maxX) { - x += 1; - index++; - return true; - } - - if (z + 1 < maxZ) { - x = minX; - z += 1; - index++; - return true; - } - - if (y + 1 < maxY) { - x = minX - 1; - z = minZ; - y += 1; - return true; - } - - return false; - } - - public int size() { - return size; - } - - public int index() { - return index; - } - - public int x() { - return x; - } - - public int y() { - return y; - } - - public int z() { - return z; - } - - /** - * Iterates over a 2D area in the x-z planes, centered on x:z, with the given radius - * - * Iteration Order: - * 1. Increments the x-axis from x - radius to x + radius (inclusive), then: - * 2. Increments the z-axis once, resets the x-axis to x - radius, then: - * 3. Repeats steps 1 & 2 until z reaches z + radius - */ - public static PosIterator radius2D(int x, int z, int radius) { - int startX = x - radius; - int startZ = z - radius; - int size = radius * 2 + 1; - return new PosIterator(startX, 0, startZ, size, 0, size); - } - - /** - * Iterates over a 3D volume, centered on x:y:z, with the given radius - * - * Iteration Order: - * 1. Increments the x-axis (starting from x - radius) up to x + radius (inclusive), then: - * 2. Increments the z-axis once (starting from z - radius) and resets the x-axis to x - radius, then: - * 3. Increments the y-axis once (starting from y - radius), resets the x & z axes to x - radius & z - radius - * respectively, then: - * 4. Repeats steps 1-3 until y reaches y + radius - */ - public static PosIterator radius3D(int x, int y, int z, int radius) { - int startX = x - radius; - int startY = y - radius; - int startZ = z - radius; - int size = radius * 2 + 1; - return new PosIterator(startX, startY, startZ, size, size, size); - } - - public static PosIterator area(int x, int z, int width, int length) { - return new PosIterator(x, 0, z, width, 0, length); - } - - public static PosIterator volume3D(int x, int y, int z, int width, int height, int length) { - return new PosIterator(x, y, z, width, height, length); - } - - public static PosIterator range2D(int minX, int minZ, int maxX, int maxZ) { - int width = maxX - minX; - int length = maxZ - minZ; - return new PosIterator(minX, 0, minZ, width, 0, length); - } - - public static PosIterator range2D(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - int width = 1 + maxX - minX; - int height = 1 + maxY - minY; - int length = 1 + maxZ - minZ; - return new PosIterator(minX, minY, minZ, width, height, length); - } -} \ No newline at end of file diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/Seed.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/Seed.java deleted file mode 100644 index 6148874..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/Seed.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util; - -public class Seed { - - private final Seed root; - - private final int value; - private int seed; - - public Seed(long seed) { - this((int) seed); - } - - public Seed(int seed) { - this.value = seed; - this.seed = seed; - this.root = this; - } - - private Seed(Seed root) { - this.root = root; - this.seed = root.next(); - this.value = seed; - } - - public int next() { - return ++root.seed; - } - - public int get() { - return value; - } - - public Seed nextSeed() { - return new Seed(root); - } - - public Seed reset() { - this.seed = value; - return this; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/VariablePredicate.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/VariablePredicate.java deleted file mode 100644 index e43ab95..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/VariablePredicate.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.Source; - -import java.util.function.BiPredicate; - -public class VariablePredicate { - - private final Module module; - private final BiPredicate, Float> predicate; - - public VariablePredicate(Module module, BiPredicate, Float> predicate) { - this.module = module; - this.predicate = predicate; - } - - public boolean test(Cell cell, float x, float z) { - return predicate.test(cell, module.getValue(x, z)); - } - - public static VariablePredicate height(Seed seed, Levels levels, int min, int max, int size, int octaves) { - float bias = levels.scale(min); - float scale = levels.scale(max - min); - Module source = Source.perlin(seed.next(), size, 1).scale(scale).bias(bias); - return new VariablePredicate(source, (cell, height) -> cell.value < height); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/Disposable.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/Disposable.java deleted file mode 100644 index 3907b7d..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/Disposable.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.terraforged.core.util.concurrent; - -public interface Disposable { - - void dispose(); - - interface Listener { - - void onDispose(T t); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ObjectPool.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ObjectPool.java deleted file mode 100644 index 033c12c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ObjectPool.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.concurrent; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -public class ObjectPool { - - private final int capacity; - private final List> pool; - private final Supplier supplier; - - public ObjectPool(int size, Supplier supplier) { - this.capacity = size; - this.pool = new ArrayList<>(size); - this.supplier = supplier; - } - - public Item get() { - synchronized (pool) { - if (pool.size() > 0) { - return pool.remove(pool.size() - 1).retain(); - } - } - return new Item<>(supplier.get(), this); - } - - public int size() { - synchronized (pool) { - return pool.size(); - } - } - - private boolean restore(Item item) { - synchronized (pool) { - int size = pool.size(); - if (size < capacity) { - pool.add(item); - return true; - } - } - return false; - } - - public static class Item implements AutoCloseable { - - private final T value; - private final ObjectPool pool; - - private boolean released = false; - - private Item(T value, ObjectPool pool) { - this.value = value; - this.pool = pool; - } - - public T getValue() { - return value; - } - - public void release() { - if (!released) { - released = true; - released = pool.restore(this); - } - } - - private Item retain() { - released = false; - return this; - } - - @Override - public void close() { - release(); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ThreadPool.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ThreadPool.java deleted file mode 100644 index 11690e9..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/ThreadPool.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.concurrent; - -import com.terraforged.core.util.concurrent.batcher.AsyncBatcher; -import com.terraforged.core.util.concurrent.batcher.Batcher; -import com.terraforged.core.util.concurrent.batcher.SyncBatcher; - -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; - -public class ThreadPool implements Executor { - - private static final ThreadPool instance = create("TF", defaultPoolSize()); - - private final ForkJoinPool service; - - private ThreadPool(ForkJoinPool service) { - this.service = service; - } - - @Override - public void execute(Runnable command) { - service.submit(command); - } - - public ForkJoinTask submit(Runnable runnable) { - return service.submit(runnable); - } - - public ForkJoinTask submit(Callable callable) { - return service.submit(callable); - } - - public Batcher batcher(int size) { - return new AsyncBatcher(service, size); - } - - public static ThreadPool getPool() { - return instance; - } - - public static ThreadPool create(String name, int size) { - if (size < 2) { - return new SingleThreadExecutor(); - } - return new ThreadPool(createPool(name, size)); - } - - public static ForkJoinPool createPool(String name, int size) { - return new ForkJoinPool(size, new WorkerFactory.ForkJoin(name), null, true); - } - - private static int defaultPoolSize() { - int threads = Runtime.getRuntime().availableProcessors(); - return Math.max(1, (int) ((threads / 3F) * 2F)); - } - - private static class SingleThreadExecutor extends ThreadPool { - - private SingleThreadExecutor() { - super(null); - } - - @Override - public void execute(Runnable command) { - command.run(); - } - - @Override - public ForkJoinTask submit(Runnable runnable) { - ForkJoinTask task = ForkJoinTask.adapt(runnable); - task.invoke(); - return task; - } - - @Override - public ForkJoinTask submit(Callable callable) { - ForkJoinTask task = ForkJoinTask.adapt(callable); - task.invoke(); - return task; - } - - @Override - public Batcher batcher(int size) { - return new SyncBatcher(); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/WorkerFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/WorkerFactory.java deleted file mode 100644 index f04ec6c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/WorkerFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.terraforged.core.util.concurrent; - -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinWorkerThread; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -// As DefaultThreadPool but with custom thread names -public class WorkerFactory implements ThreadFactory { - - protected final String prefix; - protected final ThreadGroup group; - protected final AtomicInteger threadNumber = new AtomicInteger(1); - - public WorkerFactory(String name) { - group = Thread.currentThread().getThreadGroup(); - prefix = name + "-Worker-"; - } - - @Override - public Thread newThread(Runnable task) { - Thread thread = new Thread(group, task); - thread.setDaemon(true); - thread.setName(prefix + threadNumber.getAndIncrement()); - return thread; - } - - public static class ForkJoin extends WorkerFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory { - - public ForkJoin(String name) { - super(name); - } - - @Override - public ForkJoinWorkerThread newThread(ForkJoinPool pool) { - ForkJoinWorkerThread thread = new ForkJoinWorkerThread(pool) {}; - thread.setDaemon(true); - thread.setName(prefix + threadNumber.getAndIncrement()); - return thread; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/AsyncBatcher.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/AsyncBatcher.java deleted file mode 100644 index f97947c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/AsyncBatcher.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.concurrent.batcher; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -public class AsyncBatcher implements Batcher { - - private final List> tasks; - private final ExecutorService executor; - - public AsyncBatcher(ExecutorService executor, int size) { - this.executor = executor; - this.tasks = new ArrayList<>(size); - } - - @Override - public void submit(Runnable task) { - tasks.add(executor.submit(task)); - } - - @Override - public void submit(Callable task) { - tasks.add(executor.submit(task)); - } - - @Override - public void close() { - boolean hasMore = true; - while (hasMore) { - hasMore = false; - for (Future future : tasks) { - if (!future.isDone()) { - hasMore = true; - } - } - } - tasks.clear(); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/Batcher.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/Batcher.java deleted file mode 100644 index 2661b81..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/Batcher.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.concurrent.batcher; - -import java.util.concurrent.Callable; - -public interface Batcher extends AutoCloseable { - - void submit(Runnable task); - - void submit(Callable task); - - @Override - void close(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/SyncBatcher.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/SyncBatcher.java deleted file mode 100644 index b8feb51..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/batcher/SyncBatcher.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.concurrent.batcher; - -import java.util.concurrent.Callable; - -public class SyncBatcher implements Batcher { - - @Override - public void submit(Runnable task) { - task.run(); - } - - @Override - public void submit(Callable task) { - try { - task.call(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void close() { - - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/Cache.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/Cache.java deleted file mode 100644 index 1b2d32c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/Cache.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.terraforged.core.util.concurrent.cache; - -import com.terraforged.core.util.concurrent.ThreadPool; - -import java.util.concurrent.TimeUnit; -import java.util.function.LongFunction; - -public class Cache implements Runnable { - - private final long expireMS; - private final long intervalMS; - private final SynchronizedLongMap map; - private final ThreadPool threadPool = ThreadPool.getPool(); - - private volatile long timestamp = 0L; - - public Cache(long expireTime, long interval, TimeUnit unit) { - this.expireMS = unit.toMillis(expireTime); - this.intervalMS = unit.toMillis(interval); - this.map = new SynchronizedLongMap<>(100); - } - - public void remove(long key) { - map.remove(key); - } - - public V computeIfAbsent(long key, LongFunction func) { - V v = map.computeIfAbsent(key, func); - queueUpdate(); - return v; - } - - private void queueUpdate() { - long now = System.currentTimeMillis(); - if (now - timestamp > intervalMS) { - timestamp = now; - threadPool.submit(this); - } - } - - @Override - public void run() { - final long now = timestamp; - map.removeIf(val -> now - val.getTimestamp() > expireMS); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/CacheEntry.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/CacheEntry.java deleted file mode 100644 index 4177126..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/CacheEntry.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.terraforged.core.util.concurrent.cache; - -import com.terraforged.core.util.concurrent.ThreadPool; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; - -public class CacheEntry implements ExpiringEntry { - - private volatile long timestamp; - private final Future task; - - public CacheEntry(Future task) { - this.task = task; - this.timestamp = System.currentTimeMillis(); - } - - @Override - public long getTimestamp() { - return timestamp; - } - - public boolean isDone() { - return task.isDone(); - } - - public T get() { - if (task instanceof ForkJoinTask) { - return ((ForkJoinTask) task).join(); - } - - try { - return task.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - public static CacheEntry supply(Future future) { - return new CacheEntry<>(future); - } - - public static CacheEntry supplyAsync(Callable callable, ThreadPool executor) { - return new CacheEntry<>(executor.submit(callable)); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/ExpiringEntry.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/ExpiringEntry.java deleted file mode 100644 index e780212..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/ExpiringEntry.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.terraforged.core.util.concurrent.cache; - -public interface ExpiringEntry { - - long getTimestamp(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/SynchronizedLongMap.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/SynchronizedLongMap.java deleted file mode 100644 index 5f92ad9..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/concurrent/cache/SynchronizedLongMap.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.terraforged.core.util.concurrent.cache; - -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectIterator; - -import java.util.function.LongFunction; -import java.util.function.Predicate; - -public class SynchronizedLongMap { - - private final Object lock; - private final Long2ObjectOpenHashMap map; - - public SynchronizedLongMap(int size) { - this.map = new Long2ObjectOpenHashMap<>(size); - this.lock = this; - } - - public void remove(long key) { - synchronized (lock) { - map.remove(key); - } - } - - public void put(long key, V v) { - synchronized (lock) { - map.put(key, v); - } - } - - public V get(long key) { - synchronized (lock) { - return map.get(key); - } - } - - public V computeIfAbsent(long key, LongFunction func) { - synchronized (lock) { - return map.computeIfAbsent(key, func); - } - } - - public void removeIf(Predicate predicate) { - synchronized (lock) { - ObjectIterator> iterator = map.long2ObjectEntrySet().fastIterator(); - while (iterator.hasNext()) { - if (predicate.test(iterator.next().getValue())) { - iterator.remove(); - } - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedGrid.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedGrid.java deleted file mode 100644 index aa298a8..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedGrid.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.grid; - -import me.dags.noise.util.NoiseUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -public class FixedGrid implements Iterable>> { - - private final MappedList>> grid; - - private FixedGrid(MappedList>> grid) { - this.grid = grid; - } - - public int size() { - return grid.size(); - } - - public FixedList get(float x, float y) { - return grid.get(y).get(x); - } - - public T get(float x, float y, float z) { - MappedList> row = grid.get(y); - FixedList cell = row.get(x); - return cell.get(z); - } - - @Override - public Iterator>> iterator() { - return grid.iterator(); - } - - public static FixedGrid create(List>> grid, float minX, float minY, float rangeX, float rangeY) { - List>> list = new ArrayList<>(); - for (List> src : grid) { - List> row = new ArrayList<>(src.size()); - for (List cell : src) { - row.add(FixedList.of(cell)); - } - list.add(MappedList.of(row, minX, rangeX)); - } - return new FixedGrid<>(MappedList.of(list, minY, rangeY)); - } - - public static FixedGrid generate(int size, List values, Function xFunc, Function yFunc) { - List>> src = createList(size, () -> createList(size, ArrayList::new)); - List>> dest = createList(size, () -> createList(size, ArrayList::new)); - - float minX = 1F; - float maxX = 0F; - float minY = 1F; - float maxY = 0F; - for (T value : values) { - float x = xFunc.apply(value); - float y = yFunc.apply(value); - minX = Math.min(minX, x); - maxX = Math.max(maxX, x); - minY = Math.min(minY, y); - maxY = Math.max(maxY, y); - } - - int maxIndex = size - 1; - float rangeX = maxX - minX; - float rangeY = maxY - minY; - for (T value : values) { - float colVal = (xFunc.apply(value) - minX) / rangeX; - float rowVal = (yFunc.apply(value) - minY) / rangeY; - int colIndex = NoiseUtil.round(maxIndex * colVal); - int rowIndex = NoiseUtil.round(maxIndex * rowVal); - List> row = src.get(rowIndex); - List group = row.get(colIndex); - group.add(value); - } - - for (int y = 0; y < size; y++) { - List> srcRow = src.get(y); - List> destRow = dest.get(y); - for (int x = 0; x < size; x++) { - List srcGroup = srcRow.get(x); - List destGroup = destRow.get(x); - if (srcGroup.isEmpty()) { - float fx = minX + (x / (float) maxIndex) * rangeX; - float fy = minY + (x / (float) maxIndex) * rangeY; - addClosest(values, destGroup, fx, fy, xFunc, yFunc); - } else { - destGroup.addAll(srcGroup); - } - } - } - - return create(dest, minX, minY, rangeX, rangeY); - } - - private static void addClosest(List source, List dest, float fx, float fy, Function xFunc, Function yFunc) { - float dist2 = Float.MAX_VALUE; - Map distances = new HashMap<>(); - for (T t : source) { - if (!distances.containsKey(t)) { - float dx = fx - xFunc.apply(t); - float dy = fy - yFunc.apply(t); - float d2 = dx * dx + dy * dy; - distances.put(t, d2); - if (d2 < dist2) { - dist2 = d2; - } - } - } - - if (dist2 <= 0) { - dist2 = 1F; - } - - List sorted = new ArrayList<>(distances.keySet()); - sorted.sort((o1, o2) -> Float.compare(distances.getOrDefault(o1, Float.MAX_VALUE), distances.getOrDefault(o2, Float.MAX_VALUE))); - - for (T t : sorted) { - float d2 = distances.get(t); - if (d2 / dist2 < 1.025F) { - dest.add(t); - } - } - } - - private static List createList(int size, Supplier supplier) { - List list = new ArrayList<>(); - while (list.size() < size) { - list.add(supplier.get()); - } - return list; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedList.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedList.java deleted file mode 100644 index 5224db5..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/FixedList.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.grid; - -import me.dags.noise.util.NoiseUtil; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -public class FixedList implements Iterable { - - private final int maxIndex; - private final T[] elements; - - FixedList(T[] elements) { - this.maxIndex = elements.length - 1; - this.elements = elements; - } - - public T get(int index) { - if (index < 0) { - return elements[0]; - } - if (index > maxIndex) { - return elements[maxIndex]; - } - return elements[index]; - } - - public T get(float value) { - return get(indexOf(value)); - } - - public int size() { - return elements.length; - } - - public int indexOf(float value) { - return NoiseUtil.round(value * maxIndex); - } - - public Set uniqueValues() { - Set set = new HashSet<>(); - Collections.addAll(set, elements); - return set; - } - - @Override - public Iterator iterator() { - return new Iterator() { - - private int index = 0; - - @Override - public boolean hasNext() { - return index < elements.length; - } - - @Override - public T next() { - return elements[index++]; - } - }; - } - - @SuppressWarnings("unchecked") - public static FixedList of(List list) { - return new FixedList<>((T[]) list.toArray()); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/MappedList.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/MappedList.java deleted file mode 100644 index 1548782..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/grid/MappedList.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.grid; - -import java.util.List; - -public class MappedList extends FixedList { - - private final float min; - private final float range; - - public MappedList(T[] elements, float min, float range) { - super(elements); - this.min = min; - this.range = range; - } - - @Override - public int indexOf(float value) { - return super.indexOf((value - min) / range); - } - - @SuppressWarnings("unchecked") - public static MappedList of(List list, float min, float range) { - return new MappedList<>((T[]) list.toArray(), min, range); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/points/Poisson.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/points/Poisson.java deleted file mode 100644 index cb277e6..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/points/Poisson.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.terraforged.core.util.points; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.region.Region; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.util.Vec2i; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; - -public class Poisson { - - public static void main(String[] args) { - Region region = new Region(0, 0, 5, 2); - BufferedImage image = new BufferedImage(region.getBlockSize().size, region.getBlockSize().size, BufferedImage.TYPE_INT_RGB); - points(region, 123,8, 20F, 0.8F); - render(region, image); - - JFrame frame = new JFrame(); - frame.add(new JLabel(new ImageIcon(image))); - frame.pack(); - frame.setVisible(true); - frame.setResizable(false); - frame.setLocationRelativeTo(null); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - } - - private static void points(Region region, int seed, int scale, float radius, float threshold) { - region.generate(chunk -> chunk.generate((cell, dx, dz) -> {})); - - Module noise = Source.simplex(seed, scale, 1); - - int gridSize = (int) Math.ceil(region.getBlockSize().size / radius); - Vec2i[][] grid = new Vec2i[gridSize][gridSize]; - - for (int dz = 0; dz < region.getBlockSize().size; dz++) { - for (int dx = 0; dx < region.getBlockSize().size; dx++) { - int x = region.getBlockX() + dx; - int z = region.getBlockZ() + dz; - float value = noise.getValue(x, z); - region.getCell(dx, dz).value = value; - if (true) continue; - - if (value > threshold) { - continue; - } - - int gridX = (int) (dx / radius); - int gridZ = (int) (dz / radius); - Vec2i point = grid[gridZ][gridX]; - - if (point != null) { - Cell current = region.getCell(point.x, point.y); - if (current.value > value) { - continue; - } - } - - region.getCell(dx, dz).value = value; - grid[gridZ][gridX] = new Vec2i(dx, dz); - } - } - } - - private static void render(Region region, BufferedImage image) { - region.iterate((cell, dx, dz) -> { - if (cell.value == 0) { - return; - } - int w = (int) (cell.value * 255); - image.setRGB(dx, dz, new Color(w, w, w).getRGB()); - }); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Comment.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Comment.java deleted file mode 100644 index e339c0c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Comment.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Comment { - - String[] value(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Name.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Name.java deleted file mode 100644 index ef32732..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Name.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Name { - - String value(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Option.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Option.java deleted file mode 100644 index a1fc6d7..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Option.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Option { - -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Range.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Range.java deleted file mode 100644 index 44a0086..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Range.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Range { - - float min(); - - float max(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Serializable.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Serializable.java deleted file mode 100644 index 3fd81ba..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/annotation/Serializable.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Serializable { -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Deserializer.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Deserializer.java deleted file mode 100644 index 49f899c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Deserializer.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.serializer; - -import com.terraforged.core.util.serialization.annotation.Serializable; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; - -public class Deserializer { - - public void deserialize(Reader reader, Object object) throws Throwable { - Class type = object.getClass(); - for (String name : reader.getKeys()) { - if (name.charAt(0) == '#') { - continue; - } - - try { - Reader child = reader.getChild(name); - Field field = type.getField(name); - if (Serializer.isSerializable(field)) { - field.setAccessible(true); - fromValue(child, object, field); - } - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - } - } - - private void fromValue(Reader reader, Object object, Field field) throws Throwable { - if (field.getType() == int.class) { - field.set(object, reader.getInt("value")); - return; - } - if (field.getType() == float.class) { - field.set(object, reader.getFloat("value")); - return; - } - if (field.getType() == boolean.class) { - field.set(object, reader.getString("value").equals("true")); - return; - } - if (field.getType() == String.class) { - field.set(object, reader.getString("value")); - return; - } - if (field.getType().isEnum()) { - String name = reader.getString("value"); - for (Enum e : field.getType().asSubclass(Enum.class).getEnumConstants()) { - if (e.name().equals(name)) { - field.set(object, e); - return; - } - } - } - if (field.getType().isAnnotationPresent(Serializable.class)) { - Reader child = reader.getChild("value"); - Object value = field.getType().newInstance(); - deserialize(child, value); - field.set(object, value); - return; - } - if (field.getType().isArray()) { - Class type = field.getType().getComponentType(); - if (type.isAnnotationPresent(Serializable.class)) { - Reader child = reader.getChild("value"); - Object array = Array.newInstance(type, child.getSize()); - for (int i = 0; i < child.getSize(); i++) { - Object value = type.newInstance(); - deserialize(child.getChild(i), value); - Array.set(array, i, value); - } - field.set(object, array); - } - } - } - - private static String getName(String name) { - StringBuilder sb = new StringBuilder(name.length()); - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (i == 0) { - c = Character.toLowerCase(c); - } else if (c == ' ' && i + 1 < name.length()) { - c = Character.toUpperCase(name.charAt(++i)); - } - sb.append(c); - } - return sb.toString(); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Reader.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Reader.java deleted file mode 100644 index f7ff240..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Reader.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.serializer; - -import java.util.Collection; - -public interface Reader { - - int getSize(); - - Reader getChild(String key); - - Reader getChild(int index); - - Collection getKeys(); - - String getString(); - - boolean getBool(); - - float getFloat(); - - int getInt(); - - default String getString(String key) { - return getChild(key).getString(); - } - - default boolean getBool(String key) { - return getChild(key).getBool(); - } - - default float getFloat(String key) { - return getChild(key).getFloat(); - } - - default int getInt(String key) { - return getChild(key).getInt(); - } - - default String getString(int index) { - return getChild(index).getString(); - } - - default boolean getBool(int index) { - return getChild(index).getBool(); - } - - default float getFloat(int index) { - return getChild(index).getFloat(); - } - - default int getInt(int index) { - return getChild(index).getInt(); - } - - default void writeTo(Object object) throws Throwable { - new Deserializer().deserialize(this, object); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Serializer.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Serializer.java deleted file mode 100644 index 9891b89..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Serializer.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.serializer; - -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Name; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -public class Serializer { - - public void serialize(Object object, Writer writer) throws IllegalAccessException { - if (object.getClass().isArray()) { - writer.beginArray(); - int length = Array.getLength(object); - for (int i = 0; i < length; i++) { - Object element = Array.get(object, i); - serialize(element, writer); - } - writer.endArray(); - } else if (!object.getClass().isPrimitive()) { - int order = 0; - writer.beginObject(); - for (Field field : object.getClass().getFields()) { - if (Serializer.isSerializable(field)) { - field.setAccessible(true); - write(object, field, order, writer); - order++; - } - } - writer.endObject(); - } - } - - private void write(Object object, Field field, int order, Writer writer) throws IllegalAccessException { - if (field.getType() == int.class) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value").value((int) field.get(object)); - writeMeta(field, order, writer); - writer.endObject(); - return; - } - if (field.getType() == float.class) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value").value((float) field.get(object)); - writeMeta(field, order, writer); - writer.endObject(); - return; - } - if (field.getType() == String.class) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value").value((String) field.get(object)); - writeMeta(field, order, writer); - writer.endObject(); - return; - } - if (field.getType() == boolean.class) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value").value("" + (field.get(object))); - writeMeta(field, order, writer); - writer.endObject(); - } - if (field.getType().isEnum()) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value").value(((Enum) field.get(object)).name()); - writeMeta(field, order, writer); - writer.endObject(); - return; - } - if (field.getType().isArray()) { - if (field.getType().getComponentType().isAnnotationPresent(Serializable.class)) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value"); - serialize(field.get(object), writer); - writeMeta(field, order, writer); - writer.endObject(); - } - return; - } - if (field.getType().isAnnotationPresent(Serializable.class)) { - writer.name(field.getName()); - writer.beginObject(); - writer.name("value"); - serialize(field.get(object), writer); - writeMeta(field, order, writer); - writer.endObject(); - } - } - - private void writeMeta(Field field, int order, Writer writer) { - writer.name("#display").value(getName(field)); - writer.name("#order").value(order); - - Range range = field.getAnnotation(Range.class); - if (range != null) { - if (field.getType() == int.class) { - writer.name("#min").value((int) range.min()); - writer.name("#max").value((int) range.max()); - } else { - writer.name("#min").value(range.min()); - writer.name("#max").value(range.max()); - } - } - - Comment comment = field.getAnnotation(Comment.class); - if (comment != null) { - writer.name("#comment"); - writer.beginArray(); - for (String line : comment.value()) { - writer.value(line); - } - writer.endArray(); - } - - if (field.getType() == boolean.class) { - writer.name("#options"); - writer.beginArray(); - writer.value("true"); - writer.value("false"); - writer.endArray(); - } - - if (field.getType().isEnum()) { - writer.name("#options"); - writer.beginArray(); - for (Enum o : field.getType().asSubclass(Enum.class).getEnumConstants()) { - writer.value(o.name()); - } - writer.endArray(); - } - } - - private static String getName(Field field) { - Name nameMeta = field.getAnnotation(Name.class); - - String name = nameMeta == null ? field.getName() : nameMeta.value(); - StringBuilder sb = new StringBuilder(name.length() * 2); - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (i == 0) { - c = Character.toUpperCase(c); - } else if (Character.isUpperCase(c)) { - sb.append(' '); - } - - sb.append(c); - } - return sb.toString(); - } - - protected static boolean isSerializable(Field field) { - int modifiers = field.getModifiers(); - return Modifier.isPublic(modifiers) - && !Modifier.isFinal(modifiers) - && !Modifier.isStatic(modifiers) - && !Modifier.isTransient(modifiers); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Writer.java b/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Writer.java deleted file mode 100644 index c9a566f..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/util/serialization/serializer/Writer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.util.serialization.serializer; - -public interface Writer { - - Writer name(String name); - - Writer beginObject(); - - Writer endObject(); - - Writer beginArray(); - - Writer endArray(); - - Writer value(String value); - - Writer value(float value); - - Writer value(int value); - - default void readFrom(Object value) throws IllegalAccessException { - new Serializer().serialize(value, this); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/GeneratorContext.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/GeneratorContext.java deleted file mode 100644 index 832dacb..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/GeneratorContext.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world; - -import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrains; -import com.terraforged.core.world.terrain.provider.StandardTerrainProvider; -import com.terraforged.core.world.terrain.provider.TerrainProviderFactory; - -public class GeneratorContext { - - public final Seed seed; - public final Levels levels; - public final Terrains terrain; - public final Settings settings; - public final TerrainProviderFactory terrainFactory; - - public GeneratorContext(Terrains terrain, Settings settings) { - this(terrain, settings, StandardTerrainProvider::new); - } - - public GeneratorContext(Terrains terrain, Settings settings, TerrainProviderFactory terrainFactory) { - this.terrain = terrain; - this.settings = settings; - this.seed = new Seed(settings.generator.seed); - this.levels = new Levels(settings.generator); - this.terrainFactory = terrainFactory; - } - - private GeneratorContext(GeneratorContext src) { - seed = new Seed(src.seed.get()); - levels = src.levels; - terrain = src.terrain; - settings = src.settings; - terrainFactory = src.terrainFactory; - } - - public GeneratorContext copy() { - return new GeneratorContext(this); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldDecorators.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldDecorators.java deleted file mode 100644 index 382300c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldDecorators.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world; - -import com.terraforged.core.world.decorator.Decorator; -import com.terraforged.core.world.decorator.DesertStacks; -import com.terraforged.core.world.decorator.Wetlands; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class WorldDecorators { - - private final List decorators; - - public WorldDecorators(GeneratorContext context) { - context = context.copy(); - List list = new ArrayList<>(); - list.add(new DesertStacks(context.seed, context.levels)); - list.add(new Wetlands(context.seed, context.terrain, context.levels)); - decorators = Collections.unmodifiableList(list); - } - - public List getDecorators() { - return decorators; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java deleted file mode 100644 index b5f4d32..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world; - -import com.terraforged.core.filter.Erosion; -import com.terraforged.core.filter.Filterable; -import com.terraforged.core.filter.Smoothing; -import com.terraforged.core.filter.Steepness; -import com.terraforged.core.region.Region; -import com.terraforged.core.settings.FilterSettings; -import com.terraforged.core.world.terrain.Terrain; - -public class WorldFilters { - - private final Erosion erosion; - private final Smoothing smoothing; - private final Steepness steepness; - private final FilterSettings settings; - - public WorldFilters(GeneratorContext context) { - context = context.copy(); - this.settings = context.settings.filters; - this.erosion = new Erosion(context.settings, context.levels); - this.smoothing = new Smoothing(context.settings, context.levels); - this.steepness = new Steepness(1, 10F, context.terrain, context.levels); - } - - public void apply(Region region) { - Filterable map = region.filterable(); - erosion.apply(map, region.getRegionX(), region.getRegionZ(), settings.erosion.iterations); - smoothing.apply(map, region.getRegionX(), region.getRegionZ(), settings.smoothing.iterations); - steepness.apply(map, region.getRegionX(), region.getRegionZ(), 1); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGenerator.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGenerator.java deleted file mode 100644 index f750fb2..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGenerator.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world; - -import com.terraforged.core.world.heightmap.Heightmap; - -public class WorldGenerator { - - private final Heightmap heightmap; - private final WorldFilters filters; - private final WorldDecorators decorators; - - public WorldGenerator(Heightmap heightmap, WorldDecorators decorators, WorldFilters filters) { - this.filters = filters; - this.heightmap = heightmap; - this.decorators = decorators; - } - - public Heightmap getHeightmap() { - return heightmap; - } - - public WorldFilters getFilters() { - return filters; - } - - public WorldDecorators getDecorators() { - return decorators; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java deleted file mode 100644 index a0500ca..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world; - -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.heightmap.WorldHeightmap; - -import java.util.function.Supplier; - -public class WorldGeneratorFactory implements Supplier { - - private final GeneratorContext context; - - private final Heightmap heightmap; - private final WorldDecorators decorators; - - public WorldGeneratorFactory(GeneratorContext context) { - this.context = context; - this.heightmap = new WorldHeightmap(context); - this.decorators = new WorldDecorators(context); - } - - public WorldGeneratorFactory(GeneratorContext context, Heightmap heightmap) { - this.context = context; - this.heightmap = heightmap; - this.decorators = new WorldDecorators(context); - } - - public Heightmap getHeightmap() { - return heightmap; - } - - public Climate getClimate() { - return getHeightmap().getClimate(); - } - - public WorldDecorators getDecorators() { - return decorators; - } - - public WorldFilters getFilters() { - return new WorldFilters(context); - } - - @Override - public WorldGenerator get() { - return new WorldGenerator(heightmap, decorators, getFilters()); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeData.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeData.java deleted file mode 100644 index 05d9682..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeData.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.biome; - -import java.awt.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class BiomeData implements Comparable { - - private static float[] bounds = {0, 1 / 3F, 2 / 3F, 1F}; - - public static final List BIOMES = new ArrayList<>(); - public static BiomeData DEFAULT = new BiomeData("none", "", 1, 0.5F, 0.5F); - - public final String name; - - public final Object reference; - public final float color; - public final float rainfall; - public final float temperature; - - public BiomeData(String name, Object reference, float color, float rainfall, float temperature) { - this.reference = reference; - this.name = name; - this.rainfall = rainfall; - this.temperature = temperature; - this.color = color; - } - - public BiomeData(String name, Object reference, int color, float rainfall, float temperature) { - Color c = new Color(color); - this.reference = reference; - this.name = name; - this.rainfall = rainfall; - this.temperature = temperature; - this.color = getHue(c.getRed(), c.getGreen(), c.getBlue()); - } - - @Override - public int compareTo(BiomeData o) { - return name.compareTo(o.name); - } - - public static Collection getBiomes(float temperature, float rainfall) { - int temp = Math.min(3, (int) (bounds.length * temperature)); - int rain = Math.min(3, (int) (bounds.length * rainfall)); - return getBiomes(temp, rain); - } - - public static Collection getBiomes(int tempLower, int rainLower) { - int temp0 = tempLower; - int temp1 = temp0 + 1; - int rain0 = rainLower; - int rain1 = rain0 + 1; - - float tempMin = bounds[temp0]; - float tempMax = bounds[temp1]; - float rainMin = bounds[rain0]; - float rainMax = bounds[rain1]; - - List biomes = new ArrayList<>(); - for (BiomeData biome : BIOMES) { - if (biome.temperature >= tempMin && biome.temperature <= tempMax - && biome.rainfall >= rainMin && biome.rainfall <= rainMax) { - biomes.add(biome); - } - } - - if (biomes.isEmpty()) { - biomes.add(DEFAULT); - } - - return biomes; - } - - public static Collection getTempBiomes(float temperature) { - int lower = Math.min(3, (int) (bounds.length * temperature)); - int upper = lower + 1; - - float min = bounds[lower]; - float max = bounds[upper]; - - List biomes = new ArrayList<>(); - for (BiomeData data : BIOMES) { - if (data.temperature >= min && data.temperature <= max) { - biomes.add(data); - } - } - - return biomes; - } - - public static Collection getRainBiomes(float rainfall) { - int lower = Math.min(3, (int) (bounds.length * rainfall)); - int upper = lower + 1; - - float min = bounds[lower]; - float max = bounds[upper]; - - List biomes = new ArrayList<>(); - for (BiomeData data : BIOMES) { - if (data.rainfall >= min && data.rainfall <= max) { - biomes.add(data); - } - } - - return biomes; - } - - private static float getHue(int red, int green, int blue) { - float min = Math.min(Math.min(red, green), blue); - float max = Math.max(Math.max(red, green), blue); - - if (min == max) { - return 0; - } - - float hue; - if (max == red) { - hue = (green - blue) / (max - min); - - } else if (max == green) { - hue = 2f + (blue - red) / (max - min); - - } else { - hue = 4f + (red - green) / (max - min); - } - - hue = hue * 60; - if (hue < 0) hue = hue + 360; - - return (Math.round(hue) / 360F) * 100F; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeManager.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeManager.java deleted file mode 100644 index 75e6310..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeManager.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.biome; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class BiomeManager { - - private final Map> biomes = new HashMap<>(); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeType.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeType.java deleted file mode 100644 index 9e04d36..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeType.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.biome; - -import com.terraforged.core.cell.Cell; -import me.dags.noise.util.NoiseUtil; - -import java.awt.*; - -public enum BiomeType { - - TROPICAL_RAINFOREST(7, 83, 48, new Color(7, 83, 48)), - SAVANNA(151, 165, 39, new Color(151, 165, 39)), - DESERT(200, 113, 55, new Color(200, 113, 55)), - TEMPERATE_RAINFOREST(10, 84, 109, new Color(10, 160, 65)), - TEMPERATE_FOREST(44, 137, 160, new Color(50, 200, 80)), - GRASSLAND(179, 124, 6, new Color(100, 220, 60)), - COLD_STEPPE(131, 112, 71, new Color(175, 180, 150)), - STEPPE(199, 155, 60, new Color(200, 200, 120)), - TAIGA(91, 143, 82, new Color(91, 143, 82)), - TUNDRA(147, 167, 172, new Color(147, 167, 172)), - ALPINE(0, 0, 0, new Color(160, 120, 170)); - - public static final int RESOLUTION = 256; - public static final int MAX = RESOLUTION - 1; - - private final Color lookup; - private final Color color; - - BiomeType(int r, int g, int b, Color color) { - this(new Color(r, g, b), color); - } - - BiomeType(Color lookup, Color color) { - this.lookup = lookup; - this.color = BiomeTypeColors.getInstance().getColor(name(), color); - } - - Color getLookup() { - return lookup; - } - - public Color getColor() { - return color; - } - - public boolean isExtreme() { - return this == TUNDRA || this == DESERT; - } - - public static BiomeType get(float temperature, float moisture) { - return getCurve(temperature, moisture); - } - - public static BiomeType getLinear(float temperature, float moisture) { - int x = NoiseUtil.round(MAX * temperature); - int y = getYLinear(x, temperature, moisture); - return getType(x, y); - } - - public static BiomeType getCurve(float temperature, float moisture) { - int x = NoiseUtil.round(MAX * temperature); - int y = getYCurve(x, temperature, moisture); - return getType(x, y); - } - - public static float getEdge(float temperature, float moisture) { - return getEdgeCurve(temperature, moisture); - } - - public static float getEdgeLinear(float temperature, float moisture) { - int x = NoiseUtil.round(MAX * temperature); - int y = getYLinear(x, temperature, moisture); - return getEdge(x, y); - } - - public static float getEdgeCurve(float temperature, float moisture) { - int x = NoiseUtil.round(MAX * temperature); - int y = getYCurve(x, temperature, moisture); - return getEdge(x, y); - } - - public static void apply(Cell cell) { - applyCurve(cell); - } - - public static void applyLinear(Cell cell) { - cell.biomeType = get(cell.biomeTemperature, cell.biomeMoisture); - cell.biomeTypeMask = getEdge(cell.temperature, cell.moisture); - } - - public static void applyCurve(Cell cell) { - cell.biomeType = get(cell.biomeTemperature, cell.biomeMoisture); - cell.biomeTypeMask = getEdge(cell.temperature, cell.moisture); - } - - private static BiomeType getType(int x, int y) { - return BiomeTypeLoader.getInstance().getTypeMap()[y][x]; - } - - private static float getEdge(int x, int y) { - return BiomeTypeLoader.getInstance().getEdgeMap()[y][x]; - } - - private static int getYLinear(int x, float temperature, float moisture) { - if (moisture > temperature) { - return x; - } - return NoiseUtil.round(MAX * moisture); - } - - private static int getYCurve(int x, float temperature, float moisture) { - int max = x + ((MAX - x) / 2); - int y = NoiseUtil.round(max * moisture); - return Math.min(x, y); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeColors.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeColors.java deleted file mode 100644 index 60b72d3..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeColors.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.biome; - -import java.awt.*; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -public class BiomeTypeColors { - - private static BiomeTypeColors instance = new BiomeTypeColors(); - - private final Map colors = new HashMap<>(); - - private BiomeTypeColors() { - try (InputStream inputStream = BiomeType.class.getResourceAsStream("/biomes.txt")) { - Properties properties = new Properties(); - properties.load(inputStream); - for (Map.Entry entry : properties.entrySet()) { - Color color = Color.decode("#" + entry.getValue().toString()); - colors.put(entry.getKey().toString(), color); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - public Color getColor(String name, Color defaultColor) { - return colors.getOrDefault(name, defaultColor); - } - - public static BiomeTypeColors getInstance() { - return instance; - } - - public static void main(String[] args) throws Throwable { - try (FileWriter writer = new FileWriter("biome_colors.properties")) { - Properties properties = new Properties(); - for (BiomeType type : BiomeType.values()) { - int r = type.getColor().getRed(); - int g = type.getColor().getGreen(); - int b = type.getColor().getBlue(); - properties.setProperty(type.name(), String.format("%02x%02x%02x", r, g, b)); - } - properties.store(writer, "TerraForged BiomeType Hex Colors (do not include hash/pound character)"); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeLoader.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeLoader.java deleted file mode 100644 index 010855e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/biome/BiomeTypeLoader.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.biome; - -import me.dags.noise.util.NoiseUtil; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - -public class BiomeTypeLoader { - - private static BiomeTypeLoader instance; - - private final float[][] edges = new float[BiomeType.RESOLUTION][BiomeType.RESOLUTION]; - private final BiomeType[][] map = new BiomeType[BiomeType.RESOLUTION][BiomeType.RESOLUTION]; - - public BiomeTypeLoader() { - generateTypeMap(); - generateEdgeMap(); - } - - public BiomeType[][] getTypeMap() { - return map; - } - - public float[][] getEdgeMap() { - return edges; - } - - private BiomeType getType(int x, int y) { - return map[y][x]; - } - - private void generateTypeMap() { - try { - BufferedImage image = ImageIO.read(BiomeType.class.getResourceAsStream("/biomes.png")); - float xf = image.getWidth() / (float) BiomeType.RESOLUTION; - float yf = image.getHeight() / (float) BiomeType.RESOLUTION; - for (int y = 0; y < BiomeType.RESOLUTION; y++) { - for (int x = 0; x < BiomeType.RESOLUTION; x++) { - if (BiomeType.MAX - y > x) { - map[BiomeType.MAX - y][x] = BiomeType.ALPINE; - continue; - } - int ix = NoiseUtil.round(x * xf); - int iy = NoiseUtil.round(y * yf); - int argb = image.getRGB(ix, iy); - Color color = fromARGB(argb); - map[BiomeType.MAX - y][x] = forColor(color); - } - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void generateEdgeMap() { - int[] distances = new int[BiomeType.values().length]; - for (int y = 0; y < BiomeType.RESOLUTION; y++) { - for (int x = 0; x < BiomeType.RESOLUTION; x++) { - if (y > x) continue; - BiomeType type = getType(x, y); - if (type == BiomeType.ALPINE) { - continue; - } - int distance2 = getEdge(x, y, type); - edges[y][x] = distance2; - distances[type.ordinal()] = Math.max(distances[type.ordinal()], distance2); - } - } - - for (int y = 0; y < BiomeType.RESOLUTION; y++) { - for (int x = 0; x < BiomeType.RESOLUTION; x++) { - BiomeType type = getType(x, y); - int max = distances[type.ordinal()]; - float distance = edges[y][x]; - float value = NoiseUtil.pow(distance / max, 0.33F); - edges[y][x] = NoiseUtil.clamp(value, 0, 1); - } - } - } - - private int getEdge(int cx, int cy, BiomeType type) { - int radius = BiomeType.RESOLUTION / 4; - int distance2 = Integer.MAX_VALUE; - int x0 = Math.max(0, cx - radius); - int x1 = Math.min(BiomeType.MAX, cx + radius); - int y0 = Math.max(0, cy - radius); - int y1 = Math.min(BiomeType.MAX, cy + radius); - for (int y = y0; y <= y1; y++) { - for (int x = x0; x <= x1; x++) { - BiomeType neighbour = getType(x, y); - - if (neighbour == BiomeType.ALPINE) { - continue; - } - - if (neighbour != type) { - int dist2 = dist2(cx, cy, x, y); - if (dist2 < distance2) { - distance2 = dist2; - } - } - } - } - return distance2; - } - - private static BiomeType forColor(Color color) { - BiomeType type = null; - int closest = Integer.MAX_VALUE; - for (BiomeType t : BiomeType.values()) { - int distance2 = getDistance2(color, t.getLookup()); - if (distance2 < closest) { - closest = distance2; - type = t; - } - } - if (type == null) { - return BiomeType.GRASSLAND; - } - return type; - } - - private static int getDistance2(Color a, Color b) { - int dr = a.getRed() - b.getRed(); - int dg = a.getGreen() - b.getGreen(); - int db = a.getBlue() - b.getBlue(); - return dr * dr + dg * dg + db * db; - } - - private static Color fromARGB(int argb) { - int b = (argb) & 0xFF; - int g = (argb >> 8) & 0xFF; - int r = (argb >> 16) & 0xFF; - return new Color(r, g, b); - } - - private static int dist2(int x1, int y1, int x2, int y2) { - int dx = x1 - x2; - int dy = y1 - y2; - return dx * dx + dy * dy; - } - - private static BufferedImage generateEdgeMapImage() { - BufferedImage image = new BufferedImage(BiomeType.RESOLUTION, BiomeType.RESOLUTION, BufferedImage.TYPE_INT_RGB); - for (int y = 0; y < BiomeType.RESOLUTION; y++) { - for (int x = 0; x < BiomeType.RESOLUTION; x++) { - float temperature = x / (float) BiomeType.RESOLUTION; - float moisture = y / (float) BiomeType.RESOLUTION; - float value = BiomeType.getEdge(temperature, moisture); - int color = Color.HSBtoRGB(0, 0, value); - image.setRGB(x, image.getHeight() - 1 - y, color); - } - } - return image; - } - - public static BiomeTypeLoader getInstance() { - if (instance == null) { - instance = new BiomeTypeLoader(); - } - return instance; - } - - public static void main(String[] args) throws Throwable { - BufferedImage img = generateEdgeMapImage(); - ImageIO.write(img, "png", new File("biomes_dist.png")); - JLabel label = new JLabel(new ImageIcon(img)); - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.add(label); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Climate.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Climate.java deleted file mode 100644 index 4a52538..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Climate.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.climate; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.source.Rand; - -public class Climate { - - private final float seaLevel; - private final float lowerHeight; - private final float midHeight = 0.45F; - private final float upperHeight = 0.75F; - - private final float moistureModifier = 0.1F; - private final float temperatureModifier = 0.05F; - - private final Rand rand; - private final Module treeLine; - private final Module offsetX; - private final Module offsetY; - - private final ClimateModule biomeNoise; - - public Climate(GeneratorContext context) { - this.biomeNoise = new ClimateModule(context.seed, context.settings); - - this.treeLine = Source.perlin(context.seed.next(), context.settings.generator.biome.biomeSize * 2, 1) - .scale(context.levels.scale(25)) // 30 units worth of variance - .bias(context.levels.ground(40)) // start at-least 30 units above ground level - .clamp(0, 1); - - this.rand = new Rand(Source.builder().seed(context.seed.next())); - this.offsetX = context.settings.generator.biomeEdgeNoise.build(context.seed.next()); - this.offsetY = context.settings.generator.biomeEdgeNoise.build(context.seed.next()); - this.seaLevel = context.levels.water; - this.lowerHeight = context.levels.ground; - } - - public Rand getRand() { - return rand; - } - - public float getOffsetX(float x, float z, int distance) { - return offsetX.getValue(x, z) * distance; - } - - public float getOffsetZ(float x, float z, int distance) { - return offsetY.getValue(x, z) * distance; - } - - public float getTreeLine(float x, float z) { - return treeLine.getValue(x, z); - } - - public void apply(Cell cell, float x, float z, boolean mask) { - biomeNoise.apply(cell, x, z, mask); - - modifyTemp(cell, x, z); - } - - private void modifyTemp(Cell cell, float x, float z) { - float height = cell.value; - if (height > upperHeight) { - cell.temperature = Math.max(0, cell.temperature - temperatureModifier); - return; - } - - // temperature decreases away from 'midHeight' towards 'upperHeight' - if (height > midHeight) { - float delta = (height - midHeight) / (upperHeight - midHeight); - cell.temperature = Math.max(0, cell.temperature - (delta * temperatureModifier)); - return; - } - - height = Math.max(lowerHeight, height); - - // temperature increases away from 'midHeight' towards 'lowerHeight' - if (height >= lowerHeight) { - float delta = 1 - ((height - lowerHeight) / (midHeight - lowerHeight)); - cell.temperature = Math.min(1, cell.temperature + (delta * temperatureModifier)); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/ClimateModule.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/ClimateModule.java deleted file mode 100644 index 4530609..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/ClimateModule.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.climate; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.func.DistanceFunc; -import me.dags.noise.func.EdgeFunc; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; - -public class ClimateModule { - - private final int seed; - - private final float edgeClamp; - private final float edgeScale; - private final float biomeFreq; - private final float warpStrength; - - private final Module warpX; - private final Module warpZ; - private final Module moisture; - private final Module temperature; - - public ClimateModule(Seed seed, Settings settings) { - int biomeSize = settings.generator.biome.biomeSize; - - // todo - better solution (reduces the amount that temp/moist grows with biome size) - int tempScaler = biomeSize > 500 ? 8 : 10; - int moistScaler = biomeSize > 500 ? 20 : 40; - - float biomeFreq = 1F / biomeSize; - int moistureSize = moistScaler * biomeSize; - int temperatureSize = tempScaler * biomeSize; - int moistScale = NoiseUtil.round(moistureSize * biomeFreq); - int tempScale = NoiseUtil.round(temperatureSize * biomeFreq); - int warpScale = settings.generator.biome.biomeWarpScale; - - this.seed = seed.next(); - this.edgeClamp = 1F; - this.edgeScale = 1 / edgeClamp; - this.biomeFreq = 1F / biomeSize; - this.warpStrength = settings.generator.biome.biomeWarpStrength; - this.warpX = Source.perlin(seed.next(), warpScale, 2).bias(-0.5); - this.warpZ = Source.perlin(seed.next(), warpScale, 2).bias(-0.5); - - Module moisture = Source.simplex(seed.next(), moistScale, 2).clamp(0.15, 0.85).map(0, 1); - this.moisture = settings.climate.moisture.clamp(moisture) - .warp(seed.next(), moistScale / 2, 1, moistScale / 4D) - .warp(seed.next(), moistScale / 6, 2, moistScale / 12D); - - Module temperature = Source.sin(tempScale, Source.constant(0.9)) - .clamp(0.05, 0.95).map(0, 1); - - this.temperature = new Compressor(settings.climate.temperature.clamp(temperature), 0.1F, 0.2F) - .warp(seed.next(), tempScale * 4, 2, tempScale * 4) - .warp(seed.next(), tempScale, 1, tempScale) - .warp(seed.next(), tempScale / 8, 1, tempScale / 8D); - } - - public void apply(Cell cell, float x, float y, boolean mask) { - float ox = warpX.getValue(x, y) * warpStrength; - float oz = warpZ.getValue(x, y) * warpStrength; - - x += ox; - y += oz; - - x *= biomeFreq; - y *= biomeFreq; - - int cellX = 0; - int cellY = 0; - - Vec2f vec2f = null; - int xr = NoiseUtil.round(x); - int yr = NoiseUtil.round(y); - float edgeDistance = 999999.0F; - float edgeDistance2 = 999999.0F; - float valueDistance = 3.4028235E38F; - DistanceFunc dist = DistanceFunc.NATURAL; - - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - int xi = xr + dx; - int yi = yr + dy; - Vec2f vec = NoiseUtil.CELL_2D[NoiseUtil.hash2D(seed, xi, yi) & 255]; - - float vecX = xi - x + vec.x; - float vecY = yi - y + vec.y; - float distance = dist.apply(vecX, vecY); - - if (distance < valueDistance) { - valueDistance = distance; - vec2f = vec; - cellX = xi; - cellY = yi; - } - - if (distance < edgeDistance2) { - edgeDistance2 = Math.max(edgeDistance, distance); - } else { - edgeDistance2 = Math.max(edgeDistance, edgeDistance2); - } - - edgeDistance = Math.min(edgeDistance, distance); - } - } - - if (mask) { - cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2); - } else { - cell.biome = cellValue(seed, cellX, cellY); - cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2); - cell.biomeMoisture = moisture.getValue(cellX + vec2f.x, cellY + vec2f.y); - cell.biomeTemperature = temperature.getValue(cellX + vec2f.x, cellY + vec2f.y); - cell.moisture = moisture.getValue(x, y); - cell.temperature = temperature.getValue(x, y); - - BiomeType.apply(cell); - } - } - - private float cellValue(int seed, int cellX, int cellY) { - float value = NoiseUtil.valCoord2D(seed, cellX, cellY); - return NoiseUtil.map(value, -1, 1, 2); - } - - private float edgeValue(float distance, float distance2) { - EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV; - float value = edge.apply(distance, distance2); - value = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range()); - if (value > edgeClamp) { - return 1F; - } - return value * edgeScale; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Compressor.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Compressor.java deleted file mode 100644 index 6c14475..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/climate/Compressor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.climate; - -import me.dags.noise.Module; - -public class Compressor implements Module { - - private final float lowerStart; - private final float lowerEnd; - private final float lowerRange; - private final float lowerExpandRange; - - private final float upperStart; - private final float upperEnd; - private final float upperRange; - private final float upperExpandedRange; - - private final float compression; - private final float compressionRange; - - private final Module module; - - public Compressor(Module module, float inset, float amount) { - this(module, inset, inset + amount, 1 - inset - amount, 1 - inset); - } - - public Compressor(Module module, float lowerStart, float lowerEnd, float upperStart, float upperEnd) { - this.module = module; - this.lowerStart = lowerStart; - this.lowerEnd = lowerEnd; - this.lowerRange = lowerStart; - this.lowerExpandRange = lowerEnd; - this.upperStart = upperStart; - this.upperEnd = upperEnd; - this.upperRange = 1 - upperEnd; - this.upperExpandedRange = 1 - upperStart; - this.compression = upperStart - lowerEnd; - this.compressionRange = upperEnd - lowerStart; - } - - @Override - public float getValue(float x, float y) { - float value = module.getValue(x, y); - if (value <= lowerStart) { - float alpha = value / lowerRange; - return alpha * lowerExpandRange; - } else if (value >= upperEnd) { - float delta = value - upperEnd; - float alpha = delta / upperRange; - return upperStart + alpha * upperExpandedRange; - } else { - float delta = value - lowerStart; - float alpha = delta / compressionRange; - return lowerEnd + alpha * compression; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper2.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper2.java deleted file mode 100644 index 0d7954e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper2.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.continent; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.func.Interpolation; -import me.dags.noise.util.NoiseUtil; - -public class ContinentLerper2 implements Populator { - - private final Populator lower; - private final Populator upper; - - private final float blendLower; - private final float blendUpper; - private final float blendRange; - private final float midpoint; - private final float tagThreshold; - - public ContinentLerper2(Populator lower, Populator upper, float min, float max, float split, float tagThreshold) { - this.lower = lower; - this.upper = upper; - this.blendLower = min; - this.blendUpper = max; - this.blendRange = blendUpper - blendLower; - this.midpoint = blendLower + (blendRange * split); - this.tagThreshold = tagThreshold; - } - - @Override - public void apply(Cell cell, float x, float y) { - float select = cell.continentEdge; - - if (select < blendLower) { - lower.apply(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.apply(cell, x, y); - return; - } - - float alpha = Interpolation.LINEAR.apply((select - blendLower) / blendRange); - lower.apply(cell, x, y); - - float lowerVal = cell.value; - Terrain lowerType = cell.tag; - - upper.apply(cell, x, y); - float upperVal = cell.value; - - cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha); - if (select < midpoint) { - cell.tag = lowerType; - } - } - - @Override - public void tag(Cell cell, float x, float y) { - float select = cell.continentEdge; - if (select < blendLower) { - lower.tag(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.tag(cell, x, y); - return; - } - - if (select < tagThreshold) { - lower.tag(cell, x, y); - } else { - upper.tag(cell, x, y); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper3.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper3.java deleted file mode 100644 index 06252dd..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentLerper3.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.continent; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.func.Interpolation; -import me.dags.noise.util.NoiseUtil; - -public class ContinentLerper3 implements Populator { - - private final Climate climate; - private final Populator lower; - private final Populator middle; - private final Populator upper; - private final float midpoint; - - private final float blendLower; - private final float blendUpper; - - private final float lowerRange; - private final float upperRange; - - public ContinentLerper3(Climate climate, Populator lower, Populator middle, Populator upper, float min, float mid, float max) { - this.climate = climate; - this.lower = lower; - this.upper = upper; - this.middle = middle; - - this.midpoint = mid; - this.blendLower = min; - this.blendUpper = max; - - this.lowerRange = midpoint - blendLower; - this.upperRange = blendUpper - midpoint; - } - - @Override - public void apply(Cell cell, float x, float y) { - float select = cell.continentEdge; - if (select < blendLower) { - lower.apply(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.apply(cell, x, y); - return; - } - - if (select < midpoint) { - float alpha = Interpolation.CURVE3.apply((select - blendLower) / lowerRange); - - lower.apply(cell, x, y); - float lowerVal = cell.value; - Terrain lowerType = cell.tag; - - middle.apply(cell, x, y); - float upperVal = cell.value; - - cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha); - } else { - float alpha = Interpolation.CURVE3.apply((select - midpoint) / upperRange); - - middle.apply(cell, x, y); - float lowerVal = cell.value; - - upper.apply(cell, x, y); - cell.value = NoiseUtil.lerp(lowerVal, cell.value, alpha); - } - } - - @Override - public void tag(Cell cell, float x, float y) { - float select = cell.continentEdge; - if (select < blendLower) { - lower.tag(cell, x, y); - return; - } - - if (select > blendUpper) { - upper.tag(cell, x, y); - return; - } - - if (select < midpoint) { - lower.tag(cell, x, y); - if (cell.value > cell.tag.getMax(climate.getRand().getValue(x, y))) { - upper.tag(cell, x, y); - } - } else { - upper.tag(cell, x, y); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentModule.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentModule.java deleted file mode 100644 index 7773245..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/continent/ContinentModule.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.continent; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.settings.GeneratorSettings; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.domain.Domain; -import me.dags.noise.func.DistanceFunc; -import me.dags.noise.func.EdgeFunc; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; - -public class ContinentModule implements Populator { - - private static final float edgeClampMin = 0.05F; - private static final float edgeClampMax = 0.50F; - private static final float edgeClampRange = edgeClampMax - edgeClampMin; - - private final int seed; - private final float frequency; - - private final float edgeMin; - private final float edgeMax; - private final float edgeRange; - - private final Domain warp; - private final Module shape; - - public ContinentModule(Seed seed, GeneratorSettings settings) { - int tectonicScale = settings.land.continentScale * 4; - int continentScale = settings.land.continentScale / 2; - double oceans = Math.min(Math.max(settings.world.oceanSize, 0.01), 0.99); - double shapeMin = 0.15 + (oceans * 0.35); - this.seed = seed.next(); - - this.frequency = 1F / tectonicScale; - this.edgeMin = edgeClampMin; - this.edgeMax = (float) oceans; - this.edgeRange = edgeMax - edgeMin; - - this.warp = Domain.warp(Source.SIMPLEX, seed.next(), continentScale, 3, continentScale); - - this.shape = Source.perlin(seed.next(), settings.land.continentScale, 2) - .clamp(shapeMin, 0.7) - .map(0, 1) - .warp(Source.SIMPLEX, seed.next(), continentScale / 2, 1, continentScale / 4D) - .warp(seed.next(), 50, 1, 20D); - } - - @Override - public float getValue(float x, float y) { - if (true) { - throw new RuntimeException("no pls!"); - } else { - Cell cell = new Cell<>(); - apply(cell, x, y); - return cell.continentEdge; - } - } - - @Override - public void apply(Cell cell, final float x, final float y) { - float ox = warp.getOffsetX(x, y); - float oz = warp.getOffsetY(x, y); - - float px = x + ox; - float py = y + oz; - - px *= frequency; - py *= frequency; - - int cellX = 0; - int cellY = 0; - - int xr = NoiseUtil.round(px); - int yr = NoiseUtil.round(py); - float edgeDistance = 999999.0F; - float edgeDistance2 = 999999.0F; - float valueDistance = 3.4028235E38F; - DistanceFunc dist = DistanceFunc.NATURAL; - - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - int xi = xr + dx; - int yi = yr + dy; - Vec2f vec = NoiseUtil.CELL_2D[NoiseUtil.hash2D(seed, xi, yi) & 255]; - - float vecX = xi - px + vec.x; - float vecY = yi - py + vec.y; - float distance = dist.apply(vecX, vecY); - - if (distance < valueDistance) { - valueDistance = distance; - cellX = xi; - cellY = yi; - } - - if (distance < edgeDistance2) { - edgeDistance2 = Math.max(edgeDistance, distance); - } else { - edgeDistance2 = Math.max(edgeDistance, edgeDistance2); - } - - edgeDistance = Math.min(edgeDistance, distance); - } - } - - - float shapeNoise = shape.getValue(x, y); - float continentNoise = edgeValue(edgeDistance, edgeDistance2); - - cell.continent = cellValue(seed, cellX, cellY); - cell.continentEdge = shapeNoise * continentNoise; - } - - @Override - public void tag(Cell cell, float x, float y) { - - } - - private float cellValue(int seed, int cellX, int cellY) { - float value = NoiseUtil.valCoord2D(seed, cellX, cellY); - return NoiseUtil.map(value, -1, 1, 2); - } - - private float edgeValue(float distance, float distance2) { - EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV; - float value = edge.apply(distance, distance2); - float edgeValue = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range()); - if (edgeValue < edgeMin) { - return 0F; - } - if (edgeValue > edgeMax) { - return 1F; - } - return (edgeValue - edgeMin) / edgeRange; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Decorator.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Decorator.java deleted file mode 100644 index df92f3b..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Decorator.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.decorator; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; - -public interface Decorator { - - boolean apply(Cell cell, float x, float y); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertDunes.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertDunes.java deleted file mode 100644 index 21ad1c8..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertDunes.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.decorator; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.func.CellFunc; - -public class DesertDunes implements Decorator { - - private final Module module; - private final float climateMin; - private final float climateMax; - private final float climateRange; - - private final Levels levels; - private final Terrains terrains; - private final Terrain dunes = new Terrain("dunes", 100); - - public DesertDunes(GeneratorContext context) { - this.climateMin = 0.6F; - this.climateMax = 0.85F; - this.climateRange = climateMax - climateMin; - this.levels = context.levels; - this.terrains = context.terrain; - this.module = Source.cell(context.seed.next(), 80, CellFunc.DISTANCE) - .warp(context.seed.next(), 70, 1, 70) - .scale(30 / 255D); - } - - @Override - public boolean apply(Cell cell, float x, float y) { - float temp = cell.temperature; - float moisture = 1 - cell.moisture; - float climate = temp * moisture; - if (climate < climateMin) { - return false; - } - - float duneHeight = module.getValue(x, y); - float climateMask = climate > climateMax ? 1F : (climate - climateMin) / climateRange; - float regionMask = cell.mask(0.4F, 0.5F, 0,0.8F); - - float height = duneHeight * climateMask * regionMask; - cell.value += height; - cell.tag = dunes; - - return height >= levels.unit; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertStacks.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertStacks.java deleted file mode 100644 index 8896675..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/DesertStacks.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.decorator; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Module; -import me.dags.noise.Source; - -public class DesertStacks implements Decorator { - - private final float minY; - private final float maxY; - private final Levels levels; - private final Module module; - - public DesertStacks(Seed seed, Levels levels) { - Module mask = Source.perlin(seed.next(), 500, 1).clamp(0.7, 1).map(0, 1); - - Module shape = Source.perlin(seed.next(), 25, 1).clamp(0.6, 1).map(0, 1) - .mult(Source.perlin(seed.next(), 8, 1).alpha(0.1)); - - Module top = Source.perlin(seed.next(), 4, 1).alpha(0.25); - - Module scale = Source.perlin(seed.next(), 400, 1) - .clamp(levels.scale(20), levels.scale(35)); - - Module stack = (x, y) -> { - float value = shape.getValue(x, y); - if (value > 0.3) { - return top.getValue(x, y); - } - return value * 0.95F; - }; - - this.minY = levels.water(0); - this.maxY = levels.water(50); - this.levels = levels; - this.module = stack.scale(scale).mult(mask); - } - - @Override - public boolean apply(Cell cell, float x, float y) { - if (BiomeType.DESERT != cell.biomeType) { - return false; - } - - if (cell.value <= minY || cell.value > maxY) { - return false; - } - - float value = module.getValue(x, y); - value *= cell.biomeEdge; - cell.value += value; - - return value > levels.unit; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Wetlands.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Wetlands.java deleted file mode 100644 index 661d3cc..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/decorator/Wetlands.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.decorator; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.util.NoiseUtil; - -public class Wetlands implements Decorator { - - private final Module module; - private final float poolBase; - private final float bankHeight; - - private final Terrain wetlands; - - public Wetlands(Seed seed, Terrains terrain, Levels levels) { - this.wetlands = terrain.wetlands; - this.poolBase = levels.water(-3); - this.bankHeight = levels.water(2); - this.module = Source.perlin(seed.next(), 12, 1).clamp(0.35, 0.65).map(0, 1); - } - - @Override - public boolean apply(Cell cell, float x, float y) { - if (cell.value < poolBase) { - return false; - } - - float tempAlpha = getAlpha(cell.temperature, 0.3F, 0.7F); - if (tempAlpha == 0) { - return false; - } - - float moistAlpha = getAlpha(cell.moisture, 0.7F, 1F); - if (moistAlpha == 0) { - return false; - } - - float riverAlpha = getAlpha(1 - cell.riverMask, 0.85F, 0.95F); - if (riverAlpha == 0) { - return false; - } - - float alpha = tempAlpha * moistAlpha * riverAlpha; - float value1 = NoiseUtil.lerp(cell.value, bankHeight, alpha); - cell.value = Math.min(cell.value, value1); - - float poolAlpha = getAlpha(alpha, 0.35F, 0.55F); - float shape = module.getValue(x, y); - float value2 = NoiseUtil.lerp(cell.value, poolBase, shape * poolAlpha); - cell.value = Math.min(cell.value, value2); - - if (poolAlpha > 0.5) { - cell.tag = wetlands; - } - - return true; - } - - private static float getAlpha(float value, float min, float max) { - return getAlpha(value, min, max, false); - } - - private static float getAlpha(float value, float min, float max, boolean inverse) { - if (value < min) { - return 0F; - } - if (value >= max) { - return 1F; - } - float alpha = (value - min) / (max - min); - if (inverse) { - return 1F - alpha; - } - return alpha; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/DepthBuffer.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/DepthBuffer.java deleted file mode 100644 index 3188790..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/DepthBuffer.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.terraforged.core.world.geology; - -public class DepthBuffer { - - private float sum; - private float[] buffer; - - public void init(int size) { - sum = 0F; - if (buffer == null || buffer.length < size) { - buffer = new float[size]; - } - } - - public float getSum() { - return sum; - } - - public float get(int index) { - return buffer[index]; - } - - public float getDepth(int index) { - return buffer[index] / sum; - } - - public void set(int index, float value) { - sum += value; - buffer[index] = value; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Geology.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Geology.java deleted file mode 100644 index fd7345c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Geology.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.geology; - -import me.dags.noise.Module; - -import java.util.ArrayList; -import java.util.List; - -public class Geology { - - private final Module selector; - private final List> backing = new ArrayList<>(); - - public Geology(Module selector) { - this.selector = selector; - } - - public Geology add(Geology geology) { - backing.addAll(geology.backing); - return this; - } - - public Geology add(Strata strata) { - backing.add(strata); - return this; - } - - public Strata getStrata(float x, int y) { - float noise = selector.getValue(x, y); - return getStrata(noise); - } - - public Strata getStrata(float value) { - int index = (int) (value * backing.size()); - index = Math.min(backing.size() - 1, index); - return backing.get(index); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Strata.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Strata.java deleted file mode 100644 index 1ba7be4..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Strata.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.geology; - -import com.terraforged.core.util.Seed; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.util.NoiseUtil; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -public class Strata { - - private final Module heightMod; - private final List> strata; - - private Strata(Module heightMod, List> strata) { - this.strata = strata; - this.heightMod = heightMod; - } - - public boolean downwards(final int x, final int y, final int z, final Stratum.Visitor visitor) { - DepthBuffer buffer = new DepthBuffer(); - initBuffer(buffer, x, z); - return downwards(x, y, z, buffer, visitor); - } - - public boolean downwards(final int x, final int y, final int z, final DepthBuffer buffer, Stratum.Visitor visitor) { - initBuffer(buffer, x, z); - - int py = y; - T last = null; - for (int i = 0; i < strata.size(); i++) { - float depth = buffer.getDepth(i); - int height = NoiseUtil.round(depth * y); - T value = strata.get(i).getValue(); - last = value; - for (int dy = 0; dy < height; dy++) { - if (py <= y) { - boolean cont = visitor.visit(py, value); - if (!cont) { - return false; - } - } - if (--py < 0) { - return false; - } - } - } - if (last != null) { - while (py > 0) { - visitor.visit(py, last); - py--; - } - } - return true; - } - - private int getYOffset(int x, int z) { - return (int) (64 * heightMod.getValue(x, z)); - } - - private void initBuffer(DepthBuffer buffer, int x, int z) { - buffer.init(strata.size()); - for (int i = 0; i < strata.size(); i++) { - float depth = strata.get(i).getDepth(x, z); - buffer.set(i, depth); - } - } - - public static Builder builder(int seed, me.dags.noise.source.Builder noise) { - return new Builder<>(seed, noise); - } - - public static class Builder { - - private final Seed seed; - private final me.dags.noise.source.Builder noise; - private final List> strata = new LinkedList<>(); - - public Builder(int seed, me.dags.noise.source.Builder noise) { - this.seed = new Seed(seed); - this.noise = noise; - } - - public Builder add(T material, double depth) { - Module module = noise.seed(seed.next()).perlin().scale(depth); - strata.add(Stratum.of(material, module)); - return this; - } - - public Builder add(Source type, T material, double depth) { - Module module = noise.seed(seed.next()).build(type).scale(depth); - strata.add(Stratum.of(material, module)); - return this; - } - - public Strata build() { - Module height = Source.cell(seed.next(), 100); - return new Strata<>(height, new ArrayList<>(strata)); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Stratum.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Stratum.java deleted file mode 100644 index c51ab6e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/geology/Stratum.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.geology; - -import me.dags.noise.Module; -import me.dags.noise.Source; - -public class Stratum { - - private final T value; - private final Module depth; - - public Stratum(T value, double depth) { - this(value, Source.constant(depth)); - } - - public Stratum(T value, Module depth) { - this.depth = depth; - this.value = value; - } - - public T getValue() { - return value; - } - - public float getDepth(float x, float z) { - return depth.getValue(x, z); - } - - public static Stratum of(T t, double depth) { - return new Stratum<>(t, depth); - } - - public static Stratum of(T t, Module depth) { - return new Stratum<>(t, depth); - } - - public interface Visitor { - - boolean visit(int y, T value); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Heightmap.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Heightmap.java deleted file mode 100644 index a9c176f..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Heightmap.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.heightmap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Extent; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.region.Size; -import com.terraforged.core.util.concurrent.ObjectPool; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.rivermap.RiverMap; -import com.terraforged.core.world.rivermap.RiverRegionList; -import com.terraforged.core.world.terrain.Terrain; - -public interface Heightmap extends Populator, Extent { - - Climate getClimate(); - - RiverMap getRiverMap(); - - void visit(Cell cell, float x, float z); - - void applyBase(Cell cell, float x, float z); - - void applyRivers(Cell cell, float x, float z, RiverRegionList rivers); - - void applyClimate(Cell cell, float x, float z); - - @Override - default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor visitor) { - int chunkSize = Size.chunkToBlock(1); - - int chunkMinX = Size.blockToChunk(minX); - int chunkMinZ = Size.blockToChunk(minZ); - int chunkMaxX = Size.blockToChunk(maxX); - int chunkMaxZ = Size.blockToChunk(maxZ); - - try (ObjectPool.Item> cell = Cell.pooled()) { - for (int chunkZ = chunkMinZ; chunkZ <= chunkMaxZ; chunkZ++) { - for (int chunkX = chunkMinX; chunkX <= chunkMaxX; chunkX++) { - int chunkStartX = Size.chunkToBlock(chunkX); - int chunkStartZ = Size.chunkToBlock(chunkZ); - for (int dz = 0; dz < chunkSize; dz++) { - for (int dx = 0; dx < chunkSize; dx++) { - int x = chunkStartX + dx; - int z = chunkStartZ + dz; - apply(cell.getValue(), x, z); - if (x >= minX && x < maxX && z >= minZ && z < maxZ) { - int relX = x - minX; - int relZ = z - minZ; - visitor.visit(cell.getValue(), relX, relZ); - } - } - } - } - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Levels.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Levels.java deleted file mode 100644 index bc1f6a6..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/Levels.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.heightmap; - -import com.terraforged.core.settings.GeneratorSettings; -import me.dags.noise.util.NoiseUtil; - -public class Levels { - - public final int worldHeight; - - public final float unit; - - // y index of the top-most water block - public final int waterY; - private final int groundY; - - // top of the first ground block (ie 1 above ground index) - public final int groundLevel; - // top of the top-most water block (ie 1 above water index) - public final int waterLevel; - - // ground index mapped between 0-1 (default 63 / 256) - public final float ground; - // water index mapped between 0-1 (default 62 / 256) - public final float water; - - public Levels(GeneratorSettings settings) { - worldHeight = Math.max(1, settings.world.worldHeight); - unit = NoiseUtil.div(1, worldHeight); - - waterLevel = settings.world.seaLevel; - groundLevel = waterLevel + 1; - - waterY = Math.min(waterLevel - 1, worldHeight); - groundY = Math.min(groundLevel - 1, worldHeight); - - ground = NoiseUtil.div(groundY, worldHeight); - water = NoiseUtil.div(waterY, worldHeight); - } - - public int scale(float value) { - if (value >= 1F) { - return worldHeight - 1; - } - return (int) (value * worldHeight); - } - - public float scale(int level) { - return NoiseUtil.div(level, worldHeight); - } - - public float water(int amount) { - return NoiseUtil.div(waterY + amount, worldHeight); - } - - public float ground(int amount) { - return NoiseUtil.div(groundY + amount, worldHeight); - } - - public static float getSeaLevel(GeneratorSettings settings) { - int worldHeight = Math.max(1, settings.world.worldHeight); - int waterLevel = Math.min(settings.world.seaLevel, worldHeight); - return NoiseUtil.div(waterLevel, worldHeight); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionConfig.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionConfig.java deleted file mode 100644 index 800bd95..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionConfig.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.heightmap; - -import me.dags.noise.Module; - -public class RegionConfig { - - public final int seed; - public final int scale; - public final Module warpX; - public final Module warpZ; - public final double warpStrength; - - public RegionConfig(int seed, int scale, Module warpX, Module warpZ, double warpStrength) { - this.seed = seed; - this.scale = scale; - this.warpX = warpX; - this.warpZ = warpZ; - this.warpStrength = warpStrength; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionExtent.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionExtent.java deleted file mode 100644 index 78134ac..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/RegionExtent.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.heightmap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Extent; -import com.terraforged.core.region.Region; -import com.terraforged.core.region.Size; -import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.core.world.terrain.Terrain; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -public interface RegionExtent extends Extent { - - int chunkToRegion(int coord); - - Region getRegion(int regionX, int regionZ); - - CompletableFuture getRegionAsync(int regionX, int regionZ); - - default ChunkReader getChunk(int chunkX, int chunkZ) { - int regionX = chunkToRegion(chunkX); - int regionZ = chunkToRegion(chunkZ); - Region region = getRegion(regionX, regionZ); - return region.getChunk(chunkX, chunkZ); - } - - default List> getRegions(int minRegionX, int minRegionZ, int maxRegionX, int maxRegionZ) { - List> regions = new LinkedList<>(); - for (int rz = minRegionZ; rz <= maxRegionZ; rz++) { - for (int rx = minRegionX; rx <= maxRegionX; rx++) { - regions.add(getRegionAsync(rx, rz)); - } - } - return regions; - } - - @Override - default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor visitor) { - int minRegionX = chunkToRegion(Size.blockToChunk(minX)); - int minRegionZ = chunkToRegion(Size.blockToChunk(minZ)); - int maxRegionX = chunkToRegion(Size.blockToChunk(maxX)); - int maxRegionZ = chunkToRegion(Size.blockToChunk(maxZ)); - List> regions = getRegions(minRegionX, minRegionZ, maxRegionX, maxRegionZ); - while (!regions.isEmpty()) { - regions.removeIf(future -> { - if (!future.isDone()) { - return false; - } - Region region = future.join(); - region.visit(minX, minZ, maxX, maxZ, visitor); - return true; - }); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldHeightmap.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldHeightmap.java deleted file mode 100644 index 2ecdb4c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldHeightmap.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.heightmap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.module.Blender; -import com.terraforged.core.settings.GeneratorSettings; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.continent.ContinentLerper2; -import com.terraforged.core.world.continent.ContinentLerper3; -import com.terraforged.core.world.continent.ContinentModule; -import com.terraforged.core.world.rivermap.RiverMap; -import com.terraforged.core.world.rivermap.RiverRegionList; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import com.terraforged.core.world.terrain.Terrains; -import com.terraforged.core.world.terrain.provider.TerrainProvider; -import com.terraforged.core.world.terrain.region.RegionLerper; -import com.terraforged.core.world.terrain.region.RegionModule; -import com.terraforged.core.world.terrain.region.RegionSelector; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.func.EdgeFunc; -import me.dags.noise.func.Interpolation; - -public class WorldHeightmap implements Heightmap { - - private static final float DEEP_OCEAN_VALUE = 0.2F; - private static final float OCEAN_VALUE = 0.3F; - private static final float BEACH_VALUE = 0.34F; - private static final float COAST_VALUE = 0.4F; - private static final float INLAND_VALUE = 0.6F; - - private final Levels levels; - private final Terrains terrain; - private final Settings settings; - - private final Populator continentModule; - private final Populator regionModule; - - private final Climate climate; - private final Populator root; - private final RiverMap riverMap; - private final TerrainProvider terrainProvider; - - public WorldHeightmap(GeneratorContext context) { - context = context.copy(); - - this.levels = context.levels; - this.terrain = context.terrain; - this.settings = context.settings; - this.climate = new Climate(context); - - Seed seed = context.seed; - Levels levels = context.levels; - GeneratorSettings genSettings = context.settings.generator; - - Seed regionSeed = seed.nextSeed(); - Seed regionWarp = seed.nextSeed(); - - int regionWarpScale = 400; - int regionWarpStrength = 200; - RegionConfig regionConfig = new RegionConfig( - regionSeed.get(), - context.settings.generator.land.regionSize, - Source.simplex(regionWarp.next(), regionWarpScale, 1), - Source.simplex(regionWarp.next(), regionWarpScale, 1), - regionWarpStrength - ); - - regionModule = new RegionModule(regionConfig); - - // controls where mountain chains form in the world - Module mountainShapeBase = Source.cellEdge(seed.next(), genSettings.land.mountainScale, EdgeFunc.DISTANCE_2_ADD) - .add(Source.cubic(seed.next(), genSettings.land.mountainScale, 1).scale(-0.05)); - - // sharpens the transition to create steeper mountains - Module mountainShape = mountainShapeBase - .curve(Interpolation.CURVE3) - .clamp(0, 0.9) - .map(0, 1); - - terrainProvider = context.terrainFactory.create(context, regionConfig, this); - - // the voronoi controlled terrain regions - Populator terrainRegions = new RegionSelector(terrainProvider.getPopulators()); - // the terrain type at region edges - Populator terrainRegionBorders = new TerrainPopulator(terrainProvider.getLandforms().plains(seed), context.terrain.steppe); - - // transitions between the unique terrain regions and the common border terrain - Populator terrain = new RegionLerper(terrainRegionBorders, terrainRegions); - - // mountain populator - Populator mountains = register(terrainProvider.getLandforms().mountains(seed), context.terrain.mountains); - - // controls what's ocean and what's land - continentModule = new ContinentModule(seed, settings.generator); - - // blends between normal terrain and mountain chains - Populator land = new Blender( - mountainShape, - terrain, - mountains, - 0.1F, - 0.9F, - 0.6F - ); - - // uses the continent noise to blend between deep ocean, to ocean, to coast - ContinentLerper3 oceans = new ContinentLerper3( - climate, - register(terrainProvider.getLandforms().deepOcean(seed.next()), context.terrain.deepOcean), - register(Source.constant(levels.water(-7)), context.terrain.ocean), - register(Source.constant(levels.water), context.terrain.coast), - DEEP_OCEAN_VALUE, // below == deep, above == transition to shallow - OCEAN_VALUE, // below == transition to deep, above == transition to coast - COAST_VALUE // below == transition to shallow, above == coast - ); - - // blends between the ocean/coast terrain and land terrains - root = new ContinentLerper2( - oceans, - land, - OCEAN_VALUE, // below == pure ocean - INLAND_VALUE, // above == pure land - COAST_VALUE, // split point - COAST_VALUE - 0.05F - ); - - riverMap = new RiverMap(this, context); - } - - @Override - public void visit(Cell cell, float x, float z) { - continentModule.apply(cell, x, z); - regionModule.apply(cell, x, z); - root.apply(cell, x, z); - } - - @Override - public void apply(Cell cell, float x, float z) { - applyBase(cell, x, z); - applyRivers(cell, x, z, riverMap.getRivers((int) x, (int) z)); - applyClimate(cell, x, z); - } - - @Override - public void applyBase(Cell cell, float x, float z) { - // initial type - cell.tag = terrain.steppe; - // basic shapes - continentModule.apply(cell, x, z); - regionModule.apply(cell, x, z); - // apply actual heightmap - root.apply(cell, x, z); - } - - @Override - public void applyRivers(Cell cell, float x, float z, RiverRegionList rivers) { - rivers.apply(cell, x, z); - } - - @Override - public void applyClimate(Cell cell, float x, float z) { - // apply climate data - if (cell.value <= levels.water) { - climate.apply(cell, x, z, false); - if (cell.tag == terrain.coast) { - cell.tag = terrain.ocean; - } - } else { - int range = settings.generator.biomeEdgeNoise.strength; - float dx = climate.getOffsetX(x, z, range); - float dz = climate.getOffsetZ(x, z, range); - float px = x + dx; - float pz = z + dz; - tag(cell, px, pz); - climate.apply(cell, px, pz, false); - climate.apply(cell, x, z, true); - } - } - - @Override - public void tag(Cell cell, float x, float z) { - continentModule.apply(cell, x, z); - regionModule.apply(cell, x, z); - root.tag(cell, x, z); - } - - public Climate getClimate() { - return climate; - } - - @Override - public RiverMap getRiverMap() { - return riverMap; - } - - public Populator getPopulator(Terrain terrain) { - return terrainProvider.getPopulator(terrain); - } - - private TerrainPopulator register(Module module, Terrain terrain) { - TerrainPopulator populator = new TerrainPopulator(module, terrain); - terrainProvider.registerMixable(populator); - return populator; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java deleted file mode 100644 index 5d629d7..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.terraforged.core.world.heightmap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.WorldDecorators; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.decorator.Decorator; -import com.terraforged.core.world.terrain.Terrain; - -public class WorldLookup { - - private final float waterLevel; - private final float beachLevel; - private final Heightmap heightmap; - private final WorldDecorators decorators; - private final GeneratorContext context; - - public WorldLookup(WorldGeneratorFactory factory, GeneratorContext context) { - this.context = context; - this.heightmap = factory.getHeightmap(); - this.decorators = factory.getDecorators(); - this.waterLevel = context.levels.water; - this.beachLevel = context.levels.water(5); - } - - public Cell getCell(int x, int z) { - Cell cell = new Cell<>(); - applyCell(cell, x, z); - return cell; - } - - public void applyCell(Cell cell, int x, int z) { - heightmap.apply(cell, x, z); - - // approximation - actual beaches depend on steepness but that's too expensive to calculate - if (cell.tag == context.terrain.coast && cell.value > waterLevel && cell.value <= beachLevel) { - cell.tag = context.terrain.beach; - } - - for (Decorator decorator : decorators.getDecorators()) { - if (decorator.apply(cell, x, z)) { - break; - } - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/PosGenerator.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/PosGenerator.java deleted file mode 100644 index fba5b62..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/PosGenerator.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.rivermap.river.RiverNode; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.domain.Domain; -import me.dags.noise.util.Vec2i; - -import java.util.Random; - -/** - * Generates random positions within (length / 4) of one of the 4 corners of a region. - * The first position generated will be near any of the four corners - * The second position generated will be near any of the 3 remaining corners to ensure a reasonable distance to the first - */ -public class PosGenerator { - - private final int size; - private final int quadSize; - private final Vec2i[] quads = new Vec2i[4]; - - private final int padding; - private final Domain domain; - private final Cell lookup; - private final Heightmap heightmap; - - private int i; - private int dx; - private int dz; - - public PosGenerator(Heightmap heightmap, Domain domain, Cell lookup, int size, int padding) { - this.domain = domain; - this.lookup = lookup; - this.padding = padding; - this.heightmap = heightmap; - this.size = size; - this.quadSize = (size - (padding * 2)) / 4; - int x1 = 0; - int y1 = 0; - int x2 = 3 * quadSize; - int y2 = 3 * quadSize; - quads[index(0, 0)] = new Vec2i(x1, y1); - quads[index(1, 0)] = new Vec2i(x2, y1); - quads[index(0, 1)] = new Vec2i(x1, y2); - quads[index(1, 1)] = new Vec2i(x2, y2); - } - - private void nextSeed(Random random) { - int index = random.nextInt(4); - Vec2i vec = quads[index]; - i = index; - dx = padding + vec.x + random.nextInt(quadSize); - dz = padding + vec.y + random.nextInt(quadSize); - } - - private void nextPos(Random random) { - int steps = 1 + random.nextInt(3); - int index = (i + steps) & 3; - Vec2i vec = quads[index]; - i = index; - dx = padding + vec.x + random.nextInt(quadSize); - dz = padding + vec.y + random.nextInt(quadSize); - } - - public RiverNode next(int x, int z, Random random, int attempts) { - for (int i = 0; i < attempts; i++) { - nextSeed(random); - int px = x + dx; - int pz = z + dz; - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - RiverNode.Type type1 = RiverNode.getType(value1); - RiverNode.Type type2 = RiverNode.getType(value2); - if (type1 == type2 && type1 != RiverNode.Type.NONE) { - if (type1 == RiverNode.Type.END) { - return new RiverNode(wx, wz, type1); - } - return new RiverNode(px, pz, type1); - } - } - return null; - } - - public RiverNode nextFrom(int x, int z, Random random, int attempts, RiverNode point, int mindDist2) { - for (int i = 0; i < attempts; i++) { - nextPos(random); - int px = x + dx; - int pz = z + dz; - if (dist2(px, pz, point.x, point.z) < mindDist2) { - continue; - } - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - RiverNode.Type type1 = RiverNode.getType(value1); - RiverNode.Type type2 = RiverNode.getType(value2); - if (type1 == type2 && type1 == point.type.opposite()) { - if (type1 == RiverNode.Type.END) { - return new RiverNode(wx, wz, type1); - } - return new RiverNode(px, pz, type1); - } - } - return null; - } - - public RiverNode nextRelaxed(int x, int z, Random random, int attempts) { - for (int i = 0; i < attempts; i++) { - int px = x + random.nextInt(size); - int pz = z + random.nextInt(size); - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - RiverNode.Type type1 = RiverNode.getType(value1); - RiverNode.Type type2 = RiverNode.getType(value2); - if (type1 == type2 && type1 != RiverNode.Type.NONE) { - if (type1 == RiverNode.Type.END) { - return new RiverNode(wx, wz, type1); - } - return new RiverNode(px, pz, type1); - } - } - return null; - } - - public RiverNode nextFromRelaxed(int x, int z, Random random, int attempts, RiverNode point, int mindDist2) { - for (int i = 0; i < attempts; i++) { - int px = x + random.nextInt(size); - int pz = z + random.nextInt(size); - if (dist2(px, pz, point.x, point.z) < mindDist2) { - continue; - } - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - RiverNode.Type type1 = RiverNode.getType(value1); - RiverNode.Type type2 = RiverNode.getType(value2); - if (type1 == type2 && type1 == point.type.opposite()) { - if (type1 == RiverNode.Type.END) { - return new RiverNode(wx, wz, type1); - } - return new RiverNode(px, pz, type1); - } - } - return null; - } - - public RiverNode nextType(int x, int z, Random random, int attempts, RiverNode.Type match) { - for (int i = 0; i < attempts; i++) { - nextSeed(random); - int px = x + dx; - int pz = z + dz; - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - RiverNode.Type type1 = RiverNode.getType(value1); - RiverNode.Type type2 = RiverNode.getType(value2); - if (type1 == type2 && type1 == match) { - return new RiverNode(px, pz, type1); - } - } - return null; - } - - public RiverNode nextMinHeight(int x, int z, Random random, int attempts, float minHeight) { - for (int i = 0; i < attempts; i++) { - nextPos(random); - int px = x + dx; - int pz = z + dz; - int wx = (int) domain.getX(px, pz); - int wz = (int) domain.getY(px, pz); - float value1 = getHeight(px, pz); - float value2 = getHeight(wx, wz); - if (value1 > minHeight && value2 > minHeight) { - return new RiverNode(px, pz, RiverNode.Type.START); - } - } - return null; - } - - public float getHeight(int x, int z) { - heightmap.visit(lookup, x, z); - return lookup.value; - } - - private static int index(int x, int z) { - return z * 2 + x; - } - - private static float dist2(int x1, int y1, int x2, int y2) { - float dx = x2 - x1; - float dy = y2 - y1; - return dx * dx + dy * dy; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMap.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMap.java deleted file mode 100644 index c79f54a..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMap.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.region.Region; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.util.concurrent.cache.Cache; -import com.terraforged.core.util.concurrent.cache.CacheEntry; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.rivermap.lake.LakeConfig; -import com.terraforged.core.world.rivermap.river.RiverConfig; -import com.terraforged.core.world.rivermap.river.RiverRegion; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.util.NoiseUtil; - -import java.util.concurrent.TimeUnit; - -public class RiverMap { - - private static final int QUAD_SIZE = (1 << RiverRegion.SCALE) / 2; - - private final Heightmap heightmap; - private final GeneratorContext context; - private final RiverMapConfig riverMapConfig; - private final Cache> cache; - private final ThreadPool threadPool = ThreadPool.getPool(); - - public RiverMap(Heightmap heightmap, GeneratorContext context) { - RiverConfig primary = RiverConfig.builder(context.levels) - .bankHeight(context.settings.rivers.primaryRivers.minBankHeight, context.settings.rivers.primaryRivers.maxBankHeight) - .bankWidth(context.settings.rivers.primaryRivers.bankWidth) - .bedWidth(context.settings.rivers.primaryRivers.bedWidth) - .bedDepth(context.settings.rivers.primaryRivers.bedDepth) - .fade(context.settings.rivers.primaryRivers.fade) - .length(2500) - .main(true) - .build(); - RiverConfig secondary = RiverConfig.builder(context.levels) - .bankHeight(context.settings.rivers.secondaryRiver.minBankHeight, context.settings.rivers.secondaryRiver.maxBankHeight) - .bankWidth(context.settings.rivers.secondaryRiver.bankWidth) - .bedWidth(context.settings.rivers.secondaryRiver.bedWidth) - .bedDepth(context.settings.rivers.secondaryRiver.bedDepth) - .fade(context.settings.rivers.secondaryRiver.fade) - .length(1000) - .build(); - RiverConfig tertiary = RiverConfig.builder(context.levels) - .bankHeight(context.settings.rivers.tertiaryRivers.minBankHeight, context.settings.rivers.tertiaryRivers.maxBankHeight) - .bankWidth(context.settings.rivers.tertiaryRivers.bankWidth) - .bedWidth(context.settings.rivers.tertiaryRivers.bedWidth) - .bedDepth(context.settings.rivers.tertiaryRivers.bedDepth) - .fade(context.settings.rivers.tertiaryRivers.fade) - .length(500) - .build(); - LakeConfig lakes = LakeConfig.of(context.settings.rivers.lake, context.levels); - - this.heightmap = heightmap; - this.context = context; - this.riverMapConfig = new RiverMapConfig(context.settings.rivers.riverFrequency, primary, secondary, tertiary, lakes); - this.cache = new Cache<>(3, 1, TimeUnit.MINUTES); - } - - public RiverRegionList getRivers(Region region) { - RiverRegionList rivers = new RiverRegionList(); - getRivers(region.getBlockX(), region.getBlockZ(), rivers); - return rivers; - } - - public RiverRegionList getRivers(int blockX, int blockZ) { - RiverRegionList rivers = new RiverRegionList(); - getRivers(blockX, blockZ, rivers); - return rivers; - } - - public void getRivers(Region region, RiverRegionList rivers) { - getRivers(region.getBlockX(), region.getBlockZ(), rivers); - } - - public void getRivers(int blockX, int blockZ, RiverRegionList rivers) { - int rx = RiverRegion.blockToRegion(blockX); - int rz = RiverRegion.blockToRegion(blockZ); - - // check which quarter of the region pos (x,y) is in & get the neighbouring regions' relative coords - int qx = blockX < RiverRegion.regionToBlock(rx) + QUAD_SIZE ? -1 : 1; - int qz = blockZ < RiverRegion.regionToBlock(rz) + QUAD_SIZE ? -1 : 1; - - // relative positions of neighbouring regions - int minX = Math.min(0, qx); - int minZ = Math.min(0, qz); - int maxX = Math.max(0, qx); - int maxZ = Math.max(0, qz); - - rivers.reset(); - for (int dz = minZ; dz <= maxZ; dz++) { - for (int dx = minX; dx <= maxX; dx++) { - rivers.add(getRegion(rx + dx, rz + dz)); - } - } - } - - public void apply(Cell cell, float x, float z) { - RiverRegionList rivers = new RiverRegionList(); - getRivers((int) x, (int) z, rivers); - rivers.apply(cell, x, z); - } - - private CacheEntry getRegion(int rx, int rz) { - long id = NoiseUtil.seed(rx, rz); - return cache.computeIfAbsent(id, l -> generateRegion(rx, rz)); - } - - private CacheEntry generateRegion(int rx, int rz) { - return CacheEntry.supplyAsync(() -> new RiverRegion(rx, rz, heightmap, context, riverMapConfig), threadPool); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMapConfig.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMapConfig.java deleted file mode 100644 index 957fedc..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverMapConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.terraforged.core.world.rivermap; - -import com.terraforged.core.world.rivermap.lake.LakeConfig; -import com.terraforged.core.world.rivermap.river.RiverConfig; - -public class RiverMapConfig { - - public final float frequency; - public final RiverConfig primary; - public final RiverConfig secondary; - public final RiverConfig tertiary; - public final LakeConfig lakes; - - public RiverMapConfig(float frequency, RiverConfig primary, RiverConfig secondary, RiverConfig tertiary, LakeConfig lakes) { - this.frequency = frequency; - this.primary = primary; - this.secondary = secondary; - this.tertiary = tertiary; - this.lakes = lakes; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverRegionList.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverRegionList.java deleted file mode 100644 index 9cdbc1c..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/RiverRegionList.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.terraforged.core.world.rivermap; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.concurrent.cache.CacheEntry; -import com.terraforged.core.world.rivermap.river.RiverRegion; -import com.terraforged.core.world.terrain.Terrain; - -import java.util.Arrays; - -public class RiverRegionList { - - private int index = 0; - private final CacheEntry[] regions = new CacheEntry[4]; - - protected void add(CacheEntry entry) { - if (index < regions.length) { - regions[index] = entry; - index++; - } - } - - protected void reset() { - index = 0; - } - - public void clear() { - Arrays.fill(regions, null); - } - - public void apply(Cell cell, float x, float z) { - for (CacheEntry entry : regions) { - entry.get().apply(cell, x, z); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/Lake.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/Lake.java deleted file mode 100644 index c41b639..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/Lake.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.lake; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.rivermap.river.River; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import com.terraforged.core.world.terrain.Terrains; -import me.dags.noise.Source; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; - -public class Lake extends TerrainPopulator { - - private static final int VALLEY_2 = River.VALLEY_WIDTH * River.VALLEY_WIDTH; - - private final float lakeDistance2; - private final float valleyDistance2; - private final float bankAlphaMin; - private final float bankAlphaMax; - private final float bankAlphaRange; - private final Vec2f center; - private final LakeConfig config; - private final Terrains terrains; - - public Lake(Vec2f center, float radius, LakeConfig config, Terrains terrains) { - super(Source.ZERO, terrains.lake); - this.center = center; - this.config = config; - this.bankAlphaMin = config.bankMin; - this.bankAlphaMax = Math.min(1, bankAlphaMin + 0.275F); - this.bankAlphaRange = bankAlphaMax - bankAlphaMin; - this.lakeDistance2 = radius * radius; - this.valleyDistance2 = VALLEY_2 - lakeDistance2; - this.terrains = terrains; - } - - @Override - public void apply(Cell cell, float x, float z) { - float distance2 = getDistance2(x, z); - if (distance2 > VALLEY_2) { - return; - } - - float bankHeight = getBankHeight(cell); - if (distance2 > lakeDistance2) { - if (cell.value < bankHeight) { - return; - } - float valleyAlpha = 1F - ((distance2 - lakeDistance2) / valleyDistance2); - cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha); - return; - } - - cell.value = Math.min(bankHeight, cell.value); - - if (distance2 < lakeDistance2) { - float depthAlpha = 1F - (distance2 / lakeDistance2); - float lakeDepth = Math.min(cell.value, config.depth); - cell.value = NoiseUtil.lerp(cell.value, lakeDepth, depthAlpha); - cell.tag = terrains.lake; - } - } - - @Override - public void tag(Cell cell, float x, float z) { - cell.tag = terrains.lake; - } - - private float getDistance2(float x, float z) { - float dx = center.x - x; - float dz = center.y - z; - return (dx * dx + dz * dz); - } - - private float getBankHeight(Cell cell) { - // scale bank height based on elevation of the terrain (higher terrain == taller banks) - float bankHeightAlpha = NoiseUtil.map(cell.value, bankAlphaMin, bankAlphaMax, bankAlphaRange); - // lerp between the min and max heights - return NoiseUtil.lerp(config.bankMin, config.bankMax, bankHeightAlpha); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/LakeConfig.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/LakeConfig.java deleted file mode 100644 index 49c7f82..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/lake/LakeConfig.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.lake; - -import com.terraforged.core.settings.RiverSettings; -import com.terraforged.core.world.heightmap.Levels; - -public class LakeConfig { - - public final float depth; - public final float chance; - public final float sizeMin; - public final float sizeMax; - public final float bankMin; - public final float bankMax; - public final float distanceMin; - public final float distanceMax; - - private LakeConfig(Builder builder) { - depth = builder.depth; - chance = builder.chance; - sizeMin = builder.sizeMin; - sizeMax = builder.sizeMax; - bankMin = builder.bankMin; - bankMax = builder.bankMax; - distanceMin = builder.distanceMin; - distanceMax = builder.distanceMax; - } - - public static LakeConfig of(RiverSettings.Lake settings, Levels levels) { - Builder builder = new Builder(); - builder.chance = settings.chance; - builder.sizeMin = settings.sizeMin; - builder.sizeMax = settings.sizeMax; - builder.depth = levels.water(-settings.depth); - builder.distanceMin = settings.minStartDistance; - builder.distanceMax = settings.maxStartDistance; - builder.bankMin = levels.water(settings.minBankHeight); - builder.bankMax = levels.water(settings.maxBankHeight); - return new LakeConfig(builder); - } - - public static class Builder { - public float chance; - public float depth = 10; - public float sizeMin = 30; - public float sizeMax = 100; - public float bankMin = 1; - public float bankMax = 8; - public float distanceMin = 0.025F; - public float distanceMax = 0.05F; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/River.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/River.java deleted file mode 100644 index 6ff08c9..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/River.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.river; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import com.terraforged.core.world.terrain.Terrains; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.source.Line; -import me.dags.noise.util.NoiseUtil; - -public class River extends TerrainPopulator { - - public static final int VALLEY_WIDTH = 275; - protected static final float DEPTH_FADE_STRENGTH = 0.5F; - - public final boolean main; - private final boolean connecting; - - private final float bedHeight; - - private final float minBankHeight; - private final float maxBankHeight; - private final float bankAlphaMin; - private final float bankAlphaMax; - private final float bankAlphaRange; - private final Module bankVariance; - - private final Line bed; - private final Line banks; - private final Line valley; - public final RiverConfig config; - public final RiverBounds bounds; - - private final Terrains terrains; - - private final float depthFadeBias; - - public River(RiverBounds bounds, RiverConfig config, Terrains terrains, double fadeIn, double fadeOut) { - this(bounds, config, terrains, fadeIn, fadeOut, false); - } - - public River(RiverBounds bounds, RiverConfig config, Terrains terrains, double fadeIn, double fadeOut, boolean connecting) { - super(Source.ZERO, terrains.river); - Module in = Source.constant(fadeIn); - Module out = Source.constant(fadeOut); - Module bedWidth = Source.constant(config.bedWidth * config.bedWidth); - Module bankWidth = Source.constant(config.bankWidth * config.bankWidth); - Module valleyWidth = Source.constant(VALLEY_WIDTH * VALLEY_WIDTH); - this.bounds = bounds; - this.config = config; - this.main = config.main; - this.terrains = terrains; - this.connecting = connecting; - this.bedHeight = config.bedHeight; - this.minBankHeight = config.minBankHeight; - this.maxBankHeight = config.maxBankHeight; - this.bankAlphaMin = minBankHeight; - this.bankAlphaMax = Math.min(1, minBankHeight + 0.35F); - this.bankAlphaRange = bankAlphaMax - bankAlphaMin; - this.bankVariance = Source.perlin(1234, 150, 1); - this.depthFadeBias = 1 - DEPTH_FADE_STRENGTH; - this.bed = Source.line(bounds.x1(), bounds.y1(), bounds.x2(), bounds.y2(), bedWidth, in, out, 0.1F); - this.banks = Source.line(bounds.x1(), bounds.y1(), bounds.x2(), bounds.y2(), bankWidth, in, out, 0.1F); - this.valley = Source.line(bounds.x1(), bounds.y1(), bounds.x2(), bounds.y2(), valleyWidth, Source.ZERO, Source.ZERO, 0.33F); - } - - @Override - public void apply(Cell cell, float x, float z) { - if (cell.value <= bedHeight) { - return; - } - carve(cell, x, z); - } - - @Override - public void tag(Cell cell, float x, float z) { - if (!terrains.overridesRiver(cell.tag)) { - cell.tag = terrains.river; - } - } - - private void carve(Cell cell, float x, float z) { - float valleyAlpha = valley.getValue(x, z); - if (valleyAlpha == 0) { - return; - } - - // riverMask decreases the closer to the river the position gets - cell.riverMask *= (1 - valleyAlpha); - - float bankHeight = getBankHeight(cell, x, z); - if (!carveValley(cell, valleyAlpha, bankHeight)) { - return; - } - - // is a branching river and x,z is past the connecting point - if (connecting && banks.clipEnd(x, z)) { - return; - } - - float widthModifier = banks.getWidthModifier(x, z); - float banksAlpha = banks.getValue(x, z, widthModifier); - if (banksAlpha == 0) { - return; - } - - float bedHeight = getBedHeight(bankHeight, widthModifier); - if (!carveBanks(cell, banksAlpha, bedHeight)) { - return; - } - - float bedAlpha = bed.getValue(x, z); - if (bedAlpha == 0) { - return; - } - - carveBed(cell, bedHeight); - } - - private float getBankHeight(Cell cell, float x, float z) { - // scale bank height based on elevation of the terrain (higher terrain == taller banks) - float bankHeightAlpha = NoiseUtil.map(cell.value, bankAlphaMin, bankAlphaMax, bankAlphaRange); - // use perlin noise to add a little extra variance to the bank height - float bankHeightVariance = bankVariance.getValue(x, z); - // lerp between the min and max heights - return NoiseUtil.lerp(minBankHeight, maxBankHeight, bankHeightAlpha * bankHeightVariance); - } - - private float getBedHeight(float bankHeight, float widthModifier) { - // scale depth of river by with it's width (wider == deeper) - // depthAlpha changes the river depth up ${DEPTH_FADE_STRENGTH} % - float depthAlpha = depthFadeBias + (DEPTH_FADE_STRENGTH * widthModifier); - return NoiseUtil.lerp(bankHeight, this.bedHeight, depthAlpha); - } - - private boolean carveValley(Cell cell, float valleyAlpha, float bankHeight) { - // lerp the position's height to the riverbank height - if (cell.value > bankHeight) { - cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha); - } - return true; - } - - private boolean carveBanks(Cell cell, float banksAlpha, float bedHeight) { - // lerp the position's height to the riverbed height (ie the riverbank slopes) - if (cell.value > bedHeight) { - cell.value = NoiseUtil.lerp(cell.value, bedHeight, banksAlpha); - tag(cell, terrains.riverBanks); - return true; - } - return false; - } - - private void carveBed(Cell cell, float bedHeight) { - if (cell.value > bedHeight) { - cell.value = bedHeight; - } - tag(cell, terrains.river); - } - - - private void tag(Cell cell, Terrain tag) { - if (!terrains.overridesRiver(cell.tag)) { - cell.tag = tag; - } - } - - public static boolean validStart(float value) { - return value > (70F / 256F); - } - - public static boolean validEnd(float value) { - return value < (60F / 256F); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverBounds.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverBounds.java deleted file mode 100644 index 9b78bc7..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverBounds.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.river; - -import me.dags.noise.util.Vec2f; - -public class RiverBounds { - - private final int x1; - private final int y1; - private final int x2; - private final int y2; - private final int minX; - private final int minY; - private final int maxX; - private final int maxY; - - public RiverBounds(int x1, int y1, int x2, int y2, int radius) { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - this.minX = Math.min(x1, x2) - radius; - this.minY = Math.min(y1, y2) - radius; - this.maxX = Math.max(x1, x2) + radius; - this.maxY = Math.max(y1, y2) + radius; - } - - public int x1() { - return x1; - } - - public int y1() { - return y1; - } - - public int x2() { - return x2; - } - - public int y2() { - return y2; - } - - public boolean overlaps(RiverBounds other) { - if (minX > other.maxX || maxX < other.minX) { - return false; - } - if (minY > other.maxY || maxY < other.minY) { - return false; - } - return true; - } - - public Vec2f pos(float distance) { - int dx = x2() - x1(); - int dy = y2() - y1(); - return new Vec2f(x1() + dx * distance, y1() + dy * distance); - } - - public static RiverBounds fromNodes(RiverNode p1, RiverNode p2) { - if (p1.type == RiverNode.Type.START) { - return new RiverBounds(p1.x, p1.z, p2.x, p2.z, 300); - } else { - return new RiverBounds(p2.x, p2.z, p1.x, p1.z, 300); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverConfig.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverConfig.java deleted file mode 100644 index 3f9b70e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverConfig.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.river; - -import com.terraforged.core.world.heightmap.Levels; -import me.dags.noise.util.NoiseUtil; - -public class RiverConfig { - - public final boolean main; - public final int bedWidth; - public final int bankWidth; - public final float bedHeight; - public final float minBankHeight; - public final float maxBankHeight; - public final int length2; - public final double fade; - - private RiverConfig(Builder builder) { - main = builder.main; - bedWidth = builder.bedWidth; - bankWidth = builder.bankWidth; - bedHeight = builder.levels.water(-builder.bedDepth); - minBankHeight = builder.levels.water(builder.minBankHeight); - maxBankHeight = builder.levels.water(builder.maxBankHeight); - length2 = builder.length * builder.length; - fade = builder.fade; - } - - private RiverConfig(boolean main, int bedWidth, int bankWidth, float bedHeight, float minBankHeight, float maxBankHeight, int length2, double fade) { - this.main = main; - this.bedWidth = bedWidth; - this.bankWidth = bankWidth; - this.bedHeight = bedHeight; - this.minBankHeight = minBankHeight; - this.maxBankHeight = maxBankHeight; - this.length2 = length2; - this.fade = fade; - } - - public RiverConfig createFork(float connectWidth) { - if (bankWidth < connectWidth) { - return this; - } - - float scale = bankWidth / connectWidth; - return new RiverConfig( - false, - NoiseUtil.round(bedWidth / scale), - NoiseUtil.round(bankWidth / scale), - bedHeight, - minBankHeight, - maxBankHeight, - length2, - fade - ); - } - - public static Builder builder(Levels levels) { - return new Builder(levels); - } - - public static class Builder { - - private boolean main = false; - private int bedWidth = 4; - private int bankWidth = 15; - private int bedDepth = 5; - private int maxBankHeight = 1; - private int minBankHeight = 1; - private int length = 1000; - private double fade = 0.2; - private final Levels levels; - - private Builder(Levels levels) { - this.levels = levels; - } - - public Builder main(boolean value) { - this.main = value; - return this; - } - - public Builder bedWidth(int value) { - this.bedWidth = value; - return this; - } - - public Builder bankWidth(int value) { - this.bankWidth = value; - return this; - } - - public Builder bedDepth(int depth) { - this.bedDepth = depth; - return this; - } - - public Builder bankHeight(int min, int max) { - this.minBankHeight = Math.min(min, max); - this.maxBankHeight = Math.max(min, max); - return this; - } - - public Builder length(int value) { - this.length = value; - return this; - } - - public Builder fade(double value) { - this.fade = value; - return this; - } - - public RiverConfig build() { - return new RiverConfig(this); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverNode.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverNode.java deleted file mode 100644 index 52b3952..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverNode.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.river; - -public class RiverNode { - - public final int x; - public final int z; - public final Type type; - - public RiverNode(int x, int z, Type type) { - this.x = x; - this.z = z; - this.type = type; - } - - public static Type getType(float value) { - if (River.validStart(value)) { - return Type.START; - } - if (River.validEnd(value)) { - return Type.END; - } - return Type.NONE; - } - - public enum Type { - NONE { - @Override - public Type opposite() { - return this; - } - }, - START { - @Override - public Type opposite() { - return END; - } - }, - END { - @Override - public Type opposite() { - return START; - } - }, - ; - - public abstract Type opposite(); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverRegion.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverRegion.java deleted file mode 100644 index 585a705..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/rivermap/river/RiverRegion.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.rivermap.river; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.concurrent.ObjectPool; -import com.terraforged.core.util.concurrent.cache.ExpiringEntry; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.rivermap.PosGenerator; -import com.terraforged.core.world.rivermap.RiverMapConfig; -import com.terraforged.core.world.rivermap.lake.Lake; -import com.terraforged.core.world.rivermap.lake.LakeConfig; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; -import me.dags.noise.domain.Domain; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; -import me.dags.noise.util.Vec2i; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -public class RiverRegion implements ExpiringEntry { - - public static final int SCALE = 12; - private static final double MIN_FORK_ANGLE = 20D; - private static final double MAX_FORK_ANGLE = 60D; - private static final long EXPIRE_TIME = TimeUnit.SECONDS.toMillis(60); - - private final Domain domain; - private final Terrains terrains; - private final LakeConfig lake; - private final RiverConfig primary; - private final RiverConfig secondary; - private final RiverConfig tertiary; - - private final List rivers; - private final List lakes = new LinkedList<>(); - - private final int primaryLimit; - private final int secondaryLimit; - private final int secondaryRelaxedLimit; - private final int forkLimit; - private final int tertiaryLimit; - private final int primaryAttempts; - private final int secondaryAttempts; - private final int secondaryRelaxedAttempts; - private final int forkAttempts; - private final int tertiaryAttempts; - - private final long timestamp = System.currentTimeMillis() + EXPIRE_TIME; - - public RiverRegion(int regionX, int regionZ, Heightmap heightmap, GeneratorContext context, RiverMapConfig riverMapConfig) { - int seed = new Random(NoiseUtil.seed(regionX, regionZ)).nextInt(); - this.lake = riverMapConfig.lakes; - this.primary = riverMapConfig.primary; - this.secondary = riverMapConfig.secondary; - this.tertiary = riverMapConfig.tertiary; - this.terrains = context.terrain; - this.domain = Domain.warp(seed, 400, 1, 400) - .add(Domain.warp(seed + 1, 80, 1, 35)); - - this.primaryLimit = NoiseUtil.round(10 * riverMapConfig.frequency); - this.secondaryLimit = NoiseUtil.round(20 * riverMapConfig.frequency); - this.secondaryRelaxedLimit = NoiseUtil.round(30 * riverMapConfig.frequency); - this.forkLimit = NoiseUtil.round(40 * riverMapConfig.frequency); - this.tertiaryLimit = NoiseUtil.round(50 * riverMapConfig.frequency); - - this.primaryAttempts = NoiseUtil.round(100 * riverMapConfig.frequency); - this.secondaryAttempts = NoiseUtil.round(100 * riverMapConfig.frequency); - this.secondaryRelaxedAttempts = NoiseUtil.round(50 * riverMapConfig.frequency); - this.forkAttempts = NoiseUtil.round(75 * riverMapConfig.frequency); - this.tertiaryAttempts = NoiseUtil.round(50 * riverMapConfig.frequency); - - try (ObjectPool.Item> cell = Cell.pooled()) { - PosGenerator pos = new PosGenerator(heightmap, domain, cell.getValue(),1 << SCALE, River.VALLEY_WIDTH); - this.rivers = generate(regionX, regionZ, pos); - } - } - - @Override - public long getTimestamp() { - return timestamp; - } - - public void apply(Cell cell, float x, float z) { - float px = domain.getX(x, z); - float pz = domain.getY(x, z); - for (River river : rivers) { - river.apply(cell, px, pz); - } - for (Lake lake : lakes) { - lake.apply(cell, px, pz); - } - } - - private List generate(int regionX, int regionZ, PosGenerator pos) { - int x = regionToBlock(regionX); - int z = regionToBlock(regionZ); - long regionSeed = NoiseUtil.seed(regionX, regionZ); - - Random random = new Random(regionSeed); - List rivers = new LinkedList<>(); - - for (int i = 0; rivers.size() < primaryLimit && i < primaryAttempts; i++) { - generateRiver(x, z, pos, primary, random, rivers); - } - - for (int i = 0; rivers.size() < secondaryLimit && i < secondaryAttempts; i++) { - generateRiver(x, z, pos, secondary, random, rivers); - } - - for (int i = 0; rivers.size() < secondaryRelaxedLimit && i < secondaryRelaxedAttempts; i++) { - generateRiverRelaxed(x, z, pos, secondary, random, rivers); - } - - for (int i = 0; rivers.size() < forkLimit && i < forkAttempts; i++) { - generateRiverFork(x, z, pos, tertiary, random, rivers); - } - - for (int i = 0; rivers.size() < tertiaryLimit && i < tertiaryAttempts; i++) { - generateRiver(x, z, pos, tertiary, random, rivers); - } - - Collections.reverse(rivers); - - return rivers; - } - - /** - * Attempts to generate a line that starts inland and reaches the ocean - */ - private boolean generateRiver(int x, int z, PosGenerator pos, RiverConfig config, Random random, List rivers) { - // generate either a river start or end node - RiverNode p1 = pos.next(x, z, random, 50); - if (p1 == null) { - return false; - } - - // generate a node with a min distance from p1 and that has the opposite node type to p1 - RiverNode p2 = pos.nextFrom(x, z, random,50, p1, config.length2); - if (p2 == null) { - return false; - } - - // avoid collisions with existing rivers - RiverBounds bounds = RiverBounds.fromNodes(p1, p2); - for (River river : rivers) { - if (bounds.overlaps(river.bounds)) { - return false; - } - } - - generateLake(bounds, random); - - return rivers.add(new River(bounds, config, terrains, config.fade, 0)); - } - - /** - * Attempts to generate an inland position (p1), finds the nearest river (AB) to it, and tries to connect - * a line from p1 to some position along AB - */ - private boolean generateRiverFork(int x, int z, PosGenerator pos, RiverConfig config, Random random, List rivers) { - // generate a river start node - RiverNode p1 = pos.nextType(x, z, random, 50, RiverNode.Type.START); - if (p1 == null) { - return false; - } - - // find closest river - River closest = null; - float startDist2 = Integer.MAX_VALUE; - for (River river : rivers) { - float d2 = dist2(p1.x, p1.z, river.bounds.x1(), river.bounds.y1()); - if (d2 < startDist2) { - startDist2 = d2; - closest = river; - } - } - - // no close rivers - if (closest == null) { - return false; - } - - // connection should occur no less than 20% along the river length and no greater than 40% - float distance = 0.3F + (random.nextFloat() * 0.3F); - Vec2i fork = closest.bounds.pos(distance).toInt(); - - // connection should not occur in the ocean - float height = pos.getHeight(fork.x, fork.y); - RiverNode.Type type = RiverNode.getType(height); - if (type == RiverNode.Type.END) { - return false; - } - - // calc angle between vector a (AB) & b (CB) - // A - existing river's start - // B - connection point - // C - new river's start - int ax = fork.x - closest.bounds.x1(); - int az = fork.y - closest.bounds.y1(); - int bx = fork.x - p1.x; - int bz = fork.y - p1.z; - - // radians = arccos(AB.BC / |AB||BC|) - int dotAB = ax * bx + az * bz; - double lenA = Math.sqrt(ax * ax + az * az); - double lenB = Math.sqrt(bx * bx + bz * bz); - double radians = Math.acos(dotAB / (lenA * lenB)); - double angle = Math.toDegrees(radians); - if (angle < MIN_FORK_ANGLE || angle > MAX_FORK_ANGLE) { - return false; - } - - RiverBounds bounds = new RiverBounds(p1.x, p1.z, fork.x, fork.y, 300); - // check that the new river does not clash/overlap any other nearby rivers - for (River river : rivers) { - if (river == closest) { - continue; - } - if (river.bounds.overlaps(bounds)) { - return false; - } - } - - generateLake(bounds, random); - - // scale the connecting river's width down so that it's narrower than the one it's connecting to - float forkWidth = closest.config.bankWidth * distance * 0.6F; - RiverConfig forkConfig = config.createFork(forkWidth); - - return rivers.add(new River(bounds, forkConfig, terrains, forkConfig.fade, 0, true)); - } - - private boolean generateRiverRelaxed(int x, int z, PosGenerator pos, RiverConfig config, Random random, List rivers) { - // generate either a river start or end node - RiverNode p1 = pos.nextRelaxed(x, z, random, 50); - if (p1 == null) { - return false; - } - - // generate a node with a min distance from p1 and that has the opposite node type to p1 - RiverNode p2 = pos.nextFromRelaxed(x, z, random,50, p1, config.length2); - if (p2 == null) { - return false; - } - - // avoid collisions with existing rivers - RiverBounds bounds = RiverBounds.fromNodes(p1, p2); - for (River river : rivers) { - if (bounds.overlaps(river.bounds)) { - return false; - } - } - - generateLake(bounds, random); - - return rivers.add(new River(bounds, config, terrains, config.fade, 0)); - } - - private void generateLake(RiverBounds bounds, Random random) { - if (random.nextFloat() < lake.chance) { - float size = lake.sizeMin + (random.nextFloat() * lake.sizeMax); - float distance = lake.distanceMin + (random.nextFloat() * lake.distanceMax); - Vec2f center = bounds.pos(distance); - lakes.add(new Lake(center, size, lake, terrains)); - } - } - - private static float dist2(float x1, float y1, float x2, float y2) { - float dx = x2 - x1; - float dy = y2 - y1; - return dx * dx + dy * dy; - } - - public static int regionToBlock(int value) { - return value << SCALE; - } - - public static int blockToRegion(int value) { - return value >> SCALE; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/LandForms.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/LandForms.java deleted file mode 100644 index f3bb2fa..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/LandForms.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain; - -import com.terraforged.core.settings.TerrainSettings; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.heightmap.Levels; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.func.EdgeFunc; - -public class LandForms { - - private static final int PLAINS_H = 250; - private static final double PLAINS_V = 0.24; - - public static final int PLATEAU_H = 500; - public static final double PLATEAU_V = 0.475; - - private static final int HILLS_H = 500; - private static final double HILLS1_V = 0.6; - private static final double HILLS2_V = 0.55; - - private static final int MOUNTAINS_H = 410; - private static final double MOUNTAINS_V = 0.7; - - private static final int MOUNTAINS2_H = 400; - private static final double MOUNTAINS2_V = 0.645; - - private final TerrainSettings settings; - private final float terrainHorizontalScale; - private final float terrainVerticalScale; - private final float groundLevel; - private final float seaLevel; - - public LandForms(TerrainSettings settings, Levels levels) { - this.settings = settings; - terrainHorizontalScale = settings.globalHorizontalScale; - terrainVerticalScale = settings.globalVerticalScale; - groundLevel = levels.ground; - seaLevel = levels.water; - } - - public Module deepOcean(int seed) { - Module hills = Source.perlin(++seed, 150, 3) - .scale(seaLevel * 0.7) - .bias(Source.perlin(++seed, 200, 1).scale(seaLevel * 0.2F)); - - Module canyons = Source.perlin(++seed, 150, 4) - .powCurve(0.2) - .invert() - .scale(seaLevel * 0.7) - .bias(Source.perlin(++seed, 170, 1).scale(seaLevel * 0.15F)); - - return Source.perlin(++seed, 500, 1) - .blend(hills, canyons, 0.6, 0.65) - .warp(++seed, 50, 2, 50); - } - - public Module steppe(Seed seed) { - int scaleH = Math.round(PLAINS_H * terrainHorizontalScale * settings.steppe.horizontalScale); - - double erosionAmount = 0.45; - - Module erosion = Source.build(seed.next(), scaleH * 2, 3).lacunarity(3.75).perlin().alpha(erosionAmount); - Module warpX = Source.build(seed.next(), scaleH / 4, 3).lacunarity(3).perlin(); - Module warpY = Source.build(seed.next(), scaleH / 4, 3).lacunarity(3).perlin(); - Module module = Source.perlin(seed.next(), scaleH, 1) - .mult(erosion) - .warp(warpX, warpY, Source.constant(scaleH / 4F)) - .warp(seed.next(), 256, 1, 200); - - return settings.steppe.apply(groundLevel, 0.125 * terrainVerticalScale, module); - } - - public Module plains(Seed seed) { - int scaleH = Math.round(PLAINS_H * terrainHorizontalScale * settings.plains.horizontalScale); - - double erosionAmount = 0.45; - - Module erosion = Source.build(seed.next(), scaleH * 2, 3).lacunarity(3.75).perlin().alpha(erosionAmount); - Module warpX = Source.build(seed.next(), scaleH / 4, 3).lacunarity(3.5).perlin(); - Module warpY = Source.build(seed.next(), scaleH / 4, 3).lacunarity(3.5).perlin(); - - Module module = Source.perlin(seed.next(), scaleH, 1) - .mult(erosion) - .warp(warpX, warpY, Source.constant(scaleH / 4F)) - .warp(seed.next(), 256, 1, 256); - - return settings.plains.apply(groundLevel, PLAINS_V * terrainVerticalScale, module); - } - - public Module plateau(Seed seed) { - Module valley = Source.ridge(seed.next(), 500, 1).invert() - .warp(seed.next(), 100, 1, 150) - .warp(seed.next(), 20, 1, 15); - - Module top = Source.build(seed.next(), 150, 3).lacunarity(2.45).ridge() - .warp(seed.next(), 300, 1, 150) - .warp(seed.next(), 40, 2, 20) - .scale(0.15) - .mult(valley.clamp(0.02, 0.1).map(0, 1)); - - Module surface = Source.perlin(seed.next(), 20, 3).scale(0.05) - .warp(seed.next(), 40, 2, 20); - - return settings.plateau.apply(groundLevel, PLATEAU_V * terrainVerticalScale, - valley - .mult(Source.cubic(seed.next(), 500, 1).scale(0.6).bias(0.3)) - .add(top) - .terrace( - Source.perlin(seed.next(), 20, 1).scale(0.3).bias(0.2), - Source.perlin(seed.next(), 20, 2).scale(0.1).bias(0.2), - 4, - 0.4 - ) - .add(surface)); - } - - public Module hills1(Seed seed) { - return settings.hills.apply(groundLevel, HILLS1_V * terrainVerticalScale, Source.perlin(seed.next(), 200, 3) - .mult(Source.billow(seed.next(), 400, 3).alpha(0.5)) - .warp(seed.next(), 30, 3, 20) - .warp(seed.next(), 400, 3, 200)); - } - - public Module hills2(Seed seed) { - return settings.hills.apply(groundLevel, HILLS2_V * terrainVerticalScale, Source.cubic(seed.next(), 128, 2) - .mult(Source.perlin(seed.next(), 32, 4).alpha(0.075)) - .warp(seed.next(), 30, 3, 20) - .warp(seed.next(), 400, 3, 200) - .mult(Source.ridge(seed.next(), 512, 2).alpha(0.8))); - } - - public Module dales(Seed seed) { - Module hills1 = Source.build(seed.next(), 300, 4).gain(0.8).lacunarity(4).billow().powCurve(0.5).scale(0.75); - Module hills2 = Source.build(seed.next(), 350, 3).gain(0.8).lacunarity(4).billow().pow(1.25); - Module combined = Source.perlin(seed.next(), 400, 1).clamp(0.3, 0.6).map(0, 1).blend( - hills1, - hills2, - 0.4, - 0.75 - ); - Module hills = combined - .pow(1.125) - .warp(seed.next(), 300, 1, 100); - - return settings.dales.apply(groundLevel, 0.4, hills); - } - - public Module mountains(Seed seed) { - int scaleH = Math.round(MOUNTAINS_H * terrainHorizontalScale * settings.mountains.horizontalScale); - - Module module = Source.build(seed.next(), scaleH, 4).gain(1.15).lacunarity(2.35).ridge() - .mult(Source.perlin(seed.next(), 24, 4).alpha(0.075)) - .warp(seed.next(), 350, 1, 150); - - return settings.mountains.apply(groundLevel, MOUNTAINS_V * terrainVerticalScale, module); - } - - public Module mountains2(Seed seed) { - double scale = MOUNTAINS2_V * terrainVerticalScale; - Module cell = Source.cellEdge(seed.next(), 360, EdgeFunc.DISTANCE_2).scale(1.2).clamp(0, 1) - .warp(seed.next(), 200, 2, 100); - Module blur = Source.perlin(seed.next(), 10, 1).alpha(0.025); - Module surface = Source.ridge(seed.next(), 125, 4).alpha(0.37); - Module mountains = cell.clamp(0, 1).mult(blur).mult(surface).pow(1.1); - return settings.mountains.apply(groundLevel, scale, mountains); - } - - public Module mountains3(Seed seed) { - double scale = MOUNTAINS2_V * terrainVerticalScale; - - Module cell = Source.cellEdge(seed.next(), MOUNTAINS2_H, EdgeFunc.DISTANCE_2).scale(1.2).clamp(0, 1) - .warp(seed.next(), 200, 2, 100); - Module blur = Source.perlin(seed.next(), 10, 1).alpha(0.025); - Module surface = Source.ridge(seed.next(), 125, 4).alpha(0.37); - Module mountains = cell.clamp(0, 1).mult(blur).mult(surface).pow(1.1); - - Module terraced = mountains.terrace( - Source.perlin(seed.next(), 50, 1).scale(0.5), - Source.perlin(seed.next(), 100, 1).clamp(0.5, 0.95).map(0, 1), - Source.constant(0.45), - 0.2F, - 0.45F, - 24, - 1 - ); - - return settings.mountains.apply(groundLevel, scale, terraced); - } - - public Module badlands(Seed seed) { - Module mask = Source.perlin(seed.next(), 800, 1).clamp(0.35, 0.65).map(0, 1); - Module hills = Source.ridge(seed.next(), 500, 4) - .warp(seed.next(), 400, 2, 100) - .mult(mask); - - double modulation = 0.4; - double alpha = 1 - modulation; - Module mod1 = hills.warp(seed.next(), 100, 1, 50).scale(modulation); - - Module lowFreq = hills.steps(4).scale(alpha).add(mod1); - Module highFreq = hills.steps(10).scale(alpha).add(mod1); - Module detail = lowFreq.add(highFreq); - - Module mod2 = hills.mult(Source.perlin(seed.next(), 400, 3).scale(modulation)); - Module shape = hills.terrace(0.1, 1, 4, 0.01) - .scale(alpha) - .add(mod2) - .scale(alpha); - - return settings.badlands.apply(groundLevel, 0.7, shape.mult(detail.alpha(0.5))); - } - - public Module torridonian(Seed seed) { - Module plains = Source.perlin(seed.next(), 100, 3) - .warp(seed.next(), 300, 1, 150) - .warp(seed.next(), 20, 1, 40) - .scale(0.15); - - Module hills = Source.perlin(seed.next(), 150, 4) - .warp(seed.next(), 300, 1, 200) - .warp(seed.next(), 20, 2, 20) - .boost(); - - Module test = Source.perlin(seed.next(), 200, 3) - .blend(plains, hills, 0.6, 0.6) - .terrace( - Source.perlin(seed.next(), 120, 1).scale(0.25), - Source.perlin(seed.next(), 200, 1).scale(0.5).bias(0.5), - Source.constant(0.5), - 0, - 0.3, - 6, - 1 - ).boost(); - - return settings.torridonian.apply(groundLevel, 0.5, test); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrain.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrain.java deleted file mode 100644 index fb1d3e5..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrain.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain; - -import com.terraforged.core.cell.Tag; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.world.heightmap.Levels; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -public class Terrain implements Tag { - - private static final AtomicInteger MAX_ID = new AtomicInteger(0); - private static final Map register = Collections.synchronizedMap(new HashMap<>()); - - public static final int ID_START = 10; - public static final Terrain NONE = new Terrain("none", -1); - - private final String name; - private final int id; - private final float weight; - - public Terrain(String name, int id) { - this(name, id, 1F); - } - - public Terrain(String name, int id, double weight) { - this.name = name; - this.id = id; - this.weight = (float) weight; - register.put(name, this); - MAX_ID.set(Math.max(MAX_ID.get(), id)); - } - - public int getId() { - return id; - } - - @Override - public String getName() { - return name; - } - - public float getMax(float noise) { - return 1F; - } - - public float getWeight() { - return weight; - } - - public float getHue() { - return id / (float) MAX_ID.get(); - } - - @Override - public String toString() { - return getName(); - } - - public static Terrain ocean(Settings settings) { - return new Terrain("ocean", 0) { - - private final float max = new Levels(settings.generator).water; - - @Override - public float getMax(float noise) { - return max; - } - }; - } - - public static Terrain deepOcean(Settings settings) { - return new Terrain("deep_ocean", 1) { - - private final float max = new Levels(settings.generator).water / 2F; - - @Override - public float getMax(float noise) { - return max; - } - }; - } - - public static Terrain coast(Settings settings) { - return new Terrain("coast", 2) { - - private final float max = new Levels(settings.generator).ground(1); - - @Override - public float getMax(float noise) { - return max + (noise * (1 / 255F)); - } - }; - } - - public static Terrain beach(Settings settings) { - return new Terrain("beach", 2) { - - private final float max = new Levels(settings.generator).ground(1); - - @Override - public float getMax(float noise) { - return max + (noise * (1 / 255F)); - } - }; - } - - public static Terrain lake(Settings settings) { - return new Terrain("lake", 3); - } - - public static Terrain river(Settings settings) { - return new Terrain("river", 3); - } - - public static Terrain riverBank(Settings settings) { - return new Terrain("river_banks", 4); - } - - public static Terrain wetlands(Settings settings) { - return new Terrain("wetlands", 5); - } - - public static Terrain steppe(Settings settings) { - return new Terrain("steppe", 6, settings.terrain.steppe.weight); - } - - public static Terrain plains(Settings settings) { - return new Terrain("plains", 7, settings.terrain.plains.weight); - } - - public static Terrain plateau(Settings settings) { - return new Terrain("plateau", 8, settings.terrain.plateau.weight); - } - - public static Terrain badlands(Settings settings) { - return new Terrain("badlands", 9, settings.terrain.badlands.weight); - } - - public static Terrain hills(Settings settings) { - return new Terrain("hills", 10, settings.terrain.hills.weight); - } - - public static Terrain dales(Settings settings) { - return new Terrain("dales", 11, settings.terrain.dales.weight); - } - - public static Terrain torridonian(Settings settings) { - return new Terrain("torridonian_fells", 12, settings.terrain.torridonian.weight); - } - - public static Terrain mountains(Settings settings) { - return new Terrain("mountains", 13, settings.terrain.mountains.weight); - } - - public static Terrain volcano(Settings settings) { - return new Terrain("volcano", 14, settings.terrain.volcano.weight); - } - - public static Terrain volcanoPipe(Settings settings) { - return new Terrain("volcano_pipe", 15, settings.terrain.volcano.weight); - } - - public static Optional get(String name) { - return Optional.ofNullable(register.get(name)); - } - - public static List getRegistered() { - return new ArrayList<>(register.values()); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/TerrainPopulator.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/TerrainPopulator.java deleted file mode 100644 index 3d7db53..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/TerrainPopulator.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import me.dags.noise.Module; - -public class TerrainPopulator implements Populator { - - private final Terrain type; - private final Module source; - - public TerrainPopulator(Module source, Terrain type) { - this.type = type; - this.source = clamp(source); - } - - public Module getSource() { - return source; - } - - public Terrain getType() { - return type; - } - - @Override - public void apply(Cell cell, float x, float z) { - cell.value = source.getValue(x, z); - cell.tag = type; - } - - @Override - public void tag(Cell cell, float x, float y) { - cell.tag = type; - } - - public static Module clamp(Module module) { - if (module.minValue() < 0 || module.maxValue() > 1) { - return module.clamp(0, 1); - } - return module; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrains.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrains.java deleted file mode 100644 index 3198969..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/Terrains.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain; - -import com.terraforged.core.settings.Settings; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Terrains { - - public final Terrain ocean; - public final Terrain deepOcean; - public final Terrain coast; - public final Terrain beach; - public final Terrain lake; - public final Terrain river; - public final Terrain riverBanks; - public final Terrain wetlands; - public final Terrain badlands; - public final Terrain steppe; - public final Terrain plains; - public final Terrain plateau; - public final Terrain hills; - public final Terrain dales; - public final Terrain torridonian; - public final Terrain mountains; - public final Terrain volcano; - public final Terrain volcanoPipe; - public final List index; - - private Terrains(Mutable mutable) { - List index = new ArrayList<>(); - Collections.addAll( - index, - ocean = mutable.ocean, - deepOcean = mutable.deepOcean, - coast = mutable.coast, - beach = mutable.beach, - lake = mutable.lake, - river = mutable.river, - torridonian = mutable.torridonian, - riverBanks = mutable.riverbanks, - wetlands = mutable.wetlands, - badlands = mutable.badlands, - plateau = mutable.plateau, - steppe = mutable.steppe, - plains = mutable.plains, - hills = mutable.hills, - dales = mutable.dales, - mountains = mutable.mountains, - volcano = mutable.volcanoes, - volcanoPipe = mutable.volcanoPipe - ); - this.index = Collections.unmodifiableList(index); - } - - public int getId(Terrain landForm) { - return landForm.getId(); - } - - public boolean overridesRiver(Terrain terrain) { - return isOcean(terrain) || terrain == coast; - } - - public boolean isOcean(Terrain terrain) { - return terrain == ocean || terrain == deepOcean; - } - - public boolean isRiver(Terrain terrain) { - return terrain == river || terrain == riverBanks; - } - - public static Terrains create(Settings settings) { - Mutable terrain = new Mutable(); - terrain.ocean = Terrain.ocean(settings); - terrain.deepOcean = Terrain.deepOcean(settings); - terrain.coast = Terrain.coast(settings); - terrain.beach = Terrain.beach(settings); - terrain.lake = Terrain.lake(settings); - terrain.river = Terrain.river(settings); - terrain.riverbanks = Terrain.riverBank(settings); - terrain.wetlands = Terrain.wetlands(settings); - terrain.badlands = Terrain.badlands(settings); - terrain.plateau = Terrain.plateau(settings); - terrain.steppe = Terrain.steppe(settings); - terrain.plains = Terrain.plains(settings); - terrain.hills = Terrain.hills(settings); - terrain.dales = Terrain.dales(settings); - terrain.torridonian = Terrain.torridonian(settings); - terrain.mountains = Terrain.mountains(settings); - terrain.volcanoes = Terrain.volcano(settings); - terrain.volcanoPipe = Terrain.volcanoPipe(settings); - return terrain.create(); - } - - public static final class Mutable { - public Terrain ocean = Terrain.NONE; - public Terrain deepOcean = Terrain.NONE; - public Terrain coast = Terrain.NONE; - public Terrain beach = Terrain.NONE; - public Terrain lake = Terrain.NONE; - public Terrain river = Terrain.NONE; - public Terrain riverbanks = Terrain.NONE; - public Terrain wetlands = Terrain.NONE; - public Terrain badlands = Terrain.NONE; - public Terrain plateau = Terrain.NONE; - public Terrain steppe = Terrain.NONE; - public Terrain plains = Terrain.NONE; - public Terrain hills = Terrain.NONE; - public Terrain dales = Terrain.NONE; - public Terrain torridonian = Terrain.NONE; - public Terrain mountains = Terrain.NONE; - public Terrain volcanoes = Terrain.NONE; - public Terrain volcanoPipe = Terrain.NONE; - public Terrains create() { - return new Terrains(this); - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/VolcanoPopulator.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/VolcanoPopulator.java deleted file mode 100644 index 82a93e7..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/VolcanoPopulator.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.heightmap.RegionConfig; -import me.dags.noise.Module; -import me.dags.noise.Source; -import me.dags.noise.func.EdgeFunc; - -public class VolcanoPopulator extends TerrainPopulator { - - private static final float throat_value = 0.925F; - - private final Module cone; - private final Module height; - private final Module lowlands; - private final float inversionPoint; - private final float blendLower; - private final float blendUpper; - private final float blendRange; - private final float bias; - - private final Terrain inner; - private final Terrain outer; - - public VolcanoPopulator(Seed seed, RegionConfig region, Levels levels, Terrains terrains) { - super(Source.ZERO, terrains.volcano); - float midpoint = 0.3F; - float range = 0.3F; - - Module heightNoise = Source.perlin(seed.next(), 2, 1).map(0.45, 0.65); - - this.height = Source.cellNoise(region.seed, region.scale, heightNoise) - .warp(region.warpX, region.warpZ, region.warpStrength); - - this.cone = Source.cellEdge(region.seed, region.scale, EdgeFunc.DISTANCE_2_DIV).invert() - .warp(region.warpX, region.warpZ, region.warpStrength) - .powCurve(11) - .clamp(0.475, 1) - .map(0, 1) - .grad(0, 0.5, 0.5) - .warp(seed.next(), 15, 2, 10) - .scale(height); - - this.lowlands = Source.ridge(seed.next(), 150, 3) - .warp(seed.next(), 30, 1, 30) - .scale(0.1); - - this.inversionPoint = 0.94F; - this.blendLower = midpoint - (range / 2F); - this.blendUpper = blendLower + range; - this.blendRange = blendUpper - blendLower; - this.outer = terrains.volcano; - this.inner = terrains.volcanoPipe; - this.bias = levels.ground; - } - - @Override - public void apply(Cell cell, float x, float z) { - float value = cone.getValue(x, z); - float limit = height.getValue(x, z); - float maxHeight = limit * inversionPoint; - - // as value passes the inversion point we start calculating the inner-cone of the volcano - if (value > maxHeight) { - // modifies the steepness of the volcano inner-cone (larger == steeper) - float steepnessModifier = 1F; - - // as alpha approaches 1.0, position is closer to center of volcano - float delta = (value - maxHeight) * steepnessModifier; - float range = (limit - maxHeight); - float alpha = delta / range; - - // calculate height inside volcano - if (alpha > throat_value) { - cell.tag = inner; - } - - value = maxHeight - ((maxHeight / 5F) * alpha); - } else if (value < blendLower) { - value += lowlands.getValue(x, z); - cell.tag = outer; - } else if (value < blendUpper) { - float alpha = 1 - ((value - blendLower) / blendRange); - value += (lowlands.getValue(x, z) * alpha); - cell.tag = outer; - } - - cell.value = bias + value; - } - - @Override - public void tag(Cell cell, float x, float z) { - float value = cone.getValue(x, z); - float limit = height.getValue(x, z); - float maxHeight = limit * inversionPoint; - if (value > maxHeight) { - float steepnessModifier = 1; - - // as alpha approaches 1.0, position is closer to center of volcano - float delta = (value - maxHeight) * steepnessModifier; - float range = (limit - maxHeight); - float alpha = delta / range; - - // calculate height inside volcano - if (alpha > throat_value) { - cell.tag = inner; - } else { - cell.tag = outer; - } - } else { - cell.tag = outer; - } - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/StandardTerrainProvider.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/StandardTerrainProvider.java deleted file mode 100644 index 64419c1..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/StandardTerrainProvider.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.provider; - -import com.terraforged.core.cell.Populator; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.RegionConfig; -import com.terraforged.core.world.terrain.LandForms; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import com.terraforged.core.world.terrain.VolcanoPopulator; -import me.dags.noise.Module; -import me.dags.noise.Source; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiFunction; - -public class StandardTerrainProvider implements TerrainProvider { - - private final List mixable = new ArrayList<>(); - private final List unmixable = new ArrayList<>(); - private final Map populators = new HashMap<>(); - - private final LandForms landForms; - private final RegionConfig config; - private final GeneratorContext context; - private final Populator defaultPopulator; - - public StandardTerrainProvider(GeneratorContext context, RegionConfig config, Populator defaultPopulator) { - this.config = config; - this.context = context; - this.landForms = new LandForms(context.settings.terrain, context.levels); - this.defaultPopulator = defaultPopulator; - init(); - } - - public void init() { - registerMixable(context.terrain.steppe, landForms.steppe(context.seed)); - registerMixable(context.terrain.plains, landForms.plains(context.seed)); - registerMixable(context.terrain.hills, landForms.hills1(context.seed)); - registerMixable(context.terrain.hills, landForms.hills2(context.seed)); - registerMixable(context.terrain.dales, landForms.dales(context.seed)); - registerMixable(context.terrain.badlands, landForms.badlands(context.seed)); - registerMixable(context.terrain.plateau, landForms.plateau(context.seed)); - registerMixable(context.terrain.torridonian, landForms.torridonian(context.seed)); - - registerUnMixable(new VolcanoPopulator(context.seed, config, context.levels, context.terrain)); - registerUnMixable(context.terrain.badlands, landForms.badlands(context.seed)); - registerUnMixable(context.terrain.mountains, landForms.mountains2(context.seed)); - registerUnMixable(context.terrain.mountains, landForms.mountains3(context.seed)); - } - - @Override - public void registerMixable(TerrainPopulator populator) { - populators.putIfAbsent(populator.getType(), populator); - mixable.add(populator); - } - - @Override - public void registerUnMixable(TerrainPopulator populator) { - populators.putIfAbsent(populator.getType(), populator); - unmixable.add(populator); - } - - @Override - public Populator getPopulator(Terrain terrain) { - return populators.getOrDefault(terrain, defaultPopulator); - } - - @Override - public LandForms getLandforms() { - return landForms; - } - - @Override - public List getPopulators() { - List mixed = combine(getMixable(mixable), this::combine); - List result = new ArrayList<>(mixed.size() + unmixable.size()); - result.addAll(mixed); - result.addAll(unmixable); - return result; - } - - protected GeneratorContext getContext() { - return context; - } - - private TerrainPopulator combine(TerrainPopulator tp1, TerrainPopulator tp2) { - return combine(tp1, tp2, context.seed, config.scale / 2); - } - - private static TerrainPopulator combine(TerrainPopulator tp1, TerrainPopulator tp2, Seed seed, int scale) { - float weight = Math.min(tp1.getType().getWeight(), tp2.getType().getWeight()); - - String name = tp1.getType().getName() + "-" + tp2.getType().getName(); - int id = Terrain.ID_START + 1 + tp1.getType().getId() * tp2.getType().getId(); - - Terrain type = new Terrain(name, id, weight); - Module combined = Source.perlin(seed.next(), scale, 1) - .warp(seed.next(), scale / 2, 2, scale / 2D) - .blend(tp1.getSource(), tp2.getSource(), 0.5, 0.25) - .clamp(0, 1); - - return new TerrainPopulator(combined, type); - } - - private static List combine(List input, BiFunction operator) { - int length = input.size(); - for (int i = 1; i < input.size(); i++) { - length += (input.size() - i); - } - - List result = new ArrayList<>(length); - for (int i = 0; i < length; i++) { - result.add(null); - } - - for (int i = 0, k = input.size(); i < input.size(); i++) { - T t1 = input.get(i); - result.set(i, t1); - for (int j = i + 1; j < input.size(); j++, k++) { - T t2 = input.get(j); - T t3 = operator.apply(t1, t2); - result.set(k, t3); - } - } - - return result; - } - - private static List getMixable(List input) { - List output = new ArrayList<>(input.size()); - for (TerrainPopulator populator : input) { - if (populator.getType().getWeight() > 0) { - output.add(populator); - } - } - return output; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProvider.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProvider.java deleted file mode 100644 index 58131e6..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.provider; - -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.terrain.LandForms; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import me.dags.noise.Module; - -import java.util.List; - -/** - * Provides the heightmap generator with terrain specific noise generation modules (TerrainPopulators) - */ -public interface TerrainProvider { - - LandForms getLandforms(); - - /** - * Returns the resulting set of TerrainPopulators - */ - List getPopulators(); - - /** - * Returns a populator for the provided Terrain, or the default if not registered - */ - Populator getPopulator(Terrain terrain); - - /** - * Add a TerrainPopulator to world generation. - * - * 'Mixable' TerrainPopulators are used to create additional terrain types, created by blending two - * different mixable TerrainPopulators together (this is in addition to the unmixed version of the populator) - */ - void registerMixable(TerrainPopulator populator); - - /** - * Add a TerrainPopulator to world generation - * - * 'UnMixable' TerrainPopulators are NOT blended together to create additional terrain types - */ - void registerUnMixable(TerrainPopulator populator); - - /** - * Add a TerrainPopulator to world generation. - * - * 'Mixable' TerrainPopulators are used to create additional terrain types, created by blending two - * different mixable TerrainPopulators together (this is in addition to the unmixed version of the populator) - */ - default void registerMixable(Terrain type, Module source) { - registerMixable(new TerrainPopulator(source, type)); - } - - /** - * Add a TerrainPopulator to world generation - * - * 'UnMixable' TerrainPopulators are NOT blended together to create additional terrain types - */ - default void registerUnMixable(Terrain type, Module source) { - registerUnMixable(new TerrainPopulator(source, type)); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProviderFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProviderFactory.java deleted file mode 100644 index 4ff2842..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/provider/TerrainProviderFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.provider; - -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.RegionConfig; - -public interface TerrainProviderFactory { - - TerrainProvider create(GeneratorContext context, RegionConfig config, Populator defaultPopulator); -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionLerper.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionLerper.java deleted file mode 100644 index 5055e5b..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionLerper.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.region; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.util.NoiseUtil; - -public class RegionLerper implements Populator { - - private final Populator lower; - private final Populator upper; - - public RegionLerper(Populator lower, Populator upper) { - this.lower = lower; - this.upper = upper; - } - - @Override - public void apply(Cell cell, float x, float y) { - float alpha = cell.regionEdge; - if (alpha == 0) { - lower.apply(cell, x, y); - return; - } - - if (alpha == 1) { - upper.apply(cell, x, y); - return; - } - - lower.apply(cell, x, y); - float lowerValue = cell.value; - - upper.apply(cell, x, y); - float upperValue = cell.value; - - cell.value = NoiseUtil.lerp(lowerValue, upperValue, alpha); - } - - @Override - public void tag(Cell cell, float x, float y) { - if (cell.regionEdge == 0) { - lower.tag(cell, x, y); - return; - } - upper.tag(cell, x, y); - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionModule.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionModule.java deleted file mode 100644 index 739823e..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionModule.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.region; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.heightmap.RegionConfig; -import com.terraforged.core.world.terrain.Terrain; -import me.dags.noise.Source; -import me.dags.noise.domain.Domain; -import me.dags.noise.func.DistanceFunc; -import me.dags.noise.func.EdgeFunc; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; - -public class RegionModule implements Populator { - - private final int seed; - private final float frequency; - - private final float edgeMin; - private final float edgeMax; - private final float edgeRange; - private final Domain warp; - - public RegionModule(RegionConfig regionConfig) { - seed = regionConfig.seed; - edgeMin = 0F; - edgeMax = 0.5F; - edgeRange = edgeMax - edgeMin; - frequency = 1F / regionConfig.scale; - warp = Domain.warp(regionConfig.warpX, regionConfig.warpZ, Source.constant(regionConfig.warpStrength)); - } - - @Override - public void apply(Cell cell, float x, float y) { - float ox = warp.getOffsetX(x, y); - float oz = warp.getOffsetY(x, y); - - float px = x + ox; - float py = y + oz; - - px *= frequency; - py *= frequency; - - int cellX = 0; - int cellY = 0; - - int xr = NoiseUtil.round(px); - int yr = NoiseUtil.round(py); - float edgeDistance = 999999.0F; - float edgeDistance2 = 999999.0F; - float valueDistance = 3.4028235E38F; - DistanceFunc dist = DistanceFunc.NATURAL; - - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) { - int xi = xr + dx; - int yi = yr + dy; - Vec2f vec = NoiseUtil.CELL_2D[NoiseUtil.hash2D(seed, xi, yi) & 255]; - - float vecX = xi - px + vec.x; - float vecY = yi - py + vec.y; - float distance = dist.apply(vecX, vecY); - - if (distance < valueDistance) { - valueDistance = distance; - cellX = xi; - cellY = yi; - } - - if (distance < edgeDistance2) { - edgeDistance2 = Math.max(edgeDistance, distance); - } else { - edgeDistance2 = Math.max(edgeDistance, edgeDistance2); - } - - edgeDistance = Math.min(edgeDistance, distance); - } - } - - cell.region = cellValue(seed, cellX, cellY); - cell.regionEdge = edgeValue(edgeDistance, edgeDistance2); - } - - @Override - public void tag(Cell cell, float x, float y) { - - } - - private float cellValue(int seed, int cellX, int cellY) { - float value = NoiseUtil.valCoord2D(seed, cellX, cellY); - return NoiseUtil.map(value, -1, 1, 2); - } - - private float edgeValue(float distance, float distance2) { - EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV; - float value = edge.apply(distance, distance2); - float edgeValue = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range()); - - edgeValue = NoiseUtil.pow(edgeValue, 1.5F); - - if (edgeValue < edgeMin) { - return 0F; - } - if (edgeValue > edgeMax) { - return 1F; - } - - return (edgeValue - edgeMin) / edgeRange; - } -} diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionSelector.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionSelector.java deleted file mode 100644 index d967663..0000000 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/terrain/region/RegionSelector.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.core.world.terrain.region; - -import com.terraforged.core.cell.Cell; -import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.TerrainPopulator; -import me.dags.noise.util.NoiseUtil; - -import java.util.LinkedList; -import java.util.List; - -public class RegionSelector implements Populator { - - private final int maxIndex; - private final Populator[] nodes; - - public RegionSelector(List populators) { - this.nodes = getWeightedArray(populators); - this.maxIndex = nodes.length - 1; - } - - @Override - public void apply(Cell cell, float x, float y) { - get(cell.region).apply(cell, x, y); - } - - @Override - public void tag(Cell cell, float x, float y) { - get(cell.region).tag(cell, x, y); - } - - public Populator get(float identity) { - int index = NoiseUtil.round(identity * maxIndex); - return nodes[index]; - } - - private static Populator[] getWeightedArray(List modules) { - float smallest = Float.MAX_VALUE; - for (Populator p : modules) { - if (p instanceof TerrainPopulator) { - TerrainPopulator tp = (TerrainPopulator) p; - if (tp.getType().getWeight() == 0F) { - continue; - } - smallest = Math.min(smallest, tp.getType().getWeight()); - } else { - smallest = Math.min(smallest, 1); - } - } - - if (smallest == Float.MAX_VALUE) { - return modules.toArray(new Populator[0]); - } - - List result = new LinkedList<>(); - for (Populator p : modules) { - int count; - if (p instanceof TerrainPopulator) { - TerrainPopulator tp = (TerrainPopulator) p; - if (tp.getType().getWeight() == 0F) { - continue; - } - count = Math.round(tp.getType().getWeight() / smallest); - } else { - count = Math.round(1 / smallest); - } - while (count-- > 0) { - result.add(p); - } - } - - if (result.isEmpty()) { - return modules.toArray(new Populator[0]); - } - - return result.toArray(new Populator[0]); - } -} diff --git a/TerraForgedCore/src/main/resources/biomes.png b/TerraForgedCore/src/main/resources/biomes.png deleted file mode 100644 index 131a9bf6c6a2ae4cbb474a76c6ca804c315bf120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14615 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 Czu5Kw diff --git a/TerraForgedCore/src/main/resources/biomes.txt b/TerraForgedCore/src/main/resources/biomes.txt deleted file mode 100644 index 9622c92..0000000 --- a/TerraForgedCore/src/main/resources/biomes.txt +++ /dev/null @@ -1,13 +0,0 @@ -#TerraForgedCore BiomeType Hex Colors (do not include hash/pound character) -#Fri Jan 10 23:15:10 GMT 2020 -ALPINE=a078aa -TAIGA=5b8f52 -TEMPERATE_RAINFOREST=0aa041 -TUNDRA=93a7ac -TROPICAL_RAINFOREST=075330 -SAVANNA=97a527 -GRASSLAND=64dc3c -TEMPERATE_FOREST=32c850 -STEPPE=c8c878 -DESERT=c87137 -COLD_STEPPE=afb496 \ No newline at end of file diff --git a/TerraForgedCore/src/main/resources/license.txt b/TerraForgedCore/src/main/resources/license.txt deleted file mode 100644 index 0b31935..0000000 --- a/TerraForgedCore/src/main/resources/license.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 TerraForged - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/TerraForgedCore/src/main/resources/terraforged.png b/TerraForgedCore/src/main/resources/terraforged.png deleted file mode 100644 index ecedcf8df9c4e8d900159e97cc12c17f7b4c74d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27685 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/TerraForgedMod/gradlew.bat b/TerraForgedMod/gradlew.bat deleted file mode 100644 index f955316..0000000 --- a/TerraForgedMod/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/TerraForgedMod/psd/biomes.psd b/TerraForgedMod/psd/biomes.psd deleted file mode 100644 index eedc297d809041cec1b957c80d9d488f13689c0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179445 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 be~3v81KG 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ð-5{r2Q}d$vK6&~ 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

w4ET5TrP&TK@4pyYf-Rbec-prw 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 B73BZ` diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/TerraBiomeRegistry.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/TerraBiomeRegistry.java deleted file mode 100644 index 68219be..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/TerraBiomeRegistry.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.biome.provider; - -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.biome.Biome; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; - -public class TerraBiomeRegistry { - - private static final TerraBiomeRegistry instance = new TerraBiomeRegistry(); - - public Optional getBiome(ResourceLocation name) { - if (ForgeRegistries.BIOMES.containsKey(name)) { - return Optional.ofNullable(ForgeRegistries.BIOMES.getValue(name)); - } - return Optional.empty(); - } - - public Collection getAll(Predicate filter) { - List combined = new LinkedList<>(ForgeRegistries.BIOMES.getValues()); - combined.removeIf(filter); - return combined; - } - - public static TerraBiomeRegistry getInstance() { - return instance; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkProcessor.java b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkProcessor.java deleted file mode 100644 index e9df107..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkProcessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.terraforged.mod.chunk; - -import com.terraforged.api.chunk.column.DecoratorContext; -import com.terraforged.core.region.chunk.ChunkReader; -import net.minecraft.util.math.ChunkPos; - -public interface ChunkProcessor { - - void preProcess(ChunkPos pos, ChunkReader chunk, TerraContainer container); - - void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context); -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ObfHelperChunkGenerator.java b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ObfHelperChunkGenerator.java deleted file mode 100644 index 5c9843c..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ObfHelperChunkGenerator.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.chunk; - -import com.terraforged.mod.chunk.fix.SpawnFix; -import com.terraforged.mod.util.annotation.Name; -import com.terraforged.mod.util.annotation.Ref; -import net.minecraft.entity.EntityClassification; -import net.minecraft.util.SharedSeedRandom; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.provider.BiomeProvider; -import net.minecraft.world.chunk.IChunk; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.GenerationSettings; -import net.minecraft.world.gen.Heightmap; -import net.minecraft.world.gen.INoiseGenerator; -import net.minecraft.world.gen.NoiseChunkGenerator; -import net.minecraft.world.gen.OverworldChunkGenerator; -import net.minecraft.world.gen.PerlinNoiseGenerator; -import net.minecraft.world.gen.WorldGenRegion; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.spawner.CatSpawner; -import net.minecraft.world.spawner.PatrolSpawner; -import net.minecraft.world.spawner.PhantomSpawner; -import net.minecraft.world.spawner.WorldEntitySpawner; - -import java.util.List; - -@Ref({OverworldChunkGenerator.class, NoiseChunkGenerator.class, ChunkGenerator.class}) -public abstract class ObfHelperChunkGenerator extends ChunkGenerator { - - private final CatSpawner catSpawner = new CatSpawner(); - private final PatrolSpawner patrolSpawner = new PatrolSpawner(); - private final PhantomSpawner phantomSpawner = new PhantomSpawner(); - private final INoiseGenerator surfaceNoise; - - public ObfHelperChunkGenerator(IWorld world, BiomeProvider biomeProvider, T settings) { - super(world, biomeProvider, settings); - SharedSeedRandom random = new SharedSeedRandom(world.getSeed()); - this.surfaceNoise = new PerlinNoiseGenerator(random, 3, 0); - } - - @Override - public final void generateStructureStarts(IWorld world, IChunk chunk) { - try { - super.generateStructureStarts(world, chunk); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - @Override - public final void makeBase(IWorld world, IChunk chunk) { - generateBase(world, chunk); - } - - @Override - public final void func_225551_a_(WorldGenRegion world, IChunk chunk) { - generateSurface(world, chunk); - } - - @Override - public final List getPossibleCreatures(EntityClassification type, BlockPos pos) { - if (Feature.SWAMP_HUT.func_202383_b(this.world, pos)) { - if (type == EntityClassification.MONSTER) { - return Feature.SWAMP_HUT.getSpawnList(); - } - - if (type == EntityClassification.CREATURE) { - return Feature.SWAMP_HUT.getCreatureSpawnList(); - } - } else if (type == EntityClassification.MONSTER) { - if (Feature.PILLAGER_OUTPOST.isPositionInStructure(this.world, pos)) { - return Feature.PILLAGER_OUTPOST.getSpawnList(); - } - - if (Feature.OCEAN_MONUMENT.isPositionInStructure(this.world, pos)) { - return Feature.OCEAN_MONUMENT.getSpawnList(); - } - } - return super.getPossibleCreatures(type, pos); - } - - @Override - public final void spawnMobs(WorldGenRegion region) { - // vanilla does NOT check the mobSpawning gamerule before calling this - if (SpawnFix.canSpawnMobs()) { - int chunkX = region.getMainChunkX(); - int chunkZ = region.getMainChunkZ(); - Biome biome = region.getChunk(chunkX, chunkZ).getBiomes().getNoiseBiome(0, 0, 0); - SharedSeedRandom sharedseedrandom = new SharedSeedRandom(); - sharedseedrandom.setDecorationSeed(region.getSeed(), chunkX << 4, chunkZ << 4); - WorldEntitySpawner.performWorldGenSpawning(region, biome, chunkX, chunkZ, sharedseedrandom); - } - } - - @Override - public final void spawnMobs(ServerWorld worldIn, boolean spawnHostileMobs, boolean spawnPeacefulMobs) { - // vanilla does check the mobSpawning gamerule before calling this - phantomSpawner.tick(worldIn, spawnHostileMobs, spawnPeacefulMobs); - patrolSpawner.tick(worldIn, spawnHostileMobs, spawnPeacefulMobs); - catSpawner.tick(worldIn, spawnHostileMobs, spawnPeacefulMobs); - } - - @Override - @Name("getSurfaceLevel") - public final int func_222529_a(int x, int z, Heightmap.Type type) { - int level = getTopBlockY(x, z, type) + 1; - if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) { - return level; - } - return Math.max(getSeaLevel(), level); - } - - public final double getSurfaceNoise(int x, int z) { - double scale = 0.0625D; - double noiseX = x * scale; - double noiseZ = z * scale; - double unusedValue1 = scale; - double unusedValue2 = (x & 15) * scale; - return surfaceNoise.noiseAt(noiseX, noiseZ, unusedValue1, unusedValue2); - } - - public abstract int getTopBlockY(int x, int z, Heightmap.Type type); - - public abstract void generateBase(IWorld world, IChunk chunk); - - public abstract void generateSurface(WorldGenRegion world, IChunk chunk); -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java deleted file mode 100644 index 45465db..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.chunk; - -import com.terraforged.api.chunk.column.ColumnDecorator; -import com.terraforged.api.chunk.column.DecoratorContext; -import com.terraforged.api.chunk.surface.ChunkSurfaceBuffer; -import com.terraforged.api.chunk.surface.SurfaceContext; -import com.terraforged.api.chunk.surface.SurfaceManager; -import com.terraforged.api.material.layer.LayerManager; -import com.terraforged.core.cell.Cell; -import com.terraforged.core.region.Size; -import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.core.region.gen.RegionCache; -import com.terraforged.core.region.gen.RegionGenerator; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.world.decorator.Decorator; -import com.terraforged.feature.FeatureManager; -import com.terraforged.feature.matcher.dynamic.DynamicMatcher; -import com.terraforged.feature.matcher.feature.FeatureMatcher; -import com.terraforged.feature.modifier.FeatureModifierLoader; -import com.terraforged.feature.modifier.FeatureModifiers; -import com.terraforged.feature.predicate.DeepWater; -import com.terraforged.feature.predicate.FeaturePredicate; -import com.terraforged.feature.predicate.MinDepth; -import com.terraforged.feature.predicate.MinHeight; -import com.terraforged.feature.template.type.FeatureTypes; -import com.terraforged.mod.Log; -import com.terraforged.mod.biome.provider.BiomeProvider; -import com.terraforged.mod.chunk.fix.ChunkCarverFix; -import com.terraforged.mod.chunk.fix.RegionFix; -import com.terraforged.mod.decorator.ChunkPopulator; -import com.terraforged.mod.decorator.base.BedrockDecorator; -import com.terraforged.mod.decorator.base.CoastDecorator; -import com.terraforged.mod.decorator.base.ErosionDecorator; -import com.terraforged.mod.decorator.base.GeologyDecorator; -import com.terraforged.mod.decorator.feature.LayerDecorator; -import com.terraforged.mod.decorator.feature.SnowEroder; -import com.terraforged.mod.decorator.surface.FrozenOcean; -import com.terraforged.mod.feature.Matchers; -import com.terraforged.mod.feature.TerrainHelper; -import com.terraforged.mod.feature.predicate.TreeLine; -import com.terraforged.mod.material.Materials; -import com.terraforged.mod.material.geology.GeoManager; -import com.terraforged.mod.util.Environment; -import com.terraforged.mod.util.setup.SetupHooks; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.IWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeManager; -import net.minecraft.world.biome.Biomes; -import net.minecraft.world.chunk.ChunkPrimer; -import net.minecraft.world.chunk.IChunk; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.GenerationSettings; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.Heightmap; -import net.minecraft.world.gen.WorldGenRegion; -import net.minecraft.world.gen.feature.AbstractTreeFeature; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.template.TemplateManager; - -import java.util.ArrayList; -import java.util.List; - -public class TerraChunkGenerator extends ObfHelperChunkGenerator implements ChunkProcessor { - - private final TerraContext context; - private final BiomeProvider biomeProvider; - private final TerrainHelper terrainHelper; - - private final GeoManager geologyManager; - private final FeatureManager featureManager; - private final SurfaceManager surfaceManager; - private final List baseDecorators; - private final List postProcessors; - - private final RegionCache regionCache; - - public TerraChunkGenerator(TerraContext context, BiomeProvider biomeProvider, GenerationSettings settings) { - super(context.world, biomeProvider, settings); - this.context = context; - this.biomeProvider = biomeProvider; - this.surfaceManager = SetupHooks.setup(createSurfaceManager(), context.copy()); - this.geologyManager = SetupHooks.setup(createGeologyManager(context), context.copy()); - this.baseDecorators = createBaseDecorators(context); - this.postProcessors = createFeatureDecorators(context); - this.terrainHelper = new TerrainHelper(0.75F); - this.featureManager = createFeatureManager(context); - this.regionCache = createRegionCache(context); - SetupHooks.setup(getLayerManager(), context.copy()); - SetupHooks.setup(baseDecorators, postProcessors, context.copy()); - } - - @Override - public void generateStructures(BiomeManager biomes, IChunk chunk, ChunkGenerator generator, TemplateManager templates) { - ChunkPos pos = chunk.getPos(); - int regionX = regionCache.chunkToRegion(pos.x); - int regionZ = regionCache.chunkToRegion(pos.z); - // start generating the heightmap as early as possible - regionCache.queueRegion(regionX, regionZ); - super.generateStructures(biomes, chunk, this, templates); - } - - @Override - public final void generateBiomes(IChunk chunk) { - ChunkPos pos = chunk.getPos(); - ChunkReader reader = getChunkReader(pos.x, pos.z); - TerraContainer container = getBiomeProvider().createBiomeContainer(reader); - ((ChunkPrimer) chunk).func_225548_a_(container); - // apply chunk-local heightmap modifications - preProcess(pos, reader, container); - } - - @Override - public final void preProcess(ChunkPos pos, ChunkReader chunk, TerraContainer container) { - chunk.iterate((cell, dx, dz) -> { - Biome biome = container.getBiome(dx, dz); - for (Decorator decorator : getBiomeProvider().getDecorators(biome)) { - if (decorator.apply(cell, pos.getXStart() + dx, pos.getZStart() + dz)) { - return; - } - } - }); - } - - @Override - public final void generateBase(IWorld world, IChunk chunk) { - TerraContainer container = getBiomeContainer(chunk); - DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), getContext().levels, getContext().terrain, getContext().factory.getClimate()); - container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { - int px = ctx.blockX + dx; - int pz = ctx.blockZ + dz; - int py = ctx.levels.scale(cell.value); - ctx.cell = cell; - ctx.biome = container.getBiome(dx, dz); - ChunkPopulator.INSTANCE.decorate(ctx.chunk, ctx, px, py, pz); - }); - terrainHelper.flatten(world, chunk); - } - - @Override - public final void generateSurface(WorldGenRegion world, IChunk chunk) { - TerraContainer container = getBiomeContainer(chunk); - ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk)); - SurfaceContext context = getContext().surface(buffer, getSettings()); - - container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { - int px = ctx.blockX + dx; - int pz = ctx.blockZ + dz; - int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz) + 1; - - ctx.buffer.setSurfaceLevel(top); - - ctx.cell = cell; - ctx.biome = container.getBiome(dx, dz); - ctx.noise = getSurfaceNoise(px, pz) * 15D; - - getSurfaceManager().getSurface(ctx).buildSurface(px, pz, top, ctx); - - int py = ctx.levels.scale(cell.value); - for (ColumnDecorator processor : getBaseDecorators()) { - processor.decorate(ctx.buffer, ctx, px, py, pz); - } - }); - - FastChunk.updateWGHeightmaps(chunk, context.pos); - } - - @Override - public final void func_225550_a_(BiomeManager biomeManager, IChunk chunk, GenerationStage.Carving carving) { - - // World carvers have hardcoded 'carvable' blocks which can be problematic with modded blocks - // AirCarverFix shims the actual blockstates to an equivalent carvable type - super.func_225550_a_(biomeManager, new ChunkCarverFix(chunk, context.materials), carving); - } - - @Override - public void decorate(WorldGenRegion region) { - int chunkX = region.getMainChunkX(); - int chunkZ = region.getMainChunkZ(); - IChunk chunk = region.getChunk(chunkX, chunkZ); - TerraContainer container = getBiomeContainer(chunk); - Biome biome = container.getFeatureBiome(); - DecoratorContext context = getContext().decorator(chunk); - - IWorld regionFix = new RegionFix(region, this); - BlockPos pos = new BlockPos(context.blockX, 0, context.blockZ); - - // place biome features - featureManager.decorate(this, regionFix, chunk, biome, pos); - - // run post processes on chunk - postProcess(container.getChunkReader(), container, context); - - // bake biome array & discard gen data - ((ChunkPrimer) chunk).func_225548_a_(container.bakeBiomes(Environment.isVanillaBiomes())); - - // marks the heightmap data for this chunk for removal - container.getChunkReader().dispose(); - } - - @Override - public final void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context) { - chunk.iterate(context, (cell, dx, dz, ctx) -> { - int px = ctx.blockX + dx; - int pz = ctx.blockZ + dz; - int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz); - ctx.cell = cell; - ctx.biome = container.getBiome(dx, dz); - for (ColumnDecorator decorator : getPostProcessors()) { - decorator.decorate(ctx.chunk, ctx, px, py, pz); - } - }); - } - - @Override - public int getTopBlockY(int x, int z, Heightmap.Type type) { - int chunkX = Size.blockToChunk(x); - int chunkZ = Size.blockToChunk(z); - ChunkReader chunk = getChunkReader(chunkX, chunkZ); - Cell cell = chunk.getCell(x, z); - return context.levels.scale(cell.value); - } - - @Override - public BiomeProvider getBiomeProvider() { - return biomeProvider; - } - - @Override - public final int getMaxHeight() { - return getContext().levels.worldHeight; - } - - @Override - public final int getSeaLevel() { - return getContext().levels.waterLevel; - } - - @Override - public final int getGroundHeight() { - return getContext().levels.groundLevel; - } - - public final TerraContext getContext() { - return context; - } - - public final Materials getMaterials() { - return context.materials; - } - - public final GeoManager getGeologyManager() { - return geologyManager; - } - - public final LayerManager getLayerManager() { - return context.materials.getLayerManager(); - } - - public final SurfaceManager getSurfaceManager() { - return surfaceManager; - } - - public final List getBaseDecorators() { - return baseDecorators; - } - - public final List getPostProcessors() { - return postProcessors; - } - - protected TerraContainer getBiomeContainer(IChunk chunk) { - if (chunk.getBiomes() instanceof TerraContainer) { - return (TerraContainer) chunk.getBiomes(); - } - - ChunkReader view = getChunkReader(chunk.getPos().x, chunk.getPos().z); - TerraContainer container = getBiomeProvider().createBiomeContainer(view); - if (chunk instanceof ChunkPrimer) { - ((ChunkPrimer) chunk).func_225548_a_(container); - } else if (chunk instanceof FastChunk) { - ((FastChunk) chunk).setBiomes(container); - } - - return container; - } - - protected FeatureManager createFeatureManager(TerraContext context) { - FeatureModifiers modifiers; - if (context.terraSettings.features.customBiomeFeatures) { - Log.info(" - Custom biome features enabled"); - modifiers = FeatureModifierLoader.load(); - } else { - modifiers = new FeatureModifiers(); - } - - if (context.terraSettings.features.strataDecorator) { - // block stone blobs if strata enabled - modifiers.getPredicates().add(Matchers.stoneBlobs(), FeaturePredicate.DENY); - } - - if (!context.terraSettings.features.vanillaWaterFeatures) { - // block lakes and springs if not enabled - modifiers.getPredicates().add(FeatureMatcher.of(Feature.LAKE), FeaturePredicate.DENY); - modifiers.getPredicates().add(FeatureMatcher.of(Feature.SPRING_FEATURE), FeaturePredicate.DENY); - } - - // block ugly features - modifiers.getPredicates().add(Matchers.sedimentDisks(), FeaturePredicate.DENY); - - // limit to deep oceans - modifiers.getPredicates().add(FeatureMatcher.of(Feature.SHIPWRECK), MinDepth.DEPTH55); - modifiers.getPredicates().add(FeatureMatcher.of(Feature.OCEAN_RUIN), DeepWater.INSTANCE); - modifiers.getPredicates().add(FeatureMatcher.of(Feature.OCEAN_MONUMENT), DeepWater.INSTANCE); - - // prevent mineshafts above ground - modifiers.getPredicates().add(FeatureMatcher.of(Feature.MINESHAFT), MinHeight.HEIGHT80); - - // prevent trees/bamboo growing too high up - TreeLine treeLine = new TreeLine(context); - modifiers.getPredicates().add(FeatureTypes.TREE.matcher(), treeLine); - modifiers.getPredicates().add(FeatureMatcher.of(Feature.BAMBOO), treeLine); - modifiers.getDynamic().add(DynamicMatcher.feature(AbstractTreeFeature.class), treeLine); - - return FeatureManager.create(context.world, SetupHooks.setup(modifiers, context.copy())); - } - - protected GeoManager createGeologyManager(TerraContext context) { - return new GeoManager(context); - } - - protected SurfaceManager createSurfaceManager() { - SurfaceManager manager = new SurfaceManager(); - manager.replace(Biomes.FROZEN_OCEAN, new FrozenOcean(context, 20, 15)); - manager.replace(Biomes.DEEP_FROZEN_OCEAN, new FrozenOcean(context, 30, 30)); - return manager; - } - - protected List createBaseDecorators(TerraContext context) { - List processors = new ArrayList<>(); - if (context.terraSettings.features.strataDecorator) { - Log.info(" - Geology decorator enabled"); - processors.add(new GeologyDecorator(geologyManager)); - } - - if (context.terraSettings.features.erosionDecorator) { - Log.info(" - Erosion decorator enabled"); - processors.add(new ErosionDecorator(context)); - } - processors.add(new CoastDecorator(context)); - processors.add(new BedrockDecorator(context)); - return processors; - } - - protected List createFeatureDecorators(TerraContext context) { - List processors = new ArrayList<>(); - if (context.terraSettings.features.naturalSnowDecorator) { - Log.info(" - Natural snow decorator enabled"); - processors.add(new SnowEroder(context)); - } - if (context.terraSettings.features.smoothLayerDecorator) { - Log.info(" - Smooth layer decorator enabled"); - processors.add(new LayerDecorator(context.materials.getLayerManager())); - } - return processors; - } - - protected RegionCache createRegionCache(TerraContext context) { - return RegionGenerator.builder() - .legacy(context.terraSettings.version == 0) - .pool(ThreadPool.getPool()) - .factory(context.factory) - .size(3, 2) - .build() - .toCache(false); - } - - public ChunkReader getChunkReader(int chunkX, int chunkZ) { - return regionCache.getChunk(chunkX, chunkZ); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java deleted file mode 100644 index b2c034a..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.chunk; - -import com.terraforged.mod.settings.StructureSettings; -import net.minecraft.world.gen.OverworldGenSettings; - -public class TerraGenSettings extends OverworldGenSettings { - - public TerraGenSettings(StructureSettings settings) { - super.villageDistance *= settings.villageDistance; - super.mansionDistance *= settings.mansionDistance; - super.strongholdDistance *= settings.strongholdDistance; - super.strongholdSpread *= settings.strongholdSpread; - super.biomeFeatureDistance *= settings.biomeStructureDistance; - super.oceanMonumentSpacing *= settings.oceanMonumentSpacing; - super.oceanMonumentSeparation *= settings.oceanMonumentSeparation; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java deleted file mode 100644 index a8a6926..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/Permissions.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.terraforged.mod.command; - -public class Permissions { - - public static final String QUERY = "terraforged.command.terra.query"; - public static final String DEBUG = "terraforged.command.terra.debug"; - public static final String DATA = "terraforged.command.terra.data"; - public static final String DEFAULTS = "terraforged.command.terra.defaults"; - public static final String LOCATE = "terraforged.command.terra.locate"; -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java b/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java deleted file mode 100644 index 4c1d082..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.data; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.datafixers.Dynamic; -import com.mojang.datafixers.types.JsonOps; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.IFeatureConfig; -import net.minecraft.world.gen.feature.jigsaw.JigsawManager; -import net.minecraft.world.gen.feature.jigsaw.JigsawPattern; -import net.minecraft.world.gen.feature.jigsaw.JigsawPatternRegistry; -import net.minecraft.world.gen.feature.jigsaw.JigsawPiece; -import net.minecraft.world.gen.feature.structure.Structure; -import net.minecraftforge.registries.ForgeRegistries; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class WorldGenFeatures extends DataGen { - - public static void genBiomeFeatures(File dataDir) { - if (dataDir.exists() || dataDir.mkdirs()) { - for (Biome biome : ForgeRegistries.BIOMES) { - genBiomeFeatures(dataDir, biome); - genBiomeStructures(dataDir, biome); - } - genBiomeJigsaws(dataDir); - } - } - - private static void genBiomeFeatures(File dir, Biome biome) { - write(new File(dir, getJsonPath("features", biome.getRegistryName())), writer -> { - JsonObject root = new JsonObject(); - for (GenerationStage.Decoration type : GenerationStage.Decoration.values()) { - JsonArray features = new JsonArray(); - for (ConfiguredFeature feature : biome.getFeatures(type)) { - try { - Dynamic dynamic = feature.serialize(JsonOps.INSTANCE); - features.add(dynamic.getValue()); - } catch (NullPointerException e) { - new NullPointerException("Badly written feature: " + feature.feature.getRegistryName()).printStackTrace(); - } - } - root.add(type.getName(), features); - } - write(root, writer); - }); - } - - private static void genBiomeStructures(File dir, Biome biome) { - write(new File(dir, getJsonPath("structures", biome.getRegistryName())), writer -> { - JsonObject root = new JsonObject(); - for (Map.Entry> e : Structure.STRUCTURES.entrySet()) { - JsonArray array = new JsonArray(); - IFeatureConfig config = biome.getStructureConfig(e.getValue()); - if (config == null) { - continue; - } - JsonElement element = config.serialize(JsonOps.INSTANCE).getValue(); - JsonObject object = new JsonObject(); - object.addProperty("structure", e.getValue().getRegistryName() + ""); - object.add("config", element); - array.add(object); - } - write(root, writer); - }); - } - - private static void genBiomeJigsaws(File dir) { - Random random = new Random(); - write(new File(dir, "jigsaws.json"), writer -> { - JsonObject root = new JsonObject(); - for (Map.Entry e : getJigsawRegistry().entrySet()) { - JsonArray array = new JsonArray(); - List pieces = e.getValue().getShuffledPieces(random); - for (JigsawPiece piece : pieces) { - JsonElement element = piece.serialize(JsonOps.INSTANCE).getValue(); - array.add(element); - } - root.add(e.getKey().toString(), array); - } - write(root, writer); - }); - } - - private static Map getJigsawRegistry() { - try { - for (Field field : JigsawPatternRegistry.class.getDeclaredFields()) { - if (field.getType() == Map.class) { - field.setAccessible(true); - Object value = field.get(JigsawManager.REGISTRY); - return (Map) value; - } - } - } catch (Throwable t) { - t.printStackTrace(); - } - return Collections.emptyMap(); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java deleted file mode 100644 index 09d36ff..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/Poisson.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.terraforged.mod.feature.decorator.poisson; - -import com.terraforged.core.util.concurrent.ObjectPool; -import me.dags.noise.Source; -import me.dags.noise.util.NoiseUtil; -import me.dags.noise.util.Vec2f; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.Random; -import java.util.function.BiConsumer; - -public class Poisson { - - private static final int SAMPLES = 50; - - private final int radius; - private final int radius2; - private final float halfRadius; - private final int maxDistance; - private final int regionSize; - private final int gridSize; - private final float cellSize; - private final ObjectPool pool; - - public Poisson(int radius) { - int size = 48; - this.radius = radius; - this.radius2 = radius * radius; - this.halfRadius = radius / 2F; - this.maxDistance = radius * 2; - this.regionSize = size - radius; - this.cellSize = radius / NoiseUtil.SQRT2; - this.gridSize = (int) Math.ceil(regionSize / cellSize); - this.pool = new ObjectPool<>(3, () -> new Vec2f[gridSize][gridSize]); - } - - public int getRadius() { - return radius; - } - - public void visit(int chunkX, int chunkZ, PoissonContext context, BiConsumer consumer) { - try (ObjectPool.Item grid = pool.get()) { - clear(grid.getValue()); - context.startX = (chunkX << 4); - context.startZ = (chunkZ << 4); - context.endX = context.startX + 16; - context.endZ = context.startZ + 16; - int regionX = (context.startX >> 5); - int regionZ = (context.startZ >> 5); - context.offsetX = regionX << 5; - context.offsetZ = regionZ << 5; - context.random.setSeed(NoiseUtil.hash2D(context.seed, regionX, regionZ)); - int x = context.random.nextInt(regionSize); - int z = context.random.nextInt(regionSize); - visit(x, z, grid.getValue(), SAMPLES, context, consumer); - } - } - - private void visit(float px, float pz, Vec2f[][] grid, int samples, PoissonContext context, BiConsumer consumer) { - for (int i = 0; i < samples; i++) { - float angle = context.random.nextFloat() * NoiseUtil.PI2; - float distance = radius + (context.random.nextFloat() * maxDistance); - float x = halfRadius + px + NoiseUtil.sin(angle) * distance; - float z = halfRadius + pz + NoiseUtil.cos(angle) * distance; - if (valid(x, z, grid, context)) { - Vec2f vec = new Vec2f(x, z); - visit(vec, context, consumer); - int cellX = (int) (x / cellSize); - int cellZ = (int) (z / cellSize); - grid[cellZ][cellX] = vec; - visit(vec.x, vec.y, grid, samples, context, consumer); - } - } - } - - private void visit(Vec2f pos, PoissonContext context, BiConsumer consumer) { - int dx = context.offsetX + (int) pos.x; - int dz = context.offsetZ + (int) pos.y; - if (dx >= context.startX && dx < context.endX && dz >= context.startZ && dz < context.endZ) { - consumer.accept(dx, dz); - } - } - - private boolean valid(float x, float z, Vec2f[][] grid, PoissonContext context) { - if (x < 0 || x >= regionSize || z < 0 || z >= regionSize) { - return false; - } - - int cellX = (int) (x / cellSize); - int cellZ = (int) (z / cellSize); - if (grid[cellZ][cellX] != null) { - return false; - } - - float noise = context.density.getValue(context.offsetX + x, context.offsetZ + z); - float radius2 = noise * this.radius2; - - int searchRadius = 2; - int minX = Math.max(0, cellX - searchRadius); - int maxX = Math.min(grid[0].length - 1, cellX + searchRadius); - int minZ = Math.max(0, cellZ - searchRadius); - int maxZ = Math.min(grid.length - 1, cellZ + searchRadius); - - for (int dz = minZ; dz <= maxZ; dz++) { - for (int dx = minX; dx <= maxX; dx++) { - Vec2f vec = grid[dz][dx]; - if (vec == null) { - continue; - } - - float dist2 = vec.dist2(x, z); - if (dist2 < radius2) { - return false; - } - } - } - return true; - } - - private static void clear(Vec2f[][] grid) { - for (Vec2f[] row : grid) { - Arrays.fill(row, null); - } - } - - public static void main(String[] args) { - int size = 512; - int radius = 6; - - int chunkSize = 16; - int chunks = size / chunkSize; - - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB); - Poisson poisson = new Poisson(radius); - PoissonContext context = new PoissonContext(213, new Random()); - context.density = Source.simplex(213, 100, 1).scale(2).bias(0); - - long time = 0L; - long count = 0L; - - int chunkX = 342; - int chunkZ = 546; - for (int cz = 0; cz < chunks; cz++) { - for (int cx = 0; cx < chunks; cx++) { - long start = System.nanoTime(); - poisson.visit(chunkX + cx, chunkZ + cz, context, (x, z) -> { - x -= chunkX << 4; - z -= chunkZ << 4; - if (x < 0 || x >= image.getWidth() || z < 0 || z >= image.getHeight()) { - return; - } - image.setRGB(x, z, Color.WHITE.getRGB()); - }); - time += (System.nanoTime() - start); - count++; - } - } - - double avg = (double) (time / count) / 1000000; - System.out.println(avg + "ms"); - - JFrame frame = new JFrame(); - frame.add(new JLabel(new ImageIcon(image))); - frame.setVisible(true); - frame.pack(); - frame.setResizable(false); - frame.setLocationRelativeTo(null); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonContext.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonContext.java deleted file mode 100644 index 7c6c512..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonContext.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.terraforged.mod.feature.decorator.poisson; - -import me.dags.noise.Module; -import me.dags.noise.Source; - -import java.util.Random; - -public class PoissonContext { - - public int offsetX; - public int offsetZ; - public int startX; - public int startZ; - public int endX; - public int endZ; - public Module density = Source.ONE; - - public final int seed; - public final Random random; - - public PoissonContext(long seed, Random random) { - this.seed = (int) seed; - this.random = random; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingConfig.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingConfig.java deleted file mode 100644 index 70b4333..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingConfig.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import com.google.gson.reflect.TypeToken; -import com.mojang.datafixers.types.DynamicOps; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class SaplingConfig { - - private static final TypeToken> TOKEN = new TypeToken>() { - }; - - private final Map normal; - private final Map giant; - - public SaplingConfig() { - normal = new HashMap<>(); - giant = new HashMap<>(); - } - - public SaplingConfig(T config, DynamicOps ops) { - this.normal = getSection("normal", config, ops); - this.giant = getSection("giant", config, ops); - } - - public SaplingConfig addNormal(ResourceLocation name, int weight) { - normal.put(name, weight); - return this; - } - - public SaplingConfig addNormal(String name, int weight) { - normal.put(new ResourceLocation(name), weight); - return this; - } - - public SaplingConfig addGiant(ResourceLocation name, int weight) { - giant.put(name, weight); - return this; - } - - public SaplingConfig addGiant(String name, int weight) { - giant.put(new ResourceLocation(name), weight); - return this; - } - - private Map getSection(String key, T config, DynamicOps ops) { - return ops.get(config, key).flatMap(ops::getMapValues).map(map -> { - Map backing = new HashMap<>(); - - for (Map.Entry entry : map.entrySet()) { - String name = ops.getStringValue(entry.getKey()).orElse(""); - int weight = ops.getNumberValue(entry.getValue()).orElse(0).intValue(); - if (name.isEmpty() || weight == 0) { - continue; - } - - ResourceLocation loc = new ResourceLocation(name); - backing.put(loc, weight); - } - - return backing; - }).orElse(Collections.emptyMap()); - } - - public List> getNormal() { - return build(normal); - } - - public List> getGiant() { - return build(giant); - } - - @SuppressWarnings("unchecked") - public static List> build(Map map) { - List> list = new LinkedList<>(); - for (Map.Entry entry : map.entrySet()) { - Feature feature = ForgeRegistries.FEATURES.getValue(entry.getKey()); - if (feature == null) { - continue; - } - - if (TOKEN.getRawType().isAssignableFrom(feature.getClass())) { - Feature noConfFeature = (Feature) feature; - list.add(noConfFeature); - } - } - return list; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingFeature.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingFeature.java deleted file mode 100644 index b8204ff..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingFeature.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.NoFeatureConfig; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class SaplingFeature { - - private final List> normal; - private final List> giant; - - public SaplingFeature(SaplingConfig config) { - this.normal = new ArrayList<>(config.getNormal()); - this.giant = new ArrayList<>(config.getGiant()); - } - - public Feature nextNormal(Random random) { - if (normal.isEmpty()) { - return null; - } - return normal.get(random.nextInt(normal.size())); - } - - public Feature nextGiant(Random random) { - if (giant.isEmpty()) { - return null; - } - return giant.get(random.nextInt(giant.size())); - } - - public int getNormalCount() { - return normal.size(); - } - - public int getGiantCount() { - return giant.size(); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java deleted file mode 100644 index 7836573..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingListener.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import com.terraforged.mod.TerraWorld; -import com.terraforged.mod.chunk.TerraChunkGenerator; -import com.terraforged.mod.chunk.TerraContext; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.SaplingBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3i; -import net.minecraft.world.IWorld; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.event.world.SaplingGrowTreeEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) -public class SaplingListener { - - private static final BlockPos[] NONE = {BlockPos.ZERO}; - - private static final Vec3i[][] DIRECTIONS = { - {new Vec3i(0, 0, 1), new Vec3i(1, 0, 1), new Vec3i(1, 0, 0)}, - {new Vec3i(1, 0, 0), new Vec3i(1, 0, -1), new Vec3i(0, 0, -1)}, - {new Vec3i(0, 0, -1), new Vec3i(-1, 0, -1), new Vec3i(-1, 0, 0)}, - {new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(0, 0, 1)}, - }; - - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void onTreeGrow(SaplingGrowTreeEvent event) { - // ignore if client - if (event.getWorld().isRemote()) { - return; - } - // ignore other world types - if (!TerraWorld.isTerraWorld(event.getWorld())) { - return; - } - // has user disabled custom trees? - if (!areCustomTreesEnabled(event.getWorld())) { - return; - } - - IWorld world = event.getWorld(); - BlockPos pos = event.getPos(); - Block block = world.getBlockState(pos).getBlock(); - if (block instanceof SaplingBlock) { - // get the sapling feature for the given block type - SaplingFeature tree = SaplingManager.getSapling(block.getRegistryName()); - - // tree is null if the sapling type hasn't been configured - if (tree == null) { - return; - } - - // check for a 2x2 arrangement of sapling blocks around the position - Vec3i[] directions = getNeighbourDirections(world, block, pos); - - // length is 1 if a full 2x2 arrangement could not be found - if (directions.length == 1) { - placeNormal(tree, event, directions); - } else { - placeGiant(tree, event, block, directions); - } - } - } - - private static void placeNormal(SaplingFeature tree, SaplingGrowTreeEvent event, Vec3i[] directions) { - SaplingPlacer.placeTree(tree.nextNormal(event.getRand()), event, directions); - } - - private static void placeGiant(SaplingFeature tree, SaplingGrowTreeEvent event, Block type, Vec3i[] directions) { - Feature feature = tree.nextGiant(event.getRand()); - - // if no giant tree exists for this sapling type try and place a normal one instead - if (feature == null) { - placeNormal(tree, event, directions); - return; - } - - // do not continue if unable to place the tree - if (!SaplingPlacer.placeTree(feature, event, directions)) { - return; - } - - // iterate through the contributing saplings and remove any that were not destroyed during tree creation - BlockPos pos = event.getPos(); - for (Vec3i dir : directions) { - BlockPos blockPos = pos.add(dir); - BlockState state = event.getWorld().getBlockState(blockPos); - if (state.getBlock() == type) { - event.getWorld().removeBlock(blockPos, false); - } - } - } - - private static Vec3i[] getNeighbourDirections(IWorld world, Block block, BlockPos pos) { - for (Vec3i[] dirs : DIRECTIONS) { - boolean match = true; - for (Vec3i dir : dirs) { - BlockState state = world.getBlockState(pos.add(dir)); - if (state.getBlock() != block) { - match = false; - break; - } - } - if (match) { - return dirs; - } - } - return NONE; - } - - private static boolean areCustomTreesEnabled(IWorld world) { - if (world instanceof ServerWorld) { - ServerWorld serverWorld = (ServerWorld) world; - ChunkGenerator generator = serverWorld.getChunkProvider().generator; - if (generator instanceof TerraChunkGenerator) { - TerraContext context = ((TerraChunkGenerator) generator).getContext(); - return context.terraSettings.features.customBiomeFeatures; - } - } - return false; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingManager.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingManager.java deleted file mode 100644 index 9335703..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingManager.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import com.mojang.datafixers.types.DynamicOps; -import com.terraforged.mod.Log; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.util.ResourceLocation; - -import java.util.HashMap; -import java.util.Map; - -public class SaplingManager { - - private static final Map saplings = new HashMap<>(); - - public static SaplingFeature getSapling(ResourceLocation name) { - return saplings.get(name); - } - - public static void register(Block block, SaplingConfig config) { - register(block.getRegistryName(), config); - } - - public static void register(ResourceLocation location, T config, DynamicOps ops) { - register(location, new SaplingConfig(config, ops)); - } - - public static void register(ResourceLocation location, SaplingConfig config) { - saplings.put(location, new SaplingFeature(config)); - } - - public static void init() { - register(Blocks.OAK_SAPLING, new SaplingConfig() - .addNormal("terraforged:oak_small", 4) - .addNormal("terraforged:oak_forest", 3) - .addNormal("terraforged:oak_large", 2) - .addGiant("terraforged:oak_huge", 1)); - - register(Blocks.BIRCH_SAPLING, new SaplingConfig() - .addNormal("terraforged:birch_small", 4) - .addNormal("terraforged:birch_forest", 3) - .addNormal("terraforged:birch_large", 1)); - - register(Blocks.JUNGLE_SAPLING, new SaplingConfig() - .addNormal("terraforged:jungle_small", 4) - .addGiant("terraforged:jungle_large", 1)); - - register( - Blocks.SPRUCE_SAPLING, - new SaplingConfig() - .addNormal("terraforged:spruce_small", 4) - .addNormal("terraforged:spruce_large", 1) - .addGiant("terraforged:redwood_huge", 1)); - - register(Blocks.DARK_OAK_SAPLING, new SaplingConfig() - .addNormal("terraforged:dark_oak_small", 4) - .addNormal("terraforged:dark_oak_large", 1)); - - register(Blocks.ACACIA_SAPLING, new SaplingConfig() - .addNormal("terraforged:acacia_small", 2) - .addNormal("terraforged:acacia_large", 1)); - - Log.info("Registered saplings"); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingPlacer.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingPlacer.java deleted file mode 100644 index 5c335ab..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/SaplingPlacer.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import com.terraforged.feature.template.decorator.DecoratedFeature; -import com.terraforged.feature.template.decorator.DecoratorWorld; -import com.terraforged.feature.template.feature.TemplateFeature; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3i; -import net.minecraft.world.IWorld; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.server.ServerChunkProvider; -import net.minecraftforge.event.world.SaplingGrowTreeEvent; -import net.minecraftforge.eventbus.api.Event; - -public class SaplingPlacer { - - public static boolean placeTree(Feature feature, SaplingGrowTreeEvent event, Vec3i[] dirs) { - if (feature == null) { - return false; - } - - event.setResult(Event.Result.DENY); - - if (feature instanceof DecoratedFeature) { - return placeDecorated((DecoratedFeature) feature, event, dirs); - } - - return placeNormal(feature, event, dirs); - } - - private static boolean placeDecorated(DecoratedFeature feature, SaplingGrowTreeEvent event, Vec3i[] dirs) { - if (!(event.getWorld().getChunkProvider() instanceof ServerChunkProvider)) { - return false; - } - - TreeGrowBuffer buffer = new TreeGrowBuffer(event.getWorld(), event.getPos()); - W world = feature.wrap(buffer); - - ChunkGenerator generator = ((ServerChunkProvider) event.getWorld().getChunkProvider()).getChunkGenerator(); - feature.placeFeature(world, generator, event.getRand(), event.getPos(), NoFeatureConfig.NO_FEATURE_CONFIG); - - // check that the tree can grow here - if (overheadIsSolid(event.getWorld(), event.getPos(), buffer.getTopY())) { - return false; - } - - BlockPos translation = buffer.getBaseMin().add(getMin(dirs)); - - // apply buffer to world with translation - applyBuffer(buffer, event.getWorld(), translation); - - // translate the decoration positions and apply in the world - world.setDelegate(event.getWorld()); - world.translate(translation); - feature.decorate(world, event.getRand()); - return true; - } - - private static boolean placeNormal(Feature feature, SaplingGrowTreeEvent event, Vec3i[] dirs) { - // apply the feature to a buffer - TreeGrowBuffer buffer = new TreeGrowBuffer(event.getWorld(), event.getPos()); - buffer.placeFeature(feature, event.getPos(), event.getRand()); - - // check that the tree can grow here - if (overheadIsSolid(event.getWorld(), event.getPos(), buffer.getTopY())) { - return false; - } - - // get the min position in the 2x2 grid - BlockPos translation = buffer.getBaseMin().add(getMin(dirs)); - - // copy the feature from the buffer to the world while translating each block - applyBuffer(buffer, event.getWorld(), translation); - return true; - } - - private static void applyBuffer(TreeGrowBuffer buffer, IWorld world, BlockPos translation) { - try (BlockPos.PooledMutable pos = BlockPos.PooledMutable.retain()) { - for (TemplateFeature.BlockInfo block : buffer.getChanges()) { - int x = block.getPos().getX() + translation.getX(); - int y = block.getPos().getY(); - int z = block.getPos().getZ() + translation.getZ(); - - pos.setPos(x, y, z); - - BlockState current = world.getBlockState(pos); - if (current.isSolid()) { - continue; - } - - world.setBlockState(pos, block.getState(), 2); - } - } - } - - private static boolean overheadIsSolid(IWorld world, BlockPos pos, int topY) { - try (BlockPos.PooledMutable blockPos = BlockPos.PooledMutable.retain()) { - for (int y = pos.getY(); y <= topY; y++) { - blockPos.setPos(pos.getX(), y, pos.getZ()); - BlockState state = world.getBlockState(pos); - if (state.isSolid()) { - return true; - } - } - return false; - } - } - - private static Vec3i getMin(Vec3i[] dirs) { - Vec3i min = Vec3i.NULL_VECTOR; - for (Vec3i dir : dirs) { - if (dir.getX() < min.getX() && dir.getZ() <= min.getZ()) { - min = dir; - continue; - } - if (dir.getZ() < min.getZ() && dir.getX() <= min.getX()) { - min = dir; - } - } - return min; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/TreeGrowBuffer.java b/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/TreeGrowBuffer.java deleted file mode 100644 index 27a5371..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/tree/TreeGrowBuffer.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.feature.tree; - -import com.terraforged.feature.template.feature.TemplateFeature; -import com.terraforged.feature.util.WorldDelegate; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3i; -import net.minecraft.world.IWorld; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.IFeatureConfig; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.server.ServerChunkProvider; - -import java.util.LinkedList; -import java.util.List; -import java.util.Random; - -public class TreeGrowBuffer extends WorldDelegate { - - private int topY = 0; - private final BlockPos pos; - private final MutableVec3i baseMin = new MutableVec3i(0); - private final MutableVec3i baseMax = new MutableVec3i(0); - private final List changes = new LinkedList<>(); - - public TreeGrowBuffer(IWorld delegate, BlockPos pos) { - super(delegate); - this.pos = pos; - } - - public int getTopY() { - return topY; - } - - public BlockPos getBaseMin() { - return new BlockPos(-baseMin.x, baseMin.y, -baseMin.z); - } - - public BlockPos getBaseMax() { - return new BlockPos(baseMax.x, baseMax.y, baseMax.z); - } - - public Iterable getChanges() { - return changes; - } - - @Override - public boolean setBlockState(BlockPos pos, BlockState state, int i) { - if (pos.getY() < this.pos.getY()) { - return false; - } - if (state.isSolid()) { - recordPos(pos); - } - changes.add(new TemplateFeature.BlockInfo(pos, state)); - return true; - } - - public void placeFeature(Feature feature, BlockPos pos, Random random) { - placeFeature(feature, pos, random, NoFeatureConfig.NO_FEATURE_CONFIG); - } - - public void placeFeature(Feature feature, BlockPos pos, Random random, T config) { - if (getChunkProvider() instanceof ServerChunkProvider) { - ServerChunkProvider chunkProvider = (ServerChunkProvider) getChunkProvider(); - feature.place(this, chunkProvider.getChunkGenerator(), random, pos, config); - } - } - - private void recordPos(BlockPos pos) { - if (pos.getY() > topY) { - topY = pos.getY(); - baseMax.max(pos.subtract(this.pos)); - } else if (pos.getY() == this.pos.getY()) { - baseMin.min(pos.subtract(this.pos)); - } - } - - private static class MutableVec3i { - - private int x, y, z; - - private MutableVec3i(int start) { - x = start; - y = start; - z = start; - } - - private void min(Vec3i vec) { - x = Math.min(x, vec.getX()); - y = Math.min(y, vec.getY()); - z = Math.min(z, vec.getZ()); - } - - private void max(Vec3i vec) { - x = Math.max(x, vec.getX()); - y = Math.max(y, vec.getY()); - z = Math.max(z, vec.getZ()); - } - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/DimensionsPage.java b/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/DimensionsPage.java deleted file mode 100644 index 0fece56..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/DimensionsPage.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.terraforged.mod.gui.page; - -import com.terraforged.mod.TerraWorld; -import com.terraforged.mod.gui.OverlayScreen; -import com.terraforged.mod.gui.element.TerraTextInput; -import com.terraforged.mod.settings.TerraSettings; -import com.terraforged.mod.util.nbt.NBTHelper; -import net.minecraft.client.gui.widget.Widget; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.nbt.StringNBT; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.WorldType; -import net.minecraftforge.registries.ForgeRegistries; - -public class DimensionsPage extends BasePage { - - private final TerraSettings settings; - private final CompoundNBT dimensionSettings; - - public DimensionsPage(TerraSettings settings) { - this.settings = settings; - this.dimensionSettings = NBTHelper.serialize(settings.dimensions); - - CompoundNBT generators = dimensionSettings.getCompound("dimensionGenerators").getCompound("value"); - for (String name : generators.keySet()) { - CompoundNBT setting = generators.getCompound(name); - setting.put("#options", getWorldTypes()); - } - } - - @Override - public String getTitle() { - return "Dimension Settings"; - } - - @Override - public void save() { - NBTHelper.deserialize(dimensionSettings, settings.dimensions); - } - - @Override - public void init(OverlayScreen parent) { - Column left = getColumn(0); - addElements(left.left, left.top, left, dimensionSettings, true, left.scrollPane::addButton, this::update); - } - - @Override - public void onAddWidget(Widget widget) { - if (widget instanceof TerraTextInput) { - TerraTextInput input = (TerraTextInput) widget; - input.setColorValidator(string -> ForgeRegistries.BLOCKS.containsKey(new ResourceLocation(string))); - } - } - - private static ListNBT getWorldTypes() { - ListNBT options = new ListNBT(); - for (WorldType type : WorldType.WORLD_TYPES) { - if (type == null || (type.getId() >= 1 && type.getId() <= 6) || type.getId() == 8) { - continue; - } - if (!TerraWorld.isTerraType(type)) { - options.add(StringNBT.valueOf(type.getName())); - } - } - return options; - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FilterPage.java b/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FilterPage.java deleted file mode 100644 index 9d48767..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FilterPage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.gui.page; - -import com.terraforged.core.settings.Settings; -import com.terraforged.mod.gui.OverlayScreen; -import com.terraforged.mod.gui.preview.PreviewPage; -import com.terraforged.mod.util.nbt.NBTHelper; -import net.minecraft.nbt.CompoundNBT; - -public class FilterPage extends BasePage { - - private final Settings settings; - private final PreviewPage preview; - private final CompoundNBT filterSettings; - - public FilterPage(Settings settings, PreviewPage preview) { - this.settings = settings; - this.preview = preview; - this.filterSettings = NBTHelper.serialize(settings.filters); - } - - @Override - public String getTitle() { - return "Filter Settings"; - } - - @Override - public void save() { - NBTHelper.deserialize(filterSettings, settings.filters); - } - - @Override - public void init(OverlayScreen parent) { - Column column = getColumn(0); - addElements(0, 0, column, filterSettings, true, column.scrollPane::addButton, this::update); - } - - @Override - protected void update() { - super.update(); - preview.apply(settings -> NBTHelper.deserialize(filterSettings, settings.filters)); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/GeneratorPage.java b/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/GeneratorPage.java deleted file mode 100644 index ff979a1..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/GeneratorPage.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.gui.page; - -import com.terraforged.core.settings.Settings; -import com.terraforged.mod.gui.OverlayScreen; -import com.terraforged.mod.gui.preview.PreviewPage; -import com.terraforged.mod.util.nbt.NBTHelper; -import net.minecraft.nbt.CompoundNBT; - -public class GeneratorPage extends BasePage { - - private final Settings settings; - private final PreviewPage preview; - private final CompoundNBT generatorSettings; - - public GeneratorPage(Settings settings, PreviewPage preview) { - this.settings = settings; - this.preview = preview; - this.generatorSettings = NBTHelper.serialize(settings.generator); - } - - @Override - public String getTitle() { - return "Generator Settings"; - } - - @Override - public void save() { - NBTHelper.deserialize(generatorSettings, settings.generator); - } - - @Override - public void init(OverlayScreen parent) { - Column left = getColumn(0); - addElements(left.left, left.top, left, generatorSettings, true, left.scrollPane::addButton, this::update); - } - - protected void update() { - super.update(); - preview.apply(settings -> NBTHelper.deserialize(generatorSettings, settings.generator)); - } -} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java b/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java deleted file mode 100644 index a2a0550..0000000 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * MIT License - * - * Copyright (c) 2020 TerraForged - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.terraforged.mod.util.nbt; - -import com.terraforged.core.util.serialization.serializer.Writer; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.FloatNBT; -import net.minecraft.nbt.INBT; -import net.minecraft.nbt.IntNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.nbt.StringNBT; - -public class NBTWriter implements Writer { - - private final Context root = new Context(null); - - private String name = ""; - private Context context = root; - - public NBTWriter() { - - } - - public INBT root() { - return root.value; - } - - public CompoundNBT compound() { - return (CompoundNBT) root(); - } - - public ListNBT list() { - return (ListNBT) root(); - } - - private NBTWriter begin(INBT value) { - if (root.value == null) { - root.value = value; - context.value = value; - } else { - append(value); - context = new Context(context); - context.value = value; - } - return this; - } - - private NBTWriter append(INBT value) { - if (context.value instanceof CompoundNBT) { - ((CompoundNBT) context.value).put(name, value); - } else if (context.value instanceof ListNBT) { - ((ListNBT) context.value).add(value); - } - return this; - } - - @Override - public NBTWriter name(String name) { - this.name = name; - return this; - } - - @Override - public NBTWriter beginObject() { - return begin(new CompoundNBT()); - } - - @Override - public NBTWriter endObject() { - context = context.parent; - return this; - } - - @Override - public NBTWriter beginArray() { - return begin(new ListNBT()); - } - - @Override - public NBTWriter endArray() { - context = context.parent; - return this; - } - - @Override - public NBTWriter value(String value) { - return append(StringNBT.valueOf(value)); - } - - @Override - public NBTWriter value(float value) { - return append(FloatNBT.valueOf(value)); - } - - @Override - public NBTWriter value(int value) { - return append(IntNBT.valueOf(value)); - } - - private static class Context { - - private final Context parent; - private INBT value; - - private Context(Context root) { - this.parent = root; - } - } -} diff --git a/TerraForgedMod/src/main/resources/assets/terraforged/lang/en_us.json b/TerraForgedMod/src/main/resources/assets/terraforged/lang/en_us.json deleted file mode 100644 index 529f20c..0000000 --- a/TerraForgedMod/src/main/resources/assets/terraforged/lang/en_us.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "generator.terraforged": "TerraForged", - "generator.terratest": "TerraTest", - "biome.terraforged.cold_steppe": "Cold Steppe", - "biome.terraforged.marshland": "Marshland", - "biome.terraforged.savanna_scrub": "Savanna Scrub", - "biome.terraforged.shattered_savanna_scrub": "Shattered Savanna Scrub", - "biome.terraforged.snowy_taiga_scrub": "Snowy Taiga Scrub", - "biome.terraforged.steppe": "Steppe", - "biome.terraforged.taiga_scrub": "Taiga Scrub", - "biome.terraforged.warm_beach": "Warm Beach" -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch_oak.json b/TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch_oak.json deleted file mode 100644 index e9ffca8..0000000 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch_oak.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "biomes": [ - "minecraft:wooded_hills" - ], - "match": [ - [ - "minecraft:birch_log", - "minecraft:birch_leaves", - "minecraft:oak_log", - "minecraft:oak_leaves" - ] - ], - "replace": { - "name": "minecraft:decorated", - "config": { - "feature": { - "name": "minecraft:random_selector", - "config": { - "features": [ - { - "name": "terraforged:birch_forest", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:birch_large", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:oak_forest", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:oak_large", - "config": {}, - "chance": 0.2 - } - ], - "default": { - "name": "terraforged:birch_forest", - "config": {} - } - } - }, - "decorator": { - "name": "minecraft:count_extra_heightmap", - "config": { - "count": 20, - "extra_chance": 0.1, - "extra_count": 1 - } - } - } - } -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/flower_forest.json b/TerraForgedMod/src/main/resources/data/terraforged/features/trees/flower_forest.json deleted file mode 100644 index d399328..0000000 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/flower_forest.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "biomes": [ - "minecraft:flower_forest" - ], - "match": [ - [ - "minecraft:oak_log", - "minecraft:oak_leaves" - ] - ], - "replace": { - "name": "minecraft:decorated", - "config": { - "feature": { - "name": "minecraft:random_selector", - "config": { - "features": [ - { - "name": "terraforged:birch_forest", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:birch_large", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:oak_forest", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:oak_large", - "config": {}, - "chance": 0.2 - } - ], - "default": { - "name": "terraforged:birch_forest", - "config": {} - } - } - }, - "decorator": { - "name": "minecraft:count_extra_heightmap", - "config": { - "count": 2, - "extra_chance": 0.1, - "extra_count": 2 - } - } - } - } -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_edge.json b/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_edge.json deleted file mode 100644 index 638dfc5..0000000 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_edge.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "biomes": [ - "minecraft:jungle_edge", - "minecraft:modified_jungle_edge" - ], - "match": [ - [ - "minecraft:fancy_tree" - ] - ], - "replace": { - "name": "minecraft:decorated", - "config": { - "feature": { - "name": "minecraft:random_selector", - "config": { - "features": [ - { - "name": "terraforged:jungle_small", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:jungle_large", - "config": {}, - "chance": 0.3 - } - ], - "default": { - "name": "terraforged:jungle_small", - "config": {} - } - } - }, - "decorator": { - "name": "minecraft:count_extra_heightmap", - "config": { - "count": 3, - "extra_chance": 0.25, - "extra_count": 1 - } - } - } - } -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_forest.json b/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_forest.json deleted file mode 100644 index dd1ff71..0000000 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_forest.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "biomes": [ - "minecraft:forest" - ], - "match": [ - [ - "minecraft:oak_log", - "minecraft:oak_leaves" - ] - ], - "replace": { - "name": "minecraft:decorated", - "config": { - "feature": { - "name": "minecraft:random_selector", - "config": { - "features": [ - { - "name": "terraforged:oak_forest", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:oak_large", - "config": {}, - "chance": 0.3 - } - ], - "default": { - "name": "terraforged:oak_forest", - "config": {} - } - } - }, - "decorator": { - "name": "minecraft:count_extra_heightmap", - "config": { - "count": 10, - "extra_chance": 0.1, - "extra_count": 2 - } - } - } - } -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/redwood.json b/TerraForgedMod/src/main/resources/data/terraforged/features/trees/redwood.json deleted file mode 100644 index e9fb356..0000000 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/redwood.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "biomes": [ - "minecraft:*" - ], - "match": [ - [ - "minecraft:mega_spruce_tree" - ] - ], - "replace": { - "name": "minecraft:decorated", - "config": { - "feature": { - "name": "minecraft:random_selector", - "config": { - "features": [ - { - "name": "terraforged:redwood_huge", - "config": {}, - "chance": 0.025641026 - }, - { - "name": "terraforged:pine", - "config": {}, - "chance": 0.15 - }, - { - "name": "terraforged:redwood_large", - "config": {}, - "chance": 0.33333334 - } - ], - "default": { - "name": "terraforged:redwood_large", - "config": {} - } - } - }, - "decorator": { - "name": "minecraft:count_extra_heightmap", - "config": { - "count": 10, - "extra_chance": 0.1, - "extra_count": 1 - } - } - } - } -} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt deleted file mode 100644 index 08257a8ab4065cb4e0be67549df6b9e0a3e254e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 275 zcmV+u0qp)CiwFP!000000M(RXj)E`{g@?9?aDn~jLG}=4M`x|s5ThxeSUcOG z;}XfkdwZ%uv1`!_)WkugwRLOYf2OftcUh!GP^cTYx)jF=>_BSy{488d0b$O&dKGe?e?%rlD0 ZUks26OG5U8j!IkiG0)uTKvseU004V+f~)`l diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt deleted file mode 100644 index 48cc4db10b1a38072847cda9b98aff76331c60b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 360 zcmV-u0hj(CiwFP!000000L_){Zi65chL57Py02t^_HP%mi&%CC4ed@-QxyZaCcFBf z9hOmOwnnEWMo)Y=@5|wU89)k2O$(F~GXQv4Li9>Ygr_pEaKq_VzLbsFamLD(kXUAr zy>V6}mpKXrzq3OHk>m}k0I85Vh%3hBu8#z3PEpv@5N~NA+Cc}@g8;5l?=uZ1|9p~P zb0x9rO{@#H*$?MJ7j7IAI-1tSrBZ0}%*FA;csBad{HYk@x8;Nl;a!WF*ciSgEFV@+ zj9HH#2j-PF{&|bcW?iP*Ex)uelaou^NMX_Gi1zRPm;$MpAnLWfLpWX`QQ0Jw*hS|| zU@?Kk1mB#=gpNEmW9JEVK7%0^LmW)x$#Y4IIGEUxC$gA@WA3r#CvoJlnWe*z&DitO zTBe`Wqh&IgN6TbxJX*wHZarEibLY`AnR~@VBL74UL|tLklR)x;T;#0kEPMeV2$xTv G3IG7+tEyB0 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt deleted file mode 100644 index 7385cf36b89a74d8076edc0e8b6f978d7e9af627..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmV-k0ipgMiwFP!000000M(S?PJ=KMh3|R`3?4xL`5-=o@eP)4-ep9fq%AJ->7}qT z>^g>1GbJJAgs=CU-ZsquQb=l1kTH}2K(++_Buaw&GOuW(#MV5Pjov9K%at}%W{^EA zS(7q3=@x#G`wF;G4Yh)VHcmv9RAx6QEt{iaO%2gj6xvSOlbZx^mHSZXAKAN(h1?&G z?rYULtcDEhLT+AXgmCJRVvv0dCr@(pKfV{_(^0r#j>(4HXj`s18$aKRsT60okHIh0!3hRuFg9}xofw!X;N>&1$H0LZ_a_PD@tNhBI^(sc9>W8S w@8#Bo6J9*P_+D=9e4;-XU~GT5&fjUg5s4iUk~dO1msJ<@19120K8Oea0MRj_?f?J) diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt deleted file mode 100644 index b3f643078cb76dd5a06da8081c95da8e486b37b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmV-50m}X#iwFP!000000M(V@PQxG+g>QkbEBfDmK8O!te1nC}yR5O42B=GXdRZ4b zM3~FsHf=)MllyVc2{)u1poXd!En15l0Pg3&o`pnskWGgxE!Or)4rZg3k_%%|a^Npo z^{8!w#=);@+X1tBKqpWb>qXfqZ8wuLYB(q|^iZxvYj&Hq=r;kJ8RODpxm}Lq2Xd=R zdt!_$kL9NrHOxjIGyY6!puIBGeeM>4{X?khW`)I3eP@b@DH05c7!omse+LXr^obc3 zF*L!H8Lu$UEaMe2RmLl1<{2*c$A4YOu!! HHV6O!KE08u diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt deleted file mode 100644 index e741a4e5c25abe938762068aa5a8cdf011b5f3eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 378 zcmV-=0fqh_iwFP!000000L_-|PJ=KMh7Yuif#30m|GW?{!gvP@n`apjC~1pJyn2CI z*40+Wm#sF|P2l|}k2oHH$;EE?}`IJ{;!x_sLLSi06 z{K8p@T&5^$_?2x7ppsWu2bc({f}mhrZn{XYY9IMk3BfwaL^ElNY7)TTsw>GxUQHUT z-qm4|SKoS8|G3v*@>*ljxmadw_14?QX{#{YMOXeWt#ED^2MuAEaBshd>sT^MYxcxYhW8t(hZby!2WJp&<~{;aGC}Is zX85psd{SqViNrSg&Unqx7|+4zd3+1g>S+uy7*FNW80yHQGl9Vn3o~=%(LIM2h8WD; z;+Yy+ktL7G#1_vcbK%g^{aiYkx$K<@GQwH{zt0`Y2P=xOa+R9RFfLZ-mHT z)wxjn(|X82)`p~eZA-xE5z;kd#n`E9CTeTIL;(|hm-vAZBa8?bIiruf!H6KU9LX#K yuXv)*kV!@|hsul*osZZ| zCAN*-eg3x=RxtfH)#5eY^mIzQ?o?=X4flY2%{{f(DF XMVKWlzR*!^+u>DCQR-h_Nd*7^hJJsu diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt deleted file mode 100644 index 811c3adc31ab38e716a4d3930450349c939d5d73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 367 zcmV-#0g(P5iwFP!000000L_*CZh|lr#V>6UVf%ks;*;zlmc4=L^cu;8lD5obPd~sF zYuAEvY9JwS!>{)o&gCNmNFk~C4zn^?j`9-M z%ihBKPOLu8@L(#h33IV^VS<~EiNl5KxfmM9-Ap)9^yS|Ma{Gt!mXE`!g>xgg?!e|Z6f_NBThAz`)$W;D?28hj0A^Ak9a#3~` Nz5&cO`D3%V{cHh_LjjK)f2= zps^)VXWr{m4cwX*JAsm{6Irc|J&uZWdr@iIKz5K7^@~pE76JSyeXR6r@z0ldgZu4> z@K)*F`wa|E1tHvIPvIK31jJk;q73JWdv3&%E%5eXly`-=?!$jz_?z=Mdnp#{!`0I? ze;#hW6ie<#tPzf(fYlH~{cHVL0Bba{?zbN)oWGQH)vUBQsPCS{^CX@palVNs^*k)# zVS%jF%i@tNHt}SUtf^-e$YLH(9>`)I&pJ|P>L~&|zDGpr_{^NjPjn{k27~+q4VAhc OFuwpl+lr)@2LJ%Nd7PU7 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt deleted file mode 100644 index 80c3b2f10d4f06b9198523906418e0f4c8cee2a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmV-!0g?V6iwFP!000000M(Z5Zh|lrh7YuWuCQ|zCDKm89)k2#a5^kW&rRo0s6`cgr_1eaVFS8y%e=v3eJnER9Iw? zy$N2SP&vv5p7V7HREZj!0GU)eh)OQhvX3OMw^3ME5G~kBwv*PVCjlI#-e>wp^15O! z_2;d+!1=Uy@V?@+j{_{|$mv1f9F2+Jjo3t|v$3lk-cp>}gjI_^+*geAw&Y+N=k3X0 zHg=a|n7!&ZF<8eic8X5wr2>N zBP2~S#T0hYUna1az`=wT6Ix85M}r}bJT^luhB%nWqhI>|jJ;@$o^bJbZUa8C&$(<|g=@%`r zHjNB6S~elX4}SUX^Kw`Llu&fKL1wJLt2L-sZ4jPJ-Qv#a1HYJ_j?P-MB}P+0wQ;sX z$2F3N_x99+V%MV=sELEfTkH5ZDYE@ViN1sUpc@(voiH2%_)+!A=^vF39ZOYzzEpR( z-%bhM8oPV{WrRT9J3~;9?Zed^MiC}?+lcE~IIG88$5JQmn;~k&9~jGTB9yQitI+t1 zDnWLZq<s#_+Dm@L7Fh!F{9*s~cUBPI*%j8O|db0&`%nP656K61ts k2}VUeYtJaEKQTaR4B&SO#Rod7Z99I-7xk#oupkBi018@y6aWAK diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt deleted file mode 100644 index d4e55b189e75b16e494cd1f2a2d3074fa67be1bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 413 zcmV;O0b>3iiwFP!000000L_-`Zi6rkgU+vt*fE|K}lGpJ^i2+ zG-SzEbt8aOQHu|sli0C{0U`(snxd2#1Hj`9{1=)b%(EoNC8ulooRwn38Os(zVirUE z%2|P2CMYU+#kM*4l9yNoNQG>IAZJ`|+DNeS5P4+*!J4L`erb!%O8_USx0(J;{^=mk zakXeIyrpdUeuRf6GMZ=}_U_`Rov@qOM=ndzbdQ5dw4vL6=x)TZCiF@;>q>_OIkhWY zosG^`^jr|FFM6C4oq2t#i+)Qon2n<+#t6rj(~{V>ViZT!<|{P`scy^@<^3TQi;3hJ2TOkiGlHcVJ6L8VLXi?28I~4h^FOR zw1~n47A=*T8uIv>pU~h(XJ!U1orx@3>bhc!mdc!2v{dHYqNT3=!lI=zmliFRxiaJl zw6$Lw`~;fk8%rLQxi$FFnLA4!)$_f9nQD0+D#jPdC#nk%>pOw)1Gz|8zFW!{C*aeh H=nen?iSx(y diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt deleted file mode 100644 index d6dc4ac20a459a6115cea164e5ad7b2abb0353cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmV;d0#p4TiwFP!000000Iir?Zrd;rMJbBpQ2H*=b@chsMHJmZp}I^V#IX!Z2->co z%dX^#hQVCTj8O+5kQhgIF6TiyYK>_O9lL#+rqmi^C>r;UQ0( z@4oJbAFXM>oQ7jMO??_?visSOrut<}e(Lqhr&9Nv#^S;Fy&tFUuuG#Da|p-}b}qaa=m(Ph;xiFxK<0%kt*mkFSlN zWu|og>m^eOOqiFQmlJfXpyO61Fic+dim8AfiHQov=6F|(1^X(Q(sKk%T`&z`Nt5??X3O|8i9AHrYNKDqDE5-wzg{v4pmp)@^;Q&*{@(P`xU`P=wDs(P6 zVsso}(40y-LBWtBR#fQN>|2=kk||>mV7Bt?ggKS`WY3<_iGV@#<%+o|bu3`Yebs3G1Pd6#tP2G87?=>W6khtnazY}K7R55u}F)2nV} zxcTycLHm*zQpB<=!_A-rOc~27m;e}53rQ#Y@l2k*f(d}x$|0w7(NfejDEx5qMG7V= zV&xo?B8MCk0JG(po585i$$lc!s{|O-Kctwil0kJR#q5*}%Cp1-z@R&YgkE)kLGKDA z=8|hgp1D5sfI&5tbaE_G?2BUvFlb*p6#xJL9aXjf diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt deleted file mode 100644 index d6dc4ac20a459a6115cea164e5ad7b2abb0353cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmV;d0#p4TiwFP!000000Iir?Zrd;rMJbBpQ2H*=b@chsMHJmZp}I^V#IX!Z2->co z%dX^#hQVCTj8O+5kQhgIF6TiyYK>_O9lL#+rqmi^C>r;UQ0( z@4oJbAFXM>oQ7jMO??_?visSOrut<}e(Lqhr&9Nv#^S;Fy&tFUuuG#Da|p-}b}qaa=m(Ph;xiFxK<0%kt*mkFSlN zWu|og>m^eOOqiFQmlJfXpyO61Fic+dim8AfiHQov=6F|(1^X(Q(sKk%T`&z`Nt5??X3O|8i9AHrYNKDqDE5-wzg{v4pmp)@^;Q&*{@(P`xU`P=wDs(P6 zVsso}(40y-LBWtBR#fQN>|2=kk||>mV7Bt?ggKS`WY3<_iGV@#<%+o|bu3`Yebs3G1Pd6#tP2G87?=>W6khtnazY}K7R55u}F)2nV} zxcTycLHm*zQpB<=!_A-rOc~27m;e}53rQ#Y@l2k*f(d}x$|0w7(NfejDEx5qMG7V= zV&xo?B8MCk0JG(po585i$$lc!s{|O-Kctwil0kJR#q5*}%Cp1-z@R&YgkE)kLGKDA z=8|hgp1D5sfI&5tbaE_G?2BUvFlb*p6#xJL9aXjf diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt deleted file mode 100644 index 17e91d13c9cc38b9cb1785aa777eff917f0709e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 500 zcmVgiwFP!000000Ik;DYTG~%1>lkPPttWD&(XBK$wP$F7YG|=6GR=$ctvRY z^wlO_2$Q4PHMPNDn@>lx((K3sQBUsRcVSt=Kt#49edk{SUA;{EFdqHWa_dJwPX2y3 zKMyqgIL?P~T&56L>3>g=nmA>%o4*Z4#d$JF^dHfaAjs4k^I?Pe6AJf~=`%5b_Ys?bfzI`@Lg=s5{ zsxUg8?}KTW(WiGS7z0epj0Hw*M0p_MvktiM_QN3S%T3g zV+E7z{@5Funf7E_!6;x1sD~TgV>w3&#sb6p&{gDg!0?*$+O=R5Flg^^gL;)4)MMQ6 zwRaWufdtrogX<$&#mvUT1J-KEpyc)Q24?FTO0&*Z-!7Fcz4t`&F7hC1Zfusz;hF`CQUWFuI_OU9m&!}~|a>2Js=f%N~pSL9yPfB1R-wzPj|hU&|j4FCXJQT@dL diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt deleted file mode 100644 index c80c016b3ba79e3a6217767ad5d74ff4485cadf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 567 zcmV-70?7RziwFP!000000Iio>Zrd;rMMvUO`YzCQ^p%e+BFGL3R%HUAj%8Rv&}Q|K zT(bz6%i$Qc0l~6yba;nPs3+>k9l|ayOYDirdD3^`Dbk0haUX|ccvx=35QZ^)-%XD_ z_4mi=5Rc0k=ame<$C;WxMCqxI@1Kg{InLRG{^vL^VLwD_zIf`_|L66OxL?RTgxwtf zNBH^L!cW&0e!aHv+qH!^SlE&Mv73fp^EOi+J5q;fR_pC{8T$J%ip;86;_26WrV%i0 zh0*D|;!y&Ru6XR3u@%p$y^6;OJXYYb70-4#I^FzZ8qikGw4e`bp7zW%45I*(x1|B2 z3VAq>7368oOe?6XW!h4J$un!fpt)M}SV10lL0w8PUP>@tN|2dr%Ly0{7+o0Cw`{Rljku4#sa1^R}C|Nyui~5@}&N; zf^oNuM+2s`|5&Cj2bg?M@B&Yo8;+@~1x#tZJHdK)OdbQ6ye=p3ctM^{P*(DpvM9SFT5_q@HgPWw|=zXD^FnuOmF F005Y;9EAV? diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt deleted file mode 100644 index de1dc6d918497fb24e30b430a2d26fa3ca82f4ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 530 zcmV+t0`2`DiwFP!000000IiqnPUA2Tg(vYf`MuIU$6nwE4}o}sMc%AgMUwzo6X!YhMC3f_>+lfi%fq;h!#>>2S78Xl7;ZPy z-=6xL{j`hwd5mcx!_%0kc_zxEzJ44P!(&Wrp#L+bIc$eW&84S)d7hRBaXXW_3!4=G zNATj@fv+N_Av0(6N}jghWdI!u z!;E>;N4PY4;lo$heS%FzQUnL#?i98izuz({+w##q410gMN{I)UM9n(I^Q zQA%Le&P9nafR_~*skhX0Jdh{v9|zQ@)T0!jqXEVW%-VkTfR|^zMW^v4W~hHFWUt6Q U9{zJp+ha-o0nv0<*P9Oj09kzrU;qFB diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt deleted file mode 100644 index fbfe087ef9f3bfbf4c0e366a9d5e658b430b2e67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 510 zcmVCj?*v@2H;72N^*_Fb8x!hAy(XQjZE;OXuC~SN2`UW zCn+^Tvwy~eXr)SR_2r+jW4rA@)KfUcLt2(J5Rvc5-o?j6uO6pk8qe{5`54DIPVviO z{yxy~={%p(d6`mPWqh78H9v^TRj*%OmEu#%?85Hbl$UrM6E$x-8rIMA`awD_%b2sbJsVbwo3>;L#skxWT2?VX+!$s8FnhJ6 zad}|SJa1Vf)H1+WW}2&Mgq#)_K6azXvB2;PEpG%asn`X4m)7@9QMHQ zIV|(z6#G;%78vwhzzsUbYB@pCPY2B28RZq{p=2yDduzih)`pZ56#aC-@U>BT3WBk~ zpzkJb_Ra(;Cn)+UwYthZz5FhzoORrwvv)JKv$tjpFlg^^gXXzrNx1jmd!h}shhZ0&CH6$rcH}+}50PF!jQhAf4tL9^+wr*l z@pU(S@2UTCoDT80jB#GU;nz4*^P4DN^yb+`ad?a~yRQ2-&dadhMrz)6)UW5~^+en+ z|vVi`Y|1j{=J+fzsfA} z>DzOrQ7}fqSOwz*CLKP#3p!q*6O!*UrYSH|t;BetRx9Y36Lap_Fs3;%zQP#5*n%Hl z>D>XQIN*mf+z*`?Q_*PvgVu*LXni^*4bA47{H*J z=M3L>ukaH9Q|ikp_OzA@1DMiY)R>^Cl|6ffXDO$gDb1mjQ_ht3tEQ7Zhe}@tFuX4d z7~Yoy4EK|3wTk;jtMJnaeQl_oQwtc>m!v}{rk0BaFlc@_gXV`bXnrIeukaII&{r+* zLBX_u@r7EooLaz?_OzCr02sbLt-??CT+5dMOljY1`Er0k_YFxWDEws4QcgKj+KX1W zZ=^?E={cbnX4L=&dFBlAEa_xFwRtvxLG#QRUdt&Muc#GX;91HbXG)%HIrR#ipzzZI zrqq}8JII;RY}E4Q6*@uTC)cXwD;-xtb{t^P`dkV5vVcLJB^?hK?kCr(&9hT59x$a^ zwHb4OK^c^E0${kGTuYk6YsDH~3%xr9;{g*2I=pu`kAGr@(nH;=_1IWyAJhLH)BY(w Ne*wOe3AGp#000wiITHW? diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt deleted file mode 100644 index e20cd288b3cbedaa13f39a2835e0ebbd2d1ec49c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 550 zcmV+>0@?i^iwFP!000000IiqXYTG~%hR52YRQIaT_vq;+4-xtXMNv1YsACyRgtSi| zDV4xX{+%7D4aNsPeYe`uOIe)IOz=T^E1$DA$&6iOy7BHw@C68Bl0$_OT zTU@1i=L|Z-OCG221i< zS@L*=Cjf@`&$geS=&{m0_Z_P{@^FTGyuxEvMyi(u49auK;}xE5Eh*0qFuB+@o>IN` oidyUy`Pqa0*s=ecE)VDT%d4UAwERyTj;|y30s@ir`1lV10Bdy==>Px# diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt deleted file mode 100644 index e14b0e1e4df641f6ee6622419920bd4214a4c4de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmV-H0>1qpiwFP!000000IiqZZrd;ng=tHa5~tnGfWAk6wu?Q)us0aoOwEj@aS$2B zwx^%fSr=m|ibWH^h+}*@Jfe=Gqyt!kKlb}DO`!t-zXJQUe+uyNX*h)KsehQh+z+Si z&+q$j*FpE~G#W5~>%G9^FKzCecI&Vmie5B1YB47Xl2#xhLF zv&1+>t?XIKp<$SkXNf@tlWRGl&z50IwQ6TdV!Ti*>0DIuY!^n#Aulrh zE~NcPeA(}Y^dEY!PptR$#CmT|toQE3dhfB`io(V2u=zgBBl3Gi?)ose>F4}q`up*Y zc#;{@?Z1aiV_;eX;|z>9Fl=Cgfr%ByFAOV8Ffj93-Td3YX!QiZG=gypQ>(eg@a>gJ zUpdP!OnZlE3p%Z$6CRAf@5lf8SzR|^=a;{a3Yg~sHwSYaGs(7xAn z0$|YY)XvH^2gCCTNuIn9}@cI=SX(*yX6qPXG+s_a}5e!{u24Flbh1rd4*? z0Y>V0z@T182KAz*6Akq=3scJ|$)Jpq4C<+5O8wF@Dj0O4p`Om*D|^>+%mJq4U1I`Z zO1?CmTr*d4Loz5gYC3Gt34lSlQPasaYdPitBm2b$odB3pFKYQbGg^*$z{nj8fI;4$ z((RvrOaR^`BhSh@jlwWsP(Igm+`?$N>H&j#DjC$%nohegS{^#Upq@$w?T%#7?$mUm zp`Pr^8+>V5=M4-4rqm0KiH5T}gRktJ6&(kd(tc?=Y|sgSLD^E%$u(SIW@* cV(|I&?Ht9M`Mv#NKaVB-0X$PWCD<7N04yqyMF0Q* diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt deleted file mode 100644 index 3ecd569608eff29c7bcb542f1fc1cd00eab2d6f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmV-l0igaLiwFP!000000IikVPJ}QJh6mbmx;61NjE5^9!uSTJi?iCu0-?=DeR^S) z4Vj%V-MAzq(0u(m^Or*fP(t3@21CFK089b;$?g!YcCN*Gu-ovsaYOz7(sXYXRL?`# z;}9JB5wxGqL-GYMPr5#tgm#af%qw1<54NollG_5Raomps*ak3L+j#tk@BYHRhYS1e zcwY(Grs?VrKW)KH399eB8ZW0)!|!1fm{Ak(aCgci5lkA%WD6!COggg*CS^R7QG_uO zo+B&Ntc02k!%$Clh9?*D(WEcU^hFtNtys@mK89iFTC-=ZcOAhPhT(FK^+-9JhCCv)2Q4liIoUR!`mgOK;vJ$mhw7 zG&xOn2GyswP<;V}L$_y#NFB&V=bBe-ofb?Ov@7sBU1_!uPy`_Kn9ko#S3Yc7$NHD2B^QaznAuBg85$<-v@I)3y w^`x?5=2F&@M-(!cso67iiKVlfnV~7O+08M0za{vGU diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt deleted file mode 100644 index 28c32ab03a33554bb1ed9b66cd3b2ef7af6f06a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 608 zcmV-m0-yaKiwFP!000000IiqnZqq;zg(vaO?%IW4NW2H-@`Hy!ya95<7Oc8S6k8SW z^w`B)MbqP%twMDqk=&Q|KGB=|Zl89i_ICVy)17ud zzx9V74K-g+hhsX8T^c5^{nZV$`Aw8>di(6A)IOv^+!w!h!`SY3i8j}fn(6mp`XTK{ z;@h?#(tqf^yRhE-3+sKnu->N&>wUm_HTj$Vu)7=Pi1am8$HP!fALond--|2aNoGus z-<~s@>2d{(rL!&2*%~@-VZ5PJ8MWN#atDbiwo!SN+@0ET6V31$l@bsx(fsVC4mQJn}j2ub^ z=>)Nc4y>VMq)q?~%4#U^LNc;e1Pq!zkiJhDFfu=(K<6n#1^sBA@(Xk{-?L6UV;Fcb zuj5vkJ+Jk-rylep8MIF&BYO@7Ozy`i{V-tAStl8kLrW(DX02yd_7?+YZGEigPBil4 z0kh_NDDYi7pEDB+{EEi;Q;V#k*=r+*9x&(}lMM2-7QUm|C4=^%-Z^B84CqE)xvniF9#Tu4auM!N@mTkVC3gY_>O8_8D3-^YcER%J)0~Y uw=mi|d%&Q6UKx4LjO@n^-Jf)R_`IIqD+&+uf9=EmQR*+xIe%u15dZ)y_A6Zg diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt deleted file mode 100644 index 65987716063c72a48ce7063913bddf4eda2f0844..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 302 zcmV+}0nz>+iwFQzRCQhe|E-hTO2jY_hW~C3J=_X{kKyUYhY;UDvUOI2-L^DgQJ>zl zZefkHZNU}-N%-cQpJ`hFInvftNFp6Q~ zUV4EiWf*ZLkDg!@!^FMx0*@Z*!v2JjOrA|NLv_Y8#iR@q_Yy}&O?V{3aPx^7Za#CK zF^^s_A3c#-F$|Yk%*;@Z>`bqi>3d0Mzi5QAqbwCj5B>k!)WhfU4dF=i+mHnS0FP&u Aj{pDw diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt deleted file mode 100644 index 135d30561a2b3e32152048b672ec65fb19908ae5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmV-C0mJ?uiwFR}RCQhe|E-kUPJ}QJhKKC|=&gx&K7^+mAHw(sri-)MEK3P(HtN$0 z2np8N(&&;9O7ro}%-;kBP(t478ofsa0I~r7s1FF22h(8H>79Srnyz|#u2CP+DNs+H zZL#wPT>-_5ab7nSLUvbx>i1p0fsF^T)3rl@Kl`rZzKdTz`x?l&em4%XkAF0AbLOFL z&+NOWeI>|kZL7T-j`XSo)>_B<<#0>*zBmKXYdnr`KN&tTV!>nqBM4@5!Xp<9JK>R$ zS~9`I$M5>}%3N76J16=HnXr~j@UV#y5rz{Cl~2e}`K)>7S~6kwSk5xhvspO{HZjW# z1<`ZJgdRaKVLvj#GuMipmmnA_pHxpQLq0zv`3Qoc@?k_j+?h|Dp?oTsGsus_|HL-q OF@FI@_Q)b21^@t7DU~w- diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt deleted file mode 100644 index 6499e1c02cbc89241c8e4f46892c768f5ca71bb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 439 zcmV;o0Z9HIiwFP!000000IinYPQx$^h2180e{PX@5B_er;{_0JfVvT&qHCw7nt-RL z9V?nVH?hPfP1~w3$LGZE(h{J6Y+E&M7+eVel!JY&HV!T}b?erB^*Y?I>VEzH+;ndx zluv!Pb^TB~KZ4a~?IHOBm=|51EOOP(dA2Tpsr^v3YX`|q4&`{=j~84!0KQg@cmL44 zJ+t23nf0#DtamNz6+o+|TYvber4I#|ZRgGSb$VO)eOUuI$_#G*>y$|pOsZf^gdu@R z7?U18@rX$mYS9s681v^lpo0Qq1<#y8!SmizAQuV@-=9pOGv^BJGYZU7F006e0Y6s3 zkb;@DNKuOdJ)QHX5gpF(>?knO9>#Ri17j4mLbE{v!~JB6TC<H_Ae!r zk3+w8!`L`Kfz^BCA^QLblP-=XxoYP;nP;CHKUQ7sAiJ?pPVfEn!gV9)b=7+J554OX z>s_8$@AkxcSG-;UX4Urfo1Y`SFCgFcKA(Qh!@$p_bI_B_=)RwhnM`1C8fVi`5k~JB zX)TG-`+I)CWQ4H{b4C~y?gvcH_>mZ7m?h7#eFZ-zvX)L@f@eHn)PiS>)KCXcks2by zP(PMoG_!Xl)LAnO)iDV=$S^buo1hbX>jlb7*x7;%!_~(KdFcekFbtO|Ww=aJb)-x&;oG4Mw|69dxGX5cWkDIPe+kdW zLq06v?}q)HUnlwg`jYRiFZuEMlAmzN4TNv|X}g@XSD7V0 zefyX33a09Kg$~CQolfCLVycehM`DVOQTUOVsw4T47+2o~9f^5nFPM&qC3%(@S1*PM z3dWxqE|xhnLC|^H>kGypekA5Oe?_cI#uBkOCL&Dh$J9My7>_WH@WU|?VOq~n<6SVm zVLF7N^72e9tI+WXgY{v{P`Pt{lEP2jpTIC3!nCmr!nB^PLMJG6;tTvlMZKbMzKW-g zVI0D=J?0T6Ap2Yx!{``Qzq1DRex-P`Pu@ z8&RQC^Wx^AQ!pN3s9ueVdTDf$aK4I`G{;(|ozK-1H(MOSVEfZDlpl_X2t#@1&bvbx z?EWR`1O*cnu@b_xd6_fA%_ys29Kulb;^szBFi{aJDLmKQx!Gb7hRU7O@d!iZEV(W(C8%L?4;%lVxC(DJEuuF7Y<=s9k0*{3a0w;Oe}{mRPJ2Q2L)4O lasBKOrs%kN{Fy7Xsh5TLQ2wWy4p46UzX3Eu%}2r%003oeLCpXF diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt deleted file mode 100644 index bcd26353331cf3903c2b91c57d68486742deceec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 711 zcmV;&0yzC2iwFP!000000IisBj?*v@#qIb{((oOLW3cdvLm+Oj3SBR%+HI;PS^-Dl zv@|8ImeI4{AhuGaHu~kwjOUG=wl`*D+S71I^PGBPOz4dNJUk`y_Gx!a+w<@^e|i|s z`}=X&-ygSD}o#$GU1FwM%?3gZCNfP9!v1dJ0*tB93zZYqoejEv!msZ@c zB4AK2m`<}YY~Ce<`o(ktU`ln>m=-X;P!~G~C4**%=>)(aZ%78s#r3&FvCg%<44|6`PVtrbLH)=k#*XZ0El0oat7_W$BR;Jc>3mDW3$)H{^9k0kI07mvJ z*H!b61&qwO0Sx->z;wJKp8%LrFW5dNnNly4Y>$!*>V;NE_RCMZpXuf1^JW2^X`h$>c*o;4&EL1<^*nPI008RFT7Uom diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt deleted file mode 100644 index 3d5c4a800adfb7307f130ff76c259f66ed5469f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oSliwFP!000000Iio{Z__XkhA(k!C*eC1KZC)i{fLQwFqzInQM;yUqG|B! ziAN0Obn$zIRjSlhPo8^yKBsL@)R8}hL!9T>6On7FxeHH`-aie;xI2f(`Su~4_xEGi z-ygjm+9HiuZJ~c7tI`B-~G*4 z1(Q8a;VCi6Qz`NwCVNmG#3WCx$b*>dL3t4Ko4sHvp%!PPT8POW)SuU9fvHyp)k2KD z!c)pzXV(Q&3m(o$c{pPjQ)RADs}>mUF$$&;n61nuCTG6vVY89h71m`GOd~LST~@*5 z%wCb%D>8dUpS_~bC6BuzPpjx*tLS0L;{-> zndi*bexZ3rO!lA|LyQ*~E7a=PjB$@ynHroO&PeM*j8oLgdC+WdMw(T`I7O{`Wzcsw zXQb~+&Pel&JULJ4US|YmtB2_Ka|h-yd3w-8voh$v181Z?)q42an`!tFFBkPLfrk8Z T`tLs;(=nl+RRO*c!w~=g1Jfew diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt deleted file mode 100644 index f7a72fc9edc7aeb623552f856b7a3b22e209f96d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmV;319$u%iwFP!000000Iiv8Zrd;rgeg&^9!>hQK#$SKuO6c44FWY`3d4?VSVGYD zp1n`4L>r`wA!mcefMLh@G#u`W5;8c~yY@Kl(mbcZITt$Dd>!wSdv~|lr|Z*rJAb(u zPur`*xV_pPehhB-b~+r>Y2Kvi%#J@dldFC?C)d44*QN13P3qF_W;4y>{yMqpL+6I` z@6-8*w4YtL9d}duKgo};FZt>9B|l@y-o@{`!}WGrGV-T){&<-D`Rnp-+~ce9E}UiN z^zhfeOfWE_6AU^fX3?n(ei$P<%nxH0o!a1sF`~o#Fs6}DqQe-`VSX4RI+5r+a0Z5X zZVa9oBRUq(&zTA^f$S>+CZ|){djyQuX#rC!rUQ%z@d<`FYexHtfYE+hz-T`mV493) zmQ&5-JV%4)Snw=5ZGj0Z=SVIVrXuyD8SOb57+I?(G1Lr-A!9^`^$ufN!05F^tJD_( zFu8rP9%O6PQXd7z14gga045hh)`ObSbts-oz2gCcW-ntRV6-3MT0?wFjOcWvFP0dU z`m|n|=l!K;lm`szcg>($WjfKI(*j1vr!(lt-fNOC&E(?D<_6P=2Avi#x(+*oPXB^^ zd4p#*>ok+gS7|NrQ<@u3bAj|SW1f7IK4nZWFtV1VmrG1|flg1(cg9H0*i2wd1PtnT z#?&jrdRa3lK8y(lCISZaGGjW!TC(?2?|8tVdS*Jopc4UuW&+dc41Q$qrF$C>7&H@@ zPBbtrV9>LSW^%P!x{qoBlha}IkTC%;x%y%AP&4R0is{H&Y#wSRm(!9?3m7yr7p6DN zgwkA%?(u9c^}C$ktWOye0fTCc>C`Jzs(B9>lvAb?U$9oGcZ6Ym!I%J;+*+)j850al z1PnUkdPDCpX36`YY6CqxXa?OUFdbQo%}mXpy)&Hvn4BN>EUX!nccv2ngP!9CLmg@c z)jZP)fXVHh)x2hMI_#cSGsyEBl2gAjEMJ;I`O*xU^P16qs+B3lxdsf%yJk?{nNBeH ziGb02cPmrMdj%Nnrv?mqj$=9jFxs>DVe?Qk$nyoM9}gH*hfF5`2JP#@P-B`wHKrL< zV@xL){D|jL{nUWTd1f=px>l(+ypg#iIc)%g&Vox4Lk}3Vccv2ngU;nk62k^Ci%v6b eey8UL!Q182yY_zhfAL}eVEZrjfO#T(4CC diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt deleted file mode 100644 index a20faf154c700fc34f84251b381959a317e80176..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 798 zcmV+(1L6E1iwFP!000000IiwpYTG~%g;(0E)c=J(Mz25m5T$Pr)MQhP9m`lEw0)(% zWWA{t+~MrZKphAq=JS~|JF`b78I2iCJWYqZu6Z=Z#AMu;=_#AnPrGBjKTnVA=ZERM zzniE1-C_Pdn(^y-KIQYe%gcqGe(V<0{WPY&?+toio}TkU-kKhE%Q_wJv+3R@GhSX_ zE-&QcYW(ALSn~f#zPr8T``b%?xV_}Z+e?1Jl7k7~4)gtfDSPvKF!nSr_VQ!-cINMw zv&LU!*8K9@zl>KfRmUrIIHu@y3O^E4btFF;rWb12jgk727_Vfk!jDzzXqdn-Ve8Eb zI!@u)Df~FWPps#7#dL&8fayUkPx_)d0Wd8;9Fr8a2Eb6yeLW-L3?(K2hWd#LCIP19 zS(-a#TC?DoS}QP&S1P{?+GxjaXwOJQik^4D|9SiXkQL6D90q7 zpzsqFI<D0PZ&E?4`F>6y7(z@Y4qbdti4*%&DgDbt#} zl!uf-c}SVo`EWW>p;P;kvW_yXeU?5OQ>L{W98>*ppJ^RnJn&rhgUieS7?iz*;d0C> z7zY^i9Hb0-4pIhXf}~UX;_}A=rqvh6ctx!M7_{?}PPZ{!wm87h{qcZl?GKkxQK4ft zM*7@B8FZH=9SazAzbMn1X<*KGT_Oy{n#KylfA7a~huK&ric? z_c#u_$Nl)dH~rVsc+97Ho2N57{Mb&W`Dsjf?k##Q53hM5kEW;XG!KVOHqApa{rU6h z{6Rj<#y=1HDgU43hx<#uzrW; zYy4Se&X>RbWxRqZI$oi}F^f*4@FOurNAe>vi%zRpt5vKeF|Pa;bgZCLv?R|G<8NR% zKVfBppmW(DS4=~gw#@8`X+d3-p*kKg7I>C)qQXy8X3sD!VCY&_q2mGLDs{C??NQ+; z-B6ch*7AU%dm{p-wl^G8y9G>bA975YsaN>%Ozjph)N@j-Wme|;eEEv!pqN)s?8Cs+ zT6pRNPifg6io5WWw-+j%7lgCGSdPE-363EcL8P4 zT_EWcKU|JEz@T#>=>&yN1PnUMm+uOSK6Clw6gpm^6BJBTtksnBbH#*8?cDcg3z*t| z<`@r{TJ2npMTJgM_$jqVraulav_Bp&==&jMYBQB`bz!9ZS?X^E&y+#=voKb%7MD>D zFzCEf2Ay|Fr}*JA!2t&KS<(p#ozg?E=plEOokGVebb^A3H+bf9!zq{m7_>J!VeW2a poX{W2p#EreXn)+a{gn&UudmLU_`3XGdOTcg{{h{6>{!hh0017aZ}0#B diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt deleted file mode 100644 index aca73e633ded916d9876d50cb8405ec942fe8677..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 696 zcmV;p0!RHHiwFP!000000Iis9Zqq;zhS%PYS^EG;90Lmd(L*3^P?>a#qNH&YTNQ8y z4ozaRRT#ZHI}xd5sg0gI^X{x?ZM8S1GqfMJX`WMWjG<`Um*FLucQ5N*S{;Vx`Qd3e zY#zs9^SB+q_on}P829NguhVp7hac<7G(U~W-+Pa~mxk9gv9HFb^)wH=RWi+8H2v}O z>G(m~&Bi|u+bR8@^5gB5A8xPwbbICJ+bi#}vNPe^c3f?y(|z;1Gj=~t_W0}Ra^~-k zx5gheb6WoTm+=ZFdxF9vF(*%>$Wvpor&YAt(q!8E|L^jcsXU|O(t&RE9K6}7D3@qj@+ta%79d|eSRJae1({(^CZT24{R z3ALKMexX(in9{yW9uFAaX95iGa|8@ud#A{p*A)a00fuLefZ>^QpGm0I0)~4mU`lf; zd4eJjDLhf($!m{_y@-Ox0*2>t3XfOhA%!Pr?iA;b#Dw$J2(y#9wlZIw;h6(q(AsOY z+B0JnnWeMN0S4_CXVCpz^SnI^6?vp{)dQxKNAkSQp^(P|2Aw}OPu{N}FcvU8vr~8o zFzDQ<)#|RuTs!MH!#z>Kl)rT3_yUWndu(}kR@`GI(nWN)F7<{=(lga?6-!sF)Ndg0V8Yk&xtMp)+kM%b#>e@~!+3hS zKa5ZJyTgyQS${hnj^#9O%XDVPpWDgUU&gfi-lO}<_);cv>+rCh=5fC%#@-EPeg1wr ze^K_ciI3xMD*q?>@$Dr)yuIY7x0n2kC08bW-yJqjQyuc3mGQ^JV3|$*7XU@kQU}#-lp_3F$1`P7Ci0rcAHT zl8;HTT0WAuNK61sudb|E^PEoOBp;&;%BS|o2(c<7oyRECi)Dq{B^|pkj;Y-N2F;W* z$j2x{bB=&PYgN+8ihRt%c&2s>7_>K9bi_ zrnfIRrp^7@$I!EYGQEAlo!J6ldO366n-n@N=gidQ0fWvzltE`>%JlX-=c{eKa_6xK z7_?R^!}*v844M~Z(7Y&v<|XOah2i$8S1=JUz5a0f)B~p1A8s!vz@Ytg`OPEjFUp|j zj-(S6I!U3E0fT;nT+W(`{z$&DQp}w)s6Q)VUI8$)uBgyS3Y`{<>tO^;jTNTt?{ZyK a{oi%%O@68W%^vob^8W%`+@(K$7XSd43~(3# diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt deleted file mode 100644 index 25bfaa957b929ef9df7ed1f32903e16a2b65bc60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmV;10eSu(iwFP!000000IidKZi6rk#SL-7#{nko7+d?-4l(TpRo12xDg{KMYTM}t zElg|Vm~<*qgo1u~evTg{Kml2&YvY_L0YH{ezV&TqdRG~nL%yr5)6LdEvdW8RUfT@2qyY6^x7&jq=e90Dbgi9_D7ZYS06Exk z=DfRR#Ked{OyV(;U{auKaXJ~n_~Gf}#E|p9$R$ zmmegU(7ZTC-B2qgV;qBU`8T+1D1t%aeo}9yp<3MBWdx%lYGnlDdrqe%Bl_a9fdmus kyp*xjo4fA^=l6n+Sm+B0hRRQ@&b4Rw0V?HBR~rcc00>gD(*OVf diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt deleted file mode 100644 index 88b159bc3fc9d971675049959d992e7bd454469d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 401 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 w?yQ1Ff$HW-#37CL@5v$yA$ z&>_CwqFHDsG>(A-M{^yP|M%X*J1X@J^%D?{+FA}Hy7g%7ppfs!IF|$ihq~j zVP%I{w<#VgRNd15Inu}U(y?7DFX|)q#}TWSemY-omY1)_F#9}(Vf+2{_8a5n26bNi zvu(!ZyK$`uesL5*qZN%3z1HkrC)?M{?dz-w@!d{sb-8^v%c1}AV)g3R_4fKR`!k2;YPGIE(ucc$ zeY0)V&2lr|zT0P_gXszrC(JDHSW{*$#L}2Vm`2DaIr2%4d^9Ez2J@-0@`PzgteKN}*nWN6gNcmWGMh5e#I$E9kTW!70m9c7QF5G=N@5r$FAaeptTk}?Wxg!ko zyv0NZlL&)-QS;IEy(f&6kJZb`*!RBp%-Szx*xD^769)aW&gkc^V93Df4dCX!W zVIByvteJp}6wC6D#nk#}XF*38DQD~4K?d&|HJ`!gL1d);(sbI}weI@|d$}VFi-ioH z1<|3C984w*J1ZC9Lup->=aFH4UVz8gy%!nOiG-2rW6eWk*gRYqUX6s2^3inaUQB)X zP^h8i)#zYSxO)`XDzRc=I){$NWWwOwXbaODy^IX=p`{ZYI?2IgN34M`xb}HrroHn> zsE^fO$gr~j8EH>7CKE>5Q|oN9nB-tGVc2t)KXfvuK49nTlsj;j%hKv+T(@74U z>|o}Fnfm96khA8)x_0aAwwR_cmVYcJ9>8e#!}d1EeUGtwFEUu4rZCnyhz#=&GE&ak zxziDb%@$-Z)~qm7Z#*R)L*|)KAMH%3v67-QCk*N|gkgTRbZRW^Ue^#t+Ar&Klcf_0 z!}{w%(C>#mVWe0Zv-8+P!>jYcOg;9T_z)T9!-wD>)R_|oz1k24Jyv5S!}G{6&m+TT zf~8aQ$wprw!}y)zu3qn(5E!f5kn zR+wz`4l*x@H;}<+1wCQdebr(zVWhQdGodF8>p^6soHd>7(5d-Yo<~OVp{A1$(6M^w zaoE4pvb8^k-ocp=3)3t6l?a16nK0|#CHec!kz?3l*r9c0){uymTjXrDb>!m!Vb z$gmn(I?<8OyfB^OpN25(zJZKXXYKQH@6d^kd}_|x+-M2I?nub6JCdan9r+{&lL>=& zfSR*5$9lrBxrz*%8kEsi_0jsGBaD=@)yv4R z=Qb8obJp%89bu$B)pR0Z*vzzavO}k?%ldl>WTd{Z{ss>j%sDx9vO{MejI?%Zt|G(c zs-+VN!{(u-lN~yBUDgaoM%q(NCpvTzVc4ACG1{E(2_yB6rjrOGt^L$7TTYFc@GR`l zXS}z>!c6DSOOnry(Rw)&hRtV7r{-)uJ4J@=1u|@oSvuLF(-y{hE{Y63`|2G!kuYqI zSvuLFQ**YSRU#wpg>@f82J4d@I)fvh8cXZbOc=JV=RyB$o(RJ{{~Y#$JwHT7%13+d umk!XeYKRQxoDa~^>bzrK80(6K(VpQa!r(m22k4yaG2t)#`InX^LjVAir?kfa diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt deleted file mode 100644 index a9068dc7c47322af4141a08ea3a5a8b15ac77c28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2371 zcmX9O8_Od$r}HrBl2scZ?5Q3 zCcB`{A$X;KMLC{`nyjsr^aZa@eO{D}e@?ve!=_->$oSRTW{mtnUY4Sczd8}TBA4C5 z#OFQk^Th;zl6@Xpn3-Dqte%-|ukUSNQmzhqH>s2}Q*)CS*7&lX>1j;xFEMK>A$wRo zf1UirXidQ>vwUDQ7CE;1^}$$6^2H{{71I0y#^dM9?Ct5W$_a4PQyEhkdA!16U@h#7 zN#L9Gh@B-HrQ5$byOao*wmTV)ow4v!mDy#*DCYg83e|IkSymZr=HTj5qlcVfc{~2( zT*08zS6R68*P(C*fAI78bbQ;pZSgmwYKPwo8Cg>Yqly{Hy%4(!AdT9HkwRxBG8;Vck!a+okiIvTy7$Z8WKAmQEIfB0(2LcvrknMrX@MR;^@Lfsn`;rq+TmEA@hAdj8OF>OFKUytz1`0(Xaf4M+0u-sI`+BTX?)*`b$t zX*Z8$Zq2{^gU+J1>)xzx)|C)c39_g!W^~;aecWaJ!~R`@!B@F3)Bst6tY6!U-Kshp zCJOtKYwxekf$tRqEqn|8!ErZ8Nn&wKvAS?Ys9% zA>_z-Q?ty&YM$G=D(}TKR0|_2a9iArb(TWblY*;~qW677km7ydxVr8NjCaN{&2W#3 zz=@M2V+78un{_BJXG`&LRkra$62f#82R9^UH$+%1(wUqubJF+s!@f{%oHswW3#b#`I8PV*@L1(6q~x@uF=r5l z;<3{HOS^;okifpbXb*9q*3JswP+aAvop`)F&?;&6u7@#IX?VZCF(I0Is?aAhN>97;1al9tQt zhv~$+!*qVlrF5(uGST@+-1Oml$AlE$t6n10lH^=*>~qo2@GmLWK%>n3wf!Y`-|}!s z7va2C;xj3oS*a1IK5xMwL1nfeC7j3?d4tR_9*dZDBYwdCAlMB1ey= zu(Kg(1B8f~4-)rxVkzv!hsk|K`uOGdGOQ+jHT^;BTk^%f@+cjp3_X5%`_{@Nkt2+% zj3k841~*S-Ko#azdlN$ayr{y~hwj?6)aYTa(@;>e*E0Rglt$dt!@+UEsBu?zkEi8+ z3WyGr2`C-zPM0DUBM-(8P}m}#C()PkBY7&LA;PQb*_9#wrE*&yYc&)2<_7DkW%Q)X zzpiF<%s;UKJRe)(r57(=4iycQX={PV#giC`;=DIJX(|Mz1=jD7xM%K%MCql@NQz|@n;=Vi0* zpcwtz-}cR|CE>8Hu#J91+nivtHvRwwbUPy3#bYTBy2|fX#Jz%=IHsLgTlnPe=vBXm zI{}FYWRlG5W)VSxxXscvRFUwMF_CaNu~Z{)p@5zi2J3oQXu%lC@SP_n(n^u?)_(({ zP^hzd_*b^GL)WYTuA_f*S4M;V)8EZgr(38<(O+|kEg8Ok@T5j>YMLkym_q8(T%uyF z0g_GtYBy#ExS8XgfQEFzErt+NFkfO+yLnOZvXCxMjv)n9Y((JtHZprL*$BN%x7{W> z__2C{sAd_8eF1?GfNUxKKn#z?p+ME95}lysjz${P3V@502pZN|GivvU0y4^MG7oJd z4_x!1zB)}1tFwm}&LwY)O67&Bdbsh&*1Pw%DiDHON{2z4X#(yDv}ry^1U^8IM*0o0 zaLGKMEgI-YXrW-Bcv?HaA|AI-^>O7TnL4_eN@s8D`Z#U~iqk^`MaVd38~n2T)pgsa zk0>4D$C`BerveJdi2?`WeuA{CY;(R}pwIt&`3~4u-u*5GZwp9b3)K+TI{_8e0I@i_ z<$k}m8lfdP46jRX>GRJW zaFzF-mi>_dkw@Z_yB^e(-1_9MKE9!*MQgbtH6lT?yh@>E$S(|goenxv!dX;)k&|@HlR4|*5BuGM_)y+YYb%pil2nI*hfLC zOC#?a_j6}|G1PT z^{u`<$I%eWkd}BWzQ`1@b(?GbCd*rGkUr>|`JgIj=p_XlTk@uU3cTN6pHmx55Vv~= zq0nIcl@JmF(Og`Jfs%^6J@tIVQwv%grGAPg)R!))PbD4#q45s}N2b#N diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt deleted file mode 100644 index 32bcd617f202a318ae943248ceb64791dffd8330..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2543 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 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt deleted file mode 100644 index 975566dd9cc07b3677de932574638d704141853e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1595 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 LYR5*&O+)|yP;RC0 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt deleted file mode 100644 index a3abdbcd07b9f42b6f3ffd07794c8cb91c6ba4bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1721 zcmV;q21fZGiwFP!000000L`1*ZW}ichAC@zNe)+b3KZyb^mNmQDEbD)R$aSl9m%ld z^zayc;%b$pqfGueIMzi281Xuv{~6AKoTU&7A&2-d+>eLDNFjtTD9}%jyNB`duo?F$ zG=Gl!LuhY@`~7%)8i%u|tEY$O@7w+E>F`@<4v$aM({}fGe0u+n;rM$$4sXYB{dTh* z*N?;P;fHs}?}EeBtOqPTKYo^};jhg;EdGAxzx=@e{ywlpRKW+~W84qFam3JKs*V*Oi>W%=+Vg20$1kHcTDErN4`)yeEgb?3ub*yatUZb| zlFwE>a|YFO>&TbIWWY$aw48P|MoKOSFub0tj+U?JU=m?pz;K-oFsLs$!|O0RbjaaPajdKQ92K1i7@qe87*x-eEdmVpxd5gJ>q<)fM8Kfl zv6u`PUe5%WUhrA#

xww{T`9)H5lzx>-x>cXBXQN9(}|7_=vF2JH!);p=K=#_DCx zpj=ow*};&5DS$z}oQ(cTfZ_WO0S4{iiPbYYPdS5n$6{)}vLj#F;g8l|88E!RnwcTR zpB6Aue|dC@W9>!BSJml_`Z>MNoH5q|qxDw=44=oyp;K*HGh}wun8h@eQ_hqYFg%6{ zFx*!4i4&{*c2~0SvFP-l0?Dqs{6qU{H;52JH!!PICA|fZ_XmaoDPB?;N#Zow=NmYQuWJ zIL(O0Ov@Rm#;p5|(;08PgK!4DgK$P#yY+r*G1PKU$POsQ%=2%~yF>gT4bB3P<9bnM9ES=)esoYZWxd9A1zc_<>nKLNP zmQHf`Lk^wd@TYg^tQ`Ja%}k@jc?lS<(*OqT;haIe!x^-XSvtw#Pj)cmuvHvB_YR$^ z)jE3FniDvK<^;~5Il zV5EGJBVXEVlN?M240^xt+UgabGhooZI;~$jPg}sCJ;Bn+fZ;y(4yJP2`PBdhofn)z z=Y^#c9sVSTPIl;!gDDPMy+daO7<8sgjCNMGfI;_cmQDl=ntv>v?9d^=NO9Jf9xyzH zE5M-hePXopv;mA%^Va7MmQHl&B*36^+0r40KLs#SF0>hG1sF7wOpJC<(gH@RRqeBq z?9d^HKLs$--fPWc6Qj*GEnv|5GH0av(dM!2&>@FTarj(gq|G)BV5Hix?teHV?T6M3 zY3XE#4mos+V_h{q)@KTwk@hI=)I*`4+U zMW+LdbY5sW2{7m`ZemuBy=7(SOnbd`hc+?Ry$xrOKNgc5wg@n2|Ct!;o`f@~zbu{T zV3NaDcIXgb(EKwo*8K)&q?}sw4`jiGfea|WHumQDhU)Th>2$r;qk(|--p z_SJ4?wEZVKm;@M<3rmLpBl)cD2@x=;<~f6U+0r40KLs$TPbWs(6B1ygIBPlt7|9>4 zmy?6Z4u$}O?pG&9dk4vYLH%_d^gfM%K{_{%oN@-mkTa4k?Hx7(2E~vwD2A3!wPoe& PQzrZeZMAud(LMkG9>iW8 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt deleted file mode 100644 index 37c90f780339ce4d1ca337f6db5897f4897a44d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 844 zcmV-S1GD@eiwFP!000000JWIwZqq;zh1cGj6QJ+|iRa+@gNH!80Wx7*0%;t@PPx1W zFN__$sXLsVSwmW>Qa1g1=Iq>JWvSFc`CYvUT^E*0sV9{(@9OKIF0R+xu-ey`-P@b~ z)lx0r@0(rNck9shOsLyV*~@ykJP+tz)t4;W@X|8C%`un<7#gBOg`COzO9xwJ^p<-(0=HjerAHjc*l%Kyl zq3$z%_k5?xe6W$8{oS*nz6mV}S$$f!UAf5|(a zFZklzg0Idk`1;&}Z?ND(xsRJ>^|c+={I7-5yQbCs%i-6kKR;UcCGP4j98Y%{Ju+s( z6bkE1nUXLTFgl@QCyW7piVQ!LL4GKM{1h2}N}^+d4rP!Z%D9Bi)Q<-`M^8dcHK}_A zVo_#67zY@d!;>C!cayl!AKDD2i2cFLUpW&wh4840XGMb510tU^y zq+>F4EMU;=NIE{lPrN%f7bRd)HI-&i((xI7RGf_obCI~0&FFb<1`S})PM}Qc?$S<> z{8SnDig$NRel%cGz3MW0mD6#6N$n_?Q7_Lh8ZfDv`iy?&bleO-6~h?7&{#1?1yj>< zWVn5(0fYQVIxd4LMn(&}g)-=KN7Au?K{F`D@)@zz$QWV&PzLogWm5H$o?9q`W>C_J zo~4~hnUrU4*BQW|-6H9@3_pIxy}13O0h6i)w-0TGj?3^9>owg!j}!OuOs{Id&{#Hu ziLoli&yb(tGmP6m<;ZX|r~!lan51I?gPxHp#m{>Q7}P%!V*r!#EIqSTLeFc!pnj$d z>SsyEW%!AnrRNsPq;km3m(9?LvAEe8Vl9L|)FZ?7j{yvtL5Ybvv=*ja{|r+z!*`eq Wt^CdKJ!i8$w)t;5f$&$%8UO$(i=;0A diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt deleted file mode 100644 index eae5e04c4dc924d33af174a374c6d5ada3660742..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 704 zcmV;x0zds9iwFP!000000JWFvlA1seg&UX)l4O6SD$lXG{m4V4@&+klW;bqJumsKJ z=>y8JZ0}*FNsLvNV11rGJ$+FNq7~U)xpi&p3L?77NqsEu9bMgTD!1O3H|>XGcU4gF zXk{BEbPWrcf88`~ zS*;x<*Etp4`%U+TtNzZqxMLnUzx*K$^8X{!eC30YmY3soxE#v`-&|Vo-K7QJURv-y z7F?0}vaQ$On|>wME6R3tlXaK`$;pBymU&k8WykMgw-_{jk?mshOroI(AgS>5MqVFa}>0nc8?2AFZzPnc(*$6`!6 zFiC*P0P`Hwi!;lhPP>ayKYrvrW9MiD^ol#5RIka1}K*tDle5}y^Nr&8~bNT}4 za0bnLj7bJ24a7rIq+G8;tBhaw|9iLYw@EqC+M!3I#9xq3--Y@o+_CKvQ!E~qJIke`^25$L1?qXIe^U{EbMgK8SnF#=38!aCT=6hDcHD^y{26x3!d#Xhm*YZG6}Hl8BxZq~BGyo-S_JwZGg|*WKGge^pZX ze%EaMu3P)IXMELmWUi}C>kBePb+^=;i!_I;kgcrC&XkBR-2)L5FiwOF*nr_05Z!bwGyp8eim zUmbkQB#Wzc+g0_Yr|fw_W&eHKf8pzYJevz!f3dXnKb@rc)?fZV>kAkCRowaffUlPh z_yz}Dk^Q)7F2A(HF@IQ*+BU7~FNe3LUoWNl3U*cJk9YSObz<~{$q2`pGC5-mU{oNE znJ^kKS%T**!82#L=aG^8eFHoZ+)N#)m z%9M=BPRz7l4+4H-Jyn1~vpO&?qNPv1b758u>jl@cfI*%O>jh^FV7MO(81Bah6M~d!v~H8t$~T18yYa^OpxN_Cnk1oD8Qgza0czE6vxi+ z6PtMh7__IB&FZ6omX7SQ0SwPQ8|NdUl>>%rDZqqgL)r_@gz94x>JvLxbpm4mgZ3*m zj&$}qVJ|FTQ0`8cRSg)lr&1gX7@n5{OvtlJsE@Q?5@Qpz9AMC1IFk32Goies=OAa$ z870MW34YGc%LLCc#sDVNi&z{7m{6T#XM#>(3}8aJPj~qO#3_Usvw%UK3!z^IFsRN_ z90wRwpF-%D1q_d4j~?%z36Fu+N~n(o4DW>l4A&at@Z5E~{^3VxNNV`KqEO@x!*3c* QO~WJfCt-hDIk*-80B1#PmjD0& diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt deleted file mode 100644 index 2e0d9de61399e5601fadbdcc2c709fa30b2d105e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 585 zcmV-P0=E4hiwFP!000000IiqnZrd;ng=x#W*#8FXMYe8#_7FqgpztzvFp|bWY!q9c zzE)-x0e4KQLjnj%jL(M@$>U2$)RI5-hd9r%BO({5`QAT8`tURygRDBB6Eyt(jKs?T5AN#`; z|6A?urfQ#Ws`mA!YG1HgOYX;E-0i2-#(hiXG)`vunN~x8Kh}_4WafDJ_b*cwFtx(u zrRivlUB8{eT(qv33dFiBfw6$$v0Q;py)sr{3}ASytm6uFB*p>;)iAAEsi9TsYzr9o z4jri%Z(IRWvUjb9Y59VEd1ZbQ6BM1asw<`j`*N&boUwq}ignEx#`uC*^~#unoQ)8x z0SxK|XHcCroi{%Vj0a4!v3JeyoY~6R3N`eAv5X0T;W<}1UO`Wt&@Tg+tr?Sa{5$gT z1vBP_Shj$1fZ3W2NhfOsA!i2|H1jE*ig#+jpnErGcq|7Pbp7EB-&f8@^95(NX4MO^Y=Mp| z$j2Axgo1o>&OxZN2MpKA@r=MYz@TepP`qORgL=Uk)C*0=73g@tAYTO1{jM!$5(-b=*@(tNf{Zph@Ps1r5F8#ywaqJ(z9LMh+ zb)PTeIbNnArWxyh4vDH?MERB1?3LI*$Hd-hz71*WPlrg=n})jid72-@(?sr}Kc@KK zYVYo<_V%u7@9(Pi0jss-zaGcKV_M4iqa|}5lbJ7gxw!U=^_RrtSWTf8%i5&*;{b!^&%%`E4`?t`#*6LNDhzUOEGC2AzKzMemdt3mB9`&Y&EYnCwT| z^A<2@W|o*7t8_Nz49~MuFj+_1KZ{Pw@`H3*wl3tS#CX8C9UaFQn}**pLkqBc|F(w0 U^YV>6p4Kh&2T62u@8}Q!03drEq5uE@ diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt deleted file mode 100644 index 06387f7d292e192023419a0f56a2db3114003f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1699 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 U*nM-g>-~uR00Cozk~j|l0Muof0e zY&@tsoVj<3Qpsu?eLg<->1lgoIup*rG0k)8jWHn_`*C21b4-+hiM*8`(&Co(e&5Pr|SplG#hs} z9H;c(YOimq_Ufi;Z*Qvh?xt$*xmsuZm*cpA1*Rp;4j4_cSOIbrP~rKZTRp4W7C*^@FC$gnv@rc?`UM`=2-!cVg?Ug+l?VM@I!?F~y9 z^y3M`&NiA(tnicL3Kg>~?I=eW%ujfRjz`X@r&S-p^9_0n|m4tiQIJSSMfusKDBK{j#k{@aJh6


SGvdjM3hd{gm3dO7<+NP?b3V3=_ zh$A!{d%P zf2-QBZ&mw=)iz}BcjNXcUJ}3GkUEZ0%|9=Pp^uMNWM-Kuy#M>kGyUqv^&%T05`H^OjGr1g=bR1xEH7(7K zu3$_BV*!)%Q<^Wm#A^gU5|cP-204SC{UjX=7&NC6(=Lp(?{Eg~-JHpJmY(Y*9bdtu zbxE_#88pkBL36wQXiewG*u7&JSaK{b__ltXDx;Y`ktq~ll)`TJ>NG-GreUPFR5%i_EucfP!j RkB9d(z5(_|(Q*b6002$s732T_ diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt deleted file mode 100644 index 0d95ab0768bd400f929b0863b06081789e2bb9fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1089 zcmV-H1it$piwFP!000000IizaYTPgohGpyMy({!Zdc5dEl)gdPrcPP1$%c3dY2Une zwOuQOzrSWCB>|J{^7+?{GzUp!=iK1(?fy8P&*RQHSBeXt_t&F)b$z%QFYfl2=TE2o z)z{;y6!`9yZQTR z{$jj2yLh=jPUC;8y?;@)cQ2~;_C?j+$ZFPwd-!hyK5_#Fm%bfO7gy5~N52Q>Z%>n- z|6HEv{{BSo;w*C>*H8a4-TVXtBk6?s>D~I_k?9&t_k`)mSjeDGUmroo8<;>C4@@yI z-Ntxfte!Ba;|)w8OlZvEQzinF4NNhNH5hEJz6XQNQXD42q=sJ-QwW2;SG%L26AVlw zOv|q%FqtrDbDigGh%t#tglWZ37S^;p!=7Tu(<10(0~5F3QjO}j-%^bVgh8EX&`E@0 zej$VN+*R9^`hyHx3r!~&m}nR)5eEIrgkd#G)2Z{L)hJ|8Cm3`RVOZ`UgZW+zIzy!juy@aNd3_AH4_6&xxBqnT+)SEJ4u=aKv^R!=NGSA4cy*e_i z&LhM6m&O#sSZ-r_!LN=mtiL0}dK@xrFM$lkPcrCagHAE%RNtjDNF)r)Wn@@hXgbB9 zGZ2Q=v2{I^8ifqohaAhMiM1ooukD5C-FCAPnYL^(z_H zG#S=Z>y^l~;xHL%g49m~VOqJ94KXI^)Hy5$o27G;CrryPt)FU4A`IIDEX*MI4x@yOp|%47<~_>PUGS3B&fr$guUwO727hlL*tALn(J6Vc5DO!}e^* zu>8sp^R4;O?ie+lNSKyiQVu@)W*AHA-H9;loKlont+iF#A0or@LeoivVfDEY&7!-xz7V z0%6#`PSdGlNoyJmOe75Yo(O~MRmYO*PbADTR+tXI#tQA~<6XXA{(t6lvtoY$l0{1M Hg(Uz0O3S=%1`Py;k-kNB+{oD_KIz(T<)N&iNkhzcxy3+U3c~cjJ=pjYk)m>Mh+Cv>p<>=qG!&PnfSG7Izwha2M zvc<{ugTKol8tX*&*xw4jmlRN)#?$cjmq|uO&6p@)^iTuh850ML92v3VQ4AA$G{Xoc z^Oi@9j9keh87A~7h6(d%hT-PC?%`n`zZ+Ya%%;zH)@`U>(UHMHDlue5YB$xglxAlPi0AyOCr&Cb8p|Eji&t5u+0 zI@28OY}H)_VlY-rk8?=)x=;X4GLEiq-e^Lxam~bxji(0Aw5F<>?XTjJn!SE+!Vm)(pFkqx@KgfS97O_%5ah}gW(_d}; M1j*JFjVuNL0F1|wE&u=k diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt deleted file mode 100644 index 39338cbfba3f0b3871871972d5f848fce880d820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmV-W0k8faiwFP!000000IihUPJ}QJhKHq74tFL#gts29dP&ZnXXxqNlNqe|L0IB0Sd@^(~xsi0s!Wqp3I)$YG1ch4QA^eJF|Ofy7v;w=b`Iq za5dQxGat2uXMb#d{ zY6a-mrmJ>#YWz(BY2Vp&Tuy=T^QaVXlyNk_{biB}W;3l9Ou`uT%cvCw0}S`lXXxMx zbBqPE3FOR~G~mSxd>0sCLODx1-b<=WVswDv i_Yi#_nU1pc7kMc2kwSKu{_R~mkNz9!m1wO}2LJ%!I-u(S diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt deleted file mode 100644 index 441a18178bbb358fd200d297caa11d0721f49c3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 327 zcmV-N0l5AjiwFP!000000Ik&RPQxG+2H?}dfwuolyaTVmk6&Jd@eT~uGt;aqO(Dzl z>TTzk4KiTHCC#?x;XUu5Sq)Hu98^cvQVjs21pcJ91XtU(r)E@Z`>56CrPJ><)X$?H zXtXVviK%^Sp!fiAORl{oq;_PyRpnc2tm+$r;J0s)zX3(AM!tg*J%y?FP6Y7&PE(arh&^>1hgJ%qn=26k8ru2X%?CJmP(kq= zW|484M6nQP!NA{6%(H1oWhCvfnfwx)OZXSKV3RlDWYYS1se zZFg>I)lCgzv`);g%TVz7NC9e=@p%6F$rK4@8JlH%V+uxxG8@9^44n{5M06Cx2*Q*M zvldHc)D`QGW|*~nWTdW;kBTsoVQ4JHFl#yI=;#Qe8HUSQ5Z}32l;Qd#6241@;r4t= zM`tjXn2Ehg8O{sJtko6U8;W7p>Wb-<3`5UF$VVs64rRDIA*FMPm*`K5QNPfMd7&7F z^E9OsVx>H#4CiUCPU@VhjM{SI|iuwO1uThSiuUPi z7ca7=XLl@-NLCW-^O@b5GqXucv?G7&4sje~OGG}9x$Yh!y?^MBaewaa#&79#{=JXi z55upP+MDxmis!M9X(GEneWK=xC_nY#?NhOPjEOxMe)ehXj{8W>RiJjdpQan}IFh~V z4k`YR;Kxe~e!8^amrDzNy|mzGEVv{0<1p;+)9jSn9qH4M^z?DQ4E=o>O?HwQ4DsgZ3`zIKUv!+YNQ+4Dyd< zwLm^}Lhm#SBYB=PsJ}Ra`b&yM3!^uzxmGU)7*sFLlyX?p$?K8&lryDR>zbNE4%dt= z#BzdvI8$1WtHjEC_mz4nz@R?mOeu#!m_MF*p65_4jH)miFb?>KGiYvj!K)51sJ|qg zyf5io<_zk0&hS`%gHGmZXNm(1*YSYiwa9y~ojV#Z=q%W(Bl$T{eb%Xkk$xv|2A!vz zK{GRuJfk>+&M!&F0S3+aAk@794Dvi@(0mT8rs(&^j_NZ(EljNz8Zf0;y5i?%VQM|7 z0E7IqRY%HmyTN0vP;)Ylf5)2- F001Y~8uS1F diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt deleted file mode 100644 index cbfaff2d622f78deabbbeeb1da0a9aebf5acb13d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 446 zcmV;v0YUyBiwFP!000000Iil=Zi6roMF;!>zAJSdeSY+_3#ht-ic+USC4jISwOxH7 z!Byl8_EaH~r34+{JH9iqC;)O$ec5PhbpZe>1O8NQHC$}#R#!v0u@9ynJ}dpwbngWe z&qLSi!PeT0WcgJaNWKBwuFKP1y4-2wZOqeF5k?T0X{FOT zViJ#01SUh6bis=qF>Jvr#AFEL*CS>oboOLsWT560VSF!%Fn-N^W>mmSB8>0lbh0Cc zBRMlKAA#ujj6~{*F^b^z=NZu92!qXYjFALJ5$Z{uC*fQopd$#3BrvX?(2OyJS?YU8 zM-X)6KfFTooX%XR7mUDg0wWLxo1d7Dt2xv!hA`OO%e@SjYL4}5f8Ry&+4nW#lzs$?@#;Xee0M+%=)&Kwi diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt deleted file mode 100644 index 53d7c1bf237f8342b2327900c85ab3e314bc43ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmV<40U`b$iwFP!000000IinWPJ=)Yh6k3}1+Gne4i8s8gy|a?#H}GxAS^cO(+jn0 zn(44R#x`k6$+!PM%qf%r1(=~~?KIgE05FH_vD#U<+BKc6$7(x0xM6&+?Ni&omQZfS zez4=zST~c^N8=#*1n{S>&rjKEZyh<9zcg;Dy4pf=n?pI@ck>O~O@P~~b@o4kHS1Wda83YeJA;rfJ0R+v+- zlrYFJYdVs6w7@IGcpVdn2L;S;9#0rWnAH0P7{xGLeqsy?yfnjPEAfPCnh6+W7#g!? z7#g!-7#eeOWKd8G6y!P7hu%vEbW(<)`B4l*y->h-FC*{@F(_a(!>r9kF7V0)y^#z0 zxrp>LlK$axh=O{>7-Sgg<+)hBmS+p?mgLBUW;taTZvRk*n~Ru^_X^FsVi<0>#B`8h z*5V261jR6G&mPi2fsX!zS7^5&!*FvNW4umm-YG--*$8yJS7;|_0b>}3+r1_-7m8uH z-Y}6q%zR9d-k=QCF#;X$WdvTK{j3>=%d=D`R13o}H0GRPXuZ4+-Se4izO09eqgbiH U?3Z`%zB`2U4QxlyJpl~>08B*X5C8xG diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt deleted file mode 100644 index ae5ee8c11dc18169468b04df69fc7630eebf4040..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 654 zcmV;90&)ExiwFP!000000Iir^Zrd;rgei%CQk*^&=sA++DTfGpgFQSSUKRSM5Xpu9`w*voyAGy}Gz+^vM zHYl^yA1;R+;{|>)$K{7IXm6nm$~nO7{ixT4nwdx~N+A|x# zpnD2s(0PN?aRNWNmKS8hGvA9evs%D3%-UNf^9C?z?NXgm<{e;AHYkJU-je*FGYMtT zUdQP;fll_rWrH#(8=OvJ(($}vYITDAPzLS29ODGFvY%2`4PfX!*9sUXsMQ>qQl2$n zmON{LXYSnFG2aUV7<5nRm^>$)3uazcz+|0LpRIs#fLW@=of9a7W_ls$Gi6YpIh|aK zJ0DVJXcpp^1nb)UxDpx)eWc42)SZ|0BF z;rMeMzHIm32Q_>??hoNOZ^E>Y(#J) zJ}n=F-K@;bxShgt1h09)GtPDYUr#+e$NamO?#BC<7W{w(du6|F_v;^19HQU7(ue(| zmtW(zQGdUTR%Vfz!|AW5OjE(M6^yQ6x(eo`^@wQ*(`7A&F@R|cI)-5kV321k)XEH} zV*yjru?%AYgZkryKDUW6LKc+Kg<9O%bz(Tr9biy@Bqr-PrdI5qkDm)Yj7(dh(=vWs zg-(|kE-wQZG#ixZ3Vt{pU*V@sjC4;aL;YC5lzPb3@_;dfX%fTDdFC5r^FtXl^O8=R7%q1W7_?g?#sCKG!(PbL z0H$LAeh?79C*F&XjZ< zU`qYr^0I)TIu0->uUG2doj@6#7;c9fz#z|*L7t^r*$=lj3}9&PZDP1AG+^ktvJRJ* z1`M5_?hG9-%qnHjPFRuLQ5KXzxvwg6mly{al<7*y)B=X?1P2(jdntovV3}Dc1k#t;zPWH^rbM$jjF{>BCjM)lCCx&}J>;O~p%*~;# zU~(;PHVj}&XXhAKQ7ig+O?qfSEy|R1xIP=epmRx#tEiGPEI@^O7z_53ng*(LZK zw{I_*rh;h&M(>QhVH(01z)&4m!DJmL#M*MYVOo&$_GTCZ7#hn0Mi+FX+9k$kR_K=@ zwbOjsoiW1tP=?l?b-2E3z@VN=Isq`IkdLdVOWHq@j;qk|fI)p<8PCM>fGNcaLhYL` zFl%T5gZjRC2cx3_gXW7eXuc>z_p__e$vL+bIdi^|bvWN>cII|=Y(d8``53^Ud8bUN zc3ZJGBoCJuTM^4uFuo#IsL;u^yNbSZ^KL72JYZUFr{_o zJj(2SmAr*AsIHZfd_!U^U}#;gLML;ru;(d*_B>_K{-F%*SF2!c8)y17{0$`B;tXh({tPD4U7BFZoB%NHF^!tJ`rC8hy=2+4UQl^v-r{e&FdP*LMpT6pJ#YSkgI@ lGH4$Lu+Aop*O;MRJ)2Ocm496SnVC*oxWAqFY2j59007{YMsolF diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt deleted file mode 100644 index dcd6a0c6de1c949348443319419a8d84435df52a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622 zcmV-!0+Ib6iwFP!000000IitoYTG~%g=e)lS-%T?j$VJ{Axht%sP3kSIF|7$q3zRG zO0!@lXJ+Q?C()gG%yRrW<i^6Zp62f%P0^UQc5hZZoXUYtR5v0Xtp%L9hzu;@f3&zqJJ z>h1u;bv$4^$f0L-N3+8jR8vjI0S4ueGd!-)z)+bD!H)q9kE;U=>J84+JZpQ*le{-V z0}}zm&no$mX2$@g)*I4%S-{kCDCzhHKcPV3G1@{5XNJfT_hU zG5!^2X}!T2)Q7D)L8-+~$+H6tkE<|J?1kZ;U7r4=%j9hTA@r8wWRaam$dL>$O|93CRQco*!kGc`Ym(p4{?UloVPIA<4zuj9N7r$eOXeV~3lKd&d^X(4wv z9Ow8y!gse8zP+{Z&8>y6ZY_K*3p?^(j?>|O-tLsAj?8(Q&H8aW9Q}D&LvGb9@%Ojq zOam}&h4K5lQ5c)vE3r_$vtjA8pXo^V|S*#Vq78CHRFZ7Q}Zz32?A5fS=*;hVDfxC;9zV5I$3^Dy8EfT!6RZAP^MQ>tB?nHKOkfbl>q z20W=QZT=X6DfLvFhYs*~fZ>10S({N-U`oBvJRXe2mHp)eMv7JQq*&TL?*yh4OJf*_ z_4hXe$XVNi4q!YGivdr{r*^OA%;vH4_%kMGd*-nXq0SILZqG)h6Kx~s7kWHPsY4S0 E0Qr$D82|tP diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt deleted file mode 100644 index e952b2a95b917c74ed16210848bc7bd1453d1a51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 671 zcmV;Q0$}|giwFP!000000Ik?-ZWA#S1z^wE*LK2RB-TOU7mGmb01d%K5or=-h6-2% zizZHERJq63r=pc2HPJW6kLyR9wJ|Fbj?*qJOIjOaBpUZ|x=ZHu-FBZgr|EY2Fdt7p zHtF;3@NI3@pH7EkIxX8YpXKy(JDcH`G3BW@PoGNDeVVHWXCX|PAFs@z1E$qy&6Ku+Qd0{|-5(*02d1ujAaWwn=h9YGasn`D?72PD zsYPw-90A6GT4bZ`9Scl7hmObzz|?(?z|?&nu4e4)_u8QSUK_MedpSbn1ftIo7<3+H zV-+(3)2gW@YO0-MLgaWNClEOin0j2RXUvZy)<*BH?BxhyJkeGlaw0JG{FL=0#QX@c zeuP**ni0Zy!USOIIV@w>?zj<{*4ohSI7b*E+VVtBAaWuwt+8wOparH?cg+aVmM3xo zkyHAk-OBQ-$>bLcYy;2 zt;1f9CvqY%ty*a3vjwJA3oSgpPIyM2duL|P2r%f(?B(QF{)$CA$BNO;4F?SBPtTN`-kH!d0hrdfwEg9PLH9+^ z1j3ZI9`B3#|1SZiHP4zUW7pQI0Mlx#&T;ehcY55=tGpPk3HSNCzQg_!^%tJ#zsGSE F008u7Qe^-D diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt deleted file mode 100644 index 844a9e4b2100355c23e4f5a66d8286ee6f4f9a2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1059 zcmV+;1l;={iwFP!000000IitoP8%^0g(oDtUOUhh3JtgR9eVrIhp74nRhlkUR3L~= z5#`zYqcL4qFdX|#5J(XheK~VHb8K%2B3|6Z^t4?r+aMxMknrVlanW8b=WW->XnH;G zWbj*7KYpH`wX%CQKW}H3)05?=?&9*-to?er_#yaRH|xEt`9ANK)ALy?gSU-@)!)0- zAKLS!R43EZuKlkzd8pP-ui7qSh&gmABww*YK!yLZv!v&x6{S!XBVUP$II|y(WSRI`S<09QmxD^+uPsnGmU{sI*mc6 z#6+Ee!4G4S4)ep9sIy`4!W0DT@ z!e05ej|7%&y^yk+PiV?1DV#sXkaHnt42urh&oenxuedWQ9f zF&;2zrkc@y>Yia|lxA|COH8U&%Cj>t%^EtPu=WNpTF0-UGbVF?F6BK~_YBLkX3#7c zlXTcjHIwth=A{|k9}gIPwj`a>ETW$mhW;=n>9D(UJ9;3VBU6!#X-2Or047(f^jzlw zgJ!yI=pkc9J<}9CSAaohlxA|COY=&#N*RmHj_Pv_YH0?Y35@Z8(SAlfQy2VHfN>em zrMWi-#sdb;Ye)DwrWuqm#&|=m|E81&RFsj3XB6x zF7puRQGh8!h788=g1~914n#rx5<&ZHRFerzbLGzjz z@}n8Fu6@#<1~6zA`(#}XFsO%2#{(v}F180XgPs#KgEF=+%1QXU(8}ab(y#M}}-@2CbdxB!-;{ d#|F>Gh8}7L`LXIS o$Y1SE5pwP&002Ed4wV1^ diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt deleted file mode 100644 index 7183b7a12e1af5d12c2b498a1f65702d5aa432f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1290 zcmV+l1@-zLiwFP!000000JWOyZW}icg(+*vCD%?9H`n$p+BARiBacwz4Fbj86ha)! z@Tx(Yr;pYl1NrojXOyT01Yhv!%;C&%maFyPTyp*O>T=v}$H6&wHn`#S&E|T%*{;Va zx^DGpJ-NldZujG#s}G}l^kIE9UfitSZC_5;H~(CWZ!R}~J9t<8YdvjOR~MsO{1)A? z`}?%}!+5oI{@v8Ky?`Q*B3{drvOw&DCb-MxODzb{??aaP-0?S5M%7v5fOF5XYO?YelC-12%e zmA3@<^(!o$-__4Sjw|vy8McJ%t^&hH2B$PmK8rOop^ws)L;T(Fjjwn&d^|D z_O#q%Iuh&Fw^%ze7%LG5V};Ckv36vzUeTbF2!oyn!k}lLUqSR3GOXtn6AiHvVOSq} zr}rr`HP0<38e$bct-TWnQ|k@2-@Vv7ec3<4PcZbVVj^K!y@H{~kYV*wOfVNsJV(vEkCW^C^~8{&*!9*JtkC`{c~ndVj;uMT7#ip$gunGUg;D+t+^2h!)6pR>^?>5 z6hErxkzqZin0P=e)z8QzijJBa_uSp<1zrn$W?I*aK$u88TXoc#i@>)P)_ye@Zysntu( zI%I0=QfFG_Cmpb^*kF3X)Ox<9lL&(|s_3K!Gw1NW)A!5wp`Y0q8yPkekYW2v=@dWe zvr1%G{~*KqN9ja^pW<2dJTf)Us^^ixnNVV>>pL=R{ycDZuNR4|{Q>kCGM+Fv=L2De zijHqEfiSgoss2HR)k5h+!qhyg&+CxE945kGEs9PQ^*T4y3mI0gb3?t5VRJ+2lvt{! z$gr9!ok$oq6V9EU3CPqutC^s5;sJit+(4#QFLfP6hTY@OjJkLDS=7{LM&%h9mS?3? zVySx~WZ3g%rBh;A@}r&|TXkB`j%Vhf)A#Q)qt5Dz=?zRI4BMvJ?a0)0lpkc+x|B|d)f+skUbW~v z6Kn4Y!|MLbkRN1New0p$Wm%WHzW?Idv(9HmJzqxVl&s6Db9c75FWKs?e0ned060aL ANdN!< diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt deleted file mode 100644 index 7f7417f2a07ab28e0da2762ddf765eaddf90d8d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1320 zcmV+@1=so?iwFP!000000Iiw*ZW~1u#mBXGW@k%j6WV+g9)j}m2M>Yz2FQdhvPk17 zYpTN2<1N0ZJw12MHA*BavGw!0XYR+$*cno)sobq^#@%ilQcC@hhS&GoyYYUv8K*w2 z*6%k{TKtvvfBw9FJErGvH@D;U{rb)Br|Itg&+GA*o9*w3zw7;R@9KZsOuO~%^_Ujl z_G#F^KJ8x^Z+EGCv%ZY)X{duYM$A6oFohZg+d{|VN#nl^ur z%YApvkH`DRH}mghD(_~s?d|^AqNe=o&G!0_Y2Ss5*EKEgwv)Xjr+4Nq=_o&nnROlo{3ynBlpn=p`z>@7V>-%@VrHFHz>i`~NBL3A ztkVVjD8_V@AH`&Q2pz?kj`E|JY`z1G@~oJiFbgM^T9;z-A>QgE<`FR6f$17dCX5$L zpN{Na_h=MrGL1EcDNj2BC-y$04EWqJ{7zJM)1VwPm>1N09vnJ}!!hCq)Y z!`7u3(^0ihjOnO6E2cj}N7d`G$g?pjhl(+s+=x{IjOnPgE2cj}r1Zt`n(E6P63>mi1KS_F@N5+e#&gGfOfpxX^DAOqc9W^`1upU#4`Dyi7 zCXDAt^}N!tSgjr_gkgF9GPUm;nJ{c!O2=ZUvl1EBhf2p{sh&s1i`CLGM)jCtOh?@} zo{Ib!qt2a~QFn=_fpsayVyU@6#?w(f|18kY&jLM$4BO|C@nW@VQ3jORz~hsbzqZ|%HWw$N=PO~nnyUK-GTyq>d?}q8@ME6Uodg-rvzkGrQv-f1mbyP9 zS^_jEuJ~^||s?^n4)<>z}WZKI4$_bkrG#46B9G=?R0LR|iJT4l=B! z$go*fI_9S}Uman*9I7){>GT0V7E8@3GM*nbU&wemt=XA9KNtPe9T;_=M~3-PIu=Xi z85x#mrBex$omj0qQXvfP;gv9j+{2MUKc-U}u?E6mEc4vzF^g3Lv1%ih=?o2K&hrcC zLzZV`&`)<@R-%89Vf_=;Y4unk40`SfgZZ&_se1x4o}U)e2V&JD{IvGNN*K1!zexH% zj||&?kYW3((y2%IQU6a-OeKt0(;?7f>i%;E^Tp=$Ow2_g4C{?EF&Bj}tXGvzcVJYn zBIB*Ab)WA8I`s%Y>Mnr{yBjN=N*MG!5XP&QnlEJ7_hZO-eW*S=Amimn>72t{uzSL} zsA(Y#>*pw=YKjayzs^N13Sn4Hl};s$muFQkWW2SjJ#%K%_aw-$99|^7k0Ha(xQjsl zAj9s@7lFDX!)k#HtA*030YBzhou|mKUPXrWYE(z{Au=q7mx126OnTmtVQ1WBYVXgP zFl;W6VRNB$ES8#gWLTb+P9==zN9_s7cx!Lz%*++ki=AIrqF#kCUMyAjE0Lc<7`FDP ej>_{(;khRa`waUs;OFblbkaY`OnOAwF#rH?6{KMR diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt deleted file mode 100644 index 4ce6494b4e030553aed97c6a4407ec343ce0a1b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 999 zcmV56*Pjf&>gG;Y-R^gl`?%cet9|J;TB|IM4}X5Gb0toiw8r>5-9?AjlnerKG5 zi8@Z9lVgI;MB#@qQHS|qOwc({_+d=cVSX56<2%t|Ow?h17!z~~g&)R59p;BIL8nys zVNBFvezc4ywJPGL8eZdClY|cQqh*+9tI%Og)XCLydocBgIRLes!ZTw$VB{>SfnjUN z7^h&W=!w)~j8ibN7VC>KL8n%DW{d;OG*OFrW=zz{Wi0p!$1vN=Gez%=DFukC{5*xyoeB0Y>)a0VDg0o^8fY z1sFMZ3mCL_BqRHZejLe|WKhN!6LnZt854EtOkWl-Xbq1@4y%F5&D|;(2N;z3BQY@5NUO2#@`=MmyJv{2nGEDIN(Bz+OEMTOcVqnJk zLC;Z=N%_g01r{)J4W|R+GJXocpmR_%Xzr3h=b&U{Hlm+g#!A4TeIXf?L&n5fxg1u2 zN%hV$udOvxWFyCfz8)!ZC>c~sGN>=cctx#ZU|3cqgVs{a`Uo)L4BPl)=)BNrYDN^ zkqlZNrW0$i97+bQk5(slE(brSiabjOopGlof3GV6gFH(H_0DwM9)8%|C4=V9bR1w( zvtTooOlp1D-Z@jO&l&Mt0S5VDI-%CNU{DSvgU(9Hpx@@_Vtvr>rVF8ies^C89r-)O V0%iu7CxSUN<~uy0NB6fQ005=k@%I1# diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt deleted file mode 100644 index 377d1f6c31d251225ec8721e39807d392c8a1275..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 950 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 Tb7_3iN+s@YjgM=-x0%_0oT?!6 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt deleted file mode 100644 index f548aa5ac9790c9033ff5d831a8d965fa3f77c75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 927 zcmV;Q17Q3giwFP!000000IipOZqq;z#W#)Z{cuYtRN@?b{lg&;H$W!1C?ZXw*i^th zxes>PMeX$Mz5%6@r6&6I?VFi5D>oS9jXiYRejNK?jIqIl56AtXKaQJzaHi_MZw9mY zVWwZ-cQ?Jcy4mdd^|8Ai-wlW3w{`zUuU%AhlVeEG6-Yi}^6Q=Kn>5G0hn)fmot~@dIbRxkJFD$? z)2D?u&8O{t{dJi0^vj#&VLzllY0RG=yEOG=X6)}iJ!GtcNjgrUQ(|VFg~AVGk`D93 zm|5pc;fFCvhxuVllUSm|n54t}Xqal&yT>d9;{bC8{8Wm%7~=pV{iL%rb+K90q;{)d z9AHp?YDIq-lXO_^jA`P-{4gfzFh7h*I-W3hwH5kYr}M}xB!lM8m~R7 zI*ZLhGC9v|7LN4U0tW34W4z+5I`xRmT{39yl0mazj8~i$6rNLEY+jN5h+I*Z*2l0p04Dsm_pltZSI z&SLv6nVg@N%fMPrc+187W_1TL35W3y2m7g_LS)ag`X-iu25GEnB2TdIkXBLr_k{VouH^I)z02G zB!hNGGU)zcIvy}N&p|OSc8^IWH?NY8`v*U*Vt3e`$#iBvPYi#Tm>G6&NCwS|=`@jH zcYCor9$@KZ;ov^x!8a&@tNmrSnDY~PvZR99)=8^EBwU^-60c);ZPT-rek z7_=8FMV=*t&RQw5DjAejrV{{z=CvYow}3(Ol1#2Y?0t2mn5krPeJ<%Zg--HwKO1$% zPbok4A9UIRGkbn&%I}9ZGNpGv2N<+pOedYi{+E#q$_CSEBI64Ev4F|dUdo|Y=mdqI zIx?QjT{5{omvo#$$18M_=lfZ0GM-C$whEn@xfB^gbx8)*#dMm;SmIeSC_j=x`C&Ri z;U{@^iXN77=m3-JA-`ZCo005MR B&Vv8| diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt deleted file mode 100644 index afa43f11db8376cda9f68fc8149691848b6f4bca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 921 zcmV;K17`dmiwFP!000000IivQZWA#O#hqr?Yj0CpN+r(0$6p)*aRamj7e%B=lwB&| zvRsATup^b>*>5UZX{9#$<-PIDv#q49bI~=2ZkvW7wa&RZxaxg(m)yEm|)rFHFxv>RM~+im;wKZ38GTJX(N3%9FV-K%1i&D#+ORIh)bnHUV(Vgz=){6oV_>{IM29i;%&?hi z2Cbbj;>G%`nVc8fUtaYP?Jv#bdT5zNTkxu7t`C@{Vk+?~Fg0M%x-_F}7O%!oGs}i% z(7YHUUMw4$$$6ES)48H%QGt3iqi4|oM)y$8GGFkj0E6bP88mmzpgc1s7`&urmLJWa znQ8{jlrh2JCH1h3X(m?>yT6!M1Wc~a(U1*x)@de}jS>?KUeQpqtgAKb!M32|0i){) z1|9J_C-p>E-lx^fG^A$Dpo}p_yh{100fREHnOr?A^UO=?VOiA-$|_@m!Ao@5-93E- ztP0ui2Bw-BcJF8gXsB7%#qK!Gp#7y8 zw7(b=3|=y?U|1JBH#C!57dtl?6AWI_P_wLy-Ibcj<&d2}j0py>_=uX>J*b)7nZWK! zi`Tj1`;;;D%&@(q8I&=`1cO&KGo`)b0h3!h%RJMO{*4+E0s%COCwdj=2 zx~ZNEL&g{r0E4n|VaSGNP&OD73|ubSu}t_Gi5sBRq9~_7&Hs34(s!!E8iD>W=eaf0Su~{>4+Dbg=Ww!m`(%?+FzH3 zJZmP`A2w5_BVH`?nn5~OhM8&x<@w4mFU_ENF&*(@ebx->vsH)n@Hxp(0~l0~RfpAl vZP2+Ud7hXTikZGosQS&%B+&E$A-65Gm{2sk|+ zGbO>}b-%JmBrA#ax$4#0ZObWy7~0+Prr+=T6hdgbP`zK?_Tky>deg7&me>1t!|v|e zs{eSi{gOiZaJSv{cl&ie9LVMO^$=!1La^1dJ7h27`%uwQOgeVD!JLOMJ@ z9G>Vm`%qsmZ-)MV48DG7gKr<&;H!r=`0}9*zTgI9Xg=L+S6>gW471A^=DY1MKQztw zXv6QHb{^`3nSFo!?{B7aFlMK7*eNliotZd?SnR=;SRgBqDy{ec< z7}T5ygRz^PSYQ%iuoer#VBM`2$uT?0(LW_-;qYa87KPbq2*WfV=d7Tob1>1t)b?A< zDKc2EmM~cN&S57y7}Km~85z{m5(axdI_y+t&!JiE4P@BfK!(k`Vxq&BX)eusLztXq zwWAah9llI+X}2_l$@NAo`05-?bofdR%@$W_M>T}W&1n)f9eY~MJ2GtE6;n@)nq_2I zy^vw`QcQICGCgWekzqZrnCS3jdejUelhdQ_*p;K_YmvihV${w=hSdTY7CSO5cEv=8 zujJ5dv2}%6t_YLMkJ``3Low0eD>*bMTHp?Qmq+4p&Tc_(~^eUKE&?FzBmuFwOK(cWh+X`E}GS;zEYi0vT2dWLO_6JEmEk zxyZ2DL59r^GHh=sJEmEk1<0^nhYZ_wiZNemuOgH4rS_`wWqQ=ELnc=*wd=gT)NWBs zGubN5PDdEl^R1)jkzsKm!*ZyY=Mq)eJU3=b z=s||*QA|9+mx^66kudD8g$(QGk%f5tGPJ7M-??)IC>Qs)~kv!U#fqQ$;DM-qJv2eJ*HXp1~RNSl$}VJTz*P*A2pvj zYKjbt{mfA>WLUkF9rLB~j10@OvJ(lDi%ZQHGAyohM-Gu;H9dFa2N{+hWygG}vl1DW zAFmyCo?bZm85wrQT|l1MK17CTMux?%?8FoFsJbJ=>aOfW!sKe9YKlxQKWcU^9r?Kw znp?s!J<87L>k1gwhsZEJR}edk>oM42pRXdr^gJPUs$u=JH)vd9PsiW$(B6;VE8A|u P_*I8recwY}e<%O|;X5MY diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt deleted file mode 100644 index a9b8c42934cf9a174cd04b51f3d943de6c700315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631 zcmV--0*L(|iwFP!000000IitqZqq;zMJM&g?z&LgQmM~TKK}3!h&MncY>`D8M_E(R z{^HT`7LOE$vF}tQQsg8$K6__o?L=va0=ZqgiNg>ZBC0)=AKSY~S9jeuuJ`Tj@FDH? zKi2W{rvKJZ^J(Aj;(q928p-x&muU4s#AjXqdsb}kV-hF&uU#72?K;xx##1wXp2iR2 zcA)CE-K6+G!Z*hjzCE_^-LZx5bzz|T%cfs{PkFGv0u{SH730hNtm)6AE~pwcLwtJo zH{%Qpdz`_u#AMIPkOwjBL3t39Jtu}dh+z-PgP59+z=Ig}pgf4lp3;y9G3-Hk5R*NX zArE5MgYqDz<|ptVhCL{cmGKA6N?FSpG9!jPC=X(Ck9|HKFel1dl96?>rv|l4M$3#m zUSVWr&f^SuP!AE~jcWzNOoJg0VzQ?JYXybT=H3|cAjT_<>`zb_ZKkJ&y($@PubvwA zs${g@bFsUfGL!G%v??kx^^TpHw!dV>lBAUo}|vcI!8;>klP9)o73CU|R5c6+va+DhJ8?PvOPi!uEBhjk~pd z-L5To|3ASTl&d~ahFFJ{hNXtTg!DM5wN2P1Ihg0VEq88+|0)OBwQelY@bw7^IyB?) zwBs3h#v~JrI%5Q3)T!?GU6L^Jn~^h&Vi?8rLmBGJEYKPIQ8SEU7;c7?p))iKbjG`M zBn!&WEX)F(@h-E#mx=fiBzMi|h)5QOVYs&;B6(?s;pQyJd^qovnex6wCpKpp@nsk$ O>^}iwk}b3X1^@t^KAI)~ diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt deleted file mode 100644 index 00b632503a760a3d17d050e1afdabb0c505708dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmV+y0qFi8iwFP!000000IiYhPJ}QJg->bA?XM<2hnHVIgz*hb#aYwHQo_`Y`t+7n z40gL<%#sjj^UaxaW@?~9(VLdMry78+QQr@)r@>p|66KR+Z@PvcE=$zmp2G!o9(rS1 zCX`TjW=pu(+K!sRZ2T?v!)rqiEtwrLB0*)|EJM8i6rLXzy63oRX5;!KHfDlXrxv{V zpI`;W_Jd^D!uS@`SEAUBYOV_>Q6Yb9UGu`@w$3WZ-tknT@bxGO9n5&zpMEns!H9^F z-;ACy8PdJxj6BjyFZjv-pffS~f*-xl5&lgHMqP|KV)}003KUi!}fM diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt deleted file mode 100644 index f98ae16da7fb8b65ec3698afc68a18190d65b979..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 720 zcmV;>0x$g^iwFP!000000IitoZqq;%gx9xS#|3^N@f_U#@DPYMKqhQaM4CjgseotU zVX=!>il*b8Q;|xR+UU#doSidi)y}z%3#Wb`$1!%!Ip4baV}BRj%e&nnZqNPg_+dDm ze{AFD{qbApx=-ihDW1n&944~=xf@*Z%enNfSC8Kn`};V+8{4nDVeAjv=!&!#O- z>4kV0U31&-hxk8&Z>}x)?%IN{uPykV3vQhMvOjLW4|A}8Hm*7yhidwEerosctEpTw z$&B&gr^ie&J>>;c08=eYm0@bal)y9w9Z#4Fm~vrigXcQqrzT9j;yI_|4SoV)aIWOJ z$@r-WgPAr49ZwjXD-Z_fDwf9^^74kfydf`d$SbGg4Ss@Qt~7hNV49WLgCX}|=vOfG zE2rb1;HS+nje)6``E#EMBy6vh=GJb5(|ZA;YpjhGn62yunZM zth$2?>kcxkJ4(kJ{3Oq6=aE^vXSMTIo!lOli4!}I4BL5R*3MFUhzy$x8FoKPr&t*E z8IBCwLuA+fngVOb!< zGF3YM34T-uky*P#i;n8o#*is8%#YGZXQ?cZVOc1hbe6gwWSF1MFjpsXuL;BM(5j>6 zx)I$;j5_Pa<$tHl%rnqo%yVGozt!tu_d8ye;>8?D<-+~^zvAQJLFz9i7{ibP7ytk^ CLvi8& diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt deleted file mode 100644 index 195d49488a3bbc235d603ac8d06ef81cc5dfcb84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmV;K0cQRmiwFP!000000Iil$PJ}QJhKFrSfoBuXp}zUx5sWu56}yJW0-<%Io?cjK zVrB<2%_#)pY??@fU010b!sJYVJA(Fe4!cy2;;UF{*eE})w3hv|mzBAC5vga3>0>c53I zw6KKysqO36FvoURf*Sgurmyp5;QON$m`M};>DM`vP1o)RlOaYgjM`uf!R!!|3p|!! z6k^oEXhF?-qaH&rIGg;GiKA55M;XIaL*81AYN2eSa4`$XpT<@5ndgnZ8udSKtG<&8m%usXZJZUekcg#?| zOFi67t>D?f4Ar~DQ=ojP|BFK4DG@V!bZ9<(f@aD5K4TTw^2VFmVaJG3t$&0$@E8i%0f({vd4{uu>k)eU9&K#2+GgNk|hs%W-YF<`wZ(xSXZUsGKhRV))axHFNn4$V{f?Q6J3o}$Msb{I@ s)K7^#RCdfzwJO4+L-*k`lqBiOEA~Ep+L7NFV$Z!R*`^{9gpO|1Ee$ z3vR$Zj&uJKj$^yofLi9D(&O z81;*vl1?M=lRfK#jwTrF#}EvjvlZwx0zcWa5zN^L=4=FWE-|^5E%-46L;0x%xnqXP zs}|&i87ePMC)eWUj2TKtF})iBlXbY>F+=sv>Ev2m@0g)7<(OQnv|~1N%pPi{_so?1 znA{uF7iOqkHG;e_L*>Qk<}Z=)Y$G diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt deleted file mode 100644 index 4521bd6fd24457e84cfd2834e262512383da5b99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 347 zcmV-h0i^yPiwFP!000000Iii#PJ}QJh6mbG;Mv4e_~82HA&fUL6=w~R1w!jaJ-u{g zH=FLzj!}{ZXuke4^G}=B02S!bbm$z`03b_{4`zpOwQGB9CbM<-cAVZDeCmeR8tTVs z7;$nf+L<&Tt%d9p;JE7gauu3A+F)V%(pqQw1|hpEp`PdMJb}FfwKbi^zX)#rTkw_^ zte|-AhUU$B+iofl<6y=7>4$`$M+s1~jKjmKXU&*W3qtBmmwpJAefxUCuGEm zj*2jnVAkp?7&@;uo<}9)?Wl;ZZAAd%iHSd<27$ z1Vil~$>@8?P_Y!F?>G|z?zzMV007#(s;vM3 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt deleted file mode 100644 index 2a8ba15bff3339a00e798504189789a82a03202a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 308 zcmV-40n7d$iwFP!000000IihUO2jY_hX0zRr)$AWpTWbG4Ms)W4Pd&2p??Wq~{&fVEzd~4{jGcPsjhtUi) zx|Xab^?PfPeE@US#c>ts16fvBKDXBCz9D4SC2GHK{RZ_8YNtC({}EoDT6lA6;cZ-4 zA%E&j^J>E!E-Q$^Sm9s8QuuzPfbtqg)7NiC`jv(EA54a04`hRvuCSk&cw2BdFHd$a;XRt>qjKaR3zl$Oe|NbXKSXMiDj1w^OCHe zCC}C@B<2%_#)pY??@fU010b!sJYVJA(Fe4!cy2;;UF{*eE})w3hv|mzBAC5vga3>0>c53I zw6KKysqO36FvoURf*Sgurmyp5;QON$m`M};>DM`vP1o)RlOaYgjM`uf!R!!|3p|!! z6k^oEXhF?-qaH&rIGg;GiKA55M;XIaL*81AYN2eSa4`$XpT<@5ndgnZ8udSKtG<&8m%usXZJZUekcg#?| zOFi67t>D?f4Ar~DQ=ojP|BFK4DG@V!bZ9<(f@aD5K4TTwg-z_p3*;GKHsLm1z{RGc+L76`2y_33R< zyqFyrHcHX}%{S*vJ42}eO0a`#F$AmtKoy|w-2vg^&~#XjZXfRaFuv9J*!C|KR1af6 z;20Y8k#z5khwKAjj=DUJLU%+@0*mLy2iMgI*>wR`ocD18y8wFcT91Dby!mgzTVAjP z^VIhBt54f@RYE@WK97%SX!yQ#4m!#NoZe2EOkh+TJHlj)4rMs6#F!NwHQxmO~o@UX=un0`H>|LS>W7iMB*vVfV^(@2F@?}SGh>8) jE{RTJly5$9hLT7+|BD>#G5sU@Zc6(LGi*vQSO)+A4V#>h diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt deleted file mode 100644 index 9a1f793b52b221bc9ebdbefea37cc33e00662a4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 402 zcmV;D0d4*tiwFP!000000Iil$PJ}QJhKDU}foBuXq5HOnFy6paoHaxi2(26S^wL$# zW_Dm|l!T;^um4Q{nKrEeO0a`#F$AmtATJ=la|eX0L(^eBx_#LBVSKIeq3xe5sP4yp zz%exFC(^w&9422t`cfN z8Lk$oI%^&phT(F~g`WT6gndC7&S%QdoM$bm$0)=3LmAFzNoS5F^)qES9W8ih7>0|b z6V^o;ZZA`2DVEe@lv&bQ+sk_HSE24E!5_+SwJ-_&LmAHJR2}K8v%#3_-yFVY1H^hNslM<1f-8x*R`v_>4uu!JDZ z(^q17Lb{mS8KVwB#5R7Kox9z;J)Km#E_dQZ--CchCJ?7FG+tqoX&@*`=#6cl)7^H`|0wB z<>}mw?+%Zrsj~|5w|};PWfWV0+0Y?)v*S5!%pK9Wdg{rz z7?U?f!aDVOQvpmX7hbFxFfGqs|LOr_{S1Jyb2tK~l~a!?f}aU6 zt@XwFpk-Qno!6H~z}Wdo0+WSUMetmGdp&mmOshA|j-MdtM1e^{tSsnMKi(N23QPhF zinX4BNG!{s8e8X@)EHv|V9-1>CJV7{p2)so8MJROCJC{!pi=~${l<9xy$6hqH2}u; zrcq!rV9=h){M2!I{k;cFs}7?RD*(oNj)G1Sm?C(dgt5YJTg7&8K< z)l=BnhUsKMrwBTATB8T9^?>C|<~&H(HE1<|n#8rOPuA+^ewATUW_Zu2PkVZEE_ zWP!PjO_)Qk4~~GbYcL2pQP4?(P8OIVjD5c`tiM~Pl~dN=850F23rrC_PXaRw^Hb;0 z>)kzITJyvDJJZR6&Lrr}fN9l_*WY`Vgwz)E1KOF#L$2AH}5Mo6^ zCkZ-PUSw)EAbrO&Xk1Ju0><9= zCPAladA)l83|bdVCkRXgOlw@8&MmK`#w^py7drzmCJBDBz}(`IGrwifT4qcD4BCH~ zP7!n_ftiI^`;GD53kSfUdkM?5a_aTdEa()#*!!PJU}hm!ogdaKEz{Z)Je>#_)ZrDYLtvY1=i}@*n&Ll9i5Ub9QcPHEfrZtD&J|6@o0tWRjrc(sZlfYEZUN4A%Y2}@L z)_-N#KF^p0nAW)1do;_mVktV_d%gAh6dk{ZT+bz>e=%kR44NOypgXHf)?g19dxjhY zW)xxtz@S_(rjCo9S1r@Z1zYcoNrIm`cJDK(8p~T3mGSC%{r(H7pAj&qehSG&4;VDh Zj2T}Mi{*VHIs;_7e*p0Q4AoRM005tey{!NM diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt deleted file mode 100644 index 2f46f612b5b9ce64f228e079ab075b2ebcb15588..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1233 zcmV;?1TOm@iwFP!000000Ik{EZW}ic24HFrJZ>)v^dWlNr0qo?qUakGs=FzKIF{iR zf;3Oxl}Z}U;OERA!~q1y#;2L#lFOl1*}3Gx-PWte*Cby??0R#*1MDHQJk3jrP;GN2|-=^H(f``j$`HTauf$ z)8}>E7vA;t-E{$8e~vDEycT?Z*nc}D=l{At-@V`V1$y`~x$*J5wYPZp|35#vc^~g( zz5Vv3nXf_i*YLs|gh|zmipkYXiW#bz72~VXYF?@dN}N(nQp{9MCh94QiG=ZO{4dM^ z=3)?YAx#7ZjcX9|)r+IeX(HmZd7TuKfEmI1vEmfM4D~fDW+6*Z?dr&ipFa;P{bE`+&!)IW6 zHESjlxe73-=iV%_XKE$^)62CeCIHi`M~ma@d>oW(I9D?m_k}caPY6VusjUy9o>9r= zfsy-91P1Nlx0;OgY#9$s=+vY2ua-~S=RGiTk4nJE>yv?z*SQd8A!;6~vHFfQGS>_Y z>M53qz{Jiq)XYNE+{PXhGXf*$YXYV>uAr>LOw>~dvjEeZcdLI%BggK6L48@8-gVY` z+ysn_6A6~V!K3z2K6#_EI8pgt%KIs;g_0+A~bCKIL*rd=Pce@(#j)|h4@VG=N? z=UQ>voN9e=0tP)#kOn;~kOrN@tz3yPnJ@*I-oByrWlxv@OmFO3oD2*)Z(L0w?yo|u zLnh9mm_Z07mwd zNaT86i^RCJGr&y5@kE?Jm`IpJ)RPHQ2=hEPqvuM4zR$Jd1j0ljS0dtM!W6%utPWPLM{<`$WX?z@VODnMmYHM9rCq)9TjF5)&}J z{aK3>2$Kktfstb`M4UEX*0T#~di#d;?81uE>e0?E0T^`FV&g2txU}<+ud%c<$y|-~ zTwNMevlXZ1(#{edm|iZ;Ox0Mu+cMAdVVotTL3_9rClDqQxe^g46Q+E{*tLCr1_nL< zvEl?^(0w5dIwx3hhH9+m#?tiavHFE&S}yC^vSl(b==@{FY4fE$?+w88*0c3}t`(={ vvOZTz(~G0+t5c0--KUnBTTL$v`aV}0w0@$oR&zC9&Z+wk-9QLxR4f1hzwU9E diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt deleted file mode 100644 index 50664726f4f87bf7e4c7a86f5bc5082fa43c38f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 863 zcmV-l1EBmLiwFSuBV1kp|E-y8j?+L8gvaxC{vmM@oV=J z2M-FZn(hwDN|tt`FV)r4Gi7J9F{U@^H0;YXm5nhbW#c~%PsO}=+8xUFJUmPvj>F^U z{qftzY(AZjr*fWlWt_3$`))Md4`b?EUXr(z;kk_DUHR*7oQA`;nC@*hoB8!|exV#D z6CQ^BSpHk>{aw}G-Bs<)UDaOSRqYj4>rMQ!KW-n#WmEj>jXNDjH~+d^!Tk9N&V*TJ zDwn_hW#W8w^JTA?jxgPN`76c}CM%e*GMpc~GLi99J?AUNfm#q8l;^VhpV zhua$wFagX|s?}9b3=;tp!AvEcT8rC<7BIAT4;YkD5|eN66BM)H&P7(})LN05sRIn1 zg$E4v6BJAj7?drS^UCz)07Lr-umx<^h9pl`<$-C7q=3lL6DpA5D%) znMoOxnUYS`;_}A>2CcKC6BSHS)XEB-Ze_TPvVdvz#W7jIR6kOVQHGu`uVA8rsl9WV z5CDVD4rNeANjh2Kr+Sv24=IE01(ZS0hmuZK_^F<`Z1I3W*-M$$+&P`3@RI@4$_*}m z0$`}0>YF?79x!MhN;*lQ)2$45mMvgfeQ}Hj4BCg1PE;^SQ7bES>iTfcNER@(mQ(0> z1rrray1_G-Q2{XMo-64j1(OxEs%I$=DbreK>Df=J6%{%OFs*&a>D1o2taE@t_fttH zD43{Vl7h*AY0Z?&RSy`HtC#;X3Z5m#t_+u%PQiG*tJ@~o+)IXlwlxGe0Sq+smINS_@jgPz&4 pus$9zi;f?6KTCy{@6DDE@x3$YdHH_rcreSO!EZP9InHt&008=_q;3EJ diff --git a/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt b/TerraForgedMod/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt deleted file mode 100644 index 5434dd9122e173f7af8565d8d10978779ca16a92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 867 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 diff --git a/build.gradle b/build.gradle index 04634f8..bdcefd3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,113 @@ -allprojects { - apply plugin: "java" - group = "com.terraforged" - version = mod_version +buildscript { + repositories { + jcenter() + mavenCentral() + maven { url "https://files.minecraftforge.net/maven" } + } + dependencies { + classpath group: "net.minecraftforge.gradle", name: "ForgeGradle", version: "3.+", changing: true + } } -jar.enabled(false) \ No newline at end of file +apply plugin: "net.minecraftforge.gradle" +apply plugin: "maven-publish" +apply plugin: "eclipse" + +version = "${mc_version}-${mod_version}${getClassifier()}" + +allprojects { + apply plugin: "java" +} + +configurations { + lib + compile.extendsFrom lib +} + +repositories { + jcenter() + mavenCentral() + maven { url "https://io.terraforged.com/repository/maven/" } +} + +dependencies { + minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" + lib (project(":FeatureManager")) { transitive false } + lib project(":Engine") +} + +minecraft { + mappings channel: mcp_channel, version: mcp_version + runs { + client { + workingDirectory project.file("run/client") + property "forge.logging.markers", "SCAN,REGISTRIES,REGISTRYDUMP" + property "forge.logging.console.level", "debug" + jvmArgs "-Xmx8G", "-Xms6G", "-Ddev" + mods { + terraforged { + source sourceSets.main + } + } + } + server { + workingDirectory project.file("run/server") + property "forge.logging.markers", "SCAN,REGISTRIES,REGISTRYDUMP" + property "forge.logging.console.level", "debug" + jvmArgs "-Xmx8G", "-Xms6G", "-Ddev" + mods { + terraforged { + source sourceSets.main + } + } + } + data { + workingDirectory project.file("run/data") + property "forge.logging.markers", "SCAN,REGISTRIES,REGISTRYDUMP" + property "forge.logging.console.level", "debug" + property "fml.earlyprogresswindow", "false" + args "--mod", "terraforged", "--server", "--output", file("generated/resources/") + jvmArgs "-Xmx4G", "-Xms2G" + mods { + terraforged { + source sourceSets.main + } + } + } + } +} + +sourceSets { + main.resources { + srcDirs += "generated/resources/" + exclude ".cache" + } +} + +task collectLibs(type: Copy) { + dependsOn(dependsOn: subprojects.tasks["jar"]) + from { configurations.lib.collect { it.isDirectory() ? it : zipTree(it) } } + into("build/classes/java/main") + duplicatesStrategy = "EXCLUDE" +} + +processResources { + filesMatching("**/mods.toml") { + expand("version": "${mod_version}${getClassifier()}", "mc_version": mc_version) + } +} + +classes { + dependsOn(collectLibs) +} + +static def getClassifier() { + if (System.getenv("GIT_TAG_NAME") != null) { + return "" + } + def buildNumber = System.getenv("BUILD_NUMBER") + if (buildNumber != null) { + return "-${buildNumber}" + } + return "" +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 01967c6..b38ed21 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -mod_version=0.0.14 +mod_version=0.1.0 mc_version=1.15.2 forge_version=31.1.77 mcp_channel=snapshot diff --git a/settings.gradle b/settings.gradle index 4448c28..d66aaef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,3 @@ rootProject.name = "TerraForged" -include ":TerraForgedMod" -include ":TerraForgedAPI" +include ":Engine" include ":FeatureManager" \ No newline at end of file diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeTags.java b/src/main/java/com/terraforged/api/biome/BiomeTags.java similarity index 98% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeTags.java rename to src/main/java/com/terraforged/api/biome/BiomeTags.java index e411af3..4d9db20 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeTags.java +++ b/src/main/java/com/terraforged/api/biome/BiomeTags.java @@ -25,7 +25,7 @@ package com.terraforged.api.biome; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeType; import net.minecraft.tags.Tag; import net.minecraft.tags.TagCollection; import net.minecraft.util.ResourceLocation; diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeVariant.java b/src/main/java/com/terraforged/api/biome/BiomeVariant.java similarity index 86% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeVariant.java rename to src/main/java/com/terraforged/api/biome/BiomeVariant.java index b98d854..3bf9895 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/BiomeVariant.java +++ b/src/main/java/com/terraforged/api/biome/BiomeVariant.java @@ -25,6 +25,7 @@ package com.terraforged.api.biome; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.biome.Biome; public abstract class BiomeVariant extends Biome { @@ -49,4 +50,9 @@ public abstract class BiomeVariant extends Biome { } public abstract Biome getBase(); + + protected static float getTemperatureNoise(BlockPos pos) { + float value = (float) (TEMPERATURE_NOISE.noiseAt(pos.getX() / 8F, pos.getZ() / 8F, false) * 4F); + return (value + pos.getY() - 64F) * 0.05F / 30F; + } } diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java b/src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java similarity index 86% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java rename to src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java index 773b321..7149583 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java +++ b/src/main/java/com/terraforged/api/biome/modifier/AbstractMaxHeightModifier.java @@ -26,9 +26,8 @@ package com.terraforged.api.biome.modifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.core.Seed; +import com.terraforged.world.climate.Climate; import me.dags.noise.Module; import me.dags.noise.Source; import net.minecraft.world.biome.Biome; @@ -49,7 +48,7 @@ public abstract class AbstractMaxHeightModifier extends AbstractOffsetModifier { } @Override - protected final Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz) { + protected final Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz) { float var = variance.getValue(x, z); float value = cell.value + var; if (value < minHeight) { @@ -63,5 +62,5 @@ public abstract class AbstractMaxHeightModifier extends AbstractOffsetModifier { return in; } - protected abstract Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz); + protected abstract Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz); } diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java b/src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java similarity index 85% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java rename to src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java index d0a6a43..6727c52 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java +++ b/src/main/java/com/terraforged/api/biome/modifier/AbstractOffsetModifier.java @@ -26,8 +26,7 @@ package com.terraforged.api.biome.modifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.climate.Climate; import net.minecraft.world.biome.Biome; public abstract class AbstractOffsetModifier implements BiomeModifier { @@ -39,11 +38,11 @@ public abstract class AbstractOffsetModifier implements BiomeModifier { } @Override - public Biome modify(Biome in, Cell cell, int x, int z) { + public Biome modify(Biome in, Cell cell, int x, int z) { float dx = climate.getOffsetX(x, z, 50); float dz = climate.getOffsetX(x, z, 50); return modify(in, cell, x, z, x + dx, z + dz); } - protected abstract Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz); + protected abstract Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz); } diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java b/src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java similarity index 93% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java rename to src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java index 2d81330..9e31607 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java +++ b/src/main/java/com/terraforged/api/biome/modifier/BiomeModifier.java @@ -26,7 +26,6 @@ package com.terraforged.api.biome.modifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; import net.minecraft.world.biome.Biome; public interface BiomeModifier extends Comparable { @@ -35,7 +34,7 @@ public interface BiomeModifier extends Comparable { boolean test(Biome biome); - Biome modify(Biome in, Cell cell, int x, int z); + Biome modify(Biome in, Cell cell, int x, int z); @Override default int compareTo(BiomeModifier other) { diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/ModifierManager.java b/src/main/java/com/terraforged/api/biome/modifier/ModifierManager.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/biome/modifier/ModifierManager.java rename to src/main/java/com/terraforged/api/biome/modifier/ModifierManager.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/ChunkContext.java b/src/main/java/com/terraforged/api/chunk/ChunkContext.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/ChunkContext.java rename to src/main/java/com/terraforged/api/chunk/ChunkContext.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/ChunkDelegate.java b/src/main/java/com/terraforged/api/chunk/ChunkDelegate.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/ChunkDelegate.java rename to src/main/java/com/terraforged/api/chunk/ChunkDelegate.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/ColumnDecorator.java b/src/main/java/com/terraforged/api/chunk/column/ColumnDecorator.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/ColumnDecorator.java rename to src/main/java/com/terraforged/api/chunk/column/ColumnDecorator.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java b/src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java similarity index 86% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java rename to src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java index 2181348..45ae033 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java +++ b/src/main/java/com/terraforged/api/chunk/column/DecoratorContext.java @@ -27,11 +27,10 @@ package com.terraforged.api.chunk.column; import com.terraforged.api.chunk.ChunkContext; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.geology.DepthBuffer; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.climate.Climate; +import com.terraforged.world.geology.DepthBuffer; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.world.terrain.Terrains; import net.minecraft.util.math.BlockPos; import net.minecraft.world.biome.Biome; import net.minecraft.world.chunk.IChunk; @@ -45,7 +44,7 @@ public class DecoratorContext extends ChunkContext { public final BlockPos.Mutable pos = new BlockPos.Mutable(); public Biome biome; - public Cell cell; + public Cell cell; public DecoratorContext(IChunk chunk, Levels levels, Terrains terrain, Climate climate) { super(chunk); diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/DecoratorManager.java b/src/main/java/com/terraforged/api/chunk/column/DecoratorManager.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/column/DecoratorManager.java rename to src/main/java/com/terraforged/api/chunk/column/DecoratorManager.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/CachedSurface.java b/src/main/java/com/terraforged/api/chunk/surface/CachedSurface.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/CachedSurface.java rename to src/main/java/com/terraforged/api/chunk/surface/CachedSurface.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/ChunkSurfaceBuffer.java b/src/main/java/com/terraforged/api/chunk/surface/ChunkSurfaceBuffer.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/ChunkSurfaceBuffer.java rename to src/main/java/com/terraforged/api/chunk/surface/ChunkSurfaceBuffer.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/Surface.java b/src/main/java/com/terraforged/api/chunk/surface/Surface.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/Surface.java rename to src/main/java/com/terraforged/api/chunk/surface/Surface.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java b/src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java similarity index 92% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java rename to src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java index 923351a..684ff89 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java +++ b/src/main/java/com/terraforged/api/chunk/surface/SurfaceContext.java @@ -26,9 +26,9 @@ package com.terraforged.api.chunk.surface; import com.terraforged.api.chunk.column.DecoratorContext; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.climate.Climate; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.world.terrain.Terrains; import net.minecraft.block.BlockState; import net.minecraft.world.gen.GenerationSettings; diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java b/src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java similarity index 70% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java rename to src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java index e0578de..62c3c7e 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java +++ b/src/main/java/com/terraforged/api/chunk/surface/SurfaceManager.java @@ -26,20 +26,42 @@ package com.terraforged.api.chunk.surface; import com.terraforged.api.chunk.surface.builder.Delegate; +import net.minecraft.util.ResourceLocation; import net.minecraft.world.biome.Biome; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class SurfaceManager { - private final Map surfaces = new HashMap<>(); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Map surfaces = new HashMap<>(); public SurfaceManager replace(Biome biome, Surface surface) { - surfaces.put(biome, surface); + lock.writeLock().lock(); + surfaces.put(biome.getRegistryName(), surface); + lock.writeLock().unlock(); return this; } + public Surface getSurface(Biome biome) { + lock.readLock().lock(); + Surface surface = surfaces.get(biome.getRegistryName()); + lock.readLock().unlock(); + return surface; + } + + public Surface getOrCreateSurface(Biome biome) { + Surface surface = getSurface(biome); + if (surface == null) { + surface = Delegate.FUNC.apply(biome); + replace(biome, surface); + } + return surface; + } + public SurfaceManager extend(Biome biome, Surface surface) { Surface result = getOrCreateSurface(biome).then(surface); return replace(biome, result); @@ -53,8 +75,4 @@ public class SurfaceManager { context.cached.surface = getOrCreateSurface(context.biome); return context.cached.surface; } - - public Surface getOrCreateSurface(Biome biome) { - return surfaces.computeIfAbsent(biome, Delegate.FUNC); - } } diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/builder/Combiner.java b/src/main/java/com/terraforged/api/chunk/surface/builder/Combiner.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/builder/Combiner.java rename to src/main/java/com/terraforged/api/chunk/surface/builder/Combiner.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/builder/Delegate.java b/src/main/java/com/terraforged/api/chunk/surface/builder/Delegate.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/chunk/surface/builder/Delegate.java rename to src/main/java/com/terraforged/api/chunk/surface/builder/Delegate.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/event/SetupEvent.java b/src/main/java/com/terraforged/api/event/SetupEvent.java similarity index 95% rename from TerraForgedAPI/src/main/java/com/terraforged/api/event/SetupEvent.java rename to src/main/java/com/terraforged/api/event/SetupEvent.java index e05a98c..663162a 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/event/SetupEvent.java +++ b/src/main/java/com/terraforged/api/event/SetupEvent.java @@ -30,9 +30,9 @@ import com.terraforged.api.chunk.column.DecoratorManager; import com.terraforged.api.chunk.surface.SurfaceManager; import com.terraforged.api.material.geology.GeologyManager; import com.terraforged.api.material.layer.LayerManager; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.terrain.provider.TerrainProvider; -import com.terraforged.feature.modifier.FeatureModifiers; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.terrain.provider.TerrainProvider; +import com.terraforged.mod.feature.manager.modifier.FeatureModifiers; import net.minecraftforge.eventbus.api.Event; public abstract class SetupEvent extends Event { diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/WGTags.java b/src/main/java/com/terraforged/api/material/WGTags.java similarity index 91% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/WGTags.java rename to src/main/java/com/terraforged/api/material/WGTags.java index f2c741a..9cf6f76 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/material/WGTags.java +++ b/src/main/java/com/terraforged/api/material/WGTags.java @@ -25,7 +25,6 @@ package com.terraforged.api.material; -import com.terraforged.api.material.state.StateTagPredicate; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.tags.BlockTags; @@ -51,6 +50,10 @@ public class WGTags { } public static Predicate stone() { - return new StateTagPredicate(STONE); + return toStatePredicate(STONE); + } + + private static Predicate toStatePredicate(Tag tag) { + return state -> tag.contains(state.getBlock()); } } diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/GeologyManager.java b/src/main/java/com/terraforged/api/material/geology/GeologyManager.java similarity index 95% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/GeologyManager.java rename to src/main/java/com/terraforged/api/material/geology/GeologyManager.java index dd46b94..b8a7c72 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/GeologyManager.java +++ b/src/main/java/com/terraforged/api/material/geology/GeologyManager.java @@ -25,8 +25,8 @@ package com.terraforged.api.material.geology; -import com.terraforged.core.world.geology.Geology; -import com.terraforged.core.world.geology.Strata; +import com.terraforged.world.geology.Geology; +import com.terraforged.world.geology.Strata; import net.minecraft.block.BlockState; import net.minecraft.world.biome.Biome; diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/StrataConfig.java b/src/main/java/com/terraforged/api/material/geology/StrataConfig.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/StrataConfig.java rename to src/main/java/com/terraforged/api/material/geology/StrataConfig.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/StrataGenerator.java b/src/main/java/com/terraforged/api/material/geology/StrataGenerator.java similarity index 96% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/StrataGenerator.java rename to src/main/java/com/terraforged/api/material/geology/StrataGenerator.java index ae712f4..f553a38 100644 --- a/TerraForgedAPI/src/main/java/com/terraforged/api/material/geology/StrataGenerator.java +++ b/src/main/java/com/terraforged/api/material/geology/StrataGenerator.java @@ -25,7 +25,7 @@ package com.terraforged.api.material.geology; -import com.terraforged.core.world.geology.Strata; +import com.terraforged.world.geology.Strata; import net.minecraft.block.BlockState; public interface StrataGenerator { diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/layer/LayerManager.java b/src/main/java/com/terraforged/api/material/layer/LayerManager.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/layer/LayerManager.java rename to src/main/java/com/terraforged/api/material/layer/LayerManager.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/layer/LayerMaterial.java b/src/main/java/com/terraforged/api/material/layer/LayerMaterial.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/layer/LayerMaterial.java rename to src/main/java/com/terraforged/api/material/layer/LayerMaterial.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/CachedState.java b/src/main/java/com/terraforged/api/material/state/CachedState.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/state/CachedState.java rename to src/main/java/com/terraforged/api/material/state/CachedState.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/DefaultState.java b/src/main/java/com/terraforged/api/material/state/DefaultState.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/state/DefaultState.java rename to src/main/java/com/terraforged/api/material/state/DefaultState.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateSupplier.java b/src/main/java/com/terraforged/api/material/state/StateSupplier.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/state/StateSupplier.java rename to src/main/java/com/terraforged/api/material/state/StateSupplier.java diff --git a/TerraForgedAPI/src/main/java/com/terraforged/api/material/state/States.java b/src/main/java/com/terraforged/api/material/state/States.java similarity index 100% rename from TerraForgedAPI/src/main/java/com/terraforged/api/material/state/States.java rename to src/main/java/com/terraforged/api/material/state/States.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/Log.java b/src/main/java/com/terraforged/mod/Log.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/Log.java rename to src/main/java/com/terraforged/mod/Log.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/TerraForgedMod.java b/src/main/java/com/terraforged/mod/TerraForgedMod.java similarity index 91% rename from TerraForgedMod/src/main/java/com/terraforged/mod/TerraForgedMod.java rename to src/main/java/com/terraforged/mod/TerraForgedMod.java index 83f36db..8a23460 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/TerraForgedMod.java +++ b/src/main/java/com/terraforged/mod/TerraForgedMod.java @@ -26,12 +26,12 @@ package com.terraforged.mod; import com.terraforged.api.material.WGTags; -import com.terraforged.feature.FeatureManager; +import com.terraforged.mod.feature.manager.template.TemplateManager; import com.terraforged.mod.command.TerraCommand; import com.terraforged.mod.data.DataGen; +import com.terraforged.mod.feature.context.ContextSelectorFeature; import com.terraforged.mod.feature.decorator.poisson.PoissonAtSurface; import com.terraforged.mod.feature.feature.DiskFeature; -import com.terraforged.mod.feature.tree.SaplingManager; import com.terraforged.mod.settings.SettingsHelper; import com.terraforged.mod.util.DataPackFinder; import com.terraforged.mod.util.Environment; @@ -61,16 +61,14 @@ public class TerraForgedMod { Log.info("Common setup"); WGTags.init(); TerraWorld.init(); - SaplingManager.init(); TerraCommand.init(); - SettingsHelper.initSettings(); + SettingsHelper.init(); // temp fix BiomeDictionary.addTypes(Biomes.BAMBOO_JUNGLE, BiomeDictionary.Type.OVERWORLD); BiomeDictionary.addTypes(Biomes.BAMBOO_JUNGLE_HILLS, BiomeDictionary.Type.OVERWORLD); - // allows ores to replace any world-gen stone type - OreFeatureConfig.FillerBlockType.create("WG_STONE", "wg_stone", WGTags.stone()); + OreFeatureConfig.FillerBlockType.create("wg_stone", "wg_stone", WGTags.stone()); } @SubscribeEvent @@ -83,8 +81,9 @@ public class TerraForgedMod { @SubscribeEvent public static void registerFeatures(RegistryEvent.Register> event) { Log.info("Registering features"); - FeatureManager.registerTemplates(event); + TemplateManager.register(event); event.getRegistry().register(DiskFeature.INSTANCE); + event.getRegistry().register(ContextSelectorFeature.INSTANCE); } @SubscribeEvent diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/TerraWorld.java b/src/main/java/com/terraforged/mod/TerraWorld.java similarity index 91% rename from TerraForgedMod/src/main/java/com/terraforged/mod/TerraWorld.java rename to src/main/java/com/terraforged/mod/TerraWorld.java index 0c7d479..9984787 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/TerraWorld.java +++ b/src/main/java/com/terraforged/mod/TerraWorld.java @@ -25,7 +25,6 @@ package com.terraforged.mod; -import com.terraforged.core.world.terrain.Terrains; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.chunk.ChunkGeneratorFactory; import com.terraforged.mod.chunk.TerraChunkGenerator; @@ -38,6 +37,7 @@ import com.terraforged.mod.settings.SettingsHelper; import com.terraforged.mod.settings.TerraSettings; import com.terraforged.mod.util.Environment; import com.terraforged.mod.util.nbt.NBTHelper; +import com.terraforged.world.terrain.Terrains; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.CreateWorldScreen; import net.minecraft.world.IWorld; @@ -53,10 +53,10 @@ import net.minecraftforge.api.distmarker.OnlyIn; import java.util.HashSet; import java.util.Set; +import java.util.function.Consumer; public class TerraWorld extends WorldType { - public static final int VERSION = 1; private static final Set types = new HashSet<>(); private final ChunkGeneratorFactory factory; @@ -72,10 +72,8 @@ public class TerraWorld extends WorldType { public ChunkGenerator createChunkGenerator(World world) { if (world.getDimension().getType() == DimensionType.OVERWORLD) { WorldInfo info = world.getWorldInfo(); - int version = SettingsHelper.getVersion(info); TerraSettings settings = SettingsHelper.getSettings(info); - SettingsHelper.syncSettings(world.getWorldInfo(), settings, version); - settings.dimensions.dimensionGenerators.apply(world.getWorldInfo()); + settings.dimensions.dimensions.apply(world.getWorldInfo()); Terrains terrains = Terrains.create(settings); @@ -131,6 +129,19 @@ public class TerraWorld extends WorldType { } } + public static WorldType getFirst() { + for (WorldType worldType : WorldType.WORLD_TYPES) { + if (worldType instanceof TerraWorld) { + return worldType; + } + } + throw new RuntimeException(); + } + + public static void forEach(Consumer consumer) { + types.forEach(consumer); + } + public static boolean isTerraType(WorldType type) { return types.contains(type); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ColdSteppe.java b/src/main/java/com/terraforged/mod/biome/ColdSteppe.java similarity index 92% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/ColdSteppe.java rename to src/main/java/com/terraforged/mod/biome/ColdSteppe.java index e114c54..36d348b 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ColdSteppe.java +++ b/src/main/java/com/terraforged/mod/biome/ColdSteppe.java @@ -29,7 +29,6 @@ import com.terraforged.api.biome.BiomeVariant; import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorldReader; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; import net.minecraft.world.biome.DefaultBiomeFeatures; @@ -42,8 +41,10 @@ import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; public class ColdSteppe extends BiomeVariant { + private static final float DEFAULT_TEMPERATURE = 0.4F; + public ColdSteppe() { - super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.GIANT_TREE_TAIGA, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(RainType.SNOW).category(Biome.Category.TAIGA).depth(0.2F).scale(0.25F).temperature(0.2F).downfall(0.1F).waterColor(4159204).waterFogColor(329011).parent((String) null)); + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.GIANT_TREE_TAIGA, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(RainType.SNOW).category(Biome.Category.TAIGA).depth(0.2F).scale(0.25F).temperature(0.2F).downfall(0.05F).waterColor(4159204).waterFogColor(329011).parent((String) null)); this.addStructure(Feature.VILLAGE.withConfiguration(new VillageConfig("village/taiga/town_centers", 6))); this.addStructure(Feature.PILLAGER_OUTPOST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); @@ -58,7 +59,6 @@ public class ColdSteppe extends BiomeVariant { DefaultBiomeFeatures.addGrass(this); DefaultBiomeFeatures.addVeryDenseGrass(this); DefaultBiomeFeatures.addBerryBushes(this); - DefaultBiomeFeatures.addFreezeTopLayer(this); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4)); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.PIG, 10, 4, 4)); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.CHICKEN, 10, 4, 4)); @@ -80,13 +80,12 @@ public class ColdSteppe extends BiomeVariant { } @Override - public boolean doesSnowGenerate(IWorldReader worldIn, BlockPos pos) { - return false; - } - - @Override - public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos pos) { - return false; + public float getTemperatureRaw(BlockPos pos) { + if (pos.getY() > 64) { + return DEFAULT_TEMPERATURE - getTemperatureNoise(pos); + } else { + return DEFAULT_TEMPERATURE; + } } @Override diff --git a/src/main/java/com/terraforged/mod/biome/Dunes.java b/src/main/java/com/terraforged/mod/biome/Dunes.java new file mode 100644 index 0000000..35d65c9 --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/Dunes.java @@ -0,0 +1,54 @@ +package com.terraforged.mod.biome; + +import com.terraforged.api.biome.BiomeVariant; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.IFeatureConfig; +import net.minecraft.world.gen.feature.structure.MineshaftConfig; +import net.minecraft.world.gen.feature.structure.MineshaftStructure; +import net.minecraft.world.gen.feature.structure.VillageConfig; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; + +public class Dunes extends BiomeVariant { + + protected Dunes() { + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.DEFAULT, SurfaceBuilder.SAND_SAND_GRAVEL_CONFIG).precipitation(Biome.RainType.NONE).category(Biome.Category.DESERT).depth(0.125F).scale(0.05F).temperature(2.0F).downfall(0.0F).waterColor(4159204).waterFogColor(329011).parent((String)null)); + this.addStructure(Feature.VILLAGE.withConfiguration(new VillageConfig("village/desert/town_centers", 6))); + this.addStructure(Feature.PILLAGER_OUTPOST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); + this.addStructure(Feature.DESERT_PYRAMID.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); + this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); + this.addStructure(Feature.STRONGHOLD.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); + DefaultBiomeFeatures.addCarvers(this); + DefaultBiomeFeatures.addStructures(this); + DefaultBiomeFeatures.addMonsterRooms(this); + DefaultBiomeFeatures.addStoneVariants(this); + DefaultBiomeFeatures.addOres(this); + DefaultBiomeFeatures.addDefaultFlowers(this); + DefaultBiomeFeatures.addSparseGrass(this); + DefaultBiomeFeatures.addDeadBushes(this); + DefaultBiomeFeatures.addMushrooms(this); + DefaultBiomeFeatures.addExtraReedsPumpkinsCactus(this); + DefaultBiomeFeatures.addFreezeTopLayer(this); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.RABBIT, 4, 2, 3)); + this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 19, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 1, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.HUSK, 80, 4, 4)); + setRegistryName("terraforged", "dunes"); + } + + @Override + public Biome getBase() { + return Biomes.DESERT; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FirForest.java b/src/main/java/com/terraforged/mod/biome/FirForest.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/FirForest.java rename to src/main/java/com/terraforged/mod/biome/FirForest.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/FlowerPlains.java b/src/main/java/com/terraforged/mod/biome/FlowerPlains.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/FlowerPlains.java rename to src/main/java/com/terraforged/mod/biome/FlowerPlains.java diff --git a/src/main/java/com/terraforged/mod/biome/FrozenLake.java b/src/main/java/com/terraforged/mod/biome/FrozenLake.java new file mode 100644 index 0000000..fc44c9d --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/FrozenLake.java @@ -0,0 +1,75 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.biome; + +import com.terraforged.api.biome.BiomeVariant; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.structure.MineshaftConfig; +import net.minecraft.world.gen.feature.structure.MineshaftStructure; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; + +public class FrozenLake extends BiomeVariant { + + protected FrozenLake() { + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.DEFAULT, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(Biome.RainType.SNOW).category(Biome.Category.RIVER).depth(-0.5F).scale(0.0F).temperature(0.0F).downfall(0.5F).waterColor(3750089).waterFogColor(329011).parent((String)null)); + this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); + DefaultBiomeFeatures.addCarvers(this); + DefaultBiomeFeatures.addStructures(this); + DefaultBiomeFeatures.addMonsterRooms(this); + DefaultBiomeFeatures.addStoneVariants(this); + DefaultBiomeFeatures.addOres(this); + DefaultBiomeFeatures.addSedimentDisks(this); + DefaultBiomeFeatures.addDefaultFlowers(this); + DefaultBiomeFeatures.addSparseGrass(this); + DefaultBiomeFeatures.addMushrooms(this); + DefaultBiomeFeatures.addReedsAndPumpkins(this); + DefaultBiomeFeatures.addSprings(this); + DefaultBiomeFeatures.addFreezeTopLayer(this); + this.addSpawn(EntityClassification.WATER_CREATURE, new Biome.SpawnListEntry(EntityType.SQUID, 2, 1, 4)); + this.addSpawn(EntityClassification.WATER_CREATURE, new Biome.SpawnListEntry(EntityType.SALMON, 5, 1, 5)); + this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 95, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.DROWNED, 1, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 5, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1)); + setRegistryName("terraforged", "frozen_lake"); + } + + @Override + public Biome getBase() { + return Biomes.FROZEN_RIVER; + } +} diff --git a/src/main/java/com/terraforged/mod/biome/Lake.java b/src/main/java/com/terraforged/mod/biome/Lake.java new file mode 100644 index 0000000..1cc1d03 --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/Lake.java @@ -0,0 +1,80 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.biome; + +import com.terraforged.api.biome.BiomeVariant; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.SeaGrassConfig; +import net.minecraft.world.gen.feature.structure.MineshaftConfig; +import net.minecraft.world.gen.feature.structure.MineshaftStructure; +import net.minecraft.world.gen.placement.IPlacementConfig; +import net.minecraft.world.gen.placement.Placement; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; + +public class Lake extends BiomeVariant { + + protected Lake() { + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.DEFAULT, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(Biome.RainType.RAIN).category(Biome.Category.RIVER).depth(-0.5F).scale(0.0F).temperature(0.5F).downfall(0.5F).waterColor(4159204).waterFogColor(329011).parent((String)null)); + this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); + DefaultBiomeFeatures.addCarvers(this); + DefaultBiomeFeatures.addStructures(this); + DefaultBiomeFeatures.addMonsterRooms(this); + DefaultBiomeFeatures.addStoneVariants(this); + DefaultBiomeFeatures.addOres(this); + DefaultBiomeFeatures.addSedimentDisks(this); + DefaultBiomeFeatures.addDefaultFlowers(this); + DefaultBiomeFeatures.addSparseGrass(this); + DefaultBiomeFeatures.addMushrooms(this); + DefaultBiomeFeatures.addReedsAndPumpkins(this); + DefaultBiomeFeatures.addSprings(this); + this.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.SEAGRASS.withConfiguration(new SeaGrassConfig(48, 0.4D)).withPlacement(Placement.TOP_SOLID_HEIGHTMAP.configure(IPlacementConfig.NO_PLACEMENT_CONFIG))); + DefaultBiomeFeatures.addFreezeTopLayer(this); + this.addSpawn(EntityClassification.WATER_CREATURE, new Biome.SpawnListEntry(EntityType.SQUID, 2, 1, 4)); + this.addSpawn(EntityClassification.WATER_CREATURE, new Biome.SpawnListEntry(EntityType.SALMON, 5, 1, 5)); + this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 95, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.DROWNED, 100, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 5, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1)); + setRegistryName("terraforged", "lake"); + } + + @Override + public Biome getBase() { + return Biomes.RIVER; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java b/src/main/java/com/terraforged/mod/biome/Marshland.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java rename to src/main/java/com/terraforged/mod/biome/Marshland.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java b/src/main/java/com/terraforged/mod/biome/ModBiomes.java similarity index 87% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java rename to src/main/java/com/terraforged/mod/biome/ModBiomes.java index d2ded1b..97b7f7d 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ModBiomes.java +++ b/src/main/java/com/terraforged/mod/biome/ModBiomes.java @@ -40,15 +40,19 @@ public class ModBiomes { private static final ArrayList biomes = new ArrayList<>(); public static final Biome COLD_STEPPE = register(new ColdSteppe()); +// public static final Biome DUNES = register(new Dunes()); + public static final Biome FIR_FOREST = register(new FirForest()); + public static final Biome FLOWER_PLAINS = register(new FlowerPlains()); + public static final Biome FROZEN_LAKE = register(new FrozenLake()); + public static final Biome LAKE = register(new Lake()); + public static final Biome MARSHLAND = register(new Marshland()); public static final Biome SAVANNA_SCRUB = register(new SavannaScrub()); public static final Biome SHATTERED_SAVANNA_SCRUB = register(new ShatteredSavannaScrub()); + public static final Biome SNOWY_FIR_FOREST = register(new SnowyFirForest()); public static final Biome SNOWY_TAIGA_SCRUB = register(new SnowyTaigaScrub()); public static final Biome STEPPE = register(new Steppe()); public static final Biome TAIGA_SCRUB = register(new TaigaScrub()); public static final Biome WARM_BEACH = register(new WarmBeach()); - public static final Biome MARSHLAND = register(new Marshland()); -// public static final Biome FIR_FOREST = register(new FirForest()); -// public static final Biome FLOWER_PLAINS = register(new FlowerPlains()); private static Biome register(BiomeVariant biome) { biomes.add(biome); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/SavannaScrub.java b/src/main/java/com/terraforged/mod/biome/SavannaScrub.java similarity index 99% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/SavannaScrub.java rename to src/main/java/com/terraforged/mod/biome/SavannaScrub.java index 3ce4ee9..9ac7079 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/SavannaScrub.java +++ b/src/main/java/com/terraforged/mod/biome/SavannaScrub.java @@ -63,8 +63,8 @@ public class SavannaScrub extends BiomeVariant { DefaultBiomeFeatures.addSedimentDisks(this); DefaultBiomeFeatures.addExtraDefaultFlowers(this); // func_222339_L - add grasses - add this a few times since there are no trees - DefaultBiomeFeatures.addGrass(this); DefaultBiomeFeatures.addVeryDenseGrass(this); + DefaultBiomeFeatures.addDeadBushes(this); DefaultBiomeFeatures.addMushrooms(this); DefaultBiomeFeatures.addReedsAndPumpkins(this); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4)); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java b/src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java rename to src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java index 2121706..aac48de 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java +++ b/src/main/java/com/terraforged/mod/biome/ShatteredSavannaScrub.java @@ -59,6 +59,8 @@ public class ShatteredSavannaScrub extends BiomeVariant { DefaultBiomeFeatures.addDefaultFlowers(this); DefaultBiomeFeatures.addGrass(this); DefaultBiomeFeatures.addVeryDenseGrass(this); + DefaultBiomeFeatures.addPlainsTallGrass(this); + DefaultBiomeFeatures.addDeadBushes(this); DefaultBiomeFeatures.addMushrooms(this); DefaultBiomeFeatures.addReedsAndPumpkins(this); DefaultBiomeFeatures.addFreezeTopLayer(this); diff --git a/src/main/java/com/terraforged/mod/biome/SnowyFirForest.java b/src/main/java/com/terraforged/mod/biome/SnowyFirForest.java new file mode 100644 index 0000000..421f49b --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/SnowyFirForest.java @@ -0,0 +1,60 @@ +package com.terraforged.mod.biome; + +import com.terraforged.api.biome.BiomeVariant; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.IFeatureConfig; +import net.minecraft.world.gen.feature.structure.MineshaftConfig; +import net.minecraft.world.gen.feature.structure.MineshaftStructure; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; + +public class SnowyFirForest extends BiomeVariant { + + public SnowyFirForest() { + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.DEFAULT, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(Biome.RainType.SNOW).category(Biome.Category.TAIGA).depth(0.2F).scale(0.2F).temperature(-0.5F).downfall(0.4F).waterColor(4020182).waterFogColor(329011).parent((String)null)); + this.addStructure(Feature.IGLOO.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); + this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); + this.addStructure(Feature.STRONGHOLD.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); + DefaultBiomeFeatures.addCarvers(this); + DefaultBiomeFeatures.addStructures(this); + DefaultBiomeFeatures.addMonsterRooms(this); + DefaultBiomeFeatures.addTaigaLargeFerns(this); + DefaultBiomeFeatures.addStoneVariants(this); + DefaultBiomeFeatures.addOres(this); + DefaultBiomeFeatures.addSedimentDisks(this); + DefaultBiomeFeatures.addTaigaConifers(this); + DefaultBiomeFeatures.addDefaultFlowers(this); + DefaultBiomeFeatures.addTaigaGrassAndMushrooms(this); + DefaultBiomeFeatures.addMushrooms(this); + DefaultBiomeFeatures.addReedsAndPumpkins(this); + DefaultBiomeFeatures.addSprings(this); + DefaultBiomeFeatures.addSparseBerryBushes(this); + DefaultBiomeFeatures.addFreezeTopLayer(this); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.PIG, 10, 4, 4)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.CHICKEN, 10, 4, 4)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.COW, 8, 4, 4)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.WOLF, 8, 4, 4)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.RABBIT, 4, 2, 3)); + this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.FOX, 8, 2, 4)); + this.addSpawn(EntityClassification.AMBIENT, new Biome.SpawnListEntry(EntityType.BAT, 10, 8, 8)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SPIDER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE, 95, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ZOMBIE_VILLAGER, 5, 1, 1)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SKELETON, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.CREEPER, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4)); + this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1)); + this.setRegistryName("terraforged", "snowy_fir_forest"); + } + + @Override + public Biome getBase() { + return Biomes.SNOWY_TAIGA; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/SnowyTaigaScrub.java b/src/main/java/com/terraforged/mod/biome/SnowyTaigaScrub.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/SnowyTaigaScrub.java rename to src/main/java/com/terraforged/mod/biome/SnowyTaigaScrub.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Steppe.java b/src/main/java/com/terraforged/mod/biome/Steppe.java similarity index 89% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/Steppe.java rename to src/main/java/com/terraforged/mod/biome/Steppe.java index e85f77d..742d870 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Steppe.java +++ b/src/main/java/com/terraforged/mod/biome/Steppe.java @@ -29,7 +29,6 @@ import com.terraforged.api.biome.BiomeVariant; import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorldReader; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; import net.minecraft.world.biome.DefaultBiomeFeatures; @@ -42,8 +41,10 @@ import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; public class Steppe extends BiomeVariant { + private static final float DEFAULT_TEMPERATURE = 1F; + protected Steppe() { - super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.GIANT_TREE_TAIGA, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(RainType.SNOW).category(Category.SAVANNA).depth(0.2F).scale(0.2F).temperature(0.7F).downfall(0.1F).waterColor(4159204).waterFogColor(329011).parent((String) null)); + super((new Biome.Builder()).surfaceBuilder(SurfaceBuilder.GIANT_TREE_TAIGA, SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG).precipitation(RainType.RAIN).category(Category.SAVANNA).depth(0.2F).scale(0.2F).temperature(0.7F).downfall(0.05F).waterColor(4159204).waterFogColor(329011).parent((String) null)); this.addStructure(Feature.VILLAGE.withConfiguration(new VillageConfig("village/savanna/town_centers", 6))); this.addStructure(Feature.PILLAGER_OUTPOST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG)); this.addStructure(Feature.MINESHAFT.withConfiguration(new MineshaftConfig(0.004D, MineshaftStructure.Type.NORMAL))); @@ -54,8 +55,9 @@ public class Steppe extends BiomeVariant { DefaultBiomeFeatures.addStoneVariants(this); DefaultBiomeFeatures.addOres(this); DefaultBiomeFeatures.addSedimentDisks(this); - DefaultBiomeFeatures.addGrass(this); DefaultBiomeFeatures.addVeryDenseGrass(this); + DefaultBiomeFeatures.addPlainsTallGrass(this); + DefaultBiomeFeatures.addDeadBushes(this); DefaultBiomeFeatures.addFreezeTopLayer(this); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.SHEEP, 12, 4, 4)); this.addSpawn(EntityClassification.CREATURE, new Biome.SpawnListEntry(EntityType.PIG, 10, 4, 4)); @@ -72,18 +74,16 @@ public class Steppe extends BiomeVariant { this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.SLIME, 100, 4, 4)); this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.ENDERMAN, 10, 1, 4)); this.addSpawn(EntityClassification.MONSTER, new Biome.SpawnListEntry(EntityType.WITCH, 5, 1, 1)); - setRegistryName("terraforged", "steppe"); } @Override - public boolean doesSnowGenerate(IWorldReader worldIn, BlockPos pos) { - return false; - } - - @Override - public boolean doesWaterFreeze(IWorldReader worldIn, BlockPos pos) { - return false; + public float getTemperatureRaw(BlockPos pos) { + if (pos.getY() > 64) { + return DEFAULT_TEMPERATURE - getTemperatureNoise(pos); + } else { + return DEFAULT_TEMPERATURE; + } } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/TaigaScrub.java b/src/main/java/com/terraforged/mod/biome/TaigaScrub.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/TaigaScrub.java rename to src/main/java/com/terraforged/mod/biome/TaigaScrub.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/WarmBeach.java b/src/main/java/com/terraforged/mod/biome/WarmBeach.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/WarmBeach.java rename to src/main/java/com/terraforged/mod/biome/WarmBeach.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java b/src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java similarity index 93% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java rename to src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java index aa6bb9a..7adfa55 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java +++ b/src/main/java/com/terraforged/mod/biome/map/AbstractBiomeMap.java @@ -28,7 +28,7 @@ package com.terraforged.mod.biome.map; import com.google.common.collect.Sets; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.ModBiomes; import com.terraforged.mod.biome.provider.BiomeHelper; import me.dags.noise.util.NoiseUtil; @@ -43,6 +43,7 @@ public abstract class AbstractBiomeMap implements BiomeMap { private final Biome[][] beach; private final Biome[][] river; + private final Biome[][] lake; private final Biome[][] wetland; private final Biome[][] ocean; private final Biome[][] deepOcean; @@ -50,12 +51,14 @@ public abstract class AbstractBiomeMap implements BiomeMap { protected final DefaultBiome defaultLand = this::defaultBiome; protected final DefaultBiome defaultBeach = this::defaultBeach; protected final DefaultBiome defaultRiver = this::defaultRiver; + protected final DefaultBiome defaultLake = this::defaultLake; protected final DefaultBiome defaultWetland = this::defaultWetland; protected final DefaultBiome defaultOcean = this::defaultOcean; protected final DefaultBiome defaultDeepOcean = this::defaultDeepOcean; protected AbstractBiomeMap(BiomeMapBuilder builder) { river = builder.rivers(); + lake = builder.lakes(); beach = builder.beaches(); ocean = builder.oceans(); wetland = builder.wetlands(); @@ -72,6 +75,11 @@ public abstract class AbstractBiomeMap implements BiomeMap { return get(river, getCategory(temperature), shape, temperature, defaultRiver); } + @Override + public Biome getLake(float temperature, float moisture, float shape) { + return get(lake, getCategory(temperature), shape, temperature, defaultLake); + } + @Override public Biome getWetland(float temperature, float moisture, float shape) { return get(wetland, getCategory(temperature), shape, temperature, defaultWetland); @@ -159,6 +167,13 @@ public abstract class AbstractBiomeMap implements BiomeMap { return Biomes.RIVER; } + protected Biome defaultLake(float temperature) { + if (temperature < 0.15) { + return ModBiomes.FROZEN_LAKE; + } + return ModBiomes.LAKE; + } + protected Biome defaultWetland(float temperature) { if (temperature < 0.15) { return ModBiomes.TAIGA_SCRUB; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java b/src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java rename to src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java index 37f62e8..a483825 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java +++ b/src/main/java/com/terraforged/mod/biome/map/BasicBiomeMap.java @@ -28,7 +28,7 @@ package com.terraforged.mod.biome.map; import com.google.common.collect.Sets; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.provider.BiomeHelper; import net.minecraft.world.biome.Biome; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeGroup.java b/src/main/java/com/terraforged/mod/biome/map/BiomeGroup.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeGroup.java rename to src/main/java/com/terraforged/mod/biome/map/BiomeGroup.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMap.java b/src/main/java/com/terraforged/mod/biome/map/BiomeMap.java similarity index 92% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMap.java rename to src/main/java/com/terraforged/mod/biome/map/BiomeMap.java index 7fa0f1a..751423a 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMap.java +++ b/src/main/java/com/terraforged/mod/biome/map/BiomeMap.java @@ -27,8 +27,7 @@ package com.terraforged.mod.biome.map; import com.google.gson.JsonElement; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.biome.BiomeType; import net.minecraft.world.biome.Biome; import java.util.List; @@ -40,6 +39,8 @@ public interface BiomeMap { Biome getRiver(float temperature, float moisture, float shape); + Biome getLake(float temperature, float moisture, float shape); + Biome getWetland(float temperature, float moisture, float shape); Biome getOcean(float temperature, float moisture, float shape); @@ -48,7 +49,7 @@ public interface BiomeMap { Biome getBiome(BiomeType type, float temperature, float moisture, float shape); - default Biome getBiome(Cell cell) { + default Biome getBiome(Cell cell) { return getBiome(cell.biomeType, cell.temperature, cell.moisture, cell.biome); } @@ -74,6 +75,8 @@ public interface BiomeMap { Builder addRiver(Biome biome, int count); + Builder addLake(Biome biome, int count); + Builder addWetland(Biome biome, int count); Builder addOcean(Biome biome, int count); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java b/src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java similarity index 93% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java rename to src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java index c4c2ee5..1e276e3 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java +++ b/src/main/java/com/terraforged/mod/biome/map/BiomeMapBuilder.java @@ -26,8 +26,8 @@ package com.terraforged.mod.biome.map; import com.terraforged.core.util.grid.FixedGrid; -import com.terraforged.core.world.biome.BiomeData; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeData; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.provider.BiomeHelper; import com.terraforged.mod.util.ListUtils; import net.minecraft.world.biome.Biome; @@ -44,6 +44,7 @@ import java.util.function.Function; public class BiomeMapBuilder implements BiomeMap.Builder { private final Map> rivers = new HashMap<>(); + private final Map> lakes = new HashMap<>(); private final Map> wetlands = new HashMap<>(); private final Map> beaches = new HashMap<>(); private final Map> oceans = new HashMap<>(); @@ -88,6 +89,13 @@ public class BiomeMapBuilder implements BiomeMap.Builder { return this; } + @Override + public BiomeMapBuilder addLake(Biome biome, int count) { + Biome.TempCategory category = BiomeHelper.getTempCategory(biome); + add(lakes.computeIfAbsent(category, c -> new ArrayList<>()), biome, count); + return this; + } + @Override public BiomeMapBuilder addWetland(Biome biome, int count) { Biome.TempCategory category = BiomeHelper.getTempCategory(biome); @@ -110,6 +118,10 @@ public class BiomeMapBuilder implements BiomeMap.Builder { return collectTemps(rivers); } + Biome[][] lakes() { + return collectTemps(lakes); + } + Biome[][] wetlands() { return collectTemps(wetlands); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java b/src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java rename to src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java index 30e3fcd..8e63870 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java +++ b/src/main/java/com/terraforged/mod/biome/map/BiomePredicate.java @@ -25,7 +25,7 @@ package com.terraforged.mod.biome.map; -import com.terraforged.core.world.biome.BiomeData; +import com.terraforged.world.biome.BiomeData; import com.terraforged.mod.biome.provider.BiomeHelper; import net.minecraft.world.biome.Biome; @@ -85,17 +85,19 @@ public interface BiomePredicate { } BiomePredicate COAST = type(Biome.Category.BEACH, Biome.Category.MUSHROOM).or(name("shore")).or(name("beach")); - BiomePredicate WETLAND = type(Biome.Category.SWAMP); - BiomePredicate DESERT = type(Biome.Category.DESERT).or(temp(0.9, 2).and(rain(-1, 0.2))); - BiomePredicate SAVANNA = type(Biome.Category.SAVANNA).or(temp(0.8, 2).and(rain(-1, 0.4))); - BiomePredicate MESA = type(Biome.Category.MESA); - BiomePredicate STEPPE = name("steppe").and(temp(0.3, 1)); BiomePredicate COLD_STEPPE = name("steppe").and(temp(-1, 0.3)); + BiomePredicate DESERT = type(Biome.Category.DESERT).or(temp(0.9, 2).and(rain(-1, 0.2))); BiomePredicate GRASSLAND = type(Biome.Category.PLAINS); + BiomePredicate LAKE = type(Biome.Category.RIVER).and(name("lake")); + BiomePredicate MESA = type(Biome.Category.MESA); + BiomePredicate MOUNTAIN = type(Biome.Category.EXTREME_HILLS).or(name("mountain")); + BiomePredicate RIVER = type(Biome.Category.RIVER).not(name("lake")); + BiomePredicate SAVANNA = type(Biome.Category.SAVANNA).or(temp(0.8, 2).and(rain(-1, 0.4))); + BiomePredicate STEPPE = name("steppe").and(temp(0.3, 1)); + BiomePredicate TAIGA = type(Biome.Category.TAIGA).or(temp(0.19, 0.35)).not(rainType(Biome.RainType.SNOW)); BiomePredicate TEMPERATE_FOREST = type(Biome.Category.FOREST).and(rain(-1, 0.81)); BiomePredicate TEMPERATE_RAINFOREST = type(Biome.Category.FOREST).and(rain(0.8, 2)); BiomePredicate TROPICAL_RAINFOREST = type(Biome.Category.JUNGLE); - BiomePredicate TAIGA = type(Biome.Category.TAIGA).or(temp(0.19, 0.35)).not(rainType(Biome.RainType.SNOW)); BiomePredicate TUNDRA = type(Biome.Category.ICY).or(temp(-1, 0.21).and(rainType(Biome.RainType.SNOW))); - BiomePredicate MOUNTAIN = type(Biome.Category.EXTREME_HILLS).or(name("mountain")); + BiomePredicate WETLAND = type(Biome.Category.SWAMP); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/DefaultBiome.java b/src/main/java/com/terraforged/mod/biome/map/DefaultBiome.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/DefaultBiome.java rename to src/main/java/com/terraforged/mod/biome/map/DefaultBiome.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java b/src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java rename to src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java index eb0a02f..c5278b6 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java +++ b/src/main/java/com/terraforged/mod/biome/map/GridBiomeMap.java @@ -29,7 +29,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.terraforged.core.util.grid.FixedList; import com.terraforged.core.util.grid.MappedList; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeType; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java b/src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java similarity index 86% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java rename to src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java index 8915c6d..ca5fa5c 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/AbstractMaxHeightModifier.java @@ -26,9 +26,8 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.core.Seed; +import com.terraforged.world.climate.Climate; import me.dags.noise.Module; import me.dags.noise.Source; import net.minecraft.world.biome.Biome; @@ -49,7 +48,7 @@ public abstract class AbstractMaxHeightModifier extends AbstractOffsetModifier { } @Override - protected final Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz) { + protected final Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz) { float var = variance.getValue(x, z); float value = cell.value + var; if (value < minHeight) { @@ -63,5 +62,5 @@ public abstract class AbstractMaxHeightModifier extends AbstractOffsetModifier { return in; } - protected abstract Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz); + protected abstract Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java b/src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java similarity index 86% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java rename to src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java index 0f9031a..5ba1157 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/AbstractOffsetModifier.java @@ -27,8 +27,7 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.api.biome.modifier.BiomeModifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.climate.Climate; import net.minecraft.world.biome.Biome; public abstract class AbstractOffsetModifier implements BiomeModifier { @@ -40,11 +39,11 @@ public abstract class AbstractOffsetModifier implements BiomeModifier { } @Override - public Biome modify(Biome in, Cell cell, int x, int z) { + public Biome modify(Biome in, Cell cell, int x, int z) { float dx = climate.getOffsetX(x, z, 50); float dz = climate.getOffsetX(x, z, 50); return modify(in, cell, x, z, x + dx, z + dz); } - protected abstract Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz); + protected abstract Biome modify(Biome in, Cell cell, int x, int z, float ox, float oz); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java b/src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java similarity index 75% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java rename to src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java index 31abce2..b82e173 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/BeachModifier.java @@ -27,18 +27,21 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.api.biome.modifier.BiomeModifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.biome.map.BiomeMap; +import com.terraforged.mod.chunk.TerraContext; import net.minecraft.world.biome.Biome; public class BeachModifier implements BiomeModifier { + private final Levels levels; private final Terrains terrain; private final BiomeMap biomeMap; - public BeachModifier(BiomeMap biomeMap, Terrains terrain) { - this.terrain = terrain; + public BeachModifier(BiomeMap biomeMap, TerraContext context) { + this.levels = context.levels; + this.terrain = context.terrain; this.biomeMap = biomeMap; } @@ -53,10 +56,13 @@ public class BeachModifier implements BiomeModifier { } @Override - public Biome modify(Biome in, Cell cell, int x, int z) { - if (cell.tag == terrain.beach) { + public Biome modify(Biome in, Cell cell, int x, int z) { + if (cell.terrainType == terrain.beach) { return biomeMap.getBeach(cell.temperature, cell.moisture, cell.biome); } + if (cell.terrainType == terrain.coast && cell.value <= levels.water) { + return biomeMap.getOcean(cell.temperature, cell.moisture, cell.biome); + } return in; } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java b/src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java similarity index 92% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java rename to src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java index 5cbf385..4b07659 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/BiomeModifierManager.java @@ -28,8 +28,7 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.api.biome.modifier.BiomeModifier; import com.terraforged.api.biome.modifier.ModifierManager; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.biome.BiomeType; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.provider.DesertBiomes; import com.terraforged.mod.chunk.TerraContext; @@ -47,7 +46,7 @@ public class BiomeModifierManager implements BiomeModifier, ModifierManager { public BiomeModifierManager(TerraContext context, BiomeMap biomes) { desertBiomes = new DesertBiomes(context.materials, biomes.getAllBiomes(BiomeType.DESERT)); List modifiers = new ArrayList<>(); - modifiers.add(new BeachModifier(biomes, context.terrain)); + modifiers.add(new BeachModifier(biomes, context)); modifiers.add(new DesertColorModifier(desertBiomes)); modifiers.add(new SandBiomeModifier( context.seed, @@ -79,7 +78,7 @@ public class BiomeModifierManager implements BiomeModifier, ModifierManager { } @Override - public Biome modify(Biome biome, Cell cell, int x, int z) { + public Biome modify(Biome biome, Cell cell, int x, int z) { for (BiomeModifier modifier : biomeModifiers) { if (modifier.test(biome)) { biome = modifier.modify(biome, cell, x, z); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java b/src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java similarity index 94% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java rename to src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java index d941f23..fc47448 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/DesertColorModifier.java @@ -27,7 +27,6 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.api.biome.modifier.BiomeModifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; import com.terraforged.mod.biome.provider.DesertBiomes; import net.minecraft.world.biome.Biome; @@ -50,7 +49,7 @@ public class DesertColorModifier implements BiomeModifier { } @Override - public Biome modify(Biome in, Cell cell, int x, int z) { + public Biome modify(Biome in, Cell cell, int x, int z) { if (biomes.isRedDesert(in)) { if (cell.continent <= 0.5F) { return biomes.getWhiteDesert(cell.biome); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java b/src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java similarity index 88% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java rename to src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java index bd5279b..62cc408 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java +++ b/src/main/java/com/terraforged/mod/biome/modifier/SandBiomeModifier.java @@ -26,10 +26,9 @@ package com.terraforged.mod.biome.modifier; import com.terraforged.core.cell.Cell; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.climate.Climate; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.core.Seed; +import com.terraforged.world.climate.Climate; +import com.terraforged.world.heightmap.Levels; import com.terraforged.mod.material.MaterialHelper; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; @@ -61,7 +60,7 @@ public class SandBiomeModifier extends AbstractMaxHeightModifier { } @Override - protected Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz) { + protected Biome getModifiedBiome(Biome in, Cell cell, int x, int z, float ox, float oz) { return Biomes.BADLANDS; } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java b/src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java similarity index 77% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java rename to src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java index 99cb204..a431457 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java +++ b/src/main/java/com/terraforged/mod/biome/provider/AbstractBiomeProvider.java @@ -27,22 +27,15 @@ package com.terraforged.mod.biome.provider; import net.minecraft.util.math.BlockPos; import net.minecraft.world.biome.Biome; -import net.minecraftforge.common.BiomeDictionary; -import net.minecraftforge.registries.ForgeRegistries; import java.util.List; import java.util.Random; import java.util.Set; -import java.util.stream.Collectors; public abstract class AbstractBiomeProvider extends net.minecraft.world.biome.provider.BiomeProvider { public AbstractBiomeProvider() { - super(getOverworldBiomes()); - } - - public Set getAvailableBiomes() { - return super.field_226837_c_; + super(BiomeHelper.getAllBiomes()); } @Override @@ -58,11 +51,4 @@ public abstract class AbstractBiomeProvider extends net.minecraft.world.biome.pr public abstract Set getBiomesInSquare(int x, int y, int z, int size); public abstract BlockPos findBiomePosition(int centerX, int centerY, int centerZ, int range, List biomes, Random random); - - private static Set getOverworldBiomes() { - return ForgeRegistries.BIOMES.getValues().stream() - .map(biome -> biome.delegate.get()) - .filter(biome -> BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.OVERWORLD)) - .collect(Collectors.toSet()); - } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java b/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java similarity index 80% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java rename to src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java index 121472a..8b9da6e 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java +++ b/src/main/java/com/terraforged/mod/biome/provider/BiomeHelper.java @@ -25,9 +25,8 @@ package com.terraforged.mod.biome.provider; -import com.terraforged.core.settings.BiomeSettings; -import com.terraforged.core.world.biome.BiomeData; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeData; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.ModBiomes; import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.map.BiomeMapBuilder; @@ -50,7 +49,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; public class BiomeHelper { @@ -74,33 +72,24 @@ public class BiomeHelper { public static BiomeMap getDefaultBiomeMap() { List biomes = getAllBiomeData(); + BiomeWeights weights = new BiomeWeights(); BiomeMap.Builder builder = getBuilder(biomes); for (BiomeData data : biomes) { - int weight = 10; Biome biome = (Biome) data.reference; - if (biome.isMutation() && getId(biome).contains("hills")) { continue; } - if (biome.getCategory() == Biome.Category.FOREST) { - weight = 5; - } - - // don't use BiomeDictionary with transient biomes - if (ForgeRegistries.BIOMES.containsKey(biome.getRegistryName())) { - if (BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.RARE)) { - weight = 1; - } - } - + int weight = weights.getWeight(biome); if (BiomePredicate.COAST.test(data)) { builder.addBeach(biome, weight); } else if (biome.getCategory() == Biome.Category.OCEAN) { builder.addOcean(biome, weight); - } else if (biome.getCategory() == Biome.Category.RIVER) { + } else if (BiomePredicate.RIVER.test(data)) { builder.addRiver(biome, weight); - } else if (biome.getCategory() == Biome.Category.SWAMP) { + } else if (BiomePredicate.LAKE.test(data)) { + builder.addLake(biome, weight); + } else if (BiomePredicate.WETLAND.test(data)) { builder.addWetland(biome, weight); } else { Collection types = getTypes(data, biome); @@ -111,7 +100,7 @@ public class BiomeHelper { } builder.addBiome(BiomeType.TEMPERATE_RAINFOREST, Biomes.PLAINS, 10); - builder.addBiome(BiomeType.TEMPERATE_FOREST, Biomes.FLOWER_FOREST, 3); + builder.addBiome(BiomeType.TEMPERATE_FOREST, Biomes.FLOWER_FOREST, 2); builder.addBiome(BiomeType.TEMPERATE_FOREST, Biomes.PLAINS, 10); builder.addBiome(BiomeType.TUNDRA, ModBiomes.SNOWY_TAIGA_SCRUB, 5); builder.addBiome(BiomeType.TAIGA, ModBiomes.TAIGA_SCRUB, 5); @@ -119,31 +108,6 @@ public class BiomeHelper { return builder.build(); } - public static BiomeMap getBiomeMap(BiomeSettings settings) { - List biomes = getAllBiomeData(); - BiomeMap.Builder builder = getBuilder(biomes); - Map biomeMap = biomes.stream().collect(Collectors.toMap(d -> d.name, d -> d)); - Map groupMap = settings.asMap(); - for (Map.Entry e : groupMap.entrySet()) { - for (BiomeSettings.BiomeWeight biomeWeight : e.getValue().biomes) { - BiomeData data = biomeMap.get(biomeWeight.id); - if (data == null) { - continue; - } - builder.addBiome(e.getKey(), (Biome) data.reference, biomeWeight.weight); - } - } - for (BiomeData data : biomes) { - Biome biome = (Biome) data.reference; - if (biome.getCategory() == Biome.Category.OCEAN) { - builder.addOcean(biome, 10); - } else if (biome.getCategory() == Biome.Category.RIVER) { - builder.addRiver(biome, 10); - } - } - return builder.build(); - } - public static Biome.TempCategory getTempCategory(Biome biome) { // vanilla ocean biome properties are not at all helpful for determining temperature if (biome.getCategory() == Biome.Category.OCEAN) { @@ -186,7 +150,7 @@ public class BiomeHelper { } public static List getAllBiomeData() { - Collection biomes = TerraBiomeRegistry.getInstance().getAll(BiomeHelper::filter); + Collection biomes = getAllBiomes(); Vec2f tempRange = getRange(biomes, Biome::getDefaultTemperature); Vec2f moistRange = getRange(biomes, Biome::getDownfall); List list = new LinkedList<>(); @@ -200,6 +164,17 @@ public class BiomeHelper { return list; } + public static Set getAllBiomes() { + Set biomes = new HashSet<>(); + for (Biome biome : ForgeRegistries.BIOMES) { + if (filter(biome)) { + continue; + } + biomes.add(biome.delegate.get()); + } + return biomes; + } + private static boolean filter(Biome biome) { if (biome.getCategory() == Biome.Category.NONE) { return true; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java b/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java similarity index 75% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java rename to src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java index 5e7bc4f..b4e3482 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java +++ b/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java @@ -28,18 +28,15 @@ package com.terraforged.mod.biome.provider; import com.google.common.collect.Sets; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.core.world.decorator.Decorator; -import com.terraforged.core.world.heightmap.WorldLookup; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.terrain.decorator.Decorator; +import com.terraforged.world.heightmap.WorldLookup; import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.modifier.BiomeModifierManager; -import com.terraforged.mod.chunk.TerraContainer; +import com.terraforged.mod.chunk.util.TerraContainer; import com.terraforged.mod.chunk.TerraContext; import com.terraforged.mod.util.setup.SetupHooks; -import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.feature.structure.Structure; import java.util.Collections; import java.util.HashMap; @@ -63,20 +60,8 @@ public class BiomeProvider extends AbstractBiomeProvider { this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy()); } - public TerraContext getContext() { - return context; - } - - public void lookupPos(int x, int z, Cell cell) { - worldLookup.applyCell(cell, x, z); - } - - public Cell lookupPos(int x, int z) { - return worldLookup.getCell(x, z); - } - - public boolean canSpawnAt(Cell cell) { - return cell.tag != context.terrain.ocean && cell.tag != context.terrain.deepOcean && cell.value > context.levels.ground; + public Cell lookupPos(int x, int z) { + return getWorldLookup().getCell(x, z); } @Override @@ -95,7 +80,7 @@ public class BiomeProvider extends AbstractBiomeProvider { int rangeX = maxX - minX + 1; int rangeZ = maxZ - minZ + 1; Set set = Sets.newHashSet(); - Cell cell = new Cell<>(); + Cell cell = new Cell(); for(int dz = 0; dz < rangeZ; ++dz) { for(int dx = 0; dx < rangeX; ++dx) { int x = (minX + dx) << 2; @@ -121,7 +106,7 @@ public class BiomeProvider extends AbstractBiomeProvider { BlockPos blockpos = null; int attempts = 0; - Cell cell = new Cell<>(); + Cell cell = new Cell(); for(int dz = 0; dz < rangeZ; ++dz) { for(int dx = 0; dx < rangeX; ++dx) { int x = (minX + dx) << 2; @@ -138,26 +123,12 @@ public class BiomeProvider extends AbstractBiomeProvider { return blockpos; } - @Override - public boolean hasStructure(Structure structure) { - return this.hasStructureCache.computeIfAbsent(structure, (name) -> { - for (Biome biome : getAvailableBiomes()) { - if (biome.hasStructure(name)) { - return true; - } - } - return false; - }); + public WorldLookup getWorldLookup() { + return worldLookup; } - @Override - public Set getSurfaceBlocks() { - if (this.topBlocksCache.isEmpty()) { - for (Biome biome : getAvailableBiomes()) { - this.topBlocksCache.add(biome.getSurfaceBuilderConfig().getTop()); - } - } - return this.topBlocksCache; + public TerraContext getContext() { + return context; } public BiomeModifierManager getModifierManager() { @@ -177,8 +148,8 @@ public class BiomeProvider extends AbstractBiomeProvider { return builder.build(chunkReader); } - public Biome getBiome(Cell cell, int x, int z) { - if (cell.tag == context.terrain.wetlands) { + public Biome getBiome(Cell cell, int x, int z) { + if (cell.terrainType.isWetland()) { return biomeMap.getWetland(cell.temperature, cell.moisture, cell.biome); } @@ -186,7 +157,11 @@ public class BiomeProvider extends AbstractBiomeProvider { return getModifierManager().modify(biomeMap.getBiome(cell), cell, x, z); } - if (cell.tag == context.terrain.river || cell.tag == context.terrain.riverBanks || cell.tag == context.terrain.lake) { + if (cell.terrainType.isLake()) { + return biomeMap.getLake(cell.temperature, cell.moisture, cell.biome); + } + + if (cell.terrainType.isRiver()) { Biome biome = biomeMap.getBiome(cell); if (overridesRiver(biome)) { return biome; @@ -194,21 +169,18 @@ public class BiomeProvider extends AbstractBiomeProvider { return biomeMap.getRiver(cell.temperature, cell.moisture, cell.biome); } - if (cell.tag == context.terrain.ocean) { + if (cell.terrainType.isShallowOcean()) { return biomeMap.getOcean(cell.temperature, cell.moisture, cell.biome); } return biomeMap.getDeepOcean(cell.temperature, cell.moisture, cell.biome); } + public boolean canSpawnAt(Cell cell) { + return cell.terrainType != context.terrain.ocean && cell.terrainType != context.terrain.deepOcean; + } + private static boolean overridesRiver(Biome biome) { return biome.getCategory() == Biome.Category.SWAMP || biome.getCategory() == Biome.Category.JUNGLE; } - - private static class SearchContext { - - private int count = 0; - private boolean first = true; - private final BlockPos.Mutable pos = new BlockPos.Mutable(); - } } diff --git a/src/main/java/com/terraforged/mod/biome/provider/BiomeWeights.java b/src/main/java/com/terraforged/mod/biome/provider/BiomeWeights.java new file mode 100644 index 0000000..be782e8 --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/provider/BiomeWeights.java @@ -0,0 +1,51 @@ +package com.terraforged.mod.biome.provider; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.BiomeManager; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BiomeWeights { + + private final int standardWeight; + private final int forestWeight; + private final int rareWeight; + private final Map biomes = new HashMap<>(); + + public BiomeWeights() { + this(10, 5, 1); + } + + public BiomeWeights(int standard, int forest, int rare) { + this.standardWeight = standard; + this.forestWeight = forest; + this.rareWeight = rare; + for (BiomeManager.BiomeType type : BiomeManager.BiomeType.values()) { + List entries = BiomeManager.getBiomes(type); + if (entries == null) { + continue; + } + for (BiomeManager.BiomeEntry entry : entries) { + biomes.put(entry.biome.getRegistryName(), entry.itemWeight); + } + } + } + + public int getWeight(Biome biome) { + Integer value = biomes.get(biome.getRegistryName()); + if (value != null) { + return value; + } + if (BiomeDictionary.getTypes(biome).contains(BiomeDictionary.Type.RARE)) { + return rareWeight; + } + if (biome.getCategory() == Biome.Category.FOREST) { + return forestWeight; + } + return standardWeight; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java b/src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java rename to src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java index 18941d9..5aa7546 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java +++ b/src/main/java/com/terraforged/mod/biome/provider/DesertBiomes.java @@ -27,11 +27,10 @@ package com.terraforged.mod.biome.provider; import com.terraforged.api.material.layer.LayerManager; import com.terraforged.api.material.layer.LayerMaterial; -import com.terraforged.core.util.concurrent.ObjectPool; +import com.terraforged.core.concurrent.ObjectPool; import com.terraforged.mod.material.Materials; import com.terraforged.mod.util.DummyBlockReader; import com.terraforged.mod.util.ListUtils; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.material.MaterialColor; @@ -102,7 +101,6 @@ public class DesertBiomes { } public LayerMaterial getSandLayers(Biome biome) { - Block top = biome.getSurfaceBuilderConfig().getTop().getBlock(); return layerManager.getMaterial(Blocks.SAND); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java b/src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java similarity index 77% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java rename to src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java index 188dca9..e32a6a0 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java +++ b/src/main/java/com/terraforged/mod/biome/spawn/SpawnHandler.java @@ -1,5 +1,6 @@ package com.terraforged.mod.biome.spawn; +import com.terraforged.world.continent.MutableVeci; import com.terraforged.mod.Log; import com.terraforged.mod.biome.provider.BiomeProvider; import net.minecraft.util.math.BlockPos; @@ -21,7 +22,8 @@ public class SpawnHandler { if (world.getChunkProvider().getChunkGenerator().getBiomeProvider() instanceof BiomeProvider) { Log.info("Searching for world spawn position"); BiomeProvider provider = (BiomeProvider) world.getChunkProvider().getChunkGenerator().getBiomeProvider(); - SpawnSearch search = new SpawnSearch(BlockPos.ZERO, provider); + BlockPos center = getSearchCenter(provider, true); + SpawnSearch search = new SpawnSearch(center, provider); BlockPos spawn = search.get(); Log.info("Setting world spawn: {}", spawn); @@ -36,6 +38,15 @@ public class SpawnHandler { } } + private static BlockPos getSearchCenter(BiomeProvider provider, boolean continent) { + if (continent) { + MutableVeci pos = new MutableVeci(); + provider.getContext().heightmap.getContinent().getNearestCenter(0, 0, pos); + return new BlockPos(pos.x, 0, pos.z); + } + return BlockPos.ZERO; + } + private static void createBonusChest(ServerWorld world, BlockPos pos) { ConfiguredFeature chest = Feature.BONUS_CHEST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG); chest.place(world, world.getChunkProvider().getChunkGenerator(), world.rand, pos); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java b/src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java similarity index 79% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java rename to src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java index be5b8cc..39e170d 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java +++ b/src/main/java/com/terraforged/mod/biome/spawn/SpawnSearch.java @@ -1,7 +1,6 @@ package com.terraforged.mod.biome.spawn; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; import com.terraforged.mod.Log; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.command.search.Search; @@ -10,7 +9,7 @@ import net.minecraft.util.math.BlockPos; public class SpawnSearch extends Search { private final BiomeProvider biomeProvider; - private final Cell cell = new Cell<>(); + private final Cell cell = new Cell(); public SpawnSearch(BlockPos center, BiomeProvider biomeProvider) { super(center, 0, 2048); @@ -24,19 +23,19 @@ public class SpawnSearch extends Search { @Override public boolean test(BlockPos pos) { - biomeProvider.lookupPos(pos.getX(), pos.getZ(), cell); + biomeProvider.getWorldLookup().applyCell(cell, pos.getX(), pos.getZ()); return biomeProvider.canSpawnAt(cell); } @Override - protected BlockPos success(BlockPos.Mutable pos) { + public BlockPos success(BlockPos.Mutable pos) { pos.setY(biomeProvider.getContext().levels.scale(cell.value)); Log.info("Found valid spawn position: {}", pos); return super.success(pos); } @Override - protected BlockPos fail(BlockPos pos) { + public BlockPos fail(BlockPos pos) { Log.info("Unable to find valid spawn position, defaulting x=0, z=0"); return new BlockPos(0, biomeProvider.getContext().levels.groundLevel, 0); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/DesertDunes.java b/src/main/java/com/terraforged/mod/biome/surface/DunesSurface.java similarity index 80% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/DesertDunes.java rename to src/main/java/com/terraforged/mod/biome/surface/DunesSurface.java index 7089486..f61d268 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/DesertDunes.java +++ b/src/main/java/com/terraforged/mod/biome/surface/DunesSurface.java @@ -23,25 +23,27 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.surface; +package com.terraforged.mod.biome.surface; import com.terraforged.api.chunk.surface.Surface; import com.terraforged.api.chunk.surface.SurfaceContext; import com.terraforged.api.material.layer.LayerMaterial; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.biome.provider.DesertBiomes; import com.terraforged.mod.chunk.TerraContext; import me.dags.noise.Module; import me.dags.noise.Source; import me.dags.noise.func.CellFunc; +import me.dags.noise.util.NoiseUtil; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.Heightmap; -public class DesertDunes implements Surface { +public class DunesSurface implements Surface { private final int maxHeight; private final Levels levels; @@ -50,7 +52,7 @@ public class DesertDunes implements Surface { private final DesertBiomes deserts; private final BlockPos.Mutable pos = new BlockPos.Mutable(); - public DesertDunes(TerraContext context, int maxHeight, DesertBiomes deserts) { + public DunesSurface(TerraContext context, int maxHeight, DesertBiomes deserts) { Module dunes = Source.cell(context.seed.next(), 80, CellFunc.DISTANCE) .warp(context.seed.next(), 70, 1, 70); this.terrains = context.terrain; @@ -63,16 +65,17 @@ public class DesertDunes implements Surface { @Override public void buildSurface(int x, int z, int surface, SurfaceContext ctx) { float value = module.getValue(x, z) * getMask(ctx.cell); - float baseHeight = ctx.cell.value * levels.worldHeight; + float baseHeight = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, x & 15, z & 15); float duneHeight = baseHeight + value * maxHeight; int duneBase = (int) baseHeight; - int duneTop = (int) duneHeight; + int duneTop = (int) duneHeight + 1; if (duneTop < levels.waterLevel || duneTop <= baseHeight) { return; } LayerMaterial material = deserts.getSandLayers(ctx.biome); if (material == null) { + fill(x, z, duneBase - 4, duneTop, ctx, ctx.chunk, Blocks.SAND.getDefaultState()); return; } @@ -89,10 +92,10 @@ public class DesertDunes implements Surface { } public static Surface create(TerraContext context, DesertBiomes desertBiomes) { - return new DesertDunes(context, 25, desertBiomes); + return new DunesSurface(context, 25, desertBiomes); } - private static float getMask(Cell cell) { - return cell.biomeMask(0F, 0.75F) * cell.mask(0.4F, 0.5F, 0F, 0.8F); + private static float getMask(Cell cell) { + return cell.biomeMask(0F, 0.7F) * (NoiseUtil.map(cell.riverMask, 0.5F, 0.95F, 0.45F)); } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/FrozenOcean.java b/src/main/java/com/terraforged/mod/biome/surface/IcebergsSurface.java similarity index 94% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/FrozenOcean.java rename to src/main/java/com/terraforged/mod/biome/surface/IcebergsSurface.java index 68d2929..3a80217 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/surface/FrozenOcean.java +++ b/src/main/java/com/terraforged/mod/biome/surface/IcebergsSurface.java @@ -23,13 +23,13 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.surface; +package com.terraforged.mod.biome.surface; import com.terraforged.api.chunk.surface.Surface; import com.terraforged.api.chunk.surface.SurfaceContext; import com.terraforged.api.material.state.States; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; +import com.terraforged.world.heightmap.Levels; import com.terraforged.mod.chunk.TerraContext; import me.dags.noise.Module; import me.dags.noise.Source; @@ -38,7 +38,7 @@ import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; -public class FrozenOcean implements Surface { +public class IcebergsSurface implements Surface { private final Module up; private final Module down; @@ -50,7 +50,7 @@ public class FrozenOcean implements Surface { private final float minDepth; private final float depthRange; - public FrozenOcean(TerraContext context, int height, int depth) { + public IcebergsSurface(TerraContext context, int height, int depth) { Levels levels = context.levels; Module shape = Source.perlin(context.seed.next(), 65, 3) .warp(context.seed.next(), 15, 1, 10) @@ -117,7 +117,7 @@ public class FrozenOcean implements Surface { return States.PACKED_ICE.get(); } - private float alpha(Cell cell) { + private float alpha(Cell cell) { if (cell.value > minDepth) { return 0; } diff --git a/src/main/java/com/terraforged/mod/biome/surface/SteppeSurface.java b/src/main/java/com/terraforged/mod/biome/surface/SteppeSurface.java new file mode 100644 index 0000000..c567912 --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/surface/SteppeSurface.java @@ -0,0 +1,30 @@ +package com.terraforged.mod.biome.surface; + +import com.terraforged.api.chunk.surface.Surface; +import com.terraforged.api.chunk.surface.SurfaceContext; +import com.terraforged.api.material.state.States; +import me.dags.noise.Module; +import me.dags.noise.Source; +import me.dags.noise.func.CellFunc; +import net.minecraft.block.BlockState; + +public class SteppeSurface implements Surface { + + @Override + public void buildSurface(int x, int z, int height, SurfaceContext ctx) { + Module module = Source.cell(123, 4, CellFunc.DISTANCE).warp(214, 80, 1, 40); + float value = module.getValue(x, z); + + BlockState state = States.SAND.get(); + + if (value > 0.275F) { + state = States.GRASS_BLOCK.get(); + } else if (value > 0.225F) { + state = States.DIRT.get(); + } + + ctx.chunk.setBlockState(ctx.pos.setPos(x, height, z), state, false); + ctx.chunk.setBlockState(ctx.pos.setPos(x, height-1, z), state, false); + ctx.chunk.setBlockState(ctx.pos.setPos(x, height-2, z), state, false); + } +} diff --git a/src/main/java/com/terraforged/mod/biome/surface/SwampSurface.java b/src/main/java/com/terraforged/mod/biome/surface/SwampSurface.java new file mode 100644 index 0000000..68d7d11 --- /dev/null +++ b/src/main/java/com/terraforged/mod/biome/surface/SwampSurface.java @@ -0,0 +1,34 @@ +package com.terraforged.mod.biome.surface; + +import com.terraforged.api.chunk.surface.Surface; +import com.terraforged.api.chunk.surface.SurfaceContext; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; +import net.minecraft.world.gen.surfacebuilders.SurfaceBuilderConfig; + +public class SwampSurface implements Surface { + + private final SurfaceBuilderConfig config = SurfaceBuilder.GRASS_DIRT_GRAVEL_CONFIG; + + @Override + public void buildSurface(int x, int z, int height, SurfaceContext ctx) { + double noise = Biome.INFO_NOISE.noiseAt(x * 0.25D, z * 0.25D, false); + if (noise > 0.0D) { + int dx = x & 15; + int dz = z & 15; + for (int y = height; y >= height - 10; --y) { + ctx.pos.setPos(dx, y, dz); + if (ctx.buffer.getBlockState(ctx.pos).isAir()) { + continue; + } + + if (y == ctx.seaLevel && ctx.buffer.getBlockState(ctx.pos).getBlock() != ctx.fluid.getBlock()) { + ctx.buffer.setBlockState(ctx.pos, ctx.fluid, false); + } + break; + } + } + + SurfaceBuilder.DEFAULT.buildSurface(ctx.random, ctx.buffer, ctx.biome, x, z, height, noise, ctx.solid, ctx.fluid, ctx.seaLevel, ctx.seed, config); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/tag/BiomeTagManager.java b/src/main/java/com/terraforged/mod/biome/tag/BiomeTagManager.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/biome/tag/BiomeTagManager.java rename to src/main/java/com/terraforged/mod/biome/tag/BiomeTagManager.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkGeneratorFactory.java b/src/main/java/com/terraforged/mod/chunk/ChunkGeneratorFactory.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/ChunkGeneratorFactory.java rename to src/main/java/com/terraforged/mod/chunk/ChunkGeneratorFactory.java diff --git a/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java b/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java new file mode 100644 index 0000000..904a1ad --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/TerraChunkGenerator.java @@ -0,0 +1,240 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.chunk; + +import com.terraforged.api.chunk.column.ColumnDecorator; +import com.terraforged.api.chunk.surface.SurfaceManager; +import com.terraforged.api.material.layer.LayerManager; +import com.terraforged.core.cell.Cell; +import com.terraforged.core.region.Size; +import com.terraforged.core.region.chunk.ChunkReader; +import com.terraforged.core.region.gen.RegionCache; +import com.terraforged.mod.feature.manager.FeatureManager; +import com.terraforged.mod.feature.manager.data.DataManager; +import com.terraforged.mod.Log; +import com.terraforged.mod.biome.provider.BiomeProvider; +import com.terraforged.mod.chunk.component.BiomeGenerator; +import com.terraforged.mod.chunk.component.MobGenerator; +import com.terraforged.mod.chunk.component.StructureGenerator; +import com.terraforged.mod.chunk.component.TerrainCarver; +import com.terraforged.mod.chunk.component.TerrainGenerator; +import com.terraforged.mod.chunk.util.TerraHooks; +import com.terraforged.mod.feature.BlockDataManager; +import com.terraforged.mod.material.Materials; +import com.terraforged.mod.material.geology.GeoManager; +import com.terraforged.mod.util.Environment; +import com.terraforged.mod.util.setup.SetupHooks; +import net.minecraft.entity.EntityClassification; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeManager; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.GenerationSettings; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.gen.feature.template.TemplateManager; +import net.minecraft.world.server.ServerWorld; + +import java.util.List; + +public class TerraChunkGenerator extends ChunkGenerator { + + private final TerraContext context; + private final BiomeProvider biomeProvider; + + private final MobGenerator mobGenerator; + private final BiomeGenerator biomeGenerator; + private final TerrainCarver terrainCarver; + private final TerrainGenerator terrainGenerator; + private final StructureGenerator structureGenerator; + + private final GeoManager geologyManager; + private final FeatureManager featureManager; + private final SurfaceManager surfaceManager; + private final BlockDataManager blockDataManager; + private final List baseDecorators; + private final List postProcessors; + + private final RegionCache regionCache; + + public TerraChunkGenerator(TerraContext context, BiomeProvider biomeProvider, GenerationSettings settings) { + super(context.world, biomeProvider, settings); + this.context = context; + this.biomeProvider = biomeProvider; + this.mobGenerator = new MobGenerator(this); + this.biomeGenerator = new BiomeGenerator(this); + this.terrainCarver = new TerrainCarver(this); + this.terrainGenerator = new TerrainGenerator(this); + this.structureGenerator = new StructureGenerator(this); + + this.surfaceManager = TerraHooks.createSurfaceManager(context); + this.geologyManager = TerraHooks.createGeologyManager(context); + this.baseDecorators = TerraHooks.createBaseDecorators(geologyManager, context); + this.postProcessors = TerraHooks.createFeatureDecorators(context); + this.regionCache = context.cache; + + try (DataManager data = TerraHooks.createDataManager()) { + FeatureManager.initData(data); + this.featureManager = TerraHooks.createFeatureManager(data, context); + this.blockDataManager = TerraHooks.createBlockDataManager(data, context); + FeatureManager.clearData(); + } + + SetupHooks.setup(getLayerManager(), context.copy()); + SetupHooks.setup(baseDecorators, postProcessors, context.copy()); + Log.info("Vanilla Biomes: {}", Environment.isVanillaBiomes()); + } + + @Override + public final void generateStructures(BiomeManager biomes, IChunk chunk, ChunkGenerator generator, TemplateManager templates) { + structureGenerator.generateStructureStarts(biomes, chunk, generator, templates); + } + + @Override + public final void generateStructureStarts(IWorld world, IChunk chunk) { + structureGenerator.generateStructureReferences(world, chunk); + } + + @Override + public final void generateBiomes(IChunk chunk) { + biomeGenerator.generateBiomes(chunk); + } + + @Override + public final void makeBase(IWorld world, IChunk chunk) { + terrainGenerator.generateTerrain(world, chunk); + } + + @Override + public final void func_225551_a_(WorldGenRegion world, IChunk chunk) { + terrainGenerator.generateSurface(world, chunk); + } + + @Override + public final void decorate(WorldGenRegion region) { + terrainGenerator.generateFeatures(region); + } + + @Override + public final void func_225550_a_(BiomeManager biomes, IChunk chunk, GenerationStage.Carving type) { + terrainCarver.carveTerrain(biomes, chunk, type); + } + + @Override + public final void spawnMobs(WorldGenRegion region) { + mobGenerator.generateMobs(region); + } + + @Override + public final void spawnMobs(ServerWorld worldIn, boolean hostile, boolean peaceful) { + mobGenerator.spawnMobs(worldIn, hostile, peaceful); + } + + @Override + public final List getPossibleCreatures(EntityClassification type, BlockPos pos) { + return mobGenerator.getPossibleCreatures(world, type, pos); + } + + public final Biome getBiome(BiomeManager biomes, BlockPos pos) { + return super.getBiome(biomes, pos); + } + + @Override + public final int func_222529_a(int x, int z, Heightmap.Type type) { + int chunkX = Size.blockToChunk(x); + int chunkZ = Size.blockToChunk(z); + ChunkReader chunk = getChunkReader(chunkX, chunkZ); + Cell cell = chunk.getCell(x, z); + int level = context.levels.scale(cell.value) + 1; + if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) { + return level; + } + return Math.max(getSeaLevel(), level); + } + + @Override + public BiomeProvider getBiomeProvider() { + return biomeProvider; + } + + @Override + public final int getMaxHeight() { + return getContext().levels.worldHeight; + } + + @Override + public final int getSeaLevel() { + return getContext().levels.waterLevel; + } + + @Override + public final int getGroundHeight() { + return getContext().levels.groundLevel; + } + + public final TerraContext getContext() { + return context; + } + + public final Materials getMaterials() { + return context.materials; + } + + public final FeatureManager getFeatureManager() { + return featureManager; + } + + public final GeoManager getGeologyManager() { + return geologyManager; + } + + public final LayerManager getLayerManager() { + return context.materials.getLayerManager(); + } + + public final SurfaceManager getSurfaceManager() { + return surfaceManager; + } + + public final BlockDataManager getBlockDataManager() { + return blockDataManager; + } + + public final List getBaseDecorators() { + return baseDecorators; + } + + public final List getPostProcessors() { + return postProcessors; + } + + public final ChunkReader getChunkReader(int chunkX, int chunkZ) { + return regionCache.getChunk(chunkX, chunkZ); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContext.java b/src/main/java/com/terraforged/mod/chunk/TerraContext.java similarity index 68% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContext.java rename to src/main/java/com/terraforged/mod/chunk/TerraContext.java index aacd5e8..d15ddc9 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContext.java +++ b/src/main/java/com/terraforged/mod/chunk/TerraContext.java @@ -28,14 +28,15 @@ package com.terraforged.mod.chunk; import com.terraforged.api.chunk.column.DecoratorContext; import com.terraforged.api.chunk.surface.ChunkSurfaceBuffer; import com.terraforged.api.chunk.surface.SurfaceContext; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.heightmap.Heightmap; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.core.region.gen.RegionCache; +import com.terraforged.core.region.gen.RegionGenerator; +import com.terraforged.core.concurrent.ThreadPool; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.WorldGeneratorFactory; +import com.terraforged.world.heightmap.Heightmap; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.material.Materials; import com.terraforged.mod.settings.TerraSettings; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.world.IWorld; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.GenerationSettings; @@ -45,18 +46,22 @@ public class TerraContext extends GeneratorContext { public final IWorld world; public final Heightmap heightmap; public final Materials materials; - public final WorldGeneratorFactory factory; public final TerraSettings terraSettings; + public TerraContext(TerraContext other) { + super(other.terrain, other.settings, other.terrainFactory, TerraContext::createCache); + this.world = other.world; + this.materials = other.materials; + this.terraSettings = other.terraSettings; + this.heightmap = factory.getHeightmap(); + } + public TerraContext(IWorld world, Terrains terrain, TerraSettings settings) { - super(terrain, settings, TerraTerrainProvider::new); + super(terrain, settings, TerraTerrainProvider::new, TerraContext::createCache); this.world = world; this.materials = new Materials(); this.terraSettings = settings; - this.factory = new WorldGeneratorFactory(this); this.heightmap = factory.getHeightmap(); - ItemStack stack = new ItemStack(Items.COBBLESTONE); - stack.getMaxStackSize(); } public DecoratorContext decorator(IChunk chunk) { @@ -66,4 +71,14 @@ public class TerraContext extends GeneratorContext { public SurfaceContext surface(ChunkSurfaceBuffer buffer, GenerationSettings settings) { return new SurfaceContext(buffer, levels, terrain, factory.getClimate(), settings, world.getSeed()); } + + public static RegionCache createCache(WorldGeneratorFactory factory) { + return RegionGenerator.builder() + .factory(factory) + .size(3, 2) + .pool(ThreadPool.getPool()) + .batch(6) + .build() + .toCache(); + } } diff --git a/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java b/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java new file mode 100644 index 0000000..c7eba3d --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/TerraGenSettings.java @@ -0,0 +1,92 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.chunk; + +import com.terraforged.mod.settings.StructureSettings; +import net.minecraft.world.gen.OverworldGenSettings; + +public class TerraGenSettings extends OverworldGenSettings { + + private final int villageSeparation; + private final int mansionSeparation; + private final int biomeFeatureSeparation; + private final int shipwreckDistance; + private final int shipwreckSeparation; + private final int oceanRuinDistance; + private final int oceanRuinSeparation; + + public TerraGenSettings(StructureSettings settings) { + super.villageDistance = settings.villages.distance; + this.villageSeparation = settings.villages.separation; + super.mansionDistance = settings.mansions.distance; + this.mansionSeparation = settings.mansions.separation; + super.strongholdDistance = settings.strongholds.distance; + super.strongholdSpread = settings.strongholds.separation; + super.oceanMonumentSpacing = settings.oceanMonuments.distance; + super.oceanMonumentSeparation = settings.oceanMonuments.separation; + super.biomeFeatureDistance = settings.otherStructures.distance; + this.biomeFeatureSeparation = settings.otherStructures.separation; + this.shipwreckDistance = settings.shipwrecks.distance; + this.shipwreckSeparation = settings.shipwrecks.separation; + this.oceanRuinDistance = settings.oceanRuins.distance; + this.oceanRuinSeparation = settings.oceanRuins.separation; + } + + @Override + public int getVillageSeparation() { + return villageSeparation; + } + + @Override + public int getMansionSeparation() { + return mansionSeparation; + } + + @Override + public int getBiomeFeatureSeparation() { + return biomeFeatureSeparation; + } + + @Override + public int getOceanRuinDistance() { + return oceanRuinDistance; + } + + @Override + public int getOceanRuinSeparation() { + return oceanRuinSeparation; + } + + @Override + public int getShipwreckDistance() { + return shipwreckDistance; + } + + @Override + public int getShipwreckSeparation() { + return shipwreckSeparation; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java b/src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java similarity index 89% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java rename to src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java index a6365df..9527781 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java +++ b/src/main/java/com/terraforged/mod/chunk/TerraTerrainProvider.java @@ -26,9 +26,9 @@ package com.terraforged.mod.chunk; import com.terraforged.core.cell.Populator; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.heightmap.RegionConfig; -import com.terraforged.core.world.terrain.provider.StandardTerrainProvider; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.heightmap.RegionConfig; +import com.terraforged.world.terrain.provider.StandardTerrainProvider; import com.terraforged.mod.util.setup.SetupHooks; public class TerraTerrainProvider extends StandardTerrainProvider { diff --git a/src/main/java/com/terraforged/mod/chunk/component/BiomeGenerator.java b/src/main/java/com/terraforged/mod/chunk/component/BiomeGenerator.java new file mode 100644 index 0000000..6ba46d4 --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/component/BiomeGenerator.java @@ -0,0 +1,39 @@ +package com.terraforged.mod.chunk.component; + +import com.terraforged.core.region.chunk.ChunkReader; +import com.terraforged.world.terrain.decorator.Decorator; +import com.terraforged.mod.chunk.TerraChunkGenerator; +import com.terraforged.mod.chunk.util.TerraContainer; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.ChunkPrimer; +import net.minecraft.world.chunk.IChunk; + +public class BiomeGenerator { + + private final TerraChunkGenerator generator; + + public BiomeGenerator(TerraChunkGenerator generator) { + this.generator = generator; + } + + public void generateBiomes(IChunk chunk) { + ChunkPos pos = chunk.getPos(); + ChunkReader reader = generator.getChunkReader(pos.x, pos.z); + TerraContainer container = generator.getBiomeProvider().createBiomeContainer(reader); + ((ChunkPrimer) chunk).func_225548_a_(container); + // apply chunk-local heightmap modifications + preProcess(pos, reader, container); + } + + private void preProcess(ChunkPos pos, ChunkReader chunk, TerraContainer container) { + chunk.iterate((cell, dx, dz) -> { + Biome biome = container.getBiome(dx, dz); + for (Decorator decorator : generator.getBiomeProvider().getDecorators(biome)) { + if (decorator.apply(cell, pos.getXStart() + dx, pos.getZStart() + dz)) { + return; + } + } + }); + } +} diff --git a/src/main/java/com/terraforged/mod/chunk/component/MobGenerator.java b/src/main/java/com/terraforged/mod/chunk/component/MobGenerator.java new file mode 100644 index 0000000..7807102 --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/component/MobGenerator.java @@ -0,0 +1,69 @@ +package com.terraforged.mod.chunk.component; + +import com.terraforged.mod.chunk.TerraChunkGenerator; +import com.terraforged.mod.chunk.fix.SpawnFix; +import net.minecraft.entity.EntityClassification; +import net.minecraft.util.SharedSeedRandom; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.spawner.CatSpawner; +import net.minecraft.world.spawner.PatrolSpawner; +import net.minecraft.world.spawner.PhantomSpawner; +import net.minecraft.world.spawner.WorldEntitySpawner; + +import java.util.List; + +public class MobGenerator { + + private final CatSpawner catSpawner = new CatSpawner(); + private final PatrolSpawner patrolSpawner = new PatrolSpawner(); + private final PhantomSpawner phantomSpawner = new PhantomSpawner(); + private final TerraChunkGenerator generator; + + public MobGenerator(TerraChunkGenerator generator) { + this.generator = generator; + } + + public final void generateMobs(WorldGenRegion region) { + // vanilla does NOT check the mobSpawning gamerule before calling this + if (SpawnFix.canSpawnMobs()) { + int chunkX = region.getMainChunkX(); + int chunkZ = region.getMainChunkZ(); + Biome biome = region.getChunk(chunkX, chunkZ).getBiomes().getNoiseBiome(0, 0, 0); + SharedSeedRandom sharedseedrandom = new SharedSeedRandom(); + sharedseedrandom.setDecorationSeed(region.getSeed(), chunkX << 4, chunkZ << 4); + WorldEntitySpawner.performWorldGenSpawning(region, biome, chunkX, chunkZ, sharedseedrandom); + } + } + + public final void spawnMobs(ServerWorld world, boolean hostile, boolean peaceful) { + phantomSpawner.tick(world, hostile, peaceful); + patrolSpawner.tick(world, hostile, peaceful); + catSpawner.tick(world, hostile, peaceful); + } + + public final List getPossibleCreatures(IWorld world, EntityClassification type, BlockPos pos) { + if (Feature.SWAMP_HUT.func_202383_b(world, pos)) { + if (type == EntityClassification.MONSTER) { + return Feature.SWAMP_HUT.getSpawnList(); + } + + if (type == EntityClassification.CREATURE) { + return Feature.SWAMP_HUT.getCreatureSpawnList(); + } + } else if (type == EntityClassification.MONSTER) { + if (Feature.PILLAGER_OUTPOST.isPositionInStructure(world, pos)) { + return Feature.PILLAGER_OUTPOST.getSpawnList(); + } + + if (Feature.OCEAN_MONUMENT.isPositionInStructure(world, pos)) { + return Feature.OCEAN_MONUMENT.getSpawnList(); + } + } + return world.getBiome(pos).getSpawns(type); + } +} diff --git a/src/main/java/com/terraforged/mod/chunk/component/StructureGenerator.java b/src/main/java/com/terraforged/mod/chunk/component/StructureGenerator.java new file mode 100644 index 0000000..948f27b --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/component/StructureGenerator.java @@ -0,0 +1,85 @@ +package com.terraforged.mod.chunk.component; + +import com.terraforged.mod.chunk.TerraChunkGenerator; +import net.minecraft.network.DebugPacketSender; +import net.minecraft.util.SharedSeedRandom; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MutableBoundingBox; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeManager; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.structure.Structure; +import net.minecraft.world.gen.feature.structure.StructureStart; +import net.minecraft.world.gen.feature.template.TemplateManager; + +import java.util.Map; + +public class StructureGenerator { + + private final TerraChunkGenerator generator; + + public StructureGenerator(TerraChunkGenerator generator) { + this.generator = generator; + } + + public void generateStructureStarts(BiomeManager biomes, IChunk chunk, ChunkGenerator generator, TemplateManager templates) { + ChunkPos chunkpos = chunk.getPos(); + BlockPos biomePos = new BlockPos(chunkpos.getXStart() + 9, 0, chunkpos.getZStart() + 9); + + for (Structure structure : Feature.STRUCTURES.values()) { + if (generator.getBiomeProvider().hasStructure(structure)) { + StructureStart existingStart = chunk.getStructureStart(structure.getStructureName()); + int refCount = existingStart != null ? existingStart.func_227457_j_() : 0; + + SharedSeedRandom random = new SharedSeedRandom(); + StructureStart start = StructureStart.DUMMY; + + Biome biome = biomes.getBiome(biomePos); + if (structure.func_225558_a_(biomes, generator, random, chunkpos.x, chunkpos.z, biome)) { + StructureStart altStart = structure.getStartFactory().create(structure, chunkpos.x, chunkpos.z, MutableBoundingBox.getNewBoundingBox(), refCount, generator.getSeed()); + altStart.init(generator, templates, chunkpos.x, chunkpos.z, biome); + start = altStart.isValid() ? altStart : StructureStart.DUMMY; + } + + chunk.putStructureStart(structure.getStructureName(), start); + } + } + } + + public void generateStructureReferences(IWorld world, IChunk chunk) { + try { + int radius = 8; + + int chunkX = chunk.getPos().x; + int chunkZ = chunk.getPos().z; + + int minX = chunkX << 4; + int minZ = chunkZ << 4; + int maxX = minX + 15; + int maxZ = minZ + 15; + + for (int dx = -radius; dx <= radius; ++dx) { + for (int dz = -radius; dz <= radius; ++dz) { + int cx = chunkX + dx; + int cz = chunkZ + dz; + long chunkSeed = ChunkPos.asLong(cx, cz); + IChunk c = world.getChunk(cx, cz); + for (Map.Entry entry : c.getStructureStarts().entrySet()) { + StructureStart start = entry.getValue(); + if (start != StructureStart.DUMMY && start.getBoundingBox().intersectsWith(minX, minZ, maxX, maxZ)) { + chunk.addStructureReference(entry.getKey(), chunkSeed); + DebugPacketSender.sendStructureStart(world, start); + } + } + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } +} diff --git a/src/main/java/com/terraforged/mod/chunk/component/TerrainCarver.java b/src/main/java/com/terraforged/mod/chunk/component/TerrainCarver.java new file mode 100644 index 0000000..cfbc9cd --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/component/TerrainCarver.java @@ -0,0 +1,57 @@ +package com.terraforged.mod.chunk.component; + +import com.terraforged.mod.chunk.TerraChunkGenerator; +import com.terraforged.mod.chunk.fix.ChunkCarverFix; +import net.minecraft.util.SharedSeedRandom; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.BiomeManager; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.carver.ConfiguredCarver; + +import java.util.BitSet; +import java.util.List; +import java.util.ListIterator; + +public class TerrainCarver { + + private final TerraChunkGenerator generator; + + public TerrainCarver(TerraChunkGenerator generator) { + this.generator = generator; + } + + public void carveTerrain(BiomeManager biomes, IChunk chunk, GenerationStage.Carving type) { + // World carvers have hardcoded 'carvable' blocks which can be problematic with modded blocks + // AirCarverFix shims the actual blockstates to an equivalent carvable type + chunk = new ChunkCarverFix(chunk, generator.getContext().materials); + + SharedSeedRandom random = new SharedSeedRandom(); + + ChunkPos chunkpos = chunk.getPos(); + int chunkX = chunkpos.x; + int chunkZ = chunkpos.z; + + BitSet mask = chunk.getCarvingMask(type); + Biome biome = generator.getBiome(biomes, chunkpos.asBlockPos()); + + List> carvers = biome.getCarvers(type); + ListIterator> iterator = carvers.listIterator(); + + for(int cx = chunkX - 8; cx <= chunkX + 8; ++cx) { + for(int cz = chunkZ - 8; cz <= chunkZ + 8; ++cz) { + + while(iterator.hasNext()) { + int index = iterator.nextIndex(); + ConfiguredCarver carver = iterator.next(); + random.setLargeFeatureSeed(generator.getSeed() + index, cx, cz); + if (carver.shouldCarve(random, cx, cz)) { + carver.func_227207_a_(chunk, pos -> generator.getBiome(biomes, pos), random, generator.getSeaLevel(), cx, cz, chunkX, chunkZ, mask); + } + } + } + } + + } +} diff --git a/src/main/java/com/terraforged/mod/chunk/component/TerrainGenerator.java b/src/main/java/com/terraforged/mod/chunk/component/TerrainGenerator.java new file mode 100644 index 0000000..0bbd3d6 --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/component/TerrainGenerator.java @@ -0,0 +1,143 @@ +package com.terraforged.mod.chunk.component; + +import com.terraforged.api.chunk.column.ColumnDecorator; +import com.terraforged.api.chunk.column.DecoratorContext; +import com.terraforged.api.chunk.surface.ChunkSurfaceBuffer; +import com.terraforged.api.chunk.surface.SurfaceContext; +import com.terraforged.core.region.chunk.ChunkReader; +import com.terraforged.mod.chunk.util.FastChunk; +import com.terraforged.mod.chunk.TerraChunkGenerator; +import com.terraforged.mod.chunk.util.TerraContainer; +import com.terraforged.mod.chunk.fix.RegionFix; +import com.terraforged.mod.decorator.ChunkPopulator; +import com.terraforged.mod.feature.TerrainHelper; +import com.terraforged.mod.util.Environment; +import net.minecraft.util.SharedSeedRandom; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.ChunkPrimer; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.gen.INoiseGenerator; +import net.minecraft.world.gen.PerlinNoiseGenerator; +import net.minecraft.world.gen.WorldGenRegion; + +import java.util.List; + +public class TerrainGenerator { + + private final TerraChunkGenerator generator; + private final TerrainHelper terrainHelper; + private final INoiseGenerator surfaceNoise; + + public TerrainGenerator(TerraChunkGenerator generator) { + this.generator = generator; + this.terrainHelper = new TerrainHelper(0.75F); + this.surfaceNoise = new PerlinNoiseGenerator(new SharedSeedRandom(generator.getSeed()), 3, 0); + } + + public final void generateTerrain(IWorld world, IChunk chunk) { + TerraContainer container = getBiomeContainer(chunk); + DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), generator.getContext().levels, generator.getContext().terrain, generator.getContext().factory.getClimate()); + container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { + int px = ctx.blockX + dx; + int pz = ctx.blockZ + dz; + int py = ctx.levels.scale(cell.value); + ctx.cell = cell; + ctx.biome = container.getBiome(dx, dz); + ChunkPopulator.INSTANCE.decorate(ctx.chunk, ctx, px, py, pz); + }); + terrainHelper.flatten(world, chunk); + } + + public final void generateSurface(WorldGenRegion world, IChunk chunk) { + TerraContainer container = getBiomeContainer(chunk); + ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk)); + SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings()); + + container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { + int px = ctx.blockX + dx; + int pz = ctx.blockZ + dz; + int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz) + 1; + + ctx.buffer.setSurfaceLevel(top); + + ctx.cell = cell; + ctx.biome = container.getBiome(dx, dz); + ctx.noise = getSurfaceNoise(px, pz) * 15D; + + generator.getSurfaceManager().getSurface(ctx).buildSurface(px, pz, top, ctx); + + int py = ctx.levels.scale(cell.value); + for (ColumnDecorator processor : generator.getBaseDecorators()) { + processor.decorate(ctx.buffer, ctx, px, py, pz); + } + }); + + FastChunk.updateWGHeightmaps(chunk, context.pos); + } + + public final void generateFeatures(WorldGenRegion region) { + int chunkX = region.getMainChunkX(); + int chunkZ = region.getMainChunkZ(); + IChunk chunk = region.getChunk(chunkX, chunkZ); + TerraContainer container = getBiomeContainer(chunk); + Biome biome = container.getFeatureBiome(); + DecoratorContext context = generator.getContext().decorator(chunk); + + IWorld regionFix = new RegionFix(region, generator); + BlockPos pos = new BlockPos(context.blockX, 0, context.blockZ); + + // place biome features + generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos); + + // run post processes on chunk + postProcess(container.getChunkReader(), container, context); + + // bake biome array & discard gen data + ((ChunkPrimer) chunk).func_225548_a_(container.bakeBiomes(Environment.isVanillaBiomes())); + + // marks the heightmap data for this chunk for removal + container.getChunkReader().dispose(); + } + + private void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context) { + List decorators = generator.getPostProcessors(); + chunk.iterate(context, (cell, dx, dz, ctx) -> { + int px = ctx.blockX + dx; + int pz = ctx.blockZ + dz; + int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz); + ctx.cell = cell; + ctx.biome = container.getBiome(dx, dz); + for (ColumnDecorator decorator : decorators) { + decorator.decorate(ctx.chunk, ctx, px, py, pz); + } + }); + } + + private double getSurfaceNoise(int x, int z) { + double scale = 0.0625D; + double noiseX = x * scale; + double noiseZ = z * scale; + double unusedValue1 = scale; + double unusedValue2 = (x & 15) * scale; + return surfaceNoise.noiseAt(noiseX, noiseZ, unusedValue1, unusedValue2); + } + + private TerraContainer getBiomeContainer(IChunk chunk) { + if (chunk.getBiomes() instanceof TerraContainer) { + return (TerraContainer) chunk.getBiomes(); + } + + ChunkReader view = generator.getChunkReader(chunk.getPos().x, chunk.getPos().z); + TerraContainer container = generator.getBiomeProvider().createBiomeContainer(view); + if (chunk instanceof ChunkPrimer) { + ((ChunkPrimer) chunk).func_225548_a_(container); + } else if (chunk instanceof FastChunk) { + ((FastChunk) chunk).setBiomes(container); + } + + return container; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/ChunkCarverFix.java b/src/main/java/com/terraforged/mod/chunk/fix/ChunkCarverFix.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/ChunkCarverFix.java rename to src/main/java/com/terraforged/mod/chunk/fix/ChunkCarverFix.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java b/src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java similarity index 93% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java rename to src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java index 446ef98..77351f2 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java +++ b/src/main/java/com/terraforged/mod/chunk/fix/RegionDelegate.java @@ -129,8 +129,8 @@ public class RegionDelegate extends WorldGenRegion { } @Override - public boolean func_225521_a_(BlockPos p_225521_1_, boolean p_225521_2_, @Nullable Entity p_225521_3_) { - return region.func_225521_a_(p_225521_1_, p_225521_2_, p_225521_3_); + public boolean func_225521_a_(BlockPos pos, boolean drop, @Nullable Entity entity) { + return region.func_225521_a_(pos, drop, entity); } @Override @@ -545,38 +545,38 @@ public class RegionDelegate extends WorldGenRegion { } @Override - public boolean func_226668_i_(Entity p_226668_1_) { - return region.func_226668_i_(p_226668_1_); + public boolean func_226669_j_(Entity entity) { + return region.func_226669_j_(entity); } @Override - public boolean func_226664_a_(AxisAlignedBB p_226664_1_) { - return region.func_226664_a_(p_226664_1_); + public boolean func_226664_a_(AxisAlignedBB bounds) { + return region.func_226664_a_(bounds); } @Override - public boolean func_226669_j_(Entity p_226669_1_) { - return region.func_226669_j_(p_226669_1_); + public boolean func_226668_i_(Entity entity) { + return region.func_226668_i_(entity); } @Override - public boolean func_226665_a__(Entity p_226665_1_, AxisAlignedBB p_226665_2_) { - return region.func_226665_a__(p_226665_1_, p_226665_2_); + public boolean func_226665_a__(Entity entity, AxisAlignedBB bounds) { + return region.func_226665_a__(entity, bounds); } @Override - public boolean func_226662_a_(@Nullable Entity p_226662_1_, AxisAlignedBB p_226662_2_, Set p_226662_3_) { - return region.func_226662_a_(p_226662_1_, p_226662_2_, p_226662_3_); + public boolean func_226662_a_(@Nullable Entity entity, AxisAlignedBB bounds, Set set) { + return region.func_226662_a_(entity, bounds, set); } @Override - public Stream func_226667_c_(@Nullable Entity p_226667_1_, AxisAlignedBB p_226667_2_, Set p_226667_3_) { - return region.func_226667_c_(p_226667_1_, p_226667_2_, p_226667_3_); + public Stream func_226667_c_(@Nullable Entity entity, AxisAlignedBB bounds, Set entities) { + return region.func_226667_c_(entity, bounds, entities); } @Override - public Stream func_226666_b_(@Nullable Entity p_226666_1_, AxisAlignedBB p_226666_2_) { - return region.func_226666_b_(p_226666_1_, p_226666_2_); + public Stream func_226666_b_(@Nullable Entity entity, AxisAlignedBB bounds) { + return region.func_226666_b_(entity, bounds); } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/RegionFix.java b/src/main/java/com/terraforged/mod/chunk/fix/RegionFix.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/RegionFix.java rename to src/main/java/com/terraforged/mod/chunk/fix/RegionFix.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/SpawnFix.java b/src/main/java/com/terraforged/mod/chunk/fix/SpawnFix.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/fix/SpawnFix.java rename to src/main/java/com/terraforged/mod/chunk/fix/SpawnFix.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/Test.java b/src/main/java/com/terraforged/mod/chunk/test/Test.java similarity index 87% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/Test.java rename to src/main/java/com/terraforged/mod/chunk/test/Test.java index a6e716b..b79bbdf 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/Test.java +++ b/src/main/java/com/terraforged/mod/chunk/test/Test.java @@ -25,20 +25,20 @@ package com.terraforged.mod.chunk.test; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.terrain.Terrain; +import com.terraforged.world.terrain.Terrains; +import com.terraforged.mod.biome.ModBiomes; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.Biomes; public class Test { public static boolean fixedBiome = true; public static Terrain getTerrainType(Terrains terrains) { - return terrains.mountains; + return terrains.steppe; } public static Biome getBiome() { - return Biomes.PLAINS; + return ModBiomes.STEPPE; } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java b/src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java similarity index 93% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java rename to src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java index 728d0e9..dc8c0d7 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java +++ b/src/main/java/com/terraforged/mod/chunk/test/TestBiomeProvider.java @@ -26,7 +26,6 @@ package com.terraforged.mod.chunk.test; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.terrain.Terrain; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.chunk.TerraContext; import net.minecraft.world.biome.Biome; @@ -38,7 +37,7 @@ public class TestBiomeProvider extends BiomeProvider { } @Override - public Biome getBiome(Cell cell, int x, int z) { + public Biome getBiome(Cell cell, int x, int z) { return Test.getBiome(); } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java b/src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java similarity index 71% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java rename to src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java index f823aa6..73e140f 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java +++ b/src/main/java/com/terraforged/mod/chunk/test/TestChunkGenerator.java @@ -27,13 +27,8 @@ package com.terraforged.mod.chunk.test; import com.terraforged.core.cell.Cell; import com.terraforged.core.cell.Populator; -import com.terraforged.core.region.gen.RegionCache; -import com.terraforged.core.region.gen.RegionGenerator; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.heightmap.WorldHeightmap; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.heightmap.WorldHeightmap; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.chunk.TerraChunkGenerator; import com.terraforged.mod.chunk.TerraContext; @@ -44,20 +39,10 @@ public class TestChunkGenerator extends TerraChunkGenerator { private final BiomeProvider biomeProvider; public TestChunkGenerator(TerraContext context, BiomeProvider biomeProvider, GenerationSettings settings) { - super(context, biomeProvider, settings); + super(new TestTerraContext(context), biomeProvider, settings); this.biomeProvider = new TestBiomeProvider(context); } - @Override - protected RegionCache createRegionCache(TerraContext context) { - return RegionGenerator.builder() - .factory(new WorldGeneratorFactory(context, new TestHeightMap(context))) - .pool(ThreadPool.getPool()) - .size(3, 2) - .build() - .toCache(false); - } - @Override public BiomeProvider getBiomeProvider() { return biomeProvider; @@ -73,13 +58,13 @@ public class TestChunkGenerator extends TerraChunkGenerator { } @Override - public void apply(Cell cell, float x, float y) { + public void apply(Cell cell, float x, float y) { super.apply(cell, x, y); populator.apply(cell, x, y); } @Override - public void tag(Cell cell, float x, float y) { + public void tag(Cell cell, float x, float y) { populator.tag(cell, x, y); } } diff --git a/src/main/java/com/terraforged/mod/chunk/test/TestHeightMap.java b/src/main/java/com/terraforged/mod/chunk/test/TestHeightMap.java new file mode 100644 index 0000000..c4e14bd --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/test/TestHeightMap.java @@ -0,0 +1,27 @@ +package com.terraforged.mod.chunk.test; + +import com.terraforged.core.cell.Cell; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.heightmap.WorldHeightmap; +import com.terraforged.world.terrain.Terrains; + +public class TestHeightMap extends WorldHeightmap { + + private final Terrains terrains; + + public TestHeightMap(GeneratorContext context) { + super(context); + terrains = context.terrain; + } + + @Override + public void apply(Cell cell, float x, float y) { + super.apply(cell, x, y); + getPopulator(Test.getTerrainType(terrains)).apply(cell, x, y); + } + + @Override + public void tag(Cell cell, float x, float y) { + getPopulator(Test.getTerrainType(terrains)).tag(cell, x, y); + } +} diff --git a/src/main/java/com/terraforged/mod/chunk/test/TestTerraContext.java b/src/main/java/com/terraforged/mod/chunk/test/TestTerraContext.java new file mode 100644 index 0000000..c8f3088 --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/test/TestTerraContext.java @@ -0,0 +1,17 @@ +package com.terraforged.mod.chunk.test; + +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.WorldGeneratorFactory; +import com.terraforged.mod.chunk.TerraContext; + +public class TestTerraContext extends TerraContext { + + public TestTerraContext(TerraContext context) { + super(context); + } + + @Override + protected WorldGeneratorFactory createFactory(GeneratorContext context) { + return new WorldGeneratorFactory(context, new TestHeightMap(context)); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/FastChunk.java b/src/main/java/com/terraforged/mod/chunk/util/FastChunk.java similarity index 99% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/FastChunk.java rename to src/main/java/com/terraforged/mod/chunk/util/FastChunk.java index c166475..73ace63 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/FastChunk.java +++ b/src/main/java/com/terraforged/mod/chunk/util/FastChunk.java @@ -1,4 +1,4 @@ -package com.terraforged.mod.chunk; +package com.terraforged.mod.chunk.util; import com.terraforged.api.chunk.ChunkDelegate; import net.minecraft.block.BlockState; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java b/src/main/java/com/terraforged/mod/chunk/util/TerraContainer.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java rename to src/main/java/com/terraforged/mod/chunk/util/TerraContainer.java index b9f0651..24eba45 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java +++ b/src/main/java/com/terraforged/mod/chunk/util/TerraContainer.java @@ -23,13 +23,12 @@ * SOFTWARE. */ -package com.terraforged.mod.chunk; +package com.terraforged.mod.chunk.util; import com.terraforged.api.biome.BiomeVariant; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.core.util.PosIterator; -import com.terraforged.core.world.terrain.Terrain; import net.minecraft.util.math.MathHelper; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeContainer; @@ -67,7 +66,7 @@ public class TerraContainer extends BiomeContainer { public Biome getFeatureBiome() { PosIterator iterator = PosIterator.area(0, 0, 16, 16); while (iterator.next()) { - Cell cell = chunkReader.getCell(iterator.x(), iterator.z()); + Cell cell = chunkReader.getCell(iterator.x(), iterator.z()); if (cell.biomeType.isExtreme()) { return getBiome(iterator.x(), iterator.z()); } diff --git a/src/main/java/com/terraforged/mod/chunk/util/TerraHooks.java b/src/main/java/com/terraforged/mod/chunk/util/TerraHooks.java new file mode 100644 index 0000000..5cfce69 --- /dev/null +++ b/src/main/java/com/terraforged/mod/chunk/util/TerraHooks.java @@ -0,0 +1,122 @@ +package com.terraforged.mod.chunk.util; + +import com.terraforged.api.chunk.column.ColumnDecorator; +import com.terraforged.api.chunk.surface.SurfaceManager; +import com.terraforged.mod.feature.manager.FeatureManager; +import com.terraforged.mod.feature.manager.data.DataManager; +import com.terraforged.mod.feature.manager.matcher.biome.BiomeMatcher; +import com.terraforged.mod.feature.manager.matcher.feature.FeatureMatcher; +import com.terraforged.mod.feature.manager.modifier.FeatureModifiers; +import com.terraforged.mod.feature.manager.predicate.DeepWater; +import com.terraforged.mod.feature.manager.predicate.FeaturePredicate; +import com.terraforged.mod.feature.manager.predicate.MinDepth; +import com.terraforged.mod.feature.manager.predicate.MinHeight; +import com.terraforged.mod.Log; +import com.terraforged.mod.biome.ModBiomes; +import com.terraforged.mod.biome.surface.IcebergsSurface; +import com.terraforged.mod.biome.surface.SteppeSurface; +import com.terraforged.mod.biome.surface.SwampSurface; +import com.terraforged.mod.chunk.TerraContext; +import com.terraforged.mod.decorator.terrain.BedrockDecorator; +import com.terraforged.mod.decorator.terrain.CoastDecorator; +import com.terraforged.mod.decorator.terrain.ErosionDecorator; +import com.terraforged.mod.decorator.terrain.GeologyDecorator; +import com.terraforged.mod.decorator.feature.LayerDecorator; +import com.terraforged.mod.decorator.feature.SnowEroder; +import com.terraforged.mod.feature.Matchers; +import com.terraforged.mod.feature.BlockDataManager; +import com.terraforged.mod.material.geology.GeoManager; +import com.terraforged.mod.util.setup.SetupHooks; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +import net.minecraft.world.gen.feature.Feature; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class TerraHooks { + + public static DataManager createDataManager() { + return FeatureManager.data(new File("config/terraforged/datapacks")); + } + + public static List createBaseDecorators(GeoManager geoManager, TerraContext context) { + List processors = new ArrayList<>(); + if (context.terraSettings.features.strataDecorator) { + Log.info(" - Geology decorator enabled"); + processors.add(new GeologyDecorator(geoManager)); + } + if (context.terraSettings.features.erosionDecorator) { + Log.info(" - Erosion decorator enabled"); + processors.add(new ErosionDecorator(context)); + } + processors.add(new CoastDecorator(context)); + processors.add(new BedrockDecorator(context)); + return processors; + } + + public static List createFeatureDecorators(TerraContext context) { + List processors = new ArrayList<>(); + if (context.terraSettings.features.naturalSnowDecorator) { + Log.info(" - Natural snow decorator enabled"); + processors.add(new SnowEroder(context)); + } + if (context.terraSettings.features.smoothLayerDecorator) { + Log.info(" - Smooth layer decorator enabled"); + processors.add(new LayerDecorator(context.materials.getLayerManager())); + } + return processors; + } + + public static BlockDataManager createBlockDataManager(DataManager data, TerraContext context) { + return new BlockDataManager(data); + } + + public static FeatureManager createFeatureManager(DataManager data, TerraContext context) { + FeatureModifiers modifiers = FeatureManager.modifiers(data, context.terraSettings.features.customBiomeFeatures); + + if (context.terraSettings.features.strataDecorator) { + // block stone blobs if strata enabled + modifiers.getPredicates().add(Matchers.stoneBlobs(), FeaturePredicate.DENY); + } + + if (!context.terraSettings.features.vanillaWaterFeatures) { + // block lakes and springs if not enabled + modifiers.getPredicates().add(FeatureMatcher.of(Feature.LAKE), FeaturePredicate.DENY); + modifiers.getPredicates().add(FeatureMatcher.of(Feature.SPRING_FEATURE), FeaturePredicate.DENY); + } + + if (context.terraSettings.features.customBiomeFeatures) { + // remove default trees from river biomes since forests can go up to the edge of rivers + modifiers.getPredicates().add(BiomeMatcher.of(Biome.Category.RIVER), Matchers.tree(), FeaturePredicate.DENY); + } + + // block ugly features + modifiers.getPredicates().add(Matchers.sedimentDisks(), FeaturePredicate.DENY); + + // limit to deep oceans + modifiers.getPredicates().add(FeatureMatcher.of(Feature.SHIPWRECK), MinDepth.DEPTH55); + modifiers.getPredicates().add(FeatureMatcher.of(Feature.OCEAN_RUIN), DeepWater.INSTANCE); + modifiers.getPredicates().add(FeatureMatcher.of(Feature.OCEAN_MONUMENT), DeepWater.INSTANCE); + + // prevent mineshafts above ground + modifiers.getPredicates().add(FeatureMatcher.of(Feature.MINESHAFT), MinHeight.HEIGHT80); + + return FeatureManager.create(context.world, SetupHooks.setup(modifiers, context.copy())); + } + + public static SurfaceManager createSurfaceManager(TerraContext context) { + SurfaceManager manager = new SurfaceManager(); + manager.replace(Biomes.FROZEN_OCEAN.delegate.get(), new IcebergsSurface(context, 20, 15)); + manager.replace(Biomes.DEEP_FROZEN_OCEAN.delegate.get(), new IcebergsSurface(context, 30, 30)); + manager.replace(Biomes.SWAMP.delegate.get(), new SwampSurface()); + manager.replace(ModBiomes.MARSHLAND, new SwampSurface()); + manager.replace(ModBiomes.STEPPE, new SteppeSurface()); + return SetupHooks.setup(manager, context); + } + + public static GeoManager createGeologyManager(TerraContext context) { + return new GeoManager(context); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java b/src/main/java/com/terraforged/mod/command/TerraCommand.java similarity index 79% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java rename to src/main/java/com/terraforged/mod/command/TerraCommand.java index 00b8a27..c14f1b9 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java +++ b/src/main/java/com/terraforged/mod/command/TerraCommand.java @@ -27,13 +27,14 @@ package com.terraforged.mod.command; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.WorldGenerator; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.WorldGenerator; +import com.terraforged.world.terrain.Terrain; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.Log; import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.chunk.TerraChunkGenerator; @@ -48,6 +49,7 @@ import com.terraforged.mod.data.DataGen; import com.terraforged.mod.settings.SettingsHelper; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; +import net.minecraft.command.arguments.ArgumentSerializer; import net.minecraft.command.arguments.ArgumentTypes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; @@ -68,21 +70,18 @@ import net.minecraft.world.gen.ChunkGenerator; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; -import net.minecraftforge.server.permission.DefaultPermissionLevel; -import net.minecraftforge.server.permission.PermissionAPI; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.function.Predicate; import java.util.function.Supplier; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) public class TerraCommand { public static void init() { - ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new BiomeArgType.Serializer()); - ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new TerrainArgType.Serializer()); + ArgumentTypes.register("terraforged:biome", BiomeArgType.class, new ArgumentSerializer<>(BiomeArgType::new)); + ArgumentTypes.register("terraforged:terrain", TerrainArgType.class, new ArgumentSerializer<>(TerrainArgType::new)); } @SubscribeEvent @@ -92,59 +91,31 @@ public class TerraCommand { } public static void register(CommandDispatcher dispatcher) { - registerSimple(dispatcher); - registerLocate(dispatcher); - PermissionAPI.registerNode(Permissions.QUERY, DefaultPermissionLevel.OP, "Allows use of the query command"); - PermissionAPI.registerNode(Permissions.DATA, DefaultPermissionLevel.OP, "Allows use of the data command"); - PermissionAPI.registerNode(Permissions.DEFAULTS, DefaultPermissionLevel.OP, "Allows use of the defaults command"); - PermissionAPI.registerNode(Permissions.DEBUG, DefaultPermissionLevel.OP, "Allows use of the debug command"); - PermissionAPI.registerNode(Permissions.LOCATE, DefaultPermissionLevel.OP, "Allows use of the locate command"); + dispatcher.register(command()); } - private static void registerSimple(CommandDispatcher dispatcher) { - dispatcher.register(Commands.literal("terra") + private static LiteralArgumentBuilder command() { + return Commands.literal("terra") + .requires(source -> source.hasPermissionLevel(2)) .then(Commands.literal("query") - .requires(perm(Permissions.QUERY)) .executes(TerraCommand::query)) .then(Commands.literal("data") - .requires(perm(Permissions.DATA)) .then(Commands.literal("dump") .executes(TerraCommand::dump))) .then(Commands.literal("defaults") - .requires(perm(Permissions.DEFAULTS)) .then(Commands.literal("set") .executes(TerraCommand::setDefaults))) .then(Commands.literal("debug") - .requires(perm(Permissions.DEBUG)) - .executes(TerraCommand::debugBiome))); - } - - private static void registerLocate(CommandDispatcher dispatcher) { - dispatcher.register(Commands.literal("terra") + .executes(TerraCommand::debugBiome)) .then(Commands.literal("locate") - .requires(perm(Permissions.LOCATE)) - .then(Commands.argument("biome", BiomeArgType.biome()) - .executes(TerraCommand::findBiome)))); - - dispatcher.register(Commands.literal("terra") - .then(Commands.literal("locate") - .requires(perm(Permissions.LOCATE)) - .then(Commands.argument("terrain", TerrainArgType.terrain()) - .executes(TerraCommand::findTerrain)))); - - dispatcher.register(Commands.literal("terra") - .then(Commands.literal("locate") - .requires(perm(Permissions.LOCATE)) .then(Commands.argument("biome", BiomeArgType.biome()) + .executes(TerraCommand::findBiome) .then(Commands.argument("terrain", TerrainArgType.terrain()) - .executes(TerraCommand::findTerrainAndBiome))))); - - dispatcher.register(Commands.literal("terra") - .then(Commands.literal("locate") - .requires(perm(Permissions.LOCATE)) + .executes(TerraCommand::findTerrainAndBiome))) .then(Commands.argument("terrain", TerrainArgType.terrain()) + .executes(TerraCommand::findTerrain) .then(Commands.argument("biome", BiomeArgType.biome()) - .executes(TerraCommand::findTerrainAndBiome))))); + .executes(TerraCommand::findTerrainAndBiome)))); } private static int query(CommandContext context) throws CommandSyntaxException { @@ -155,10 +126,10 @@ public class TerraCommand { BlockPos pos = context.getSource().asPlayer().getPosition(); BiomeProvider biomeProvider = getBiomeProvider(context); - Cell cell = biomeProvider.lookupPos(pos.getX(), pos.getZ()); + Cell cell = biomeProvider.lookupPos(pos.getX(), pos.getZ()); Biome biome = biomeProvider.getBiome(cell, pos.getX(), pos.getZ()); context.getSource().sendFeedback( - new StringTextComponent("Terrain=" + cell.tag.getName() + ", Biome=" + biome.getRegistryName()), + new StringTextComponent("Terrain=" + cell.terrainType.getName() + ", Biome=" + biome.getRegistryName()), false ); @@ -223,7 +194,7 @@ public class TerraCommand { WorldGenerator worldGenerator = terraContext.factory.get(); Search search = new TerrainSearchTask(pos, worldGenerator, target); doSearch(server, playerID, search); - context.getSource().sendFeedback(new StringTextComponent("Locating terrain..."), false); + context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); return Command.SINGLE_SUCCESS; } @@ -242,7 +213,7 @@ public class TerraCommand { IWorldReader reader = context.getSource().asPlayer().getServerWorld(); Search search = new BiomeSearchTask(pos, reader, biome); doSearch(server, playerID, search); - context.getSource().sendFeedback(new StringTextComponent("Locating biome..."), false); + context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); return Command.SINGLE_SUCCESS; } @@ -266,7 +237,7 @@ public class TerraCommand { Search terrainSearch = new TerrainSearchTask(pos, worldGenerator, target); Search search = new BothSearchTask(pos, biomeSearch, terrainSearch); doSearch(server, playerID, search); - context.getSource().sendFeedback(new StringTextComponent("Locating biome & terrain..."), false); + context.getSource().sendFeedback(new StringTextComponent("Searching..."), false); return Command.SINGLE_SUCCESS; } @@ -283,8 +254,11 @@ public class TerraCommand { return; } + double distance = Math.sqrt(player.getPosition().distanceSq(pos)); + ITextComponent result = new StringTextComponent("Nearest match: ") - .appendSibling(createTeleportMessage(pos)); + .appendSibling(createTeleportMessage(pos)) + .appendSibling(new StringTextComponent(String.format(" Distance: %.2f", distance))); player.sendMessage(result); })); @@ -304,31 +278,14 @@ public class TerraCommand { // the terrain parsed from the command will not be the same instance as used in the // world generator, so find the matching instance by name private static Terrain getTerrainInstance(Terrain find, Terrains terrains) { - // search for exact match first for (Terrain t : terrains.index) { if (t.getName().equals(find.getName())) { return t; } } - // find a mixed terrain as a fallback - for (Terrain t : terrains.index) { - if (t.getName().contains("-") && t.getName().contains(find.getName())) { - return t; - } - } return find; } - private static Predicate perm(String node) { - return source -> { - try { - return PermissionAPI.hasPermission(source.asPlayer(), node); - } catch (Throwable t) { - return source.hasPermissionLevel(2); - } - }; - } - private static BiomeProvider getBiomeProvider(CommandContext context) { return (BiomeProvider) context.getSource().getWorld().getChunkProvider().getChunkGenerator().getBiomeProvider(); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java b/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java similarity index 66% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java rename to src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java index 0053536..0dfc4a5 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java +++ b/src/main/java/com/terraforged/mod/command/arg/BiomeArgType.java @@ -25,7 +25,6 @@ package com.terraforged.mod.command.arg; -import com.google.gson.JsonObject; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; @@ -34,9 +33,8 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.command.ISuggestionProvider; -import net.minecraft.command.arguments.IArgumentSerializer; -import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.Registry; import net.minecraft.util.text.StringTextComponent; import net.minecraft.world.biome.Biome; import net.minecraftforge.registries.ForgeRegistries; @@ -47,28 +45,9 @@ public class BiomeArgType implements ArgumentType { @Override public Biome parse(StringReader reader) throws CommandSyntaxException { - int cursor = reader.getCursor(); - String raw = reader.getString().substring(cursor); - - if (raw.indexOf(':') == -1) { - reader.setCursor(cursor); - throw createException("Invalid biome", "%s is not a valid biome", raw); - } - - ResourceLocation resourcelocation = ResourceLocation.tryCreate(raw); - if (resourcelocation == null) { - reader.setCursor(cursor); - throw createException("Invalid biome", "%s is not a valid biome", raw); - } - - if (!ForgeRegistries.BIOMES.containsKey(resourcelocation)) { - reader.setCursor(cursor); - throw createException("Invalid biome", "%s is not a valid biome", resourcelocation); - } - - reader.setCursor(reader.getString().length()); - - return ForgeRegistries.BIOMES.getValue(resourcelocation); + ResourceLocation resourcelocation = ResourceLocation.read(reader); + return Registry.BIOME.getValue(resourcelocation) + .orElseThrow(() -> createException("Invalid biome", "%s is not a valid biome", resourcelocation)); } @Override @@ -90,22 +69,4 @@ public class BiomeArgType implements ArgumentType { public static Biome getBiome(CommandContext context, String name) { return context.getArgument(name, Biome.class); } - - public static class Serializer implements IArgumentSerializer { - - @Override - public void write(BiomeArgType type, PacketBuffer buffer) { - - } - - @Override - public BiomeArgType read(PacketBuffer buffer) { - return new BiomeArgType(); - } - - @Override - public void write(BiomeArgType type, JsonObject json) { - - } - } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java b/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java similarity index 78% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java rename to src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java index dc843a0..9465da4 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java +++ b/src/main/java/com/terraforged/mod/command/arg/TerrainArgType.java @@ -25,7 +25,6 @@ package com.terraforged.mod.command.arg; -import com.google.gson.JsonObject; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; @@ -33,12 +32,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import com.terraforged.core.settings.Settings; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.terrain.Terrain; import net.minecraft.command.ISuggestionProvider; -import net.minecraft.command.arguments.IArgumentSerializer; -import net.minecraft.network.PacketBuffer; import net.minecraft.util.text.StringTextComponent; import java.util.List; @@ -47,7 +42,7 @@ import java.util.stream.Collectors; public class TerrainArgType implements ArgumentType { - private final List terrains = createTerrainList(); + private final List terrains = Terrain.getRegistered(); @Override public Terrain parse(StringReader reader) throws CommandSyntaxException { @@ -81,26 +76,4 @@ public class TerrainArgType implements ArgumentType { new StringTextComponent(String.format(message, args)) ); } - - private static List createTerrainList() { - return Terrains.create(new Settings()).index; - } - - public static class Serializer implements IArgumentSerializer { - - @Override - public void write(TerrainArgType type, PacketBuffer buffer) { - - } - - @Override - public TerrainArgType read(PacketBuffer buffer) { - return new TerrainArgType(); - } - - @Override - public void write(TerrainArgType type, JsonObject json) { - - } - } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/BiomeSearchTask.java b/src/main/java/com/terraforged/mod/command/search/BiomeSearchTask.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/search/BiomeSearchTask.java rename to src/main/java/com/terraforged/mod/command/search/BiomeSearchTask.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/BothSearchTask.java b/src/main/java/com/terraforged/mod/command/search/BothSearchTask.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/search/BothSearchTask.java rename to src/main/java/com/terraforged/mod/command/search/BothSearchTask.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/Search.java b/src/main/java/com/terraforged/mod/command/search/Search.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/search/Search.java rename to src/main/java/com/terraforged/mod/command/search/Search.java index 3bc5f1a..5a61899 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/Search.java +++ b/src/main/java/com/terraforged/mod/command/search/Search.java @@ -38,14 +38,6 @@ public abstract class Search implements Supplier { return 16; } - protected BlockPos success(BlockPos.Mutable pos) { - return pos.toImmutable(); - } - - protected BlockPos fail(BlockPos pos) { - return pos; - } - @Override public BlockPos get() { int radius = maxRadius; @@ -87,4 +79,12 @@ public abstract class Search implements Supplier { } public abstract boolean test(BlockPos pos); + + public BlockPos success(BlockPos.Mutable pos) { + return pos.toImmutable(); + } + + public BlockPos fail(BlockPos pos) { + return pos; + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java b/src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java similarity index 77% rename from TerraForgedMod/src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java rename to src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java index a48e45c..0adf8f8 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java +++ b/src/main/java/com/terraforged/mod/command/search/TerrainSearchTask.java @@ -1,15 +1,15 @@ package com.terraforged.mod.command.search; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.WorldGenerator; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.WorldGenerator; +import com.terraforged.world.terrain.Terrain; import net.minecraft.util.math.BlockPos; public class TerrainSearchTask extends Search { private final Terrain type; private final WorldGenerator generator; - private final Cell cell = new Cell<>(); + private final Cell cell = new Cell(); public TerrainSearchTask(BlockPos center, WorldGenerator generator, Terrain type) { super(center, 256); @@ -25,6 +25,6 @@ public class TerrainSearchTask extends Search { @Override public boolean test(BlockPos pos) { generator.getHeightmap().apply(cell, pos.getX(), pos.getZ()); - return cell.tag == type; + return cell.terrainType == type; } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/data/DataGen.java b/src/main/java/com/terraforged/mod/data/DataGen.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/data/DataGen.java rename to src/main/java/com/terraforged/mod/data/DataGen.java diff --git a/src/main/java/com/terraforged/mod/data/DataGenerator.java b/src/main/java/com/terraforged/mod/data/DataGenerator.java new file mode 100644 index 0000000..d34c1af --- /dev/null +++ b/src/main/java/com/terraforged/mod/data/DataGenerator.java @@ -0,0 +1,92 @@ +package com.terraforged.mod.data; + +import com.terraforged.core.util.NameUtil; +import com.terraforged.mod.gui.preview.PreviewSettings; +import com.terraforged.mod.settings.TerraSettings; +import com.terraforged.mod.util.nbt.NBTHelper; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.biome.Biome; +import net.minecraftforge.common.data.LanguageProvider; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; +import net.minecraftforge.registries.ForgeRegistries; + +import java.util.function.UnaryOperator; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class DataGenerator { + + @SubscribeEvent + public static void gather(GatherDataEvent event) { + LanguageProvider langProvider = new LanguageProvider(event.getGenerator(), "terraforged", "en_us") { + @Override + protected void addTranslations() { + worlds(this); + biomes(this); + settings(this); + } + }; + event.getGenerator().addProvider(langProvider); + } + + private static void worlds(LanguageProvider provider) { + provider.add("generator.terraforged", "TerraForged"); + provider.add("generator.terratest", "TerraTest"); + } + + private static void biomes(LanguageProvider provider) { + for (Biome biome : ForgeRegistries.BIOMES) { + ResourceLocation name = biome.getRegistryName(); + if (name != null && name.getNamespace().equals("terraforged")) { + provider.add(biome, NameUtil.toDisplayName(name.getPath())); + } + } + } + + private static void settings(LanguageProvider provider) { + visit(NBTHelper.serialize(new DataGenSettings()), provider); + } + + private static void visit(CompoundNBT tag, LanguageProvider lang) { + tag.keySet().forEach(name -> { + if (name.startsWith("#")) { + return; + } + + INBT value = tag.get(name); + if (value instanceof CompoundNBT) { + visit((CompoundNBT) value, lang); + } + + CompoundNBT meta = tag.getCompound("#" + name); + if (meta.isEmpty()) { + return; + } + + add(meta, "key", "display", NameUtil::toDisplayNameKey, lang); + add(meta, "key", "comment", NameUtil::toTooltipKey, lang); + }); + } + + private static void add(CompoundNBT tag, String keyName, String valName, UnaryOperator keyFunc, LanguageProvider lang) { + String key = keyFunc.apply(tag.getString(keyName)); + if (key.isEmpty()) { + return; + } + + String value = tag.getString(valName); + if (value.isEmpty()) { + return; + } + + lang.add(key, value); + } + + public static class DataGenSettings extends TerraSettings { + + public PreviewSettings preview = new PreviewSettings(); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenBiomes.java b/src/main/java/com/terraforged/mod/data/WorldGenBiomes.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenBiomes.java rename to src/main/java/com/terraforged/mod/data/WorldGenBiomes.java index 0f99d3a..eb92713 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenBiomes.java +++ b/src/main/java/com/terraforged/mod/data/WorldGenBiomes.java @@ -28,7 +28,7 @@ package com.terraforged.mod.data; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.terraforged.core.world.biome.BiomeType; +import com.terraforged.world.biome.BiomeType; import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.provider.BiomeHelper; import net.minecraft.util.ResourceLocation; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenBlocks.java b/src/main/java/com/terraforged/mod/data/WorldGenBlocks.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/data/WorldGenBlocks.java rename to src/main/java/com/terraforged/mod/data/WorldGenBlocks.java diff --git a/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java b/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java new file mode 100644 index 0000000..cbe327b --- /dev/null +++ b/src/main/java/com/terraforged/mod/data/WorldGenFeatures.java @@ -0,0 +1,68 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.data; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.JsonOps; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraftforge.registries.ForgeRegistries; + +import java.io.File; + +public class WorldGenFeatures extends DataGen { + + public static void genBiomeFeatures(File dataDir) { + if (dataDir.exists() || dataDir.mkdirs()) { + for (Biome biome : ForgeRegistries.BIOMES) { + genBiomeFeatures(dataDir, biome); + } + } + } + + private static void genBiomeFeatures(File dir, Biome biome) { + write(new File(dir, getJsonPath("features", biome.getRegistryName())), writer -> { + JsonObject root = new JsonObject(); + for (GenerationStage.Decoration type : GenerationStage.Decoration.values()) { + JsonArray features = new JsonArray(); + for (ConfiguredFeature feature : biome.getFeatures(type)) { + try { + Dynamic dynamic = feature.serialize(JsonOps.INSTANCE); + features.add(dynamic.getValue()); + } catch (NullPointerException e) { + new NullPointerException("Badly written feature: " + feature.feature.getRegistryName()).printStackTrace(); + } + } + root.add(type.getName(), features); + } + write(root, writer); + }); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java b/src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java rename to src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java index 87e826f..f9ca4c4 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java +++ b/src/main/java/com/terraforged/mod/decorator/ChunkPopulator.java @@ -36,7 +36,7 @@ public class ChunkPopulator implements ColumnDecorator { @Override public void decorate(IChunk chunk, DecoratorContext context, int x, int y, int z) { - if (context.cell.tag == context.terrains.volcanoPipe && context.cell.riverMask > 0.25F) { + if (context.cell.terrainType == context.terrains.volcanoPipe && context.cell.riverMask > 0.25F) { int lavaStart = Math.max(context.levels.waterY + 10, y - 30); int lavaEnd = Math.max(5, context.levels.waterY - 10); fillDown(context, chunk, x, z, lavaStart, lavaEnd, States.LAVA.get()); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java b/src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java rename to src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java index 5467be8..cb26630 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java +++ b/src/main/java/com/terraforged/mod/decorator/feature/LayerDecorator.java @@ -30,7 +30,7 @@ import com.terraforged.api.chunk.column.DecoratorContext; import com.terraforged.api.material.layer.LayerManager; import com.terraforged.api.material.layer.LayerMaterial; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; +import com.terraforged.world.heightmap.Levels; import com.terraforged.mod.material.MaterialHelper; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; @@ -72,7 +72,7 @@ public class LayerDecorator implements ColumnDecorator { } } - private void setLayer(IChunk chunk, BlockPos pos, LayerMaterial material, Cell cell, Levels levels, float min) { + private void setLayer(IChunk chunk, BlockPos pos, LayerMaterial material, Cell cell, Levels levels, float min) { float height = cell.value * levels.worldHeight; float depth = material.getDepth(height); if (depth > min) { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java b/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java rename to src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java index 829a6d9..465e7a1 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java +++ b/src/main/java/com/terraforged/mod/decorator/feature/SnowEroder.java @@ -28,7 +28,7 @@ package com.terraforged.mod.decorator.feature; import com.terraforged.api.chunk.column.ColumnDecorator; import com.terraforged.api.chunk.column.DecoratorContext; import com.terraforged.mod.chunk.TerraContext; -import com.terraforged.mod.decorator.base.ErosionDecorator; +import com.terraforged.mod.decorator.terrain.ErosionDecorator; import me.dags.noise.source.Rand; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -71,7 +71,7 @@ public class SnowEroder extends ErosionDecorator { float var = -ColumnDecorator.getNoise(x, z, seed1, 16, 0); float hNoise = rand.getValue(x, z, seed2) * HEIGHT_MODIFIER; float sNoise = rand.getValue(x, z, seed3) * SLOPE_MODIFIER; - float vModifier = context.cell.tag == context.terrains.volcano ? 0.15F : 0F; + float vModifier = context.cell.terrainType == context.terrains.volcano ? 0.15F : 0F; float height = context.cell.value + var + hNoise + vModifier; float steepness = context.cell.steepness + var + sNoise + vModifier; if (snowErosion(x, z, steepness, height)) { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/BedrockDecorator.java b/src/main/java/com/terraforged/mod/decorator/terrain/BedrockDecorator.java similarity index 90% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/BedrockDecorator.java rename to src/main/java/com/terraforged/mod/decorator/terrain/BedrockDecorator.java index 9e52080..297a2ad 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/BedrockDecorator.java +++ b/src/main/java/com/terraforged/mod/decorator/terrain/BedrockDecorator.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.base; +package com.terraforged.mod.decorator.terrain; import com.terraforged.api.chunk.column.ColumnDecorator; import com.terraforged.api.chunk.column.DecoratorContext; @@ -44,9 +44,9 @@ public class BedrockDecorator implements ColumnDecorator { private final BlockState material; public BedrockDecorator(TerraContext context) { - minDepth = context.terraSettings.dimensions.baseLayer.minDepth; - variance = context.terraSettings.dimensions.baseLayer.variance; - material = getState(context.terraSettings.dimensions.baseLayer.material); + minDepth = context.terraSettings.dimensions.bedrockLayer.minDepth; + variance = context.terraSettings.dimensions.bedrockLayer.variance; + material = getState(context.terraSettings.dimensions.bedrockLayer.material); } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/CoastDecorator.java b/src/main/java/com/terraforged/mod/decorator/terrain/CoastDecorator.java similarity index 94% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/CoastDecorator.java rename to src/main/java/com/terraforged/mod/decorator/terrain/CoastDecorator.java index 686d4b8..b98a9c2 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/CoastDecorator.java +++ b/src/main/java/com/terraforged/mod/decorator/terrain/CoastDecorator.java @@ -23,13 +23,13 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.base; +package com.terraforged.mod.decorator.terrain; import com.terraforged.api.chunk.column.ColumnDecorator; import com.terraforged.api.chunk.column.DecoratorContext; import com.terraforged.api.material.state.States; import com.terraforged.core.util.VariablePredicate; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.chunk.TerraContext; import net.minecraft.block.BlockState; import net.minecraft.world.chunk.IChunk; @@ -59,7 +59,7 @@ public class CoastDecorator implements ColumnDecorator { @Override public void decorate(IChunk chunk, DecoratorContext context, int x, int y, int z) { - if (context.cell.tag != terrains.beach) { + if (context.cell.terrainType != terrains.beach) { return; } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/ErosionDecorator.java b/src/main/java/com/terraforged/mod/decorator/terrain/ErosionDecorator.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/ErosionDecorator.java rename to src/main/java/com/terraforged/mod/decorator/terrain/ErosionDecorator.java index e72cd23..4b03d21 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/ErosionDecorator.java +++ b/src/main/java/com/terraforged/mod/decorator/terrain/ErosionDecorator.java @@ -23,12 +23,12 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.base; +package com.terraforged.mod.decorator.terrain; import com.terraforged.api.chunk.column.ColumnDecorator; import com.terraforged.api.chunk.column.DecoratorContext; import com.terraforged.api.material.state.States; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.chunk.TerraContext; import com.terraforged.mod.material.Materials; import net.minecraft.block.BlockState; @@ -69,17 +69,17 @@ public class ErosionDecorator implements ColumnDecorator { this.seed1 = context.seed.next(); this.seed2 = context.seed.next(); this.seed3 = context.seed.next(); - this.minY = context.levels.ground(4); + this.minY = context.levels.water; this.materials = context.materials; } @Override public void decorate(IChunk chunk, DecoratorContext context, int x, int y, int z) { - if (context.cell.value < minY || context.cell.tag == terrain.river || context.cell.tag == terrain.riverBanks) { + if (context.cell.value < minY || context.cell.terrainType == terrain.river || context.cell.terrainType == terrain.riverBanks) { return; } - if (context.cell.tag == terrain.volcanoPipe) { + if (context.cell.terrainType == terrain.volcanoPipe) { return; } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/GeologyDecorator.java b/src/main/java/com/terraforged/mod/decorator/terrain/GeologyDecorator.java similarity index 97% rename from TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/GeologyDecorator.java rename to src/main/java/com/terraforged/mod/decorator/terrain/GeologyDecorator.java index 2d5a2f1..80f381a 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/decorator/base/GeologyDecorator.java +++ b/src/main/java/com/terraforged/mod/decorator/terrain/GeologyDecorator.java @@ -23,7 +23,7 @@ * SOFTWARE. */ -package com.terraforged.mod.decorator.base; +package com.terraforged.mod.decorator.terrain; import com.terraforged.api.chunk.column.ColumnDecorator; import com.terraforged.api.chunk.column.DecoratorContext; diff --git a/src/main/java/com/terraforged/mod/feature/BlockDataConfig.java b/src/main/java/com/terraforged/mod/feature/BlockDataConfig.java new file mode 100644 index 0000000..fcf6f54 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/BlockDataConfig.java @@ -0,0 +1,16 @@ +package com.terraforged.mod.feature; + +import com.google.gson.JsonObject; +import net.minecraft.block.Block; + +import java.util.Optional; + +public interface BlockDataConfig { + + Block getTarget(); + + interface Parser { + + Optional parse(JsonObject data); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/BlockDataManager.java b/src/main/java/com/terraforged/mod/feature/BlockDataManager.java new file mode 100644 index 0000000..bb615b5 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/BlockDataManager.java @@ -0,0 +1,35 @@ +package com.terraforged.mod.feature; + +import com.google.common.collect.ImmutableMap; +import com.terraforged.mod.feature.manager.data.DataManager; +import com.terraforged.mod.feature.manager.util.Json; +import com.terraforged.mod.feature.sapling.SaplingConfig; +import net.minecraft.block.Block; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class BlockDataManager { + + private static final Map parsers = ImmutableMap.builder() + .put("terraforged:sapling", SaplingConfig::deserialize) + .build(); + + private final Map blockdata = new HashMap<>(); + + public BlockDataManager(DataManager dataManager) { + dataManager.forEachJson("blocks/saplings", (name, data) -> { + String type = Json.getString("type", data.getAsJsonObject(), ""); + BlockDataConfig.Parser parser = parsers.get(type); + if (parser == null) { + return; + } + parser.parse(data.getAsJsonObject()).ifPresent(config -> blockdata.put(config.getTarget(), config)); + }); + } + + public Optional getConfig(Block block, Class type) { + return Optional.ofNullable(blockdata.get(block)).filter(type::isInstance).map(type::cast); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/Matchers.java b/src/main/java/com/terraforged/mod/feature/Matchers.java similarity index 84% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/Matchers.java rename to src/main/java/com/terraforged/mod/feature/Matchers.java index 645e85f..253e793 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/Matchers.java +++ b/src/main/java/com/terraforged/mod/feature/Matchers.java @@ -25,10 +25,11 @@ package com.terraforged.mod.feature; -import com.terraforged.feature.matcher.BiomeFeatureMatcher; -import com.terraforged.feature.matcher.biome.BiomeMatcher; -import com.terraforged.feature.matcher.feature.FeatureMatcher; +import com.terraforged.mod.feature.manager.matcher.BiomeFeatureMatcher; +import com.terraforged.mod.feature.manager.matcher.biome.BiomeMatcher; +import com.terraforged.mod.feature.manager.matcher.feature.FeatureMatcher; import com.terraforged.mod.feature.feature.DiskFeature; +import net.minecraft.block.Blocks; import net.minecraft.world.biome.Biome; import net.minecraft.world.gen.feature.Feature; @@ -44,6 +45,12 @@ public class Matchers { .build(); } + public static FeatureMatcher tree() { + return FeatureMatcher.builder() + .or(Blocks.OAK_LOG).and(Blocks.OAK_LEAVES) + .build(); + } + public static BiomeFeatureMatcher sedimentDisks() { return new BiomeFeatureMatcher( BiomeMatcher.of(Biome.Category.RIVER, Biome.Category.SWAMP), diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/TerrainHelper.java b/src/main/java/com/terraforged/mod/feature/TerrainHelper.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/TerrainHelper.java rename to src/main/java/com/terraforged/mod/feature/TerrainHelper.java diff --git a/src/main/java/com/terraforged/mod/feature/context/ChanceContext.java b/src/main/java/com/terraforged/mod/feature/context/ChanceContext.java new file mode 100644 index 0000000..f0b7095 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/ChanceContext.java @@ -0,0 +1,83 @@ +package com.terraforged.mod.feature.context; + +import com.terraforged.core.cell.Cell; +import com.terraforged.core.region.chunk.ChunkReader; +import com.terraforged.core.concurrent.ObjectPool; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.mod.chunk.util.TerraContainer; +import com.terraforged.mod.chunk.fix.RegionDelegate; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.BiomeContainer; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.WorldGenRegion; + +import java.util.Random; + +public class ChanceContext { + + private static final ObjectPool pool = new ObjectPool<>(10, ChanceContext::new); + + public IChunk chunk; + public Levels levels; + public ChunkReader reader; + public Cell cell = Cell.empty(); + + private int length; + private float total = 0F; + private float[] buffer; + + void setPos(BlockPos pos) { + cell = reader.getCell(pos.getX(), pos.getZ()); + } + + void init(int size) { + total = 0F; + length = 0; + if (buffer == null || buffer.length < size) { + buffer = new float[size]; + } + } + + void record(int index, float chance) { + buffer[index] = chance; + total += chance; + length++; + } + + int nextIndex(Random random) { + float value = 0F; + float chance = random.nextFloat() * total; + for (int i = 0; i < length; i++) { + value += buffer[i]; + if (value >= chance) { + return i; + } + } + return -1; + } + + public static ObjectPool.Item pooled(IWorld world) { + if (world instanceof RegionDelegate) { + Levels levels = new Levels(world.getMaxHeight(), world.getSeaLevel()); + WorldGenRegion region = ((RegionDelegate) world).getRegion(); + IChunk chunk = region.getChunk(region.getMainChunkX(), region.getMainChunkZ()); + return pooled(chunk, levels); + } + return null; + } + + public static ObjectPool.Item pooled(IChunk chunk, Levels levels) { + BiomeContainer container = chunk.getBiomes(); + if (container instanceof TerraContainer) { + ChunkReader reader = ((TerraContainer) container).getChunkReader(); + ObjectPool.Item item = pool.get(); + ChanceContext context = item.getValue(); + context.chunk = chunk; + context.levels = levels; + context.reader = reader; + return item; + } + return null; + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/ContextSelectorConfig.java b/src/main/java/com/terraforged/mod/feature/context/ContextSelectorConfig.java new file mode 100644 index 0000000..17496a2 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/ContextSelectorConfig.java @@ -0,0 +1,28 @@ +package com.terraforged.mod.feature.context; + +import com.google.common.collect.ImmutableMap; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.DynamicOps; +import net.minecraft.world.gen.feature.IFeatureConfig; + +import java.util.List; + +public class ContextSelectorConfig implements IFeatureConfig { + + public final List features; + + public ContextSelectorConfig(List features) { + this.features = features; + } + + @Override + public Dynamic serialize(DynamicOps ops) { + return new Dynamic<>(ops, ops.createMap(ImmutableMap.of( + ops.createString("features"), ops.createList(features.stream().map(f -> f.serialize(ops).getValue()) + )))); + } + + public static ContextSelectorConfig deserialize(Dynamic dynamic) { + return new ContextSelectorConfig(dynamic.get("features").asList(ContextualFeature::deserialize)); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/ContextSelectorFeature.java b/src/main/java/com/terraforged/mod/feature/context/ContextSelectorFeature.java new file mode 100644 index 0000000..6be7ad8 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/ContextSelectorFeature.java @@ -0,0 +1,45 @@ +package com.terraforged.mod.feature.context; + +import com.terraforged.core.concurrent.ObjectPool; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.GenerationSettings; +import net.minecraft.world.gen.feature.Feature; + +import java.util.Random; + +public class ContextSelectorFeature extends Feature { + + public static final ContextSelectorFeature INSTANCE = new ContextSelectorFeature(); + + public ContextSelectorFeature() { + super(ContextSelectorConfig::deserialize); + setRegistryName("terraforged", "context_selector"); + } + + @Override + public boolean place(IWorld world, ChunkGenerator generator, Random random, BlockPos pos, ContextSelectorConfig config) { + try (ObjectPool.Item item = ChanceContext.pooled(world)) { + if (item == null) { + return false; + } + + ChanceContext context = item.getValue(); + context.setPos(pos); + context.init(config.features.size()); + for (int i = 0; i < config.features.size(); i++) { + ContextualFeature feature = config.features.get(i); + float chance = feature.getChance(pos, context); + context.record(i, chance); + } + + int index = context.nextIndex(random); + if (index > -1) { + return config.features.get(index).feature.place(world, generator, random, pos); + } + + return false; + } + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/ContextualFeature.java b/src/main/java/com/terraforged/mod/feature/context/ContextualFeature.java new file mode 100644 index 0000000..8d60b8c --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/ContextualFeature.java @@ -0,0 +1,81 @@ +package com.terraforged.mod.feature.context; + +import com.google.common.collect.ImmutableMap; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.OptionalDynamic; +import com.mojang.datafixers.types.DynamicOps; +import com.terraforged.mod.feature.context.modifier.ContextModifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ContextualFeature { + + public final float chance; + public final List contexts; + public final ConfiguredFeature feature; + + public ContextualFeature(ConfiguredFeature feature, float chance, List contexts) { + this.chance = chance; + this.feature = feature; + this.contexts = contexts; + } + + public String getName() { + return "chance"; + } + + public float getChance(BlockPos pos, ChanceContext context) { + float chance = this.chance; + for (ContextModifier modifier : contexts) { + chance *= modifier.getChance(pos, context); + } + return chance; + } + + public Dynamic serialize(DynamicOps ops) { + return new Dynamic<>(ops, ops.createMap(ImmutableMap.of( + ops.createString("feature"), feature.serialize(ops).getValue(), + ops.createString("context"), serializeContext(ops).getValue() + ))); + } + + private Dynamic serializeContext(DynamicOps ops) { + Map map = new LinkedHashMap<>(); + map.put(ops.createString("chance"), ops.createFloat(chance)); + for (ContextModifier context : contexts) { + map.put(ops.createString(context.getName()), context.serialize(ops).getValue()); + } + return new Dynamic<>(ops, ops.createMap(map)); + } + + public static ContextualFeature deserialize(Dynamic dynamic) { + ConfiguredFeature feature = deserializeFeature(dynamic.get("feature")); + OptionalDynamic context = dynamic.get("context"); + float chance = context.get("chance").asFloat(0); + List contexts = deserializeContexts(context); + return new ContextualFeature(feature, chance, contexts); + } + + private static ConfiguredFeature deserializeFeature(OptionalDynamic dynamic) { + return dynamic.map(ConfiguredFeature::deserialize).orElseThrow(NullPointerException::new); + } + + private static List deserializeContexts(OptionalDynamic dynamic) { + return dynamic.map(d -> d.getMapValues().map(map -> { + List contexts = new ArrayList<>(map.size()); + map.forEach((key, value) -> { + String name = key.asString(""); + if (!name.equals("chance")) { + contexts.add(ContextModifier.parse(name, value)); + } + }); + return contexts; + }).orElse(Collections.emptyList())).orElseThrow(NullPointerException::new); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/modifier/Biome.java b/src/main/java/com/terraforged/mod/feature/context/modifier/Biome.java new file mode 100644 index 0000000..d123c3f --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/modifier/Biome.java @@ -0,0 +1,29 @@ +package com.terraforged.mod.feature.context.modifier; + +import com.mojang.datafixers.Dynamic; +import com.terraforged.mod.feature.context.ChanceContext; +import net.minecraft.util.math.BlockPos; + +public class Biome extends RangeContextModifier { + + public Biome(float chance, float min, float max) { + super(min, max); + } + + @Override + public String getName() { + return "biome"; + } + + @Override + protected float getValue(BlockPos pos, ChanceContext context) { + return context.cell.biomeEdge; + } + + public static ContextModifier deserialize(Dynamic dynamic) { + float chance = dynamic.get("chance").asFloat(0F); + float min = dynamic.get("min").asFloat(0F); + float max = dynamic.get("max").asFloat(1F); + return new Biome(chance, min, max); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/modifier/ContextModifier.java b/src/main/java/com/terraforged/mod/feature/context/modifier/ContextModifier.java new file mode 100644 index 0000000..f540823 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/modifier/ContextModifier.java @@ -0,0 +1,34 @@ +package com.terraforged.mod.feature.context.modifier; + +import com.google.common.collect.ImmutableMap; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.DynamicOps; +import com.terraforged.mod.feature.context.ChanceContext; +import net.minecraft.util.math.BlockPos; + +import java.util.Map; +import java.util.function.Function; + +public interface ContextModifier { + + Map, ContextModifier>> REGISTRY = ImmutableMap.of( + "elevation", Elevation::deserialize, + "biome", Biome::deserialize + ); + + ContextModifier NONE = new None(); + + String getName(); + + float getChance(BlockPos pos, ChanceContext context); + + Dynamic serialize(DynamicOps ops); + + static ContextModifier parse(String type, Dynamic dynamic) { + Function, ContextModifier> func = REGISTRY.get(type); + if (func == null) { + return NONE; + } + return func.apply(dynamic); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/modifier/Elevation.java b/src/main/java/com/terraforged/mod/feature/context/modifier/Elevation.java new file mode 100644 index 0000000..44119d4 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/modifier/Elevation.java @@ -0,0 +1,28 @@ +package com.terraforged.mod.feature.context.modifier; + +import com.mojang.datafixers.Dynamic; +import com.terraforged.mod.feature.context.ChanceContext; +import net.minecraft.util.math.BlockPos; + +public class Elevation extends RangeContextModifier { + + public Elevation(float min, float max) { + super(min, max); + } + + @Override + public String getName() { + return "elevation"; + } + + @Override + protected float getValue(BlockPos pos, ChanceContext context) { + return context.levels.elevation(context.cell.value); + } + + public static ContextModifier deserialize(Dynamic dynamic) { + float min = dynamic.get("min").asFloat(0F); + float max = dynamic.get("max").asFloat(1F); + return new Elevation(min, max); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/modifier/None.java b/src/main/java/com/terraforged/mod/feature/context/modifier/None.java new file mode 100644 index 0000000..6a4d572 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/modifier/None.java @@ -0,0 +1,24 @@ +package com.terraforged.mod.feature.context.modifier; + +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.DynamicOps; +import com.terraforged.mod.feature.context.ChanceContext; +import net.minecraft.util.math.BlockPos; + +public class None implements ContextModifier { + + @Override + public String getName() { + return "none"; + } + + @Override + public float getChance(BlockPos pos, ChanceContext context) { + return 0; + } + + @Override + public Dynamic serialize(DynamicOps ops) { + return new Dynamic<>(ops); + } +} diff --git a/src/main/java/com/terraforged/mod/feature/context/modifier/RangeContextModifier.java b/src/main/java/com/terraforged/mod/feature/context/modifier/RangeContextModifier.java new file mode 100644 index 0000000..9d9e6cb --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/context/modifier/RangeContextModifier.java @@ -0,0 +1,30 @@ +package com.terraforged.mod.feature.context.modifier; + +import com.google.common.collect.ImmutableMap; +import com.mojang.datafixers.Dynamic; +import com.mojang.datafixers.types.DynamicOps; +import com.terraforged.mod.feature.context.ChanceContext; +import com.terraforged.mod.util.RangeModifier; +import net.minecraft.util.math.BlockPos; + +public abstract class RangeContextModifier extends RangeModifier implements ContextModifier { + + public RangeContextModifier(float min, float max) { + super(min, max); + } + + @Override + public float getChance(BlockPos pos, ChanceContext context) { + return apply(getValue(pos, context)); + } + + @Override + public Dynamic serialize(DynamicOps ops) { + return new Dynamic<>(ops, ops.createMap(ImmutableMap.of( + ops.createString("min"), ops.createFloat(min), + ops.createString("max"), ops.createFloat(max) + ))); + } + + protected abstract float getValue(BlockPos pos, ChanceContext context); +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java b/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java similarity index 93% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java rename to src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java index a54c154..85a8d14 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java +++ b/src/main/java/com/terraforged/mod/feature/decorator/poisson/BiomeVariance.java @@ -2,7 +2,7 @@ package com.terraforged.mod.feature.decorator.poisson; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; -import com.terraforged.mod.chunk.TerraContainer; +import com.terraforged.mod.chunk.util.TerraContainer; import com.terraforged.mod.chunk.fix.RegionDelegate; import me.dags.noise.Module; import me.dags.noise.Source; @@ -28,7 +28,7 @@ public class BiomeVariance implements Module { @Override public float getValue(float x, float y) { - Cell cell = chunk.getCell((int) x, (int) y); + Cell cell = chunk.getCell((int) x, (int) y); return NoiseUtil.map(1 - cell.biomeEdge, MIN_FADE, fade, range); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonAtSurface.java b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonAtSurface.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonAtSurface.java rename to src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonAtSurface.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java rename to src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonConfig.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java rename to src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java index 7a480e0..f8a34e4 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java +++ b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonDecorator.java @@ -1,5 +1,7 @@ package com.terraforged.mod.feature.decorator.poisson; +import com.terraforged.core.util.poisson.Poisson; +import com.terraforged.core.util.poisson.PoissonContext; import me.dags.noise.Module; import me.dags.noise.Source; import net.minecraft.util.math.BlockPos; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java similarity index 84% rename from TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java rename to src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java index b39b6ad..998ff1c 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java +++ b/src/main/java/com/terraforged/mod/feature/decorator/poisson/PoissonVisitor.java @@ -1,14 +1,15 @@ package com.terraforged.mod.feature.decorator.poisson; +import com.terraforged.core.util.poisson.Poisson; +import com.terraforged.core.util.poisson.PoissonContext; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.feature.ConfiguredFeature; import java.util.Random; -import java.util.function.BiConsumer; -public class PoissonVisitor extends PoissonContext implements BiConsumer { +public class PoissonVisitor extends PoissonContext implements Poisson.Visitor { private final BlockPos pos; private final IWorld world; @@ -33,7 +34,7 @@ public class PoissonVisitor extends PoissonContext implements BiConsumer normal; + private final List giant; + + private SaplingConfig(Block block, List normal, List giant) { + this.block = block; + this.normal = normal; + this.giant = giant; + } + + @Override + public Block getTarget() { + return block; + } + + public boolean hasNormal() { + return !normal.isEmpty(); + } + + public boolean hasGiant() { + return !giant.isEmpty(); + } + + public TemplateFeatureConfig next(Random random, boolean giant) { + if (giant) { + TemplateFeatureConfig config = nextGiant(random); + if (config != null) { + return config; + } + } + return nextNormal(random); + } + + public TemplateFeatureConfig nextNormal(Random random) { + if (normal.isEmpty()) { + return null; + } + return normal.get(random.nextInt(normal.size())); + } + + public TemplateFeatureConfig nextGiant(Random random) { + if (giant.isEmpty()) { + return null; + } + return giant.get(random.nextInt(giant.size())); + } + + public static Optional deserialize(JsonObject data) { + String sapling = Json.getString("sapling", data, ""); + Block block = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(sapling)); + if (block == Blocks.AIR) { + return Optional.empty(); + } + List normal = deserializeList(data.getAsJsonObject("normal")); + List giant = deserializeList(data.getAsJsonObject("giant")); + if (normal.isEmpty() && giant.isEmpty()) { + return Optional.empty(); + } + return Optional.of(new SaplingConfig(block, normal, giant)); + } + + private static List deserializeList(JsonObject object) { + List list = Collections.emptyList(); + if (object != null) { + for (Map.Entry e : object.entrySet()) { + ResourceLocation name = new ResourceLocation(e.getKey()); + TemplateFeatureConfig template = TemplateManager.getInstance().getTemplateConfig(name); + if (template != TemplateFeatureConfig.NONE) { + int weight = Json.getInt("weight", e.getValue().getAsJsonObject(), 1); + for (int i = 0; i < weight; i++) { + if (list.isEmpty()) { + list = new ArrayList<>(); + } + list.add(template); + } + } + } + } + return list; + } +} diff --git a/src/main/java/com/terraforged/mod/feature/sapling/SaplingListener.java b/src/main/java/com/terraforged/mod/feature/sapling/SaplingListener.java new file mode 100644 index 0000000..6369126 --- /dev/null +++ b/src/main/java/com/terraforged/mod/feature/sapling/SaplingListener.java @@ -0,0 +1,208 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.feature.sapling; + +import com.terraforged.mod.feature.manager.template.Template; +import com.terraforged.mod.feature.manager.template.feature.TemplateFeature; +import com.terraforged.mod.feature.manager.template.feature.TemplateFeatureConfig; +import com.terraforged.mod.TerraWorld; +import com.terraforged.mod.chunk.TerraChunkGenerator; +import com.terraforged.mod.chunk.TerraContext; +import com.terraforged.mod.feature.BlockDataManager; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.Mirror; +import net.minecraft.util.Rotation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.IWorld; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.event.world.SaplingGrowTreeEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.util.Optional; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE) +public class SaplingListener { + + private static final BlockPos[] CENTER = {BlockPos.ZERO}; + + private static final Vec3i[][] DIRECTIONS = { + {new Vec3i(0, 0, 1), new Vec3i(1, 0, 1), new Vec3i(1, 0, 0)}, + {new Vec3i(1, 0, 0), new Vec3i(1, 0, -1), new Vec3i(0, 0, -1)}, + {new Vec3i(0, 0, -1), new Vec3i(-1, 0, -1), new Vec3i(-1, 0, 0)}, + {new Vec3i(-1, 0, 0), new Vec3i(-1, 0, 1), new Vec3i(0, 0, 1)}, + }; + + @SubscribeEvent + public static void onTreeGrow(SaplingGrowTreeEvent event) { + Optional dataManager = getDataManger(event); + if (!dataManager.isPresent()) { + return; + } + + IWorld world = event.getWorld(); + Block block = world.getBlockState(event.getPos()).getBlock(); + Optional saplingConfig = dataManager.get().getConfig(block, SaplingConfig.class); + if (!saplingConfig.isPresent()) { + return; + } + + Mirror mirror = TemplateFeature.nextMirror(event.getRand()); + Rotation rotation = TemplateFeature.nextRotation(event.getRand()); + + // if part of a 2x2 grid get the min corner of it + BlockPos pos = getMinPos(world, block, event.getPos(), saplingConfig.get().hasGiant()); + Vec3i[] directions = getNeighbours(world, block, pos, saplingConfig.get().hasGiant()); + TemplateFeatureConfig feature = saplingConfig.get().next(event.getRand(), directions.length == 3); + if (feature == null) { + return; + } + + // translate the pos so that the mirrored/rotated 2x2 grid aligns correctly + BlockPos origin = pos.subtract(getTranslation(directions, mirror, rotation)); + + // require that directly above the sapling(s) is open air + if (!isClearOverhead(world, origin, directions)) { + event.setResult(Event.Result.DENY); + return; + } + + // attempt to paste the tree & then clear up any remaining saplings + if (TemplateFeature.pasteChecked(world, event.getRand(), origin, mirror, rotation, feature, feature.decorator)) { + event.setResult(Event.Result.DENY); + for (Vec3i dir : directions) { + BlockPos neighbour = origin.add(dir); + BlockState state = world.getBlockState(neighbour); + if (state.getBlock() == block) { + world.destroyBlock(neighbour, false); + } + } + } + } + + private static Optional getDataManger(SaplingGrowTreeEvent event) { + // ignore if client + if (event.getWorld().isRemote()) { + return Optional.empty(); + } + + // ignore other world types + if (!TerraWorld.isTerraWorld(event.getWorld())) { + return Optional.empty(); + } + + // get the data manager from the world's chunk generator + if (event.getWorld() instanceof ServerWorld) { + ServerWorld serverWorld = (ServerWorld) event.getWorld(); + ChunkGenerator generator = serverWorld.getChunkProvider().generator; + if (generator instanceof TerraChunkGenerator) { + TerraContext context = ((TerraChunkGenerator) generator).getContext(); + if (context.terraSettings.features.customBiomeFeatures) { + return Optional.of(((TerraChunkGenerator) generator).getBlockDataManager()); + } + } + } + return Optional.empty(); + } + + private static boolean isClearOverhead(IWorld world, BlockPos pos, Vec3i[] directions) { + for (Vec3i dir : directions) { + int x = pos.getX() + dir.getX(); + int z = pos.getZ() + dir.getZ(); + int y = world.getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); + if (y > pos.getY()) { + return false; + } + } + return true; + } + + private static BlockPos getMinPos(IWorld world, Block block, BlockPos pos, boolean checkNeighbours) { + if (checkNeighbours) { + for (Vec3i[] dirs : DIRECTIONS) { + boolean match = true; + for (Vec3i dir : dirs) { + BlockState state = world.getBlockState(pos.add(dir)); + if (state.getBlock() != block) { + match = false; + break; + } + } + if (match) { + return pos.add(getMin(dirs, Mirror.NONE, Rotation.NONE)); + } + } + } + return pos; + } + + private static Vec3i getTranslation(Vec3i[] directions, Mirror mirror, Rotation rotation) { + if (directions.length == 1 || mirror == Mirror.NONE && rotation == Rotation.NONE) { + return Vec3i.NULL_VECTOR; + } + return getMin(directions, mirror, rotation); + } + + private static Vec3i getMin(Vec3i[] directions, Mirror mirror, Rotation rotation) { + Vec3i min = Vec3i.NULL_VECTOR; + BlockPos.Mutable pos = new BlockPos.Mutable(); + for (Vec3i vec : directions) { + BlockPos dir = Template.transform(pos.setPos(vec), mirror, rotation); + if (dir.getX() < min.getX() && dir.getZ() <= min.getZ()) { + min = dir; + continue; + } + if (dir.getZ() < min.getZ() && dir.getX() <= min.getX()) { + min = dir; + } + } + return min; + } + + private static Vec3i[] getNeighbours(IWorld world, Block block, BlockPos pos, boolean checkNeighbours) { + if (checkNeighbours) { + for (Vec3i[] dirs : DIRECTIONS) { + boolean match = true; + for (Vec3i dir : dirs) { + BlockState state = world.getBlockState(pos.add(dir)); + if (state.getBlock() != block) { + match = false; + break; + } + } + if (match) { + return dirs; + } + } + } + return CENTER; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/OverlayRenderer.java b/src/main/java/com/terraforged/mod/gui/OverlayRenderer.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/OverlayRenderer.java rename to src/main/java/com/terraforged/mod/gui/OverlayRenderer.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/OverlayScreen.java b/src/main/java/com/terraforged/mod/gui/OverlayScreen.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/OverlayScreen.java rename to src/main/java/com/terraforged/mod/gui/OverlayScreen.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/ScrollPane.java b/src/main/java/com/terraforged/mod/gui/ScrollPane.java similarity index 94% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/ScrollPane.java rename to src/main/java/com/terraforged/mod/gui/ScrollPane.java index dbbc9d3..2a58688 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/ScrollPane.java +++ b/src/main/java/com/terraforged/mod/gui/ScrollPane.java @@ -105,16 +105,6 @@ public class ScrollPane extends AbstractOptionList implements return option.mouseReleased(x, y, button); } - @Override - public boolean keyPressed(int i, int j, int k) { - return option.keyPressed(i, j, k); - } - - @Override - public boolean charTyped(char c, int code) { - return option.charTyped(c, code); - } - @Override public void render(int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean wut, float partialTicks) { int optionWidth = Math.min(396, width); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/SettingsScreen.java b/src/main/java/com/terraforged/mod/gui/SettingsScreen.java similarity index 80% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/SettingsScreen.java rename to src/main/java/com/terraforged/mod/gui/SettingsScreen.java index cae2e4b..9a5aad0 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/SettingsScreen.java +++ b/src/main/java/com/terraforged/mod/gui/SettingsScreen.java @@ -25,17 +25,15 @@ package com.terraforged.mod.gui; -import com.terraforged.mod.gui.element.TerraButton; import com.terraforged.mod.gui.element.TerraLabel; import com.terraforged.mod.gui.page.ClimatePage; -import com.terraforged.mod.gui.page.DimensionsPage; -import com.terraforged.mod.gui.page.FeaturePage; -import com.terraforged.mod.gui.page.FilterPage; -import com.terraforged.mod.gui.page.GeneratorPage; +import com.terraforged.mod.gui.page.MiscPage; import com.terraforged.mod.gui.page.Page; +import com.terraforged.mod.gui.page.PresetsPage; import com.terraforged.mod.gui.page.RiverPage; import com.terraforged.mod.gui.page.StructurePage; import com.terraforged.mod.gui.page.TerrainPage; +import com.terraforged.mod.gui.page.WorldPage; import com.terraforged.mod.gui.preview.PreviewPage; import com.terraforged.mod.settings.SettingsHelper; import com.terraforged.mod.settings.TerraSettings; @@ -58,21 +56,19 @@ public class SettingsScreen extends OverlayScreen { private final TerraSettings settings = new TerraSettings(); private int pageIndex = 0; - private boolean hasChanged = false; public SettingsScreen(CreateWorldScreen parent) { SettingsHelper.applyDefaults(parent.chunkProviderSettingsJson, settings); this.parent = parent; this.preview = new PreviewPage(settings, getSeed(parent)); this.pages = new Page[]{ - new GeneratorPage(settings, preview), + new PresetsPage(), + new WorldPage(settings, preview), new ClimatePage(settings, preview), new TerrainPage(settings, preview), new RiverPage(settings, preview), - new FilterPage(settings, preview), - new FeaturePage(settings), new StructurePage(settings), - new DimensionsPage(settings), + new MiscPage(settings) }; } @@ -89,7 +85,6 @@ public class SettingsScreen extends OverlayScreen { if (pageIndex < pages.length) { Page page = pages[pageIndex]; - page.callback(() -> this.hasChanged = true); TerraLabel title = new TerraLabel(page.getTitle()); title.visible = true; title.x = 16; @@ -155,44 +150,6 @@ public class SettingsScreen extends OverlayScreen { } }); - addButton(new TerraButton("Set Defaults", "Use the current settings as the defaults", "CTRL + click to clear them") { - - private boolean ctrl = false; - - @Override - public void render(int mouseX, int mouseY, float partialTicks) { - if (Screen.hasControlDown()) { - if (!ctrl) { - ctrl = true; - setMessage("Clear Defaults"); - } - super.active = true; - } else { - if (ctrl) { - ctrl = false; - setMessage("Set Defaults"); - } - super.active = hasChanged; - } - super.render(mouseX, mouseY, partialTicks); - } - - @Override - public void onClick(double mouseX, double mouseY) { - super.onClick(mouseX, mouseY); - if (Screen.hasControlDown()) { - SettingsHelper.clearDefaults(); - hasChanged = true; - } else { - for (Page page : pages) { - page.save(); - } - hasChanged = false; - SettingsHelper.exportDefaults(settings); - } - } - }.init(width - buttonWidth - 55, buttonsRow, 90, buttonHeight)); - super.init(); } @@ -251,13 +208,6 @@ public class SettingsScreen extends OverlayScreen { return a || b || c; } - @Override - public boolean charTyped(char c, int code) { - boolean a = pages[pageIndex].action(pane -> pane.charTyped(c, code)); - boolean b = preview.action(pane -> pane.charTyped(c, code)); - return a || b || super.charTyped(c, code); - } - @Override public void onClose() { for (Page page : pages) { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/CheckBox.java b/src/main/java/com/terraforged/mod/gui/element/CheckBox.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/CheckBox.java rename to src/main/java/com/terraforged/mod/gui/element/CheckBox.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/Element.java b/src/main/java/com/terraforged/mod/gui/element/Element.java similarity index 68% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/Element.java rename to src/main/java/com/terraforged/mod/gui/element/Element.java index 2596595..f3dc045 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/Element.java +++ b/src/main/java/com/terraforged/mod/gui/element/Element.java @@ -25,15 +25,12 @@ package com.terraforged.mod.gui.element; +import net.minecraft.client.resources.I18n; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.INBT; -import net.minecraft.nbt.ListNBT; -import net.minecraftforge.common.util.Constants; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; public interface Element { @@ -47,13 +44,23 @@ public interface Element { return ID_COUNTER.getAndAdd(1); } - static List readTooltip(CompoundNBT value) { - if (value.contains("#comment")) { - ListNBT comment = value.getList("#comment", Constants.NBT.TAG_STRING); - return comment.stream() - .map(INBT::getString) - .collect(Collectors.toList()); - } - return Collections.emptyList(); + static String getDisplayName(String name, CompoundNBT value) { + return I18n.format(getDisplayKey(name, value)); + } + + static List getToolTip(String name, CompoundNBT value) { + return Collections.singletonList(I18n.format(getCommentKey(name, value))); + } + + static String getDisplayKey(String name, CompoundNBT value) { + return "display.terraforged." + getKey(name, value); + } + + static String getCommentKey(String name, CompoundNBT value) { + return "tooltip.terraforged." + getKey(name, value); + } + + static String getKey(String name, CompoundNBT value) { + return value.getCompound("#" + name).getString("key"); } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraButton.java b/src/main/java/com/terraforged/mod/gui/element/TerraButton.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraButton.java rename to src/main/java/com/terraforged/mod/gui/element/TerraButton.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraLabel.java b/src/main/java/com/terraforged/mod/gui/element/TerraLabel.java similarity index 87% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraLabel.java rename to src/main/java/com/terraforged/mod/gui/element/TerraLabel.java index 8acddf5..0877937 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraLabel.java +++ b/src/main/java/com/terraforged/mod/gui/element/TerraLabel.java @@ -30,17 +30,9 @@ import net.minecraft.client.gui.FontRenderer; public class TerraLabel extends TerraButton { -// private final GuiLabel label; - public TerraLabel(String text) { super(text); visible = true; -// label = new GuiLabel( -// Collections.singletonList(text), -// 0xFFFFFF, -// Minecraft.getInstance().fontRenderer -// ); -// label.visible = true; } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraSlider.java b/src/main/java/com/terraforged/mod/gui/element/TerraSlider.java similarity index 72% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraSlider.java rename to src/main/java/com/terraforged/mod/gui/element/TerraSlider.java index d0f3707..145a1ee 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraSlider.java +++ b/src/main/java/com/terraforged/mod/gui/element/TerraSlider.java @@ -32,16 +32,18 @@ import java.util.List; public abstract class TerraSlider extends Slider implements Slider.ISlider, Element { + protected final String name; private final CompoundNBT value; private final List tooltip; private Runnable callback = () -> {}; - public TerraSlider(String prefix, CompoundNBT value, boolean decimal) { - super(0, 0, 100, 20, prefix, "", value.getFloat("#min"), value.getFloat("#max"), 0F, decimal, true, b -> {}); + public TerraSlider(String name, CompoundNBT value, boolean decimal) { + super(0, 0, 100, 20, Element.getDisplayName(name, value) + ": ", "", min(name, value), max(name, value), 0F, decimal, true, b -> {}); + this.name = name; this.value = value; this.parent = this; - this.tooltip = Element.readTooltip(value); + this.tooltip = Element.getToolTip(name, value); } public TerraSlider callback(Runnable callback) { @@ -71,24 +73,24 @@ public abstract class TerraSlider extends Slider implements Slider.ISlider, Elem public static class Int extends TerraSlider { - public Int(String prefix, CompoundNBT value) { - super(prefix, value, false); - setValue(value.getInt("value")); + public Int(String name, CompoundNBT value) { + super(name, value, false); + setValue(value.getInt(name)); updateSlider(); } @Override protected void onChange(Slider slider, CompoundNBT value) { - value.putInt("value", slider.getValueInt()); + value.putInt(name, slider.getValueInt()); } } public static class Float extends TerraSlider { - public Float(String prefix, CompoundNBT value) { - super(prefix, value, true); + public Float(String name, CompoundNBT value) { + super(name, value, true); precision = 3; - setValue(value.getFloat("value")); + setValue(value.getFloat(name)); updateSlider(); } @@ -96,7 +98,17 @@ public abstract class TerraSlider extends Slider implements Slider.ISlider, Elem protected void onChange(Slider slider, CompoundNBT value) { int i = (int) (slider.getValue() * 1000); float f = i / 1000F; - value.putFloat("value", f); + value.putFloat(name, f); } } + + private static float min(String name, CompoundNBT value) { + CompoundNBT meta = value.getCompound("#" + name); + return meta.getFloat("min"); + } + + private static float max(String name, CompoundNBT value) { + CompoundNBT meta = value.getCompound("#" + name); + return meta.getFloat("max"); + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java b/src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java similarity index 85% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java rename to src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java index 42c5d3e..81415f8 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java +++ b/src/main/java/com/terraforged/mod/gui/element/TerraTextInput.java @@ -11,16 +11,18 @@ import java.util.function.Predicate; public class TerraTextInput extends TextFieldWidget implements Element, Consumer { + private final String name; private final CompoundNBT value; private final List tooltip; private Predicate validator = s -> true; private Consumer callback = t -> {}; public TerraTextInput(String name, CompoundNBT value) { - super(Minecraft.getInstance().fontRenderer, 0, 0, 100, 20, name); + super(Minecraft.getInstance().fontRenderer, 0, 0, 100, 20, Element.getDisplayName(name, value) + ": "); + this.name = name; this.value = value; - this.tooltip = Element.readTooltip(value); - setText(value.getString("value")); + this.tooltip = Element.getToolTip(name, value); + setText(value.getString(name)); setResponder(this); } @@ -45,7 +47,7 @@ public class TerraTextInput extends TextFieldWidget implements Element, Consumer @Override public void accept(String text) { - value.put("value", StringNBT.valueOf(text)); + value.put(name, StringNBT.valueOf(text)); callback.accept(this); if (validator.test(text)) { setTextColor(14737632); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraToggle.java b/src/main/java/com/terraforged/mod/gui/element/TerraToggle.java similarity index 83% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraToggle.java rename to src/main/java/com/terraforged/mod/gui/element/TerraToggle.java index 27946e9..7a3e2b7 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/element/TerraToggle.java +++ b/src/main/java/com/terraforged/mod/gui/element/TerraToggle.java @@ -35,6 +35,7 @@ import java.util.List; public class TerraToggle extends TerraButton { private final String prefix; + private final String name; private final CompoundNBT value; private final ListNBT options; private final List tooltip; @@ -42,20 +43,22 @@ public class TerraToggle extends TerraButton { private int index; private Runnable callback = () -> {}; - public TerraToggle(String prefix, CompoundNBT value) { - super(value.getString("value")); + public TerraToggle(String name, CompoundNBT value) { + super(value.getString(name)); + this.name = name; this.value = value; - this.prefix = prefix; - this.tooltip = Element.readTooltip(value); - this.options = value.getList("#options", Constants.NBT.TAG_STRING); + this.prefix = Element.getDisplayName(name, value) + ": "; + this.tooltip = Element.getToolTip(name, value); + CompoundNBT meta = value.getCompound("#" + name); + this.options = meta.getList("options", Constants.NBT.TAG_STRING); for (int i = 0; i < options.size(); i++) { String s = options.getString(i); - if (s.equals(value.getString("value"))) { + if (s.equals(value.getString(name))) { index = i; break; } } - setMessage(prefix + value.getString("value")); + setMessage(prefix + value.getString(name)); } public TerraToggle callback(Runnable runnable) { @@ -88,7 +91,7 @@ public class TerraToggle extends TerraButton { index = options.size() - 1; } String option = options.getString(index); - value.putString("value", option); + value.putString(name, option); setMessage(prefix + option); callback.run(); } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/BasePage.java b/src/main/java/com/terraforged/mod/gui/page/BasePage.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/BasePage.java rename to src/main/java/com/terraforged/mod/gui/page/BasePage.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/ClimatePage.java b/src/main/java/com/terraforged/mod/gui/page/ClimatePage.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/ClimatePage.java rename to src/main/java/com/terraforged/mod/gui/page/ClimatePage.java index 940c15e..b23869e 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/ClimatePage.java +++ b/src/main/java/com/terraforged/mod/gui/page/ClimatePage.java @@ -40,7 +40,7 @@ public class ClimatePage extends BasePage { public ClimatePage(Settings settings, PreviewPage preview) { this.settings = settings; this.preview = preview; - this.climateSettings = NBTHelper.serialize(settings.climate); + this.climateSettings = NBTHelper.serialize("climate", settings.climate); } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FeaturePage.java b/src/main/java/com/terraforged/mod/gui/page/MiscPage.java similarity index 74% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FeaturePage.java rename to src/main/java/com/terraforged/mod/gui/page/MiscPage.java index 2f32b62..cd7a0cc 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/FeaturePage.java +++ b/src/main/java/com/terraforged/mod/gui/page/MiscPage.java @@ -26,33 +26,40 @@ package com.terraforged.mod.gui.page; import com.terraforged.mod.gui.OverlayScreen; +import com.terraforged.mod.gui.element.TerraLabel; import com.terraforged.mod.settings.TerraSettings; import com.terraforged.mod.util.nbt.NBTHelper; import net.minecraft.nbt.CompoundNBT; -public class FeaturePage extends BasePage { +public class MiscPage extends BasePage { private final TerraSettings settings; + private final CompoundNBT filterSettings; private final CompoundNBT featureSettings; - public FeaturePage(TerraSettings settings) { + public MiscPage(TerraSettings settings) { this.settings = settings; - this.featureSettings = NBTHelper.serialize(settings.features); + this.filterSettings = NBTHelper.serialize("filters", settings.filters); + this.featureSettings = NBTHelper.serialize("features", settings.features); } @Override public String getTitle() { - return "Feature Settings"; + return "Miscellaneous Settings"; } @Override public void save() { + NBTHelper.deserialize(filterSettings, settings.filters); NBTHelper.deserialize(featureSettings, settings.features); } @Override public void init(OverlayScreen parent) { Column left = getColumn(0); + addElements(left.left, left.top, left, filterSettings, true, left.scrollPane::addButton, this::update); + + left.scrollPane.addButton(new TerraLabel("Features & Decorators")); addElements(left.left, left.top, left, featureSettings, false, left.scrollPane::addButton, this::update); } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/Page.java b/src/main/java/com/terraforged/mod/gui/page/Page.java similarity index 89% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/Page.java rename to src/main/java/com/terraforged/mod/gui/page/Page.java index 824a562..a02e5aa 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/Page.java +++ b/src/main/java/com/terraforged/mod/gui/page/Page.java @@ -28,6 +28,7 @@ package com.terraforged.mod.gui.page; import com.terraforged.mod.gui.OverlayRenderer; import com.terraforged.mod.gui.OverlayScreen; import com.terraforged.mod.gui.ScrollPane; +import com.terraforged.mod.gui.element.Element; import com.terraforged.mod.gui.element.TerraLabel; import com.terraforged.mod.gui.element.TerraSlider; import com.terraforged.mod.gui.element.TerraTextInput; @@ -40,6 +41,7 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraftforge.common.util.Constants; +import java.util.Comparator; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.function.Function; @@ -135,9 +137,8 @@ public abstract class Page implements IGuiEventListener, OverlayRenderer { public void addElements(int x, int y, Column column, CompoundNBT settings, boolean deep, Consumer consumer, Runnable callback) { AtomicInteger top = new AtomicInteger(y); - NBTHelper.stream(settings).forEach(value -> { - String name = value.getString("#display"); - Widget button = createButton(name, value, callback); + NBTHelper.streamkeys(settings).forEach(name -> { + Widget button = createButton(name, settings, callback); if (button != null) { button.setWidth(column.width); button.setHeight(SLIDER_HEIGHT); @@ -146,11 +147,11 @@ public abstract class Page implements IGuiEventListener, OverlayRenderer { consumer.accept(button); onAddWidget(button); } else if (deep) { - INBT child = value.get("value"); + INBT child = settings.get(name); if (child == null || child.getId() != Constants.NBT.TAG_COMPOUND) { return; } - TerraLabel label = new TerraLabel(name); + TerraLabel label = new TerraLabel(Element.getDisplayName(name, settings)); label.x = x; label.y = top.getAndAdd(SLIDER_HEIGHT + SLIDER_PAD); consumer.accept(label); @@ -160,18 +161,18 @@ public abstract class Page implements IGuiEventListener, OverlayRenderer { } public Widget createButton(String name, CompoundNBT value, Runnable callback) { - INBT tag = value.get("value"); + INBT tag = value.get(name); if (tag == null) { return null; } byte type = tag.getId(); if (type == Constants.NBT.TAG_INT) { - return new TerraSlider.Int(name + ": ", value).callback(callback); + return new TerraSlider.Int(name, value).callback(callback); } else if (type == Constants.NBT.TAG_FLOAT) { - return new TerraSlider.Float(name + ": ", value).callback(callback); - } else if (type == Constants.NBT.TAG_STRING && value.contains("#options")) { - return new TerraToggle(name + ": ", value).callback(callback); + return new TerraSlider.Float(name, value).callback(callback); + } else if (type == Constants.NBT.TAG_STRING && hasOptions(name, value)) { + return new TerraToggle(name, value).callback(callback); } else if (type == Constants.NBT.TAG_STRING) { return new TerraTextInput(name, value); } else { @@ -205,4 +206,8 @@ public abstract class Page implements IGuiEventListener, OverlayRenderer { this.scrollPane.setLeftPos(this.left); } } + + private static boolean hasOptions(String name, CompoundNBT value) { + return value.getCompound("#" + name).contains("options"); + } } diff --git a/src/main/java/com/terraforged/mod/gui/page/PresetPage.java b/src/main/java/com/terraforged/mod/gui/page/PresetPage.java new file mode 100644 index 0000000..12be3a8 --- /dev/null +++ b/src/main/java/com/terraforged/mod/gui/page/PresetPage.java @@ -0,0 +1,16 @@ +package com.terraforged.mod.gui.page; + +import com.terraforged.mod.gui.OverlayScreen; + +public class PresetPage extends BasePage { + + @Override + public void save() { + + } + + @Override + public void init(OverlayScreen parent) { + + } +} diff --git a/src/main/java/com/terraforged/mod/gui/page/PresetsPage.java b/src/main/java/com/terraforged/mod/gui/page/PresetsPage.java new file mode 100644 index 0000000..5c8f733 --- /dev/null +++ b/src/main/java/com/terraforged/mod/gui/page/PresetsPage.java @@ -0,0 +1,21 @@ +package com.terraforged.mod.gui.page; + +import com.terraforged.mod.gui.OverlayScreen; + +public class PresetsPage extends BasePage { + + @Override + public String getTitle() { + return "Presets & Defaults"; + } + + @Override + public void save() { + + } + + @Override + public void init(OverlayScreen parent) { + + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/RiverPage.java b/src/main/java/com/terraforged/mod/gui/page/RiverPage.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/RiverPage.java rename to src/main/java/com/terraforged/mod/gui/page/RiverPage.java index f19fc4f..94162dd 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/RiverPage.java +++ b/src/main/java/com/terraforged/mod/gui/page/RiverPage.java @@ -40,7 +40,7 @@ public class RiverPage extends BasePage { public RiverPage(Settings settings, PreviewPage preview) { this.settings = settings; this.preview = preview; - this.riverSettings = NBTHelper.serialize(settings.rivers); + this.riverSettings = NBTHelper.serialize("rivers", settings.rivers); } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java b/src/main/java/com/terraforged/mod/gui/page/StructurePage.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java rename to src/main/java/com/terraforged/mod/gui/page/StructurePage.java index e0a8278..e2b30af 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/StructurePage.java +++ b/src/main/java/com/terraforged/mod/gui/page/StructurePage.java @@ -37,7 +37,7 @@ public class StructurePage extends BasePage { public StructurePage(TerraSettings settings) { this.settings = settings; - this.structureSettings = NBTHelper.serialize(settings.structures); + this.structureSettings = NBTHelper.serialize("structures", settings.structures); } @Override diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/TerrainPage.java b/src/main/java/com/terraforged/mod/gui/page/TerrainPage.java similarity index 96% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/TerrainPage.java rename to src/main/java/com/terraforged/mod/gui/page/TerrainPage.java index d1e951d..2dbd732 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/page/TerrainPage.java +++ b/src/main/java/com/terraforged/mod/gui/page/TerrainPage.java @@ -40,7 +40,7 @@ public class TerrainPage extends BasePage { public TerrainPage(Settings settings, PreviewPage preview) { this.settings = settings; this.preview = preview; - this.terrainSettings = NBTHelper.serialize(settings.terrain); + this.terrainSettings = NBTHelper.serialize("terrain", settings.terrain); } @Override diff --git a/src/main/java/com/terraforged/mod/gui/page/WorldPage.java b/src/main/java/com/terraforged/mod/gui/page/WorldPage.java new file mode 100644 index 0000000..6513e1f --- /dev/null +++ b/src/main/java/com/terraforged/mod/gui/page/WorldPage.java @@ -0,0 +1,105 @@ +/* + * + * MIT License + * + * Copyright (c) 2020 TerraForged + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.terraforged.mod.gui.page; + +import com.terraforged.mod.TerraWorld; +import com.terraforged.mod.gui.OverlayScreen; +import com.terraforged.mod.gui.element.TerraTextInput; +import com.terraforged.mod.gui.preview.PreviewPage; +import com.terraforged.mod.settings.TerraSettings; +import com.terraforged.mod.util.nbt.NBTHelper; +import net.minecraft.client.gui.widget.Widget; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.StringNBT; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.WorldType; +import net.minecraftforge.registries.ForgeRegistries; + +public class WorldPage extends BasePage { + + private final TerraSettings settings; + private final PreviewPage preview; + private final CompoundNBT worldSettings; + private final CompoundNBT dimSettings; + + public WorldPage(TerraSettings settings, PreviewPage preview) { + this.settings = settings; + this.preview = preview; + this.worldSettings = NBTHelper.serialize("world", settings.world); + this.dimSettings = NBTHelper.serialize("dimensions", settings.dimensions); + + CompoundNBT generators = dimSettings.getCompound("dimensions").getCompound("value"); + for (String name : generators.keySet()) { + CompoundNBT setting = generators.getCompound(name); + setting.put("#options", getWorldTypes()); + } + } + + @Override + public String getTitle() { + return "World Settings"; + } + + @Override + public void save() { + NBTHelper.deserialize(worldSettings, settings.world); + NBTHelper.deserialize(dimSettings, settings.dimensions); + } + + @Override + public void init(OverlayScreen parent) { + Column left = getColumn(0); + addElements(left.left, left.top, left, worldSettings, true, left.scrollPane::addButton, this::update); + addElements(left.left, left.top, left, dimSettings, true, left.scrollPane::addButton, this::update); + } + + @Override + public void onAddWidget(Widget widget) { + if (widget instanceof TerraTextInput) { + TerraTextInput input = (TerraTextInput) widget; + input.setColorValidator(string -> ForgeRegistries.BLOCKS.containsKey(new ResourceLocation(string))); + } + } + + protected void update() { + super.update(); + preview.apply(settings -> NBTHelper.deserialize(worldSettings, settings.world)); + } + + private static ListNBT getWorldTypes() { + ListNBT options = new ListNBT(); + for (WorldType type : WorldType.WORLD_TYPES) { + if (type == null || (type.getId() >= 1 && type.getId() <= 6) || type.getId() == 8) { + continue; + } + if (!TerraWorld.isTerraType(type)) { + options.add(StringNBT.valueOf(type.getName())); + } + } + return options; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/Preview.java b/src/main/java/com/terraforged/mod/gui/preview/Preview.java similarity index 85% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/Preview.java rename to src/main/java/com/terraforged/mod/gui/preview/Preview.java index 226d03d..700e8c6 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/Preview.java +++ b/src/main/java/com/terraforged/mod/gui/preview/Preview.java @@ -29,15 +29,15 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.Region; +import com.terraforged.core.region.Size; import com.terraforged.core.region.gen.RegionGenerator; import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.concurrent.ThreadPool; -import com.terraforged.core.util.concurrent.cache.CacheEntry; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.WorldGeneratorFactory; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; -import com.terraforged.core.world.terrain.Terrains; +import com.terraforged.core.concurrent.ThreadPool; +import com.terraforged.core.concurrent.cache.CacheEntry; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.continent.MutableVeci; +import com.terraforged.world.heightmap.Levels; +import com.terraforged.world.terrain.Terrains; import com.terraforged.mod.util.nbt.NBTHelper; import me.dags.noise.util.NoiseUtil; import net.minecraft.client.Minecraft; @@ -54,9 +54,9 @@ import java.util.Random; public class Preview extends Button { private static final int FACTOR = 4; - public static final int WIDTH = 256; + public static final int WIDTH = Size.chunkToBlock(1 << FACTOR); private static final int SLICE_HEIGHT = 64; - public static final int HEIGHT = WIDTH + SLICE_HEIGHT; + public static final int HEIGHT = WIDTH + SLICE_HEIGHT;//Size.chunkToBlock(1 << FACTOR); private static final float[] LEGEND_SCALES = {1, 0.9F, 0.75F, 0.6F}; private final int offsetX; @@ -65,15 +65,15 @@ public class Preview extends Button { private final PreviewSettings previewSettings = new PreviewSettings(); private final DynamicTexture texture = new DynamicTexture(new NativeImage(WIDTH, HEIGHT, true)); - private final String[] values = {"", "", ""}; - private final String[] labels = {"Area: ", "Terrain: ", "Biome: "}; - private int seed; private long lastUpdate = 0L; private Settings settings = new Settings(); private CacheEntry task = null; private Region region = null; + private String[] labels = {"Area: ", "Terrain: ", "Biome: "}; + private String[] values = {"", "", ""}; + public Preview(int seed) { super(0, 0, 0, 0, "", b -> {}); this.seed = seed == -1 ? random.nextInt() : seed; @@ -122,7 +122,7 @@ public class Preview extends Button { lastUpdate = time; NBTHelper.deserialize(prevSettings, previewSettings); - settings.generator.seed = seed; + settings.world.seed = seed; task = generate(settings, prevSettings); } @@ -147,7 +147,7 @@ public class Preview extends Button { } RenderMode renderer = previewSettings.mode; - Levels levels = new Levels(settings.generator); + Levels levels = new Levels(settings.world); int stroke = 2; int width = region.getBlockSize().size; @@ -159,8 +159,8 @@ public class Preview extends Button { float zoomUnit = 1F - (zoom / 100F); float zoomStrength = 0.5F; float unit = (1 - zoomStrength) + (zoomStrength * zoomUnit); - float heightModifier = settings.generator.world.worldHeight / 256F; - float waterLevelModifier = settings.generator.world.seaLevel / (float) settings.generator.world.worldHeight; + float heightModifier = settings.world.levels.worldHeight / 256F; + float waterLevelModifier = settings.world.levels.seaLevel / (float) settings.world.levels.worldHeight; float imageWaterLevelY = image.getHeight() - 1 - (waterLevelModifier * SLICE_HEIGHT * unit); region.iterate((cell, x, z) -> { @@ -194,18 +194,24 @@ public class Preview extends Button { private CacheEntry generate(Settings settings, CompoundNBT prevSettings) { NBTHelper.deserialize(prevSettings, previewSettings); - settings.generator.seed = seed; + settings.world.seed = seed; this.settings = settings; - GeneratorContext context = new GeneratorContext(Terrains.create(settings), settings); + GeneratorContext context = GeneratorContext.createNoCache(Terrains.create(settings), settings); + + MutableVeci center = new MutableVeci(); + context.factory.getHeightmap().getContinent().getNearestCenter(offsetX, offsetZ, center); RegionGenerator renderer = RegionGenerator.builder() - .factory(new WorldGeneratorFactory(context)) .pool(ThreadPool.getPool()) .size(FACTOR, 0) + .factory(context.factory) + .batch(6) .build(); - return renderer.queue(offsetX, offsetZ, 101 - previewSettings.zoom, false); + float zoom = 101 - previewSettings.zoom; + + return renderer.getAsync(center.x, center.z, zoom, false); } private void updateLegend(int mx ,int my) { @@ -222,7 +228,7 @@ public class Preview extends Button { float fz = (my - top) / size; int ix = NoiseUtil.round(fx * region.getBlockSize().size); int iz = NoiseUtil.round(fz * region.getBlockSize().size); - Cell cell = region.getCell(ix, iz); + Cell cell = region.getCell(ix, iz); values[1] = getTerrainName(cell); values[2] = getBiomeName(cell); } @@ -269,16 +275,16 @@ public class Preview extends Button { RenderSystem.popMatrix(); } - private static String getTerrainName(Cell cell) { - String terrain = cell.tag.getName().toLowerCase(); + private static String getTerrainName(Cell cell) { + String terrain = cell.terrainType.getName().toLowerCase(); if (terrain.contains("river")) { return "river"; } return terrain; } - private static String getBiomeName(Cell cell) { - String terrain = cell.tag.getName().toLowerCase(); + private static String getBiomeName(Cell cell) { + String terrain = cell.terrainType.getName().toLowerCase(); if (terrain.contains("ocean")) { if (cell.temperature < 0.3) { return "cold_ocean"; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java b/src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java rename to src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java index 97bd7be..40d2af7 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java +++ b/src/main/java/com/terraforged/mod/gui/preview/PreviewPage.java @@ -38,7 +38,7 @@ public class PreviewPage extends BasePage { private final Preview preview; private final Settings settings; - private final CompoundNBT previewerSettings = NBTHelper.serialize(new PreviewSettings()); + private final CompoundNBT previewerSettings = NBTHelper.serialize("preview", new PreviewSettings()); public PreviewPage(Settings settings, int seed) { this.preview = new Preview(seed); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java b/src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java similarity index 80% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java rename to src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java index 661c80c..b283aae 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java +++ b/src/main/java/com/terraforged/mod/gui/preview/PreviewSettings.java @@ -25,12 +25,17 @@ package com.terraforged.mod.gui.preview; -import com.terraforged.core.util.serialization.annotation.Range; +import com.terraforged.core.serialization.annotation.Comment; +import com.terraforged.core.serialization.annotation.Range; +import com.terraforged.core.serialization.annotation.Serializable; +@Serializable public class PreviewSettings { @Range(min = 1, max = 100) + @Comment("Controls the zoom level of the preview map") public int zoom = 100 - 32; + @Comment("Controls the rendering mode on the preview map") public RenderMode mode = RenderMode.BIOME_TYPE; } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/RenderMode.java b/src/main/java/com/terraforged/mod/gui/preview/RenderMode.java similarity index 83% rename from TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/RenderMode.java rename to src/main/java/com/terraforged/mod/gui/preview/RenderMode.java index 0442131..2085934 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/gui/preview/RenderMode.java +++ b/src/main/java/com/terraforged/mod/gui/preview/RenderMode.java @@ -26,8 +26,7 @@ package com.terraforged.mod.gui.preview; import com.terraforged.core.cell.Cell; -import com.terraforged.core.world.heightmap.Levels; -import com.terraforged.core.world.terrain.Terrain; +import com.terraforged.world.heightmap.Levels; import me.dags.noise.util.NoiseUtil; import java.awt.*; @@ -35,7 +34,7 @@ import java.awt.*; public enum RenderMode { BIOME_TYPE { @Override - public int getColor(Cell cell, float scale, float bias) { + public int getColor(Cell cell, float scale, float bias) { Color color = cell.biomeType.getColor(); float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), new float[3]); return rgba(hsb[0], hsb[1], (hsb[2] * scale) + bias); @@ -43,7 +42,7 @@ public enum RenderMode { }, TEMPERATURE { @Override - public int getColor(Cell cell, float scale, float bias) { + public int getColor(Cell cell, float scale, float bias) { float saturation = 0.7F; float brightness = 0.8F; return rgba(step(1 - cell.temperature, 8) * 0.65F, saturation, brightness); @@ -51,7 +50,7 @@ public enum RenderMode { }, MOISTURE { @Override - public int getColor(Cell cell, float scale, float bias) { + public int getColor(Cell cell, float scale, float bias) { float saturation = 0.7F; float brightness = 0.8F; return rgba(step(cell.moisture, 8) * 0.65F, saturation, brightness); @@ -59,15 +58,15 @@ public enum RenderMode { }, BIOME_SHAPE { @Override - public int getColor(Cell cell, float scale, float bias) { + public int getColor(Cell cell, float scale, float bias) { float saturation = 0.7F; float brightness = 0.8F; return rgba(cell.biome, saturation, brightness); } }, - TERRAIN_TYPE { + REGION_SHAPE { @Override - public int getColor(Cell cell, float scale, float bias) { + public int getColor(Cell cell, float scale, float bias) { float saturation = 0.7F; float brightness = 0.8F; return rgba(cell.region, saturation, brightness); @@ -75,7 +74,7 @@ public enum RenderMode { }, ; - public int getColor(Cell cell, Levels levels) { + public int getColor(Cell cell, Levels levels) { float baseHeight = levels.water; if (cell.value < baseHeight) { return rgba(40, 140, 200); @@ -89,7 +88,7 @@ public enum RenderMode { return getColor(cell, scale, bias); } - public abstract int getColor(Cell cell, float scale, float bias); + public abstract int getColor(Cell cell, float scale, float bias); private static float step(float value, int steps) { return ((float) NoiseUtil.round(value * steps)) / steps; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/material/MaterialHelper.java b/src/main/java/com/terraforged/mod/material/MaterialHelper.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/material/MaterialHelper.java rename to src/main/java/com/terraforged/mod/material/MaterialHelper.java index fdc1360..a6e68c6 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/material/MaterialHelper.java +++ b/src/main/java/com/terraforged/mod/material/MaterialHelper.java @@ -26,7 +26,7 @@ package com.terraforged.mod.material; import com.google.common.collect.Sets; -import com.terraforged.core.util.concurrent.ObjectPool; +import com.terraforged.core.concurrent.ObjectPool; import com.terraforged.mod.util.DummyBlockReader; import net.minecraft.block.Block; import net.minecraft.block.BlockState; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/material/Materials.java b/src/main/java/com/terraforged/mod/material/Materials.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/material/Materials.java rename to src/main/java/com/terraforged/mod/material/Materials.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java b/src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java similarity index 98% rename from TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java rename to src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java index a8760b9..0c6ff2d 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java +++ b/src/main/java/com/terraforged/mod/material/geology/GeoGenerator.java @@ -28,7 +28,7 @@ package com.terraforged.mod.material.geology; import com.terraforged.api.material.WGTags; import com.terraforged.api.material.geology.StrataConfig; import com.terraforged.api.material.geology.StrataGenerator; -import com.terraforged.core.world.geology.Strata; +import com.terraforged.world.geology.Strata; import com.terraforged.mod.material.MaterialHelper; import com.terraforged.mod.material.Materials; import me.dags.noise.Source; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoManager.java b/src/main/java/com/terraforged/mod/material/geology/GeoManager.java similarity index 95% rename from TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoManager.java rename to src/main/java/com/terraforged/mod/material/geology/GeoManager.java index 2b6634b..92ed10b 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/material/geology/GeoManager.java +++ b/src/main/java/com/terraforged/mod/material/geology/GeoManager.java @@ -27,9 +27,9 @@ package com.terraforged.mod.material.geology; import com.terraforged.api.material.geology.GeologyManager; import com.terraforged.api.material.geology.StrataConfig; -import com.terraforged.core.util.Seed; -import com.terraforged.core.world.geology.Geology; -import com.terraforged.core.world.geology.Strata; +import com.terraforged.core.Seed; +import com.terraforged.world.geology.Geology; +import com.terraforged.world.geology.Strata; import com.terraforged.mod.chunk.TerraContext; import com.terraforged.mod.material.Materials; import me.dags.noise.Module; @@ -49,7 +49,7 @@ public class GeoManager implements GeologyManager { private final Map> specific = new HashMap<>(); public GeoManager(TerraContext context) { - int scale = context.settings.generator.land.regionSize / 2; + int scale = context.settings.terrain.general.terrainRegionSize / 2; this.selector = Source.cell(context.seed.next(), scale) .warp(context.seed.next(), scale / 4, 2, scale / 2D) .warp(context.seed.next(), 15, 2, 30); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/DimesionSettings.java b/src/main/java/com/terraforged/mod/settings/DimesionSettings.java similarity index 86% rename from TerraForgedMod/src/main/java/com/terraforged/mod/settings/DimesionSettings.java rename to src/main/java/com/terraforged/mod/settings/DimesionSettings.java index 7290350..10214ce 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/DimesionSettings.java +++ b/src/main/java/com/terraforged/mod/settings/DimesionSettings.java @@ -1,8 +1,8 @@ package com.terraforged.mod.settings; -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; +import com.terraforged.core.serialization.annotation.Comment; +import com.terraforged.core.serialization.annotation.Range; +import com.terraforged.core.serialization.annotation.Serializable; import com.terraforged.mod.TerraWorld; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.StringNBT; @@ -14,9 +14,9 @@ import org.jline.utils.Log; @Serializable public class DimesionSettings { - public BaseDecorator baseLayer = new BaseDecorator(); + public BaseDecorator bedrockLayer = new BaseDecorator(); - public DimensionGenerators dimensionGenerators = new DimensionGenerators(); + public DimensionGenerators dimensions = new DimensionGenerators(); @Serializable public static class BaseDecorator { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/FeatureSettings.java b/src/main/java/com/terraforged/mod/settings/Miscellaneous.java similarity index 91% rename from TerraForgedMod/src/main/java/com/terraforged/mod/settings/FeatureSettings.java rename to src/main/java/com/terraforged/mod/settings/Miscellaneous.java index 878f360..d68e17d 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/FeatureSettings.java +++ b/src/main/java/com/terraforged/mod/settings/Miscellaneous.java @@ -25,11 +25,11 @@ package com.terraforged.mod.settings; -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Serializable; +import com.terraforged.core.serialization.annotation.Comment; +import com.terraforged.core.serialization.annotation.Serializable; @Serializable -public class FeatureSettings { +public class Miscellaneous { @Comment("Modifies layer block levels (ie snow) to fit the terrain") public boolean smoothLayerDecorator = true; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/SettingsHelper.java b/src/main/java/com/terraforged/mod/settings/SettingsHelper.java similarity index 78% rename from TerraForgedMod/src/main/java/com/terraforged/mod/settings/SettingsHelper.java rename to src/main/java/com/terraforged/mod/settings/SettingsHelper.java index 86af287..78ec610 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/SettingsHelper.java +++ b/src/main/java/com/terraforged/mod/settings/SettingsHelper.java @@ -29,22 +29,6 @@ public class SettingsHelper { public static final File SETTINGS_FILE= new File(SETTINGS_DIR, SETTINGS_FILE_NAME); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - public static int getVersion(WorldInfo info) { - if (info.getGeneratorOptions().isEmpty()) { - // if options have not been set then the world has been created - // during the current runtime .: is not legacy - return TerraWorld.VERSION; - } - - CompoundNBT version = info.getGeneratorOptions().getCompound("version"); - if (version.isEmpty()) { - // version tag is absent in legacy worlds .: is legacy - return 0; - } - - return version.getInt("value"); - } - public static void clearDefaults() { if (SETTINGS_FILE.exists() && SETTINGS_FILE.delete()) { Log.info("Deleted generator defaults"); @@ -93,14 +77,7 @@ public class SettingsHelper { return settings; } - public static void syncSettings(WorldInfo info, TerraSettings settings, int version) { - settings.version = version; - settings.generator.seed = info.getSeed(); - CompoundNBT options = NBTHelper.serialize(settings); - info.setGeneratorOptions(options); - } - - public static void initSettings() { + public static void init() { if (SETTINGS_FILE.exists()) { return; } @@ -121,8 +98,4 @@ public class SettingsHelper { DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> exportDefaults(new TerraSettings())); } } - - private static void initServerSettings() { - DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> exportDefaults(new TerraSettings())); - } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/StructureSettings.java b/src/main/java/com/terraforged/mod/settings/StructureSettings.java similarity index 52% rename from TerraForgedMod/src/main/java/com/terraforged/mod/settings/StructureSettings.java rename to src/main/java/com/terraforged/mod/settings/StructureSettings.java index 866fe53..8201e4d 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/StructureSettings.java +++ b/src/main/java/com/terraforged/mod/settings/StructureSettings.java @@ -25,38 +25,45 @@ package com.terraforged.mod.settings; -import com.terraforged.core.util.serialization.annotation.Comment; -import com.terraforged.core.util.serialization.annotation.Range; -import com.terraforged.core.util.serialization.annotation.Serializable; +import com.terraforged.core.serialization.annotation.Comment; +import com.terraforged.core.serialization.annotation.Range; +import com.terraforged.core.serialization.annotation.Serializable; @Serializable public class StructureSettings { - @Range(min = 1, max = 10) - @Comment("Controls the distance between villages") - public int villageDistance = 2; + public Structure villages = new Structure(32, 8); - @Range(min = 1, max = 10) - @Comment("Controls the distance between mansions") - public int mansionDistance = 3; + public Structure mansions = new Structure(80, 20); - @Range(min = 1, max = 10) - @Comment("Controls the distance between strongholds") - public int strongholdDistance = 3; + public Structure strongholds = new Structure(32, 3); - @Range(min = 1, max = 10) - @Comment("Controls the distance between strongholds") - public int strongholdSpread = 3; + public Structure shipwrecks = new Structure(16, 8); - @Range(min = 1, max = 10) - @Comment("Controls the distance between biome structures") - public int biomeStructureDistance = 4; + public Structure oceanRuins = new Structure(16, 8); - @Range(min = 1, max = 10) - @Comment("Controls the distance between ocean monuments") - public int oceanMonumentSpacing = 3; + public Structure oceanMonuments = new Structure(32, 5); - @Range(min = 1, max = 10) - @Comment("Controls the separation between ocean monuments") - public int oceanMonumentSeparation = 3; + public Structure otherStructures = new Structure(32, 1); + + @Serializable + public static class Structure { + + @Range(min = 1, max = 200) + @Comment("The distance (in chunks) between placements of this feature") + public int distance; + + @Range(min = 1, max = 50) + @Comment("The separation (in chunks) between placements of this feature") + public int separation; + + public Structure() { + + } + + public Structure(int distance, int separation) { + this.distance = distance; + this.separation = separation; + } + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/TerraSettings.java b/src/main/java/com/terraforged/mod/settings/TerraSettings.java similarity index 89% rename from TerraForgedMod/src/main/java/com/terraforged/mod/settings/TerraSettings.java rename to src/main/java/com/terraforged/mod/settings/TerraSettings.java index e880506..30aad9e 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/settings/TerraSettings.java +++ b/src/main/java/com/terraforged/mod/settings/TerraSettings.java @@ -26,14 +26,12 @@ package com.terraforged.mod.settings; import com.terraforged.core.settings.Settings; -import com.terraforged.core.util.serialization.annotation.Serializable; +import com.terraforged.core.serialization.annotation.Serializable; @Serializable public class TerraSettings extends Settings { - public int version = 1; - - public FeatureSettings features = new FeatureSettings(); + public Miscellaneous features = new Miscellaneous(); public StructureSettings structures = new StructureSettings(); diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/DataPackFinder.java b/src/main/java/com/terraforged/mod/util/DataPackFinder.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/DataPackFinder.java rename to src/main/java/com/terraforged/mod/util/DataPackFinder.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/DummyBlockReader.java b/src/main/java/com/terraforged/mod/util/DummyBlockReader.java similarity index 97% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/DummyBlockReader.java rename to src/main/java/com/terraforged/mod/util/DummyBlockReader.java index 00254c4..43c6d1e 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/util/DummyBlockReader.java +++ b/src/main/java/com/terraforged/mod/util/DummyBlockReader.java @@ -25,7 +25,7 @@ package com.terraforged.mod.util; -import com.terraforged.core.util.concurrent.ObjectPool; +import com.terraforged.core.concurrent.ObjectPool; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.fluid.FluidState; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/Environment.java b/src/main/java/com/terraforged/mod/util/Environment.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/Environment.java rename to src/main/java/com/terraforged/mod/util/Environment.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/ListUtils.java b/src/main/java/com/terraforged/mod/util/ListUtils.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/ListUtils.java rename to src/main/java/com/terraforged/mod/util/ListUtils.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/NBTLeavesFixer.java b/src/main/java/com/terraforged/mod/util/NBTLeavesFixer.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/NBTLeavesFixer.java rename to src/main/java/com/terraforged/mod/util/NBTLeavesFixer.java diff --git a/src/main/java/com/terraforged/mod/util/RangeModifier.java b/src/main/java/com/terraforged/mod/util/RangeModifier.java new file mode 100644 index 0000000..afdaeed --- /dev/null +++ b/src/main/java/com/terraforged/mod/util/RangeModifier.java @@ -0,0 +1,35 @@ +package com.terraforged.mod.util; + +public abstract class RangeModifier { + + protected final float min; + protected final float max; + private final float range; + + public RangeModifier(float min, float max) { + this.min = min; + this.max = max; + this.range = Math.abs(max - min); + } + + public float apply(float value) { + if (min < max) { + if (value <= min) { + return 0F; + } + if (value >= max) { + return 1F; + } + return (value - min) / range; + } else if (min > max) { + if (value <= min) { + return 1F; + } + if (value >= max) { + return 0F; + } + return 1F - (value / range); + } + return 1F; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/annotation/Name.java b/src/main/java/com/terraforged/mod/util/annotation/Name.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/annotation/Name.java rename to src/main/java/com/terraforged/mod/util/annotation/Name.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/annotation/Ref.java b/src/main/java/com/terraforged/mod/util/annotation/Ref.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/annotation/Ref.java rename to src/main/java/com/terraforged/mod/util/annotation/Ref.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java b/src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java similarity index 88% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java rename to src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java index a2c486f..536261a 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java +++ b/src/main/java/com/terraforged/mod/util/nbt/NBTHelper.java @@ -28,7 +28,7 @@ package com.terraforged.mod.util.nbt; import com.google.gson.JsonElement; import com.mojang.datafixers.Dynamic; import com.mojang.datafixers.types.JsonOps; -import com.terraforged.core.util.serialization.serializer.Serializer; +import com.terraforged.core.serialization.serializer.Serializer; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; @@ -53,17 +53,14 @@ public class NBTHelper { return (CompoundNBT) output.getValue(); } - public static Stream stream(CompoundNBT tag) { - return tag.keySet().stream() - .map(tag::getCompound) - .sorted(Comparator.comparing(t -> t.getInt("#order"))); - + public static CompoundNBT serialize(Object object) { + return serialize("", object); } - public static CompoundNBT serialize(Object object) { + public static CompoundNBT serialize(String owner, Object object) { try { NBTWriter writer = new NBTWriter(); - writer.readFrom(object); + Serializer.serialize(object, writer, owner, true); return writer.compound(); } catch (IllegalAccessException e) { return new CompoundNBT(); @@ -91,6 +88,12 @@ public class NBTHelper { } } + public static Stream streamkeys(CompoundNBT compound) { + return compound.keySet().stream() + .filter(name -> !name.startsWith("#")) + .sorted(Comparator.comparing(name -> compound.getCompound("#" + name).getInt("order"))); + } + public static T stripMetadata(T tag) { if (tag instanceof CompoundNBT) { CompoundNBT compound = (CompoundNBT) tag; diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTReader.java b/src/main/java/com/terraforged/mod/util/nbt/NBTReader.java similarity index 97% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTReader.java rename to src/main/java/com/terraforged/mod/util/nbt/NBTReader.java index 2ed5270..e634bf1 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/util/nbt/NBTReader.java +++ b/src/main/java/com/terraforged/mod/util/nbt/NBTReader.java @@ -25,7 +25,7 @@ package com.terraforged.mod.util.nbt; -import com.terraforged.core.util.serialization.serializer.Reader; +import com.terraforged.core.serialization.serializer.Reader; import net.minecraft.nbt.ByteNBT; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.FloatNBT; diff --git a/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java b/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java new file mode 100644 index 0000000..4e793f8 --- /dev/null +++ b/src/main/java/com/terraforged/mod/util/nbt/NBTWriter.java @@ -0,0 +1,66 @@ +package com.terraforged.mod.util.nbt; + +import com.terraforged.core.serialization.serializer.AbstractWriter; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.FloatNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.IntNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.StringNBT; + +public class NBTWriter extends AbstractWriter { + + public CompoundNBT compound() { + return (CompoundNBT) getRoot(); + } + + @Override + protected NBTWriter self() { + return this; + } + + @Override + protected boolean isObject(INBT value) { + return value instanceof CompoundNBT; + } + + @Override + protected boolean isArray(INBT value) { + return value instanceof ListNBT; + } + + @Override + protected void add(INBT parent, String key, INBT value) { + ((CompoundNBT) parent).put(key, value); + } + + @Override + protected void add(INBT parent, INBT value) { + ((ListNBT) parent).add(value); + } + + @Override + protected INBT createObject() { + return new CompoundNBT(); + } + + @Override + protected INBT createArray() { + return new ListNBT(); + } + + @Override + protected INBT create(String value) { + return StringNBT.valueOf(value); + } + + @Override + protected INBT create(int value) { + return IntNBT.valueOf(value); + } + + @Override + protected INBT create(float value) { + return FloatNBT.valueOf(value); + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/setup/SetupDebug.java b/src/main/java/com/terraforged/mod/util/setup/SetupDebug.java similarity index 100% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/setup/SetupDebug.java rename to src/main/java/com/terraforged/mod/util/setup/SetupDebug.java diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/util/setup/SetupHooks.java b/src/main/java/com/terraforged/mod/util/setup/SetupHooks.java similarity index 94% rename from TerraForgedMod/src/main/java/com/terraforged/mod/util/setup/SetupHooks.java rename to src/main/java/com/terraforged/mod/util/setup/SetupHooks.java index f533316..e3b28f9 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/util/setup/SetupHooks.java +++ b/src/main/java/com/terraforged/mod/util/setup/SetupHooks.java @@ -32,9 +32,9 @@ import com.terraforged.api.chunk.surface.SurfaceManager; import com.terraforged.api.event.SetupEvent; import com.terraforged.api.material.geology.GeologyManager; import com.terraforged.api.material.layer.LayerManager; -import com.terraforged.core.world.GeneratorContext; -import com.terraforged.core.world.terrain.provider.TerrainProvider; -import com.terraforged.feature.modifier.FeatureModifiers; +import com.terraforged.world.GeneratorContext; +import com.terraforged.world.terrain.provider.TerrainProvider; +import com.terraforged.mod.feature.manager.modifier.FeatureModifiers; import net.minecraftforge.common.MinecraftForge; import java.util.List; diff --git a/TerraForgedMod/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml similarity index 100% rename from TerraForgedMod/src/main/resources/META-INF/mods.toml rename to src/main/resources/META-INF/mods.toml diff --git a/TerraForgedMod/src/main/resources/biomes.txt b/src/main/resources/biomes.txt similarity index 100% rename from TerraForgedMod/src/main/resources/biomes.txt rename to src/main/resources/biomes.txt diff --git a/TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_clay.json b/src/main/resources/data/forge/tags/blocks/wg_clay.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_clay.json rename to src/main/resources/data/forge/tags/blocks/wg_clay.json diff --git a/TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_dirt.json b/src/main/resources/data/forge/tags/blocks/wg_dirt.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_dirt.json rename to src/main/resources/data/forge/tags/blocks/wg_dirt.json diff --git a/TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_erodible.json b/src/main/resources/data/forge/tags/blocks/wg_erodible.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_erodible.json rename to src/main/resources/data/forge/tags/blocks/wg_erodible.json diff --git a/TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_sediment.json b/src/main/resources/data/forge/tags/blocks/wg_sediment.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_sediment.json rename to src/main/resources/data/forge/tags/blocks/wg_sediment.json diff --git a/TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_stone.json b/src/main/resources/data/forge/tags/blocks/wg_stone.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/forge/tags/blocks/wg_stone.json rename to src/main/resources/data/forge/tags/blocks/wg_stone.json diff --git a/src/main/resources/data/terraforged/blocks/saplings/birch_sapling.json b/src/main/resources/data/terraforged/blocks/saplings/birch_sapling.json new file mode 100644 index 0000000..6d605e7 --- /dev/null +++ b/src/main/resources/data/terraforged/blocks/saplings/birch_sapling.json @@ -0,0 +1,12 @@ +{ + "type": "terraforged:sapling", + "sapling": "minecraft:birch_sapling", + "normal": { + "terraforged:birch_small": { + "weight": 1 + }, + "terraforged:birch_large": { + "weight": 2 + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/blocks/saplings/jungle_sapling.json b/src/main/resources/data/terraforged/blocks/saplings/jungle_sapling.json new file mode 100644 index 0000000..2bb6b3d --- /dev/null +++ b/src/main/resources/data/terraforged/blocks/saplings/jungle_sapling.json @@ -0,0 +1,17 @@ +{ + "type": "terraforged:sapling", + "sapling": "minecraft:jungle_sapling", + "normal": { + "terraforged:jungle_small": { + "weight": 2 + }, + "terraforged:jungle_large": { + "weight": 1 + } + }, + "giant": { + "terraforged:jungle_huge": { + "weight": 1 + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/blocks/saplings/oak_sapling.json b/src/main/resources/data/terraforged/blocks/saplings/oak_sapling.json new file mode 100644 index 0000000..b3c43eb --- /dev/null +++ b/src/main/resources/data/terraforged/blocks/saplings/oak_sapling.json @@ -0,0 +1,12 @@ +{ + "type": "terraforged:sapling", + "sapling": "minecraft:oak_sapling", + "normal": { + "terraforged:oak_small": { + "weight": 2 + }, + "terraforged:oak_large": { + "weight": 1 + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/coal.json b/src/main/resources/data/terraforged/features/ores/coal.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/coal.json rename to src/main/resources/data/terraforged/features/ores/coal.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/diamond.json b/src/main/resources/data/terraforged/features/ores/diamond.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/diamond.json rename to src/main/resources/data/terraforged/features/ores/diamond.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/gold.json b/src/main/resources/data/terraforged/features/ores/gold.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/gold.json rename to src/main/resources/data/terraforged/features/ores/gold.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/gold_extra.json b/src/main/resources/data/terraforged/features/ores/gold_extra.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/gold_extra.json rename to src/main/resources/data/terraforged/features/ores/gold_extra.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/iron.json b/src/main/resources/data/terraforged/features/ores/iron.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/iron.json rename to src/main/resources/data/terraforged/features/ores/iron.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/lapis.json b/src/main/resources/data/terraforged/features/ores/lapis.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/lapis.json rename to src/main/resources/data/terraforged/features/ores/lapis.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/ores/redstone.json b/src/main/resources/data/terraforged/features/ores/redstone.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/ores/redstone.json rename to src/main/resources/data/terraforged/features/ores/redstone.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/sediments/clay.json b/src/main/resources/data/terraforged/features/sediments/clay.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/sediments/clay.json rename to src/main/resources/data/terraforged/features/sediments/clay.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/sediments/dirt.json b/src/main/resources/data/terraforged/features/sediments/dirt.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/sediments/dirt.json rename to src/main/resources/data/terraforged/features/sediments/dirt.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/sediments/gravel.json b/src/main/resources/data/terraforged/features/sediments/gravel.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/sediments/gravel.json rename to src/main/resources/data/terraforged/features/sediments/gravel.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/shrubs/dead_bush.json b/src/main/resources/data/terraforged/features/shrubs/dead_bush.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/shrubs/dead_bush.json rename to src/main/resources/data/terraforged/features/shrubs/dead_bush.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/shrubs/forest_grass.json b/src/main/resources/data/terraforged/features/shrubs/forest_grass.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/features/shrubs/forest_grass.json rename to src/main/resources/data/terraforged/features/shrubs/forest_grass.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/acacia.json b/src/main/resources/data/terraforged/features/trees/acacia.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/acacia.json rename to src/main/resources/data/terraforged/features/trees/acacia.json index cf5e9ac..6b9f902 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/acacia.json +++ b/src/main/resources/data/terraforged/features/trees/acacia.json @@ -13,19 +13,25 @@ "config": { "features": [ { - "name": "terraforged:acacia_large", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:acacia_large" + }, "chance": 0.4 }, { - "name": "terraforged:acacia_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:acacia_small" + }, "chance": 0.15 } ], "default": { - "name": "terraforged:acacia_large", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:acacia_large" + } } } }, diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch.json b/src/main/resources/data/terraforged/features/trees/birch.json similarity index 50% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch.json rename to src/main/resources/data/terraforged/features/trees/birch.json index fea9e44..957fcd9 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/birch.json +++ b/src/main/resources/data/terraforged/features/trees/birch.json @@ -17,28 +17,36 @@ "config": { "features": [ { - "name": "terraforged:birch_forest", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + }, "chance": 0.2 }, { - "name": "terraforged:birch_large", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_large" + }, "chance": 0.2 } ], "default": { - "name": "terraforged:birch_forest", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 21, - "extra_chance": 0.1, - "extra_count": 1 + "radius": 9, + "fade": 0.25, + "scale": 300, + "min": 0, + "max": 2 } } } diff --git a/src/main/resources/data/terraforged/features/trees/birch_oak.json b/src/main/resources/data/terraforged/features/trees/birch_oak.json new file mode 100644 index 0000000..eb1820e --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/birch_oak.json @@ -0,0 +1,69 @@ +{ + "biomes": [ + "minecraft:wooded_hills" + ], + "match": [ + [ + "minecraft:birch_log", + "minecraft:birch_leaves", + "minecraft:oak_log", + "minecraft:oak_leaves" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "minecraft:random_selector", + "config": { + "features": [ + { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_large" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_forest" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_large" + }, + "chance": 0.2 + } + ], + "default": { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + } + } + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 8, + "fade": 0.35, + "scale": 300, + "min": 0, + "max": 2 + } + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/dark_oak.json b/src/main/resources/data/terraforged/features/trees/dark_oak.json similarity index 78% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/dark_oak.json rename to src/main/resources/data/terraforged/features/trees/dark_oak.json index 5c82c0e..4c45cda 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/dark_oak.json +++ b/src/main/resources/data/terraforged/features/trees/dark_oak.json @@ -87,38 +87,50 @@ "chance": 0.05 }, { - "name": "terraforged:dark_oak_large", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:dark_oak_large" + }, "chance": 0.3 }, { - "name": "terraforged:dark_oak_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:dark_oak_small" + }, "chance": 0.2 }, { - "name": "terraforged:birch_forest", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + }, "chance": 0.05 }, { - "name": "terraforged:oak_forest", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_forest" + }, "chance": 0.025 } ], "default": { - "name": "terraforged:dark_oak_large", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:dark_oak_large" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 10, - "extra_chance": 0.1, - "extra_count": 1 + "radius": 8, + "fade": 0.4, + "scale": 200, + "min": 0, + "max": 1.85 } } } diff --git a/src/main/resources/data/terraforged/features/trees/fir_foreset.json b/src/main/resources/data/terraforged/features/trees/fir_foreset.json new file mode 100644 index 0000000..5441002 --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/fir_foreset.json @@ -0,0 +1,65 @@ +{ + "biomes": [ + "terraforged:fir_forest", + "terraforged:snowy_fir_forest" + ], + "match": [ + [ + "minecraft:normal_tree", + "minecraft:spruce_log", + "minecraft:spruce_leaves" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "terraforged:context_selector", + "config": { + "features": [ + { + "feature": { + "name": "terraforged:template", + "config": { + "template": "terraforged:spruce_small" + } + }, + "context": { + "chance": 0.2, + "elevation": { + "min": 0.75, + "max": 0.25 + } + } + }, + { + "feature": { + "name": "terraforged:template", + "config": { + "template": "terraforged:spruce_large" + } + }, + "context": { + "chance": 0.2, + "elevation": { + "min": 0.5, + "max": 0.0 + } + } + } + ] + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 6, + "fade": 0.3, + "scale": 200, + "min": 0, + "max": 2.5 + } + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/features/trees/flower_forest.json b/src/main/resources/data/terraforged/features/trees/flower_forest.json new file mode 100644 index 0000000..97aae28 --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/flower_forest.json @@ -0,0 +1,69 @@ +{ + "biomes": [ + "minecraft:flower_forest" + ], + "match": [ + [ + "minecraft:birch_log", + "minecraft:birch_leaves", + "minecraft:oak_log", + "minecraft:oak_leaves" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "minecraft:random_selector", + "config": { + "features": [ + { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_large" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_forest" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_large" + }, + "chance": 0.2 + } + ], + "default": { + "name": "terraforged:template", + "config": { + "template": "terraforged:birch_forest" + } + } + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 15, + "fade": 0.3, + "scale": 500, + "min": 0.75, + "max": 2 + } + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle.json b/src/main/resources/data/terraforged/features/trees/jungle.json similarity index 67% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle.json rename to src/main/resources/data/terraforged/features/trees/jungle.json index 791bfe7..214ea0f 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle.json +++ b/src/main/resources/data/terraforged/features/trees/jungle.json @@ -17,18 +17,24 @@ "config": { "features": [ { - "name": "terraforged:jungle_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + }, "chance": 0.2 }, { - "name": "terraforged:jungle_large", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_large" + }, "chance": 0.3 }, { - "name": "terraforged:jungle_huge", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_huge" + }, "chance": 0.4 }, { @@ -60,17 +66,21 @@ } ], "default": { - "name": "terraforged:jungle_small", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 15, - "extra_chance": 0.25, - "extra_count": 1 + "radius": 6, + "fade": 0.2, + "scale": 400, + "min": 0.25, + "max": 2 } } } diff --git a/src/main/resources/data/terraforged/features/trees/jungle_edge.json b/src/main/resources/data/terraforged/features/trees/jungle_edge.json new file mode 100644 index 0000000..935bd77 --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/jungle_edge.json @@ -0,0 +1,53 @@ +{ + "biomes": [ + "minecraft:jungle_edge", + "minecraft:modified_jungle_edge" + ], + "match": [ + [ + "minecraft:fancy_tree" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "minecraft:random_selector", + "config": { + "features": [ + { + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_large" + }, + "chance": 0.3 + } + ], + "default": { + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + } + } + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 9, + "fade": 0.3, + "scale": 350, + "min": 0.75, + "max": 1.5 + } + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_hills.json b/src/main/resources/data/terraforged/features/trees/jungle_hills.json similarity index 66% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_hills.json rename to src/main/resources/data/terraforged/features/trees/jungle_hills.json index 6e75e30..8fe9b88 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/jungle_hills.json +++ b/src/main/resources/data/terraforged/features/trees/jungle_hills.json @@ -16,19 +16,25 @@ "config": { "features": [ { - "name": "terraforged:jungle_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + }, + "chance": 0.3 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_large" + }, "chance": 0.4 }, { - "name": "terraforged:jungle_large", - "config": {}, - "chance": 0.2 - }, - { - "name": "terraforged:jungle_huge", - "config": {}, - "chance": 0.05 + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_huge" + }, + "chance": 0.3 }, { "name": "minecraft:jungle_ground_bush", @@ -55,21 +61,25 @@ "decorators": [], "base_height": 4 }, - "chance": 0.3 + "chance": 0.2 } ], "default": { - "name": "terraforged:jungle_small", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:jungle_small" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 6, - "extra_chance": 0.25, - "extra_count": 1 + "radius": 8, + "fade": 0.2, + "scale": 200, + "min": 0.35, + "max": 1.85 } } } diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_badlands.json b/src/main/resources/data/terraforged/features/trees/oak_badlands.json similarity index 73% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_badlands.json rename to src/main/resources/data/terraforged/features/trees/oak_badlands.json index 6166a24..a2eb50d 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_badlands.json +++ b/src/main/resources/data/terraforged/features/trees/oak_badlands.json @@ -19,14 +19,18 @@ "config": { "features": [ { - "name": "terraforged:oak_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_small" + }, "chance": 0.2 } ], "default": { - "name": "terraforged:oak_small", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_small" + } } } }, diff --git a/src/main/resources/data/terraforged/features/trees/oak_forest.json b/src/main/resources/data/terraforged/features/trees/oak_forest.json new file mode 100644 index 0000000..4881be2 --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/oak_forest.json @@ -0,0 +1,52 @@ +{ + "biomes": [ + "minecraft:forest" + ], + "match": [ + [ + "minecraft:oak_log", + "minecraft:oak_leaves" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "minecraft:random_selector", + "config": { + "features": [ + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_forest" + }, + "chance": 0.2 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_large" + }, + "chance": 0.3 + } + ], + "default": { + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_forest" + } + } + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 9, + "scale": 150, + "min": 0.15, + "max": 1.75 + } + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_plains.json b/src/main/resources/data/terraforged/features/trees/oak_plains.json similarity index 52% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_plains.json rename to src/main/resources/data/terraforged/features/trees/oak_plains.json index 777f214..ad4bd9f 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/oak_plains.json +++ b/src/main/resources/data/terraforged/features/trees/oak_plains.json @@ -1,19 +1,7 @@ { "biomes": [ "minecraft:plains", - "minecraft:sunflower_plains", - "minecraft:river", - "minecraft:frozen_river", - "minecraft:ocean", - "minecraft:deep_ocean", - "minecraft:warm_ocean", - "minecraft:deep_warm_ocean", - "minecraft:lukewarm_ocean", - "minecraft:deep_lukewarm_ocean", - "minecraft:cold_ocean", - "minecraft:deep_cold_ocean", - "minecraft:frozen_ocean", - "minecraft:deep_frozen_ocean" + "minecraft:river" ], "match": [ [ @@ -29,19 +17,25 @@ "config": { "features": [ { - "name": "terraforged:oak_huge", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_huge" + }, "chance": 0.1 }, { - "name": "terraforged:oak_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_small" + }, "chance": 0.2 } ], "default": { - "name": "terraforged:oak_small", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:oak_small" + } } } }, @@ -55,4 +49,4 @@ } } } -} +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/pine.json b/src/main/resources/data/terraforged/features/trees/pine.json similarity index 58% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/pine.json rename to src/main/resources/data/terraforged/features/trees/pine.json index 119dacf..f38787b 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/pine.json +++ b/src/main/resources/data/terraforged/features/trees/pine.json @@ -19,23 +19,29 @@ "config": { "features": [ { - "name": "terraforged:pine", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + }, "chance": 0.3 } ], "default": { - "name": "terraforged:pine", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 8, - "extra_chance": 0.1, - "extra_count": 1 + "radius": 10, + "fade": 0.25, + "scale": 250, + "min": 0.0, + "max": 2.75 } } } diff --git a/src/main/resources/data/terraforged/features/trees/redwood.json b/src/main/resources/data/terraforged/features/trees/redwood.json new file mode 100644 index 0000000..93b8260 --- /dev/null +++ b/src/main/resources/data/terraforged/features/trees/redwood.json @@ -0,0 +1,59 @@ +{ + "biomes": [ + "minecraft:*" + ], + "match": [ + [ + "minecraft:mega_spruce_tree" + ] + ], + "replace": { + "name": "minecraft:decorated", + "config": { + "feature": { + "name": "minecraft:random_selector", + "config": { + "features": [ + { + "name": "terraforged:template", + "config": { + "template": "terraforged:redwood_huge" + }, + "chance": 0.025641026 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + }, + "chance": 0.15 + }, + { + "name": "terraforged:template", + "config": { + "template": "terraforged:redwood_large" + }, + "chance": 0.33333334 + } + ], + "default": { + "name": "terraforged:template", + "config": { + "template": "terraforged:redwood_large" + } + } + } + }, + "decorator": { + "name": "terraforged:poisson_surface", + "config": { + "radius": 9, + "fade": 0.2, + "scale": 250, + "min": 0.15, + "max": 2.25 + } + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce.json b/src/main/resources/data/terraforged/features/trees/spruce.json similarity index 58% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce.json rename to src/main/resources/data/terraforged/features/trees/spruce.json index ff1b679..d8809db 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce.json +++ b/src/main/resources/data/terraforged/features/trees/spruce.json @@ -19,23 +19,29 @@ "config": { "features": [ { - "name": "terraforged:pine", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + }, "chance": 0.3 } ], "default": { - "name": "terraforged:pine", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + } } } }, "decorator": { - "name": "minecraft:count_extra_heightmap", + "name": "terraforged:poisson_surface", "config": { - "count": 8, - "extra_chance": 0.1, - "extra_count": 1 + "radius": 10, + "fade": 0.3, + "scale": 250, + "min": 0.15, + "max": 1.75 } } } diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce_tundra.json b/src/main/resources/data/terraforged/features/trees/spruce_tundra.json similarity index 72% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce_tundra.json rename to src/main/resources/data/terraforged/features/trees/spruce_tundra.json index b746237..cbb134f 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/spruce_tundra.json +++ b/src/main/resources/data/terraforged/features/trees/spruce_tundra.json @@ -18,14 +18,18 @@ "config": { "features": [ { - "name": "terraforged:pine", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + }, "chance": 0.3 } ], "default": { - "name": "terraforged:pine", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:pine" + } } } }, diff --git a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/willow.json b/src/main/resources/data/terraforged/features/trees/willow.json similarity index 64% rename from TerraForgedMod/src/main/resources/data/terraforged/features/trees/willow.json rename to src/main/resources/data/terraforged/features/trees/willow.json index ba31490..da35439 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/features/trees/willow.json +++ b/src/main/resources/data/terraforged/features/trees/willow.json @@ -19,19 +19,25 @@ "config": { "features": [ { - "name": "terraforged:willow_small", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:willow_small" + }, "chance": 0.2 }, { - "name": "terraforged:willow_large", - "config": {}, + "name": "terraforged:template", + "config": { + "template": "terraforged:willow_large" + }, "chance": 0.35 } ], "default": { - "name": "terraforged:willow_large", - "config": {} + "name": "terraforged:template", + "config": { + "template": "terraforged:willow_large" + } } } }, diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_7.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_mushroom_7.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_musroom_6.nbt b/src/main/resources/data/terraforged/structures/mushrooms/brown/brown_musroom_6.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt b/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_2.nbt b/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt b/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_4.nbt b/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt b/src/main/resources/data/terraforged/structures/mushrooms/red/red_mushroom_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/bush/acacia_bush_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/large/acacia_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/acacia/small/acacia_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_1.nbt b/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt b/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt b/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_4.nbt b/src/main/resources/data/terraforged/structures/trees/birch/forest/forest_birch_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt b/src/main/resources/data/terraforged/structures/trees/birch/large/birch_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/large/birch_2.nbt b/src/main/resources/data/terraforged/structures/trees/birch/large/birch_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt b/src/main/resources/data/terraforged/structures/trees/birch/large/birch_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt b/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt b/src/main/resources/data/terraforged/structures/trees/birch/small/birch_bush_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/birch/small/birch_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_1.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/large/dark_oak_tall_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_1.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_3.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt b/src/main/resources/data/terraforged/structures/trees/dark_oak/small/dark_oak_bush_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_1.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_2.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_5.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_6.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/huge/jungle_massive_6.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_2.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_3.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/large/jungle_tall_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_3.nbt b/src/main/resources/data/terraforged/structures/trees/jungle/small/jungle_small_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt b/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_2.nbt b/src/main/resources/data/terraforged/structures/trees/oak/forest/forest_oak_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt b/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_2.nbt b/src/main/resources/data/terraforged/structures/trees/oak/huge/oak_big_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/large/oak_1.nbt b/src/main/resources/data/terraforged/structures/trees/oak/large/oak_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/large/oak_2.nbt b/src/main/resources/data/terraforged/structures/trees/oak/large/oak_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/large/oak_3.nbt b/src/main/resources/data/terraforged/structures/trees/oak/large/oak_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/large/oak_4.nbt b/src/main/resources/data/terraforged/structures/trees/oak/large/oak_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt b/src/main/resources/data/terraforged/structures/trees/oak/large/oak_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_1.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_2.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_bush_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_3.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_4.nbt b/src/main/resources/data/terraforged/structures/trees/oak/small/oak_small_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_1.nbt b/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt b/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt b/src/main/resources/data/terraforged/structures/trees/pine/huangshan_pine_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt b/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_2.nbt b/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/pine/scots_pine_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_1.nbt b/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt b/src/main/resources/data/terraforged/structures/trees/pine/stone_pine_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_6.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/huge/redwood_massive_6.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_3.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt b/src/main/resources/data/terraforged/structures/trees/redwood/large/redwood_tall_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_1.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/bush/spruce_bush_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_3.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_4.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/large/spruce_5.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_3.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_3.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt b/src/main/resources/data/terraforged/structures/trees/spruce/small/spruce_small_4.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_1.nbt b/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt b/src/main/resources/data/terraforged/structures/trees/willow/large/weeping_willow_big_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt b/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_1.nbt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt b/src/main/resources/data/terraforged/structures/trees/willow/small/weeping_willow_small_2.nbt new file mode 100644 index 0000000..e69de29 diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/alpine.json b/src/main/resources/data/terraforged/tags/biomes/alpine.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/alpine.json rename to src/main/resources/data/terraforged/tags/biomes/alpine.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/cold_steppe.json b/src/main/resources/data/terraforged/tags/biomes/cold_steppe.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/cold_steppe.json rename to src/main/resources/data/terraforged/tags/biomes/cold_steppe.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/desert.json b/src/main/resources/data/terraforged/tags/biomes/desert.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/desert.json rename to src/main/resources/data/terraforged/tags/biomes/desert.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/grassland.json b/src/main/resources/data/terraforged/tags/biomes/grassland.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/grassland.json rename to src/main/resources/data/terraforged/tags/biomes/grassland.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/savanna.json b/src/main/resources/data/terraforged/tags/biomes/savanna.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/savanna.json rename to src/main/resources/data/terraforged/tags/biomes/savanna.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/steppe.json b/src/main/resources/data/terraforged/tags/biomes/steppe.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/steppe.json rename to src/main/resources/data/terraforged/tags/biomes/steppe.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/taiga.json b/src/main/resources/data/terraforged/tags/biomes/taiga.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/taiga.json rename to src/main/resources/data/terraforged/tags/biomes/taiga.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/temperate_forest.json b/src/main/resources/data/terraforged/tags/biomes/temperate_forest.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/temperate_forest.json rename to src/main/resources/data/terraforged/tags/biomes/temperate_forest.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/temperate_rainforest.json b/src/main/resources/data/terraforged/tags/biomes/temperate_rainforest.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/temperate_rainforest.json rename to src/main/resources/data/terraforged/tags/biomes/temperate_rainforest.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/tropical_rainforest.json b/src/main/resources/data/terraforged/tags/biomes/tropical_rainforest.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/tropical_rainforest.json rename to src/main/resources/data/terraforged/tags/biomes/tropical_rainforest.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/tundra.json b/src/main/resources/data/terraforged/tags/biomes/tundra.json similarity index 100% rename from TerraForgedMod/src/main/resources/data/terraforged/tags/biomes/tundra.json rename to src/main/resources/data/terraforged/tags/biomes/tundra.json diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_large.json b/src/main/resources/data/terraforged/templates/trees/acacia_large.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_large.json rename to src/main/resources/data/terraforged/templates/trees/acacia_large.json index 3d3c39b..4ef9117 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_large.json +++ b/src/main/resources/data/terraforged/templates/trees/acacia_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:acacia_large", "paths": [ "terraforged:trees/acacia/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_small.json b/src/main/resources/data/terraforged/templates/trees/acacia_small.json similarity index 67% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_small.json rename to src/main/resources/data/terraforged/templates/trees/acacia_small.json index 7fd1cab..9159f1d 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/acacia_small.json +++ b/src/main/resources/data/terraforged/templates/trees/acacia_small.json @@ -1,9 +1,12 @@ { "type": "tree", - "base": 3, "name": "terraforged:acacia_small", "paths": [ "terraforged:trees/acacia/small", "terraforged:trees/acacia/bush" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/src/main/resources/data/terraforged/templates/trees/birch_forest.json b/src/main/resources/data/terraforged/templates/trees/birch_forest.json new file mode 100644 index 0000000..ca616d7 --- /dev/null +++ b/src/main/resources/data/terraforged/templates/trees/birch_forest.json @@ -0,0 +1,23 @@ +{ + "type": "tree", + "name": "terraforged:birch_forest", + "paths": [ + "terraforged:trees/birch/forest" + ], + "config": { + "extend_base": 3, + "check_bounds": true + }, + "decorators": { + "default": { + "minecraft:beehive": { + "probability": 0.002 + } + }, + "minecraft:flower_forest": { + "minecraft:beehive": { + "probability": 0.02 + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/templates/trees/birch_large.json b/src/main/resources/data/terraforged/templates/trees/birch_large.json new file mode 100644 index 0000000..2dfd97e --- /dev/null +++ b/src/main/resources/data/terraforged/templates/trees/birch_large.json @@ -0,0 +1,23 @@ +{ + "type": "tree", + "name": "terraforged:birch_large", + "paths": [ + "terraforged:trees/birch/large" + ], + "config": { + "extend_base": 3, + "check_bounds": true + }, + "decorators": { + "default": { + "minecraft:beehive": { + "probability": 0.002 + } + }, + "minecraft:flower_forest": { + "minecraft:beehive": { + "probability": 0.02 + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/birch_small.json b/src/main/resources/data/terraforged/templates/trees/birch_small.json similarity index 59% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/birch_small.json rename to src/main/resources/data/terraforged/templates/trees/birch_small.json index 285f490..c5c80e0 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/birch_small.json +++ b/src/main/resources/data/terraforged/templates/trees/birch_small.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:birch_small", "paths": [ "terraforged:trees/birch/small" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/brown_mushroom.json b/src/main/resources/data/terraforged/templates/trees/brown_mushroom.json similarity index 68% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/brown_mushroom.json rename to src/main/resources/data/terraforged/templates/trees/brown_mushroom.json index 430485a..ea95b1d 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/brown_mushroom.json +++ b/src/main/resources/data/terraforged/templates/trees/brown_mushroom.json @@ -1,8 +1,10 @@ { "type": "tree", - "base": 0, "name": "terraforged:brown_mushroom", "paths": [ "terraforged:mushrooms/brown" - ] + ], + "config": { + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_large.json b/src/main/resources/data/terraforged/templates/trees/dark_oak_large.json similarity index 61% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_large.json rename to src/main/resources/data/terraforged/templates/trees/dark_oak_large.json index 0d08afb..a48e848 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_large.json +++ b/src/main/resources/data/terraforged/templates/trees/dark_oak_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:dark_oak_large", "paths": [ "terraforged:trees/dark_oak/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_small.json b/src/main/resources/data/terraforged/templates/trees/dark_oak_small.json similarity index 61% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_small.json rename to src/main/resources/data/terraforged/templates/trees/dark_oak_small.json index 1cab783..eb3b102 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/dark_oak_small.json +++ b/src/main/resources/data/terraforged/templates/trees/dark_oak_small.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:dark_oak_small", "paths": [ "terraforged:trees/dark_oak/small" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_huge.json b/src/main/resources/data/terraforged/templates/trees/jungle_huge.json similarity index 59% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_huge.json rename to src/main/resources/data/terraforged/templates/trees/jungle_huge.json index 9966e5b..c61262c 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_huge.json +++ b/src/main/resources/data/terraforged/templates/trees/jungle_huge.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:jungle_huge", "paths": [ "terraforged:trees/jungle/huge" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_large.json b/src/main/resources/data/terraforged/templates/trees/jungle_large.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_large.json rename to src/main/resources/data/terraforged/templates/trees/jungle_large.json index 2158117..47916e9 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_large.json +++ b/src/main/resources/data/terraforged/templates/trees/jungle_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:jungle_large", "paths": [ "terraforged:trees/jungle/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_small.json b/src/main/resources/data/terraforged/templates/trees/jungle_small.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_small.json rename to src/main/resources/data/terraforged/templates/trees/jungle_small.json index c242c73..31ce662 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/jungle_small.json +++ b/src/main/resources/data/terraforged/templates/trees/jungle_small.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:jungle_small", "paths": [ "terraforged:trees/jungle/small" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/src/main/resources/data/terraforged/templates/trees/oak_forest.json b/src/main/resources/data/terraforged/templates/trees/oak_forest.json new file mode 100644 index 0000000..5cca2a5 --- /dev/null +++ b/src/main/resources/data/terraforged/templates/trees/oak_forest.json @@ -0,0 +1,23 @@ +{ + "type": "tree", + "name": "terraforged:oak_forest", + "paths": [ + "terraforged:trees/oak/forest" + ], + "config": { + "extend_base": 3, + "check_bounds": true + }, + "decorators": { + "default": { + "minecraft:beehive": { + "probability": 0.002 + } + }, + "minecraft:flower_forest": { + "minecraft:beehive": { + "probability": 0.02 + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/templates/trees/oak_huge.json b/src/main/resources/data/terraforged/templates/trees/oak_huge.json new file mode 100644 index 0000000..05f1b54 --- /dev/null +++ b/src/main/resources/data/terraforged/templates/trees/oak_huge.json @@ -0,0 +1,23 @@ +{ + "type": "tree", + "name": "terraforged:oak_huge", + "paths": [ + "terraforged:trees/oak/huge" + ], + "config": { + "extend_base": 3, + "check_bounds": true + }, + "decorators": { + "default": { + "minecraft:beehive": { + "probability": 0.002 + } + }, + "minecraft:flower_forest": { + "minecraft:beehive": { + "probability": 0.02 + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/data/terraforged/templates/trees/oak_large.json b/src/main/resources/data/terraforged/templates/trees/oak_large.json new file mode 100644 index 0000000..ee09c8f --- /dev/null +++ b/src/main/resources/data/terraforged/templates/trees/oak_large.json @@ -0,0 +1,23 @@ +{ + "type": "tree", + "name": "terraforged:oak_large", + "paths": [ + "terraforged:trees/oak/large" + ], + "config": { + "extend_base": 3, + "check_bounds": true + }, + "decorators": { + "default": { + "minecraft:beehive": { + "probability": 0.002 + } + }, + "minecraft:flower_forest": { + "minecraft:beehive": { + "probability": 0.02 + } + } + } +} \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_small.json b/src/main/resources/data/terraforged/templates/trees/oak_small.json similarity index 58% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_small.json rename to src/main/resources/data/terraforged/templates/trees/oak_small.json index cbb9289..087b1ec 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/oak_small.json +++ b/src/main/resources/data/terraforged/templates/trees/oak_small.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:oak_small", "paths": [ "terraforged:trees/oak/small" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/pine.json b/src/main/resources/data/terraforged/templates/trees/pine.json similarity index 56% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/pine.json rename to src/main/resources/data/terraforged/templates/trees/pine.json index 8ec0f47..853e5ae 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/pine.json +++ b/src/main/resources/data/terraforged/templates/trees/pine.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:pine", "paths": [ "terraforged:trees/pine" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/red_mushroom.json b/src/main/resources/data/terraforged/templates/trees/red_mushroom.json similarity index 59% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/red_mushroom.json rename to src/main/resources/data/terraforged/templates/trees/red_mushroom.json index 6e7882b..d8ea62e 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/red_mushroom.json +++ b/src/main/resources/data/terraforged/templates/trees/red_mushroom.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 0, "name": "terraforged:red_mushroom", "paths": [ "terraforged:mushrooms/red" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_huge.json b/src/main/resources/data/terraforged/templates/trees/redwood_huge.json similarity index 85% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_huge.json rename to src/main/resources/data/terraforged/templates/trees/redwood_huge.json index f84b835..eb39293 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_huge.json +++ b/src/main/resources/data/terraforged/templates/trees/redwood_huge.json @@ -1,10 +1,13 @@ { "type": "tree", - "base": 3, "name": "terraforged:redwood_huge", "paths": [ "terraforged:trees/redwood/huge" ], + "config": { + "extend_base": 3, + "check_bounds": true + }, "decorators": { "minecraft:alter_ground": { "provider": { diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_large.json b/src/main/resources/data/terraforged/templates/trees/redwood_large.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_large.json rename to src/main/resources/data/terraforged/templates/trees/redwood_large.json index c9c829c..47b9690 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/redwood_large.json +++ b/src/main/resources/data/terraforged/templates/trees/redwood_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:redwood_large", "paths": [ "terraforged:trees/redwood/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_large.json b/src/main/resources/data/terraforged/templates/trees/spruce_large.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_large.json rename to src/main/resources/data/terraforged/templates/trees/spruce_large.json index 4738b7b..c11388b 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_large.json +++ b/src/main/resources/data/terraforged/templates/trees/spruce_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:spruce_large", "paths": [ "terraforged:trees/spruce/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_small.json b/src/main/resources/data/terraforged/templates/trees/spruce_small.json similarity index 67% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_small.json rename to src/main/resources/data/terraforged/templates/trees/spruce_small.json index 1e0c950..0ed96cf 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/spruce_small.json +++ b/src/main/resources/data/terraforged/templates/trees/spruce_small.json @@ -1,9 +1,12 @@ { "type": "tree", - "base": 3, "name": "terraforged:spruce_small", "paths": [ "terraforged:trees/spruce/small", "terraforged:trees/spruce/bush" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_large.json b/src/main/resources/data/terraforged/templates/trees/willow_large.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_large.json rename to src/main/resources/data/terraforged/templates/trees/willow_large.json index 467ae54..477b8b4 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_large.json +++ b/src/main/resources/data/terraforged/templates/trees/willow_large.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:willow_large", "paths": [ "terraforged:trees/willow/large" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_small.json b/src/main/resources/data/terraforged/templates/trees/willow_small.json similarity index 60% rename from TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_small.json rename to src/main/resources/data/terraforged/templates/trees/willow_small.json index 1de4946..8014327 100644 --- a/TerraForgedMod/src/main/resources/data/terraforged/templates/trees/willow_small.json +++ b/src/main/resources/data/terraforged/templates/trees/willow_small.json @@ -1,8 +1,11 @@ { "type": "tree", - "base": 3, "name": "terraforged:willow_small", "paths": [ "terraforged:trees/willow/small" - ] + ], + "config": { + "extend_base": 3, + "check_bounds": true + } } \ No newline at end of file diff --git a/TerraForgedAPI/src/main/resources/license.txt b/src/main/resources/license.txt similarity index 100% rename from TerraForgedAPI/src/main/resources/license.txt rename to src/main/resources/license.txt diff --git a/TerraForgedMod/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta similarity index 100% rename from TerraForgedMod/src/main/resources/pack.mcmeta rename to src/main/resources/pack.mcmeta diff --git a/TerraForgedMod/psd/terraforged.png b/src/main/resources/terraforged.png similarity index 100% rename from TerraForgedMod/psd/terraforged.png rename to src/main/resources/terraforged.png