From 2875526f02d252a5ef3223a78c106b720bf4da0b Mon Sep 17 00:00:00 2001 From: luk3yx Date: Sun, 26 Jul 2020 22:57:41 +1200 Subject: [PATCH] Initial commit --- README.md | 38 +++++ depends.txt | 2 + init.lua | 272 +++++++++++++++++++++++++++++++++ mod.conf | 3 + sscsm.lua | 74 +++++++++ textures/weather_lite_rain.png | Bin 0 -> 2493 bytes textures/weather_lite_snow.png | Bin 0 -> 569 bytes 7 files changed, 389 insertions(+) create mode 100644 README.md create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 mod.conf create mode 100644 sscsm.lua create mode 100644 textures/weather_lite_rain.png create mode 100644 textures/weather_lite_snow.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..3b3b37f --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +MultiCraft Game mod: weather_lite +================================= + +Authors of source code +---------------------- + +Based on Weather mod + +Copyright (C) Jeija (2013) + +Copyright (C) HybridDog (2015) + +Copyright (C) theFox6 (2018) + +Copyright (C) MultiCraft Development Team (2019-2020) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3.0 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +Authors of textures +------------------- + +TeddyDesTodes (textures) CC-BY-SA 3.0: + +* weather_lite_rain.png +* weather_lite_snow.png diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..2b16848 --- /dev/null +++ b/depends.txt @@ -0,0 +1,2 @@ +default +sscsm? diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..fa3b41e --- /dev/null +++ b/init.lua @@ -0,0 +1,272 @@ +if not minetest.settings:get_bool("enable_weather") then + return +end + +local vmultiply, vadd = vector.multiply, vector.add +local random = math.random +local snow_covers = minetest.settings:get_bool("weather_snow_covers") ~= false + +local weather = { + type = "none", + wind = {x = 0, y = 0, z = 0} +} + + +-- +-- Save and restore weather condition +-- + +local mod_storage = minetest.get_mod_storage() + +do + local saved_weather = minetest.deserialize( + mod_storage:get_string("weather")) + if type(saved_weather) == "table" then + weather = saved_weather + end +end + +minetest.register_on_shutdown(function() + mod_storage:set_string("weather", minetest.serialize( + ({type = weather.type, wind = weather.wind}))) +end) + + +-- +-- Registration of weather types +-- + +weather.registered = {} +function weather.register(id, def) + local ndef = table.copy(def) + weather.registered[id] = ndef +end + +-- Rain +weather.register("rain", { + falling_speed = 5, + amount = 7, + size = 25, + height = 3, + vertical = true, + texture = "weather_lite_rain.png" +}) + +-- Snow +weather.register("snow", { + falling_speed = 2, + amount = 5, + size = 35, + height = 2, + texture = "weather_lite_snow.png" +}) + + +-- +-- Change of weather +-- + +function weather.set(weather_type, wind) + weather.type = weather_type + if wind then + weather.wind = wind + end + if minetest.global_exists("sscsm") then + sscsm.com_send_all("weather_lite:set", { + type = weather_type, + wind = wind + }) + end +end + +local function weather_change() + if weather.type == "none" then + for id, _ in pairs(weather.registered) do + if random(3) == 1 then + weather.set(id, { + x = random(0, 8), + y = 0, + z = random(0, 8) + }) + + break + end + end + minetest.after(random(60, 300), weather_change) + else + weather.set("none") + minetest.after(random(1800, 3600), weather_change) + end +end +minetest.after(random(600, 1800), weather_change) + + +-- +-- Processing players +-- + +local is_valid_pos = minetest.is_valid_pos +if not is_valid_pos then + is_valid_pos = function() return true end +end + +-- This is a separate function to prevent "return" from breaking. +local function process_player(player, current_downfall) + local player_name = player:get_player_name() + if not player:is_player() or (sscsm and sscsm.has_sscsms_enabled(player_name)) then + return + end + + local ppos = vector.round(player:get_pos()) + ppos.y = ppos.y + 1.5 + -- Higher than clouds + local cloud_height = player:get_clouds().height + cloud_height = cloud_height ~= 0 and cloud_height or 120 + if not is_valid_pos(ppos) or ppos.y > cloud_height or ppos.y < -8 then return end + -- Inside liquid + local head_inside = minetest.get_node_or_nil(ppos) + local def_inside = head_inside and minetest.registered_nodes[head_inside.name] + if def_inside and def_inside.drawtype == "liquid" then return end + -- Too dark, probably not under the sky + local light = minetest.get_node_light(ppos, 0.5) + if light and light < 12 then return end + + local wind_pos = vmultiply(weather.wind, -1) + local minp = vadd(vadd(ppos, {x = -8, y = current_downfall.height, z = -8}), wind_pos) + local maxp = vadd(vadd(ppos, {x = 8, y = current_downfall.height, z = 8}), wind_pos) + local vel = {x = weather.wind.x, y = -current_downfall.falling_speed, z = weather.wind.z} + local vert = current_downfall.vertical or false + + minetest.add_particlespawner({ + amount = current_downfall.amount, + time = 0.1, + minpos = minp, + maxpos = maxp, + minvel = vel, + maxvel = vel, + minsize = current_downfall.size, + maxsize = current_downfall.size, + collisiondetection = true, + collision_removal = true, + vertical = vert, + texture = current_downfall.texture, + glow = 1, + playername = player_name + }) +end + +minetest.register_globalstep(function() + local current_downfall = weather.registered[weather.type] + if current_downfall == nil then return end + + for _, player in pairs(minetest.get_connected_players()) do + process_player(player, current_downfall) + end +end) + + +-- +-- Snow will cover the blocks and melt after some time +-- + +if snow_covers then + -- Temp node to start the node timer + minetest.register_node("weather_lite:snow_cover", { + tiles = {"blank.png"}, + drawtype = "signlike", + buildable_to = true, + groups = {not_in_creative_inventory = 1, dig_immediate = 3}, + on_construct = function(pos) + minetest.get_node_timer(pos):start(random(60, 180)) + minetest.swap_node(pos, {name = "default:snow"}) + end + }) + + minetest.override_item("default:snow", { + on_timer = function(pos) + if weather and weather.type and weather.type == "snow" then + return true + end + + minetest.remove_node(pos) + end + }) + + minetest.register_abm({ + label = "Weather: snow cover", + nodenames = {"group:crumbly", "group:snappy", "group:cracky", "group:choppy"}, + neighbors = {"air"}, + interval = 15, + chance = 500, + catch_up = false, + action = function(pos, node) + if weather.type == "snow" then + if pos.y < -8 or pos.y > 120 then return end + if minetest.registered_nodes[node.name].drawtype == "normal" + or minetest.registered_nodes[node.name].drawtype == "allfaces_optional" then + pos.y = pos.y + 1 + if minetest.get_node(pos).name ~= "air" then return end + local light_day = minetest.get_node_light(pos, 0.5) + local light_night = minetest.get_node_light(pos, 0) + if light_day and light_day == 15 + and light_night and light_night < 10 then + minetest.add_node(pos, {name = "weather_lite:snow_cover"}) + end + end + end + end + }) +end + +minetest.register_privilege("weather", { + description = "Allows changing the weather", + give_to_singleplayer = minetest.settings:get_bool("creative_mode") +}) + +minetest.register_chatcommand("weather", { + params = "", + description = "Set weather type", + privs = {weather = true}, + func = function(name, param) + if param and (weather.registered[param] or param == "none") then + weather.set(param) + minetest.chat_send_player(name, "Set weather type: " .. param) + else + local types = "none" + for w, _ in pairs(weather.registered) do + types = types .. ", " .. w + end + minetest.chat_send_player(name, "Avalible weather types: " .. types) + end + end +}) + +if not minetest.global_exists("sscsm") then + return +end + +sscsm.register({ + name = "weather_lite", + file = minetest.get_modpath("weather_lite") .. "/sscsm.lua" +}) + +local liquids +sscsm.register_on_sscsms_loaded(function(name) + if not liquids then + liquids = {} + for node, def in pairs(minetest.registered_nodes) do + if def.drawtype == "liquid" then + liquids[node] = true + end + end + end + + local player = minetest.get_player_by_name(name) + sscsm.com_send(name, "weather_lite:set", { + type = weather.type, + wind = weather.wind, + registered = weather.registered, + cloud_height = player:get_clouds().height, + liquids = liquids + }) +end) diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..3a0f1d9 --- /dev/null +++ b/mod.conf @@ -0,0 +1,3 @@ +name = weather_lite +depends = default +optional_depends = sscsm diff --git a/sscsm.lua b/sscsm.lua new file mode 100644 index 0000000..a029947 --- /dev/null +++ b/sscsm.lua @@ -0,0 +1,74 @@ +local vmultiply, vadd = vector.multiply, vector.add +local random = math.random + +local weather = { + type = "none", + wind = {x = 0, y = 0, z = 0}, + registered = {}, + liquids = {} +} + +local is_valid_pos = minetest.is_valid_pos +if not is_valid_pos then + is_valid_pos = function() return true end +end + +-- +-- Change of weather +-- + +sscsm.register_on_com_receive("weather_lite:set", function(msg) + for k, v in pairs(msg) do + weather[k] = v + end +end) + +-- +-- Processing players +-- + +assert(minetest.localplayer) +sscsm.every(0.09, function() + local current_downfall = weather.registered[weather.type] + if current_downfall == nil then return end + + local ppos = vector.round(minetest.localplayer:get_pos()) + + ppos.y = ppos.y + 1.5 + -- Higher than clouds + local cloud_height = weather.cloud_height + cloud_height = cloud_height ~= 0 and cloud_height or 120 + if not is_valid_pos(ppos) or ppos.y > cloud_height or ppos.y < -8 then return end + + -- Inside liquid + local head_inside = minetest.get_node_or_nil(ppos) + if head_inside and weather.liquids[head_inside.name] then return end + + -- Too dark, probably not under the sky + if minetest.get_node_light then + local light = minetest.get_node_light(ppos, 0.5) + if light and light < 12 then return end + end + + local wind_pos = vmultiply(weather.wind, -1) + local minp = vadd(vadd(ppos, {x = -8, y = current_downfall.height, z = -8}), wind_pos) + local maxp = vadd(vadd(ppos, {x = 8, y = current_downfall.height, z = 8}), wind_pos) + local vel = {x = weather.wind.x, y = -current_downfall.falling_speed, z = weather.wind.z} + local vert = current_downfall.vertical or false + + minetest.add_particlespawner({ + amount = current_downfall.amount, + time = 0.1, + minpos = minp, + maxpos = maxp, + minvel = vel, + maxvel = vel, + minsize = current_downfall.size, + maxsize = current_downfall.size, + collisiondetection = true, + collision_removal = true, + vertical = vert, + texture = current_downfall.texture, + glow = 1 + }) +end) diff --git a/textures/weather_lite_rain.png b/textures/weather_lite_rain.png new file mode 100644 index 0000000000000000000000000000000000000000..3e2a4c6dbc4965201f723c3d920abd0b7c0118fb GIT binary patch literal 2493 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 ABLDyZ literal 0 HcmV?d00001