-
Notifications
You must be signed in to change notification settings - Fork 1
/
auto_save.lua
201 lines (175 loc) · 5.7 KB
/
auto_save.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
minetest.register_chatcommand("mapsync_autosave", {
description = "enable or disable the autosave feature",
params = "[on|off]",
privs = { mapsync = true },
func = function(_, params)
if params == "on" then
mapsync.autosave = true
mapsync.storage:set_int("autosave", 1)
return true, "Autosave enabled"
else
mapsync.autosave = false
mapsync.storage:set_int("autosave", 0)
return true, "Autosave disabled"
end
end
})
-- list of chunks marked for export
local chunks = {}
-- autosave worker function
local function worker()
local count = 0
for hash in pairs(chunks) do
count = count + 1
local chunk_pos = minetest.get_position_from_hash(hash)
mapsync.save(chunk_pos)
end
if count > 0 then
minetest.chat_send_all("[mapsync] Dispatched " .. count .. " chunk(s) to export")
end
chunks = {}
minetest.after(2, worker)
end
minetest.after(1, worker)
--- marks a region as changed, to be used by dependent mods whose changes don't get caught
--- by the usual change-detection
-- @param pos1 the first position of the changed region
-- @param pos2 the second position of the changed region
function mapsync.mark_changed(pos1, pos2)
mapsync.last_mapchange = os.time()
if not mapsync.autosave then
return
end
if not pos2 then
-- default to same pos2 as pos1
pos2 = pos1
end
pos1, pos2 = mapsync.sort_pos(pos1, pos2)
local chunk_pos1 = mapsync.get_chunkpos(pos1)
local chunk_pos2 = mapsync.get_chunkpos(pos2)
for x=chunk_pos1.x,chunk_pos2.x do
for y=chunk_pos1.y,chunk_pos2.y do
for z=chunk_pos1.z,chunk_pos2.z do
local chunk_pos = {x=x, y=y, z=z}
local hash = minetest.hash_node_position(chunk_pos)
chunks[hash] = true
end
end
end
end
-- autosave on minetest.set_node
local old_set_node = minetest.set_node
function minetest.set_node(pos, node)
mapsync.mark_changed(pos)
return old_set_node(pos, node)
end
-- autosave on minetest.swap_node
local old_swap_node = minetest.swap_node
function minetest.swap_node(pos, node)
mapsync.mark_changed(pos)
return old_swap_node(pos, node)
end
-- autosave on place/dignode
local function place_dig_callback(pos)
mapsync.mark_changed(pos)
end
minetest.register_on_placenode(place_dig_callback)
minetest.register_on_dignode(place_dig_callback)
-- autosave on we commands
if minetest.get_modpath("worldedit") then
-- used by various primitives and commands
local old_mapgenhelper_init = worldedit.manip_helpers.init
worldedit.manip_helpers.init = function(pos1, pos2)
mapsync.mark_changed(pos1, pos2)
return old_mapgenhelper_init(pos1, pos2)
end
-- used by //load and others
local old_keeploaded = worldedit.keep_loaded
worldedit.keep_loaded = function(pos1, pos2)
mapsync.mark_changed(pos1, pos2)
return old_keeploaded(pos1, pos2)
end
-- //fixlight
local old_fixlight = worldedit.fixlight
worldedit.fixlight = function(pos1, pos2)
mapsync.mark_changed(pos1, pos2)
return old_fixlight(pos1, pos2)
end
end
-- intercept various node-based events
minetest.register_on_mods_loaded(function()
for nodename, def in pairs(minetest.registered_nodes) do
if type(def.on_receive_fields) == "function" then
-- intercept formspec events
local old_on_receive_fields = def.on_receive_fields
minetest.override_item(nodename, {
on_receive_fields = function(pos, formname, fields, sender)
mapsync.mark_changed(pos)
return old_on_receive_fields(pos, formname, fields, sender)
end
})
end
if type(def.on_metadata_inventory_move) == "function" then
-- intercept inv move event
local old_inv_move = def.on_metadata_inventory_move
minetest.override_item(nodename, {
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
mapsync.mark_changed(pos)
return old_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
end
})
end
if type(def.on_metadata_inventory_put) == "function" then
-- intercept inv put event
local old_inv_put = def.on_metadata_inventory_put
minetest.override_item(nodename, {
on_metadata_inventory_put = function(pos, listname, index, stack, player)
mapsync.mark_changed(pos)
return old_inv_put(pos, listname, index, stack, player)
end
})
end
if type(def.on_metadata_inventory_take) == "function" then
-- intercept inv take event
local old_inv_take = def.on_metadata_inventory_take
minetest.override_item(nodename, {
on_metadata_inventory_take = function(pos, listname, index, stack, player)
mapsync.mark_changed(pos)
return old_inv_take(pos, listname, index, stack, player)
end
})
end
end
end)
if minetest.get_modpath("screwdriver2") and minetest.registered_items["screwdriver2:screwdriver"] then
local old_nodedef = minetest.registered_items["screwdriver2:screwdriver"]
local old_on_use = old_nodedef.on_use
local old_on_place = old_nodedef.on_place
local function handle_pointed_thing(pointed_thing)
if pointed_thing.above then
mapsync.mark_changed(pointed_thing.above)
end
if pointed_thing.under then
mapsync.mark_changed(pointed_thing.under)
end
end
minetest.override_item("screwdriver2:screwdriver", {
on_use = function(itemstack, player, pointed_thing)
handle_pointed_thing(pointed_thing)
return old_on_use(itemstack, player, pointed_thing)
end,
on_place = function(itemstack, player, pointed_thing)
handle_pointed_thing(pointed_thing)
return old_on_place(itemstack, player, pointed_thing)
end
})
end
if minetest.get_modpath("travelnet") and type(travelnet.on_receive_fields) == "function" then
local old_on_receive_fields = travelnet.on_receive_fields
function travelnet.on_receive_fields(pos, _, fields, player)
if pos then
mapsync.mark_changed(pos)
end
return old_on_receive_fields(pos, _, fields, player)
end
end