]> git.lizzy.rs Git - crafter_client.git/blob - weather_handling.lua
Fix rain sound not restarting
[crafter_client.git] / weather_handling.lua
1 local minetest,name,vector,math,pairs = minetest,minetest.localplayer:get_name(),vector,math,pairs
2
3 local weather_intake = minetest.mod_channel_join("weather_intake")
4 local weather = minetest.mod_channel_join("weather_nodes")
5 local weather_type = minetest.mod_channel_join("weather_type")
6
7 local all_nodes = {}
8 local do_effects = false
9 local snow = false
10 local rain = false
11 local weather_update_timer = 0
12 local id_table = {}
13
14 local rain_sound_handle = nil
15
16
17
18 local y
19 local pos
20 local radius = 10
21 local particle_table
22 local area
23 local min
24 local max
25 local area_index
26 local spawn_table
27 local lightlevel
28 local null
29 local curr_light
30 local weather_effects = function(player,defined_type)
31         pos = vector.round(player:get_pos())
32         area = vector.new(10,10,10)
33         min = vector.subtract(pos, area)
34         max = vector.add(pos, area)
35         area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
36         spawn_table = {}
37         --find the highest y value
38         for _,index in pairs(area_index) do
39                 if not spawn_table[index.x] then spawn_table[index.x] = {} end
40                 if not spawn_table[index.x][index.z] then
41                         spawn_table[index.x][index.z] = index.y
42                 elseif spawn_table[index.x][index.z] < index.y then
43                         spawn_table[index.x][index.z] = index.y
44                 end
45         end
46
47         if defined_type == "rain" then
48         curr_light = minetest.get_node_light({x=pos.x,y=pos.y+1,z=pos.z},0.5)
49         --rain sound effect
50         if curr_light then
51                 if curr_light >= 15 then
52                         if not rain_sound_handle then
53                                 rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
54                         end
55                         minetest.sound_fade(rain_sound_handle, 0.5, 1)
56                 elseif curr_light < 15 and rain_sound_handle then
57                         minetest.sound_fade(rain_sound_handle, -0.5, 0)
58                         rain_sound_handle = nil
59                 end
60         end
61
62         particle_table = {
63                 amount = 3,
64                 time = 0.5,
65                 minvel = {x=0, y=-20, z=0},
66                 maxvel = {x=0, y=-20, z=0},
67                 minacc = {x=0, y=0, z=0},
68                 maxacc = {x=0, y=0, z=0},
69                 minexptime = 0.5,
70                 maxexptime = 0.5,
71                 minsize = 4,
72                 maxsize = 4,
73                 collisiondetection = true,
74                 collision_removal = true,
75                 object_collision = false,
76                 vertical = true,
77                 texture = "raindrop.png^[opacity:80",
78         }
79         elseif defined_type == "snow" then
80         particle_table = {
81                 amount = 1,
82                 time = 0.5,
83                 minvel = {x=-0.2, y=-0.2, z=-0.2},
84                 maxvel = {x=0.2, y=-0.5, z=0.2},
85                 minacc = {x=0, y=0, z=0},
86                 maxacc = {x=0, y=0, z=0},
87                 minexptime = 1,
88                 maxexptime = 1,
89                 minsize = 1,
90                 maxsize = 1,
91                 collisiondetection = true,
92                 collision_removal = true,
93                 object_collision = false,
94                 texture = "snowflake_"..math.random(1,2)..".png",
95         }
96         elseif defined_type == "ichor" then
97         particle_table = {
98                 amount = 1,
99                 time = 0.5,
100                 minvel = {x=-0.2, y=0.2, z=-0.2},
101                 maxvel = {x=0.2, y=0.5, z=0.2},
102                 minacc = {x=0, y=0, z=0},
103                 maxacc = {x=0, y=0, z=0},
104                 minexptime = 1,
105                 maxexptime = 1,
106                 minsize = 1,
107                 maxsize = 1,
108                 collisiondetection = true,
109                 collision_removal = true,
110                 object_collision = false,
111                 texture = "ichor_"..math.random(1,2)..".png",
112         }
113         end
114
115
116         for x = min.x,max.x do
117                 for z = min.z,max.z do
118                         y = pos.y - 5
119                         if spawn_table[x] and spawn_table[x][z] then
120                                 y = spawn_table[x][z]
121                         end
122                         if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
123                                 lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
124                                 if lightlevel >= 14 or defined_type == "ichor" then
125
126                                         particle_table.minpos = vector.new(x-0.5,y,z-0.5)
127                                         particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
128
129                                         null = minetest.add_particlespawner(particle_table)
130                                 end
131                         end
132                 end
133         end
134 end
135
136
137
138 --client runs through spawning weather particles
139 local player_pos
140 local function update_weather()
141         player_pos = minetest.localplayer:get_pos()
142         if do_effects then
143                 if snow or rain then
144                         --do normal weather
145                         if player_pos.y > -10033 then
146                                 if snow == true then
147                                         weather_effects(minetest.localplayer, "snow")
148                                 elseif rain == true then
149                                         weather_effects(minetest.localplayer, "rain")
150                                 end
151                         --rain blood upwards in the nether
152                         else
153                                 if snow == true or rain == true then
154                                         weather_effects(minetest.localplayer, "ichor")
155                                 end
156                         
157                                 --stop the rain sound effect
158                                 if rain_sound_handle then
159                                         minetest.sound_fade(rain_sound_handle, -0.5, 0)
160                                         rain_sound_handle = nil
161                                 end
162                         end
163                 end
164         end
165         if not rain and rain_sound_handle then
166                 minetest.sound_fade(rain_sound_handle, -0.5, 0)
167                 rain_sound_handle = nil
168         end
169         --do again every half second
170         minetest.after(0.5, function()
171                 update_weather()
172         end)
173 end
174
175 minetest.register_on_modchannel_message(function(channel_name, sender, message)
176         --receive the initial packet which tells the client which nodes
177         --to spawn weather columns on
178         if sender == "" and channel_name == "weather_nodes" then
179                 all_nodes = minetest.deserialize(message)
180                 do_effects = true
181                 weather:leave() --leave the channel
182         end
183         --receive the weather type
184         if sender == "" and channel_name == "weather_type" then
185                 if message == "1" then
186                         rain = false
187                         snow = true
188                 elseif message == "2" then
189                         rain = true
190                         snow = false
191                 else
192                         rain = false
193                         snow = false
194                 end
195         end
196 end)
197
198
199 --We must tell the server that we're ready
200 minetest.after(0,function()
201         weather_intake:send_all("READY")
202         weather_intake:leave()
203         weather_intake = nil --leave the channel
204         
205         --begin weather update
206         update_weather()
207 end)