-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.lua
541 lines (495 loc) · 15.7 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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
-- Another Map Generator for Minetest [amgmt]
-- by Muhammad Rifqi Priyo Susanto (srifqi)
-- License: CC0 1.0 Universal
-- Dependencies: default, flowers, bakedclay?
amgmt = {}
print("[amgmt] (Another Map Generator for Minetest)")
--param?
amgmt.DEBUG = false -- set to true if you want to get more info (all player will be noticed)
amgmt.wl = 0 -- water level
amgmt.HMAX = 1000 -- maximum height for the mapgen to generate
amgmt.HMIN = -30000 -- minimum height for the mapgen to generate
amgmt.BEDROCK = -30000 -- bedrock level
amgmt.spawn_radius = 5000 -- radius from center for a random spawn place (100 - 30000)
function amgmt.debug(text)
if amgmt.DEBUG == true then
print("[amgmt]: "..(text or ""))
minetest.chat_send_all("[amgmt]: "..(text or ""))
end
end
amgmt.biome = {}
amgmt.tree = {}
dofile(minetest.get_modpath(minetest.get_current_modname()).."/nodes.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/abm.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/trees.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/biomemgr.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/oremgr.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/mineshaft.lua")
minetest.register_on_mapgen_init(function(mgparams)
amgmt.seed = mgparams.seed
minetest.set_mapgen_params({mgname="singlenode", flags="nolight"})
end)
local function get_perlin_map(np, sidelen)
return minetest.get_perlin_map(
{offset=0, scale=1, spread={x=np.c, y=np.c, z=np.c}, seed=np.s, octaves=np.o, persist=np.p},
{x=sidelen, y=sidelen, z=sidelen}
)
end
-- noiseparam
amgmt.np = {
-- s = seed, o = octaves, p = persistance, c = scale
b = {s = 1234, o = 6, p = 0.5, c = 512}, -- base terrain
p = {s = 3333, o = 5, p = 0.5, c = 256}, -- plateau (flat at top)
t = {s = 5678, o = 3, p = 0.5, c = 512}, -- temperature
h = {s = 8765, o = 3, p = 0.5, c = 512}, -- humidity
l = {s = 1667, o = 6, p = 0.5, c = 256}, -- lake
c = {s = 1024, o = 7, p = 0.5, c = 512}, -- cave
d = {s = 2048, o = 7, p = 0.5, c = 512}, -- cave deepness
v_a = {s = 4848, o = 4, p = 0.5, c = 32}, -- 3d cave (a)
v_b = {s = 4816, o = 4, p = 0.5, c = 32}, -- 3d cave (b)
v_c = {s = -483, o = 4, p = 0.5, c = 32}, -- 3d cave (c)
v_d = {s = 4832, o = 4, p = 0.5, c = 32}, -- 3d cave (d)
}
local np = amgmt.np -- copy of noiseparam
--node id?
local gci = minetest.get_content_id
local c_air = gci("air")
local c_bedrock = gci("amgmt:bedrock")
local c_stone = gci("default:stone")
local c_dirt = gci("default:dirt")
local c_dirt_grass = gci("default:dirt_with_grass")
local c_dirt_snow = gci("default:dirt_with_snow")
local c_dirt_savanna = gci("amgmt:dirt_at_savanna")
local c_sand = gci("default:sand")
local c_sandstone = gci("default:sandstone")
local c_water = gci("default:water_source")
local c_lava_source = gci("default:lava_source")
function get_base(base, temp, humi, plat)
if base < amgmt.wl then return math.ceil(base) end
local base_ = base
local bwl = base - amgmt.wl
local plat = plat+1
local opt = 1/10 -- one per ten LOL
--river
if humi <= 52.5 and humi >= 47.5 then
if humi >= 50 then
base_ = amgmt.wl-(1-(humi-50)/2.5)*(base%3+1)-1
elseif humi <= 50 then
base_ = amgmt.wl-(1-(50-humi)/2.5)*(base%3+1)-1
end
--riverbank (canyon-like structure)
elseif humi < 55 and humi > 45 then
if plat > 0.25 and plat < 0.45 then
if humi >= 50 then
base_ = amgmt.wl+((humi-52.5)/2.5)*25
elseif humi <= 50 then
base_ = amgmt.wl+((47.5-humi)/2.5)*25
end
else
if humi >= 50 then
base_ = amgmt.wl+((humi-52.5)/2.5)*bwl
elseif humi <= 50 then
base_ = amgmt.wl+((47.5-humi)/2.5)*bwl
end
end
--plateau
elseif plat > 0.25 and plat < 0.45 then
base_ = amgmt.wl+25+(bwl/4%2)
--plateau edge
elseif plat > 0.25-opt and plat < 0.45+opt then
if plat >= 0.35 then
base_ = math.max(amgmt.wl+(1-(plat-0.45)/opt)*25,base)
elseif plat <= 0.35 then
base_ = math.max(amgmt.wl+(1-(0.25-plat)/opt)*25,base)
end
else
base_ = base
end
return math.ceil(base_)
end
local function distance2(x1,y1,x2,y2)
return ((x2-x1)^2+(y2-y1)^2)^0.5
end
local function distance3(x1,y1,z1,x2,y2,z2)
return ((x2-x1)^2+(y2-y1)^2+(z2-z1)^2)^0.5
end
local function build_cave_segment(x, y, z, data, area, shape, radius, deletednodes)
if shape == 1 then --sphere
for zz = -radius, radius do
for yy = -radius, radius do
for xx = -radius, radius do
local vi = area:index(x+xx,y+yy,z+zz)
local via = area:index(x+xx,y+yy+1,z+zz)
if
data[vi] == deletednodes and
distance3(x,y,z,x+xx,y+yy,z+zz) <= radius and
data[via] == deletednodes
then
data[vi] = c_air
end
end
end
end
elseif shape == 2 then --cube
for zz = -radius, radius do
for yy = -radius, radius do
for xx = -radius, radius do
local vi = area:index(x+xx,y+yy,z+zz)
local via = area:index(x+xx,y+yy+1,z+zz)
if data[vi] == deletednodes and data[via] == deletednodes then
data[vi] = c_air
end
end
end
end
elseif shape == 3 then --tube
for zz = -radius, radius do
for xx = -radius, radius do
if distance2(x,z,x+xx,z+zz) <= radius then
for yy = -radius, radius do
local vi = area:index(x+xx,y+yy,z+zz)
local via = area:index(x+xx,y+yy+1,z+zz)
if data[vi] == deletednodes and data[via] == deletednodes then
data[vi] = c_air
end
end
end
end
end
end
end
--loaded perlin noises
local pn = {}
local function amgmt_generate(minp, maxp, seed, vm, emin, emax)
local t1 = os.clock()
local pr = PseudoRandom(seed)
amgmt.debug(minp.x..","..minp.y..","..minp.z)
local area = VoxelArea:new{
MinEdge={x=emin.x, y=emin.y, z=emin.z},
MaxEdge={x=emax.x, y=emax.y, z=emax.z},
}
local data = vm:get_data()
--noise
local t2 = os.clock()
local sidelen = maxp.x - minp.x +1
-- make perlin map objects
if pn.base == nil then
pn.base = get_perlin_map(np.b, sidelen) -- base height
pn.plat = get_perlin_map(np.p, sidelen) -- plateau
pn.temp = get_perlin_map(np.t, sidelen) -- temperature (0-2)
pn.humi = get_perlin_map(np.h, sidelen) -- humidity (0-100)
pn.lake = get_perlin_map(np.l, sidelen) -- lake
pn.cave = {}
pn.deep = {}
for o = 1, 2 do
local cnp = np.c
cnp.s = cnp.s + o
pn.cave[o] = get_perlin_map(cnp, sidelen)
local dnp = np.d
dnp.s = dnp.s + o
pn.deep[o] = get_perlin_map(dnp, sidelen)
end
pn.cave3d = {
get_perlin_map(np.v_a, sidelen, true),
get_perlin_map(np.v_b, sidelen, true),
get_perlin_map(np.v_c, sidelen, true),
get_perlin_map(np.v_d, sidelen, true)
}
end
-- local noises
local minpxz = {x = minp.x, y = minp.z, z = 1}
local base = pn.base:get2dMap_flat(minpxz) -- base height
local plat = pn.plat:get2dMap_flat(minpxz) -- plateau
local temp = pn.temp:get2dMap_flat(minpxz) -- temperature (0-2)
local humi = pn.humi:get2dMap_flat(minpxz) -- humidity (0-100)
local lake = pn.humi:get2dMap_flat(minpxz) -- lake
local cave = {} -- list of caves
local deep = {} -- list of cave deepness
for o = 1, 2 do
cave[o] = pn.cave[o]:get2dMap_flat(minpxz)
deep[o] = pn.deep[o]:get2dMap_flat(minpxz)
end
local cave3d = {} -- list of 3d caves
for o = 1, 4 do
cave3d[o] = pn.cave3d[o]:get3dMap_flat(minp)
end
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("noise calculated - "..t3.."ms")
--terraforming
local t2 = os.clock()
local nizx = 1
local nizyx = 1
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
local base_ = math.ceil((base[nizx] * 25) + amgmt.wl)
local plat_ = plat[nizx]
local temp_ = math.abs(temp[nizx] * 2)
local humi_ = math.abs(humi[nizx] * 100)
base_ = get_base(base_, temp_, humi_, plat_)
for y_ = minp.y, maxp.y do
local vi = area:index(x,y_,z)
-- world height limit :(
if y_ <= amgmt.HMIN or y_ >= amgmt.HMAX then
-- air
elseif y_ == amgmt.BEDROCK then
data[vi] = c_bedrock
-- biome
else
if not ( -- if is not cave
cave3d[1][nizyx] ^ 2 +
cave3d[2][nizyx] ^ 2 +
cave3d[3][nizyx] ^ 2 +
cave3d[4][nizyx] ^ 2 < 0.072
) then
local node = amgmt.biome.get_block_by_temp_humi(
temp_, humi_, base_,
amgmt.wl, y_, x, z
)
if node ~= c_air then
data[vi] = node
end
end
end
nizyx = nizyx + sidelen
end
nizx = nizx + 1
nizyx = nizyx - sidelen * sidelen +1
end
nizyx = nizyx + sidelen * (sidelen-1)
end
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("terrain generated - "..t3.."ms")
--ore generation
local t2 = os.clock()
amgmt.ore.generate(minp, maxp, data, area, seed)
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("ore generated - "..t3.."ms")
--mineshaft construction
local t2 = os.clock()
amgmt.mineshaft.generate(minp, maxp, data, area, seed, pr, plat)
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("mineshaft constructed - "..t3.."ms")
--cave forming
local t2 = os.clock()
local nizx = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
nizx = nizx + 1
local base_ = math.ceil((base[nizx] * 25) + amgmt.wl)
for o = 1, 2 do
local cave_ = (cave[o][nizx]+1)/2
local deep_ = deep[o][nizx] * 45 - 25
if cave_ > 1-0.001 then
local y = math.floor(amgmt.wl + deep_)
local shape = (base_%3) + 1
build_cave_segment(x, y, z, data, area, shape, 1, c_stone)
build_cave_segment(x, y, z, data, area, shape, 1, c_dirt)
build_cave_segment(x, y, z, data, area, shape, 1, c_dirt_grass)
build_cave_segment(x, y, z, data, area, shape, 1, c_dirt_snow)
build_cave_segment(x, y, z, data, area, shape, 1, c_dirt_savanna)
build_cave_segment(x, y, z, data, area, shape, 1, c_sandstone)
build_cave_segment(x, y, z, data, area, shape, 1, c_sand)
--amgmt.debug("cave generated at:"..x..","..y..","..z)
end
end
end
end
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("cave generated - "..t3.."ms")
--forming lake
local t2 = os.clock()
local chulen = (maxp.x - minp.x + 1) / 16
local nizx = 0
for cz = 0, chulen-1 do
for cx = 0, chulen-1 do
-- for every chunk do
nizx = (cz*chulen + cx) * 16
local found_lake = false
for z = minp.z + cz*16 +3, minp.z + (cz+1)*16 -3 do -- +-3 for lake borders
if found_lake == true then break end
for x = minp.x + cx*16 +3, minp.x + (cx+1)*16 -3 do -- +-3 for lake borders
if found_lake == true then break end
nizx = nizx + 1
local base_ = math.ceil((base[nizx] * 25) + amgmt.wl)
local plat_ = plat[nizx]
local temp_ = math.abs(temp[nizx] * 2)
local humi_ = math.abs(humi[nizx] * 100)
base_ = get_base(base_, temp_, humi_, plat_)
local lake_ = math.abs(lake[nizx])
if lake_ < 0.0005 and base_ > 5 then
--amgmt.debug("lake found! "..x..","..base_..","..z.." ("..lake_..")")
found_lake = true
for u = -2, 2 do
for i = -2, 2 do
local vi = area:index(x+u,base_-2,z+i)
if pr:next(1,3) >= 2 then
data[vi] = c_sandstone
else
data[vi] = c_stone
end
for o = -1, 0 do
local vi = area:index(x+u,base_+o,z+i)
if u > -2 and u < 2 and i > -2 and i < 2 and o == 0 then
data[vi] = c_water
else
data[vi] = c_sand
end
end
for o = 1, 2 do
local vi = area:index(x+u,base_+o,z+i)
data[vi] = c_air
end
end
end
for ii = 1, 10 do
local xx = pr:next(-1,1)
local zz = pr:next(-1,1)
local vi = area:index(x+xx,base_-1,z+zz)
data[vi] = c_water
end
end
end
end
end
end
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("lake formed - "..t3.."ms")
--tree planting
local t2 = os.clock()
local nizx = 0
for z = minp.z, maxp.z do
for x = minp.x, maxp.x do
nizx = nizx + 1
local base_ = math.ceil((base[nizx] * 25) + amgmt.wl)
local plat_ = plat[nizx]
local temp_ = math.abs(temp[nizx] * 2)
local humi_ = math.abs(humi[nizx] * 100)
base_ = get_base(base_, temp_, humi_, plat_)
local biome__ = amgmt.biome.list[ amgmt.biome.get_by_temp_humi(temp_,humi_)[1] ]
local tr = biome__.trees
local filled = false
for i = 1, #tr do
if filled == true then break end
local tri = amgmt.tree.registered[ tr[i][1] ] or amgmt.tree.registered["nil"]
local chance = tr[i][2] or 1024
if
pr:next(1,chance) == 1 and
base_+1 >= tri.minh and base_+1 <= tri.maxh and
data[area:index(x,base_,z)] == gci(tri.grows_on)
then
amgmt.tree.spawn({x=x,y=base_+1,z=z},tr[i][1],data,area,seed,minp,maxp,pr)
filled = true
end
end
end
end
local t3 = math.ceil((os.clock() - t2) * 100000)/100
amgmt.debug("tree planted - "..t3.."ms")
amgmt.debug("applying map data")
vm:set_data(data)
vm:set_lighting({day=0, night=0})
vm:update_liquids()
vm:calc_lighting()
vm:write_to_map(data)
local chugent = math.ceil((os.clock() - t1) * 100000)/100
amgmt.debug("Done in "..chugent.."ms")
end
minetest.register_on_generated(function(minp, maxp, seed)
if minp.y > amgmt.HMAX or maxp.y < amgmt.HMIN then return end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
amgmt_generate(minp, maxp, seed, vm, emin, emax)
end)
local function amgmt_regenerate(pos, name)
minetest.chat_send_all("Regenerating "..name.."'s map chunk...")
local minp = {
x = 80*math.floor((pos.x+32)/80)-32,
y = 80*math.floor((pos.y+32)/80)-32,
z = 80*math.floor((pos.z+32)/80)-32
}
local maxp = {x = minp.x+79, y = minp.y+79, z = minp.z+79}
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(minp, maxp)
local data = {}
for i = 1, (maxp.x-minp.x+1)*(maxp.y-minp.y+1)*(maxp.z-minp.z+1) do
data[i] = c_air
end
vm:set_data(data)
vm:write_to_map()
amgmt_generate(minp, maxp, amgmt.seed or os.clock(), vm, emin, emax)
minetest.chat_send_player(name, "Regenerating done, fixing lighting. This may take a while...")
-- Fix lighting
local nodes = minetest.find_nodes_in_area(minp, maxp, "air")
local nnodes = #nodes
local p = math.floor(nnodes/5)
local dig_node = minetest.dig_node
for _, pos in ipairs(nodes) do
dig_node(pos)
if _%p == 0 then
minetest.chat_send_player(name, math.floor(_/nnodes*100).."%")
end
end
minetest.chat_send_all("Done")
end
minetest.register_chatcommand("amgmt_regenerate", {
privs = {server = true},
func = function(name, param)
local player = minetest.get_player_by_name(name)
if player then
local pos = player:getpos()
amgmt_regenerate(pos, name)
end
end,
})
local function amgmt_fixlight(pos, name)
minetest.chat_send_player(name, "Fixing lightning. This may take a while...")
local minp = {
x = 80*math.floor((pos.x+32)/80)-32,
y = 80*math.floor((pos.y+32)/80)-32,
z = 80*math.floor((pos.z+32)/80)-32
}
local maxp = {x = minp.x+79, y = minp.y+79, z = minp.z+79}
-- Fix lighting
local nodes = minetest.find_nodes_in_area(minp, maxp, "air")
local nnodes = #nodes
local p = math.floor(nnodes/5)
local dig_node = minetest.dig_node
for _, pos in ipairs(nodes) do
dig_node(pos)
if _%p == 0 then
minetest.chat_send_player(name, math.floor(_/nnodes*100).."%")
end
end
minetest.chat_send_all("Done")
end
minetest.register_chatcommand("amgmt_fixlight", {
privs = {server = true},
func = function(name, param)
local player = minetest.get_player_by_name(name)
if player then
local pos = player:getpos()
amgmt_fixlight(pos, name)
end
end,
})
dofile(minetest.get_modpath(minetest.get_current_modname()).."/hud.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/spawn.lua")
-- after all mods loaded, wait a second and print the statistics
minetest.after(1, function()
-- should we use this?
local function plural(n, singular, plural) return n < 2 and singular or plural end
print("[amgmt]:"..
(amgmt.tree.count-1).." ".. -- do not count nil tree!
plural(amgmt.tree.count-1, "tree", "trees")..
" registered"
)
print("[amgmt]:"..
#amgmt.biome.list.." "..
plural(#amgmt.biome.list, "biome", "biomes")..
" registered"
)
print("[amgmt]:"..
#amgmt.ore.registered.." "..
plural(#amgmt.ore.registered, "ore", "ores")..
" registered"
)
end)