init.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. local function player_wields_tools(user)
  2. local chisel_index = user:get_wield_index()
  3. local hammer_index = chisel_index + 1
  4. local inv = user:get_inventory()
  5. local chisel_stack = inv:get_stack("main", chisel_index)
  6. local chisel_name = chisel_stack:get_name()
  7. local hammer_stack = inv:get_stack("main", hammer_index)
  8. local hammer_name = hammer_stack:get_name()
  9. if chisel_name ~= "engraver:chisel" then
  10. return false
  11. end
  12. if hammer_name ~= "xdecor:hammer" and hammer_name ~= "anvil:hammer" then
  13. return false
  14. end
  15. return true
  16. end
  17. local function node_can_be_chiseled(pos)
  18. local node = minetest.get_node(pos)
  19. local ndef = minetest.registered_nodes[node.name]
  20. if not ndef then
  21. return false
  22. end
  23. -- Check node drawtype (must be full node).
  24. local dt = ndef.drawtype
  25. if dt ~= "normal" and dt ~= "glasslike" and dt ~= "glasslike_framed" and dt ~= "glasslike_framed_optional" and dt ~= "allfaces" and dt ~= "allfaces_optional" then
  26. return false
  27. end
  28. -- Check node groups (must be stone, brick or block).
  29. local groups = ndef.groups or {}
  30. if (groups.stone and groups.stone > 0) or (groups.brick and groups.brick > 0) or (groups.block and groups.block > 0) then
  31. -- Do nothing.
  32. else
  33. return false
  34. end
  35. -- Check meta (cannot have infotext or formspec, or must have been previously chiseled).
  36. local meta = minetest.get_meta(pos)
  37. local data = meta:to_table() or {fields={}, inventory={}}
  38. -- Any inventory fields means this node can't be engraved.
  39. for k, v in pairs(data.inventory) do
  40. return false
  41. end
  42. local was_engraved = false
  43. local was_polished = false
  44. local has_other_fields = false
  45. local has_infotext = false
  46. for k, v in pairs(data.fields) do
  47. if k == "engraver_chiseled" then
  48. was_engraved = true
  49. elseif k == "infotext" then
  50. has_infotext = true
  51. elseif k == "chiseled_text" or k == "chiseled_date" then
  52. -- Nothing to be done. Ignore these fields.
  53. elseif k == "chiseled_polished" then
  54. was_polished = true
  55. else
  56. has_other_fields = true
  57. end
  58. end
  59. if has_infotext and not was_engraved then
  60. return false
  61. end
  62. if has_other_fields or was_polished then
  63. return false
  64. end
  65. return true
  66. end
  67. local function show_chisel_formspec(pos, user)
  68. local pname = user:get_player_name()
  69. local node = minetest.get_node(pos)
  70. local text = minetest.get_meta(pos):get_string("chiseled_text")
  71. local formspec = "size[5,2.3]" ..
  72. default.gui_bg ..
  73. default.gui_bg_img ..
  74. default.gui_slots ..
  75. "item_image[1,1;1,1;" .. minetest.formspec_escape(node.name) .. "]" ..
  76. "field[0.3,0.3;5,1;text;;" .. minetest.formspec_escape(text) .. "]" ..
  77. "button_exit[2,1;2,1;proceed;Chisel Text]" ..
  78. "label[0,2;`%n' inserts a new line.]"
  79. local formname = "engraver:chisel_" .. minetest.pos_to_string(pos)
  80. minetest.show_formspec(pname, formname, formspec)
  81. end
  82. -- Must be a tool for the wear bar to work.
  83. minetest.register_tool("engraver:chisel", {
  84. description = "Chisel",
  85. groups = {not_repaired_by_anvil = 1},
  86. inventory_image = "engraver_chisel.png",
  87. wield_image = "engraver_chisel.png",
  88. on_use = function(itemstack, user, pt)
  89. if not user or not user:is_player() then
  90. return
  91. end
  92. if pt.type ~= "node" then
  93. return
  94. end
  95. if not player_wields_tools(user) then
  96. return
  97. end
  98. if not node_can_be_chiseled(pt.under) then
  99. return
  100. end
  101. ambiance.sound_play("anvil_clang", pt.under, 1.0, 30)
  102. show_chisel_formspec(pt.under, user)
  103. end,
  104. })
  105. local function handle_engraver_use(player, formname, fields)
  106. if not string.find(formname, "^engraver:chisel_") then
  107. return
  108. end
  109. if not player or not player:is_player() then
  110. return true
  111. end
  112. local pname = player:get_player_name()
  113. local pos = minetest.string_to_pos(string.sub(formname, string.len("engraver:chisel_") + 1))
  114. if not pos then
  115. return true
  116. end
  117. if not player_wields_tools(player) then
  118. return true
  119. end
  120. if not node_can_be_chiseled(pos) then
  121. return true
  122. end
  123. if not fields.text or type(fields.text) ~= "string" then
  124. return true
  125. end
  126. local message = utility.trim_remove_special_chars(fields.text)
  127. if anticurse.check(pname, message, "foul") then
  128. anticurse.log(pname, message)
  129. minetest.chat_send_player(pname, "# Server: Don't use a chisel for naughty talk!")
  130. return true
  131. elseif anticurse.check(pname, message, "curse") then
  132. anticurse.log(pname, message)
  133. minetest.chat_send_player(pname, "# Server: Please do not curse with a chisel.")
  134. return true
  135. end
  136. if string.len(message) > 256 then
  137. minetest.chat_send_player(pname, "# Server: Message is too long. Put something shorter.")
  138. return true
  139. end
  140. -- Add wear to the chisel.
  141. local got_chisel = false
  142. local inv = player:get_inventory()
  143. local index = player:get_wield_index()
  144. local chisel = inv:get_stack("main", index)
  145. if chisel:get_name() == "engraver:chisel" then
  146. chisel:add_wear(300)
  147. inv:set_stack("main", index, chisel)
  148. if chisel:is_empty() == 0 then
  149. ambiance.sound_play("default_tool_breaks", pos, 1.0, 10)
  150. end
  151. got_chisel = true
  152. end
  153. if got_chisel then
  154. local meta = minetest.get_meta(pos)
  155. meta:set_string("chiseled_text", message)
  156. meta:set_string("chiseled_date", os.time())
  157. meta:set_int("engraver_chiseled", 1)
  158. meta:mark_as_private({"chiseled_text", "chiseled_date", "engraver_chiseled"})
  159. -- Translate escape sequences.
  160. message = string.gsub(message, "%%[nN]", "\n")
  161. if message ~= "" then
  162. meta:set_string("infotext", message)
  163. else
  164. meta:set_string("infotext", "")
  165. meta:set_int("engraver_chiseled", 0)
  166. end
  167. minetest.chat_send_player(pname, "# Server: Text chiseled successfully.")
  168. ambiance.sound_play("anvil_clang", pos, 1.0, 30)
  169. end
  170. return true
  171. end
  172. minetest.register_on_player_receive_fields(handle_engraver_use)
  173. minetest.register_craft({
  174. output = "engraver:chisel",
  175. recipe = {
  176. {"carbon_steel:ingot"},
  177. {"default:stick"},
  178. },
  179. })
  180. -- Code by 'octacian'
  181. --
  182. -- Formspec
  183. --
  184. local function get_workbench_formspec(pos, error)
  185. local msg = "Rename Item"
  186. local text = minetest.get_meta(pos):get_string("text")
  187. if error then
  188. msg = minetest.colorize("red", error)
  189. end
  190. return
  191. "size[8,7]" ..
  192. default.gui_bg ..
  193. default.gui_bg_img ..
  194. default.gui_slots ..
  195. "field[0.5,0.5;6.2,1;text;"..msg..";"..minetest.formspec_escape(text).."]" ..
  196. "button[6.5,0.2;1.5,1;rename;Rename]" ..
  197. "list[context;input;1.5,1.4;1,1;]" ..
  198. "image[2.5,1.4;1,1;gui_workbench_plus.png]" ..
  199. "image[3.5,1.4;1,1;default_nametag_slot.png]" ..
  200. "list[context;nametag;3.5,1.4;1,1;]" ..
  201. "image[4.5,1.4;1,1;gui_furnace_arrow_bg.png^[transformR270]" ..
  202. "list[context;output;5.5,1.4;1,1]" ..
  203. "list[current_player;main;0,2.85;8,1;]" ..
  204. "list[current_player;main;0,4.08;8,3;8]" ..
  205. "field_close_on_enter[text;false]" ..
  206. default.get_hotbar_bg(0,2.85)
  207. end
  208. local function get_item_desc(stack)
  209. if not stack:is_known() then
  210. return
  211. end
  212. local desc = stack:get_meta():get_string("description")
  213. if desc == "" then
  214. desc = minetest.registered_items[stack:get_name()].description or ""
  215. end
  216. desc = utility.get_short_desc(desc)
  217. return desc
  218. end
  219. local function workbench_update_text(pos, stack)
  220. local meta = minetest.get_meta(pos)
  221. meta:set_string("text", get_item_desc(stack))
  222. meta:set_string("formspec", get_workbench_formspec(pos))
  223. end
  224. local function workbench_update_help(pos, type, string)
  225. local meta = minetest.get_meta(pos)
  226. meta:set_string("formspec", get_workbench_formspec(pos, string))
  227. meta:set_string("error", type)
  228. end
  229. --
  230. -- Node definition
  231. --
  232. minetest.register_node(":engraver:bench", {
  233. description = "Engraving Bench",
  234. tiles = {"default_workbench_top.png", "default_wood.png", "default_workbench_sides.png",
  235. "default_workbench_sides.png", "default_workbench_sides.png", "default_workbench_sides.png"},
  236. groups = utility.dig_groups("furniture", {flammable = 3}),
  237. sounds = default.node_sound_wood_defaults(),
  238. drawtype = "nodebox",
  239. paramtype = "light",
  240. node_box = {
  241. type = "fixed",
  242. fixed = {
  243. {-0.5, 3/16, -0.5, 0.5, 0.5, 0.5},
  244. {-7/16, -0.5, 1/4, -1/4, 0.5, 7/16},
  245. {-7/16, -0.5, -7/16, -1/4, 0.5, -1/4},
  246. {1/4, -0.5, 1/4, 7/16, 0.5, 7/16},
  247. {1/4, -0.5, -7/16, 7/16, 0.5, -1/4},
  248. }
  249. },
  250. on_construct = function(pos)
  251. local meta = minetest.get_meta(pos)
  252. meta:set_string("formspec", get_workbench_formspec(pos))
  253. local inv = meta:get_inventory()
  254. inv:set_size("input", 1)
  255. inv:set_size("nametag", 1)
  256. inv:set_size("output", 1)
  257. end,
  258. can_dig = function(pos, player)
  259. local inv = minetest.get_meta(pos):get_inventory()
  260. if inv:is_empty("input") and inv:is_empty("nametag") and
  261. inv:is_empty("output") then
  262. return true
  263. else
  264. return false
  265. end
  266. end,
  267. on_blast = function(pos)
  268. local inv = minetest.get_meta(pos):get_inventory()
  269. local drops = {
  270. inv:get_list("input")[1],
  271. inv:get_list("nametag")[1],
  272. inv:get_list("output")[1],
  273. "engraver:bench",
  274. }
  275. minetest.remove_node(pos)
  276. return drops
  277. end,
  278. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  279. local pname = player:get_player_name()
  280. if minetest.test_protection(pos, pname) then
  281. return 0
  282. end
  283. if not stack:is_known() then
  284. return 0
  285. end
  286. if listname == "nametag" then
  287. if stack:get_name() ~= "engraver:plate" then
  288. return 0
  289. else
  290. return stack:get_count()
  291. end
  292. elseif listname == "output" then
  293. return 0
  294. elseif listname == "input" then
  295. if minetest.get_item_group(stack:get_name(), "not_renamable") > 0 then
  296. return 0
  297. end
  298. if stack:get_stack_max() > 1 then
  299. return 0
  300. end
  301. return stack:get_count()
  302. end
  303. return 0
  304. end,
  305. allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  306. return 0
  307. end,
  308. allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  309. local pname = player:get_player_name()
  310. if minetest.test_protection(pos, pname) then
  311. return 0
  312. end
  313. return stack:get_count()
  314. end,
  315. on_metadata_inventory_put = function(pos, listname, index, stack)
  316. local meta = minetest.get_meta(pos)
  317. local inv = meta:get_inventory()
  318. local error = meta:get_string("error")
  319. if error == "input" and not inv:is_empty("input") then
  320. meta:set_string("formspec", get_workbench_formspec(pos))
  321. elseif error == "nametag" and not inv:is_empty("nametag") then
  322. meta:set_string("formspec", get_workbench_formspec(pos))
  323. end
  324. if listname == "input" then
  325. workbench_update_text(pos, stack)
  326. end
  327. end,
  328. on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index)
  329. -- Moving is not allowed.
  330. end,
  331. on_metadata_inventory_take = function(pos, listname)
  332. local meta = minetest.get_meta(pos)
  333. local inv = meta:get_inventory()
  334. local error = meta:get_string("error")
  335. if error == "output" and inv:is_empty("output") then
  336. meta:set_string("formspec", get_workbench_formspec(pos))
  337. end
  338. if listname == "input" then
  339. meta:set_string("text", "")
  340. meta:set_string("formspec", get_workbench_formspec(pos))
  341. end
  342. end,
  343. on_receive_fields = function(pos, formname, fields, sender)
  344. local meta = minetest.get_meta(pos)
  345. local inv = meta:get_inventory()
  346. local pname = sender:get_player_name()
  347. if fields.rename or fields.key_enter_field == "text" then
  348. meta:set_string("text", fields.text)
  349. if inv:is_empty("input") then
  350. workbench_update_help(pos, "input", "Missing input item!")
  351. elseif inv:is_empty("nametag") then
  352. workbench_update_help(pos, "nametag", "Missing nameplate!")
  353. elseif not inv:is_empty("output") then
  354. workbench_update_help(pos, "output", "No room in output!")
  355. else
  356. local new_stack = inv:get_stack("input", 1)
  357. if not new_stack:is_known() then
  358. workbench_update_help(pos, nil, "Cannot rename unknown item!")
  359. return
  360. end
  361. local item = minetest.registered_items[new_stack:get_name()]
  362. local renameable = item.groups.renameable ~= 0
  363. if not renameable then
  364. workbench_update_help(pos, nil, "Item cannot be renamed!")
  365. return
  366. elseif new_stack:get_stack_max() > 1 then
  367. workbench_update_help(pos, nil, "Item cannot be renamed!")
  368. return
  369. elseif fields.text == "" then
  370. workbench_update_help(pos, nil, "Description cannot be blank!")
  371. return
  372. elseif anticurse.check(pname, fields.text, "foul") then
  373. workbench_update_help(pos, nil, "No foul language!")
  374. return
  375. elseif anticurse.check(pname, fields.text, "curse") then
  376. workbench_update_help(pos, nil, "No cursing!")
  377. return
  378. elseif fields.text:len() > 256 then
  379. workbench_update_help(pos, nil, "Description too long (max 256 characters)!")
  380. return
  381. elseif fields.text == get_item_desc(inv:get_stack("input", 1)) then
  382. workbench_update_help(pos, nil, "Description not changed!")
  383. end
  384. local itemmeta = new_stack:get_meta()
  385. itemmeta:set_string("en_desc", fields.text)
  386. toolranks.apply_description(itemmeta, new_stack:get_definition())
  387. minetest.log("action", pname .. " renames "
  388. ..inv:get_stack("input", 1):get_name().." to "..fields.text)
  389. inv:remove_item("input", inv:get_stack("input", 1))
  390. inv:remove_item("nametag", inv:get_stack("nametag", 1):take_item(1))
  391. inv:set_stack("output", 1, new_stack)
  392. meta:set_string("text", "")
  393. workbench_update_help(pos)
  394. end
  395. end
  396. end,
  397. })
  398. minetest.register_craft({
  399. output = "engraver:bench",
  400. recipe = {
  401. {'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'},
  402. {'basictrees:tree_wood', '', 'basictrees:tree_wood'},
  403. {'basictrees:tree_wood', '', 'basictrees:tree_wood'},
  404. }
  405. })
  406. minetest.register_craftitem(":engraver:plate", {
  407. description = "Nameplate",
  408. inventory_image = "default_nametag.png",
  409. groups = {not_renamable = 1}
  410. })
  411. minetest.register_craft({
  412. type = "compressing",
  413. output = "engraver:plate 4",
  414. recipe = "default:bronze_ingot",
  415. time = 10,
  416. })