2 minetest,name,vector,math,pairs
4 minetest,minetest.localplayer:get_name(),vector,math,pairs
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")
11 local do_effects = false
14 local weather_update_timer = 0
17 local rain_sound_handle = nil
20 ["main:water"] = true,
21 ["main:waterflow"] = true,
23 ["main:lavaflow"] = true,
24 ["nether:lava"] = true,
25 ["nether:lavaflow"] = true,
41 local distance = vector.distance
43 local weather_effects = function(player,defined_type)
44 pos = vector.round(player:get_pos())
45 area = vector.new(10,10,10)
46 min = vector.subtract(pos, area)
47 max = vector.add(pos, area)
48 area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
50 --find the highest y value
51 for _,index in pairs(area_index) do
52 if not spawn_table[index.x] then spawn_table[index.x] = {} end
53 if not spawn_table[index.x][index.z] then
54 spawn_table[index.x][index.z] = index.y
55 elseif spawn_table[index.x][index.z] < index.y then
56 spawn_table[index.x][index.z] = index.y
60 if defined_type == "rain" then
61 curr_light = minetest.get_node_light(minetest.camera:get_pos(),0.5)
64 current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
66 if curr_light >= 15 and current_node and not liquids[current_node.name] then
67 if not rain_sound_handle then
68 rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
70 minetest.sound_fade(rain_sound_handle, 0.5, 1)
71 elseif rain_sound_handle then
72 minetest.sound_fade(rain_sound_handle, -0.5, 0)
73 rain_sound_handle = nil
80 minvel = {x=0, y=-30, z=0},
81 maxvel = {x=0, y=-30, z=0},
82 minacc = {x=0, y=0, z=0},
83 maxacc = {x=0, y=0, z=0},
88 collisiondetection = true,
89 collision_removal = true,
90 object_collision = false,
92 texture = "raindrop.png^[opacity:80",
94 elseif defined_type == "snow" then
98 minvel = {x=-0.2, y=-0.2, z=-0.2},
99 maxvel = {x=0.2, y=-0.5, z=0.2},
100 minacc = {x=0, y=0, z=0},
101 maxacc = {x=0, y=0, z=0},
106 collisiondetection = true,
107 collision_removal = true,
108 object_collision = false,
109 texture = "snowflake_"..math.random(1,2)..".png",
111 elseif defined_type == "ichor" then
115 minvel = {x=-0.2, y=0.2, z=-0.2},
116 maxvel = {x=0.2, y=0.5, z=0.2},
117 minacc = {x=0, y=0, z=0},
118 maxacc = {x=0, y=0, z=0},
123 collisiondetection = true,
124 collision_removal = true,
125 object_collision = false,
126 texture = "ichor_"..math.random(1,2)..".png",
131 for x = min.x,max.x do
132 for z = min.z,max.z do
133 if distance({x=x,y=0,z=z},{x=pos.x,y=0,z=pos.z}) <= 10 then
135 if spawn_table[x] and spawn_table[x][z] then
136 y = spawn_table[x][z]
138 if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
139 lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
140 if lightlevel >= 14 or defined_type == "ichor" then
142 particle_table.minpos = vector.new(x-0.5,y,z-0.5)
143 particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
145 null = minetest.add_particlespawner(particle_table)
156 --client runs through spawning weather particles
159 local function update_weather()
160 player_pos = minetest.localplayer:get_pos()
163 current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
164 if current_node and not liquids[current_node.name] then
166 if player_pos.y > -10033 then
168 weather_effects(minetest.localplayer, "snow")
169 elseif rain == true then
170 weather_effects(minetest.localplayer, "rain")
172 --rain blood upwards in the nether
174 if snow == true or rain == true then
175 weather_effects(minetest.localplayer, "ichor")
178 --stop the rain sound effect
179 if rain_sound_handle then
180 minetest.sound_fade(rain_sound_handle, -0.5, 0)
181 rain_sound_handle = nil
184 elseif rain_sound_handle then
185 minetest.sound_fade(rain_sound_handle, -0.5, 0)
186 rain_sound_handle = nil
191 if not rain and rain_sound_handle then
192 minetest.sound_fade(rain_sound_handle, -0.5, 0)
193 rain_sound_handle = nil
195 --do again every half second
196 minetest.after(0.5, function()
201 minetest.register_on_modchannel_message(function(channel_name, sender, message)
202 --receive the initial packet which tells the client which nodes
203 --to spawn weather columns on
204 if sender == "" and channel_name == "weather_nodes" then
205 all_nodes = minetest.deserialize(message)
207 for _,key in pairs(all_nodes) do
211 weather:leave() --leave the channel
213 --receive the weather type
214 if sender == "" and channel_name == "weather_type" then
215 if message == "1" then
218 elseif message == "2" then
229 --We must tell the server that we're ready
230 minetest.after(0,function()
231 weather_intake:send_all("READY")
232 weather_intake:leave()
233 weather_intake = nil --leave the channel
235 --begin weather update