From 63a27f5fcc43f00a3d197dbd6703236e7f80f4c0 Mon Sep 17 00:00:00 2001 From: theFox6 Date: Wed, 15 Apr 2020 17:21:53 +0200 Subject: [PATCH] redesign the api to have player individual weather --- .luacheckrc | 1 - weather/api.lua | 162 ++++++++++++++++++++++++++++---------------- weather/command.lua | 56 ++++++++------- weather/init.lua | 42 ++---------- weather/rain.lua | 4 +- weather/sand.lua | 2 +- weather/snow.lua | 48 +++++++++---- 7 files changed, 178 insertions(+), 137 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 784a91b..f20d260 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -21,7 +21,6 @@ read_globals = { globals = { "weather", - "weather_mod" } exclude_files = {"weather/development/"} diff --git a/weather/api.lua b/weather/api.lua index 675c61a..55a7bd4 100644 --- a/weather/api.lua +++ b/weather/api.lua @@ -1,4 +1,6 @@ -weather_mod.registered_downfalls = {} +local storage = minetest.get_mod_storage() + +weather.registered_downfalls = {} local function check_modname_prefix(name) if name:sub(1,1) == ":" then @@ -66,10 +68,10 @@ local default_damage = { time = 100 } -function weather_mod.register_downfall(id,def) +function weather.register_downfall(id,def) local name = check_modname_prefix(id) if name == "none" then error("\"none\" means none, thanks") end - if weather_mod.registered_downfalls[name]~=nil then error(name.." is already registered") end + if weather.registered_downfalls[name]~=nil then error(name.." is already registered") end local ndef = table.copy(def) --what the downfall looks like if not ndef.texture then @@ -78,26 +80,26 @@ function weather_mod.register_downfall(id,def) set_defaults(ndef,default_downfall) --when to delete the particles if not ndef.exptime then - ndef.exptime = ndef.max_pos.y / (math.sqrt(ndef.falling_acceleration) + ndef.falling_speed) + ndef.exptime = ndef.max_pos.y / ndef.falling_speed end if ndef.damage_player then set_defaults(ndef.damage_player,default_damage) end --actually register the downfall - weather_mod.registered_downfalls[name]=ndef + weather.registered_downfalls[name]=ndef end -function weather_mod.disable_downfall(id,disable) +function weather.disable_downfall(id,disable) local state = disable if disable == nil then state = true end - weather_mod.registered_downfalls[id].disabled = state + weather.registered_downfalls[id].disabled = state end +--[[ if minetest.get_modpath("lightning") then lightning.auto = false - --rawset(lightning,"auto",false) end function weather_mod.handle_lightning(current_weather) @@ -110,10 +112,47 @@ function weather_mod.handle_lightning(current_weather) minetest.after(time, lightning.strike) end end +]] local do_raycasts = minetest.is_yes(minetest.settings:get_bool('raycast_hitcheck')) local damage_steps = 0 +local function get_player_meta(player) + local p = player + if type(player) == "string" then + p = minetest.get_player_by_name(player) + end + return p:get_meta() +end + +function weather.get_weather(player) + local meta = get_player_meta(player) + return meta:get_string("weather_type") +end + +function weather.set_weather(player,type) + local meta = get_player_meta(player) + meta:set_string("weather_type",type) +end + +function weather.get_wind() + return { + x = storage:get_float("wind_x"), + y = 0, + z = storage:get_float("wind_z") + } +end + +function weather.set_wind(x,z) + if type(x) == "table" then + storage:set_float("wind_x",x.x) + storage:set_float("wind_z",x.z) + else + storage:set_float("wind_x",x) + storage:set_float("wind_z",z) + end +end + local function handle_damage(damage,player, downfall_origin) if not damage then return end damage_steps = damage_steps +1 @@ -143,64 +182,67 @@ local function handle_damage(damage,player, downfall_origin) end end -local function weather_step() - local current_downfall = weather_mod.registered_downfalls[weather.type] - if current_downfall==nil then return end - for _, player in ipairs(minetest.get_connected_players()) do - local ppos = player:getpos() +local function weather_step(player,meta) + local weather_type = meta:get_string("weather_type") + if weather_type and weather_type ~= "" and weather_type ~= "none" then + local current_downfall = weather.registered_downfalls[weather_type] + if current_downfall then + local ppos = player:getpos() + + if ppos.y > 120 then return end + + local wind = weather.get_wind() + local wind_pos = vector.multiply(wind,-1) - if ppos.y > 120 then return end - - local wind_pos = vector.multiply(weather.wind,-1) - - local minp = vector.add(vector.add(ppos, current_downfall.min_pos),wind_pos) - local maxp = vector.add(vector.add(ppos, current_downfall.max_pos),wind_pos) - - local vel = {x=weather.wind.x,y=-current_downfall.falling_speed,z=weather.wind.z} - local acc = {x=0, y=0, z=0} - - local exp = current_downfall.exptime - - minetest.add_particlespawner({ - amount=current_downfall.amount, time=0.5, - minpos=minp, maxpos=maxp, - minvel=vel, maxvel=vel, - minacc=acc, maxacc=acc, - minexptime=exp, maxexptime=exp, - minsize=current_downfall.size, maxsize=current_downfall.size, - collisiondetection=true, collision_removal=true, - vertical=true, - texture=current_downfall.texture, player=player:get_player_name() - }) - - local downfall_origin = vector.divide(vector.add(minp,maxp),2) - handle_damage(current_downfall.damage_player,player,downfall_origin) + local minp = vector.add(vector.add(ppos, current_downfall.min_pos),wind_pos) + local maxp = vector.add(vector.add(ppos, current_downfall.max_pos),wind_pos) + + local vel = {x=wind.x,y=-current_downfall.falling_speed,z=wind.z} + local acc = {x=0, y=0, z=0} + + local exp = current_downfall.exptime + + minetest.add_particlespawner({ + amount=current_downfall.amount, time=0.5, + minpos=minp, maxpos=maxp, + minvel=vel, maxvel=vel, + minacc=acc, maxacc=acc, + minexptime=exp, maxexptime=exp, + minsize=current_downfall.size, maxsize=current_downfall.size, + collisiondetection=true, collision_removal=true, + vertical=true, + texture=current_downfall.texture, playername=player:get_player_name() + }) + + local downfall_origin = vector.divide(vector.add(minp,maxp),2) + handle_damage(current_downfall.damage_player,player,downfall_origin) + end end end minetest.register_globalstep(function() - if math.random(1, 10000) == 1 then - weather.type = "none" - if minetest.get_modpath("lightning") then - lightning.auto = false - --rawset(lightning,"auto",false) - end - else - for id,w in pairs(weather_mod.registered_downfalls) do - if math.random(1, 50000) == 1 then - weather.wind = { - x = math.random(0,10), - y = 0, - z = math.random(0,10) - } - if (not w.disabled) and vector.length(weather.wind) >= w.min_wind then - weather.type = id - weather_mod.handle_lightning(w) - break + if math.random(1, 50000) == 1 then + weather.set_wind(math.random(0,10),math.random(0,10)) + end + for _, player in ipairs(minetest.get_connected_players()) do + local meta = get_player_meta(player) + if math.random(1, 10000) == 1 then + meta:set_string("weather_type","none") + --[[if minetest.get_modpath("lightning") then + lightning.auto = false + end]] + else + for id,w in pairs(weather.registered_downfalls) do + if math.random(1, 50000) == 1 then + if (not w.disabled) and vector.length(weather.get_wind()) >= w.min_wind then + meta:set_string("weather_type",id) + --weather_mod.handle_lightning(w) + break + end end end end - end - weather_step() -end) \ No newline at end of file + weather_step(player,meta) + end +end) diff --git a/weather/command.lua b/weather/command.lua index 2a49168..8205839 100644 --- a/weather/command.lua +++ b/weather/command.lua @@ -3,29 +3,35 @@ minetest.register_privilege("weather", { give_to_singleplayer = false }) +local function list_types() + local types="none" + for i,_ in pairs(weather.registered_downfalls) do + types=types..", "..i + end +end + -- Set weather minetest.register_chatcommand("setweather", { - params = "", - description = "Set weather to a registered type of downfall\ - show all types when no parameters are given", -- full description - privs = {weather = true}, - func = function(name, param) - if param == nil or param == "" or param == "?" then - local types="none" - for i,_ in pairs(weather_mod.registered_downfalls) do - types=types..", "..i - end - minetest.chat_send_player(name, "avalible weather types: "..types) - else - if weather_mod.registered_downfalls[param] == nil and not param == "none" then - minetest.chat_send_player(name, "This type of weather is not registered.\n".. - "To list all types of weather run the command without parameters.") - else - weather.type = param - weather_mod.handle_lightning() - end - end - end + params = "", + description = "Set weather to a registered type of downfall\ + show all types when no parameters are given", -- full description + privs = {weather = true}, + func = function(name, param) + if param == nil or param == "" or param == "?" then + return false, "registered weather types: "..list_types() + end + local w = weather.registered_downfalls[param] + if (not w) and param ~= "none" then + return false, "This type of weather is not registered.\n".. + "registered types: "..list_types() + end + if w.disabled then + minetest.chat_send_player(name,param.." is disabled.") + end + weather.set_weather(name,param) + --weather_mod.handle_lightning() + return true + end }) -- Set wind @@ -35,8 +41,7 @@ minetest.register_chatcommand("setwind", { privs = {weather = true}, func = function(name, param) if param==nil or param=="" then - minetest.chat_send_player(name, "please provide two comma seperated numbers") - return + return false,"please provide two comma seperated numbers" end local x,z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)$") x=tonumber(x) @@ -45,9 +50,10 @@ minetest.register_chatcommand("setwind", { x, z = string.match(param, "^%( *([%d.-]+)[, ] *([%d.-]+) *%)$") end if x and z then - weather.wind = vector.new(x,0,z) + weather.set_wind(x,z) + return true else - minetest.chat_send_player(name, param.." are not two comma seperated numbers") + return false,param.." are not two comma seperated numbers" end end }) diff --git a/weather/init.lua b/weather/init.lua index bf62d59..9090056 100644 --- a/weather/init.lua +++ b/weather/init.lua @@ -1,39 +1,11 @@ --- Weather: --- * rain --- * snow --- * wind - assert(minetest.add_particlespawner, "Weather doesn't work with this really old minetest.") -weather_mod={ - modpath=minetest.get_modpath("weather"), +weather = { + modpath = minetest.get_modpath("weather"), } -weather = (function() - local file_name = minetest.get_worldpath() .. "/weather" - - minetest.register_on_shutdown(function() - local file = io.open(file_name, "w") - file:write(minetest.serialize(weather)) - file:close() - end) - - local file = io.open(file_name, "r") - if file ~= nil then - local readweather = minetest.deserialize(file:read("*a")) - file:close() - if type(readweather)~="table" then - return {type = "none", wind = 0} - end - return readweather - end - return {type = "none", wind = vector.new(0,0,0)} -end) () - -dofile(weather_mod.modpath.."/api.lua") -dofile(weather_mod.modpath.."/rain.lua") -dofile(weather_mod.modpath.."/sand.lua") -dofile(weather_mod.modpath.."/snow.lua") -dofile(weather_mod.modpath.."/command.lua") - -weather_mod.handle_lightning() +dofile(weather.modpath.."/api.lua") +dofile(weather.modpath.."/rain.lua") +dofile(weather.modpath.."/sand.lua") +dofile(weather.modpath.."/snow.lua") +dofile(weather.modpath.."/command.lua") diff --git a/weather/rain.lua b/weather/rain.lua index 65dcdc1..187ece9 100644 --- a/weather/rain.lua +++ b/weather/rain.lua @@ -1,5 +1,5 @@ -- Rain -weather_mod.register_downfall("weather:rain",{ +weather.register_downfall("weather:rain",{ min_pos = {x=-15, y=7, z=-15}, max_pos = {x= 15, y=7, z= 15}, falling_speed=10, @@ -10,7 +10,7 @@ weather_mod.register_downfall("weather:rain",{ enable_lightning=true, }) -weather_mod.register_downfall("weather:storm",{ +weather.register_downfall("weather:storm",{ min_pos = {x = -15, y = 7, z = -15}, max_pos = {x = 15, y = 7, z = 15}, falling_speed = 10, diff --git a/weather/sand.lua b/weather/sand.lua index e640676..43259a6 100644 --- a/weather/sand.lua +++ b/weather/sand.lua @@ -1,4 +1,4 @@ -weather_mod.register_downfall("weather:sandstorm",{ +weather.register_downfall("weather:sandstorm",{ min_pos = {x=-20, y=0, z=-20}, max_pos = {x= 20, y=2, z= 20}, falling_speed=-1, diff --git a/weather/snow.lua b/weather/snow.lua index 2abe5d2..31b8e19 100644 --- a/weather/snow.lua +++ b/weather/snow.lua @@ -1,5 +1,5 @@ -- Snow -weather_mod.register_downfall("weather:snow",{ +weather.register_downfall("weather:snow",{ min_pos = {x=-15, y=7, z=-15}, max_pos = {x= 15, y=7, z= 15}, falling_speed=5, @@ -9,7 +9,7 @@ weather_mod.register_downfall("weather:snow",{ texture="weather_snow.png", }) -weather_mod.register_downfall("weather:hail",{ +weather.register_downfall("weather:hail",{ min_pos = {x=-15, y=7, z=-15}, max_pos = {x= 15, y=7, z= 15}, falling_speed=25, @@ -37,6 +37,25 @@ minetest.register_node("weather:snow_cover", { drop = {} }) +local function get_nearest_player(pos,range_distance) + local player, min_distance = nil, range_distance + local position = pos + + local all_objects = minetest.get_objects_inside_radius(position, range_distance) + for _, object in pairs(all_objects) do + if object:is_player() then + local player_position = object:getpos() + local distance = vector.distance(position, player_position) + + if distance < min_distance then + min_distance = distance + player = object + end + end + end + return player +end + -- Snow cover ABM when snow_covers_abm setting is set to `true` if minetest.is_yes(minetest.settings:get_bool('snow_covers_abm')) then minetest.log('action', '[weather] Loaded fast computer ABM (snow covers when weather:snow is set)') @@ -46,16 +65,19 @@ if minetest.is_yes(minetest.settings:get_bool('snow_covers_abm')) then interval = 10.0, chance = 80, action = function (pos, node) - if weather.type == "weather:snow" then - if minetest.registered_nodes[node.name].drawtype == "normal" - or minetest.registered_nodes[node.name].drawtype == "allfaces_optional" then - local np = vector.add(pos, {x=0, y=1, z=0}) - if minetest.env:get_node_light(np, 0.5) == 15 - and minetest.env:get_node(np).name == "air" then - minetest.env:add_node(np, {name="weather:snow_cover"}) - end - end - end - end + local player = get_nearest_player(pos,50) + if not player then return end + if weather.get_type(player) ~= "weather:snow" then + return + end + if minetest.registered_nodes[node.name].drawtype == "normal" + or minetest.registered_nodes[node.name].drawtype == "allfaces_optional" then + local np = vector.add(pos, {x=0, y=1, z=0}) + if minetest.env:get_node_light(np, 0.5) == 15 + and minetest.env:get_node(np).name == "air" then + minetest.env:add_node(np, {name="weather:snow_cover"}) + end + end + end }) end