-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathinit.lua
352 lines (269 loc) · 8.27 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
-- Copyright 2015 Eduardo Mezêncio
---------------
-- Constants --
---------------
local modname = "em_dungeon_gen"
local roomsize = 6
local halfrs = math.floor(roomsize / 2)
local wallarea = (roomsize + 1) * (roomsize - 1)
local pit_floors_min, pit_floors_max = 4, 8
local pit_layer_size = pit_floors_max * roomsize
----------------------
-- Helper Functions --
----------------------
local function chance(num, den)
return (math.random(den) <= num)
end
---------------
-- Materials --
---------------
local c_air = minetest.get_content_id("air")
local c_cobble = minetest.get_content_id("default:cobble")
local c_mossycobble = minetest.get_content_id("default:mossycobble")
local c_torch = minetest.get_content_id("default:torch")
local c_bar_ns = minetest.get_content_id("xpanes:bar_5")
local c_bar_ew = minetest.get_content_id("xpanes:bar_10")
local function c_wall()
if chance(1,2) then
return c_cobble
else
return c_mossycobble
end
end
local schematic_stairs = minetest.get_modpath(modname).."/schems/stairs.mts"
------------------
-- Change Spawn --
------------------
local spawn_x, spawn_y, spawn_z = halfrs, 1, halfrs
minetest.register_on_newplayer(function(player)
player:setpos({x = spawn_x, y = spawn_y, z = spawn_z})
end)
minetest.register_on_respawnplayer(function(player)
player:setpos({x = spawn_x, y = spawn_y, z = spawn_z})
return true
end)
-------------------------
-- Map Generation Init --
-------------------------
local mapseed
minetest.register_on_mapgen_init(function(mgparams)
if mgparams.mgname ~= "singlenode" then
minetest.set_mapgen_params({mgname="singlenode"})
end
mapseed = minetest.get_mapgen_params().seed
end)
--------------------
-- Map Generation --
--------------------
minetest.register_on_generated(function(minp, maxp, blockseed)
-- just for now, so that you can take a look from above :)
if minp.y > 0 then return end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local data = vm:get_data()
local x_step = va:index(1,0,0) - va:index(0,0,0)
local y_step = va:index(0,1,0) - va:index(0,0,0)
local z_step = va:index(0,0,1) - va:index(0,0,0)
-------------------
-- Floor/Ceiling --
-------------------
math.randomseed(minp.x + minp.y^2 + minp.z^3)
for y = minp.y, maxp.y do
if y % roomsize == 0 then
for z = minp.z, maxp.z do
local index = va:index(minp.x, y, z)
for x = minp.x, maxp.x do
data[index] = c_wall()
index = index + x_step
end
end
end
end
-- I'm subtracting roomsize at the end here so that each chunk also
-- 'generates' one room outside of it. The reason is to build correctly
-- things that are in the block borders
local minx, miny, minz = minp.x, minp.y, minp.z
if minx % roomsize ~= 0 then minx = minx - (minx % roomsize) - roomsize end
if miny % roomsize ~= 0 then miny = miny - (miny % roomsize) - roomsize end
if minz % roomsize ~= 0 then minz = minz - (minz % roomsize) - roomsize end
------------------------------
-- Walls, Doors and Torches --
------------------------------
local doors, next_door = {}, 1
local stairs, next_stairs = {}, 1
local function place_stuff(x, y, z, ns)
-----------
-- Walls --
-----------
if chance(3,4) then
local xval, zval, step
local rect = {b = math.max(minp.y, y + 1),
t = math.min(maxp.y, y + roomsize - 1)}
if ns then
rect.l = math.max(minp.x, x)
rect.r = math.min(maxp.x, x + roomsize)
xval = rect.l
zval = z
step = x_step
else
rect.l = math.max(minp.z, z)
rect.r = math.min(maxp.z, z + roomsize)
xval = x
zval = rect.l
step = z_step
end
local wallnodes = 0
for yval = rect.b, rect.t do
local index = va:index(xval, yval, zval)
for x_or_z = rect.l, rect.r do
data[index] = c_wall()
wallnodes = wallnodes + 1
index = index + step
end
end
-- This will hopefully ensure that the random number
-- generator is always in the same "position" after
-- generating the wall
while wallnodes < wallarea do
math.random()
wallnodes = wallnodes + 1
end
-----------
-- Doors --
-----------
if chance(1,2) then
local coord = {x = x, y = y + 2, z = z}
if ns then coord.x = coord.x + halfrs
else coord.z = coord.z + halfrs end
-- Portal --
if va:contains(coord.x, coord.y, coord.z) then
data[va:index(coord.x, coord.y, coord.z)] = c_air end
coord.y = coord.y - 1
if va:contains(coord.x, coord.y, coord.z) then
data[va:index(coord.x, coord.y, coord.z)] = c_air end
-- Door (generated later) --
if chance(1,2) then
doors[next_door] = {x=coord.x, y=coord.y, z=coord.z, ns=ns}
next_door = next_door + 1
end
else
if chance(1,2) then
local c_bar
local coord = {x = x, y = y + 2, z = z}
if ns then
coord.x = coord.x + halfrs
c_bar = c_bar_ns
else
coord.z = coord.z + halfrs
c_bar = c_bar_ew
end
-- Window --
if va:contains(coord.x, coord.y, coord.z) then
data[va:index(coord.x, coord.y, coord.z)] = c_bar
end
end
end
end
end
for y=miny, maxp.y, roomsize do
for z=minz, maxp.z, roomsize do
for x=minx, maxp.x, roomsize do
math.randomseed(x + y^2 + z^3)
-- Stairs (generated later)
if chance(1, 128) then
stairs[next_stairs] = {x = x, y = y, z = z,
dir = math.random(0,3)}
next_stairs = next_stairs + 1
else
place_stuff(x, y, z, true) -- along the x axis
place_stuff(x, y, z, false) -- along the z axix
-------------
-- Torches --
-------------
if chance(1,8) then
local coord = {x = x + halfrs,
y = y + roomsize - 1,
z = z + halfrs}
if va:contains(coord.x, coord.y, coord.z) then
data[va:index(coord.x, coord.y, coord.z)] = c_torch
end
end
end
end
end
end
----------
-- Pits --
----------
local block_depth = maxp.y - minp.y + 1
local pit_layers = math.ceil(block_depth / pit_layer_size) + 2
local first_pit_layer = minp.y - (minp.y % pit_layer_size) - pit_layer_size
local y = first_pit_layer
for layer_count = 1, pit_layers do
for z=minz, maxp.z, roomsize do
for x=minx, maxp.x, roomsize do
math.randomseed(x + y^2 + z^3)
if chance(1, 128) then
local start = math.random(1, pit_floors_max)
local size = math.random(pit_floors_min, pit_floors_max)
local yy = y + start * roomsize
for floor_count = 1, size do
-- Remove torches
if va:contains(x + halfrs, yy - 1, z + halfrs) then
data[va:index(x + halfrs, yy - 1, z + halfrs)] = c_air
end
if yy > maxp.y then break end
if yy >= minp.y then
for zz = math.max(minp.z, z + 1), math.min(maxp.x, z + roomsize - 1) do
local startx = math.max(minp.x, x + 1)
local index = va:index(startx, yy, zz)
for xx = startx, math.min(maxp.x, x + roomsize - 1) do
data[index] = c_air
index = index + x_step
end
end
end
yy = yy + roomsize
end
end
end
end
y = y + pit_layer_size
end
vm:set_data(data)
vm:set_lighting({day=0, night=0})
vm:calc_lighting()
vm:write_to_map(data)
-----------------
-- Place Doors --
-----------------
for current_door_index, current_door in pairs(doors) do
local door_dir
if current_door.ns then
door_dir = minetest.dir_to_facedir({x = 0, y = 0, z = 1})
else
door_dir = minetest.dir_to_facedir({x = 1, y = 0, z = 0})
end
local door_pos = {x = current_door.x,
y = current_door.y,
z = current_door.z}
minetest.set_node(door_pos, {name = "doors:door_wood_b_1",
param2 = door_dir})
door_pos.y = door_pos.y + 1
minetest.set_node(door_pos, {name = "doors:door_wood_t_1",
param2 = door_dir})
end
------------------
-- Place Stairs --
------------------
for unused, s in pairs(stairs) do
minetest.place_schematic({x = s.x, y = s.y + 1, z = s.z},
schematic_stairs, s.dir * 90, {}, true)
if chance(7,8) then
minetest.set_node({x = s.x + halfrs,
y = s.y + 2 * roomsize - 1,
z = s.z + halfrs},
{name = "default:torch"})
end
end
end)