Add node particles when leafdecay removes a node (#2686)
[oweals/minetest_game.git] / mods / default / craftitems.lua
1 -- mods/default/craftitems.lua
2
3 -- support for MT game translation.
4 local S = default.get_translator
5
6 local lpp = 14 -- Lines per book's page
7 local function book_on_use(itemstack, user)
8         local player_name = user:get_player_name()
9         local meta = itemstack:get_meta()
10         local title, text, owner = "", "", player_name
11         local page, page_max, lines, string = 1, 1, {}, ""
12
13         -- Backwards compatibility
14         local old_data = minetest.deserialize(itemstack:get_metadata())
15         if old_data then
16                 meta:from_table({ fields = old_data })
17         end
18
19         local data = meta:to_table().fields
20
21         if data.owner then
22                 title = data.title
23                 text = data.text
24                 owner = data.owner
25
26                 for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do
27                         lines[#lines+1] = str
28                 end
29
30                 if data.page then
31                         page = data.page
32                         page_max = data.page_max
33
34                         for i = ((lpp * page) - lpp) + 1, lpp * page do
35                                 if not lines[i] then break end
36                                 string = string .. lines[i] .. "\n"
37                         end
38                 end
39         end
40
41         local formspec
42         local esc = minetest.formspec_escape
43         if owner == player_name then
44                 formspec = "size[8,8]" ..
45                         "field[0.5,1;7.5,0;title;" .. esc(S("Title:")) .. ";" ..
46                                 esc(title) .. "]" ..
47                         "textarea[0.5,1.5;7.5,7;text;" .. esc(S("Contents:")) .. ";" ..
48                                 esc(text) .. "]" ..
49                         "button_exit[2.5,7.5;3,1;save;" .. esc(S("Save")) .. "]"
50         else
51                 formspec = "size[8,8]" ..
52                         "label[0.5,0.5;" .. esc(S("by @1", owner)) .. "]" ..
53                         "tablecolumns[color;text]" ..
54                         "tableoptions[background=#00000000;highlight=#00000000;border=false]" ..
55                         "table[0.4,0;7,0.5;title;#FFFF00," .. esc(title) .. "]" ..
56                         "textarea[0.5,1.5;7.5,7;;" ..
57                                 minetest.formspec_escape(string ~= "" and string or text) .. ";]" ..
58                         "button[2.4,7.6;0.8,0.8;book_prev;<]" ..
59                         "label[3.2,7.7;" .. esc(S("Page @1 of @2", page, page_max)) .. "]" ..
60                         "button[4.9,7.6;0.8,0.8;book_next;>]"
61         end
62
63         minetest.show_formspec(player_name, "default:book", formspec)
64         return itemstack
65 end
66
67 local max_text_size = 10000
68 local max_title_size = 80
69 local short_title_size = 35
70 minetest.register_on_player_receive_fields(function(player, formname, fields)
71         if formname ~= "default:book" then return end
72         local inv = player:get_inventory()
73         local stack = player:get_wielded_item()
74
75         if fields.save and fields.title and fields.text
76                         and fields.title ~= "" and fields.text ~= "" then
77                 local new_stack, data
78                 if stack:get_name() ~= "default:book_written" then
79                         local count = stack:get_count()
80                         if count == 1 then
81                                 stack:set_name("default:book_written")
82                         else
83                                 stack:set_count(count - 1)
84                                 new_stack = ItemStack("default:book_written")
85                         end
86                 else
87                         data = stack:get_meta():to_table().fields
88                 end
89
90                 if data and data.owner and data.owner ~= player:get_player_name() then
91                         return
92                 end
93
94                 if not data then data = {} end
95                 data.title = fields.title:sub(1, max_title_size)
96                 data.owner = player:get_player_name()
97                 local short_title = data.title
98                 -- Don't bother triming the title if the trailing dots would make it longer
99                 if #short_title > short_title_size + 3 then
100                         short_title = short_title:sub(1, short_title_size) .. "..."
101                 end
102                 data.description = S("\"@1\" by @2", short_title, data.owner)
103                 data.text = fields.text:sub(1, max_text_size)
104                 data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n")
105                 data.page = 1
106                 data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp)
107
108                 if new_stack then
109                         new_stack:get_meta():from_table({ fields = data })
110                         if inv:room_for_item("main", new_stack) then
111                                 inv:add_item("main", new_stack)
112                         else
113                                 minetest.add_item(player:get_pos(), new_stack)
114                         end
115                 else
116                         stack:get_meta():from_table({ fields = data })
117                 end
118
119         elseif fields.book_next or fields.book_prev then
120                 local data = stack:get_meta():to_table().fields
121                 if not data or not data.page then
122                         return
123                 end
124
125                 data.page = tonumber(data.page)
126                 data.page_max = tonumber(data.page_max)
127
128                 if fields.book_next then
129                         data.page = data.page + 1
130                         if data.page > data.page_max then
131                                 data.page = 1
132                         end
133                 else
134                         data.page = data.page - 1
135                         if data.page == 0 then
136                                 data.page = data.page_max
137                         end
138                 end
139
140                 stack:get_meta():from_table({fields = data})
141                 stack = book_on_use(stack, player)
142         end
143
144         -- Update stack
145         player:set_wielded_item(stack)
146 end)
147
148 minetest.register_craftitem("default:skeleton_key", {
149         description = S("Skeleton Key"),
150         inventory_image = "default_key_skeleton.png",
151         on_use = function(itemstack, user, pointed_thing)
152                 if pointed_thing.type ~= "node" then
153                         return itemstack
154                 end
155
156                 local pos = pointed_thing.under
157                 local node = minetest.get_node(pos)
158
159                 if not node then
160                         return itemstack
161                 end
162
163                 local on_skeleton_key_use = minetest.registered_nodes[node.name].on_skeleton_key_use
164                 if not on_skeleton_key_use then
165                         return itemstack
166                 end
167
168                 -- make a new key secret in case the node callback needs it
169                 local random = math.random
170                 local newsecret = string.format(
171                         "%04x%04x%04x%04x",
172                         random(2^16) - 1, random(2^16) - 1,
173                         random(2^16) - 1, random(2^16) - 1)
174
175                 local secret, _, _ = on_skeleton_key_use(pos, user, newsecret)
176
177                 if secret then
178                         local inv = minetest.get_inventory({type="player", name=user:get_player_name()})
179
180                         -- update original itemstack
181                         itemstack:take_item()
182
183                         -- finish and return the new key
184                         local new_stack = ItemStack("default:key")
185                         local meta = new_stack:get_meta()
186                         meta:set_string("secret", secret)
187                         meta:set_string("description", S("Key to @1's @2", user:get_player_name(),
188                                 minetest.registered_nodes[node.name].description))
189
190                         if itemstack:get_count() == 0 then
191                                 itemstack = new_stack
192                         else
193                                 if inv:add_item("main", new_stack):get_count() > 0 then
194                                         minetest.add_item(user:get_pos(), new_stack)
195                                 end -- else: added to inventory successfully
196                         end
197
198                         return itemstack
199                 end
200         end
201 })
202
203 --
204 -- Craftitem registry
205 --
206
207 minetest.register_craftitem("default:blueberries", {
208         description = S("Blueberries"),
209         inventory_image = "default_blueberries.png",
210         groups = {food_blueberries = 1, food_berry = 1},
211         on_use = minetest.item_eat(2),
212 })
213
214 minetest.register_craftitem("default:book", {
215         description = S("Book"),
216         inventory_image = "default_book.png",
217         groups = {book = 1, flammable = 3},
218         on_use = book_on_use,
219 })
220
221 minetest.register_craftitem("default:book_written", {
222         description = S("Book with Text"),
223         inventory_image = "default_book_written.png",
224         groups = {book = 1, not_in_creative_inventory = 1, flammable = 3},
225         stack_max = 1,
226         on_use = book_on_use,
227 })
228
229 minetest.register_craftitem("default:bronze_ingot", {
230         description = S("Bronze Ingot"),
231         inventory_image = "default_bronze_ingot.png"
232 })
233
234 minetest.register_craftitem("default:clay_brick", {
235         description = S("Clay Brick"),
236         inventory_image = "default_clay_brick.png",
237 })
238
239 minetest.register_craftitem("default:clay_lump", {
240         description = S("Clay Lump"),
241         inventory_image = "default_clay_lump.png",
242 })
243
244 minetest.register_craftitem("default:coal_lump", {
245         description = S("Coal Lump"),
246         inventory_image = "default_coal_lump.png",
247         groups = {coal = 1, flammable = 1}
248 })
249
250 minetest.register_craftitem("default:copper_ingot", {
251         description = S("Copper Ingot"),
252         inventory_image = "default_copper_ingot.png"
253 })
254
255 minetest.register_craftitem("default:copper_lump", {
256         description = S("Copper Lump"),
257         inventory_image = "default_copper_lump.png"
258 })
259
260 minetest.register_craftitem("default:diamond", {
261         description = S("Diamond"),
262         inventory_image = "default_diamond.png",
263 })
264
265 minetest.register_craftitem("default:flint", {
266         description = S("Flint"),
267         inventory_image = "default_flint.png"
268 })
269
270 minetest.register_craftitem("default:gold_ingot", {
271         description = S("Gold Ingot"),
272         inventory_image = "default_gold_ingot.png"
273 })
274
275 minetest.register_craftitem("default:gold_lump", {
276         description = S("Gold Lump"),
277         inventory_image = "default_gold_lump.png"
278 })
279
280 minetest.register_craftitem("default:iron_lump", {
281         description = S("Iron Lump"),
282         inventory_image = "default_iron_lump.png"
283 })
284
285 minetest.register_craftitem("default:mese_crystal", {
286         description = S("Mese Crystal"),
287         inventory_image = "default_mese_crystal.png",
288 })
289
290 minetest.register_craftitem("default:mese_crystal_fragment", {
291         description = S("Mese Crystal Fragment"),
292         inventory_image = "default_mese_crystal_fragment.png",
293 })
294
295 minetest.register_craftitem("default:obsidian_shard", {
296         description = S("Obsidian Shard"),
297         inventory_image = "default_obsidian_shard.png",
298 })
299
300 minetest.register_craftitem("default:paper", {
301         description = S("Paper"),
302         inventory_image = "default_paper.png",
303         groups = {flammable = 3},
304 })
305
306 minetest.register_craftitem("default:steel_ingot", {
307         description = S("Steel Ingot"),
308         inventory_image = "default_steel_ingot.png"
309 })
310
311 minetest.register_craftitem("default:stick", {
312         description = S("Stick"),
313         inventory_image = "default_stick.png",
314         groups = {stick = 1, flammable = 2},
315 })
316
317 minetest.register_craftitem("default:tin_ingot", {
318         description = S("Tin Ingot"),
319         inventory_image = "default_tin_ingot.png"
320 })
321
322 minetest.register_craftitem("default:tin_lump", {
323         description = S("Tin Lump"),
324         inventory_image = "default_tin_lump.png"
325 })
326
327 --
328 -- Crafting recipes
329 --
330
331 minetest.register_craft({
332         output = "default:book",
333         recipe = {
334                 {"default:paper"},
335                 {"default:paper"},
336                 {"default:paper"},
337         }
338 })
339
340 default.register_craft_metadata_copy("default:book", "default:book_written")
341
342 minetest.register_craft({
343         output = "default:bronze_ingot 9",
344         recipe = {
345                 {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"},
346                 {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
347                 {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"},
348         }
349 })
350
351 minetest.register_craft({
352         output = "default:clay_brick 4",
353         recipe = {
354                 {"default:brick"},
355         }
356 })
357
358 minetest.register_craft({
359         output = "default:clay_lump 4",
360         recipe = {
361                 {"default:clay"},
362         }
363 })
364
365 minetest.register_craft({
366         output = "default:coal_lump 9",
367         recipe = {
368                 {"default:coalblock"},
369         }
370 })
371
372 minetest.register_craft({
373         output = "default:copper_ingot 9",
374         recipe = {
375                 {"default:copperblock"},
376         }
377 })
378
379 minetest.register_craft({
380         output = "default:diamond 9",
381         recipe = {
382                 {"default:diamondblock"},
383         }
384 })
385
386 minetest.register_craft({
387         output = "default:gold_ingot 9",
388         recipe = {
389                 {"default:goldblock"},
390         }
391 })
392
393 minetest.register_craft({
394         output = "default:mese_crystal",
395         recipe = {
396                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
397                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
398                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
399         }
400 })
401
402 minetest.register_craft({
403         output = "default:mese_crystal 9",
404         recipe = {
405                 {"default:mese"},
406         }
407 })
408
409 minetest.register_craft({
410         output = "default:mese_crystal_fragment 9",
411         recipe = {
412                 {"default:mese_crystal"},
413         }
414 })
415
416 minetest.register_craft({
417         output = "default:obsidian_shard 9",
418         recipe = {
419                 {"default:obsidian"}
420         }
421 })
422
423 minetest.register_craft({
424         output = "default:paper",
425         recipe = {
426                 {"default:papyrus", "default:papyrus", "default:papyrus"},
427         }
428 })
429
430 minetest.register_craft({
431         output = "default:skeleton_key",
432         recipe = {
433                 {"default:gold_ingot"},
434         }
435 })
436
437 minetest.register_craft({
438         output = "default:steel_ingot 9",
439         recipe = {
440                 {"default:steelblock"},
441         }
442 })
443
444 minetest.register_craft({
445         output = "default:stick 4",
446         recipe = {
447                 {"group:wood"},
448         }
449 })
450
451 minetest.register_craft({
452         output = "default:tin_ingot 9",
453         recipe = {
454                 {"default:tinblock"},
455         }
456 })
457
458 --
459 -- Cooking recipes
460 --
461
462 minetest.register_craft({
463         type = "cooking",
464         output = "default:clay_brick",
465         recipe = "default:clay_lump",
466 })
467
468 minetest.register_craft({
469         type = "cooking",
470         output = "default:copper_ingot",
471         recipe = "default:copper_lump",
472 })
473
474 minetest.register_craft({
475         type = "cooking",
476         output = "default:gold_ingot",
477         recipe = "default:gold_lump",
478 })
479
480 minetest.register_craft({
481         type = "cooking",
482         output = "default:gold_ingot",
483         recipe = "default:key",
484         cooktime = 5,
485 })
486
487 minetest.register_craft({
488         type = "cooking",
489         output = "default:gold_ingot",
490         recipe = "default:skeleton_key",
491         cooktime = 5,
492 })
493
494 minetest.register_craft({
495         type = "cooking",
496         output = "default:steel_ingot",
497         recipe = "default:iron_lump",
498 })
499
500 minetest.register_craft({
501         type = "cooking",
502         output = "default:tin_ingot",
503         recipe = "default:tin_lump",
504 })
505
506 --
507 -- Fuels
508 --
509
510 minetest.register_craft({
511         type = "fuel",
512         recipe = "default:book",
513         burntime = 3,
514 })
515
516 minetest.register_craft({
517         type = "fuel",
518         recipe = "default:book_written",
519         burntime = 3,
520 })
521
522 minetest.register_craft({
523         type = "fuel",
524         recipe = "default:coal_lump",
525         burntime = 40,
526 })
527
528 minetest.register_craft({
529         type = "fuel",
530         recipe = "default:paper",
531         burntime = 1,
532 })
533
534 minetest.register_craft({
535         type = "fuel",
536         recipe = "group:stick",
537         burntime = 1,
538 })