From eb98db71e678a66347ae7dcef71bdcaa0b3660ff Mon Sep 17 00:00:00 2001 From: rnd1 Date: Fri, 2 Sep 2016 17:49:33 +0200 Subject: [PATCH] init --- depends.txt | 1 + init.lua | 316 +++++++++++++++++++++++++++++++++++++++++ textures/harvester.png | Bin 0 -> 1448 bytes 3 files changed, 317 insertions(+) create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 textures/harvester.png diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..44050e7 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +protector? \ No newline at end of file diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..6e81928 --- /dev/null +++ b/init.lua @@ -0,0 +1,316 @@ +-- BASIC_HARVEST: lightweight simple harvesting to be used with protector mod +-- minetest 0.4.14+ +-- (c) 2015-2016 rnd + +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . + + + +local harvest = {}; + +-- SETTINGS + +harvest.radius = 5; -- this should be protector radius +harvest.full = 5; -- how many steps before new harvest cycle begins: so harvester is activated every 5x20s by default +harvest.timestep = 20; -- how frequently to process harvesters ( default every 30 seconds ) +harvest.fuel_cost = 0.1; -- how many coal units to harvest 1 piece + +harvest.forbidden_nodes = { + ["air"]=true, + ["default:water_source"]=true, + ["default:water_flowing"]=true, + ["default:lava_source"]=true, + ["default:lava_flowing"]=true, +} + +-- END OF SETTINGS + + + +local harvest_process = function(pos) -- burn fuel, dig, put materials in target container + + local meta = minetest.get_meta(pos); + local search_node = meta:get_string("filter"); + + if search_node == "" or harvest.forbidden_nodes[search_node] then + meta:set_string("infotext","error: right click harvester and set what to harvest by inserting item in FILTER"); + return + end + + local x0,y0,z0; -- protector position + x0 = meta:get_int("x0");y0 = meta:get_int("y0");z0 = meta:get_int("z0"); + local x1,y1,z1; -- container position + x1 = meta:get_int("x1");y1 = meta:get_int("y1");z1 = meta:get_int("z1"); + local tpos = {x=x1,y=y1,z=z1}; + + if minetest.is_protected(tpos, meta:get_string("owner")) then + meta:set_string("infotext", "error. target position " .. minetest.string_to_pos(tpos) .. " is protected."); + return + end + + -- DIG PROCESS + local pos1 = {x=x0-harvest.radius,y=y0-harvest.radius,z=z0-harvest.radius} + local pos2 = {x=x0+harvest.radius,y=y0+harvest.radius,z=z0+harvest.radius} + + -- load area data + local manip = minetest.get_voxel_manip() -- VoxelManip object + local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2) -- --Reads a chunk of map from the map containing the region formed by pos1 and pos2 + local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) -- create new VoxelArea instance, needed for iterating over area in loop + + local data = manip:get_data() -- Gets the data read into the VoxelManip object + + local search_id = minetest.get_content_id(search_node); + local replace_id = minetest.get_content_id("air"); + + local count = 0 + + for i in area:iterp(pos1, pos2) do -- returns an iterator that returns indices inside VoxelArea + if data[i] == search_id then + data[i] = replace_id + count = count + 1 + end + end + + if count == 0 then + meta:set_string("infotext","idle. nothing to harvest."); + return + end + + -- CHECK FUEL + -- check for selected fuel source + local inv = meta:get_inventory(); + local fuel_source = inv:get_stack("fuel_select",1):get_name(); + + + local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = inv:get_list("fuel_select") }) + local fuel_need; + local caloric_value = fueladd.time or 0; -- equals 1 for default:coal_lump + caloric_value = caloric_value / 40; + fuel_need = harvest.fuel_cost*count; + + if caloric_value <= 0 then + meta:set_string("infotext","error. insert proper fuel into FUEL SELECTOR.") + return + end + + fuel_need = math.ceil(fuel_need/caloric_value); + + if not inv:contains_item("main", ItemStack(fuel_source .. " " .. fuel_need)) then + meta:set_string("infotext", "not enough fuel. Need ".. fuel_need .. " pieces of " .. fuel_source .. " in main inventory of harvester "); + return; + end + + -- CHECK TARGET INVENTORY + local tinv = minetest.get_meta(tpos):get_inventory(); + if not tinv then + meta:set_string("infotext", "error. target position " .. minetest.pos_to_string(tpos) .. " does not have inventory "); + return + end + + -- TO DO: replace search_node with proper item drops + if not tinv:room_for_item("main", ItemStack(search_node .. " " .. count)) then + meta:set_string("infotext", "error. can not insert " .. search_node .. " " .. count .. " in target main inventory "); + return + end + + -- ALL OK: add items to target, burn fuel + --tinv:add_item("main", ItemStack(search_node .. " " .. count)); + + -- drop code emulation + local table = minetest.registered_items[search_node]; + if table~=nil then --put in chest + if table.drop~= nil then -- drop handling + if table.drop.items then + --handle drops better, emulation of drop code + local max_items = table.drop.max_items or 0; + if max_items==0 then -- just drop all the items (taking the rarity into consideration) + max_items = #table.drop.items or 0; + end + local drop = table.drop; + local i = 0; + for k,v in pairs(drop.items) do + if i > max_items then break end; i=i+1; + local rare = v.rarity or 1; + + local count1 = math.floor(count/rare); + for _,v1 in pairs(v.items) do + tinv:add_item("main",ItemStack(v1 .. " " .. count1)); + end + end + else + tinv:add_item("main",ItemStack(table.drop .. " " .. count)); + end + else + tinv:add_item("main",ItemStack(search_node .. " " .. count)); + end + end + + + --burn fuel + inv:remove_item("main", ItemStack(fuel_source.. " " .. fuel_need)); + + -- Update map + manip:set_data(data) -- Sets the data contents of the VoxelManip object + manip:write_to_map() -- Writes the data loaded from the VoxelManip back to the map + manip:update_map() -- Update map after writing chunk back to map + + meta:set_string("infotext", "Harvest cycle completed. Processed ".. count .. " items "); + meta:set_int("process",0); -- resets harvester - new cycle begins +end + + +minetest.register_abm{ + nodenames = {"basic_harvest:harvester"}, + neighbors = {}, + interval = harvest.timestep, + chance = 1, + action = function(pos) + local meta = minetest.get_meta(pos); + local player = minetest.get_player_by_name(meta:get_string("owner")); if not player then return end + local process = meta:get_int("process"); + + if process= harvest.full then + -- try harvest + harvest_process(pos); + else + meta:set_int("process", process); + meta:set_string("infotext","processing harvest: " .. process .. "/" .. harvest.full); + end + end, +} + + +local harvester_update_meta = function(pos) + local meta = minetest.get_meta(pos); + local x1,y1,z1; + x1 = meta:get_int("x1"); y1 = meta:get_int("y1");z1 = meta:get_int("z1"); + local filter = meta:get_string("filter"); + + local list_name = "nodemeta:"..pos.x..','..pos.y..','..pos.z + local form = + "size[8,10]" .. -- width, height + --"size[6,10]" .. -- width, height + "label[0,0;FUEL SELECTOR]".."label[2,0;FILTER]".. + "list["..list_name..";fuel_select;0.,0.5;1,1;]".. + "list["..list_name..";filter;2.,0.5;1,1;]".. "field[3.25,0.75;2,1;filter;filter;"..filter.."]" .. + "field[5.25,0.75;1,1;x1;Target;"..x1.."] field[6.25,0.75;1,1;y1;;"..y1.."] field[7.25,0.75;1,1;z1;;"..z1.."]".. + "list["..list_name..";main;0.,1.5;8,4;]".. + "list[current_player;main;0,6;8,4;]".. + "button[8.5,0.5;1,1;OK;OK]"; + meta:set_string("formspec", form); +end + + + +minetest.register_node("basic_harvest:harvester", { + description = "Harvester : harvest all selected nodes inside nearby protector space", + tiles = {"harvester.png"}, + groups = {oddly_breakable_by_hand=2}, + sounds = "", + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos); + + local ppos = minetest.find_node_near(pos,harvest.radius,"protector:protect"); + if not ppos then + meta:set_string("infotext", "error: need to place inside protector area."); + return + end + + local name = placer:get_player_name(); + if minetest.get_meta(ppos):get_string("owner")~=name then + meta:set_string("infotext", "error: must be placed by owner of protector"); + end + + meta:set_int("x1",pos.x);meta:set_int("y1",pos.y);meta:set_int("z1",pos.z); + + meta:set_int("x0",ppos.x);meta:set_int("y0",ppos.y);meta:set_int("z0",ppos.z); + + meta:set_string("infotext", "Harvester: To operate it insert fuel into FUEL_SELECTOR and main inventory, then insert item to be harvested into FILTER. After that just wait.") + meta:set_string("owner", placer:get_player_name()); + + local inv = meta:get_inventory(); + inv:set_size("filter", 1); + inv:set_size("main",32); + inv:set_size("fuel_select",1); + end, + + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + local meta = minetest.get_meta(pos); + local privs = minetest.get_player_privs(player:get_player_name()); + if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return end + harvester_update_meta(pos); + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos); + local privs = minetest.get_player_privs(player:get_player_name()); + if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return 0 end + + if listname == "filter" then + meta:set_string("filter", stack:get_name()) + harvester_update_meta(pos); + end + return stack:get_count(); + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos); + local privs = minetest.get_player_privs(player:get_player_name()); + if minetest.is_protected(pos, player:get_player_name()) and not privs.privs then return 0 end + + if listname == "filter" then + meta:set_string("filter", "") + harvester_update_meta(pos); + end + return stack:get_count(); + end, + + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + return 0; + end, + + on_receive_fields = function(pos, formname, fields, sender) + + if minetest.is_protected(pos, sender:get_player_name()) then return end + + local meta = minetest.get_meta(pos); + if fields.filter then + meta:set_string("filter",fields.filter) + end + + if fields.x1 then meta:set_int("x1",fields.x1) end + if fields.y1 then meta:set_int("y1",fields.y1) end + if fields.z1 then meta:set_int("z1",fields.z1) end + + harvester_update_meta(pos); + + if fields.quit then return end + end, + +}) + + +minetest.register_craft({ + output = "basic_harvest:harvester", + recipe = { + {"default:steel_ingot","default:mese","default:steel_ingot"}, + {"default:mese","default:diamondblock","default:mese"}, + {"default:steel_ingot","default:mese","default:steel_ingot"}, + } +}) \ No newline at end of file diff --git a/textures/harvester.png b/textures/harvester.png new file mode 100644 index 0000000000000000000000000000000000000000..5669074848175e8b45517f6e53888c334d14dd85 GIT binary patch literal 1448 zcmV;Z1y}lsP)J0|o{I1_uHL3IqoR0|yBN2L}ZR2L%WS0SFof2?hoV3kVAe2n-Jj4Gjwp3knVr z4G<6(76=p<78n=`85jx|8W|uR1SB8`B_RnYBn%}a79%DlDkl;xDGn|v4lpYYGA|Z3 zG8{iUB0xYgTv8uYQbk~1P-J6PX=YM~bRmFrLWy=GjDSvsg@vMtAESvMhlhuwiXfzl zAc%;FiHV7(j31|rAf}8Xii(Phi;Jj^A&iWSjg5_tj*gFykFAm+t&$>;kdTp)k*|~@ zl9H0Jl_Haqld_g2v6m{9m6fxYD72U-mX?;6mzS8Bn6{fMxtk=nn=6@_nYx@Lnwpxs zoh6%_o1C1Syq_n%pC`MYFP)v8o}QkcpP!+jp}?dxqN1Y0r7feQqokyy!lyUIr!b|Z zrN^i!rlzK+r>Cf>sLZP;#j8EWt3Iizsm`n<&8#QRtR=>*KF+Ks&8#ZMtUt%BKdP## z&aEZRttQT`C(o@V&#flUttY~*Qmd=0&#orVt|!p0C(Euj&#o-2tgO(lC(*Aa(XS`E zu6(Vnt;DZZ)377buqe^6E6T7#%dkVPuCCLuD9o`zudlDwvL?*3Ma{BCu&}VrvqsLd zN3pT7*R&|kv`5dhNV2lB*tIFowMEahNVBuEw6wI_wuz*=jZ3>=;-U~>+J08?d|RQ`uh9(`~3X;|NsAy1fSyo0004E zOGiWihy@);00009a7bBm000XU000XU0RWnu7ytkO2XskIMF-#s0t*8-;!Fbd0000T zX;fHrLvL+uWo~o;00000Lvm$dbY)~9cWHEJAV*0}P-HG;2LJ#9GD$>1R5;6Jl1*zG zQ51&XZT9{I3Al18$*cwnx=_Xu8YEE2xEQ1^j1nRQI}5iiU1gJdt*s#cT22>mBE6Bq z@wgO|<8fJ*W3iZQD;^hKy&`Kr}?cbUegN}DjsJ+jelT|={7 zWtUoRg^3y;-=p(TX92=P-3Qg~J)Xvn3WOZveCKQZ9~dmlPGEWH+D%nn4ly%IPJk5P zT5ep`oMA!Ke}JY7KErlPWR7QY?MUlBPziQ$L;g^p$fOPR0PYB7bUPvwOjuw^Q^!-1 z299Wy;!ET=#(Q8z6P^@xOu)N%@_{RnF@|fv8mdRPb1(L76{mM}5>6#U^en(!n51`r z!+kf?nw3`QVXy`I?#=eK?qOFLY+C5-Nep_o>%-CtL;PG=3#+)#ZWz+~ytpsc<%rG~Z|AF^WQ}kjBXsa1U zdSwrIpc@=^;;Ju0d>b(pMylZh1E{0#=sec`d+dFS?pNG>W?JZ8H~{ra3yu2iF28W* z!F^~{QBrcdLne8r)ZA4CYWnS|a-CIj`2wqazMy1M$%`A5i-BlZ5JXW3+n;4DOBWK^ zd=pwWEs650uo#Yrp-?ay6N15LKs-yvP7~+Zi_TxFb&sO%um!sS0000