forked from coil0/replacer
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtest.lua
269 lines (239 loc) · 8.18 KB
/
test.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
-- enable developer mode
replacer.dev_mode =
minetest.settings:get_bool('replacer.dev_mode') or false
if not replacer.dev_mode then return end
replacer.test = {}
local r = replacer
local rt = replacer.test
local pd = r.print_dump
rt.spacing = 2
rt.player = nil
rt.facing = vector.new(0, 0, 0)
rt.active = false
rt.no_support = false
rt.move_player = false
rt.nodes_per_step = 444
rt.air_node = { name = 'air' }
rt.seconds_between_steps = 1.1
rt.support_node = { name = 'default:cobble' }
-- skip these patterns that return a match with string:find(pattern)
rt.skip = {
-- these can be counter-productive and not replacer nodes
'^air$', '^ignore$', 'corium', '^tnt:',
'^technic:hv_nuclear_reactor_core_active$',
'^default:lava_source$', '^default:lava_flowing$',
'^hades_core:lava_source$', '^hades_core:lava_flowing$',
'^mcl_core:lava_source$', '^mcl_core:lava_flowing$',
'^default:.*water_source$', '^default:.*water_flowing$',
'^hades_core:water_source$', '^hades_core:water_flowing$',
'^ks_terrain:water_source$', '^ks_terrain:water_flowing$',
'^mcl_core:water_source$', '^mcl_core:water_flowing$',
--'^default:large_cactus_seedling$', -- depends on support_node
'^digistuff:heatsink_onic$', -- depends on support_node
--'^farming:seed_', -- depends on support_node
-- these are removed right away
'^illumination:light_', '^morelights_extras:stairlight$',
'^throwing:arrow', '^vacuum:vacuum$',
-- sun matter is harmless, but not needed as not pointable
'^planetoidgen:sun$',
-- not pointable (can right-click with inspection tool to see them)
'^digistuff:piston_pusher$', '^doors:hidden$', '^elevator:placeholder$',
'^fancy_vend:display_node$',
-- these cause crashes
'^advtrains_interlocking:dtrack_npr_st',
'^advtrains_line_automation:dtrack_stop_st',
'^basic_signs:sign_',
'^default:sign_'
}
function replacer.test.inform(message)
if not rt.player or not rt.player.get_player_name then return end
r.inform(rt.player:get_player_name(), message)
end -- inform
local rti = rt.inform
-- This function is quite robust but it still can happen that game crashes.
-- It has worked best if area was already generated and loaded at least once.
-- Don't be too hasty to add nodes to deny-patterns.
-- It probably helps to turn off mesecons_debug and metrics in general for this
-- kind of excercise.
-- It's also advisable to have damage turned off or to wear a hazmat suit when
-- technic is involved and move_player flag is set.
function replacer.test.chatcommand_place_all(player_name, param)
if rt.active then
return false, 'There is an active task in progress, try again later'
end
param = param or ''
local dry_run
local params = param:split(' ')
local patterns = {}
rt.no_support = false
rt.move_player = false
for _, param2 in ipairs(params) do
if 'dry-run' == param2 then
dry_run = true
elseif 'move_player' == param2 then
rt.move_player = true
elseif 'no_support_node' == param2 then
rt.no_support = true
else
table.insert(patterns, param2)
end
end
if 0 == #patterns then table.insert(patterns, '.*') end
rt.player = minetest.get_player_by_name(player_name)
rt.pos = rt.player:get_pos()--vector.add(player:get_pos(), vector.new(1, 0, 1))--
rt.selected = {}
rt.count = 0
local function has_match(name, patterns_to_check)
for _, pattern in ipairs(patterns_to_check) do
if name:find(pattern) then return true end
end
return false
end -- has_match
for name, _ in pairs(minetest.registered_nodes) do
if not has_match(name, rt.skip)
and has_match(name, patterns)
then
table.insert(rt.selected, name)
rt.count = rt.count + 1
end
end
if 0 == rt.count then
return true, 'Nothing to do.'
end
table.sort(rt.selected)
rt.side, rt.x, rt.z = math.floor((rt.count ^ .5) + .5), 0, 0
local full_side = rt.spacing * (rt.side + 1)
local pos2 = vector.add(rt.pos, vector.new(full_side, 0, full_side))
if dry_run then
return true, 'Required space: ' .. r.nice_pos_string(rt.pos)
.. ' to ' .. r.nice_pos_string(pos2)
end
minetest.emerge_area(rt.pos, vector.add(pos2, vector.new(0, -1, 0)))
rt.i = 1
rt.active = true
rt.succ_count = 0
minetest.after(.1, rt.step)
return true, 'Started process'
end -- chatcommand_place_all
function replacer.test.step()
-- player may have logged off already
if not rt.active then return end
local new_item, succ, pos_, pos__, node, name
local function move_player()
if not rt.move_player then return end
rt.player:set_pos(vector.add(pos_, vector.new(-.25, 0, -1)))
--rt.player:set_rotation(rt.facing)
rt.player:set_look_horizontal(math.rad(0))
rt.player:set_look_vertical(math.rad(45))
end -- move_player
for _ = 1, rt.nodes_per_step do
name = rt.selected[rt.i]
node = minetest.registered_nodes[name]
pos_ = vector.add(rt.pos, vector.new(rt.x, 0, rt.z))
pos__ = vector.add(pos_, vector.new(0, -1, 0))
-- ensure area is generated and loaded
if rt.check_mapgen(pos_) then
rti('waiting for mapgen')
minetest.after(5, rt.step)
return
end
if minetest.find_node_near(pos_, 1, 'ignore', true) then
rti('emerging area')
move_player()
minetest.emerge_area(pos_, pos__)
minetest.after(2, rt.step)
return
end
minetest.set_node(pos_, rt.air_node)
if not rt.no_support then
minetest.set_node(pos__, rt.support_node)
end
move_player()
print(r.nice_pos_string(pos_) .. ' ' .. name)
new_item, succ = node.on_place(ItemStack(node.name), rt.player, {
type = 'node',
under = vector.new(pos_),
above = vector.add(pos_, vector.new(0, 1, 0))
})
if (false == succ) or (nil == new_item) then
pd('Could not place ' .. node.name .. ' at ' .. r.nice_pos_string(pos_))
else
rt.succ_count = rt.succ_count + 1
end
rt.x = rt.x + rt.spacing if rt.spacing * rt.side < rt.x then
rt.x = 0
rt.z = rt.z + rt.spacing
end
rt.i = rt.i + 1
if rt.count < rt.i then break end
end
-- keep player alive
--rt.player:set_hp(55555, { type = 'set_hp', from = 'mod' })
minetest.do_item_eat(55555, 'farming:bread 99', ItemStack('farming:bread 99'),
rt.player, { type = 'nothing' })
if rt.count <= rt.i then
rti(tostring(rt.succ_count) .. ' of ' .. tostring(rt.count)
.. ' nodes placed successfuly')
rt.active = false
return
end
rti('Step ' .. tostring(rt.i) .. ' of ' .. tostring(rt.count) .. ' done')
minetest.after(rt.seconds_between_steps, rt.step)
end -- step
function replacer.test.dealloc_player(player)
if not rt.player or not rt.player.get_player_name then return end
if rt.player:get_player_name() ~= player:get_player_name() then return end
rt.active = false
rt.player = nil
end -- dealloc_player
minetest.register_on_leaveplayer(rt.dealloc_player)
minetest.register_chatcommand('place_all', {
params = '[dry-run][ move_player][ no_support_node][ [<include pattern1>] ... [ <include patternN>] ]',
description = 'Places one of all registered nodes on a grid in +x,+z plane starting '
.. 'at player position. You can use dry-run option to detect how much space you will need. '
.. 'Pass patterns to only place nodes whose name matches. e.g. "^beacon:" "_tinted$" '
.. '-> only place nodes beginning with "beacon:" i.e. beacon-mod, and all nodes ending '
.. 'with "_tinted" i.e. paintbrush nodes. To exclude patterns, edit test.lua and add to '
.. 'rt.skip table.',
func = rt.chatcommand_place_all,
privs = { privs = true }
})
-- from jumpdrive code, mapgen tracking
local events = {} -- list of { minp, maxp, time }
-- update last mapgen event time
--luacheck: no unused args
minetest.register_on_generated(function(minp, maxp, seed)
table.insert(events, {
minp = minp,
maxp = maxp,
time = minetest.get_us_time()
})
end)
-- true = mapgen recently active in that area
function replacer.test.check_mapgen(pos)
for _, event in ipairs(events) do
if 200 > vector.distance(pos, event.minp) then
return true
end
end
return false
end -- check_mapgen
-- cleanup
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if 5 > timer then return end
timer = 0
local time = minetest.get_us_time()
local delay_seconds = 10
local copied_events = events
events = {}
local count = 0
for _, event in ipairs(copied_events) do
if event.time > (time - (delay_seconds * 1000000)) then
-- still recent
table.insert(events, event)
count = count + 1
end
end
end)