From 422751cc7ee93de5d022d80b164adcb967871199 Mon Sep 17 00:00:00 2001 From: Oilboi Date: Thu, 13 Feb 2020 01:51:40 -0500 Subject: [PATCH] Add furnace --- mods/main/craft_recipes.lua | 47 ++- .../main/textures/default_furnace_fire_bg.png | Bin 0 -> 119 bytes .../main/textures/default_furnace_fire_fg.png | Bin 0 -> 189 bytes mods/main/textures/furnace_bottom.png | Bin 0 -> 191 bytes mods/main/textures/furnace_front.png | Bin 0 -> 257 bytes mods/main/textures/furnace_front_active.png | Bin 0 -> 300 bytes mods/main/textures/furnace_side.png | Bin 0 -> 229 bytes mods/main/textures/furnace_top.png | Bin 0 -> 191 bytes mods/main/textures/gui_furnace_arrow_bg.png | Bin 0 -> 161 bytes mods/main/textures/gui_furnace_arrow_fg.png | Bin 0 -> 157 bytes mods/main/textures/gui_hb_bg.png | Bin 0 -> 1485 bytes mods/utility/depends.txt | 1 + mods/utility/init.lua | 378 ++++++++++++++++++ todo.txt | 2 +- 14 files changed, 425 insertions(+), 3 deletions(-) create mode 100755 mods/main/textures/default_furnace_fire_bg.png create mode 100755 mods/main/textures/default_furnace_fire_fg.png create mode 100755 mods/main/textures/furnace_bottom.png create mode 100755 mods/main/textures/furnace_front.png create mode 100755 mods/main/textures/furnace_front_active.png create mode 100755 mods/main/textures/furnace_side.png create mode 100755 mods/main/textures/furnace_top.png create mode 100755 mods/main/textures/gui_furnace_arrow_bg.png create mode 100755 mods/main/textures/gui_furnace_arrow_fg.png create mode 100755 mods/main/textures/gui_hb_bg.png create mode 100644 mods/utility/depends.txt create mode 100644 mods/utility/init.lua diff --git a/mods/main/craft_recipes.lua b/mods/main/craft_recipes.lua index 0c71e1e..c679d3b 100644 --- a/mods/main/craft_recipes.lua +++ b/mods/main/craft_recipes.lua @@ -1,8 +1,49 @@ --crafting recipes -local tool = {"wood","stone", "iron","gold","diamond"}--the tool name -local material = {"wood","cobble","iron","gold","diamond"}--material to craft +--cooking +minetest.register_craft({ + type = "cooking", + output = "main:diamond", + recipe = "main:diamondore", +}) +minetest.register_craft({ + type = "cooking", + output = "main:coal 4", + recipe = "main:coalore", +}) +minetest.register_craft({ + type = "cooking", + output = "main:gold", + recipe = "main:goldore", +}) +minetest.register_craft({ + type = "cooking", + output = "main:iron", + recipe = "main:ironore", +}) +--fuel +minetest.register_craft({ + type = "fuel", + recipe = "main:stick", + burntime = 3, +}) +minetest.register_craft({ + type = "fuel", + recipe = "main:wood", + burntime = 12, +}) +minetest.register_craft({ + type = "fuel", + recipe = "main:leaves", + burntime = 3, +}) +minetest.register_craft({ + type = "fuel", + recipe = "main:coal", + burntime = 20, +}) +---crafting minetest.register_craft({ type = "shapeless", output = "main:wood 4", @@ -17,6 +58,8 @@ minetest.register_craft({ } }) +local tool = {"wood","stone", "iron","gold","diamond"}--the tool name +local material = {"wood","cobble","iron","gold","diamond"}--material to craft for id,tool in pairs(tool) do minetest.register_craft({ diff --git a/mods/main/textures/default_furnace_fire_bg.png b/mods/main/textures/default_furnace_fire_bg.png new file mode 100755 index 0000000000000000000000000000000000000000..abeefc0f5257e266adda7ba67c71800f2f3d3dea GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uo3?x5+55>R9jKJS M)78&qol`;+08Nx33jhEB literal 0 HcmV?d00001 diff --git a/mods/main/textures/default_furnace_fire_fg.png b/mods/main/textures/default_furnace_fire_fg.png new file mode 100755 index 0000000000000000000000000000000000000000..e5b3909669aa59b5cb119934096033440bd2d499 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^d?3ui3?$#C89V|~q5(c3t|1{IWo2a-^VGLnbN@M0 z`E;K9M0vg=84lNg3K&a*{DK)Ap4~_Ta>6`a978G?lNp%Y*f<1)7=nA$m=f9+bS+Zs z$bRu?4acJ1m}Vx&EnXQN$`i!GIJrv27+!IOhVimpKDNqH!Ro|~5Ka$n?U|A@88eTi iY<}Xhp|YuoiHG5{57(=%D)SVe4Gf;HelF{r5}E+fK06-( literal 0 HcmV?d00001 diff --git a/mods/main/textures/furnace_bottom.png b/mods/main/textures/furnace_bottom.png new file mode 100755 index 0000000000000000000000000000000000000000..7844072d5459549e8962a427b8f0155cb0988c61 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHV5AX?b-L-n@(&-cGN($Q>Y9@C! z-Eakt!6@2uk(XJK$GP}8lY)_hx7C40V~52l|7X71w|=?$X{EnXd%I8M zrZtr96c73MZ&SsUNc~JpwR2S|N@=rfFO{f0h~DzRVDSr`kU*i0%I3$PNE|)$cY{gA oq1XTatlX=tp`eq}Q+SeJHd5H<)4brtKx-L1UHx3vIVCg!0Ofv4%K!iX literal 0 HcmV?d00001 diff --git a/mods/main/textures/furnace_front.png b/mods/main/textures/furnace_front.png new file mode 100755 index 0000000000000000000000000000000000000000..388addd4e5ef7346c323ea3bf41ae539773e9d9e GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHF3h)VWZEvXAwR-8&=@YUO6MY@6 zBK_R!N(v`;HW%ci87nEti%Qtq+9pJY>*(kduX*YR)HTV|#WAFUF*!j%L?k36B`GN( zDJ3N+C?O!pppcW3w~(_i&BK(>H=)>!H^D>Ce{DwjdX9vIG`)2m#rYh`9(mrn9%bGJ z2??pjg}kNj44AdP#ca*W+Q7)%z54p9Q16&K5<#aOd$t&`rS-iq-o0LJHseNZ@o3vCGeYX1iFsF)78&qol`;+0FG-` A@Bjb+ literal 0 HcmV?d00001 diff --git a/mods/main/textures/furnace_front_active.png b/mods/main/textures/furnace_front_active.png new file mode 100755 index 0000000000000000000000000000000000000000..c425604d25adc2174f3521ddc220a1393d5e678f GIT binary patch literal 300 zcmV+{0n`48P)P)t-shk$&# ztEHuvkZWOKO+h+YPDg%pag&LIaBOD5fl0%jQ%*ZHSw}#xXh}07B3=*)geVTO83@Rv zS=K=t9~Bt?YB2x6I{!s5pjbdXsW%Y-005jxL_t(|0VPibqC+tZVk4nGmv{e@ett(A zcL1l2vmefW{wG*901Gf8GBR_^Ae3aL0L8yz$x@W1))J*uJ3z3oR4GbD3Sw2u)_aR4 z5I~}Fj5+7vs?=^eF4ybrdYM)Mc-pXizg~wY3!d;8wx74_Xi5P@o3D+z$n9A3_IiI_ yx4C|MNOnBGcChZTWUiz4V}+E0JY^rY5&8q%QU=+d%RWB<0000Eakt!6uB(R-ul;xB+ z6|&pyn`-QM=!W9m>opFSO>(n&d_rfwlb2=tcIb`#2A3z{uNJO!@P7BPeBa`;C+~KY zp162$+I6{aRn2mn_%_=JrX`-=Y9@C! z-Eakt!6@2uk(XJK$GP}8lY)_hx7C40V~52l|7X71w|=?$X{EnXd%I8M zrZtr96c73MZ&SsUNc~JpwR2S|N@=rfFO{f0h~DzRVDSr`kU*i0%I3$PNE|)$cY{gA oq1XTatlX=tp`eq}Q+SeJHd5H<)4brtKx-L1UHx3vIVCg!0Ofv4%K!iX literal 0 HcmV?d00001 diff --git a/mods/main/textures/gui_furnace_arrow_bg.png b/mods/main/textures/gui_furnace_arrow_bg.png new file mode 100755 index 0000000000000000000000000000000000000000..2456a803ea0184e87de63ff6b76b0282c33dfcf9 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^3P5bY!3HD?)>PyJsSHmS$B+ufw^tik4>$<0Ui`AZ zHaD6x+(}OG%qPnPxq|TRyVsi=f3G~OQP;-Nr+w&g#|H}~n?8*T=??k zOGZY9ySw}1#f#_8oqK!bJ|UnSV@Z%-FoVOh8)*y-tO=ejjv*C{Z|`pGz2YEp{NeU> z2i^xwn(E5FtbsdbsdACJ$b$!73!5)L<+!1&>|k6il-&RA_tF1vE^k)*EKvDN#4tv0 z1xG6uTSF z6s(Z6Ld8JWyk2xH_t@Y2ldErSR(ibbasU0vdz4{5eFRL265A!e*Zc3Q4&Hfo$Jrkr zswb7RU`@2J*vFPsNQj|RTjvzcF8u%f$-HlCPV9L3>I{2|zPCp~%CMf(WKb*{4&oErH49-}{rcZzCrb-X_b!CCNSO?pkd8_4S*{ zT&vjobK{(4O^%#@U-;?E<5UjztB&gr^Jd#uR(0OzT-J~m6Ckt~R4RMA`njxgN@xNA D0IsRG literal 0 HcmV?d00001 diff --git a/mods/utility/depends.txt b/mods/utility/depends.txt new file mode 100644 index 0000000..ba2906d --- /dev/null +++ b/mods/utility/depends.txt @@ -0,0 +1 @@ +main diff --git a/mods/utility/init.lua b/mods/utility/init.lua new file mode 100644 index 0000000..da9a95d --- /dev/null +++ b/mods/utility/init.lua @@ -0,0 +1,378 @@ +--formspecs + +local furnace = {} + +function furnace.get_hotbar_bg(x,y) + local out = "" + for i=0,7,1 do + out = out .."image["..x+i..","..y..";1,1;gui_furnace_arrow_bg.png]" + end + return(out) +end + +function furnace.get_inventory_drops(pos, inventory, drops) + local inv = minetest.get_meta(pos):get_inventory() + local n = #drops + for i = 1, inv:get_size(inventory) do + local stack = inv:get_stack(inventory, i) + if stack:get_count() > 0 then + drops[n+1] = stack:to_table() + n = n + 1 + end + end +end + +function furnace.get_furnace_active_formspec(fuel_percent, item_percent) + return "size[8,8.5]".. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. + (fuel_percent)..":default_furnace_fire_fg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:".. + (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]".. + furnace.get_hotbar_bg(0, 4.25) +end + +function furnace.get_furnace_inactive_formspec() + return "size[8,8.5]".. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]".. + furnace.get_hotbar_bg(0, 4.25) +end + +-- +-- Node callback functions that are the same for active and inactive furnace +-- + +local function can_dig(pos, player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src") +end + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if listname == "fuel" then + if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then + if inv:is_empty("src") then + meta:set_string("infotext", "Furnace is empty") + end + return stack:get_count() + else + return 0 + end + elseif listname == "src" then + return stack:get_count() + elseif listname == "dst" then + return 0 + end +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(from_list, from_index) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function swap_node(pos, name) + local node = minetest.get_node(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function furnace_node_timer(pos, elapsed) + -- + -- Initialize metadata + -- + local meta = minetest.get_meta(pos) + local fuel_time = meta:get_float("fuel_time") or 0 + local src_time = meta:get_float("src_time") or 0 + local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 + + local inv = meta:get_inventory() + local srclist, fuellist + local dst_full = false + + local cookable, cooked + local fuel + + local update = true + while elapsed > 0 and update do + update = false + + srclist = inv:get_list("src") + fuellist = inv:get_list("fuel") + + -- + -- Cooking + -- + + -- Check if we have cookable content + local aftercooked + cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) + cookable = cooked.time ~= 0 + + local el = math.min(elapsed, fuel_totaltime - fuel_time) + if cookable then -- fuel lasts long enough, adjust el to cooking duration + el = math.min(el, cooked.time - src_time) + end + + -- Check if we have enough fuel to burn + if fuel_time < fuel_totaltime then + -- The furnace is currently active and has enough fuel + fuel_time = fuel_time + el + -- If there is a cookable item then check if it is ready yet + if cookable then + src_time = src_time + el + if src_time >= cooked.time then + -- Place result in dst list if possible + if inv:room_for_item("dst", cooked.item) then + inv:add_item("dst", cooked.item) + inv:set_stack("src", 1, aftercooked.items[1]) + src_time = src_time - cooked.time + update = true + else + dst_full = true + end + else + -- Item could not be cooked: probably missing fuel + update = true + end + end + else + -- Furnace ran out of fuel + if cookable then + -- We need to get new fuel + local afterfuel + fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist}) + + if fuel.time == 0 then + -- No valid fuel in fuel list + fuel_totaltime = 0 + src_time = 0 + else + -- Take fuel from fuel list + inv:set_stack("fuel", 1, afterfuel.items[1]) + -- Put replacements in dst list or drop them on the furnace. + local replacements = fuel.replacements + if replacements[1] then + local leftover = inv:add_item("dst", replacements[1]) + if not leftover:is_empty() then + local above = vector.new(pos.x, pos.y + 1, pos.z) + local drop_pos = minetest.find_node_near(above, 1, {"air"}) or above + minetest.item_drop(replacements[1], nil, drop_pos) + end + end + update = true + fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time) + end + else + -- We don't need to get new fuel since there is no cookable item + fuel_totaltime = 0 + src_time = 0 + end + fuel_time = 0 + end + + elapsed = elapsed - el + end + + if fuel and fuel_totaltime > fuel.time then + fuel_totaltime = fuel.time + end + if srclist and srclist[1]:is_empty() then + src_time = 0 + end + + -- + -- Update formspec, infotext and node + -- + local formspec + local item_state + local item_percent = 0 + if cookable then + item_percent = math.floor(src_time / cooked.time * 100) + if dst_full then + item_state = "100% (output full)" + else + item_state = "@1%", item_percent + end + else + if srclist and not srclist[1]:is_empty() then + item_state = "Not cookable" + else + item_state = "Empty" + end + end + + local fuel_state = "Empty" + local active = false + local result = false + + if fuel_totaltime ~= 0 then + active = true + local fuel_percent = 100 - math.floor(fuel_time / fuel_totaltime * 100) + fuel_state = "@1%", fuel_percent + formspec = furnace.get_furnace_active_formspec(fuel_percent, item_percent) + swap_node(pos, "utility:furnace_active") + -- make sure timer restarts automatically + result = true + else + if fuellist and not fuellist[1]:is_empty() then + fuel_state = "@1%", 0 + end + formspec = furnace.get_furnace_inactive_formspec() + swap_node(pos, "utility:furnace") + -- stop timer on the inactive furnace + minetest.get_node_timer(pos):stop() + end + + + local infotext + if active then + infotext = "Furnace active" + else + infotext = "Furnace inactive" + end + infotext = infotext .. "\n" .. "(Item: @1; Fuel: @2)", item_state, fuel_state + + -- + -- Set meta values + -- + meta:set_float("fuel_totaltime", fuel_totaltime) + meta:set_float("fuel_time", fuel_time) + meta:set_float("src_time", src_time) + meta:set_string("formspec", formspec) + meta:set_string("infotext", infotext) + + return result +end + +-- +-- Node definitions +-- + +minetest.register_node("utility:furnace", { + description = "Furnace", + tiles = { + "furnace_top.png", "furnace_bottom.png", + "furnace_side.png", "furnace_side.png", + "furnace_side.png", "furnace_front.png" + }, + paramtype2 = "facedir", + groups = {stone=2}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = main.stoneSound(), + + can_dig = can_dig, + + on_timer = furnace_node_timer, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size('src', 1) + inv:set_size('fuel', 1) + inv:set_size('dst', 4) + furnace_node_timer(pos, 0) + end, + + on_metadata_inventory_move = function(pos) + minetest.get_node_timer(pos):start(1.0) + end, + on_metadata_inventory_put = function(pos) + -- start timer function, it will sort out whether furnace can burn or not. + minetest.get_node_timer(pos):start(1.0) + end, + on_blast = function(pos) + local drops = {} + furnace.get_inventory_drops(pos, "src", drops) + furnace.get_inventory_drops(pos, "fuel", drops) + furnace.get_inventory_drops(pos, "dst", drops) + drops[#drops+1] = "default:furnace" + minetest.remove_node(pos) + return drops + end, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) + +minetest.register_node("utility:furnace_active", { + description = "Furnace", + tiles = { + "furnace_top.png", "furnace_bottom.png", + "furnace_side.png", "furnace_side.png", + "furnace_side.png", + { + image = "furnace_front_active.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.5 + }, + } + }, + paramtype2 = "facedir", + light_source = 8, + drop = "default:furnace", + groups = {stone=2, not_in_creative_inventory=1}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = main.stoneSound(), + on_timer = furnace_node_timer, + + can_dig = can_dig, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) + +minetest.register_craft({ + output = "utility:furnace", + recipe = { + {"main:stone", "main:stone", "main:stone"}, + {"main:stone", "", "main:stone"}, + {"main:stone", "main:stone", "main:stone"}, + } +}) diff --git a/todo.txt b/todo.txt index efc4ec6..95af0f8 100644 --- a/todo.txt +++ b/todo.txt @@ -7,7 +7,7 @@ --add treecapitator --itemstack max 1000 --ores -vignette +--vignette furnace crafting recipes make trees drop items on treecapitator -- 2.44.0