diff --git a/init.lua b/init.lua index 29227a9..df76b0f 100644 --- a/init.lua +++ b/init.lua @@ -70,6 +70,7 @@ dofile(minetest.get_modpath("cottages").."/nodes_fences.lua"); dofile(minetest.get_modpath("cottages").."/nodes_roof.lua"); dofile(minetest.get_modpath("cottages").."/nodes_barrel.lua"); dofile(minetest.get_modpath("cottages").."/nodes_mining.lua"); +dofile(minetest.get_modpath("cottages").."/nodes_water.lua"); --dofile(minetest.get_modpath("cottages").."/nodes_chests.lua"); -- this is only required and useful if you run versions of the random_buildings mod where the nodes where defined inside that mod diff --git a/locale/de.txt b/locale/de.txt index 8ff2979..efee145 100644 --- a/locale/de.txt +++ b/locale/de.txt @@ -136,7 +136,15 @@ You have grinded the last %s wheat seeds. = Du hast die letzten %s Weizenkoerner Your threshing floor can now be used by other players as well. = Dein Dreschboden kann jetzt auch von anderen Spielern benutzt werden. Your mill, powered by punching can now be used by other players as well. = Deine Mühle kann jetzt auch von anderen Spielern benutzt werden. -Your threshing floor can only be used by yourself. = Dein Dreschboden kann nur noch von dir benutzt werden. -Your mill, powered by punching can only be used by yourself. = Deine Mühle kann nur noch von dir benutzt werden. +Your threshing floor can only be used by yourself. = Dein Dreschboden kann jetzt nur noch von dir selbst benutzt werden. +Your mill, powered by punching can only be used by yourself. = Deine Mühle kann jetzt nur noch von dir selbst benutzt werden. -Public? = Öffentlich? +Public? = Oeffentlich? + +Public tree trunk well = Oeffentlicher Baumstammbrunnen +Public tree trunk well (owned by %s) = Oeffentlicher Baumstammbrunnen (gehoert %s) +Private tree trunk well (owned by %s) = Privater Baumstammbrunnen (gehoert %s) +This tree trunk well is owned by %s. You can't use it. = Dieser Baumstammbrunnen gehoert %s. Du kannst ihn leider nicht benutzen. +Sorry. You have no room for the bucket. Please free some space in your inventory first! = Du hast leider keinen Platz mehr fuer den Eimer. Bitte schaffe erst ein wenig Platz! +Your tree trunk well can now be used by other players as well. = Dein Baumstammbrunnen kann jetzt auch von anderen Spielern benutzt werdn. +Your tree trunk well can only be used by yourself. = Dein Baumstammbrunnen kann jetzt nur noch von dir selbst benutzt werdn. diff --git a/locale/template.txt b/locale/template.txt index 36b3f87..6c6dd66 100644 --- a/locale/template.txt +++ b/locale/template.txt @@ -139,3 +139,10 @@ Your threshing floor can only be used by yourself. = Your mill, powered by punching can only be used by yourself. = Public? = + +Public tree trunk well = +Public tree trunk well (owned by %s) = +This tree trunk well is owned by %s. You can't use it. = +Sorry. You have no room for the bucket. Please free some space in your inventory first! = +Your tree trunk well can now be used by other players as well. = +Your tree trunk well can only be used by yourself. = diff --git a/nodes_water.lua b/nodes_water.lua new file mode 100644 index 0000000..09f44ec --- /dev/null +++ b/nodes_water.lua @@ -0,0 +1,312 @@ + +-- TODO: play sound while working +-- TODO: play sound when emptying a bucket +-- TODO: store correct bucket texture when loading the world anew +-- TODO: show particles when running? distinguish between running/idle state? (with punch?) + +-- well for getting water +-- * has some storage space for buckets (filled with water, river water or empty) +-- * only the owner can use the bucket store and the well +-- * the bucket will be added as an entity and slowly rotate; +-- once filled, the texture of the bucket is changed +-- * full (water or river water) buckets can be emptied +-- * by default public; but can also be made private + + +-- how many seconds does it take to fill a bucket? +cottages.water_fill_time = 10 + + +-- code taken from the itemframes mod in homedecor +-- (the relevant functions are sadly private there and thus cannot be reused) +local tmp = {} +minetest.register_entity("cottages:bucket_entity",{ + hp_max = 1, + visual="wielditem", + visual_size={x = 0.33, y = 0.33}, + collisionbox = {0, 0, 0, 0, 0, 0}, + physical = false, + textures = {"air"}, + on_activate = function(self, staticdata) + if tmp.nodename ~= nil and tmp.texture ~= nil then + self.nodename = tmp.nodename + tmp.nodename = nil + self.texture = tmp.texture + tmp.texture = nil + else + if staticdata ~= nil and staticdata ~= "" then + local data = staticdata:split(';') + if data and data[1] and data[2] then + self.nodename = data[1] + self.texture = data[2] + end + end + end + if self.texture ~= nil then + self.object:set_properties({textures = {self.texture}}) + end + self.object:set_properties({automatic_rotate = 1}) + if self.texture ~= nil and self.nodename ~= nil then + local entity_pos = vector.round(self.object:get_pos()) + local objs = minetest.get_objects_inside_radius(entity_pos, 0.5) + for _, obj in ipairs(objs) do + if obj ~= self.object and + obj:get_luaentity() and + obj:get_luaentity().name == "cottages:bucket_entity" and + obj:get_luaentity().nodename == self.nodename and + obj:get_properties() and + obj:get_properties().textures and + obj:get_properties().textures[1] == self.texture then + minetest.log("action","[cottages] Removing extra " .. + self.texture .. " found in " .. self.nodename .. " at " .. + minetest.pos_to_string(entity_pos)) + self.object:remove() + break + end + end + end + end, + get_staticdata = function(self) + if self.nodename ~= nil and self.texture ~= nil then + return self.nodename .. ';' .. self.texture + end + return "" + end, +}) + +cottages.water_gen_fill_bucket = function(pos) + if( not(pos)) then + return + end + local meta = minetest.get_meta(pos) + local bucket = meta:get_string("bucket") + -- nothing to do + if( not(bucket) or bucket ~= "bucket:bucket_empty") then + return + end + -- abort if the water has not been running long enough + -- (the player may have removed a bucket before it was full) + start = meta:get_string("fillstarttime") + if( (minetest.get_us_time()/1000000) - tonumber(start) < cottages.water_fill_time -2) then + return + end + + -- the bucket has been filled + meta:set_string("bucket", "bucket:bucket_river_water") + + -- change the texture of the bucket to that of one filled with river water + local objs = nil + objs = minetest.get_objects_inside_radius(pos, .5) + if objs then + for _, obj in ipairs(objs) do + if obj and obj:get_luaentity() and obj:get_luaentity().name == "cottages:bucket_entity" then + obj:set_properties( { textures = { "bucket:bucket_river_water" }}) + obj:get_luaentity().nodename = "bucket:bucket_river_water" + obj:get_luaentity().texture = "bucket:bucket_river_water" + end + end + end +end + + +minetest.register_node("cottages:water_gen", { + description = "Tree Trunk Well", + tiles = {"default_tree_top.png", "default_tree.png^[transformR90", "default_tree.png^[transformR90"}, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + node_box = { + type = "fixed", + fixed = { + -- floor of water bassin + {-0.5, -0.5+(3/16), -0.5, 0.5, -0.5+(4/16), 0.5}, + -- walls + {-0.5, -0.5+(3/16), -0.5, 0.5, (4/16), -0.5+(2/16)}, + {-0.5, -0.5+(3/16), -0.5, -0.5+(2/16), (4/16), 0.5}, + { 0.5, -0.5+(3/16), 0.5, 0.5-(2/16), (4/16), -0.5}, + { 0.5, -0.5+(3/16), 0.5, -0.5+(2/16), (4/16), 0.5-(2/16)}, + -- feet + {-0.5+(3/16), -0.5, -0.5+(3/16), -0.5+(6/16), -0.5+(3/16), 0.5-(3/16)}, + { 0.5-(3/16), -0.5, -0.5+(3/16), 0.5-(6/16), -0.5+(3/16), 0.5-(3/16)}, + -- real pump + { 0.5-(4/16), -0.5, -(2/16), 0.5, 0.5+(4/16), (2/16)}, + -- water pipe inside wooden stem + { 0.5-(8/16), 0.5+(1/16), -(1/16), 0.5, 0.5+(3/16), (1/16)}, + -- where the water comes out + { 0.5-(15/32), 0.5, -(1/32), 0.5-(12/32), 0.5+(1/16), (1/32)}, + }, + }, + selection_box = { + type = "fixed", + fixed = { -0.5, -0.5, -0.5, 0.5, 0.5+(4/16), 0.5 } + }, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local spos = pos.x .. "," .. pos.y .. "," .. pos.z + meta:set_string("formspec", + "size[8,9]" .. + "label[3.0,0.0;Tree trunk well]".. + "label[1.5,0.7;Punch the well while wielding an empty bucket.]".. + "label[1.5,1.0;Your bucket will slowly be filled with river water.]".. + "label[1.5,1.3;Punch again to get the bucket back when it is full.]".. + "label[1.0,2.9;Internal bucket storage (passive storage only):]".. + "item_image[0.2,0.7;1.0,1.0;bucket:bucket_empty]".. + "item_image[0.2,1.7;1.0,1.0;bucket:bucket_river_water]".. + "label[1.5,1.9;Punch well with full water bucket in order to empty bucket.]".. + "button_exit[6.0,0.0;2,0.5;public;"..S("Public?").."]".. + "list[nodemeta:" .. spos .. ";main;1,3.3;8,1;]" .. + "list[current_player;main;0,4.85;8,1;]" .. + "list[current_player;main;0,6.08;8,3;8]" .. + "listring[nodemeta:" .. spos .. ";main]" .. + "listring[current_player;main]") + local inv = meta:get_inventory() + inv:set_size('main', 6) + meta:set_string("infotext", S("Public tree trunk well")) -- (punch with empty bucket to fill bucket)") + end, + after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name() or "") + meta:set_string("infotext", S("Public tree trunk well (owned by %s)"):format(meta:get_string("owner"))) + -- no bucket loaded + meta:set_string("bucket", "") + meta:set_string("public", "public") + end, + can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") and + default.can_interact_with_node(player, pos) + end, + -- no inventory move allowed + allow_metadata_inventory_move = function(pos, from_list, from_index, + to_list, to_index, count, player) + return 0 + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if not(stack) or not cottages.player_can_use(meta, player:get_player_name()) then + return 0 + end + local inv = meta:get_inventory() + -- only for buckets + local sname = stack:get_name() + if( sname ~= "bucket:bucket_empty" + and sname ~= "bucket:bucket_water" + and sname ~= "bucket:bucket_river_water") then + return 0 + end + return stack:get_count() + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + if not(cottages.player_can_use(meta:get_string(pos), player:get_player_name())) then + return 0 + end + return stack:get_count() + end, + on_blast = function() end, + on_receive_fields = function(pos, formname, fields, sender) + cottages.switch_public(pos, formname, fields, sender, 'tree trunk well') + end, + -- punch to place and retrieve bucket + on_punch = function(pos, node, puncher) + if( not( pos ) or not( node ) or not( puncher )) then + return + end + -- only the owner can use the well + local name = puncher:get_player_name() + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local public = meta:get_string("public") + if( name ~= owner and public~="public") then + minetest.chat_send_player( name, S("This tree trunk well is owned by %s. You can't use it."):format(name)) + return + end + + -- we will either add or take from the players inventory + local pinv = puncher:get_inventory() + + -- is the well working on something? (either empty or full bucket) + local bucket = meta:get_string("bucket") + -- there is a bucket loaded - either empty or full + if( bucket and bucket~="") then + if( not(pinv:room_for_item("main", bucket))) then + minetest.chat_send_player( puncher:get_player_name(), + S("Sorry. You have no room for the bucket. Please free some ".. + "space in your inventory first!")) + return + end + end + + -- remove the old entity (either a bucket will be placed now or a bucket taken) + local objs = nil + objs = minetest.get_objects_inside_radius(pos, .5) + if objs then + for _, obj in ipairs(objs) do + if obj and obj:get_luaentity() and obj:get_luaentity().name == "cottages:bucket_entity" then + obj:remove() + end + end + end + + -- the player gets the bucket (either empty or full) into his inventory + if( bucket and bucket ~= "") then + pinv:add_item("main", bucket ) + meta:set_string("bucket", "") + -- we are done + return + end + + -- punching with empty bucket will put that bucket into the well (as an entity) + -- and will slowly fill it + local wielded = puncher:get_wielded_item() + if( wielded + and wielded:get_name() + and wielded:get_name() == "bucket:bucket_empty") then + -- remove the bucket from the players inventory + pinv:remove_item( "main", "bucket:bucket_empty") + -- remember that we got a bucket loaded + meta:set_string("bucket", "bucket:bucket_empty") + -- create the entity + tmp.nodename = "bucket:bucket_empty" + -- TODO: add a special texture with a handle for the bucket here + tmp.texture = "bucket:bucket_empty" + local e = minetest.add_entity({x=pos.x,y=pos.y+(4/16),z=pos.z},"cottages:bucket_entity") + -- fill the bucket with water + minetest.after(cottages.water_fill_time, cottages.water_gen_fill_bucket, pos) + -- the bucket will only be filled if the water ran long enough + meta:set_string("fillstarttime", tostring(minetest.get_us_time()/1000000)) + return; + end + -- buckets can also be emptied here + if( wielded + and wielded:get_name() + and (wielded:get_name() == "bucket:bucket_water" + or wielded:get_name() == "bucket:bucket_river_water") + and (pinv:room_for_item("main", "bucket:bucket_empty"))) then + -- remove the full bucket from the players inventory + pinv:remove_item( "main", wielded:get_name()) + -- add empty bucket + pinv:add_item("main", "bucket:bucket_empty") + -- TODO: play diffrent sound when pouring a bucket + return; + end + + -- else check if there is a bucket that can be retrieved + meta:set_string("bucket","") + end, +}) + + +-- a well (will fill water buckets) crafted from wooden materials +minetest.register_craft({ + output = 'cottages:water_gen', + recipe = { + {'default:stick', '', ''}, + {'default:tree', 'bucket:bucket_empty', 'bucket:bucket_empty'}, + {'default:tree', 'default:tree', 'default:tree'}, + } +}) +