1 local minetest,name,vector,math,pairs = minetest,minetest.localplayer:get_name(),vector,math,pairs
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")
8 local do_effects = false
11 local weather_update_timer = 0
14 local rain_sound_handle = nil
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)
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
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)
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})
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)
64 minvel = {x=0, y=-20, z=0},
65 maxvel = {x=0, y=-20, z=0},
66 minacc = {x=0, y=0, z=0},
67 maxacc = {x=0, y=0, z=0},
72 collisiondetection = true,
73 collision_removal = true,
74 object_collision = false,
76 texture = "raindrop.png^[opacity:80",
78 elseif defined_type == "snow" then
82 minvel = {x=-0.2, y=-0.2, z=-0.2},
83 maxvel = {x=0.2, y=-0.5, z=0.2},
84 minacc = {x=0, y=0, z=0},
85 maxacc = {x=0, y=0, z=0},
90 collisiondetection = true,
91 collision_removal = true,
92 object_collision = false,
93 texture = "snowflake_"..math.random(1,2)..".png",
95 elseif defined_type == "ichor" then
99 minvel = {x=-0.2, y=0.2, z=-0.2},
100 maxvel = {x=0.2, y=0.5, z=0.2},
101 minacc = {x=0, y=0, z=0},
102 maxacc = {x=0, y=0, z=0},
107 collisiondetection = true,
108 collision_removal = true,
109 object_collision = false,
110 texture = "ichor_"..math.random(1,2)..".png",
115 for x = min.x,max.x do
116 for z = min.z,max.z do
118 if spawn_table[x] and spawn_table[x][z] then
119 y = spawn_table[x][z]
121 if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
122 lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
123 if lightlevel >= 14 or defined_type == "ichor" then
125 particle_table.minpos = vector.new(x-0.5,y,z-0.5)
126 particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
128 null = minetest.add_particlespawner(particle_table)
137 --client runs through spawning weather particles
139 local function update_weather()
140 player_pos = minetest.localplayer:get_pos()
144 if player_pos.y > -10033 then
146 weather_effects(minetest.localplayer, "snow")
147 elseif rain == true then
148 weather_effects(minetest.localplayer, "rain")
150 --rain blood upwards in the nether
152 if snow == true or rain == true then
153 weather_effects(minetest.localplayer, "ichor")
156 --stop the rain sound effect
157 if rain_sound_handle then
158 minetest.sound_fade(rain_sound_handle, -0.5, 0)
159 rain_sound_handle = nil
164 if not rain and rain_sound_handle then
165 minetest.sound_fade(rain_sound_handle, -0.5, 0)
166 rain_sound_handle = nil
168 --do again every half second
169 minetest.after(0.5, function()
174 minetest.register_on_modchannel_message(function(channel_name, sender, message)
175 --receive the initial packet which tells the client which nodes
176 --to spawn weather columns on
177 if sender == "" and channel_name == "weather_nodes" then
178 all_nodes = minetest.deserialize(message)
180 weather:leave() --leave the channel
182 --receive the weather type
183 if sender == "" and channel_name == "weather_type" then
184 if message == "1" then
187 elseif message == "2" then
198 --We must tell the server that we're ready
199 minetest.after(0,function()
200 weather_intake:send_all("READY")
201 weather_intake:leave()
202 weather_intake = nil --leave the channel
204 --begin weather update