-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
265 lines (217 loc) · 7.25 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
-- Far Glitch Land
-- MIT License
-- To change parameters, use the Settings menu.
----------------
-- Parameters --
----------------
local thickness = 80
local is_clean_gen = true
local height_min = -31000
local height_max = 31000
-------------------
-- Read settings --
-------------------
local thickness_setting = minetest.settings:get("fgl_thickness")
if thickness_setting ~= nil then
thickness = tonumber(thickness_setting)
end
if thickness <= 0 then
return -- Do nothing
end
is_clean_gen = minetest.settings:get_bool("fgl_clean_generation", false)
local height_min_setting = minetest.settings:get("fgl_min_height")
if height_min_setting ~= nil then
height_min = tonumber(height_min_setting)
end
local height_max_setting = minetest.settings:get("fgl_max_height")
if height_max_setting ~= nil then
height_max = tonumber(height_max_setting)
end
if height_max < height_min then
return -- Do nothing
end
-----------------------
-- Initial variables --
-----------------------
local edge_min, edge_max = minetest.get_mapgen_edges()
local chunksize = tonumber(minetest.get_mapgen_setting("chunksize"))
local sidelen = chunksize * 16 -- 16*16*16 nodes per chunk
local sidelen_v = {x = sidelen, y = sidelen, z = sidelen}
local water_level = tonumber(minetest.get_mapgen_setting("water_level"))
-- Land generation limits
thickness = thickness - 1 -- Offset by 1
local e_xmin = edge_min.x + thickness
local e_xmax = edge_max.x - thickness
local e_zmin = edge_min.z + thickness
local e_zmax = edge_max.z - thickness
local g_ymin = math.max(edge_min.y, height_min)
local g_ymax = math.min(edge_max.y, height_max)
-- Main noise
local spread_base = 3
local spread_mult_y = 2
local spread_mult_side = 32
local np_shape = {
offset = 0,
scale = 1,
spread = {x = spread_base, y = spread_base, z = spread_base},
seed = 40,
octaves = 1,
persistence = 0.5,
lacunarity = 2.0,
}
--------------------
-- Map generation --
--------------------
minetest.register_on_generated(function(minp, maxp, seed)
if minp.y > g_ymax and maxp.y < g_ymin and
minp.x > e_xmin and maxp.x < e_xmax and
minp.z > e_zmin and maxp.z < e_zmax then
return -- Do nothing
end
minetest.log("info", "far_glitch_land is generating | " ..
"minp: (" .. minp.x .. ", " .. minp.y .. ", " .. minp.z .. ") | " ..
"maxp: (" .. maxp.x .. ", " .. maxp.y .. ", " .. maxp.z .. ")")
-- Initial variables
local cid = minetest.get_content_id
local air_block = cid("air")
local stone_block = cid("mapgen_stone")
local water_block = cid("mapgen_water_source")
local pr = PseudoRandom(seed)
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local data = vm:get_data()
-- Noises
local p3d_shape_x = nil
local p3d_shape_z = nil
local p3d_shape_xz = nil
if minp.x <= e_xmin or maxp.x >= e_xmax then
np_shape.spread.x = spread_base * spread_mult_side
np_shape.spread.y = spread_base * spread_mult_y
np_shape.spread.z = spread_base
local pm_shape_x = minetest.get_perlin_map(np_shape, sidelen_v)
p3d_shape_x = pm_shape_x:get_3d_map_flat(minp)
end
if minp.z <= e_zmin or maxp.z >= e_zmax then
np_shape.spread.x = spread_base
np_shape.spread.y = spread_base * spread_mult_y
np_shape.spread.z = spread_base * spread_mult_side
local pm_shape_z = minetest.get_perlin_map(np_shape, sidelen_v)
p3d_shape_z = pm_shape_z:get_3d_map_flat(minp)
end
if (minp.x <= e_xmin or maxp.x >= e_xmax) and
(minp.z <= e_zmin or maxp.z >= e_zmax) then
np_shape.spread.x = spread_base * spread_mult_side
np_shape.spread.y = spread_base
np_shape.spread.z = spread_base * spread_mult_side
local pm_shape_xz = minetest.get_perlin_map(np_shape, sidelen_v)
p3d_shape_xz = pm_shape_xz:get_3d_map_flat(minp)
end
-- Main generation
local ni = 1
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
ni = ni + sidelen * (sidelen - 1)
if x <= e_xmin or x >= e_xmax or
z <= e_zmin or z >= e_zmax then
-- Read biome data
local biome_id = minetest.get_biome_data(vector.new(x, maxp.y, z))["biome"]
local biome_name = minetest.get_biome_name(biome_id)
local biome_data = minetest.registered_biomes[biome_name]
if biome_data == nil then
biome_data = {}
end
local block_top = stone_block
if biome_data["node_top"] ~= nil then
block_top = cid(biome_data["node_top"])
end
local depth_top = 0
if biome_data["depth_top"] ~= nil then
depth_top = biome_data["depth_top"]
end
local block_filler = stone_block
if biome_data["node_filler"] ~= nil then
block_filler = cid(biome_data["node_filler"])
end
local depth_filler = 0
if biome_data["depth_filler"] ~= nil then
depth_filler = biome_data["depth_filler"]
depth_filler = pr:next(0, depth_filler)
end
local block_riverbed = stone_block
if biome_data["node_riverbed"] ~= nil then
block_riverbed = cid(biome_data["node_riverbed"])
end
local depth_riverbed = 0
if biome_data["depth_riverbed"] ~= nil then
depth_riverbed = biome_data["depth_riverbed"]
end
local block_stone = stone_block
if biome_data["node_stone"] ~= nil then
block_stone = cid(biome_data["node_stone"])
end
-- Generation is run from top to bottom to make it easier when
-- placing land cover (block_top), below it (block_filler),
-- and stone (block_stone).
local last_air_block = maxp.y + sidelen * sidelen
local last_water_block = maxp.y + sidelen * sidelen
for y = maxp.y, minp.y, -1 do
local vi = area:index(x, y, z)
if y >= g_ymin and y <= g_ymax then
if is_clean_gen or
data[vi] == air_block or
data[vi] == stone_block or
data[vi] == water_block then
local value = 0
if (x <= e_xmin or x >= e_xmax) and
(z <= e_zmin or z >= e_zmax) then
value = p3d_shape_xz[ni] + 0.25 -- More air
elseif x <= e_xmin or x >= e_xmax then
value = p3d_shape_x[ni]
elseif z <= e_zmin or z >= e_zmax then
value = p3d_shape_z[ni]
end
if value <= 0 then -- Is solid
local dist_to_air = last_air_block - y
local dist_to_water = last_water_block - y
local depth_both = depth_filler + depth_top
if dist_to_air > depth_top and dist_to_air <= depth_both or
dist_to_water > depth_riverbed and dist_to_water <= depth_both then
data[vi] = block_filler
elseif dist_to_air > 0 and dist_to_air <= depth_top then
data[vi] = block_top
elseif dist_to_water > 0 and dist_to_water <= depth_riverbed then
data[vi] = block_riverbed
else
data[vi] = block_stone
end
elseif is_clean_gen then
if y > water_level then
data[vi] = air_block
else
data[vi] = water_block
end
end
end
end
if data[vi] == air_block then
last_air_block = y
elseif data[vi] == water_block then
last_water_block = y
end
ni = ni - sidelen
end -- For each y
else
ni = ni - sidelen * sidelen
end
ni = ni + sidelen + 1
end -- For each x
ni = ni + sidelen * (sidelen - 1)
end -- For each z
-- Decorations and ores
vm:set_data(data)
minetest.generate_decorations(vm)
minetest.generate_ores(vm)
vm:calc_lighting()
vm:write_to_map()
vm:update_liquids()
end)