XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

MyDimension

【Java】我的维度模组

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/MyDimension

完善空岛算法

f7d38aa
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

4 个文件 +408 -101
Modified build.gradle +16 -2
@@ -125,8 +125,22 @@ tasks.register('generatePlayerMindDimensions') {
125 125 generator: [
126 126 type : 'mydimension:soaring_islands',
127 127 biome_source: [
128 type : 'minecraft:multi_noise',
129 preset: 'minecraft:overworld'
128 type : 'minecraft:checkerboard',
129 biomes : [
130 'minecraft:plains',
131 'minecraft:forest',
132 'minecraft:flower_forest',
133 'minecraft:birch_forest',
134 'minecraft:meadow',
135 'minecraft:cherry_grove',
136 'minecraft:snowy_plains',
137 'minecraft:grove',
138 'minecraft:desert',
139 'minecraft:savanna',
140 'minecraft:jungle',
141 'minecraft:windswept_hills'
142 ],
143 scale : 3
130 144 ]
131 145 ]
132 146 ]
Modified src/main/java/com/xfestudio/mydimension/item/RiftItem.java +17 -29
@@ -3,6 +3,7 @@ package com.xfestudio.mydimension.item;
3 3 import com.xfestudio.mydimension.client.RiftClient;
4 4 import com.xfestudio.mydimension.world.MindInstances;
5 5 import com.xfestudio.mydimension.world.ModDimensions;
6 import com.xfestudio.mydimension.world.SoaringMindChunkGenerator;
6 7 import net.minecraft.core.BlockPos;
7 8 import net.minecraft.core.registries.Registries;
8 9 import net.minecraft.nbt.CompoundTag;
@@ -195,6 +196,13 @@ public class RiftItem extends Item {
195 196 yRot = mindPoint.yRot();
196 197 xRot = mindPoint.xRot();
197 198 }
199
200 if (ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(actualTargetDimension))) {
201 EntryPoint safe = safeEntryPoint(targetLevel, actualTargetDimension, x, z);
202 x = safe.x();
203 y = safe.y();
204 z = safe.z();
205 }
198 206 }
199 207
200 208 if (returningFromSelectedMind) {
@@ -217,12 +225,13 @@ public class RiftItem extends Item {
217 225 private static EntryPoint safeEntryPoint(ServerLevel level, ResourceKey<Level> dimension, double x, double z) {
218 226 int blockX = (int) Math.floor(x);
219 227 int blockZ = (int) Math.floor(z);
228 boolean soaringMind = ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(dimension));
220 229 int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockX, blockZ);
221 230 if (height > level.getMinBuildHeight()) {
222 return new EntryPoint(x, height + 1.0D, z);
231 return new EntryPoint(x, soaringMind ? height : height + 1.0D, z);
223 232 }
224 233
225 if (ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(dimension))) {
234 if (soaringMind) {
226 235 EntryPoint nearby = findNearbySurface(level, blockX, blockZ);
227 236 if (nearby != null) {
228 237 return nearby;
@@ -233,35 +242,14 @@ public class RiftItem extends Item {
233 242 }
234 243
235 244 private static EntryPoint findNearbySurface(ServerLevel level, int centerX, int centerZ) {
236 for (int radius = 8; radius <= 128; radius += 8) {
237 EntryPoint best = null;
238 int bestDistance = Integer.MAX_VALUE;
239 for (int dx = -radius; dx <= radius; dx += 8) {
240 for (int dz = -radius; dz <= radius; dz += 8) {
241 if (Math.abs(dx) != radius && Math.abs(dz) != radius) {
242 continue;
243 }
244
245 int x = centerX + dx;
246 int z = centerZ + dz;
247 int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z);
248 if (height <= level.getMinBuildHeight()) {
249 continue;
250 }
251
252 int distance = dx * dx + dz * dz;
253 if (distance < bestDistance) {
254 bestDistance = distance;
255 best = new EntryPoint(x + 0.5D, height + 1.0D, z + 0.5D);
256 }
257 }
258 }
259 if (best != null) {
260 return best;
261 }
245 BlockPos surface = SoaringMindChunkGenerator.findNearestSurface(centerX, centerZ, 768);
246 if (surface == null) {
247 return null;
262 248 }
263 249
264 return null;
250 int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, surface.getX(), surface.getZ());
251 double y = height > level.getMinBuildHeight() ? height : surface.getY();
252 return new EntryPoint(surface.getX() + 0.5D, y, surface.getZ() + 0.5D);
265 253 }
266 254
267 255 public static boolean sendToMind(ServerPlayer player, LivingEntity target, ItemStack stack, RiftAction action) {
Modified src/main/java/com/xfestudio/mydimension/world/SoaringMindChunkGenerator.java +359 -68
@@ -33,13 +33,23 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
33 33
34 34 private static final int MIN_Y = 0;
35 35 private static final int HEIGHT = 256;
36 private static final int CELL_SIZE = 144;
37 private static final int CELL_MARGIN = 48;
36 private static final int CELL_SIZE = 384;
37 private static final int CELL_MARGIN = 150;
38 38 private static final int NEIGHBOR_RADIUS = 2;
39 private static final double TWO_PI = Math.PI * 2.0D;
39 40 private static final BlockState AIR = Blocks.AIR.defaultBlockState();
40 41 private static final BlockState GRASS = Blocks.GRASS_BLOCK.defaultBlockState();
41 42 private static final BlockState DIRT = Blocks.DIRT.defaultBlockState();
42 43 private static final BlockState STONE = Blocks.STONE.defaultBlockState();
44 private static final BlockState WATER = Blocks.WATER.defaultBlockState();
45 private static final BlockState SAND = Blocks.SAND.defaultBlockState();
46 private static final BlockState SANDSTONE = Blocks.SANDSTONE.defaultBlockState();
47 private static final BlockState GRAVEL = Blocks.GRAVEL.defaultBlockState();
48 private static final BlockState SNOW_BLOCK = Blocks.SNOW_BLOCK.defaultBlockState();
49 private static final BlockState MOSS = Blocks.MOSS_BLOCK.defaultBlockState();
50 private static final BlockState PODZOL = Blocks.PODZOL.defaultBlockState();
51 private static final BlockState COARSE_DIRT = Blocks.COARSE_DIRT.defaultBlockState();
52 private static final BlockState CLAY = Blocks.CLAY.defaultBlockState();
43 53
44 54 public SoaringMindChunkGenerator(BiomeSource biomeSource) {
45 55 super(biomeSource, Util.memoize(holder -> holder.value().getGenerationSettings()));
@@ -81,13 +91,15 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
81 91 int x = minX + localX;
82 92 for (int localZ = 0; localZ < 16; localZ++) {
83 93 int z = minZ + localZ;
84 int topY = topIslandY(x, z);
85 if (topY < MIN_Y) {
94 IslandSlice slice = sliceAt(x, z);
95 if (slice == null) {
86 96 continue;
87 97 }
88 98
89 for (int y = MIN_Y; y <= topY; y++) {
90 BlockState state = blockStateAt(x, y, z, topY);
99 int minY = Math.max(slice.bottomY(), chunk.getMinBuildHeight());
100 int maxY = Math.min(slice.topY(), chunk.getMaxBuildHeight() - 1);
101 for (int y = minY; y <= maxY; y++) {
102 BlockState state = stateForY(x, y, z, slice);
91 103 if (state.isAir()) {
92 104 continue;
93 105 }
@@ -103,9 +115,15 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
103 115
104 116 @Override
105 117 public int getBaseHeight(int x, int z, Heightmap.Types heightmapType, LevelHeightAccessor heightAccessor, RandomState randomState) {
106 int topY = Math.min(topIslandY(x, z), heightAccessor.getMaxBuildHeight() - 1);
107 for (int y = topY; y >= heightAccessor.getMinBuildHeight(); y--) {
108 BlockState state = blockStateAt(x, y, z, topY);
118 IslandSlice slice = sliceAt(x, z);
119 if (slice == null) {
120 return heightAccessor.getMinBuildHeight();
121 }
122
123 int topY = Math.min(slice.topY(), heightAccessor.getMaxBuildHeight() - 1);
124 int bottomY = Math.max(slice.bottomY(), heightAccessor.getMinBuildHeight());
125 for (int y = topY; y >= bottomY; y--) {
126 BlockState state = stateForY(x, y, z, slice);
109 127 if (heightmapType.isOpaque().test(state)) {
110 128 return y + 1;
111 129 }
@@ -116,10 +134,10 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
116 134 @Override
117 135 public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor heightAccessor, RandomState randomState) {
118 136 BlockState[] states = new BlockState[heightAccessor.getHeight()];
119 int topY = topIslandY(x, z);
137 IslandSlice slice = sliceAt(x, z);
120 138 for (int index = 0; index < states.length; index++) {
121 139 int y = heightAccessor.getMinBuildHeight() + index;
122 states[index] = blockStateAt(x, y, z, topY);
140 states[index] = stateForY(x, y, z, slice);
123 141 }
124 142 return new NoiseColumn(heightAccessor.getMinBuildHeight(), states);
125 143 }
@@ -144,108 +162,311 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
144 162 info.add("Soaring Mind islands");
145 163 }
146 164
147 private static int topIslandY(int x, int z) {
148 int topY = -1;
149 int baseCellX = Math.floorDiv(x, CELL_SIZE);
150 int baseCellZ = Math.floorDiv(z, CELL_SIZE);
165 public static BlockPos findNearestSurface(int centerX, int centerZ, int maxRadius) {
166 BlockPos exact = surfaceAt(centerX, centerZ);
167 if (exact != null) {
168 return exact;
169 }
151 170
152 for (int cellX = baseCellX - NEIGHBOR_RADIUS; cellX <= baseCellX + NEIGHBOR_RADIUS; cellX++) {
153 for (int cellZ = baseCellZ - NEIGHBOR_RADIUS; cellZ <= baseCellZ + NEIGHBOR_RADIUS; cellZ++) {
154 Island island = islandFor(cellX, cellZ);
155 if (island == null) {
156 continue;
171 for (int radius = 4; radius <= maxRadius; radius += 4) {
172 BlockPos best = null;
173 int bestDistance = Integer.MAX_VALUE;
174 for (int offset = -radius; offset <= radius; offset += 4) {
175 best = closerSurface(centerX, centerZ, centerX + offset, centerZ - radius, best, bestDistance);
176 if (best != null) {
177 bestDistance = distanceSquared(centerX, centerZ, best.getX(), best.getZ());
157 178 }
158
159 double dx = (double) (x - island.x()) / island.radiusX();
160 double dz = (double) (z - island.z()) / island.radiusZ();
161 double horizontal = dx * dx + dz * dz;
162 if (horizontal > 1.0D) {
163 continue;
179 best = closerSurface(centerX, centerZ, centerX + offset, centerZ + radius, best, bestDistance);
180 if (best != null) {
181 bestDistance = distanceSquared(centerX, centerZ, best.getX(), best.getZ());
182 }
183 best = closerSurface(centerX, centerZ, centerX - radius, centerZ + offset, best, bestDistance);
184 if (best != null) {
185 bestDistance = distanceSquared(centerX, centerZ, best.getX(), best.getZ());
186 }
187 best = closerSurface(centerX, centerZ, centerX + radius, centerZ + offset, best, bestDistance);
188 if (best != null) {
189 bestDistance = distanceSquared(centerX, centerZ, best.getX(), best.getZ());
164 190 }
191 }
165 192
166 double edge = 1.0D - horizontal;
167 int surface = island.y() + (int) Math.round(Math.sqrt(edge) * island.height() * 0.42D);
168 surface += surfaceNoise(x, z, island.seed());
169 topY = Math.max(topY, surface);
193 if (best != null) {
194 return best;
170 195 }
171 196 }
172 197
173 return Math.min(topY, HEIGHT - 16);
198 return null;
174 199 }
175 200
176 private static BlockState blockStateAt(int x, int y, int z, int topY) {
177 if (topY < MIN_Y || y > topY || y < MIN_Y) {
178 return AIR;
201 private static BlockPos closerSurface(int centerX, int centerZ, int x, int z, BlockPos current, int currentDistance) {
202 BlockPos candidate = surfaceAt(x, z);
203 if (candidate == null) {
204 return current;
179 205 }
180 206
207 int distance = distanceSquared(centerX, centerZ, x, z);
208 return distance < currentDistance ? candidate : current;
209 }
210
211 private static int distanceSquared(int centerX, int centerZ, int x, int z) {
212 int dx = x - centerX;
213 int dz = z - centerZ;
214 return dx * dx + dz * dz;
215 }
216
217 private static BlockPos surfaceAt(int x, int z) {
218 IslandSlice slice = sliceAt(x, z);
219 if (slice == null || slice.hasWater()) {
220 return null;
221 }
222 return new BlockPos(x, slice.topY() + 1, z);
223 }
224
225 private static int topIslandY(int x, int z) {
226 IslandSlice slice = sliceAt(x, z);
227 return slice == null ? -1 : slice.topY();
228 }
229
230 private static IslandSlice sliceAt(int x, int z) {
231 IslandSlice best = null;
232 int topY = -1;
181 233 int baseCellX = Math.floorDiv(x, CELL_SIZE);
182 234 int baseCellZ = Math.floorDiv(z, CELL_SIZE);
183 boolean insideIsland = false;
184 235
185 for (int cellX = baseCellX - NEIGHBOR_RADIUS; cellX <= baseCellX + NEIGHBOR_RADIUS && !insideIsland; cellX++) {
236 for (int cellX = baseCellX - NEIGHBOR_RADIUS; cellX <= baseCellX + NEIGHBOR_RADIUS; cellX++) {
186 237 for (int cellZ = baseCellZ - NEIGHBOR_RADIUS; cellZ <= baseCellZ + NEIGHBOR_RADIUS; cellZ++) {
187 238 Island island = islandFor(cellX, cellZ);
188 239 if (island == null) {
189 240 continue;
190 241 }
191 242
192 int localTop = islandTopAt(x, z, island);
193 if (localTop < MIN_Y || y > localTop) {
243 double shape = islandShape(x, z, island);
244 if (shape > 1.0D) {
194 245 continue;
195 246 }
196 247
197 double dx = (double) (x - island.x()) / island.radiusX();
198 double dz = (double) (z - island.z()) / island.radiusZ();
199 double dy = (double) (y - island.y()) / island.height();
200 double taper = dx * dx + dz * dz + dy * dy * 1.35D;
201 if (taper <= 1.0D || y >= island.y() - 3) {
202 insideIsland = true;
203 break;
248 IslandSlice slice = islandSliceAt(x, z, island, shape);
249 if (slice.topY() > topY) {
250 topY = slice.topY();
251 best = slice;
204 252 }
205 253 }
206 254 }
207 255
208 if (!insideIsland) {
256 return best;
257 }
258
259 private static IslandSlice islandSliceAt(int x, int z, Island island, double shape) {
260 int landTop = islandTopAt(x, z, island, shape);
261 int solidTop = landTop;
262 int waterTop = -1;
263 double lakeShape = lakeShape(x, z, island, shape);
264
265 if (lakeShape < 1.0D) {
266 int depression = 2 + (int) Math.round((1.0D - lakeShape) * 4.0D);
267 waterTop = Math.min(island.waterY(), landTop - 1);
268 solidTop = Math.min(waterTop - 1, landTop - depression);
269 }
270
271 int bottomY = islandBottomAt(x, z, island, shape, landTop);
272 return new IslandSlice(waterTop >= 0 ? waterTop : landTop, bottomY, solidTop, waterTop, island);
273 }
274
275 private static BlockState stateForY(int x, int y, int z, IslandSlice slice) {
276 if (slice == null || y < slice.bottomY() || y > slice.topY()) {
209 277 return AIR;
210 278 }
211 if (y == topY) {
212 return GRASS;
279 if (slice.hasWater() && y > slice.solidTopY() && y <= slice.waterTopY()) {
280 return WATER;
281 }
282 if (y == slice.solidTopY()) {
283 return slice.hasWater() ? lakeBedState(slice.island().theme()) : surfaceState(x, z, slice.island());
213 284 }
214 if (y >= topY - 4) {
215 return DIRT;
285 if (y >= slice.solidTopY() - 4) {
286 return subsurfaceState(slice.island().theme());
216 287 }
217 return STONE;
288 return fillerState(slice.island().theme());
289 }
290
291 private static double islandShape(int x, int z, Island island) {
292 double rawX = x - island.x();
293 double rawZ = z - island.z();
294 double cos = Math.cos(island.angle());
295 double sin = Math.sin(island.angle());
296 double dx = (rawX * cos + rawZ * sin) / island.radiusX();
297 double dz = (-rawX * sin + rawZ * cos) / island.radiusZ();
298 double angle = Math.atan2(dz, dx);
299 double distance = Math.sqrt(dx * dx + dz * dz);
300 double boundary = 1.0D;
301 boundary += 0.18D * Math.sin(angle * 2.0D + phase(island.seed(), 10));
302 boundary += 0.13D * Math.sin(angle * 4.0D + phase(island.seed(), 11));
303 boundary += 0.08D * Math.sin(angle * 7.0D + phase(island.seed(), 12));
304 boundary += 0.05D * Math.sin(angle * 11.0D + phase(island.seed(), 13));
305 boundary += smoothNoise(x, z, island.seed() ^ 0x31C5E0DADDL, 42) * 0.12D;
306 boundary += smoothNoise(x, z, island.seed() ^ 0x6A09E667F3BCC909L, 22) * 0.06D;
307 return distance / Math.max(0.62D, boundary);
308 }
309
310 private static int islandTopAt(int x, int z, Island island, double shape) {
311 double edgeDrop = smoothStep(0.94D, 1.0D, shape);
312 int surface = island.y() - (int) Math.round(edgeDrop * island.edgeDrop());
313 surface += surfaceNoise(x, z, island.seed());
314 return Math.min(Math.max(surface, MIN_Y + 8), HEIGHT - 16);
218 315 }
219 316
220 private static int islandTopAt(int x, int z, Island island) {
221 double dx = (double) (x - island.x()) / island.radiusX();
222 double dz = (double) (z - island.z()) / island.radiusZ();
223 double horizontal = dx * dx + dz * dz;
224 if (horizontal > 1.0D) {
225 return -1;
317 private static int islandBottomAt(int x, int z, Island island, double shape, int topY) {
318 double cone = Math.max(0.0D, 1.0D - shape);
319 double tip = 1.0D - smoothStep(0.0D, 0.20D, shape);
320 int thickness = island.edgeThickness() + (int) Math.round(island.height() * cone + island.tipDepth() * tip);
321 int underside = topY - thickness + undersideNoise(x, z, island.seed());
322 return Math.max(MIN_Y, underside);
323 }
324
325 private static double lakeShape(int x, int z, Island island, double islandShape) {
326 if (!island.hasLake() || islandShape > 0.66D) {
327 return 2.0D;
226 328 }
227 double edge = 1.0D - horizontal;
228 return island.y() + (int) Math.round(Math.sqrt(edge) * island.height() * 0.42D) + surfaceNoise(x, z, island.seed());
329
330 double dx = (double) (x - island.lakeX()) / island.lakeRadiusX();
331 double dz = (double) (z - island.lakeZ()) / island.lakeRadiusZ();
332 return dx * dx + dz * dz;
229 333 }
230 334
231 335 private static Island islandFor(int cellX, int cellZ) {
232 336 long seed = mix(cellX, cellZ);
233 if (randomUnit(seed) > 0.72D) {
337 if (randomUnit(seed) > 0.86D) {
234 338 return null;
235 339 }
236 340
341 IslandTheme theme = IslandTheme.values()[randomInt(seed, 14, IslandTheme.values().length)];
237 342 int centerX = cellX * CELL_SIZE + CELL_MARGIN + randomInt(seed, 0, CELL_SIZE - CELL_MARGIN * 2);
238 343 int centerZ = cellZ * CELL_SIZE + CELL_MARGIN + randomInt(seed, 1, CELL_SIZE - CELL_MARGIN * 2);
239 int centerY = 78 + randomInt(seed, 2, 76);
240 int radiusX = 16 + randomInt(seed, 3, 32);
241 int radiusZ = 16 + randomInt(seed, 4, 32);
242 int height = 10 + randomInt(seed, 5, 24);
243 return new Island(centerX, centerY, centerZ, radiusX, radiusZ, height, seed);
344 IslandSize size = islandSize(seed);
345 int centerY = 82 + randomInt(seed, 2, 72);
346 int radiusX = size.minRadius() + randomInt(seed, 3, size.radiusRange());
347 int radiusZ = size.minRadius() + randomInt(seed, 4, size.radiusRange());
348 if (randomUnit(seed + 17) > 0.52D) {
349 radiusX += size.stretch() + randomInt(seed, 18, Math.max(1, size.stretch() + 1));
350 } else if (randomUnit(seed + 19) > 0.52D) {
351 radiusZ += size.stretch() + randomInt(seed, 20, Math.max(1, size.stretch() + 1));
352 }
353 int height = size.minHeight() + randomInt(seed, 5, size.heightRange());
354 int edgeDrop = randomInt(seed, 6, 3);
355 int edgeThickness = 2 + randomInt(seed, 7, 2);
356 double angle = phase(seed, 9);
357 int tipDepth = size.tipDepth() + randomInt(seed, 8, Math.max(1, size.tipDepth() / 2));
358 boolean hasLake = size.allowsLake() && theme != IslandTheme.ROCKY && randomUnit(seed + 21) < lakeChance(theme);
359 int lakeX = centerX + randomInt(seed, 22, Math.max(1, radiusX)) - radiusX / 2;
360 int lakeZ = centerZ + randomInt(seed, 23, Math.max(1, radiusZ)) - radiusZ / 2;
361 int lakeRadiusX = Math.max(4, radiusX / 8) + randomInt(seed, 24, Math.max(1, Math.min(18, radiusX / 4)));
362 int lakeRadiusZ = Math.max(4, radiusZ / 8) + randomInt(seed, 25, Math.max(1, Math.min(18, radiusZ / 4)));
363 int waterY = centerY - 1 + randomInt(seed, 26, 3) - 1;
364 return new Island(centerX, centerY, centerZ, radiusX, radiusZ, height, edgeDrop, edgeThickness,
365 tipDepth, angle, theme, hasLake, lakeX, lakeZ, lakeRadiusX, lakeRadiusZ, waterY, seed);
366 }
367
368 private static IslandSize islandSize(long seed) {
369 int roll = randomInt(seed, 27, 100);
370 if (roll < 18) {
371 return IslandSize.TINY;
372 }
373 if (roll < 46) {
374 return IslandSize.SMALL;
375 }
376 if (roll < 80) {
377 return IslandSize.MEDIUM;
378 }
379 return IslandSize.LARGE;
380 }
381
382 private static double lakeChance(IslandTheme theme) {
383 return switch (theme) {
384 case LUSH -> 0.72D;
385 case PLAINS, FOREST -> 0.48D;
386 case SNOWY -> 0.34D;
387 case DESERT -> 0.20D;
388 case ROCKY -> 0.0D;
389 };
390 }
391
392 private static BlockState surfaceState(int x, int z, Island island) {
393 return switch (island.theme()) {
394 case LUSH -> smoothNoise(x, z, island.seed() ^ 0x94D049BB133111EBL, 18) > 0.18D ? MOSS : GRASS;
395 case FOREST -> smoothNoise(x, z, island.seed() ^ 0x2545F4914F6CDD1DL, 20) > 0.25D ? PODZOL : GRASS;
396 case DESERT -> SAND;
397 case SNOWY -> SNOW_BLOCK;
398 case ROCKY -> smoothNoise(x, z, island.seed() ^ 0xD6E8FEB86659FD93L, 16) > 0.10D ? GRAVEL : STONE;
399 case PLAINS -> smoothNoise(x, z, island.seed() ^ 0xBF58476D1CE4E5B9L, 24) > 0.42D ? COARSE_DIRT : GRASS;
400 };
401 }
402
403 private static BlockState lakeBedState(IslandTheme theme) {
404 return switch (theme) {
405 case DESERT -> SAND;
406 case ROCKY -> GRAVEL;
407 case SNOWY -> CLAY;
408 case LUSH, FOREST, PLAINS -> CLAY;
409 };
410 }
411
412 private static BlockState subsurfaceState(IslandTheme theme) {
413 return switch (theme) {
414 case DESERT -> SANDSTONE;
415 case ROCKY -> STONE;
416 case SNOWY, LUSH, FOREST, PLAINS -> DIRT;
417 };
418 }
419
420 private static BlockState fillerState(IslandTheme theme) {
421 return switch (theme) {
422 case DESERT -> SANDSTONE;
423 default -> STONE;
424 };
244 425 }
245 426
246 427 private static int surfaceNoise(int x, int z, long seed) {
247 long mixed = mix(x + (int) seed, z - (int) (seed >>> 32));
248 return randomInt(mixed, 0, 5) - 2;
428 return (int) Math.round(smoothNoise(x, z, seed ^ 0xA24BAED4963EE407L, 48) * 1.2D
429 + smoothNoise(x, z, seed ^ 0x9FB21C651E98DF25L, 96) * 1.4D);
430 }
431
432 private static int undersideNoise(int x, int z, long seed) {
433 return (int) Math.round(smoothNoise(x, z, seed ^ 0xC2B2AE3D27D4EB4FL, 42) * 1.4D);
434 }
435
436 private static double smoothNoise(int x, int z, long seed, int scale) {
437 int cellX = Math.floorDiv(x, scale);
438 int cellZ = Math.floorDiv(z, scale);
439 double localX = (double) (x - cellX * scale) / scale;
440 double localZ = (double) (z - cellZ * scale) / scale;
441 double sx = fade(localX);
442 double sz = fade(localZ);
443
444 double v00 = randomSigned(seed, cellX, cellZ);
445 double v10 = randomSigned(seed, cellX + 1, cellZ);
446 double v01 = randomSigned(seed, cellX, cellZ + 1);
447 double v11 = randomSigned(seed, cellX + 1, cellZ + 1);
448 return lerp(lerp(v00, v10, sx), lerp(v01, v11, sx), sz);
449 }
450
451 private static double randomSigned(long seed, int x, int z) {
452 return randomUnit(seed + mix(x, z)) * 2.0D - 1.0D;
453 }
454
455 private static double smoothStep(double edge0, double edge1, double value) {
456 double t = Math.max(0.0D, Math.min(1.0D, (value - edge0) / (edge1 - edge0)));
457 return t * t * (3.0D - 2.0D * t);
458 }
459
460 private static double fade(double value) {
461 return value * value * value * (value * (value * 6.0D - 15.0D) + 10.0D);
462 }
463
464 private static double lerp(double a, double b, double t) {
465 return a + (b - a) * t;
466 }
467
468 private static double phase(long seed, int salt) {
469 return randomUnit(seed + salt * 0x632BE59BD9B4E019L) * TWO_PI;
249 470 }
250 471
251 472 private static int randomInt(long seed, int salt, int bound) {
@@ -269,6 +490,76 @@ public class SoaringMindChunkGenerator extends ChunkGenerator {
269 490 return value;
270 491 }
271 492
272 private record Island(int x, int y, int z, int radiusX, int radiusZ, int height, long seed) {
493 private enum IslandTheme {
494 PLAINS,
495 FOREST,
496 LUSH,
497 DESERT,
498 SNOWY,
499 ROCKY
500 }
501
502 private enum IslandSize {
503 TINY(4, 8, 8, 10, 4, 5, false),
504 SMALL(11, 15, 14, 16, 8, 8, true),
505 MEDIUM(28, 34, 34, 28, 16, 18, true),
506 LARGE(58, 60, 58, 42, 30, 34, true);
507
508 private final int minRadius;
509 private final int radiusRange;
510 private final int minHeight;
511 private final int heightRange;
512 private final int stretch;
513 private final int tipDepth;
514 private final boolean allowsLake;
515
516 IslandSize(int minRadius, int radiusRange, int minHeight, int heightRange, int stretch, int tipDepth, boolean allowsLake) {
517 this.minRadius = minRadius;
518 this.radiusRange = radiusRange;
519 this.minHeight = minHeight;
520 this.heightRange = heightRange;
521 this.stretch = stretch;
522 this.tipDepth = tipDepth;
523 this.allowsLake = allowsLake;
524 }
525
526 private int minRadius() {
527 return minRadius;
528 }
529
530 private int radiusRange() {
531 return radiusRange;
532 }
533
534 private int minHeight() {
535 return minHeight;
536 }
537
538 private int heightRange() {
539 return heightRange;
540 }
541
542 private int stretch() {
543 return stretch;
544 }
545
546 private int tipDepth() {
547 return tipDepth;
548 }
549
550 private boolean allowsLake() {
551 return allowsLake;
552 }
553 }
554
555 private record Island(int x, int y, int z, int radiusX, int radiusZ, int height, int edgeDrop,
556 int edgeThickness, int tipDepth, double angle, IslandTheme theme, boolean hasLake,
557 int lakeX, int lakeZ, int lakeRadiusX, int lakeRadiusZ, int waterY, long seed) {
558 }
559
560 private record IslandSlice(int topY, int bottomY, int solidTopY, int waterTopY, Island island) {
561 private boolean hasWater() {
562 return waterTopY >= 0;
563 }
273 564 }
274 565 }
Modified src/main/resources/data/mydimension/dimension/soaring_mind.json +16 -2
@@ -3,8 +3,22 @@
3 3 "generator": {
4 4 "type": "mydimension:soaring_islands",
5 5 "biome_source": {
6 "type": "minecraft:multi_noise",
7 "preset": "minecraft:overworld"
6 "type": "minecraft:checkerboard",
7 "biomes": [
8 "minecraft:plains",
9 "minecraft:forest",
10 "minecraft:flower_forest",
11 "minecraft:birch_forest",
12 "minecraft:meadow",
13 "minecraft:cherry_grove",
14 "minecraft:snowy_plains",
15 "minecraft:grove",
16 "minecraft:desert",
17 "minecraft:savanna",
18 "minecraft:jungle",
19 "minecraft:windswept_hills"
20 ],
21 "scale": 3
8 22 }
9 23 }
10 24 }