-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmigrate.lua
388 lines (339 loc) · 9.85 KB
/
migrate.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
--[[
Hyperloop Mod
=============
Copyright (C) 2017 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
Migrate from v1 to v2
]]--
-- for lazy programmers
local SP = minetest.pos_to_string
local P = minetest.string_to_pos
local M = minetest.get_meta
-- Load support for intllib.
local S = hyperloop.S
local Tube = hyperloop.Tube
local Shaft = hyperloop.Shaft
local Elevators = hyperloop.Elevators
local Stations = hyperloop.Stations
local tLegacyNodeNames = {}
local JunctionsToBePlacedAfter = {}
local function get_tube_data(pos, dir1, dir2, num_tubes)
local param2, tube_type = tubelib2.encode_param2(dir1, dir2, num_tubes)
return pos, param2, tube_type, num_tubes
end
-- Check if node has a connection on the given dir
local function connected(self, pos, dir)
local _,node = self:get_node(pos, dir)
return self.primary_node_names[node.name]
or self.secondary_node_names[node.name]
end
-- Determine dirs via surrounding nodes
local function determine_dir1_dir2_and_num_conn(self, pos)
local dirs = {}
for dir = 1, 6 do
if connected(self, pos, dir) then
dirs[#dirs+1] = dir
end
end
if #dirs == 1 then
return dirs[1], nil, 1
elseif #dirs == 2 then
return dirs[1], dirs[2], 2
end
end
-- convert legacy tubes to current tubes
for idx = 0,2 do
minetest.register_node("hyperloop:tube"..idx, {
description = S("Hyperloop Legacy Tube"),
tiles = {
-- up, down, right, left, back, front
"hyperloop_tube_locked.png^[transformR90]",
"hyperloop_tube_locked.png^[transformR90]",
'hyperloop_tube_closed.png',
'hyperloop_tube_closed.png',
'hyperloop_tube_open.png',
'hyperloop_tube_open.png',
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
local node = minetest.get_node(pos)
node.name = "hyperloop:tubeS"
minetest.swap_node(pos, node)
if not Tube:after_place_tube(pos, placer, pointed_thing) then
minetest.remove_node(pos)
return true
end
return false
end,
paramtype2 = "facedir",
node_placement_prediction = "hyperloop:tubeS",
groups = {cracky=2, not_in_creative_inventory=1},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
})
end
local function convert_legary_nodes(self, pos, dir)
local convert_next_tube = function(self, pos, dir)
local npos, node = self:get_node(pos, dir)
if tLegacyNodeNames[node.name] then
local dir1, dir2, num = determine_dir1_dir2_and_num_conn(self, npos)
if dir1 then
self.clbk_after_place_tube(get_tube_data(npos, dir1,
dir2 or tubelib2.Turn180Deg[dir1], num))
if tubelib2.Turn180Deg[dir] == dir1 then
return npos, dir2
else
return npos, dir1
end
end
end
end
local cnt = 0
if not dir then return pos, dir, cnt end
while cnt <= 64000 do
local new_pos, new_dir = convert_next_tube(self, pos, dir)
if cnt > 0 and (cnt % self.max_tube_length) == 0 then -- border reached?
JunctionsToBePlacedAfter[#JunctionsToBePlacedAfter + 1] = pos
end
if not new_dir then break end
pos, dir = new_pos, new_dir
cnt = cnt + 1
end
return pos, dir, cnt
end
local function convert_line(self, pos, dir)
convert_legary_nodes(self, pos, dir)
self:tool_repair_tube(pos)
end
local tWifiNodes = {} -- user for pairing
local lWifiNodes = {} -- used for post processing
local function set_pairing(pos, peer_pos)
M(pos):set_int("tube_dir", Tube:get_primary_dir(pos))
M(peer_pos):set_int("tube_dir", Tube:get_primary_dir(peer_pos))
Tube:store_teleport_data(pos, peer_pos)
Tube:store_teleport_data(peer_pos, pos)
end
local function wifi_post_processing()
for _,pos in ipairs(lWifiNodes) do
local dir = Tube:get_primary_dir(pos)
local npos = Tube:get_pos(pos, dir)
Tube:tool_repair_tube(npos)
end
end
-- Wifi nodes don't know their counterpart.
-- But by means of the tube head nodes, two
-- Wifi nodes in one tube line can be determined.
local function determine_wifi_pairs(pos)
-- determine 1. tube head node
local pos1 = M(pos):get_string("peer")
if pos1 == "" then return end
-- determine 2. tube head node
local pos2 = M(P(pos1)):get_string("peer")
if pos2 == "" then return end
for k,item in pairs(tWifiNodes) do
-- entry already available
if item[1] == pos2 and item[2] == pos1 then
tWifiNodes[k] = nil
-- start paring
set_pairing(P(k), pos)
return
end
end
-- add single Wifi node to pairing table
tWifiNodes[SP(pos)] = {pos1, pos2}
end
local function next_node_on_the_way_to_a_wifi_node(pos)
local dirs = {}
for dir = 1, 6 do
local npos, node = Tube:get_node(pos, dir)
if tLegacyNodeNames[node.name] then
dirs[#dirs+1] = dir
elseif node.name == "hyperloop:tube_wifi1" then
lWifiNodes[#lWifiNodes+1] = npos
determine_wifi_pairs(npos)
end
end
if #dirs == 1 then
return dirs[1], nil, 1
elseif #dirs == 2 then
return dirs[1], dirs[2], 2
end
end
local function search_wifi_node(pos, dir)
local convert_next_tube = function(pos, dir)
local npos, _ = Tube:get_node(pos, dir)
local dir1, dir2, _ = next_node_on_the_way_to_a_wifi_node(npos)
if dir1 then
if tubelib2.Turn180Deg[dir] == dir1 then
return npos, dir2
else
return npos, dir1
end
end
end
local cnt = 0
if not dir then return pos, cnt end
while true do
local new_pos, new_dir = convert_next_tube(pos, dir)
if not new_dir then break end
pos, dir = new_pos, new_dir
cnt = cnt + 1
end
return pos, dir, cnt
end
local function search_wifi_node_in_all_dirs(pos)
-- check all positions
for dir = 1, 6 do
local _, node = Tube:get_node(pos, dir)
if node and node.name == "hyperloop:tube1" then
search_wifi_node(pos, dir)
end
end
end
local function convert_tube_line(pos)
-- check all positions
for dir = 1, 6 do
local _, node = Tube:get_node(pos, dir)
if node and node.name == "hyperloop:tube1" then
convert_line(Tube, pos, dir)
end
end
end
local function convert_shaft_line(pos)
-- check lower position
convert_line(Shaft, pos, 5)
-- check upper position
pos.y = pos.y + 1
convert_line(Shaft, pos, 6)
pos.y = pos.y - 1
end
local function station_name(item)
if item.junction == true then
return "Junction"
elseif item.station_name then
return item.station_name
else
return "Station"
end
end
local function add_to_table(tbl, tValues)
local res = table.copy(tbl)
for k,v in pairs(tValues) do
tbl[k] = v
end
return res
end
local function convert_station_data(tAllStations)
tLegacyNodeNames = {
["hyperloop:tube0"] = true,
["hyperloop:tube1"] = true,
["hyperloop:tube2"] = true,
}
local originNodeNames = add_to_table(Tube.primary_node_names, tLegacyNodeNames)
for key,item in pairs(tAllStations) do
if item.pos and Tube:is_secondary_node(item.pos) then
Stations:set(item.pos, station_name(item), {
owner = item.owner or S("<unknown>"),
junction = item.junction,
facedir = item.facedir,
booking_info = item.booking_info,
booking_pos = item.booking_pos,
})
end
end
-- First perform the Wifi node pairing
-- before all tube node loose their meta data
-- while converted.
for key,item in pairs(tAllStations) do
if item.pos and Tube:is_secondary_node(item.pos) then
search_wifi_node_in_all_dirs(item.pos)
end
end
-- Then convert all tube nodes
for key,item in pairs(tAllStations) do
if item.pos and Tube:is_secondary_node(item.pos) then
convert_tube_line(item.pos)
Tube:after_place_node(item.pos)
end
end
-- Repair the tube lines of wifi nodes
wifi_post_processing()
Tube.primary_node_names = originNodeNames
end
local function convert_elevator_data(tAllElevators)
tLegacyNodeNames = {
["hyperloop:shaft"] = true,
["hyperloop:shaft2"] = true,
}
local originNodeNames = add_to_table(Shaft.primary_node_names, tLegacyNodeNames)
local originDirsToCheck = table.copy(Shaft.dirs_to_check)
Shaft.dirs_to_check = {5,6} -- legacy elevators use up/down only
for pos,tElevator in pairs(tAllElevators) do
for _,floor in pairs(tElevator.floors) do
if floor.pos and Shaft:is_secondary_node(floor.pos) then
Elevators:set(floor.pos, floor.name, {
facedir = floor.facedir,
})
convert_shaft_line(floor.pos)
M(floor.pos):set_int("change_counter", 0)
Shaft:after_place_node(floor.pos)
end
end
end
Shaft.primary_node_names = originNodeNames
Shaft.dirs_to_check = originDirsToCheck
end
local function place_junctions()
for _,pos in ipairs(JunctionsToBePlacedAfter) do
minetest.set_node(pos, {name = "hyperloop:junction"})
M(pos):set_string("infotext", S("Junction"))
Stations:set(pos, "Junction", {owner = S("unknown"), junction = true})
Tube:after_place_node(pos)
minetest.log("action", "[Hyperloop] Junction placed at "..SP(pos))
end
end
local wpath = minetest.get_worldpath()
function hyperloop.file2table(filename)
local f = io.open(wpath..DIR_DELIM..filename, "r")
if f == nil then return nil end
local t = f:read("*all")
f:close()
if t == "" or t == nil then return nil end
return minetest.deserialize(t)
end
local function migrate()
local data = hyperloop.file2table("mod_hyperloop.data")
if data then
minetest.log("action", "[Hyperloop] Migrate data...")
hyperloop.convert = true
convert_station_data(data.tAllStations)
convert_elevator_data(data.tAllElevators)
os.remove(wpath..DIR_DELIM.."mod_hyperloop.data")
place_junctions()
hyperloop.convert = nil
minetest.log("action", "[Hyperloop] Data migrated")
end
end
minetest.after(5, migrate)
minetest.register_lbm({
label = "[Hyperloop] booking/seat/door migration",
name = "hyperloop:migrate",
nodenames = {
"hyperloop:booking", "hyperloop:booking_ground",
"hyperloop:doorTopPassive", "hyperloop:doorBottom",
"hyperloop:seat",
},
run_at_every_load = true,
action = function(pos, node)
local meta = M(pos)
if meta:get_string("key_str") ~= "" then
local s = meta:get_string("key_str")
meta:set_string("sStationPos", "("..string.sub(s, 2, -2)..")")
if node.name == "hyperloop:booking" or node.name == "hyperloop:booking_ground" then
meta:set_int("change_counter", 0)
end
end
end
})