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)
50 if curr_light >= 15 then
51 if not rain_sound_handle then
52 rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
54 minetest.sound_fade(rain_sound_handle, 0.5, 1)
55 elseif curr_light < 15 and rain_sound_handle then
56 minetest.sound_fade(rain_sound_handle, -0.5, 0)
62 minvel = {x=0, y=-20, z=0},
63 maxvel = {x=0, y=-20, z=0},
64 minacc = {x=0, y=0, z=0},
65 maxacc = {x=0, y=0, z=0},
70 collisiondetection = true,
71 collision_removal = true,
72 object_collision = false,
74 texture = "raindrop.png^[opacity:80",
76 elseif defined_type == "snow" then
80 minvel = {x=-0.2, y=-0.2, z=-0.2},
81 maxvel = {x=0.2, y=-0.5, z=0.2},
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,
91 texture = "snowflake_"..math.random(1,2)..".png",
93 elseif defined_type == "ichor" then
97 minvel = {x=-0.2, y=0.2, z=-0.2},
98 maxvel = {x=0.2, y=0.5, z=0.2},
99 minacc = {x=0, y=0, z=0},
100 maxacc = {x=0, y=0, z=0},
105 collisiondetection = true,
106 collision_removal = true,
107 object_collision = false,
108 texture = "ichor_"..math.random(1,2)..".png",
113 for x = min.x,max.x do
114 for z = min.z,max.z do
116 if spawn_table[x] and spawn_table[x][z] then
117 y = spawn_table[x][z]
119 if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
120 lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
121 if lightlevel >= 14 or defined_type == "ichor" then
123 particle_table.minpos = vector.new(x-0.5,y,z-0.5)
124 particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
126 null = minetest.add_particlespawner(particle_table)
135 --client runs through spawning weather particles
137 local function update_weather()
138 player_pos = minetest.localplayer:get_pos()
142 if player_pos.y > -10033 then
144 weather_effects(minetest.localplayer, "snow")
145 elseif rain == true then
146 weather_effects(minetest.localplayer, "rain")
148 --rain blood upwards in the nether
150 if snow == true or rain == true then
151 weather_effects(minetest.localplayer, "ichor")
154 --stop the rain sound effect
155 if rain_sound_handle then
156 minetest.sound_fade(rain_sound_handle, -0.5, 0)
157 rain_sound_handle = nil
162 if not rain and rain_sound_handle then
163 minetest.sound_fade(rain_sound_handle, -0.5, 0)
164 rain_sound_handle = nil
166 --do again every half second
167 minetest.after(0.5, function()
172 minetest.register_on_modchannel_message(function(channel_name, sender, message)
173 --receive the initial packet which tells the client which nodes
174 --to spawn weather columns on
175 if sender == "" and channel_name == "weather_nodes" then
176 all_nodes = minetest.deserialize(message)
178 weather:leave() --leave the channel
180 --receive the weather type
181 if sender == "" and channel_name == "weather_type" then
182 if message == "1" then
185 elseif message == "2" then
196 --We must tell the server that we're ready
197 minetest.after(0,function()
198 weather_intake:send_all("READY")
199 weather_intake:leave()
200 weather_intake = nil --leave the channel
202 --begin weather update