Clear node probability for default prob
[minetest_schemedit.git] / init.lua
blobac9dfb81b25407a33917d0f6b8d86dd33d008014
1 -- advschem/init.lua
3 advschem = {}
5 local path = minetest.get_worldpath().."/advschem.mt"
6 local marked = {}
7 advschem.markers = {}
9 -- [local function] Renumber table
10 local function renumber(t)
11 local res = {}
12 for _, i in pairs(t) do
13 res[#res + 1] = i
14 end
15 return res
16 end
18 ---
19 --- Formspec API
20 ---
22 local contexts = {}
23 local form_data = {}
24 local tabs = {}
25 local forms = {}
27 -- [function] Add form
28 function advschem.add_form(name, def)
29 def.name = name
30 forms[name] = def
32 if def.tab then
33 tabs[#tabs + 1] = name
34 end
35 end
37 -- [function] Generate tabs
38 function advschem.generate_tabs(current)
39 local retval = "tabheader[0,0;tabs;"
40 for _, t in pairs(tabs) do
41 local f = forms[t]
42 if f.tab ~= false and f.caption then
43 retval = retval..f.caption..","
45 if type(current) ~= "number" and current == f.name then
46 current = _
47 end
48 end
49 end
50 retval = retval:sub(1, -2) -- Strip last comma
51 retval = retval..";"..current.."]" -- Close tabheader
52 return retval
53 end
55 -- [function] Handle tabs
56 function advschem.handle_tabs(pos, name, fields)
57 local tab = tonumber(fields.tabs)
58 if tab and tabs[tab] and forms[tabs[tab]] then
59 advschem.show_formspec(pos, name, forms[tabs[tab]].name)
60 return true
61 end
62 end
64 -- [function] Show formspec
65 function advschem.show_formspec(pos, player, tab, show, ...)
66 if forms[tab] then
67 if type(player) == "string" then
68 player = minetest.get_player_by_name(player)
69 end
70 local name = player:get_player_name()
72 if show ~= false then
73 if not form_data[name] then
74 form_data[name] = {}
75 end
77 local form = forms[tab].get(form_data[name], pos, name, ...)
78 if forms[tab].tab then
79 form = form..advschem.generate_tabs(tab)
80 end
82 minetest.show_formspec(name, "advschem:"..tab, form)
83 contexts[name] = pos
85 -- Update player attribute
86 if forms[tab].cache_name ~= false then
87 player:set_attribute("advschem:tab", tab)
88 end
89 else
90 minetest.close_formspec(pname, "advschem:"..tab)
91 end
92 end
93 end
95 -- [event] On receive fields
96 minetest.register_on_player_receive_fields(function(player, formname, fields)
97 local formname = formname:split(":")
99 if formname[1] == "advschem" and forms[formname[2]] then
100 local handle = forms[formname[2]].handle
101 local name = player:get_player_name()
102 if contexts[name] then
103 if not form_data[name] then
104 form_data[name] = {}
107 if not advschem.handle_tabs(contexts[name], name, fields) and handle then
108 handle(form_data[name], contexts[name], name, fields)
112 end)
115 --- Formspec Tabs
118 advschem.add_form("main", {
119 tab = true,
120 caption = "Main",
121 get = function(self, pos, name)
122 local meta = minetest.get_meta(pos):to_table().fields
123 local strpos = minetest.pos_to_string(pos)
125 local border_button
126 if meta.schem_border == "true" and advschem.markers[strpos] then
127 border_button = "button[3.5,7.5;3,1;border;Hide Border]"
128 else
129 border_button = "button[3.5,7.5;3,1;border;Show Border]"
132 -- TODO: Show information regarding volume, pos1, pos2, etc... in formspec
133 return [[
134 size[7,8]
135 label[0.5,-0.1;Position: ]]..strpos..[[]
136 label[3,-0.1;Owner: ]]..name..[[]
138 field[0.8,1;5,1;name;Schematic Name:;]]..(meta.schem_name or "")..[[]
139 button[5.3,0.69;1.2,1;save_name;Save]
140 tooltip[save_name;Save schematic name]
141 field_close_on_enter[name;false]
143 button[0.5,1.5;6,1;export;Export Schematic]
144 label[0.5,2.2;Schematic will be exported as a .mts file and stored in]
145 label[0.5,2.45;<minetest dir>/worlds/<worldname>/schems/<name>.mts]
147 field[0.8,7;2,1;x;X-Size:;]]..meta.x_size..[[]
148 field[2.8,7;2,1;y;Y-Size:;]]..meta.y_size..[[]
149 field[4.8,7;2,1;z;Z-Size:;]]..meta.z_size..[[]
150 field_close_on_enter[x;false]
151 field_close_on_enter[y;false]
152 field_close_on_enter[z;false]
154 button[0.5,7.5;3,1;save;Save Size]
155 ]]..
156 border_button
157 end,
158 handle = function(self, pos, name, fields)
159 local realmeta = minetest.get_meta(pos)
160 local meta = realmeta:to_table().fields
161 local strpos = minetest.pos_to_string(pos)
163 -- Toggle border
164 if fields.border then
165 if meta.schem_border == "true" and advschem.markers[strpos] then
166 advschem.unmark(pos)
167 meta.schem_border = "false"
168 else
169 advschem.mark(pos)
170 meta.schem_border = "true"
174 local update_positions = false
175 -- Save size vector values
176 if (fields.save or fields.key_enter_field == "x" or
177 fields.key_enter_field == "y" or fields.key_enter_field == "z")
178 and (fields.x and fields.y and fields.z and fields.x ~= ""
179 and fields.y ~= "" and fields.z ~= "") then
180 local x, y, z = tonumber(fields.x), tonumber(fields.y), tonumber(fields.z)
182 if x then
183 meta.x_size = math.max(x, 1)
185 if y then
186 meta.y_size = math.max(y, 1)
188 if z then
189 meta.z_size = math.max(z, 1)
192 -- Set positions to be updated
193 update_positions = true
196 -- Save schematic name
197 if fields.save_name or fields.key_enter_field == "name" and fields.name and
198 fields.name ~= "" then
199 meta.schem_name = fields.name
202 -- Export schematic
203 if fields.export and meta.schem_name and meta.schem_name ~= "" then
204 local pos1, pos2 = advschem.size(pos)
205 local path = minetest.get_worldpath().."/schems/"
206 minetest.mkdir(path)
208 local plist = minetest.deserialize(meta.prob_list)
209 local probability_list = {}
210 for _, i in pairs(plist) do
211 local prob = i.prob
212 if i.force_place == true then
213 prob = prob + 128
216 probability_list[#probability_list + 1] = {
217 pos = minetest.string_to_pos(_),
218 prob = prob,
222 local slist = minetest.deserialize(meta.slices)
223 local slice_list = {}
224 for _, i in pairs(slist) do
225 slice_list[#slice_list + 1] = {
226 ypos = pos.y + i.ypos,
227 prob = i.prob,
231 local filepath = path..meta.schem_name..".mts"
232 local res = minetest.create_schematic(pos1, pos2, probability_list, filepath, slice_list)
234 if res then
235 minetest.chat_send_player(name, minetest.colorize("#00ff00",
236 "Exported schematic to "..filepath))
237 else
238 minetest.chat_send_player(name, minetest.colorize("red",
239 "Failed to export schematic to "..filepath))
243 -- Save meta before updating visuals
244 local inv = realmeta:get_inventory():get_lists()
245 realmeta:from_table({fields = meta, inventory = inv})
247 -- Update border
248 if not fields.border and meta.schem_border == "true" then
249 advschem.mark(pos)
252 -- Update formspec
253 if not fields.quit then
254 advschem.show_formspec(pos, minetest.get_player_by_name(name), "main")
257 -- Update pos1 and pos2 in marked table (for interaction checking)
258 if update_positions then
259 local pos1, pos2 = advschem.size(pos)
260 pos1, pos2 = advschem.sort_pos(pos1, pos2)
261 marked[minetest.pos_to_string(pos)] = {
262 pos1 = pos1,
263 pos2 = pos2,
266 end,
269 advschem.add_form("prob", {
270 tab = true,
271 caption = "Probability",
272 get = function(self, pos, name)
273 local meta = minetest.get_meta(pos)
274 local inventory = meta:get_inventory()
275 local stack = inventory:get_stack("probability", 1)
276 local stringpos = pos.x..","..pos.y..","..pos.z
278 local form = [[
279 size[8,6]
280 list[nodemeta:]]..stringpos..[[;probability;0,0;1,1;]
281 label[0,1;Probability is a number between 0 and 127.]
282 list[current_player;main;0,1.5;8,4;]
283 listring[nodemeta:]]..stringpos..[[;probability]
284 listring[current_player;main]
287 if stack:get_name() ~= "" then
288 local smeta = stack:get_meta():to_table().fields
290 form = form .. [[
291 field[1.3,0.4;2,1;probability;Probability:;]]..
292 (smeta.advschem_prob or "127").."]" ..
294 field_close_on_enter[probability;false]
295 checkbox[3.1,0.1;force_place;Force Place;]]..(smeta.advschem_force_place or "false")..[[]
296 button[5,0.1;1.5,1;rst;Reset]
297 button[6.5,0.1;1.5,1;save;Save]
299 else
300 form = form .. [[
301 label[1,0.2;Insert node in slot.]
305 return form
306 end,
307 handle = function(self, pos, name, fields)
308 local meta = minetest.get_meta(pos)
309 local inventory = meta:get_inventory()
310 local stack = inventory:get_stack("probability", 1)
311 local smeta = stack:get_meta()
313 if stack:get_name() ~= "" then
314 if fields.rst then
315 smeta:set_string("advschem_prob", nil)
316 smeta:set_string("advschem_force_place", nil)
318 -- Reset description
319 local original_desc = smeta:get_string("original_desc")
320 if not original_desc or original_desc == "" then
321 original_desc = minetest.registered_items[stack:get_name()].description
324 smeta:set_string("description", original_desc)
325 elseif fields.force_place or fields.save or
326 fields.key_enter_field == "probability" then
328 local prob_desc = "\nProbability: "..(fields.probability or
329 smeta:get_string("advschem_prob") or "Not Set")
330 -- Update probability
331 if fields.probability ~= "" then
332 local prob = tonumber(fields.probability)
333 if prob and prob >= 0 and prob < 127 then
334 smeta:set_string("advschem_prob", fields.probability)
335 elseif prob and prob == 127 then
336 -- Clear prob metadata for default probability
337 prob_desc = ""
338 smeta:set_string("advschem_prob", nil)
339 else
340 prob_desc = "\nProbability: "..(smeta:get_string("advschem_prob") or
341 "Not Set")
342 advschem.show_formspec(pos, minetest.get_player_by_name(name), "prob")
344 else
345 smeta:set_string("advschem_prob", nil)
348 -- Update force place if fields value is not nil
349 if fields.force_place ~= nil then
350 smeta:set_string("advschem_force_place", fields.force_place)
353 -- Update description
354 local desc = minetest.registered_items[stack:get_name()].description
355 local meta_desc = smeta:get_string("description")
356 if meta_desc and meta_desc ~= "" then
357 desc = meta_desc
360 local original_desc = smeta:get_string("original_description")
361 if original_desc and original_desc ~= "" then
362 desc = original_desc
363 else
364 smeta:set_string("original_description", desc)
367 local force_desc = ""
368 if smeta:get_string("advschem_force_place") == "true" then
369 force_desc = "\n".."Force Place"
372 desc = desc..minetest.colorize("grey", prob_desc..force_desc)
374 smeta:set_string("description", desc)
377 -- Update itemstack
378 inventory:set_stack("probability", 1, stack)
380 -- Refresh formspec on reset or force placement change
381 if fields.rst or fields.force_place then
382 advschem.show_formspec(pos, minetest.get_player_by_name(name), "prob")
385 end,
388 advschem.add_form("slice", {
389 caption = "Y-Slice",
390 tab = true,
391 get = function(self, pos, name, visible_panel)
392 local meta = minetest.get_meta(pos):to_table().fields
394 self.selected = self.selected or 1
395 local selected = tostring(self.selected)
396 local slice_list = minetest.deserialize(meta.slices)
397 local slices = ""
398 for _, i in pairs(slice_list) do
399 local insert = "Y = "..tostring(i.ypos).."; Probability = "..tostring(i.prob)
400 slices = slices..minetest.formspec_escape(insert)..","
402 slices = slices:sub(1, -2) -- Remove final comma
404 local form = [[
405 size[7,6]
406 table[0,0;6.8,4;slices;]]..slices..[[;]]..selected..[[]
409 if self.panel_add or self.panel_edit then
410 local ypos_default, prob_default = "", ""
411 local done_button = "button[5,5.18;2,1;done_add;Done]"
412 if self.panel_edit then
413 done_button = "button[5,5.18;2,1;done_edit;Done]"
414 ypos_default = slice_list[self.selected].ypos
415 prob_default = slice_list[self.selected].prob
418 form = form..[[
419 field[0.3,5.5;2.5,1;ypos;Y-Position (max ]]..(meta.y_size - 1)..[[):;]]..ypos_default..[[]
420 field[2.8,5.5;2.5,1;prob;Probability (0-127):;]]..prob_default..[[]
421 field_close_on_enter[ypos;false]
422 field_close_on_enter[prob;false]
423 ]]..done_button
426 if not self.panel_edit then
427 form = form.."button[0,4;2,1;add;+ Add Slice]"
430 if slices ~= "" and self.selected and not self.panel_add then
431 if not self.panel_edit then
432 form = form..[[
433 button[2,4;2,1;remove;- Remove Slice]
434 button[4,4;2,1;edit;+/- Edit Slice]
436 else
437 form = form..[[
438 button[0,4;2,1;remove;- Remove Slice]
439 button[2,4;2,1;edit;+/- Edit Slice]
444 return form
445 end,
446 handle = function(self, pos, name, fields)
447 local meta = minetest.get_meta(pos)
448 local player = minetest.get_player_by_name(name)
450 if fields.slices then
451 local slices = fields.slices:split(":")
452 self.selected = tonumber(slices[2])
455 if fields.add then
456 if not self.panel_add then
457 self.panel_add = true
458 advschem.show_formspec(pos, player, "slice")
459 else
460 self.panel_add = nil
461 advschem.show_formspec(pos, player, "slice")
465 local ypos, prob = tonumber(fields.ypos), tonumber(fields.prob)
466 if (fields.done_add or fields.done_edit) and fields.ypos and fields.prob and
467 fields.ypos ~= "" and fields.prob ~= "" and ypos and prob and
468 ypos <= (meta:get_int("y_size") - 1) and prob >= 0 and prob <= 255 then
469 local slice_list = minetest.deserialize(meta:get_string("slices"))
470 local index = #slice_list + 1
471 if fields.done_edit then
472 index = self.selected
475 slice_list[index] = {ypos = ypos, prob = prob}
477 meta:set_string("slices", minetest.serialize(slice_list))
479 -- Update and show formspec
480 self.panel_add = nil
481 advschem.show_formspec(pos, player, "slice")
484 if fields.remove and self.selected then
485 local slice_list = minetest.deserialize(meta:get_string("slices"))
486 slice_list[self.selected] = nil
487 meta:set_string("slices", minetest.serialize(renumber(slice_list)))
489 -- Update formspec
490 self.selected = 1
491 self.panel_edit = nil
492 advschem.show_formspec(pos, player, "slice")
495 if fields.edit then
496 if not self.panel_edit then
497 self.panel_edit = true
498 advschem.show_formspec(pos, player, "slice")
499 else
500 self.panel_edit = nil
501 advschem.show_formspec(pos, player, "slice")
504 end,
508 --- API
511 -- [function] Load
512 function advschem.load()
513 local res = io.open(path, "r")
514 if res then
515 marked = minetest.deserialize(res:read("*a"))
516 res:close()
519 if type(marked) ~= "table" then
520 marked = {}
524 -- [function] Save
525 function advschem.save()
526 local res = io.open(path, "w")
527 if res then
528 res:write(minetest.serialize(marked))
529 res:close()
533 --- Copies and modifies positions `pos1` and `pos2` so that each component of
534 -- `pos1` is less than or equal to the corresponding component of `pos2`.
535 -- Returns the new positions.
536 function advschem.sort_pos(pos1, pos2)
537 if not pos1 or not pos2 then
538 return
541 pos1, pos2 = table.copy(pos1), table.copy(pos2)
542 if pos1.x > pos2.x then
543 pos2.x, pos1.x = pos1.x, pos2.x
545 if pos1.y > pos2.y then
546 pos2.y, pos1.y = pos1.y, pos2.y
548 if pos1.z > pos2.z then
549 pos2.z, pos1.z = pos1.z, pos2.z
551 return pos1, pos2
554 -- [function] Prepare size
555 function advschem.size(pos)
556 local pos1 = vector.new(pos)
557 local meta = minetest.get_meta(pos)
558 local node = minetest.get_node(pos)
559 local param2 = node.param2
560 local size = {
561 x = meta:get_int("x_size"),
562 y = math.max(meta:get_int("y_size") - 1, 0),
563 z = meta:get_int("z_size"),
566 if param2 == 1 then
567 local new_pos = vector.add({x = size.z, y = size.y, z = -size.x}, pos)
568 pos1.x = pos1.x + 1
569 new_pos.z = new_pos.z + 1
570 return pos1, new_pos
571 elseif param2 == 2 then
572 local new_pos = vector.add({x = -size.x, y = size.y, z = -size.z}, pos)
573 pos1.z = pos1.z - 1
574 new_pos.x = new_pos.x + 1
575 return pos1, new_pos
576 elseif param2 == 3 then
577 local new_pos = vector.add({x = -size.z, y = size.y, z = size.x}, pos)
578 pos1.x = pos1.x - 1
579 new_pos.z = new_pos.z - 1
580 return pos1, new_pos
581 else
582 local new_pos = vector.add(size, pos)
583 pos1.z = pos1.z + 1
584 new_pos.x = new_pos.x - 1
585 return pos1, new_pos
589 -- [function] Mark region
590 function advschem.mark(pos)
591 advschem.unmark(pos)
593 local id = minetest.pos_to_string(pos)
594 local owner = minetest.get_meta(pos):get_string("owner")
595 local pos1, pos2 = advschem.size(pos)
596 pos1, pos2 = advschem.sort_pos(pos1, pos2)
598 local thickness = 0.2
599 local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2
600 local m = {}
601 local low = true
602 local offset
604 -- XY plane markers
605 for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do
606 if low then
607 offset = -0.01
608 else
609 offset = 0.01
611 local marker = minetest.add_entity({x = pos1.x + sizex - 0.5, y = pos1.y + sizey - 0.5, z = z + offset}, "advschem:display")
612 if marker ~= nil then
613 marker:set_properties({
614 visual_size={x=(sizex+0.01) * 2, y=sizey * 2},
615 collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness},
617 marker:get_luaentity().id = id
618 marker:get_luaentity().owner = owner
619 table.insert(m, marker)
621 low = false
624 low = true
625 -- YZ plane markers
626 for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do
627 if low then
628 offset = -0.01
629 else
630 offset = 0.01
633 local marker = minetest.add_entity({x = x + offset, y = pos1.y + sizey - 0.5, z = pos1.z + sizez - 0.5}, "advschem:display")
634 if marker ~= nil then
635 marker:set_properties({
636 visual_size={x=(sizez+0.01) * 2, y=sizey * 2},
637 collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez},
639 marker:set_yaw(math.pi / 2)
640 marker:get_luaentity().id = id
641 marker:get_luaentity().owner = owner
642 table.insert(m, marker)
644 low = false
647 advschem.markers[id] = m
648 return true
651 -- [function] Unmark region
652 function advschem.unmark(pos)
653 local id = minetest.pos_to_string(pos)
654 if advschem.markers[id] then
655 local retval
656 for _, entity in ipairs(advschem.markers[id]) do
657 entity:remove()
658 retval = true
660 return retval
665 --- Registrations
668 -- [event] Save data on shut down
669 minetest.register_on_shutdown(advschem.save)
671 -- [event] Transfer probabilities and force place on place node
672 minetest.register_on_placenode(function(pos, newnode, player, oldnode, itemstack)
673 local smeta = itemstack:get_meta():to_table().fields
675 local prob
676 if smeta.advschem_prob and tonumber(smeta.advschem_prob) then
677 prob = tonumber(smeta.advschem_prob)
678 elseif newnode.name == "advschem:void" then
679 prob = 0
680 else
681 return
684 local px, py, pz = pos.x, pos.y, pos.z
685 for strpos, r in pairs(marked) do
686 local ap1, ap2 = r.pos1, r.pos2
687 if (px >= ap1.x and px <= ap2.x) and
688 (py >= ap1.y and py <= ap2.y) and
689 (pz >= ap1.z and pz <= ap2.z) then
690 local realpos = minetest.string_to_pos(strpos)
691 local node = minetest.get_node_or_nil(realpos)
693 if node and node.name == "advschem:creator" then
694 local meta = minetest.get_meta(realpos)
695 local prob_list = minetest.deserialize(meta:get_string("prob_list"))
697 local force_place = false
698 if newnode.name ~= "advschem:void" and smeta.advschem_force_place == "true" then
699 force_place = true
702 local ostrpos = minetest.pos_to_string(pos)
703 prob_list[ostrpos] = {
704 pos = pos,
705 prob = prob,
706 force_place = force_place,
708 meta:set_string("prob_list", minetest.serialize(prob_list))
712 end)
714 -- [event] Remove probability on break node
715 minetest.register_on_dignode(function(pos, oldnode, player)
716 local original_strpos = minetest.pos_to_string(pos)
717 local px, py, pz = pos.x, pos.y, pos.z
718 for strpos, r in pairs(marked) do
719 local ap1, ap2 = r.pos1, r.pos2
720 if (px >= ap1.x and px <= ap2.x) and
721 (py >= ap1.y and py <= ap2.y) and
722 (pz >= ap1.z and pz <= ap2.z) then
723 local realpos = minetest.string_to_pos(strpos)
724 local meta = minetest.get_meta(realpos)
725 local prob_list = minetest.deserialize(meta:get_string("prob_list"))
727 if prob_list then
728 for _, i in pairs(prob_list) do
729 if _ == original_strpos then
730 prob_list[_] = nil
735 meta:set_string("prob_list", minetest.serialize(prob_list))
738 end)
740 -- [priv] schematic_override
741 minetest.register_privilege("schematic_override", {
742 description = "Allows you to access advschem nodes not owned by you",
743 give_to_singleplayer = false,
746 -- [node] Schematic creator
747 minetest.register_node("advschem:creator", {
748 description = "Schematic Creator",
749 tiles = {"advschem_creator_top.png", "advschem_creator_bottom.png",
750 "advschem_creator_sides.png"},
751 groups = { dig_immediate = 3},
752 paramtype2 = "facedir",
753 is_ground_content = false,
755 after_place_node = function(pos, player)
756 local name = player:get_player_name()
757 local meta = minetest.get_meta(pos)
759 meta:set_string("owner", name)
760 meta:set_string("infotext", "Schematic Creator\n(owned by "..name..")")
761 meta:set_string("prob_list", minetest.serialize({}))
762 meta:set_string("slices", minetest.serialize({}))
764 local node = minetest.get_node(pos)
765 local dir = minetest.facedir_to_dir(node.param2)
767 meta:set_int("x_size", 1)
768 meta:set_int("y_size", 1)
769 meta:set_int("z_size", 1)
771 local inv = meta:get_inventory()
772 inv:set_size("probability", 1)
774 local pos1, pos2 = advschem.size(pos)
775 marked[minetest.pos_to_string(pos)] = {
776 pos1 = pos1,
777 pos2 = pos2,
780 -- Don't take item from itemstack
781 return true
782 end,
783 can_dig = function(pos, player)
784 local name = player:get_player_name()
785 local meta = minetest.get_meta(pos)
786 if meta:get_string("owner") == name or
787 minetest.check_player_privs(player, "schematic_override") == true then
788 return true
791 return false
792 end,
793 on_rightclick = function(pos, node, player)
794 local meta = minetest.get_meta(pos)
795 local name = player:get_player_name()
796 if meta:get_string("owner") == name or
797 minetest.check_player_privs(player, "schematic_override") == true then
798 -- Get player attribute
799 local tab = player:get_attribute("advschem:tab")
800 if not forms[tab] then
801 tab = "main"
804 advschem.show_formspec(pos, player, tab, true)
806 end,
807 after_destruct = function(pos)
808 advschem.unmark(pos)
809 end,
811 -- Update formspec when items are added to or taken from the probability inventory
812 on_metadata_inventory_put = function(pos, listname, index, stack, player)
813 if listname == "probability" then
814 advschem.show_formspec(pos, player, "prob", true)
816 end,
817 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
818 if listname == "probability" then
819 local itemstring = stack:get_name()
820 if itemstring == "advschem:void" then
821 return 0
822 elseif minetest.registered_items[itemstring].type ~= "node" then
823 return 0
826 return stack:get_count()
827 end,
828 on_metadata_inventory_take = function(pos, listname, index, stack, player)
829 if listname == "probability" then
830 advschem.show_formspec(pos, player, "prob", true)
832 end,
835 minetest.register_node("advschem:void", {
836 description = "Schematic Void",
837 tiles = { "advschem_void.png" },
838 drawtype = "nodebox",
839 is_ground_content = false,
840 paramtype = "light",
841 walkable = false,
842 sunlight_propagates = true,
843 node_box = {
844 type = "fixed",
845 fixed = {
846 { -4/16, -4/16, -4/16, 4/16, 4/16, 4/16 },
849 groups = { dig_immediate = 3},
852 -- [entity] Display
853 minetest.register_entity("advschem:display", {
854 initial_properties = {
855 visual = "upright_sprite",
856 textures = {"advschem_border.png"},
857 visual_size = {x=10, y=10},
858 physical = false,
860 on_step = function(self, dtime)
861 if not self.id then
862 self.object:remove()
863 elseif not advschem.markers[self.id] then
864 self.object:remove()
866 end,
867 on_punch = function(self, hitter)
868 local pos = minetest.string_to_pos(self.id)
869 local meta = minetest.get_meta(pos)
870 if meta:get_string("owner") == hitter:get_player_name() or
871 minetest.check_player_privs(hitter, "schematic_override") == true then
872 advschem.unmark(pos)
873 meta:set_string("schem_border", "false")
875 end,
876 on_activate = function(self)
877 self.object:set_armor_groups({immortal = 1})
878 end,
881 -- [chatcommand] Place schematic
882 minetest.register_chatcommand("placeschem", {
883 description = "Place schematic at the position specified or the current "..
884 "player position (loaded from "..minetest.get_worldpath().."/schems/)",
885 privs = {debug = true},
886 params = "[<schematic name>.mts] (<x> <y> <z>)",
887 func = function(name, param)
888 local schem, p = string.match(param, "^([^ ]+) *(.*)$")
889 local pos = minetest.string_to_pos(p)
891 if not pos then
892 pos = minetest.get_player_by_name(name):get_pos()
895 return true, "Success: "..dump(minetest.place_schematic(pos,
896 minetest.get_worldpath().."/schems/"..schem..".mts", "random", nil, false))
897 end,
901 --- Load Data
904 advschem.load()