-
Notifications
You must be signed in to change notification settings - Fork 2
/
init.lua
141 lines (122 loc) · 5.13 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
settlements = {}
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- internationalization boilerplate
settlements.S, settlements.NS = dofile(modpath.."/intllib.lua")
settlements.half_map_chunk_size = tonumber(minetest.get_mapgen_setting("chunksize")) * 16 / 2
settlements.surface_materials = {}
settlements.registered_settlements = {}
-- Minimum distance between settlements
settlements.min_dist_settlements = tonumber(minetest.settings:get("settlements_minimum_distance_between_settlements")) or 500
-- maximum allowed difference in height for building a settlement
local max_height_difference = tonumber(minetest.settings:get("settlements_maximum_height_difference")) or 10
dofile(modpath.."/upgrades.lua")
dofile(modpath.."/buildings.lua")
dofile(modpath.."/bookgen.lua")
dofile(modpath.."/admin_commands.lua")
dofile(modpath.."/admin_tools.lua")
settlements.register_settlement = function(settlement_type_name, settlement_def)
assert(not settlements.registered_settlements[settlement_type_name])
settlement_def.name = settlement_type_name
settlements.registered_settlements[settlement_type_name] = settlement_def
for _, material in ipairs(settlement_def.surface_materials) do
local c_mat = minetest.get_content_id(material)
local material_list = settlements.surface_materials[c_mat] or {}
settlements.surface_materials[c_mat] = material_list
table.insert(material_list, settlement_def)
end
end
-- Interconverting lua and mts formatted schematics
-- Useful for modders adding existing schematics that are in mts format
function settlements.convert_mts_to_lua(schem_path)
local str = minetest.serialize_schematic(schem_path, "lua", {lua_use_comments = true})
local file = io.open(schem_path:sub(1,-4).."lua", "w")
file:write(str.."\nreturn schematic")
file:close()
end
-------------------------------------------------------------------------------
-- check distance to other settlements
-------------------------------------------------------------------------------
local function check_distance_other_settlements(center_new_chunk)
local min_edge = vector.subtract(center_new_chunk, settlements.min_dist_settlements)
local max_edge = vector.add(center_new_chunk, settlements.min_dist_settlements)
-- This gets all neighbors within a cube-shaped volume
local neighbors = named_waypoints.get_waypoints_in_area("settlements", min_edge, max_edge)
-- Search through those to find any that are within a spherical volume
for i, settlement in pairs(neighbors) do
local distance = vector.distance(center_new_chunk, settlement.pos)
if distance < settlements.min_dist_settlements then
return false
end
end
return true
end
-------------------------------------------------------------------------------
-- evaluate heightmap
-------------------------------------------------------------------------------
local function evaluate_heightmap(heightmap)
-- max height and min height, initialize with impossible values for easier first time setting
local max_y = -50000
local min_y = 50000
-- only evaluate the center square of heightmap 40 x 40
local square_start = 1621
local square_end = 1661
for j = 1, 40 do
for i = square_start, square_end do
-- skip buggy heightmaps, return high value
if heightmap[i] == -31000 or
heightmap[i] == 31000 then
return max_height_difference + 1
end
if heightmap[i] < min_y then
min_y = heightmap[i]
end
if heightmap[i] > max_y then
max_y = heightmap[i]
end
end
-- set next line
square_start = square_start + 80
square_end = square_end + 80
end
-- return the difference between highest and lowest pos in chunk
local height_diff = max_y - min_y
-- filter buggy heightmaps
if height_diff < 0 then
return max_height_difference + 1
end
return height_diff
end
local half_map_chunk_size = settlements.half_map_chunk_size
minetest.register_on_generated(function(minp, maxp)
-- don't build settlement underground
if maxp.y < -100 then
return
end
local existing_settlements = named_waypoints.get_waypoints_in_area("settlements", minp, maxp)
local id, data = next(existing_settlements)
if id ~= nil then
-- There's already a settlement in this chunk despite us being in mapgen.
-- This chunk must have been previously generated and is now being re-generated. Override
-- any further checks and try building a settlement here.
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
data = data.data
settlements.generate_settlement_vm(vm, va, minp, maxp, data.name)
return
end
-- don't build settlements too close to each other
local center_of_chunk = vector.subtract(maxp, half_map_chunk_size)
local dist_ok = check_distance_other_settlements(center_of_chunk)
if dist_ok == false then
return
end
-- don't build settlements on (too) uneven terrain
local heightmap = minetest.get_mapgen_object("heightmap")
local height_difference = evaluate_heightmap(heightmap)
if height_difference > max_height_difference then
return
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
settlements.generate_settlement_vm(vm, va, minp, maxp)
end)