1 local storage = minetest.get_mod_storage()
3 local min, max = math.min, math.max
4 local building, build_index, build_data, build_pos, just_placed_node, failed_count, out_of_blocks, last_good_block
6 minetest.register_chatcommand("pos1", {
7 description = "Set schematicas position 1 at your current location",
9 pos1 = vector.round(minetest.localplayer:get_pos())
10 return true, "Position 1 set to " .. minetest.pos_to_string(pos1)
14 minetest.register_chatcommand("pos2", {
15 description = "Set schematicas position 2 at your current location",
17 pos2 = vector.round(minetest.localplayer:get_pos())
18 return true, "Position 2 set to " .. minetest.pos_to_string(pos2)
23 minetest.register_chatcommand("schemesave", {
24 description = "Save a schematica",
27 if not pos1 or not pos2 then
28 return false, "Position 1 or 2 not set."
33 local lx, ly, lz, hx, hy, hz = min(pos1.x, pos2.x), min(pos1.y, pos2.y), min(pos1.z, pos2.z), max(pos1.x, pos2.x), max(pos1.y, pos2.y), max(pos1.z, pos2.z)
41 local node = minetest.get_node_or_nil({x = x, y = y, z = z})
42 if node and node.name ~= "air" then
43 table.insert(data, {pos = {x = rx, y = ry, z = rz}, node = node.name})
49 storage:set_string(name, minetest.serialize(data))
50 return true, "Scheme saved successfully as '" .. name .. "'."
54 minetest.register_chatcommand("schemebuild", {
55 description = "Build a schematica",
59 return false, "Position 1 not set."
62 return false, "Still building a scheme. Use .schemeabort to stop it."
64 local rawdata = storage:get(name)
66 return false, "Schematica '" .. name .. "' not found."
68 building, build_index, build_data, build_pos, just_placed_node, failed_count, out_of_blocks = true, 1, minetest.deserialize(rawdata), vector.new(pos1), false, 0, false
72 minetest.register_chatcommand("schemerecipe", {
73 description = "Print the recipe for a schematica",
76 local rawdata = storage:get(name)
78 return false, "Schematica '" .. name .. "' not found."
80 local data = minetest.deserialize(rawdata)
82 for _, d in ipairs(data) do
87 minetest.register_chatcommand("schemeresume", {
88 description = "Resume constructing a schematica",
90 if not build_data then
91 return false, "Currently not building a scheme."
93 building, out_of_blocks = true, false
94 return true, "Resumed."
98 minetest.register_chatcommand("schemepause", {
99 description = "Pause constructing a schematica",
101 if not build_data then
102 return false, "Currently not building a scheme."
105 return true, "Paused."
109 minetest.register_chatcommand("schemeabort", {
110 description = "Abort constructing a schematica",
113 if not build_data then
114 return false, "Currently not building a scheme."
116 building, build_index, build_data, build_pos, just_placed_node, failed_count, out_of_blocks = nilw
117 return true, "Aborted."
121 minetest.register_chatcommand("schemeskip", {
122 description = "Skip a step in constructing a schematica",
125 if not build_data then
126 return false, "Currently not building a scheme."
128 building, build_index = true, build_index + 1
129 return true, "Skipped."
133 minetest.register_chatcommand("schemegetindex", {
134 description = "Output the build index of the schematica",
136 return build_index and true or false, build_index
140 minetest.register_chatcommand("schemesetindex", {
141 description = "Set the build index of the schematica",
143 func = function(param)
144 local index = tonumber(param)
145 if not index then return false, "Invalid usage." end
147 last_good_block = index
148 return true, "Index Changed"
152 local function step()
154 local data = build_data[build_index]
156 building, build_index, build_data, build_pos, just_placed_node, failed_count, out_of_blocks = nil
157 minetest.display_chat_message("Completed Schematica.")
160 local pos, node = vector.add(build_pos, data.pos), data.node
161 if just_placed_node then
162 just_placed_node = false
163 local map_node = minetest.get_node_or_nil(pos)
164 if map_node and map_node.name == node or build_index % 50 == 0 then
165 local lgb = last_good_block or 0
166 if lgb < build_index - 1 then
167 build_index = lgb + 1
169 if map_node and map_node.name == node then
170 last_good_block = build_index
171 build_index = build_index + 1
172 just_placed_node = true
178 failed_count = failed_count + 1
180 if reliable and failed_count < 10 then
183 if not reliable and not map_node then
186 build_index = build_index + 1
190 local inventory = minetest.get_inventory("current_player").main
191 for index, stack in ipairs(inventory) do
192 if minetest.get_item_def(stack:get_name()).node_placement_prediction == node then
197 if not new_index then
198 if not out_of_blocks then
199 minetest.display_chat_message("Out of blocks for schematica. Missing ressource: '" .. node .. "'. It will resume as soon as you got it or use .schemeskip to skip it.")
200 minetest.send_chat_message("[Schematicas] Missing ressource: " .. node)
205 if out_of_blocks then
206 minetest.send_chat_message("[Schematicas] Resuming.")
208 out_of_blocks = false
209 minetest.localplayer:set_wield_index(new_index)
210 minetest.localplayer:set_pos(minetest.find_node_near(pos, 5, {"air", "ignore", "mcl_core:water_source", "mcl_core:water_flowing"}, false) or pos)
211 minetest.place_node(pos)
212 just_placed_node = true
213 if build_index % 500 == 0 then
214 minetest.send_chat_message("[Schematicas] " .. build_index .. " of " .. #build_data .. " blocks placed!")
219 minetest.register_globalstep(step)