From 1b4d5d477f39c41961a269f1be91bf16314c5b9a Mon Sep 17 00:00:00 2001 From: theFox6 Date: Sun, 29 Apr 2018 17:22:05 +0200 Subject: [PATCH] added an api for downfall registration --- weather/api.lua | 110 ++++++++++++++++++++++++++++++++++++++++++++ weather/command.lua | 41 +++++++++++++++-- weather/init.lua | 33 ++++--------- weather/rain.lua | 32 ++++--------- weather/snow.lua | 43 ++++------------- 5 files changed, 173 insertions(+), 86 deletions(-) create mode 100644 weather/api.lua diff --git a/weather/api.lua b/weather/api.lua new file mode 100644 index 0000000..c173bbd --- /dev/null +++ b/weather/api.lua @@ -0,0 +1,110 @@ +weather_mod.registered_downfalls = {} + +local function check_modname_prefix(name) + if name:sub(1,1) == ":" then + -- If the name starts with a colon, we can skip the modname prefix + -- mechanism. + return name:sub(2) + else + -- Enforce that the name starts with the correct mod name. + local modname = minetest.get_current_modname() + if modname == nil then + modname="journal" + end + local expected_prefix = modname .. ":" + if name:sub(1, #expected_prefix) ~= expected_prefix then + error("Name " .. name .. " does not follow naming conventions: " .. + "\"" .. expected_prefix .. "\" or \":\" prefix required") + end + + -- Enforce that the name only contains letters, numbers and underscores. + local subname = name:sub(#expected_prefix+1) + if subname:find("[^%w_]") then + error("Name " .. name .. " does not follow naming conventions: " .. + "contains unallowed characters") + end + + return name + end +end + + +function weather_mod.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 + local ndef = table.copy(def) + if not ndef.min_pos then --minimum starting position + ndef.min_pos = {x=-9, y=10, z=-9} + end + if not ndef.maxp then --maximum starting position + ndef.max_pos = {x= 9, y=10, z= 9} + end + if not ndef.falling_speed then --y falling speed + ndef.falling_speed = 10 + end + if not ndef.amount then --number of textures spawned + ndef.amount = 10 + end + if not ndef.exptime then + ndef.exptime = ndef.max_pos.y / (math.sqr(ndef.falling_acceleration) + ndef.falling_speed) + end + if not ndef.texture then + error("no texture given") + end + if not ndef.size then + ndef.size = 25 + end + weather_mod.registered_downfalls[name]=def +end + +minetest.register_globalstep(function() + if weather.type=="none" then + for id,el in pairs(weather_mod.registered_downfalls) do + if math.random(1, 50000) == 1 then + weather.wind = {} + weather.wind.x = math.random(0,10) + weather.wind.y = 0 + weather.wind.z = math.random(0,10) + weather.type = id + end + end + else + if math.random(1, 10000) == 1 then + weather.type = "none" + end + end + local current_downfall + for id,el in pairs(weather_mod.registered_downfalls) do + if weather.type == id then + current_downfall = el + break + end + end + if current_downfall==nil then return end + for _, player in ipairs(minetest.get_connected_players()) do + local ppos = player:getpos() + + -- Make sure player is not in a cave/house... + if minetest.env:get_node_light(ppos, 0.5) ~= 15 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=false, vertical=true, + texture=current_downfall.texture, player=player:get_player_name()}) + end +end) \ No newline at end of file diff --git a/weather/command.lua b/weather/command.lua index 6e715f4..4277ac1 100644 --- a/weather/command.lua +++ b/weather/command.lua @@ -6,10 +6,43 @@ minetest.register_privilege("weather", { -- Set weather minetest.register_chatcommand("setweather", { params = "", - description = "Set weather to rain, snow or none", -- full description + description = "Set weather to a registered type of downfall or show all types when nor parameters are given", -- full description privs = {weather = true}, - func = function(_, param) --name, param - weather.type = param - save_weather() + func = function(name, param) + if param == nil 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 + weather.type = param + save_weather() + end + end +}) + +-- Set weather +minetest.register_chatcommand("setwind", { + params = "", + description = "Set windspeed to the given x,z direction", -- full description + 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 + end + local x,z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)$") + x=tonumber(x) + z=tonumber(z) + if (not x) or (not z) then + x, z = string.match(param, "^%( *([%d.-]+)[, ] *([%d.-]+) *%)$") + end + if x and z then + weather.wind = vector.new(x,0,z) + save_weather() + else + minetest.chat_send_player(name, param.." are not two comma seperated numbers") + end end }) diff --git a/weather/init.lua b/weather/init.lua index e9500cc..414f6c7 100644 --- a/weather/init.lua +++ b/weather/init.lua @@ -5,6 +5,10 @@ assert(minetest.add_particlespawner, "I told you to run the latest GitHub!") +weather_mod={ + modpath=minetest.get_modpath("weather"), +} + save_weather = function () local file = io.open(minetest.get_worldpath().."/weather", "w+") file:write(minetest.serialize(weather)) @@ -24,28 +28,7 @@ end weather = read_weather() -minetest.register_globalstep(function() - if weather.type == "rain" or weather.type == "snow" then - if math.random(1, 10000) == 1 then - weather.type = "none" - save_weather() - end - else - if math.random(1, 50000) == 1 then - weather.wind = math.random(0,10) - weather.type = "rain" - save_weather() - end - if math.random(1, 50000) == 2 then - weather.wind = math.random(0,10) - weather.type = "snow" - save_weather() - end - end -end) - -dofile(minetest.get_modpath("weather").."/rain.lua") -dofile(minetest.get_modpath("weather").."/snow.lua") -dofile(minetest.get_modpath("weather").."/command.lua") - - +dofile(weather_mod.modpath.."/api.lua") +dofile(weather_mod.modpath.."/rain.lua") +dofile(weather_mod.modpath.."/snow.lua") +dofile(weather_mod.modpath.."/command.lua") diff --git a/weather/rain.lua b/weather/rain.lua index 2c4b6a9..abfda27 100644 --- a/weather/rain.lua +++ b/weather/rain.lua @@ -1,24 +1,10 @@ -- Rain -minetest.register_globalstep(function() - if weather.type ~= "rain" then return end - for _, player in ipairs(minetest.get_connected_players()) do - local ppos = player:getpos() - - -- Make sure player is not in a cave/house... - if minetest.env:get_node_light(ppos, 0.5) ~= 15 then return end - - local minp = vector.add(ppos, {x=-9, y=7, z=-9}) - local maxp = vector.add(ppos, {x= 9, y=7, z= 9}) - - local vel = {x=math.random()*weather.wind, y= -4, z=math.random()*weather.wind} - local acc = {x=0, y=-9.81, z=0} - - minetest.add_particlespawner({amount=25, time=0.5, - minpos=minp, maxpos=maxp, - minvel=vel, maxvel=vel, - minacc=acc, maxacc=acc, - minexptime=0.8, maxexptime=0.8, - minsize=25, maxsize=25, - collisiondetection=false, vertical=true, texture="weather_rain.png", player=player:get_player_name()}) - end -end) +weather_mod.register_downfall("weather:rain",{ + min_pos = {x=-9, y=7, z=-9}, + max_pos = {x= 9, y=7, z= 9}, + falling_speed=10, + amount=25, + exptime=0.8, + size=25, + texture="weather_rain.png", +}) diff --git a/weather/snow.lua b/weather/snow.lua index 1642685..5c867bb 100644 --- a/weather/snow.lua +++ b/weather/snow.lua @@ -1,38 +1,13 @@ -- Snow -minetest.register_globalstep(function() - if weather.type ~= "snow" then return end - for _, player in ipairs(minetest.get_connected_players()) do - local ppos = player:getpos() - - -- Make sure player is not in a cave/house... - if minetest.env:get_node_light(ppos, 0.5) ~= 15 then return end - - local minp = vector.add(ppos, {x=-9, y=7, z=-9}) - local maxp = vector.add(ppos, {x= 9, y=7, z= 9}) - - local minp_deep = vector.add(ppos, {x=-10, y=3.2, z=-10}) - local maxp_deep = vector.add(ppos, {x= 10, y=2.6, z= 10}) - - local vel = {x=math.random()*weather.wind, y= -0.5, z=math.random()*weather.wind} - local acc = {x=0, y= -0.5, z=0} - - minetest.add_particlespawner(5, 0.5, - minp, maxp, - vel, vel, - acc, acc, - 5, 5, - 25, 25, - false, "weather_snow.png", player:get_player_name()) - - minetest.add_particlespawner(4, 0.5, - minp_deep, maxp_deep, - vel, vel, - acc, acc, - 4, 4, - 25, 25, - false, "weather_snow.png", player:get_player_name()) - end -end) +weather_mod.register_downfall("weather:snow",{ + min_pos = {x=-9, y=7, z=-9}, + max_pos = {x= 9, y=7, z= 9}, + falling_speed=5, + amount=10, + exptime=5, + size=25, + texture="weather_snow.png" +}) local snow_box = {