A minetest mod for mapmaking
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

961 lines
27KB

  1. -- Arguments
  2. -- gui: The GUI API
  3. -- gui_skin: The GUI skin
  4. -- audio: The audio playback API
  5. -- maps: The map API
  6. -- materials: The material API
  7. -- map_item: The map item API
  8. -- settings: The mod settings
  9. local gui, gui_skin, audio, maps, materials, map_item, settings = ...;
  10. local SCALE_SMALL = 1;
  11. local SCALE_MEDIUM = 2;
  12. local SCALE_LARGE = 4;
  13. local SCALE_HUGE = 8;
  14. -- Get the material cost for the given map scale and detail level
  15. --
  16. -- scale: The map scale
  17. -- detail: The detail level
  18. --
  19. -- Returns a table with material costs
  20. local function get_material_cost(scale, detail)
  21. local paper = scale * 4;
  22. local pigment = detail * 5;
  23. if scale == SCALE_SMALL then
  24. pigment = pigment + 5;
  25. elseif scale == SCALE_MEDIUM then
  26. pigment = pigment + 10;
  27. elseif scale == SCALE_LARGE then
  28. pigment = pigment + 15;
  29. elseif scale == SCALE_HUGE then
  30. pigment = pigment + 20;
  31. end
  32. return {
  33. paper = math.max(paper, 0),
  34. pigment = math.max(pigment, 0),
  35. };
  36. end
  37. -- Get the material cost of the craft settings from the given table metadata
  38. --
  39. -- meta: The metadata to read
  40. --
  41. -- Returns a table with the material costs, and a boolean indicating if the
  42. -- costs were positive or negative before clamping.
  43. local function get_craft_material_cost(meta)
  44. local cost = get_material_cost(meta:get_int("scale") or SCALE_SMALL, meta:get_int("detail") or 0);
  45. local stack = meta:get_inventory():get_stack("output", 1);
  46. local is_positive = true;
  47. if stack:get_name() == "cartographer:map" then
  48. local smeta = stack:get_meta();
  49. local sub_cost = get_material_cost(smeta:get_int("cartographer:scale") or SCALE_SMALL,
  50. (smeta:get_int("cartographer:detail") or 1) - 1);
  51. is_positive = cost.paper >= sub_cost.paper and cost.pigment >= sub_cost.pigment;
  52. cost.paper = math.max(cost.paper - sub_cost.paper, 0);
  53. cost.pigment = math.max(cost.pigment - sub_cost.pigment, 0);
  54. end
  55. return cost, is_positive;
  56. end
  57. -- Check if the given table metadata has enough materials to cover the given
  58. -- cost table.
  59. --
  60. -- cost: A table of material costs
  61. -- meta: The metadata
  62. --
  63. -- Returns true if the table's materials can cover the cost
  64. local function can_afford(cost, meta)
  65. return cost.paper + cost.pigment > 0
  66. and cost.paper <= meta:get_int("paper")
  67. and cost.pigment <= meta:get_int("pigment");
  68. end
  69. -- Get the material cost of the copy settings from the given table metadata
  70. --
  71. -- meta: The metadata to read
  72. --
  73. -- Returns a table with the material costs
  74. local function get_copy_material_cost(meta)
  75. local inv = meta:get_inventory();
  76. local in_stack = inv:get_stack("copy_input", 1);
  77. local out_stack = inv:get_stack("copy_output", 1);
  78. if out_stack:is_empty() and in_stack:get_name() == "cartographer:map" then
  79. local smeta = in_stack:get_meta();
  80. local scale = smeta:get_int("cartographer:scale") or SCALE_SMALL;
  81. local detail = smeta:get_int("cartographer:detail") or 1;
  82. return get_material_cost(scale, detail - 1);
  83. end
  84. return {
  85. paper = 0,
  86. pigment = 0,
  87. };
  88. end
  89. local fs = {};
  90. -- Draw a 1px thick horizontal separator formspec element
  91. --
  92. -- y: The y position of the separator
  93. -- skin: A 9-slice background skin table
  94. --
  95. -- Returns a formspec string
  96. function fs.separator(y, skin)
  97. return gui.bg9 {
  98. x = 0.1,
  99. y = y,
  100. w = 10.05,
  101. h = 0.01,
  102. skin = skin,
  103. };
  104. end
  105. -- Draw all the essential formspec data (size, background, styles, tabs)
  106. --
  107. -- w: The width of the formspec
  108. -- h: The height of the formspec
  109. -- rank: An into defining the 'rank' of the table being displayed
  110. -- tab: An int defining the index of the selected tab
  111. -- skin: A formspec skin table
  112. --
  113. -- Returns a formspec string
  114. function fs.header(w, h, rank, tab, skin)
  115. local data = {
  116. gui.formspec {
  117. w = w,
  118. h = h,
  119. bg = skin.background,
  120. },
  121. gui.bg9 {
  122. x = 0.125,
  123. y = 0.125,
  124. w = w - 0.25,
  125. h = h - 0.25,
  126. skin = skin.inner_background,
  127. },
  128. gui.style_type {
  129. selector = "button",
  130. properties = {
  131. noclip = true,
  132. border = false,
  133. bgimg = skin.tab.texture .. ".png",
  134. bgimg_hovered = skin.tab.hovered_texture .. ".png",
  135. bgimg_pressed = skin.tab.pressed_texture .. ".png",
  136. bgimg_middle = skin.tab.radius,
  137. textcolor = skin.tab.font_color,
  138. }
  139. },
  140. gui.style {
  141. selector = "tab" .. tostring(tab),
  142. properties = {
  143. bgimg = skin.tab.selected_texture .. ".png",
  144. bgimg_hovered = skin.tab.selected_texture .. ".png",
  145. bgimg_pressed = skin.tab.selected_texture .. ".png",
  146. }
  147. },
  148. gui.button {
  149. x = 0.25,
  150. y = -0.425,
  151. w = 1.5,
  152. h = 0.55,
  153. id = "tab1",
  154. text = "Materials"
  155. },
  156. gui.button {
  157. x = 1.75,
  158. y = -0.425,
  159. w = 1.5,
  160. h = 0.55,
  161. id = "tab2",
  162. text = "Create Map"
  163. },
  164. };
  165. if rank >= 2 then
  166. table.insert(data, gui.button {
  167. x = 3.25,
  168. y = -0.425,
  169. w = 1.5,
  170. h = 0.55,
  171. id = "tab3",
  172. text = "Copy Map"
  173. });
  174. end
  175. table.insert(data, gui.style_type {
  176. selector = "button",
  177. properties = {
  178. bgimg = skin.button.texture .. ".png",
  179. bgimg_hovered = skin.button.hovered_texture .. ".png",
  180. bgimg_pressed = skin.button.pressed_texture .. ".png",
  181. bgimg_middle = skin.button.radius,
  182. textcolor = skin.button.font_color,
  183. },
  184. });
  185. table.insert(data, gui.style {
  186. selector = "disabled_button",
  187. properties = {
  188. bgimg = "",
  189. bgimg_hovered = "",
  190. bgimg_pressed = "",
  191. textcolor = skin.button.disabled_font_color,
  192. },
  193. });
  194. return table.concat(data);
  195. end
  196. -- Draw material counters from a table's metadata
  197. --
  198. -- x: The x position of the labels
  199. -- y: The y position of the labels
  200. -- meta: A metadata object containing the material quantities
  201. -- skin: A formspec skin table
  202. --
  203. -- Returns a formspec string
  204. function fs.materials(x, y, meta, skin)
  205. return gui.container {
  206. x = x,
  207. y = y,
  208. gui.bg9 {
  209. x = 0,
  210. y = 0.125,
  211. w = 1.0,
  212. h = 0.25,
  213. skin = skin.label,
  214. },
  215. gui.image {
  216. x = 0.125,
  217. y = 0.125,
  218. w = 0.25,
  219. h = 0.25,
  220. image = skin.paper_texture .. ".png",
  221. },
  222. gui.label {
  223. x = 0.375,
  224. y = 0.25,
  225. textcolor = skin.label.font_color,
  226. text = string.format("x %d", meta:get_int("paper")),
  227. },
  228. gui.bg9 {
  229. x = 1.25,
  230. y = 0.125,
  231. w = 1.0,
  232. h = 0.25,
  233. skin = skin.label,
  234. },
  235. gui.image {
  236. x = 1.375,
  237. y = 0.125,
  238. w = 0.25,
  239. h = 0.25,
  240. image = skin.pigment_texture .. ".png",
  241. },
  242. gui.label {
  243. x = 1.625,
  244. y = 0.25,
  245. textcolor = skin.label.font_color,
  246. text = string.format("x %d", meta:get_int("pigment")),
  247. },
  248. };
  249. end
  250. -- Draw a label with material costs from a table
  251. --
  252. -- x: The x position of the interface
  253. -- y: The y position of the interface
  254. -- cost: A table of material costs, with string keys for the material
  255. -- names and integer values
  256. -- skin: A formspec skin table
  257. --
  258. -- Returns a formspec string
  259. function fs.cost(x, y, cost, skin)
  260. local data = {
  261. gui.bg9 {
  262. x = x,
  263. y = y - 0.125,
  264. w = 1,
  265. h = 0.5,
  266. skin = skin.label,
  267. },
  268. }
  269. local i = 0;
  270. for name,value in pairs(cost) do
  271. local texture = "";
  272. if name == "paper" then
  273. texture = skin.paper_texture .. ".png";
  274. elseif name == "pigment" then
  275. texture = skin.pigment_texture .. ".png";
  276. end
  277. table.insert(data, gui.image {
  278. x = x + 0.125,
  279. y = y + (i * 0.25) - 0.125,
  280. w = 0.25,
  281. h = 0.25,
  282. image = texture,
  283. });
  284. table.insert(data, gui.label {
  285. x = x + 0.375,
  286. y = y + (i * 0.25);
  287. w = 0.25,
  288. h = 0.25,
  289. textcolor = skin.label.font_color,
  290. text = string.format("x %d", value);
  291. });
  292. i = i + 1;
  293. end
  294. return table.concat(data);
  295. end
  296. -- Draw the material conversion tab UI
  297. --
  298. -- x: The x position of the interface
  299. -- y: The y position of the interface
  300. -- pos: The table position (for displaying the inventory)
  301. -- skin: A formspec skin table
  302. --
  303. -- Returns a formspec string
  304. function fs.convert(x, y, pos, skin)
  305. local meta = minetest.get_meta(pos);
  306. local value = materials.get_stack_value(meta:get_inventory():get_stack("input", 1));
  307. return gui.container {
  308. x = x,
  309. y = y,
  310. gui.inventory {
  311. x = 0,
  312. y = 0,
  313. w = 1,
  314. h = 1,
  315. location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
  316. id = "input",
  317. bg = skin.slot,
  318. tooltip = "Place items here to convert\nthem into mapmaking materials",
  319. },
  320. gui.button {
  321. x = 2.5,
  322. y = 0.25,
  323. w = 2,
  324. h = 0.5,
  325. id = "convert",
  326. text = "Convert Materials",
  327. disabled = value.paper + value.pigment <= 0,
  328. },
  329. fs.cost(1.25, 0.375, value, skin),
  330. };
  331. end
  332. -- Draw the map crafting tab UI
  333. --
  334. -- x: The x position of the interface
  335. -- y: The y position of the interface
  336. -- pos: The table position (for displaying the inventory)
  337. -- rank: The 'rank' of the table
  338. -- meta: A metadata object containing the table settings and material
  339. -- quantities
  340. -- skin: A formspec skin table
  341. --
  342. -- Returns a formspec string
  343. function fs.craft(x, y, pos, rank, meta, skin)
  344. local cost, is_positive = get_craft_material_cost(meta);
  345. local stack = meta:get_inventory():get_stack("output", 1);
  346. local data = {
  347. x = x,
  348. y = y,
  349. gui.inventory {
  350. x = 0,
  351. y = 1,
  352. w = 1,
  353. h = 1,
  354. location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
  355. id = "output",
  356. bg = skin.slot,
  357. tooltip = "Place a map here to upgrade it,\nor leave empty to craft",
  358. },
  359. gui.button {
  360. x = 2.5,
  361. y = 1.25,
  362. w = 2,
  363. h = 0.5,
  364. id = "craft",
  365. text = stack:get_name() == "cartographer:map" and "Upgrade Map" or "Craft Map",
  366. disabled = not (is_positive and can_afford(cost, meta)),
  367. },
  368. fs.cost(1.25, 1.375, cost, skin),
  369. gui.style {
  370. selector = string.format("%dx,%d", meta:get_int("scale"), meta:get_int("detail") + 1),
  371. properties = {
  372. bgimg = skin.button.selected_texture .. ".png",
  373. bgimg_hovered = skin.button.selected_texture .. ".png",
  374. bgimg_pressed = skin.button.selected_texture .. ".png",
  375. },
  376. },
  377. gui.label {
  378. x = 0,
  379. y = 0,
  380. text = "Detail Level",
  381. textcolor = skin.label.font_color,
  382. },
  383. };
  384. if rank > 1 then
  385. table.insert(data, gui.button {
  386. x = 2.5,
  387. y = 0.25,
  388. w = 0.5,
  389. h = 0.5,
  390. id = "1x",
  391. text = "1x",
  392. });
  393. table.insert(data, gui.button {
  394. x = 3.0,
  395. y = 0.25,
  396. w = 0.5,
  397. h = 0.5,
  398. id = "2x",
  399. text = "2x",
  400. });
  401. if rank > 2 then
  402. table.insert(data, gui.button {
  403. x = 3.5,
  404. y = 0.25,
  405. w = 0.5,
  406. h = 0.5,
  407. id = "4x",
  408. text = "4x",
  409. });
  410. table.insert(data, gui.button {
  411. x = 4.0,
  412. y = 0.25,
  413. w = 0.5,
  414. h = 0.5,
  415. id = "8x",
  416. text = "8x",
  417. });
  418. end
  419. end
  420. table.insert(data, gui.button {
  421. x = 0,
  422. y = 0.25,
  423. w = 0.5,
  424. h = 0.5,
  425. id = "1",
  426. text = "1",
  427. });
  428. table.insert(data, gui.button {
  429. x = 0.5,
  430. y = 0.25,
  431. w = 0.5,
  432. h = 0.5,
  433. id = "2",
  434. text = "2",
  435. });
  436. if rank > 1 then
  437. table.insert(data, gui.button {
  438. x = 1.0,
  439. y = 0.25,
  440. w = 0.5,
  441. h = 0.5,
  442. id = "3",
  443. text = "3",
  444. });
  445. if rank > 2 then
  446. table.insert(data, gui.button {
  447. x = 1.5,
  448. y = 0.25,
  449. w = 0.5,
  450. h = 0.5,
  451. id = "4",
  452. text = "4",
  453. });
  454. end
  455. end
  456. return gui.container(data);
  457. end
  458. -- Draw the map copying tab UI
  459. --
  460. -- x: The x position of the interface
  461. -- y: The y position of the interface
  462. -- pos: The table position (for displaying the inventory)
  463. -- skin: A formspec skin table
  464. --
  465. -- Returns a formspec string
  466. function fs.copy(x, y, pos, skin)
  467. local meta = minetest.get_meta(pos);
  468. local costs = get_copy_material_cost(meta);
  469. return gui.container {
  470. x = x,
  471. y = y,
  472. gui.inventory {
  473. x = 0,
  474. y = 0,
  475. w = 1,
  476. h = 1,
  477. location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
  478. id = "copy_input",
  479. bg = skin.slot,
  480. },
  481. gui.inventory {
  482. x = 8.75,
  483. y = 0,
  484. w = 1,
  485. h = 1,
  486. location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z),
  487. id = "copy_output",
  488. bg = skin.slot,
  489. },
  490. gui.button {
  491. x = 2.5,
  492. y = 0.25,
  493. w = 2,
  494. h = 0.5,
  495. id = "copy",
  496. text = "Copy Map",
  497. disabled = not can_afford(costs, meta),
  498. },
  499. fs.cost(1.25, 0.375, costs, skin),
  500. };
  501. end
  502. -- Draw the player's inventory
  503. --
  504. -- x: The x position of the inventory
  505. -- y: The y position of the inventory
  506. -- skin: A formspec skin table
  507. --
  508. -- Returns a formspec string
  509. function fs.inv(x, y, skin)
  510. return gui.inventory {
  511. x = x,
  512. y = y,
  513. w = 8,
  514. h = 4,
  515. location = "current_player",
  516. id = "main",
  517. bg = skin.slot,
  518. };
  519. end
  520. local player_tables = {};
  521. -- Show the table formspec to the specified player
  522. -- The player must be recorded in player_tables in order to receive
  523. -- a formspec.
  524. --
  525. -- player: The player's name
  526. local function table_formspec(player)
  527. local data = player_tables[player];
  528. local pos = data.pos;
  529. if not pos then
  530. return;
  531. end
  532. local meta = minetest.get_meta(pos);
  533. local rank = 1;
  534. local skin = gui_skin.table_skins.simple_table;
  535. local name = minetest.get_node(pos).name;
  536. if name == "cartographer:standard_table" then
  537. rank = 2;
  538. skin = gui_skin.table_skins.standard_table;
  539. elseif name == "cartographer:advanced_table" then
  540. rank = 3;
  541. skin = gui_skin.table_skins.advanced_table;
  542. end
  543. if data.tab == 1 then
  544. minetest.show_formspec(player, "cartographer:table",
  545. fs.header(10.25, 7.375, rank, data.tab, skin) ..
  546. fs.materials(0.25, 0.1875, meta, skin) ..
  547. fs.separator(0.6875, skin.separator) ..
  548. fs.convert(0.25, 0.875, pos, skin) ..
  549. fs.separator(2.125, skin.separator) ..
  550. fs.inv(0.25, 2.375, skin)
  551. );
  552. elseif data.tab == 2 then
  553. minetest.show_formspec(player, "cartographer:table",
  554. fs.header(10.25, 8.25, rank, data.tab, skin) ..
  555. fs.materials(0.25, 0.1875, meta, skin) ..
  556. fs.separator(0.6875, skin.separator) ..
  557. fs.craft(0.25, 0.875, pos, rank, meta, skin) ..
  558. fs.separator(3, skin.separator) ..
  559. fs.inv(0.25, 3.25, skin)
  560. );
  561. elseif data.tab == 3 then
  562. minetest.show_formspec(player, "cartographer:table",
  563. fs.header(10.25, 7.375, rank, data.tab, skin) ..
  564. fs.materials(0.25, 0.1875, meta, skin) ..
  565. fs.separator(0.6875, skin.separator) ..
  566. fs.copy(0.25, 0.875, pos, skin) ..
  567. fs.separator(2.125, skin.separator) ..
  568. fs.inv(0.25, 2.375, skin)
  569. );
  570. end
  571. end
  572. -- Called when a player sends input to the server from a formspec
  573. -- This callback handles player input in the table formspec
  574. --
  575. -- player: The player who sent the input
  576. -- name: The formspec name
  577. -- fields: A table containing the input
  578. minetest.register_on_player_receive_fields(function(player, name, fields)
  579. if name == "cartographer:table" then
  580. local meta = minetest.get_meta(player_tables[player:get_player_name()].pos);
  581. local rank = 1;
  582. local node_name = minetest.get_node(player_tables[player:get_player_name()].pos).name;
  583. if node_name == "cartographer:standard_table" then
  584. rank = 2;
  585. elseif node_name == "cartographer:advanced_table" then
  586. rank = 3;
  587. end
  588. if fields["convert"] then
  589. local inv = meta:get_inventory();
  590. local stack = inv:get_stack("input", 1);
  591. local value = materials.get_stack_value(stack);
  592. if value.paper + value.pigment > 0 then
  593. meta:set_int("paper", meta:get_int("paper") + value.paper);
  594. meta:set_int("pigment", meta:get_int("pigment") + value.pigment);
  595. inv:set_stack("input", 1, ItemStack(nil));
  596. end
  597. elseif fields["craft"] then
  598. local size = meta:get_int("size");
  599. local detail = meta:get_int("detail");
  600. local scale = meta:get_int("scale");
  601. local cost, is_positive = get_craft_material_cost(meta);
  602. if is_positive and can_afford(cost, meta) then
  603. meta:set_int("paper", meta:get_int("paper") - cost.paper);
  604. meta:set_int("pigment", meta:get_int("pigment") - cost.pigment);
  605. local inv = meta:get_inventory();
  606. local stack = inv:get_stack("output", 1);
  607. if stack:is_empty() then
  608. inv:set_stack("output", 1, map_item.create(size, 1 + detail, scale));
  609. else
  610. local smeta = stack:get_meta();
  611. smeta:set_int("cartographer:detail", 1 + detail);
  612. map_item.resize(smeta, size);
  613. map_item.rescale(smeta, scale);
  614. local map = maps.get(smeta:get_int("cartographer:map_id"));
  615. if map then
  616. map.detail = 1 + detail;
  617. end
  618. inv:set_stack("output", 1, stack);
  619. end
  620. audio.play_feedback("cartographer_write", player);
  621. end
  622. elseif fields["copy"] and rank >= 2 then
  623. local cost = get_copy_material_cost(meta);
  624. if can_afford(cost, meta) then
  625. meta:set_int("paper", meta:get_int("paper") - cost.paper);
  626. meta:set_int("pigment", meta:get_int("pigment") - cost.pigment);
  627. audio.play_feedback("cartographer_write", player);
  628. local inv = meta:get_inventory();
  629. inv:set_stack("copy_output", 1, map_item.copy(inv:get_stack("copy_input", 1)));
  630. end
  631. elseif fields["1"] then
  632. meta:set_int("detail", 0);
  633. elseif fields["2"] then
  634. meta:set_int("detail", 1);
  635. elseif fields["3"] and rank > 1 then
  636. meta:set_int("detail", 2);
  637. elseif fields["4"] and rank > 2 then
  638. meta:set_int("detail", 3);
  639. elseif fields["1x"] and rank > 1 then
  640. meta:set_int("scale", SCALE_SMALL);
  641. elseif fields["2x"] and rank > 1 then
  642. meta:set_int("scale", SCALE_MEDIUM);
  643. elseif fields["4x"] and rank > 2 then
  644. meta:set_int("scale", SCALE_LARGE);
  645. elseif fields["8x"] and rank > 2 then
  646. meta:set_int("scale", SCALE_HUGE);
  647. elseif fields["tab1"] then
  648. player_tables[player:get_player_name()].tab = 1;
  649. audio.play_feedback("cartographer_turn_page", player);
  650. elseif fields["tab2"] then
  651. player_tables[player:get_player_name()].tab = 2;
  652. audio.play_feedback("cartographer_turn_page", player);
  653. elseif fields["tab3"] and rank >= 2 then
  654. player_tables[player:get_player_name()].tab = 3;
  655. audio.play_feedback("cartographer_turn_page", player);
  656. end
  657. if not fields["quit"] then
  658. table_formspec(player:get_player_name());
  659. end
  660. end
  661. end);
  662. -- Called after a table is placed. Sets up the table's inventory and metadata.
  663. --
  664. -- pos: The node's position
  665. local function setup_table_node(pos)
  666. local meta = minetest.get_meta(pos);
  667. meta:get_inventory():set_size("input", 1);
  668. meta:get_inventory():set_size("output", 1);
  669. meta:get_inventory():set_size("copy_input", 1);
  670. meta:get_inventory():set_size("copy_output", 1);
  671. meta:set_int("size", settings.default_size);
  672. meta:set_int("scale", SCALE_SMALL);
  673. meta:set_int("detail", 0);
  674. end
  675. -- Called when the player tries to put an item into one of the table's
  676. -- inventories.
  677. --
  678. -- listname: The name of the inventory the item is being placed in.
  679. -- stack: The itemstack
  680. --
  681. -- Returns 0 if the place is invalid; otherwise, returns the number of items
  682. -- that can be placed.
  683. local function table_can_put(_, listname, _, stack, _)
  684. if listname == "copy_output" then
  685. return 0;
  686. end
  687. if stack:get_name() ~= "cartographer:map" and (listname == "output" or listname == "copy_input") then
  688. return 0;
  689. end
  690. return stack:get_count();
  691. end
  692. -- Called when the player tries to move an item between two of the table's
  693. -- inventories.
  694. --
  695. -- to_list: The name of the inventory the item is being placed in.
  696. -- count: The number of items being moved
  697. --
  698. -- Returns 0 if the move is invalid; otherwise, returns the number of items
  699. -- that can be moved.
  700. local function table_can_move(_, _, _, to_list, _, count, _)
  701. if to_list == "copy_output" then
  702. return 0;
  703. end
  704. return count;
  705. end
  706. -- Called when a change occurs in a table's inventory
  707. --
  708. -- pos: The node's position
  709. -- listname: The name of the changed inventory list
  710. local function table_on_items_changed(pos, listname, _, _, _)
  711. for player, data in pairs(player_tables) do
  712. if vector.equals(pos, data.pos) and (
  713. (data.tab == 1 and listname == "input")
  714. or (data.tab == 2 and listname == "output")
  715. or (data.tab == 3 and listname == "copy_input")) then
  716. table_formspec(player);
  717. end
  718. end
  719. end
  720. -- The table node definitions
  721. minetest.register_node("cartographer:simple_table", {
  722. description = "Shabby Cartographer's Table",
  723. drawtype = "mesh",
  724. mesh = gui_skin.table_skins.simple_table.node_mesh,
  725. tiles = { gui_skin.table_skins.simple_table.node_texture },
  726. paramtype2 = "facedir",
  727. groups = {
  728. choppy = 2,
  729. oddly_breakable_by_hand = 2,
  730. },
  731. selection_box = {
  732. type = "fixed",
  733. fixed = {
  734. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  735. },
  736. },
  737. collision_box = {
  738. type = "fixed",
  739. fixed = {
  740. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  741. },
  742. },
  743. on_rightclick = function(_, _, player, _, pointed_thing)
  744. player_tables[player:get_player_name()] = {
  745. pos = minetest.get_pointed_thing_position(pointed_thing),
  746. tab = 1,
  747. };
  748. audio.play_feedback("cartographer_open_map", player);
  749. table_formspec(player:get_player_name())
  750. end,
  751. after_place_node = setup_table_node,
  752. allow_metadata_inventory_move = table_can_move,
  753. allow_metadata_inventory_put = table_can_put,
  754. on_metadata_inventory_put = table_on_items_changed,
  755. on_metadata_inventory_take = table_on_items_changed,
  756. });
  757. minetest.register_node("cartographer:standard_table", {
  758. description = "Simple Cartographer's Table",
  759. drawtype = "mesh",
  760. mesh = gui_skin.table_skins.standard_table.node_mesh,
  761. tiles = { gui_skin.table_skins.standard_table.node_texture },
  762. paramtype2 = "facedir",
  763. groups = {
  764. choppy = 2,
  765. oddly_breakable_by_hand = 2,
  766. },
  767. selection_box = {
  768. type = "fixed",
  769. fixed = {
  770. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  771. },
  772. },
  773. collision_box = {
  774. type = "fixed",
  775. fixed = {
  776. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  777. },
  778. },
  779. on_rightclick = function(_, _, player, _, pointed_thing)
  780. player_tables[player:get_player_name()] = {
  781. pos = minetest.get_pointed_thing_position(pointed_thing),
  782. tab = 1,
  783. };
  784. audio.play_feedback("cartographer_open_map", player);
  785. table_formspec(player:get_player_name())
  786. end,
  787. after_place_node = setup_table_node,
  788. allow_metadata_inventory_move = table_can_move,
  789. allow_metadata_inventory_put = table_can_put,
  790. on_metadata_inventory_put = table_on_items_changed,
  791. on_metadata_inventory_take = table_on_items_changed,
  792. });
  793. minetest.register_node("cartographer:advanced_table", {
  794. description = "Advanced Cartographer's Table",
  795. drawtype = "mesh",
  796. mesh = gui_skin.table_skins.advanced_table.node_mesh,
  797. tiles = { gui_skin.table_skins.advanced_table.node_texture },
  798. paramtype2 = "facedir",
  799. groups = {
  800. choppy = 2,
  801. oddly_breakable_by_hand = 2,
  802. },
  803. selection_box = {
  804. type = "fixed",
  805. fixed = {
  806. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  807. },
  808. },
  809. collision_box = {
  810. type = "fixed",
  811. fixed = {
  812. {-0.5, -0.5, -0.375, 0.5, 0.6875, 0.375},
  813. },
  814. },
  815. on_rightclick = function(_, _, player, _, pointed_thing)
  816. player_tables[player:get_player_name()] = {
  817. pos = minetest.get_pointed_thing_position(pointed_thing),
  818. tab = 1,
  819. };
  820. audio.play_feedback("cartographer_open_map", player);
  821. table_formspec(player:get_player_name())
  822. end,
  823. after_place_node = setup_table_node,
  824. allow_metadata_inventory_move = table_can_move,
  825. allow_metadata_inventory_put = table_can_put,
  826. on_metadata_inventory_put = table_on_items_changed,
  827. on_metadata_inventory_take = table_on_items_changed,
  828. });