-
Notifications
You must be signed in to change notification settings - Fork 0
/
mapgen_v6.lua
278 lines (244 loc) · 9.81 KB
/
mapgen_v6.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
--Identify content ID's of nodes
local c_dirt_with_grass = minetest.get_content_id("default:dirt_with_grass")
local c_snow = minetest.get_content_id("default:snow")
local c_snow_block = minetest.get_content_id("default:snowblock")
local c_dirt_with_snow = minetest.get_content_id("default:dirt_with_snow")
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local c_stone = minetest.get_content_id("default:stone")
local c_dry_shrub = minetest.get_content_id("default:dry_shrub")
local c_leaves = minetest.get_content_id("default:leaves")
local c_jungleleaves = minetest.get_content_id("default:jungleleaves")
local c_junglegrass = minetest.get_content_id("default:junglegrass")
local c_ice = minetest.get_content_id("default:ice")
local c_water = minetest.get_content_id("default:water_source")
local c_papyrus = minetest.get_content_id("default:papyrus")
local c_sand = minetest.get_content_id("default:sand")
--Snow biomes are found at 0.53 and greater perlin noise.
minetest.register_on_generated(function(minp, maxp, seed)
--if maxp.y >= -10 and maxp.y > snow.min_height then
--Start timer
local t1 = os.clock()
local in_biome = false
--Load Voxel Manipulator
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local a = 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()
local debug = snow.debug
local min_height = snow.min_height
--Should make things a bit faster.
local env = minetest.env
-- Assume X and Z lengths are equal
local divlen = 16
local divs = (maxp.x-minp.x)+1;
local x0 = minp.x
local z0 = minp.z
local x1 = maxp.x
local z1 = maxp.z
--Get map specific perlin noise.
local perlin1 = env:get_perlin(112,3, 0.5, 150)
--Speed hack: checks the corners and middle of the chunk for "snow biome".
--[[if not ( perlin1:get2d( {x=x0, y=z0} ) > 0.53 ) --top left
and not ( perlin1:get2d( { x = x0 + ( (x1-x0)/2), y=z0 } ) > 0.53 )--top middle
and not (perlin1:get2d({x=x1, y=z1}) > 0.53) --bottom right
and not (perlin1:get2d({x=x1, y=z0+((z1-z0)/2)}) > 0.53) --right middle
and not (perlin1:get2d({x=x0, y=z1}) > 0.53) --bottom left
and not (perlin1:get2d({x=x1, y=z0}) > 0.53) --top right
and not (perlin1:get2d({x=x0+((x1-x0)/2), y=z1}) > 0.53) --left middle
and not (perlin1:get2d({x=(x1-x0)/2, y=(z1-z0)/2}) > 0.53) --middle
and not (perlin1:get2d({x=x0, y=z1+((z1-z0)/2)}) > 0.53) then --bottom middle
return
end]]
--Choose a biome types.
local pr = PseudoRandom(seed+57)
local biome
--Land biomes
biome = pr:next(1, 5)
local snowy = biome == 1 --spawns alot of snow
local plain = biome == 2 --spawns not much
local alpine = biome == 3 --rocky terrain
-- biome == 4 or biome == 5 -- normal biome
--Water biomes
biome2 = pr:next(1, 5)
local cool = biome == 1 --only spawns ice on edge of water
local icebergs = biome == 2
local icesheet = biome == 3
local icecave = biome == 4
local icehole = biome == 5 --icesheet with holes
--Misc biome settings.
local icy = pr:next(1, 2) == 2 --If enabled spawns ice in sand instead of snow blocks.
local mossy = pr:next(1,2) == 1 --Spawns moss in snow.
local shrubs = pr:next(1,2) == 1 --Spawns dry shrubs in snow.
local pines = pr:next(1,2) == 1 --spawns pines.
--Debugging function
local biomeToString = function(num,num2)
local biome, biome2
if num == 1 then biome = "snowy"
elseif num == 2 then biome = "plain"
elseif num == 3 then biome = "alpine"
elseif num == 4 or num == 5 then biome = "normal"
else biome = "unknown "..num end
if num2 == 1 then biome2 = "cool"
elseif num2 == 2 then biome2 = "icebergs"
elseif num2 == 3 then biome2 = "icesheet"
elseif num2 == 4 then biome2 = "icecave"
elseif num2 == 5 then biome2 = "icehole"
else biome2 = "unknown "..num end
return biome, biome2
end
local spawn_pine = snow.voxelmanip_pine
local smooth = snow.smooth_biomes
local legacy = snow.legacy
--Reseed random.
pr = PseudoRandom(seed+68)
--[[if alpine then
local trees = env:find_nodes_in_area(minp, maxp, {"default:leaves","default:tree"})
for i,v in pairs(trees) do
env:remove_node(v)
end
end]]
--Loop through chunk.
for x = minp.x, maxp.x do
for z = minp.z, maxp.z do
--Check if we are in a "Snow biome"
local in_biome = false
local test = perlin1:get2d({x=x, y=z})
if smooth and (not snowy) and (test > 0.73 or (test > 0.43 and pr:next(0,29) > (0.73 - test) * 100 )) then
in_biome = true
elseif (not smooth or snowy) and test > 0.53 then
in_biome = true
end
if in_biome then
local perlin2 = env:get_perlin(322345,3, 0.5, 80)
local icetype = perlin2:get2d({x=x, y=z})
local cool = icetype > 0 --only spawns ice on edge of water
local icebergs = icetype > -0.2 and icetype <= 0
local icehole = icetype > -0.4 and icetype <= -0.2
local icesheet = icetype > -0.6 and icetype <= -0.4
local icecave = icetype <= -0.6
--if not plain or pr:next(1,12) == 1 then
-- Find ground level (0...15)
local ground_y = nil
for y=maxp.y,minp.y,-1 do
local n = data[a:index(x, y, z)]
if n ~= c_air and n ~= c_ignore then
ground_y = y
break
end
end
if ground_y then --and ground_y > min_height then
-- Snowy biome stuff
local node = a:index(x, ground_y, z)
local abovenode = a:index(x, ground_y+1, z)
local belownode = a:index(x, ground_y+2, z)
if ground_y and data[node] == c_dirt_with_grass then
--local veg
--if legacy and mossy and pr:next(1,10) == 1 then veg = 1 end
if alpine then
--Gets rid of dirt
data[abovenode] = c_snow
for y=ground_y,-6,-1 do
local stone = a:index(x, y, z)
if data[stone] == "default:stone" then
break
else
data[stone] = c_stone
end
end
elseif (shrubs and pr:next(1,28) == 1) then
--Spawns dry shrubs.
data[node] = c_dirt_with_snow
data[abovenode] = c_dry_shrub
elseif pines and pr:next(1,36) == 1 then
--Spawns pines.
data[node] = c_dirt_with_snow
spawn_pine({x=x, y=ground_y+1, z=z},a,data)
--elseif snowy then
--Spawns snow blocks.
--env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow_block"})
--data[aanode] = c_snow
else
--Spawns snow.
data[node] = c_dirt_with_snow
data[abovenode] = c_snow
end
elseif ground_y and data[belownode] == c_sand then
--Spawns ice in sand if icy, otherwise spawns snow on top.
if not icy then
data[node] = c_snow
else
data[belownode] = c_ice
end
elseif ground_y and data[node] == c_leaves or data[node] == c_jungleleaves then
data[abovenode] = c_snow
elseif ground_y and data[node] == c_junglegrass then
data[node] = c_dry_shrub
elseif ground_y and data[node] == c_papyrus then
for i=ground_y, ground_y-4, -1 do
local papyrus = a:index(x, y, z)
if data[papyrus] == c_papyrus then
local papyrusabove = a:index(x, ground_y, z)
data[papyrusabove] = c_snow
data[papyrus] = c_snow_block
end
end
elseif ground_y and data[node] == c_water then
if not icesheet and not icecave and not icehole then
--Coastal ice.
local x1 = data[a:index(x+1,ground_y,z)]
local z1 = data[a:index(x,ground_y,z+1)]
local xz1 = data[a:index(x+1,ground_y,z+1)]
local xz2 = data[a:index(x-1,ground_y,z-1)]
local x2 = data[a:index(x-1,ground_y,z)]
local z2 = data[a:index(x,ground_y,z-1)]
local y = data[a:index(x,ground_y-1,z)]
local rand = pr:next(1,4) == 1
if
((x1 and x1 ~= c_water and x1 ~= c_ice and x1 ~= c_air and x1 ~= c_ignore) or ((cool or icebergs) and x1 == c_ice and rand)) or
((z1 and z1 ~= c_water and z1 ~= c_ice and z1 ~= c_air and z1 ~= c_ignore) or ((cool or icebergs) and z1 == c_ice and rand)) or
((xz1 and xz1 ~= c_water and xz1 ~= c_ice and xz1 ~= c_air and xz1 ~= c_ignore) or ((cool or icebergs) and xz1 == c_ice and rand)) or
((xz2 and xz2 ~= c_water and xz2 ~= c_ice and xz2 ~= c_air and xz2 ~= c_ignore) or ((cool or icebergs) and xz2 == c_ice and rand)) or
((x2 and x2 ~= c_water and x2 ~= c_ice and x2 ~= c_air and x2 ~= c_ignore) or ((cool or icebergs) and x2 == c_ice and rand)) or
((z2 and z2 ~= c_water and z2 ~= c_ice and z2 ~= c_air and z2 ~= c_ignore) or ((cool or icebergs) and z2 == c_ice and rand)) or
(y ~= c_water and y ~= c_ice and y ~= "air") or (pr:next(1,6) == 1 and icebergs) then
data[node] = c_ice
end
else
--Icesheets, Broken icesheet, Icecaves
if (icehole and pr:next(1,10) > 1) or icecave or icesheet then
data[node] = c_ice
end
if icecave then
--Gets rid of water underneath ice
for y=ground_y-1,-60,-1 do
local water = a:index(x, y, z)
if data[water] ~= c_water then
break
else
data[water] = c_air
end
end
end
end
end
end
--end
end
end
end
vm:set_data(data)
vm:calc_lighting(
{x=minp.x-16, y=minp.y, z=minp.z-16},
{x=maxp.x+16, y=maxp.y, z=maxp.z+16}
)
vm:write_to_map(data)
if debug then
biome_string,biome2_string = biomeToString(biome,biome2)
print(biome_string.." and "..biome2_string..": Snow Biome Genarated near x"..minp.x.." z"..minp.z)
print(string.format("elapsed time: %.2fms", (os.clock() - t1) * 1000))
end
--end
end)