summaryrefslogtreecommitdiff
path: root/cottages/nodes_water.lua
blob: 1cfe77df82fa2bdbcec069af2f4346a0bbe588c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
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'},
	}
})