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)
58 rain_sound_handle = nil
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},
73 collisiondetection = true,
74 collision_removal = true,
75 object_collision = false,
77 texture = "raindrop.png^[opacity:80",
79 elseif defined_type == "snow" then
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},
91 collisiondetection = true,
92 collision_removal = true,
93 object_collision = false,
94 texture = "snowflake_"..math.random(1,2)..".png",
96 elseif defined_type == "ichor" then
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},
108 collisiondetection = true,
109 collision_removal = true,
110 object_collision = false,
111 texture = "ichor_"..math.random(1,2)..".png",
116 for x = min.x,max.x do
117 for z = min.z,max.z do
119 if spawn_table[x] and spawn_table[x][z] then
120 y = spawn_table[x][z]
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
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)
129 null = minetest.add_particlespawner(particle_table)
138 --client runs through spawning weather particles
140 local function update_weather()
141 player_pos = minetest.localplayer:get_pos()
145 if player_pos.y > -10033 then
147 weather_effects(minetest.localplayer, "snow")
148 elseif rain == true then
149 weather_effects(minetest.localplayer, "rain")
151 --rain blood upwards in the nether
153 if snow == true or rain == true then
154 weather_effects(minetest.localplayer, "ichor")
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
165 if not rain and rain_sound_handle then
166 minetest.sound_fade(rain_sound_handle, -0.5, 0)
167 rain_sound_handle = nil
169 --do again every half second
170 minetest.after(0.5, function()
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)
181 weather:leave() --leave the channel
183 --receive the weather type
184 if sender == "" and channel_name == "weather_type" then
185 if message == "1" then
188 elseif message == "2" then
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
205 --begin weather update