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