summaryrefslogtreecommitdiff
path: root/cottages/nodes_water.lua
diff options
context:
space:
mode:
Diffstat (limited to 'cottages/nodes_water.lua')
-rw-r--r--cottages/nodes_water.lua312
1 files changed, 312 insertions, 0 deletions
diff --git a/cottages/nodes_water.lua b/cottages/nodes_water.lua
new file mode 100644
index 0000000..1cfe77d
--- /dev/null
+++ b/cottages/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 = cottages.sounds.wood,
+ 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) 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)) 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'},
+ }
+})
+