238 lines
5.9 KiB
Lua
238 lines
5.9 KiB
Lua
local
|
|
minetest,name,vector,math,pairs
|
|
=
|
|
minetest,minetest.localplayer:get_name(),vector,math,pairs
|
|
|
|
local weather_intake = minetest.mod_channel_join("weather_intake")
|
|
local weather = minetest.mod_channel_join("weather_nodes")
|
|
local weather_type = minetest.mod_channel_join("weather_type")
|
|
|
|
local all_nodes = {}
|
|
local do_effects = false
|
|
local snow = false
|
|
local rain = false
|
|
local weather_update_timer = 0
|
|
local id_table = {}
|
|
|
|
local rain_sound_handle = nil
|
|
|
|
local liquids = {
|
|
["main:water"] = true,
|
|
["main:waterflow"] = true,
|
|
["main:lava"] = true,
|
|
["main:lavaflow"] = true,
|
|
["nether:lava"] = true,
|
|
["nether:lavaflow"] = true,
|
|
}
|
|
|
|
|
|
local y
|
|
local pos
|
|
local radius = 10
|
|
local particle_table
|
|
local area
|
|
local min
|
|
local max
|
|
local area_index
|
|
local spawn_table
|
|
local lightlevel
|
|
local null
|
|
local curr_light
|
|
local distance = vector.distance
|
|
local current_node
|
|
local weather_effects = function(player,defined_type)
|
|
pos = vector.round(player:get_pos())
|
|
area = vector.new(10,10,10)
|
|
min = vector.subtract(pos, area)
|
|
max = vector.add(pos, area)
|
|
area_index = minetest.find_nodes_in_area_under_air(min, max, all_nodes)
|
|
spawn_table = {}
|
|
--find the highest y value
|
|
for _,index in pairs(area_index) do
|
|
if not spawn_table[index.x] then spawn_table[index.x] = {} end
|
|
if not spawn_table[index.x][index.z] then
|
|
spawn_table[index.x][index.z] = index.y
|
|
elseif spawn_table[index.x][index.z] < index.y then
|
|
spawn_table[index.x][index.z] = index.y
|
|
end
|
|
end
|
|
|
|
if defined_type == "rain" then
|
|
curr_light = minetest.get_node_light(minetest.camera:get_pos(),0.5)
|
|
--rain sound effect
|
|
if curr_light then
|
|
current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
|
|
|
|
if curr_light >= 15 and current_node and not liquids[current_node.name] then
|
|
if not rain_sound_handle then
|
|
rain_sound_handle = minetest.sound_play("rain", {loop=true,gain=0})
|
|
end
|
|
minetest.sound_fade(rain_sound_handle, 0.5, 1)
|
|
elseif rain_sound_handle then
|
|
minetest.sound_fade(rain_sound_handle, -0.5, 0)
|
|
rain_sound_handle = nil
|
|
end
|
|
end
|
|
|
|
particle_table = {
|
|
amount = 3,
|
|
time = 0.5,
|
|
minvel = {x=0, y=-30, z=0},
|
|
maxvel = {x=0, y=-30, z=0},
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 0.5,
|
|
maxexptime = 0.5,
|
|
minsize = 4,
|
|
maxsize = 4,
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
object_collision = false,
|
|
vertical = true,
|
|
texture = "raindrop.png^[opacity:80",
|
|
}
|
|
elseif defined_type == "snow" then
|
|
particle_table = {
|
|
amount = 1,
|
|
time = 0.5,
|
|
minvel = {x=-0.2, y=-0.2, z=-0.2},
|
|
maxvel = {x=0.2, y=-0.5, z=0.2},
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 1,
|
|
maxexptime = 1,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
object_collision = false,
|
|
texture = "snowflake_"..math.random(1,2)..".png",
|
|
}
|
|
elseif defined_type == "ichor" then
|
|
particle_table = {
|
|
amount = 1,
|
|
time = 0.5,
|
|
minvel = {x=-0.2, y=0.2, z=-0.2},
|
|
maxvel = {x=0.2, y=0.5, z=0.2},
|
|
minacc = {x=0, y=0, z=0},
|
|
maxacc = {x=0, y=0, z=0},
|
|
minexptime = 1,
|
|
maxexptime = 1,
|
|
minsize = 1,
|
|
maxsize = 1,
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
object_collision = false,
|
|
texture = "ichor_"..math.random(1,2)..".png",
|
|
}
|
|
end
|
|
|
|
|
|
for x = min.x,max.x do
|
|
for z = min.z,max.z do
|
|
if distance({x=x,y=0,z=z},{x=pos.x,y=0,z=pos.z}) <= 10 then
|
|
y = pos.y - 5
|
|
if spawn_table[x] and spawn_table[x][z] then
|
|
y = spawn_table[x][z]
|
|
end
|
|
if minetest.get_node_or_nil(vector.new(x,y+1,z)) ~= nil then
|
|
lightlevel = minetest.get_node_light(vector.new(x,y+1,z), 0.5)
|
|
if lightlevel >= 14 or defined_type == "ichor" then
|
|
|
|
particle_table.minpos = vector.new(x-0.5,y,z-0.5)
|
|
particle_table.maxpos = vector.new(x+0.5,y+20,z+0.5)
|
|
|
|
null = minetest.add_particlespawner(particle_table)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
--client runs through spawning weather particles
|
|
local player_pos
|
|
local current_node
|
|
local function update_weather()
|
|
player_pos = minetest.localplayer:get_pos()
|
|
if do_effects then
|
|
if snow or rain then
|
|
current_node = minetest.get_node_or_nil(minetest.camera:get_pos())
|
|
if current_node and not liquids[current_node.name] then
|
|
--do normal weather
|
|
if player_pos.y > -10033 then
|
|
if snow == true then
|
|
weather_effects(minetest.localplayer, "snow")
|
|
elseif rain == true then
|
|
weather_effects(minetest.localplayer, "rain")
|
|
end
|
|
--rain blood upwards in the nether
|
|
else
|
|
if snow == true or rain == true then
|
|
weather_effects(minetest.localplayer, "ichor")
|
|
end
|
|
|
|
--stop the rain sound effect
|
|
if rain_sound_handle then
|
|
minetest.sound_fade(rain_sound_handle, -0.5, 0)
|
|
rain_sound_handle = nil
|
|
end
|
|
end
|
|
elseif rain_sound_handle then
|
|
minetest.sound_fade(rain_sound_handle, -0.5, 0)
|
|
rain_sound_handle = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
if not rain and rain_sound_handle then
|
|
minetest.sound_fade(rain_sound_handle, -0.5, 0)
|
|
rain_sound_handle = nil
|
|
end
|
|
--do again every half second
|
|
minetest.after(0.5, function()
|
|
update_weather()
|
|
end)
|
|
end
|
|
|
|
minetest.register_on_modchannel_message(function(channel_name, sender, message)
|
|
--receive the initial packet which tells the client which nodes
|
|
--to spawn weather columns on
|
|
if sender == "" and channel_name == "weather_nodes" then
|
|
all_nodes = minetest.deserialize(message)
|
|
nodes = {}
|
|
for _,key in pairs(all_nodes) do
|
|
nodes[key] = true
|
|
end
|
|
do_effects = true
|
|
weather:leave() --leave the channel
|
|
end
|
|
--receive the weather type
|
|
if sender == "" and channel_name == "weather_type" then
|
|
if message == "1" then
|
|
rain = false
|
|
snow = true
|
|
elseif message == "2" then
|
|
rain = true
|
|
snow = false
|
|
else
|
|
rain = false
|
|
snow = false
|
|
end
|
|
end
|
|
end)
|
|
|
|
|
|
--We must tell the server that we're ready
|
|
minetest.after(0,function()
|
|
weather_intake:send_all("READY")
|
|
weather_intake:leave()
|
|
weather_intake = nil --leave the channel
|
|
|
|
--begin weather update
|
|
update_weather()
|
|
end)
|