Separate map projects and add reusable island and operator camera tools
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Deterministic floating-island columns, independent of any map or server.
|
||||
|
||||
Large contour harmonics shape the silhouette; correlated low-frequency fields
|
||||
shape the underside. Surface grading and gameplay layout belong to the caller.
|
||||
This is an offline geometry helper, not an additional MCP tool or live edit API.
|
||||
"""
|
||||
import math
|
||||
|
||||
|
||||
def smooth(value):
|
||||
value = max(0., min(1., value))
|
||||
return value * value * (3 - 2 * value)
|
||||
|
||||
|
||||
def hash_value(x, z, seed):
|
||||
n = (x * 374761393 + z * 668265263 + seed * 1442695041) & 0xffffffff
|
||||
n = ((n ^ (n >> 13)) * 1274126177) & 0xffffffff
|
||||
return (n ^ (n >> 16)) / 0xffffffff
|
||||
|
||||
|
||||
def noise(x, z, seed):
|
||||
x0, z0 = math.floor(x), math.floor(z)
|
||||
u, v = smooth(x - x0), smooth(z - z0)
|
||||
a = hash_value(x0, z0, seed) * (1 - u) + hash_value(x0 + 1, z0, seed) * u
|
||||
b = hash_value(x0, z0 + 1, seed) * (1 - u) + hash_value(x0 + 1, z0 + 1, seed) * u
|
||||
return a * (1 - v) + b * v
|
||||
|
||||
|
||||
def columns(cx, cz, radius_x, radius_z, surface_y, depth, seed, contour=.055):
|
||||
"""Return {(x,z): {bottom, top, radial}} with inclusive occupied Y ranges.
|
||||
|
||||
``radial`` is normalized distance from the warped boundary (0 centre,1 rim).
|
||||
The terrain is a connected solid below each top, with no inferred live air.
|
||||
Neighbouring columns have coherent variation; random per-block noise is left
|
||||
out deliberately. Integers give reproducible inclusive world coordinates.
|
||||
"""
|
||||
values = (radius_x, radius_z, depth, contour)
|
||||
if not all(math.isfinite(v) for v in values) or min(radius_x, radius_z, depth) <= 0 or not 0 <= contour <= .2:
|
||||
raise ValueError('Use positive finite radii/depth and contour in0..0.2')
|
||||
if any(type(v) is not int for v in (cx, cz, surface_y, seed)):
|
||||
raise ValueError('Centre, surface and seed must be integers')
|
||||
result = {}
|
||||
for x in range(math.floor(cx - radius_x * 1.3), math.ceil(cx + radius_x * 1.3) + 1):
|
||||
for z in range(math.floor(cz - radius_z * 1.3), math.ceil(cz + radius_z * 1.3) + 1):
|
||||
dx, dz = (x - cx) / radius_x, (z - cz) / radius_z
|
||||
angle = math.atan2(dz, dx)
|
||||
boundary = 1 + contour * (math.sin(3 * angle + seed * .07)
|
||||
+ .45 * math.sin(7 * angle - seed * .11))
|
||||
radial = math.hypot(dx, dz) / boundary
|
||||
if radial > 1:
|
||||
continue
|
||||
# A broad taper and coherent hanging buttresses give a recognisable
|
||||
# mass even when viewed in silhouette, before material decoration.
|
||||
taper = max(0., 1 - radial ** 1.55) ** .62
|
||||
buttress = .63 + .37 * noise(x / 7.5, z / 7.5, seed + 31)
|
||||
ribs = 2.5 * smooth(noise(x / 3.8, z / 3.8, seed + 57))
|
||||
thickness = max(3, round(3 + depth * taper * buttress + ribs))
|
||||
result[x, z] = {'top': surface_y, 'bottom': surface_y - thickness + 1,
|
||||
'radial': radial}
|
||||
return result
|
||||
Reference in New Issue
Block a user