1c93eb23335f67c097d2ab4c5f5c854dee109613
[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_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
149         if itemstack:get_name() ~= "default:book_written" then
150                 return
151         end
152
153         local original
154         local index
155         for i = 1, player:get_inventory():get_size("craft") do
156                 if old_craft_grid[i]:get_name() == "default:book_written" then
157                         original = old_craft_grid[i]
158                         index = i
159                 end
160         end
161         if not original then
162                 return
163         end
164         local copymeta = original:get_meta():to_table()
165         -- copy of the book held by player's mouse cursor
166         itemstack:get_meta():from_table(copymeta)
167         -- put the book with metadata back in the craft grid
168         craft_inv:set_stack("craft", index, original)
169 end)
170
171 minetest.register_craftitem("default:skeleton_key", {
172         description = S("Skeleton Key"),
173         inventory_image = "default_key_skeleton.png",
174         groups = {key = 1},
175         on_use = function(itemstack, user, pointed_thing)
176                 if pointed_thing.type ~= "node" then
177                         return itemstack
178                 end
179
180                 local pos = pointed_thing.under
181                 local node = minetest.get_node(pos)
182
183                 if not node then
184                         return itemstack
185                 end
186
187                 local on_skeleton_key_use = minetest.registered_nodes[node.name].on_skeleton_key_use
188                 if not on_skeleton_key_use then
189                         return itemstack
190                 end
191
192                 -- make a new key secret in case the node callback needs it
193                 local random = math.random
194                 local newsecret = string.format(
195                         "%04x%04x%04x%04x",
196                         random(2^16) - 1, random(2^16) - 1,
197                         random(2^16) - 1, random(2^16) - 1)
198
199                 local secret, _, _ = on_skeleton_key_use(pos, user, newsecret)
200
201                 if secret then
202                         local inv = minetest.get_inventory({type="player", name=user:get_player_name()})
203
204                         -- update original itemstack
205                         itemstack:take_item()
206
207                         -- finish and return the new key
208                         local new_stack = ItemStack("default:key")
209                         local meta = new_stack:get_meta()
210                         meta:set_string("secret", secret)
211                         meta:set_string("description", S("Key to @1's @2", user:get_player_name(),
212                                 minetest.registered_nodes[node.name].description))
213
214                         if itemstack:get_count() == 0 then
215                                 itemstack = new_stack
216                         else
217                                 if inv:add_item("main", new_stack):get_count() > 0 then
218                                         minetest.add_item(user:get_pos(), new_stack)
219                                 end -- else: added to inventory successfully
220                         end
221
222                         return itemstack
223                 end
224         end
225 })
226
227 --
228 -- Craftitem registry
229 --
230
231 minetest.register_craftitem("default:blueberries", {
232         description = S("Blueberries"),
233         inventory_image = "default_blueberries.png",
234         groups = {food_blueberries = 1, food_berry = 1},
235         on_use = minetest.item_eat(2),
236 })
237
238 minetest.register_craftitem("default:book", {
239         description = S("Book"),
240         inventory_image = "default_book.png",
241         groups = {book = 1, flammable = 3},
242         on_use = book_on_use,
243 })
244
245 minetest.register_craftitem("default:book_written", {
246         description = S("Book with Text"),
247         inventory_image = "default_book_written.png",
248         groups = {book = 1, not_in_creative_inventory = 1, flammable = 3},
249         stack_max = 1,
250         on_use = book_on_use,
251 })
252
253 minetest.register_craftitem("default:bronze_ingot", {
254         description = S("Bronze Ingot"),
255         inventory_image = "default_bronze_ingot.png"
256 })
257
258 minetest.register_craftitem("default:clay_brick", {
259         description = S("Clay Brick"),
260         inventory_image = "default_clay_brick.png",
261 })
262
263 minetest.register_craftitem("default:clay_lump", {
264         description = S("Clay Lump"),
265         inventory_image = "default_clay_lump.png",
266 })
267
268 minetest.register_craftitem("default:coal_lump", {
269         description = S("Coal Lump"),
270         inventory_image = "default_coal_lump.png",
271         groups = {coal = 1, flammable = 1}
272 })
273
274 minetest.register_craftitem("default:copper_ingot", {
275         description = S("Copper Ingot"),
276         inventory_image = "default_copper_ingot.png"
277 })
278
279 minetest.register_craftitem("default:copper_lump", {
280         description = S("Copper Lump"),
281         inventory_image = "default_copper_lump.png"
282 })
283
284 minetest.register_craftitem("default:diamond", {
285         description = S("Diamond"),
286         inventory_image = "default_diamond.png",
287 })
288
289 minetest.register_craftitem("default:flint", {
290         description = S("Flint"),
291         inventory_image = "default_flint.png"
292 })
293
294 minetest.register_craftitem("default:gold_ingot", {
295         description = S("Gold Ingot"),
296         inventory_image = "default_gold_ingot.png"
297 })
298
299 minetest.register_craftitem("default:gold_lump", {
300         description = S("Gold Lump"),
301         inventory_image = "default_gold_lump.png"
302 })
303
304 minetest.register_craftitem("default:iron_lump", {
305         description = S("Iron Lump"),
306         inventory_image = "default_iron_lump.png"
307 })
308
309 minetest.register_craftitem("default:mese_crystal", {
310         description = S("Mese Crystal"),
311         inventory_image = "default_mese_crystal.png",
312 })
313
314 minetest.register_craftitem("default:mese_crystal_fragment", {
315         description = S("Mese Crystal Fragment"),
316         inventory_image = "default_mese_crystal_fragment.png",
317 })
318
319 minetest.register_craftitem("default:obsidian_shard", {
320         description = S("Obsidian Shard"),
321         inventory_image = "default_obsidian_shard.png",
322 })
323
324 minetest.register_craftitem("default:paper", {
325         description = S("Paper"),
326         inventory_image = "default_paper.png",
327         groups = {flammable = 3},
328 })
329
330 minetest.register_craftitem("default:steel_ingot", {
331         description = S("Steel Ingot"),
332         inventory_image = "default_steel_ingot.png"
333 })
334
335 minetest.register_craftitem("default:stick", {
336         description = S("Stick"),
337         inventory_image = "default_stick.png",
338         groups = {stick = 1, flammable = 2},
339 })
340
341 minetest.register_craftitem("default:tin_ingot", {
342         description = S("Tin Ingot"),
343         inventory_image = "default_tin_ingot.png"
344 })
345
346 minetest.register_craftitem("default:tin_lump", {
347         description = S("Tin Lump"),
348         inventory_image = "default_tin_lump.png"
349 })
350
351 --
352 -- Crafting recipes
353 --
354
355 minetest.register_craft({
356         output = "default:book",
357         recipe = {
358                 {"default:paper"},
359                 {"default:paper"},
360                 {"default:paper"},
361         }
362 })
363
364 minetest.register_craft({
365         type = "shapeless",
366         output = "default:book_written",
367         recipe = {"default:book", "default:book_written"}
368 })
369
370 minetest.register_craft({
371         output = "default:bronze_ingot 9",
372         recipe = {
373                 {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"},
374                 {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"},
375                 {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"},
376         }
377 })
378
379 minetest.register_craft({
380         output = "default:clay_brick 4",
381         recipe = {
382                 {"default:brick"},
383         }
384 })
385
386 minetest.register_craft({
387         output = "default:clay_lump 4",
388         recipe = {
389                 {"default:clay"},
390         }
391 })
392
393 minetest.register_craft({
394         output = "default:coal_lump 9",
395         recipe = {
396                 {"default:coalblock"},
397         }
398 })
399
400 minetest.register_craft({
401         output = "default:copper_ingot 9",
402         recipe = {
403                 {"default:copperblock"},
404         }
405 })
406
407 minetest.register_craft({
408         output = "default:diamond 9",
409         recipe = {
410                 {"default:diamondblock"},
411         }
412 })
413
414 minetest.register_craft({
415         output = "default:gold_ingot 9",
416         recipe = {
417                 {"default:goldblock"},
418         }
419 })
420
421 minetest.register_craft({
422         output = "default:mese_crystal",
423         recipe = {
424                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
425                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
426                 {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"},
427         }
428 })
429
430 minetest.register_craft({
431         output = "default:mese_crystal 9",
432         recipe = {
433                 {"default:mese"},
434         }
435 })
436
437 minetest.register_craft({
438         output = "default:mese_crystal_fragment 9",
439         recipe = {
440                 {"default:mese_crystal"},
441         }
442 })
443
444 minetest.register_craft({
445         output = "default:obsidian_shard 9",
446         recipe = {
447                 {"default:obsidian"}
448         }
449 })
450
451 minetest.register_craft({
452         output = "default:paper",
453         recipe = {
454                 {"default:papyrus", "default:papyrus", "default:papyrus"},
455         }
456 })
457
458 minetest.register_craft({
459         output = "default:skeleton_key",
460         recipe = {
461                 {"default:gold_ingot"},
462         }
463 })
464
465 minetest.register_craft({
466         output = "default:steel_ingot 9",
467         recipe = {
468                 {"default:steelblock"},
469         }
470 })
471
472 minetest.register_craft({
473         output = "default:stick 4",
474         recipe = {
475                 {"group:wood"},
476         }
477 })
478
479 minetest.register_craft({
480         output = "default:tin_ingot 9",
481         recipe = {
482                 {"default:tinblock"},
483         }
484 })
485
486 --
487 -- Cooking recipes
488 --
489
490 minetest.register_craft({
491         type = "cooking",
492         output = "default:clay_brick",
493         recipe = "default:clay_lump",
494 })
495
496 minetest.register_craft({
497         type = "cooking",
498         output = "default:copper_ingot",
499         recipe = "default:copper_lump",
500 })
501
502 minetest.register_craft({
503         type = "cooking",
504         output = "default:gold_ingot",
505         recipe = "default:gold_lump",
506 })
507
508 minetest.register_craft({
509         type = "cooking",
510         output = "default:gold_ingot",
511         recipe = "default:key",
512         cooktime = 5,
513 })
514
515 minetest.register_craft({
516         type = "cooking",
517         output = "default:gold_ingot",
518         recipe = "default:skeleton_key",
519         cooktime = 5,
520 })
521
522 minetest.register_craft({
523         type = "cooking",
524         output = "default:steel_ingot",
525         recipe = "default:iron_lump",
526 })
527
528 minetest.register_craft({
529         type = "cooking",
530         output = "default:tin_ingot",
531         recipe = "default:tin_lump",
532 })
533
534 --
535 -- Fuels
536 --
537
538 minetest.register_craft({
539         type = "fuel",
540         recipe = "default:book",
541         burntime = 3,
542 })
543
544 minetest.register_craft({
545         type = "fuel",
546         recipe = "default:book_written",
547         burntime = 3,
548 })
549
550 minetest.register_craft({
551         type = "fuel",
552         recipe = "default:coal_lump",
553         burntime = 40,
554 })
555
556 minetest.register_craft({
557         type = "fuel",
558         recipe = "default:paper",
559         burntime = 1,
560 })
561
562 minetest.register_craft({
563         type = "fuel",
564         recipe = "group:stick",
565         burntime = 1,
566 })