-
Notifications
You must be signed in to change notification settings - Fork 20
/
nodes_water.lua
326 lines (306 loc) · 11.5 KB
/
nodes_water.lua
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
313
314
315
316
317
318
319
320
321
322
323
324
325
-- 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
local S = cottages.S
-- 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, cracky = 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()
local bucket = meta:get_string("bucket")
local start = meta:get_string("fillstarttime")
return inv:is_empty("main")
and default.can_interact_with_node(player, pos)
and (not(bucket) or bucket == "")
and ((not(start) or start == "" or
(minetest.get_us_time()/1000000) - tonumber(start)
>= cottages.water_fill_time -2))
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)
local meta = minetest.get_meta(pos)
if not(cottages.player_can_use(meta, 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, pointed_thing)
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(owner))
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~="" and bucket ~= "bucket:bucket_empty") 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
elseif( bucket and bucket == "bucket:bucket_empty") then
minetest.chat_send_player( puncher:get_player_name(),
S("Please wait until your bucket has been filled."))
-- do not give the empty bucket back immediately
return
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
-- 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))
-- remove the bucket from the players inventory
pinv:remove_item( "main", "bucket:bucket_empty")
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'},
}
})