Merge branch 'master' into day_night_ratio

Wuzzy 2017-11-22 01:41:23 +01:00
commit bccc7fa957
158 changed files with 2394 additions and 2049 deletions

@ -109,6 +109,7 @@ These groups are used mostly for informational purposes
* `flower_pot=2`: Flower pot with a plant or flower * `flower_pot=2`: Flower pot with a plant or flower
* `flower=1`: Flower * `flower=1`: Flower
* `place_flowerlike=1`: Node has placement rules like that of a flower * `place_flowerlike=1`: Node has placement rules like that of a flower
* `place_flowerlike=2`: Node has placement rules like tall grass
* `cake`: Cake (rating = slices left) * `cake`: Cake (rating = slices left)
* `book=1`: Book * `book=1`: Book
* `pane=1`: Node is a “pane”-like node glass pane or iron bars * `pane=1`: Node is a “pane”-like node glass pane or iron bars

@ -2,7 +2,7 @@
An unofficial Minecraft-like game for Minetest. Forked from MineClone by daredevils. An unofficial Minecraft-like game for Minetest. Forked from MineClone by daredevils.
Developed by Wuzzy and contributors. Not developed or endorsed by Mojang AB. Developed by Wuzzy and contributors. Not developed or endorsed by Mojang AB.
Version: 0.29.2 Version: 0.30.0
### Gameplay ### Gameplay
You start in a randomly-generated world made entirely of cubes. You can explore You start in a randomly-generated world made entirely of cubes. You can explore
@ -149,6 +149,7 @@ Bonus features (not found in Minecraft 1.11):
* Built-in crafting guide which shows you crafting and smelting recipes * Built-in crafting guide which shows you crafting and smelting recipes
* In-game help system containing extensive help about gameplay basics, blocks, items and more * In-game help system containing extensive help about gameplay basics, blocks, items and more
* Temporary crafting recipes. They only exist to make some otherwise unaccessible items available when you're not in creative mode. These recipes will be removed as development goes on an more features become available * Temporary crafting recipes. They only exist to make some otherwise unaccessible items available when you're not in creative mode. These recipes will be removed as development goes on an more features become available
* Saplings in chests (only in mapgen v6, because only 3 out of 6 tree species grow here)
Technical differences from Minecraft: Technical differences from Minecraft:
@ -161,7 +162,7 @@ Technical differences from Minecraft:
* Different textures (Pixel Perfection) * Different textures (Pixel Perfection)
* Different sounds (various sources) * Different sounds (various sources)
* Different engine (Minetest) * Different engine (Minetest)
* Free software (“free” as in freedom *and* free beer) * Free software (“free” as in freedom)
## Reporting bugs ## Reporting bugs
Please report all bugs and missing Minecraft features here: Please report all bugs and missing Minecraft features here:

@ -72,6 +72,8 @@ end
mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border mcl_vars.mg_end_min = -27073 -- Carefully chosen to be at a mapchunk border
mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit mcl_vars.mg_end_max_official = mcl_vars.mg_end_min + minecraft_height_limit
mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000 mcl_vars.mg_end_max = mcl_vars.mg_overworld_min - 2000
mcl_vars.mg_end_platform_pos = { x = 100, y = mcl_vars.mg_end_min + 80, z = 0 }
-- Realm barrier used to safely separate the End from the void below the Overworld -- Realm barrier used to safely separate the End from the void below the Overworld
mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max mcl_vars.mg_realm_barrier_overworld_end_max = mcl_vars.mg_end_max
mcl_vars.mg_realm_barrier_overworld_end_min = mcl_vars.mg_end_max - 11 mcl_vars.mg_realm_barrier_overworld_end_min = mcl_vars.mg_end_max - 11

@ -134,3 +134,10 @@ function mcl_sounds.node_sound_water_defaults(table)
mcl_sounds.node_sound_defaults(table) mcl_sounds.node_sound_defaults(table)
return table return table
end end
-- Player death sound
minetest.register_on_dieplayer(function(player)
-- TODO: Add separate death sound
minetest.sound_play({name="player_damage", gain = 1.0}, {pos=player:get_pos(), max_hear_distance=16})
end)

@ -411,10 +411,12 @@ end
mcl_util.clock_works = mcl_util.compass_works mcl_util.clock_works = mcl_util.compass_works
-- Returns a on_place function for plants -- Returns a on_place function for plants
-- * condition: function(pos, node) -- * condition: function(pos, node, itemstack)
-- * A function which is called by the on_place function to check if the node can be placed -- * A function which is called by the on_place function to check if the node can be placed
-- * Must return true, if placement is allowed, false otherwise -- * Must return true, if placement is allowed, false otherwise.
-- * If it returns a string, placement is allowed, but will place this itemstring as a node instead
-- * pos, node: Position and node table of plant node -- * pos, node: Position and node table of plant node
-- * itemstack: Itemstack to place
function mcl_util.generate_on_place_plant_function(condition) function mcl_util.generate_on_place_plant_function(condition)
return function(itemstack, placer, pointed_thing) return function(itemstack, placer, pointed_thing)
if pointed_thing.type ~= "node" then if pointed_thing.type ~= "node" then
@ -445,9 +447,10 @@ function mcl_util.generate_on_place_plant_function(condition)
end end
-- Check placement rules -- Check placement rules
if (condition(place_pos, node) == true) then local result, param2 = condition(place_pos, node, itemstack)
if result == true then
local idef = itemstack:get_definition() local idef = itemstack:get_definition()
local new_itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing) local new_itemstack, success = minetest.item_place_node(itemstack, placer, pointed_thing, param2)
if success then if success then
if idef.sounds and idef.sounds.place then if idef.sounds and idef.sounds.place then

@ -241,6 +241,19 @@ mobs_mc.enderman_takable = {
"nether:rack", "nether:rack",
} }
--[[ Table of nodes to replace when an enderman takes it.
If the enderman takes an indexed node, it the enderman will get the item in the value.
Table indexes: Original node, taken by enderman.
Table values: The item which the enderman *actually* gets
Example:
mobs_mc.enderman_node_replace = {
["default:dirt_with_dry_grass"] = "default_dirt_with_grass",
}
-- This means, if the enderman takes a dirt with dry grass, he will get a dirt with grass
-- on his hand instead.
]]
mobs_mc.enderman_replace_on_take = {} -- no replacements by default
-- A table which can be used to override block textures of blocks carried by endermen. -- A table which can be used to override block textures of blocks carried by endermen.
-- Only works for cube-shaped nodes and nodeboxes. -- Only works for cube-shaped nodes and nodeboxes.
-- Key: itemstrings of the blocks to replace -- Key: itemstrings of the blocks to replace
@ -307,6 +320,9 @@ if minetest.get_modpath("mobs_mc_gameconfig") and mobs_mc.override then
if mobs_mc.override.enderman_takable then if mobs_mc.override.enderman_takable then
mobs_mc.enderman_takable = mobs_mc.override.enderman_takable mobs_mc.enderman_takable = mobs_mc.override.enderman_takable
end end
if mobs_mc.override.enderman_replace_on_take then
mobs_mc.enderman_replace_on_take = mobs_mc.override.enderman_replace_on_take
end
if mobs_mc.enderman_block_texture_overrides then if mobs_mc.enderman_block_texture_overrides then
mobs_mc.enderman_block_texture_overrides = mobs_mc.override.enderman_block_texture_overrides mobs_mc.enderman_block_texture_overrides = mobs_mc.override.enderman_block_texture_overrides
end end

@ -213,7 +213,11 @@ mobs:register_mob("mobs_mc:enderman", {
local node = minetest.get_node(take_pos) local node = minetest.get_node(take_pos)
local dug = minetest.dig_node(take_pos) local dug = minetest.dig_node(take_pos)
if dug then if dug then
self._taken_node = node.name if mobs_mc.enderman_replace_on_take[node.name] then
self._taken_node = mobs_mc.enderman_replace_on_take[node.name]
else
self._taken_node = node.name
end
local def = minetest.registered_nodes[self._taken_node] local def = minetest.registered_nodes[self._taken_node]
-- Update animation and texture accordingly (adds visibly carried block) -- Update animation and texture accordingly (adds visibly carried block)
local block_type local block_type

@ -86,7 +86,8 @@ mobs_mc.override.items = {
mycelium = "mcl_core:mycelium", mycelium = "mcl_core:mycelium",
carrot = "mcl_farming:carrot_item", carrot = "mcl_farming:carrot_item",
golden_carrot = "mcl_farming:carrot_item_gold", golden_carrot = "mcl_farming:carrot_item_gold",
fishing_rod = "mcl_fishing:fishing_rod", fishing_rod = "mcl_core:stick",
--TODO: Re-enable: fishing_rod = "mcl_fishing:fishing_rod",
fish_raw = "mcl_fishing:fish_raw", fish_raw = "mcl_fishing:fish_raw",
salmon_raw = "mcl_fishing:salmon_raw", salmon_raw = "mcl_fishing:salmon_raw",
clownfish_raw = "mcl_fishing:clownfish_raw", clownfish_raw = "mcl_fishing:clownfish_raw",
@ -150,6 +151,7 @@ mobs_mc.override.replace = {
-- Sheep eat grass -- Sheep eat grass
sheep = { sheep = {
{ "mcl_core:dirt_with_grass", "mcl_core:dirt", -1 }, { "mcl_core:dirt_with_grass", "mcl_core:dirt", -1 },
{ "mcl_core:dirt_with_dry_grass", "mcl_core:dirt", -1 },
{ "mcl_flowers:tallgrass", "air", 0 }, { "mcl_flowers:tallgrass", "air", 0 },
}, },
-- Silverfish populate stone, etc. with monster eggs -- Silverfish populate stone, etc. with monster eggs
@ -168,7 +170,9 @@ mobs_mc.override.enderman_takable = {
-- Generic handling, useful for entensions -- Generic handling, useful for entensions
"group:enderman_takable", "group:enderman_takable",
} }
mobs_mc.override.enderman_replace_on_take = {
["mcl_core:dirt_with_dry_grass"] = "mcl_core:dirt_with_grass",
}
-- Texuture overrides for enderman block. Required for cactus because it's original is a nodebox -- Texuture overrides for enderman block. Required for cactus because it's original is a nodebox
-- and the textures have tranparent pixels. -- and the textures have tranparent pixels.
@ -190,18 +194,18 @@ mobs_mc.override.enderman_block_texture_overrides = {
-- List of nodes on which mobs can spawn -- List of nodes on which mobs can spawn
mobs_mc.override.spawn = { mobs_mc.override.spawn = {
solid = { "group:solid", }, -- spawn on "solid" nodes solid = { "group:solid", }, -- spawn on "solid" nodes
grassland = { mobs_mc.override.items.grass_block }, grassland = { "mcl_core:dirt_with_grass" },
savanna = { "group:sand", "mcl_core:sandstone", "mcl_core:redsandstone" }, savanna = { "mcl_core:dirt_with_dry_grass" },
grassland_savanna = { mobs_mc.override.items.grass_block, "group:sand", "mcl_core:sandstone", "mcl_core:redsandstone" }, grassland_savanna = { "mcl_core:dirt_with_grass", "mcl_core:dirt_with_dry_grass" },
desert = { "group:sand" }, desert = { "mcl_core:sand", "mcl_core:sandstone" },
jungle = { "mcl_core:jungletree", "mcl_core:jungleleaves", "mcl_flowers:fern", "mcl_core:vine" }, jungle = { "mcl_core:jungletree", "mcl_core:jungleleaves", "mcl_flowers:fern", "mcl_core:vine" },
snow = { "mcl_core:snow", "mcl_core:snowblock", "mcl_core:dirt_with_grass_snow" }, snow = { "mcl_core:snow", "mcl_core:snowblock", "mcl_core:dirt_with_grass_snow", "mcl_core:dirt_with_dry_grass_snow" },
-- End stone added for shulkers because End cities don't generate yet -- End stone added for shulkers because End cities don't generate yet
end_city = { "mcl_end:end_stone", "mcl_end:purpur_block" }, end_city = { "mcl_end:end_stone", "mcl_end:purpur_block" },
nether = { "mcl_nether:netherrack", "mcl_nether:quartz_ore" }, nether = { "mcl_nether:netherrack", "mcl_nether:quartz_ore" },
-- Netherrack added because there are no Nether fortresses yet. TODO: Remove netherrac from list as soon they're available -- Netherrack added because there are no Nether fortresses yet. TODO: Remove netherrac from list as soon they're available
nether_fortress = { "mcl_nether:nether_brick", "mcl_nether:netherrack" }, nether_fortress = { "mcl_nether:nether_brick", "mcl_nether:netherrack" },
wolf = { mobs_mc.override.items.grass_block, "mcl_core:dirt", "mcl_core:dirt_with_grass_snow", "mcl_core:snow", "mcl_core:snowblock", "mcl_core:podzol" }, wolf = { mobs_mc.override.items.grass_block, "mcl_core:dirt", "mcl_core:dirt_with_grass_snow", "mcl_core:dirt_with_dry_grass_snow", "mcl_core:snow", "mcl_core:snowblock", "mcl_core:podzol" },
} }
-- This table contains important spawn height references for the mob spawn height. -- This table contains important spawn height references for the mob spawn height.

@ -34,7 +34,7 @@ local revertsky = function(dtime)
return return
end end
skycolor.remove_layer("lightning") mcl_weather.skycolor.remove_layer("lightning")
ps = {} ps = {}
end end
@ -136,8 +136,8 @@ lightning.strike = function(pos)
local name = player:get_player_name() local name = player:get_player_name()
if ps[name] == nil then if ps[name] == nil then
ps[name] = {p = player, sky = sky} ps[name] = {p = player, sky = sky}
skycolor.add_layer("lightning", {{r=255,g=255,b=255}}, true) mcl_weather.skycolor.add_layer("lightning", {{r=255,g=255,b=255}}, true)
skycolor.active = true mcl_weather.skycolor.active = true
end end
end end
@ -184,7 +184,7 @@ lightning.strike = function(pos)
if lua.name == "mobs_mc:pig" then if lua.name == "mobs_mc:pig" then
local rot = obj:get_yaw() local rot = obj:get_yaw()
obj:remove() obj:remove()
obj = minetest.add_entity(pos2, "mobs_mc:zombiepig") obj = minetest.add_entity(pos2, "mobs_mc:pigman")
obj:set_yaw(rot) obj:set_yaw(rot)
-- villager → witch -- villager → witch
elseif lua.name == "mobs_mc:villager" then elseif lua.name == "mobs_mc:villager" then

@ -1,6 +1,6 @@
weather-pack `mcl_weather`
======================= =======================
Weather mod for Minetest (http://minetest.net/) Weather mod for MineClone 2. Forked from `weather_pack`.
Weathers included Weathers included
----------------------- -----------------------
@ -10,13 +10,13 @@ Weathers included
Commands Commands
----------------------- -----------------------
`set_weather <weather>` requires `weather_manager` privilege. `weather <weather>`, requires `weather_manager` privilege.
Dependencies Dependencies
----------------------- -----------------------
Thunder weather requres [lightning](https://github.com/minetest-mods/lightning) mod. Thunder weather requres [lightning](https://github.com/minetest-mods/lightning) mod.
Configuration properties Configuration prope, ties
----------------------- -----------------------
Weather mod for indoor check depends on sunlight propogation check. Some nodes (e.g. glass block) propogates sunlight and thus weather particles will go through it. To change that set `weather_allow_override_nodes=true` in `minetest.conf` file. Be aware that just few nodes will be override and these blocks needs to be re-builded to take effect. Maybe in future other 'cheap' way to check indoor will be available. Weather mod for indoor check depends on sunlight propogation check. Some nodes (e.g. glass block) propogates sunlight and thus weather particles will go through it. To change that set `weather_allow_override_nodes=true` in `minetest.conf` file. Be aware that just few nodes will be override and these blocks needs to be re-builded to take effect. Maybe in future other 'cheap' way to check indoor will be available.

@ -0,0 +1 @@
Weather: Rain, snow, thunderstorm.

@ -1,4 +1,4 @@
local modpath = minetest.get_modpath("weather_pack"); local modpath = minetest.get_modpath("mcl_weather");
dofile(modpath.."/weather_core.lua") dofile(modpath.."/weather_core.lua")
dofile(modpath.."/snow.lua") dofile(modpath.."/snow.lua")
dofile(modpath.."/rain.lua") dofile(modpath.."/rain.lua")

@ -0,0 +1 @@
name = mcl_weather

@ -1,7 +1,7 @@
local PARTICLES_COUNT_RAIN = 30 local PARTICLES_COUNT_RAIN = 30
local PARTICLES_COUNT_THUNDER = 45 local PARTICLES_COUNT_THUNDER = 45
rain = { mcl_weather.rain = {
-- max rain particles created at time -- max rain particles created at time
particles_count = PARTICLES_COUNT_RAIN, particles_count = PARTICLES_COUNT_RAIN,
@ -18,7 +18,7 @@ rain = {
init_done = false, init_done = false,
} }
rain.sound_handler = function(player) mcl_weather.rain.sound_handler = function(player)
return minetest.sound_play("weather_rain", { return minetest.sound_play("weather_rain", {
object = player, object = player,
max_hear_distance = 2, max_hear_distance = 2,
@ -27,16 +27,16 @@ rain.sound_handler = function(player)
end end
-- set skybox based on time (uses skycolor api) -- set skybox based on time (uses skycolor api)
rain.set_sky_box = function() mcl_weather.rain.set_sky_box = function()
if weather.state == "rain" then if mcl_weather.state == "rain" then
skycolor.add_layer( mcl_weather.skycolor.add_layer(
"weather-pack-rain-sky", "weather-pack-rain-sky",
{{r=0, g=0, b=0}, {{r=0, g=0, b=0},
{r=85, g=86, b=98}, {r=85, g=86, b=98},
{r=175, g=175, b=191}, {r=175, g=175, b=191},
{r=85, g=86, b=98}, {r=85, g=86, b=98},
{r=0, g=0, b=0}}) {r=0, g=0, b=0}})
skycolor.active = true mcl_weather.skycolor.active = true
for _, player in pairs(minetest.get_connected_players()) do for _, player in pairs(minetest.get_connected_players()) do
player:set_clouds({color="#5D5D5FE8"}) player:set_clouds({color="#5D5D5FE8"})
end end
@ -45,13 +45,13 @@ end
-- creating manually parctiles instead of particles spawner because of easier to control -- creating manually parctiles instead of particles spawner because of easier to control
-- spawn position. -- spawn position.
rain.add_rain_particles = function(player) mcl_weather.rain.add_rain_particles = function(player)
rain.last_rp_count = 0 mcl_weather.rain.last_rp_count = 0
for i=rain.particles_count, 1,-1 do for i=mcl_weather.rain.particles_count, 1,-1 do
local random_pos_x, random_pos_y, random_pos_z = weather.get_random_pos_by_player_look_dir(player) local random_pos_x, random_pos_y, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player)
if weather.is_outdoor({x=random_pos_x, y=random_pos_y, z=random_pos_z}) then if mcl_weather.is_outdoor({x=random_pos_x, y=random_pos_y, z=random_pos_z}) then
rain.last_rp_count = rain.last_rp_count + 1 mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1
minetest.add_particle({ minetest.add_particle({
pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z},
velocity = {x=0, y=-10, z=0}, velocity = {x=0, y=-10, z=0},
@ -61,7 +61,7 @@ rain.add_rain_particles = function(player)
collisiondetection = true, collisiondetection = true,
collision_removal = true, collision_removal = true,
vertical = true, vertical = true,
texture = rain.get_texture(), texture = mcl_weather.rain.get_texture(),
playername = player:get_player_name() playername = player:get_player_name()
}) })
end end
@ -69,7 +69,7 @@ rain.add_rain_particles = function(player)
end end
-- Simple random texture getter -- Simple random texture getter
rain.get_texture = function() mcl_weather.rain.get_texture = function()
local texture_name local texture_name
local random_number = math.random() local random_number = math.random()
if random_number > 0.33 then if random_number > 0.33 then
@ -84,42 +84,42 @@ end
-- register player for rain weather. -- register player for rain weather.
-- basically needs for origin sky reference and rain sound controls. -- basically needs for origin sky reference and rain sound controls.
rain.add_player = function(player) mcl_weather.rain.add_player = function(player)
if weather.players[player:get_player_name()] == nil then if mcl_weather.players[player:get_player_name()] == nil then
local player_meta = {} local player_meta = {}
player_meta.origin_sky = {player:get_sky()} player_meta.origin_sky = {player:get_sky()}
weather.players[player:get_player_name()] = player_meta mcl_weather.players[player:get_player_name()] = player_meta
end end
end end
-- remove player from player list effected by rain. -- remove player from player list effected by rain.
-- be sure to remove sound before removing player otherwise soundhandler reference will be lost. -- be sure to remove sound before removing player otherwise soundhandler reference will be lost.
rain.remove_player = function(player) mcl_weather.rain.remove_player = function(player)
local player_meta = weather.players[player:get_player_name()] local player_meta = mcl_weather.players[player:get_player_name()]
if player_meta ~= nil and player_meta.origin_sky ~= nil then if player_meta ~= nil and player_meta.origin_sky ~= nil then
player:set_sky(player_meta.origin_sky[1], player_meta.origin_sky[2], player_meta.origin_sky[3], true) player:set_sky(player_meta.origin_sky[1], player_meta.origin_sky[2], player_meta.origin_sky[3], true)
player:set_clouds({color="#FFF0F0E5"}) player:set_clouds({color="#FFF0F0E5"})
weather.players[player:get_player_name()] = nil mcl_weather.players[player:get_player_name()] = nil
end end
end end
-- adds and removes rain sound depending how much rain particles around player currently exist. -- adds and removes rain sound depending how much rain particles around player currently exist.
-- have few seconds delay before each check to avoid on/off sound too often -- have few seconds delay before each check to avoid on/off sound too often
-- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance. -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
rain.update_sound = function(player) mcl_weather.rain.update_sound = function(player)
local player_meta = weather.players[player:get_player_name()] local player_meta = mcl_weather.players[player:get_player_name()]
if player_meta ~= nil then if player_meta ~= nil then
if player_meta.sound_updated ~= nil and player_meta.sound_updated + 5 > minetest.get_gametime() then if player_meta.sound_updated ~= nil and player_meta.sound_updated + 5 > minetest.get_gametime() then
return false return false
end end
if player_meta.sound_handler ~= nil then if player_meta.sound_handler ~= nil then
if rain.last_rp_count == 0 then if mcl_weather.rain.last_rp_count == 0 then
minetest.sound_stop(player_meta.sound_handler) minetest.sound_stop(player_meta.sound_handler)
player_meta.sound_handler = nil player_meta.sound_handler = nil
end end
elseif rain.last_rp_count > 0 then elseif mcl_weather.rain.last_rp_count > 0 then
player_meta.sound_handler = rain.sound_handler(player) player_meta.sound_handler = mcl_weather.rain.sound_handler(player)
end end
player_meta.sound_updated = minetest.get_gametime() player_meta.sound_updated = minetest.get_gametime()
@ -127,8 +127,8 @@ rain.update_sound = function(player)
end end
-- rain sound removed from player. -- rain sound removed from player.
rain.remove_sound = function(player) mcl_weather.rain.remove_sound = function(player)
local player_meta = weather.players[player:get_player_name()] local player_meta = mcl_weather.players[player:get_player_name()]
if player_meta ~= nil and player_meta.sound_handler ~= nil then if player_meta ~= nil and player_meta.sound_handler ~= nil then
minetest.sound_stop(player_meta.sound_handler) minetest.sound_stop(player_meta.sound_handler)
player_meta.sound_handler = nil player_meta.sound_handler = nil
@ -136,63 +136,55 @@ rain.remove_sound = function(player)
end end
-- callback function for removing rain -- callback function for removing rain
rain.clear = function() mcl_weather.rain.clear = function()
rain.raining = false mcl_weather.rain.raining = false
rain.sky_last_update = -1 mcl_weather.rain.sky_last_update = -1
rain.init_done = false mcl_weather.rain.init_done = false
rain.set_particles_mode("rain") mcl_weather.rain.set_particles_mode("rain")
skycolor.remove_layer("weather-pack-rain-sky") mcl_weather.skycolor.remove_layer("weather-pack-rain-sky")
for _, player in ipairs(minetest.get_connected_players()) do for _, player in ipairs(minetest.get_connected_players()) do
rain.remove_sound(player) mcl_weather.rain.remove_sound(player)
rain.remove_player(player) mcl_weather.rain.remove_player(player)
end end
end end
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if weather.state ~= "rain" then if mcl_weather.state ~= "rain" then
return false return false
end end
rain.make_weather() mcl_weather.rain.make_weather()
end) end)
rain.make_weather = function() mcl_weather.rain.make_weather = function()
if rain.init_done == false then if mcl_weather.rain.init_done == false then
rain.raining = true mcl_weather.rain.raining = true
rain.set_sky_box() mcl_weather.rain.set_sky_box()
rain.init_done = true mcl_weather.rain.set_particles_mode(mcl_weather.mode)
rain.set_particles_mode(weather.mode) mcl_weather.rain.init_done = true
end end
for _, player in ipairs(minetest.get_connected_players()) do for _, player in ipairs(minetest.get_connected_players()) do
if (weather.is_underwater(player) or not mcl_util.has_weather(player:getpos())) then if (mcl_weather.is_underwater(player) or not mcl_util.has_weather(player:getpos())) then
rain.remove_sound(player) mcl_weather.rain.remove_sound(player)
return false return false
end end
rain.add_player(player) mcl_weather.rain.add_player(player)
rain.add_rain_particles(player) mcl_weather.rain.add_rain_particles(player)
rain.update_sound(player) mcl_weather.rain.update_sound(player)
end end
end end
if weather.reg_weathers.rain == nil then
weather.reg_weathers.rain = {
chance = 15,
light_factor = 0.7,
clear = rain.clear
}
end
-- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops
rain.set_particles_mode = function(mode) mcl_weather.rain.set_particles_mode = function(mode)
if mode == "thunder" then if mode == "thunder" then
rain.particles_count = PARTICLES_COUNT_THUNDER mcl_weather.rain.particles_count = PARTICLES_COUNT_THUNDER
else else
rain.particles_count = PARTICLES_COUNT_RAIN mcl_weather.rain.particles_count = PARTICLES_COUNT_RAIN
end end
end end
if weather.allow_abm then if mcl_weather.allow_abm then
-- ABM for extinguish fire -- ABM for extinguish fire
minetest.register_abm({ minetest.register_abm({
label = "Rain extinguishes fire", label = "Rain extinguishes fire",
@ -200,8 +192,8 @@ if weather.allow_abm then
interval = 4.0, interval = 4.0,
chance = 2, chance = 2,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
if rain.raining and rain.extinguish_fire then if mcl_weather.rain.raining and mcl_weather.rain.extinguish_fire then
if weather.is_outdoor(pos) then if mcl_weather.is_outdoor(pos) then
minetest.remove_node(pos) minetest.remove_node(pos)
minetest.sound_play("fire_extinguish_flame", {pos = pos, max_hear_distance = 16, gain = 0.15}) minetest.sound_play("fire_extinguish_flame", {pos = pos, max_hear_distance = 16, gain = 0.15})
end end
@ -216,7 +208,7 @@ if weather.allow_abm then
interval = 56.0, interval = 56.0,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
if rain.raining and weather.is_outdoor(pos) then if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then
if node.name == "mcl_cauldrons:cauldron" then if node.name == "mcl_cauldrons:cauldron" then
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_1"}) minetest.set_node(pos, {name="mcl_cauldrons:cauldron_1"})
elseif node.name == "mcl_cauldrons:cauldron_1" then elseif node.name == "mcl_cauldrons:cauldron_1" then
@ -235,7 +227,7 @@ if weather.allow_abm then
interval = 22.0, interval = 22.0,
chance = 3, chance = 3,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
if rain.raining and weather.is_outdoor(pos) then if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then
if node.name == "mcl_farming:soil" then if node.name == "mcl_farming:soil" then
minetest.set_node(pos, {name="mcl_farming:soil_wet"}) minetest.set_node(pos, {name="mcl_farming:soil_wet"})
end end
@ -243,3 +235,18 @@ if weather.allow_abm then
end end
}) })
end end
if mcl_weather.reg_weathers.rain == nil then
mcl_weather.reg_weathers.rain = {
clear = mcl_weather.rain.clear,
light_factor = 0.6,
-- 10min - 20min
min_duration = 600,
max_duration = 1200,
transitions = {
[65] = "none",
[70] = "snow",
[100] = "thunder",
}
}
end

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

@ -1,4 +1,4 @@
skycolor = { mcl_weather.skycolor = {
-- Should be activated before do any effect. -- Should be activated before do any effect.
active = true, active = true,
@ -38,26 +38,26 @@ skycolor = {
-- To layer to colors table -- To layer to colors table
add_layer = function(layer_name, layer_color, instant_update) add_layer = function(layer_name, layer_color, instant_update)
skycolor.colors[layer_name] = layer_color mcl_weather.skycolor.colors[layer_name] = layer_color
table.insert(skycolor.layer_names, layer_name) table.insert(mcl_weather.skycolor.layer_names, layer_name)
if (instant_update ~= true) then if (instant_update ~= true) then
skycolor.init_transition() mcl_weather.skycolor.init_transition()
end end
skycolor.force_update = true mcl_weather.skycolor.force_update = true
end, end,
-- Retrieve layer from colors table -- Retrieve layer from colors table
retrieve_layer = function() retrieve_layer = function()
local last_layer = skycolor.layer_names[#skycolor.layer_names] local last_layer = mcl_weather.skycolor.layer_names[#mcl_weather.skycolor.layer_names]
return skycolor.colors[last_layer] return mcl_weather.skycolor.colors[last_layer]
end, end,
-- Remove layer from colors table -- Remove layer from colors table
remove_layer = function(layer_name) remove_layer = function(layer_name)
for k, name in ipairs(skycolor.layer_names) do for k, name in ipairs(mcl_weather.skycolor.layer_names) do
if name == layer_name then if name == layer_name then
table.remove(skycolor.layer_names, k) table.remove(mcl_weather.skycolor.layer_names, k)
skycolor.force_update = true mcl_weather.skycolor.force_update = true
return return
end end
end end
@ -65,22 +65,21 @@ skycolor = {
-- Update sky color. If players not specified update sky for all players. -- Update sky color. If players not specified update sky for all players.
update_sky_color = function(players) update_sky_color = function(players)
local color = skycolor.current_sky_layer_color() local color = mcl_weather.skycolor.current_sky_layer_color()
if (color == nil) then if (color == nil) then
skycolor.set_default_sky() mcl_weather.skycolor.set_default_sky()
return return
end end
players = skycolor.utils.get_players(players)
-- Make everything darker for player -- Make everything darker for player
players = mcl_weather.skycolor.utils.get_players(players)
for _, player in ipairs(players) do for _, player in ipairs(players) do
local pos = player:getpos() local pos = player:getpos()
local _, dim = mcl_util.y_to_layer(pos.y) local _, dim = mcl_util.y_to_layer(pos.y)
if dim == "overworld" then if dim == "overworld" then
player:set_sky(color, "plain", nil, true) player:set_sky(color, "plain", nil, true)
local lf = weather.get_current_light_factor() local lf = mcl_weather.get_current_light_factor()
if lf then if lf then
local w = minetest.get_timeofday() local w = minetest.get_timeofday()
local light = (w * (lf*2)) local light = (w * (lf*2))
@ -102,34 +101,34 @@ skycolor = {
-- Returns current layer color in {r, g, b} format -- Returns current layer color in {r, g, b} format
current_sky_layer_color = function() current_sky_layer_color = function()
if #skycolor.layer_names == 0 then if #mcl_weather.skycolor.layer_names == 0 then
return nil return nil
end end
-- min timeofday value 0; max timeofday value 1. So sky color gradient range will be between 0 and 1 * skycolor.max_value. -- min timeofday value 0; max timeofday value 1. So sky color gradient range will be between 0 and 1 * mcl_weather.skycolor.max_val.
local timeofday = minetest.get_timeofday() local timeofday = minetest.get_timeofday()
local rounded_time = math.floor(timeofday * skycolor.max_val) local rounded_time = math.floor(timeofday * mcl_weather.skycolor.max_val)
local color = skycolor.utils.convert_to_rgb(skycolor.min_val, skycolor.max_val, rounded_time, skycolor.retrieve_layer()) local color = mcl_weather.skycolor.utils.convert_to_rgb(mcl_weather.skycolor.min_val, mcl_weather.skycolor.max_val, rounded_time, mcl_weather.skycolor.retrieve_layer())
return color return color
end, end,
-- Initialy used only on -- Initialy used only on
update_transition_sky_color = function() update_transition_sky_color = function()
if #skycolor.layer_names == 0 then if #mcl_weather.skycolor.layer_names == 0 then
skycolor.set_default_sky() mcl_weather.skycolor.set_default_sky()
return return
end end
local multiplier = 100 local multiplier = 100
local rounded_time = math.floor(skycolor.transition_timer * multiplier) local rounded_time = math.floor(mcl_weather.skycolor.transition_timer * multiplier)
if rounded_time >= skycolor.transition_time * multiplier then if rounded_time >= mcl_weather.skycolor.transition_time * multiplier then
skycolor.stop_transition() mcl_weather.skycolor.stop_transition()
return return
end end
local color = skycolor.utils.convert_to_rgb(0, skycolor.transition_time * multiplier, rounded_time, skycolor.transition_colors) local color = mcl_weather.skycolor.utils.convert_to_rgb(0, mcl_weather.skycolor.transition_time * multiplier, rounded_time, mcl_weather.skycolor.transition_colors)
local players = skycolor.utils.get_players(nil) local players = mcl_weather.skycolor.utils.get_players(nil)
for _, player in ipairs(players) do for _, player in ipairs(players) do
local pos = player:getpos() local pos = player:getpos()
local _, dim = mcl_util.y_to_layer(pos.y) local _, dim = mcl_util.y_to_layer(pos.y)
@ -143,12 +142,13 @@ skycolor = {
-- Could be sometimes useful but not recomended to use in general case as there may be other color layers -- Could be sometimes useful but not recomended to use in general case as there may be other color layers
-- which needs to preserve. -- which needs to preserve.
set_default_sky = function(players) set_default_sky = function(players)
local players = skycolor.utils.get_players(players) local players = mcl_weather.skycolor.utils.get_players(players)
for _, player in ipairs(players) do for _, player in ipairs(players) do
local pos = player:getpos() local pos = player:getpos()
local _, dim = mcl_util.y_to_layer(pos.y) local _, dim = mcl_util.y_to_layer(pos.y)
if dim == "overworld" then if dim == "overworld" then
player:set_sky(nil, "regular", nil, true) player:set_sky(nil, "regular", nil, true)
player:override_day_night_ratio(nil)
end end
end end
end, end,
@ -156,23 +156,23 @@ skycolor = {
init_transition = function() init_transition = function()
-- sadly default sky returns unpredictible colors so transition mode becomes usable only for user defined color layers -- sadly default sky returns unpredictible colors so transition mode becomes usable only for user defined color layers
-- Here '2' means that one color layer existed before new added and transition is posible. -- Here '2' means that one color layer existed before new added and transition is posible.
if #skycolor.layer_names < 2 then if #mcl_weather.skycolor.layer_names < 2 then
return return
end end
local transition_start_color = skycolor.utils.get_current_bg_color() local transition_start_color = mcl_weather.skycolor.utils.get_current_bg_color()
if (transition_start_color == nil) then if (transition_start_color == nil) then
return return
end end
local transition_end_color = skycolor.current_sky_layer_color() local transition_end_color = mcl_weather.skycolor.current_sky_layer_color()
skycolor.transition_colors = {transition_start_color, transition_end_color} mcl_weather.skycolor.transition_colors = {transition_start_color, transition_end_color}
skycolor.transition_in_progress = true mcl_weather.skycolor.transition_in_progress = true
end, end,
stop_transition = function() stop_transition = function()
skycolor.transition_in_progress = false mcl_weather.skycolor.transition_in_progress = false
skycolor.transition_colors = {} mcl_weather.skycolor.transition_colors = {}
skycolor.transition_timer = 0 mcl_weather.skycolor.transition_timer = 0
end, end,
utils = { utils = {
@ -197,7 +197,7 @@ skycolor = {
-- Returns first player sky color. I assume that all players are in same color layout. -- Returns first player sky color. I assume that all players are in same color layout.
get_current_bg_color = function() get_current_bg_color = function()
local players = skycolor.utils.get_players(nil) local players = mcl_weather.skycolor.utils.get_players(nil)
for _, player in ipairs(players) do for _, player in ipairs(players) do
return player:get_sky() return player:get_sky()
end end
@ -209,34 +209,34 @@ skycolor = {
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if skycolor.active ~= true or #minetest.get_connected_players() == 0 then if mcl_weather.skycolor.active ~= true or #minetest.get_connected_players() == 0 then
return return
end end
if skycolor.smooth_transitions and skycolor.transition_in_progress then if mcl_weather.skycolor.smooth_transitions and mcl_weather.skycolor.transition_in_progress then
skycolor.transition_timer = skycolor.transition_timer + dtime mcl_weather.skycolor.transition_timer = mcl_weather.skycolor.transition_timer + dtime
skycolor.update_transition_sky_color() mcl_weather.skycolor.update_transition_sky_color()
return return
end end
if skycolor.force_update then if mcl_weather.skycolor.force_update then
skycolor.update_sky_color() mcl_weather.skycolor.update_sky_color()
skycolor.force_update = false mcl_weather.skycolor.force_update = false
return return
end end
-- regular updates based on iterval -- regular updates based on iterval
timer = timer + dtime; timer = timer + dtime;
if timer >= skycolor.update_interval then if timer >= mcl_weather.skycolor.update_interval then
skycolor.update_sky_color() mcl_weather.skycolor.update_sky_color()
timer = 0 timer = 0
end end
end) end)
local initsky = function(player) local initsky = function(player)
if (skycolor.active) then if (mcl_weather.skycolor.active) then
skycolor.force_update = true mcl_weather.skycolor.force_update = true
end end
-- MC-style clouds: Layer 127, thickness 4, fly to the “West” -- MC-style clouds: Layer 127, thickness 4, fly to the “West”

@ -1,16 +1,16 @@
snow = {} mcl_weather.snow = {}
snow.particles_count = 15 mcl_weather.snow.particles_count = 15
snow.init_done = false mcl_weather.snow.init_done = false
-- calculates coordinates and draw particles for snow weather -- calculates coordinates and draw particles for snow weather
snow.add_rain_particles = function(player) mcl_weather.snow.add_snow_particles = function(player)
rain.last_rp_count = 0 mcl_weather.rain.last_rp_count = 0
for i=snow.particles_count, 1,-1 do for i=mcl_weather.snow.particles_count, 1,-1 do
local random_pos_x, random_pos_y, random_pos_z = weather.get_random_pos_by_player_look_dir(player) local random_pos_x, random_pos_y, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player)
random_pos_y = math.random() + math.random(player:getpos().y - 1, player:getpos().y + 7) random_pos_y = math.random() + math.random(player:getpos().y - 1, player:getpos().y + 7)
if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then
rain.last_rp_count = rain.last_rp_count + 1 mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1
minetest.add_particle({ minetest.add_particle({
pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z},
velocity = {x = math.random(-1,-0.5), y = math.random(-2,-1), z = math.random(-1,-0.5)}, velocity = {x = math.random(-1,-0.5), y = math.random(-2,-1), z = math.random(-1,-0.5)},
@ -20,30 +20,30 @@ snow.add_rain_particles = function(player)
collisiondetection = true, collisiondetection = true,
collision_removal = true, collision_removal = true,
vertical = true, vertical = true,
texture = snow.get_texture(), texture = mcl_weather.snow.get_texture(),
playername = player:get_player_name() playername = player:get_player_name()
}) })
end end
end end
end end
snow.set_sky_box = function() mcl_weather.snow.set_sky_box = function()
skycolor.add_layer( mcl_weather.skycolor.add_layer(
"weather-pack-snow-sky", "weather-pack-snow-sky",
{{r=0, g=0, b=0}, {{r=0, g=0, b=0},
{r=241, g=244, b=249}, {r=241, g=244, b=249},
{r=0, g=0, b=0}} {r=0, g=0, b=0}}
) )
skycolor.active = true mcl_weather.skycolor.active = true
end end
snow.clear = function() mcl_weather.snow.clear = function()
skycolor.remove_layer("weather-pack-snow-sky") mcl_weather.skycolor.remove_layer("weather-pack-snow-sky")
snow.init_done = false mcl_weather.snow.init_done = false
end end
-- Simple random texture getter -- Simple random texture getter
snow.get_texture = function() mcl_weather.snow.get_texture = function()
local texture_name local texture_name
local random_number = math.random() local random_number = math.random()
if random_number > 0.5 then if random_number > 0.5 then
@ -56,7 +56,7 @@ end
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if weather.state ~= "snow" then if mcl_weather.state ~= "snow" then
return false return false
end end
@ -67,25 +67,32 @@ minetest.register_globalstep(function(dtime)
return return
end end
if snow.init_done == false then if mcl_weather.snow.init_done == false then
snow.set_sky_box() mcl_weather.snow.set_sky_box()
snow.init_done = true mcl_weather.snow.init_done = true
end end
for _, player in ipairs(minetest.get_connected_players()) do for _, player in ipairs(minetest.get_connected_players()) do
if (weather.is_underwater(player) or not mcl_util.has_weather(player:getpos())) then if (mcl_weather.is_underwater(player) or not mcl_util.has_weather(player:getpos())) then
return false return false
end end
snow.add_rain_particles(player) mcl_weather.snow.add_snow_particles(player)
end end
end) end)
-- register snow weather -- register snow weather
if weather.reg_weathers.snow == nil then if mcl_weather.reg_weathers.snow == nil then
weather.reg_weathers.snow = { mcl_weather.reg_weathers.snow = {
chance = 10, clear = mcl_weather.snow.clear,
light_factor = 0.7, light_factor = 0.6,
clear = snow.clear -- 10min - 20min
} min_duration = 600,
max_duration = 1200,
transitions = {
[65] = "none",
[80] = "rain",
[100] = "thunder",
}
}
end end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 B

After

Width:  |  Height:  |  Size: 296 B

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

Before

Width:  |  Height:  |  Size: 220 B

After

Width:  |  Height:  |  Size: 220 B

Before

Width:  |  Height:  |  Size: 192 B

After

Width:  |  Height:  |  Size: 192 B

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 195 B

@ -0,0 +1,61 @@
-- turn off lightning mod 'auto mode'
lightning.auto = false
mcl_weather.thunder = {
next_strike = 0,
min_delay = 3,
max_delay = 12,
init_done = false,
}
minetest.register_globalstep(function(dtime)
if mcl_weather.get_weather() ~= "thunder" then
return false
end
mcl_weather.rain.set_particles_mode("thunder")
mcl_weather.rain.make_weather()
if mcl_weather.thunder.init_done == false then
mcl_weather.skycolor.add_layer(
"weather-pack-thunder-sky",
{{r=0, g=0, b=0},
{r=40, g=40, b=40},
{r=85, g=86, b=86},
{r=40, g=40, b=40},
{r=0, g=0, b=0}})
mcl_weather.skycolor.active = true
for _, player in pairs(minetest.get_connected_players()) do
player:set_clouds({color="#3D3D3FE8"})
end
mcl_weather.thunder.init_done = true
end
if (mcl_weather.thunder.next_strike <= minetest.get_gametime()) then
lightning.strike()
local delay = math.random(mcl_weather.thunder.min_delay, mcl_weather.thunder.max_delay)
mcl_weather.thunder.next_strike = minetest.get_gametime() + delay
end
end)
mcl_weather.thunder.clear = function()
mcl_weather.rain.clear()
mcl_weather.skycolor.remove_layer("weather-pack-thunder-sky")
mcl_weather.skycolor.remove_layer("lightning")
mcl_weather.thunder.init_done = false
end
-- register thunderstorm weather
if mcl_weather.reg_weathers.thunder == nil then
mcl_weather.reg_weathers.thunder = {
clear = mcl_weather.thunder.clear,
light_factor = 0.33333,
-- 10min - 20min
min_duration = 600,
max_duration = 1200,
transitions = {
[100] = "rain",
}
}
end

@ -1,21 +1,18 @@
weather = { mcl_weather = {
-- weather states, 'none' is default, other states depends from active mods -- weather states, 'none' is default, other states depends from active mods
state = "none", state = "none",
-- player list for saving player meta info -- player list for saving player meta info
players = {}, players = {},
-- time when weather should be re-calculated
next_check = 0,
-- default weather recalculation interval -- default weather recalculation interval
check_interval = 300, check_interval = 300,
-- weather min duration -- weather min duration
min_duration = 240, min_duration = 600,
-- weather max duration -- weather max duration
max_duration = 3600, max_duration = 9000,
-- weather calculated end time -- weather calculated end time
end_time = nil, end_time = nil,
@ -30,26 +27,39 @@ weather = {
allow_abm = true, allow_abm = true,
} }
weather.get_rand_end_time = function(min_duration, max_duration) mcl_weather.reg_weathers["none"] = {
min_duration = mcl_weather.min_duration,
max_duration = mcl_weather.max_duration,
light_factor = nil,
transitions = {
[50] = "rain",
[100] = "snow",
},
clear = function() end,
}
mcl_weather.get_rand_end_time = function(min_duration, max_duration)
local r
if min_duration ~= nil and max_duration ~= nil then if min_duration ~= nil and max_duration ~= nil then
return minetest.get_gametime() + math.random(min_duration, max_duration); r = math.random(min_duration, max_duration);
else else
return minetest.get_gametime() + math.random(weather.min_duration, weather.max_duration); r = math.random(mcl_weather.min_duration, mcl_weather.max_duration);
end end
return minetest.get_gametime() + r
end end
weather.get_current_light_factor = function() mcl_weather.get_current_light_factor = function()
if weather.state == "none" then if mcl_weather.state == "none" then
return nil return nil
else else
return weather.reg_weathers[weather.state].light_factor return mcl_weather.reg_weathers[mcl_weather.state].light_factor
end end
end end
-- Returns true if pos is outdoor. -- Returns true if pos is outdoor.
-- Outdoor is defined as any node in the Overworld under open sky. -- Outdoor is defined as any node in the Overworld under open sky.
-- FIXME: Nodes below glass also count as “outdoor”, this should not be the case. -- FIXME: Nodes below glass also count as “outdoor”, this should not be the case.
weather.is_outdoor = function(pos) mcl_weather.is_outdoor = function(pos)
local cpos = {x=pos.x, y=pos.y+1, z=pos.z} local cpos = {x=pos.x, y=pos.y+1, z=pos.z}
local _, dim = mcl_util.y_to_layer(cpos.y) local _, dim = mcl_util.y_to_layer(cpos.y)
if minetest.get_node_light(cpos, 0.5) == 15 and dim == "overworld" then if minetest.get_node_light(cpos, 0.5) == 15 and dim == "overworld" then
@ -60,7 +70,7 @@ end
-- checks if player is undewater. This is needed in order to -- checks if player is undewater. This is needed in order to
-- turn off weather particles generation. -- turn off weather particles generation.
weather.is_underwater = function(player) mcl_weather.is_underwater = function(player)
local ppos = player:getpos() local ppos = player:getpos()
local offset = player:get_eye_offset() local offset = player:get_eye_offset()
local player_eye_pos = {x = ppos.x + offset.x, local player_eye_pos = {x = ppos.x + offset.x,
@ -75,7 +85,7 @@ end
-- trying to locate position for particles by player look direction for performance reason. -- trying to locate position for particles by player look direction for performance reason.
-- it is costly to generate many particles around player so goal is focus mainly on front view. -- it is costly to generate many particles around player so goal is focus mainly on front view.
weather.get_random_pos_by_player_look_dir = function(player) mcl_weather.get_random_pos_by_player_look_dir = function(player)
local look_dir = player:get_look_dir() local look_dir = player:get_look_dir()
local player_pos = player:getpos() local player_pos = player:getpos()
@ -106,39 +116,55 @@ weather.get_random_pos_by_player_look_dir = function(player)
end end
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
if weather.auto_mode == false then if mcl_weather.auto_mode == false then
return 0 return 0
end end
-- recalculate weather only when there aren't currently any if mcl_weather.end_time == nil then
if (weather.state ~= "none") then mcl_weather.end_time = mcl_weather.get_rand_end_time()
if (weather.end_time ~= nil and weather.end_time <= minetest.get_gametime()) then end
weather.reg_weathers[weather.state].clear() -- recalculate weather
weather.state = "none" if mcl_weather.end_time <= minetest.get_gametime() then
end mcl_weather.set_random_weather(mcl_weather.state, mcl_weather.reg_weathers[mcl_weather.state])
elseif (weather.next_check <= minetest.get_gametime()) then
for weather_name, weather_meta in pairs(weather.reg_weathers) do
weather.set_random_weather(weather_name, weather_meta)
end
-- fallback next_check set, weather 'none' will be.
weather.next_check = minetest.get_gametime() + weather.check_interval
end end
end) end)
-- sets random weather (which could be 'regular' (no weather)). -- Sets random weather (which could be 'none' (no weather)).
weather.set_random_weather = function(weather_name, weather_meta) mcl_weather.set_random_weather = function(weather_name, weather_meta)
if weather.next_check > minetest.get_gametime() then return 0 end if (weather_meta ~= nil) then
local transitions = weather_meta.transitions
if (weather_meta ~= nil and weather_meta.chance ~= nil) then
local random_roll = math.random(0,100) local random_roll = math.random(0,100)
if (random_roll <= weather_meta.chance) then local new_weather
weather.state = weather_name for v, weather in pairs(transitions) do
weather.end_time = weather.get_rand_end_time(weather_meta.min_duration, weather_meta.max_duration) if random_roll < v then
weather.next_check = minetest.get_gametime() + weather.check_interval new_weather = weather
break
end
end
if new_weather then
mcl_weather.change_weather(new_weather)
end end
end end
end end
mcl_weather.change_weather = function(new_weather)
if (mcl_weather.reg_weathers ~= nil and mcl_weather.reg_weathers[new_weather] ~= nil) then
if (mcl_weather.state ~= nil and mcl_weather.reg_weathers[mcl_weather.state] ~= nil) then
mcl_weather.reg_weathers[mcl_weather.state].clear()
end
mcl_weather.state = new_weather
local weather_meta = mcl_weather.reg_weathers[mcl_weather.state]
mcl_weather.end_time = mcl_weather.get_rand_end_time(weather_meta.min_duration, weather_meta.max_duration)
mcl_weather.skycolor.update_sky_color()
return true
end
return false
end
mcl_weather.get_weather = function()
return mcl_weather.state
end
minetest.register_privilege("weather_manager", { minetest.register_privilege("weather_manager", {
description = "Gives ability to control weather", description = "Gives ability to control weather",
give_to_singleplayer = false give_to_singleplayer = false
@ -151,27 +177,19 @@ minetest.register_chatcommand("weather", {
privs = {weather_manager = true}, privs = {weather_manager = true},
func = function(name, param) func = function(name, param)
if (param == "") then if (param == "") then
minetest.chat_send_player(name, "Error: No weather specified.") return false, "Error: No weather specified."
return
end end
local success = false local new_weather
if (param == "clear") then if param == "clear" then
if (weather.state ~= nil and weather.reg_weathers[weather.state] ~= nil) then new_weather = "none"
weather.reg_weathers[weather.state].clear()
end
weather.state = "none"
success = true
return
end
if (weather.reg_weathers ~= nil and weather.reg_weathers[param] ~= nil) then
if (weather.state ~= nil and weather.state ~= "none" and weather.reg_weathers[weather.state] ~= nil) then
weather.reg_weathers[weather.state].clear()
end
weather.state = param
return
else else
minetest.chat_send_player(name, "Error: Invalid weather specified. Use “clear”, “rain”, “snow” or “thunder”.") new_weather = param
end
local success = mcl_weather.change_weather(new_weather)
if success then
return true
else
return false, "Error: Invalid weather specified. Use “clear”, “rain”, “snow” or “thunder”."
end end
end end
}) })
@ -182,19 +200,14 @@ minetest.register_chatcommand("toggledownfall", {
privs = {weather_manager = true}, privs = {weather_manager = true},
func = function(name, param) func = function(name, param)
-- Currently rain/thunder/snow: Set weather to clear -- Currently rain/thunder/snow: Set weather to clear
if weather.state ~= "none" then if mcl_weather.state ~= "none" then
if (weather.state ~= nil and weather.state ~= "none" and weather.reg_weathers[weather.state] ~= nil) then return mcl_weather.change_weather("none")
weather.reg_weathers[weather.state].clear()
end
weather.state = "none"
-- Currently clear: Set weather randomly to rain/thunder/snow -- Currently clear: Set weather randomly to rain/thunder/snow
else else
local new = { "rain", "thunder", "snow" } local new = { "rain", "thunder", "snow" }
local r = math.random(1, #new) local r = math.random(1, #new)
if (weather.state ~= nil and weather.state ~= "none" and weather.reg_weathers[weather.state] ~= nil) then return mcl_weather.change_weather(new[r])
weather.reg_weathers[weather.state].clear()
end
weather.state = new[r]
end end
end end
}) })
@ -203,5 +216,5 @@ minetest.register_chatcommand("toggledownfall", {
-- Weather mods expected to be use this flag before registering ABM. -- Weather mods expected to be use this flag before registering ABM.
local weather_allow_abm = minetest.settings:get_bool("weather_allow_abm") local weather_allow_abm = minetest.settings:get_bool("weather_allow_abm")
if weather_allow_abm ~= nil and weather_allow_abm == false then if weather_allow_abm ~= nil and weather_allow_abm == false then
weather.allow_abm = false mcl_weather.allow_abm = false
end end

@ -1 +0,0 @@
Set of weathers for minetest.

@ -1 +0,0 @@
name = weather_pack

@ -1,59 +0,0 @@
-- turn off lightning mod 'auto mode'
lightning.auto = false
thunder = {
next_strike = 0,
min_delay = 3,
max_delay = 12,
init_done = false,
}
minetest.register_globalstep(function(dtime)
if weather.state ~= "thunder" then
return false
end
rain.set_particles_mode("thunder")
rain.make_weather()
if thunder.init_done == false then
skycolor.add_layer(
"weather-pack-thunder-sky",
{{r=0, g=0, b=0},
{r=40, g=40, b=40},
{r=85, g=86, b=86},
{r=40, g=40, b=40},
{r=0, g=0, b=0}})
skycolor.active = true
for _, player in pairs(minetest.get_connected_players()) do
player:set_clouds({color="#3D3D3FE8"})
end
thunder.init_done = true
end
if (thunder.next_strike <= minetest.get_gametime()) then
lightning.strike()
local delay = math.random(thunder.min_delay, thunder.max_delay)
thunder.next_strike = minetest.get_gametime() + delay
end
end)
thunder.clear = function()
rain.clear()
skycolor.remove_layer("weather-pack-thunder-sky")
skycolor.remove_layer("lightning")
thunder.init_done = false
end
-- register thunderstorm weather
if weather.reg_weathers.thunder == nil then
weather.reg_weathers.thunder = {
chance = 5,
light_factor = 0.33333,
clear = thunder.clear,
min_duration = 120,
max_duration = 600,
}
end

@ -62,7 +62,9 @@ end)
doc.sub.items.register_factoid("nodes", "groups", function(itemstring, def) doc.sub.items.register_factoid("nodes", "groups", function(itemstring, def)
local datastring = "" local datastring = ""
if def.groups.place_flowerlike == 1 then if def.groups.place_flowerlike == 1 then
return "This plant can only grow on dirt, grass blocks and podzol. To survive, it needs to have an unobstructed view to the sky above or be exposed to a light level of 8 or higher." return "This plant can only grow on grass blocks and dirt. To survive, it needs to have an unobstructed view to the sky above or be exposed to a light level of 8 or higher."
elseif def.groups.place_flowerlike == 2 then
return "This plant can grow on grass blocks, podzol, dirt and coarse dirt. To survive, it needs to have an unobstructed view to the sky above or be exposed to a light level of 8 or higher."
end end
return "" return ""
end) end)

@ -139,18 +139,36 @@ local boffset = {} --
local hoch = {} local hoch = {}
local bg = {} local bg = {}
noffset["blocks"] = {-0.29,-0.25} local noffset_x_start = -0.24
noffset["deco"] = {0.98,-0.25} local noffset_x = noffset_x_start
noffset["redstone"] = {2.23,-0.25} local noffset_y = -0.25
noffset["rail"] = {3.495,-0.25} local next_noffset = function(id, right)
noffset["misc"] = {4.75,-0.25} if right then
noffset["nix"] = {8.99,-0.25} noffset[id] = { 8.94, noffset_y }
noffset["food"] = {-0.29,8.12} else
noffset["tools"] = {0.98,8.12} noffset[id] = { noffset_x, noffset_y }
noffset["combat"] = {2.23,8.12} noffset_x = noffset_x + 1.25
noffset["brew"] = {3.495,8.12} end
noffset["matr"] = {4.74,8.12} end
noffset["inv"] = {8.99,8.12}
-- Upper row
next_noffset("blocks")
next_noffset("deco")
next_noffset("redstone")
next_noffset("rail")
next_noffset("misc")
next_noffset("nix", true)
noffset_x = noffset_x_start
noffset_y = 8.12
-- Lower row
next_noffset("food")
next_noffset("tools")
next_noffset("combat")
next_noffset("brew")
next_noffset("matr")
next_noffset("inv", true)
for k,v in pairs(noffset) do for k,v in pairs(noffset) do
offset[k] = tostring(v[1]) .. "," .. tostring(v[2]) offset[k] = tostring(v[1]) .. "," .. tostring(v[2])
@ -218,8 +236,14 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
"listring[current_player;main]".. "listring[current_player;main]"..
"listring[detached:trash;main]" "listring[detached:trash;main]"
if page ~= nil then name = page end if page ~= nil then
name = page
if players[playername] then
players[playername].page = page
end
end
bg[name] = "crafting_creative_bg.png" bg[name] = "crafting_creative_bg.png"
local inv_bg = "crafting_inventory_creative.png" local inv_bg = "crafting_inventory_creative.png"
if name == "inv" then if name == "inv" then
inv_bg = "crafting_inventory_creative_survival.png" inv_bg = "crafting_inventory_creative_survival.png"
@ -287,61 +311,67 @@ mcl_inventory.set_creative_formspec = function(player, start_i, pagenum, inv_siz
"image[9.033," .. tostring(slider_pos) .. ";0.78,"..tostring(slider_height) .. ";crafting_slider.png]".. "image[9.033," .. tostring(slider_pos) .. ";0.78,"..tostring(slider_height) .. ";crafting_slider.png]"..
"image_button[9.02,6.15;"..tostring(arrow_height)..",0.6;crafting_creative_down.png;creative_next;]" "image_button[9.02,6.15;"..tostring(arrow_height)..",0.6;crafting_creative_down.png;creative_next;]"
end end
local function tab(current, check)
local img local tab_icon = {
if current == check then blocks = "mcl_core:brick_block",
img = "crafting_creative_active.png" deco = "mcl_flowers:peony",
redstone = "mesecons:redstone",
rail = "mcl_minecarts:golden_rail",
misc = "mcl_buckets:bucket_lava",
nix = "mcl_compass:compass",
food = "mcl_core:apple",
tools = "mcl_core:axe_iron",
combat = "mcl_core:sword_gold",
brew = "mcl_potions:potion_water",
matr = "mcl_core:stick",
inv = "mcl_chests:chest",
}
local function tab(current_tab, this_tab)
local bg_img
if current_tab == this_tab then
bg_img = "crafting_creative_active.png"
else else
img = "crafting_creative_inactive.png" bg_img = "crafting_creative_inactive.png"
end end
return "image[" .. offset[check] .. ";1.5,1.44;" .. img .. hoch[check].. "]" .. return
"image[" .. boffset[check] .. ";1,1;crafting_creative_marker.png]" "item_image_button[" .. boffset[this_tab] ..";1,1;"..tab_icon[this_tab]..";"..this_tab..";]"..
"image[" .. offset[this_tab] .. ";1.5,1.44;" .. bg_img .. hoch[this_tab].. "]" ..
"image[" .. boffset[this_tab] .. ";1,1;crafting_creative_marker.png]"
end end
local fnt = "" local fnt = ""
if name ~= "inv" then if name ~= "inv" then
fnt = "image[0,1;5,0.75;mcl_inventory_fnt_"..name..".png]" fnt = "image[0,1;5,0.75;mcl_inventory_fnt_"..name..".png]"
end end
formspec = "size[10,9.3]".. formspec = "size[10,9.3]"..
mcl_vars.inventory_header.. mcl_vars.inventory_header..
"background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]".. "background[-0.19,-0.25;10.5,9.87;"..inv_bg.."]"..
"label[-5,-5;"..name.."]".. "label[-5,-5;"..name.."]"..
"item_image_button[-0.1,0;1,1;mcl_core:brick_block;blocks;]".. --build blocks
tab(name, "blocks") .. tab(name, "blocks") ..
"tooltip[blocks;Building Blocks]".. "tooltip[blocks;Building Blocks]"..
"item_image_button[1.15,0;1,1;mcl_flowers:peony;deco;]".. --decoration blocks
tab(name, "deco") .. tab(name, "deco") ..
"tooltip[deco;Decoration Blocks]".. "tooltip[deco;Decoration Blocks]"..
"item_image_button[2.415,0;1,1;mesecons:redstone;redstone;]".. --redstone
tab(name, "redstone") .. tab(name, "redstone") ..
"tooltip[redstone;Redstone]".. "tooltip[redstone;Redstone]"..
"item_image_button[3.693,0;1,1;mcl_minecarts:golden_rail;rail;]".. --transportation
tab(name, "rail") .. tab(name, "rail") ..
"tooltip[rail;Transportation]".. "tooltip[rail;Transportation]"..
"item_image_button[4.93,0;1,1;mcl_buckets:bucket_lava;misc;]".. --miscellaneous
tab(name, "misc") .. tab(name, "misc") ..
"tooltip[misc;Miscellaneous]".. "tooltip[misc;Miscellaneous]"..
"item_image_button[9.19,0;1,1;mcl_compass:compass;nix;]".. --search
tab(name, "nix") .. tab(name, "nix") ..
"tooltip[nix;Search Items]".. "tooltip[nix;Search Items]"..
fnt.. fnt..
"list[current_player;main;0,7;9,1;]".. "list[current_player;main;0,7;9,1;]"..
main_list.. main_list..
"item_image_button[-0.1,8.37;1,1;mcl_core:apple;food;]".. --foodstuff
tab(name, "food") .. tab(name, "food") ..
"tooltip[food;Foodstuffs]".. "tooltip[food;Foodstuffs]"..
"item_image_button[1.15,8.37;1,1;mcl_core:axe_iron;tools;]".. --tools
tab(name, "tools") .. tab(name, "tools") ..
"tooltip[tools;Tools]".. "tooltip[tools;Tools]"..
"item_image_button[2.415,8.37;1,1;mcl_core:sword_gold;combat;]".. --combat
tab(name, "combat") .. tab(name, "combat") ..
"tooltip[combat;Combat]".. "tooltip[combat;Combat]"..
"item_image_button[3.693,8.37;1,1;mcl_potions:potion_water;brew;]".. --brewing
tab(name, "brew") .. tab(name, "brew") ..
"tooltip[brew;Brewing]".. "tooltip[brew;Brewing]"..
"item_image_button[4.938,8.37;1,1;mcl_core:stick;matr;]".. --materials
tab(name, "matr") .. tab(name, "matr") ..
"tooltip[matr;Materials]".. "tooltip[matr;Materials]"..
"item_image_button[9.19,8.37;1,1;mcl_chests:chest;inv;]".. --inventory
tab(name, "inv") .. tab(name, "inv") ..
"tooltip[inv;Survival Inventory]".. "tooltip[inv;Survival Inventory]"..
"list[detached:trash;main;9,7;1,1;]".. "list[detached:trash;main;9,7;1,1;]"..

@ -85,9 +85,9 @@ local buttonuse = "Rightclick the button to push it."
minetest.register_node("mesecons_button:button_stone_off", { minetest.register_node("mesecons_button:button_stone_off", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"default_stone.png"}, tiles = {"default_stone.png"},
wield_image = "default_stone.png^[mask:mesecons_button_wield_mask.png", wield_image = "mesecons_button_wield_mask.png^default_stone.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
-- FIXME: Use proper 3D inventory image -- FIXME: Use proper 3D inventory image
inventory_image = "default_stone.png^[mask:mesecons_button_wield_mask.png", inventory_image = "mesecons_button_wield_mask.png^default_stone.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=1}, wield_scale = { x=1, y=1, z=1},
paramtype = "light", paramtype = "light",
paramtype2 = "wallmounted", paramtype2 = "wallmounted",
@ -119,8 +119,8 @@ minetest.register_node("mesecons_button:button_stone_off", {
minetest.register_node("mesecons_button:button_stone_on", { minetest.register_node("mesecons_button:button_stone_on", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"default_stone.png"}, tiles = {"default_stone.png"},
wield_image = "default_stone.png^[mask:mesecons_button_wield_mask.png", wield_image = "mesecons_button_wield_mask.png^default_stone.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
inventory_image = "default_stone.png^[mask:mesecons_button_wield_mask.png", inventory_image = "mesecons_button_wield_mask.png^default_stone.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=0.5}, wield_scale = { x=1, y=1, z=0.5},
paramtype = "light", paramtype = "light",
paramtype2 = "wallmounted", paramtype2 = "wallmounted",
@ -145,8 +145,8 @@ minetest.register_node("mesecons_button:button_stone_on", {
minetest.register_node("mesecons_button:button_wood_off", { minetest.register_node("mesecons_button:button_wood_off", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"default_wood.png"}, tiles = {"default_wood.png"},
wield_image = "default_wood.png^[mask:mesecons_button_wield_mask.png", wield_image = "mesecons_button_wield_mask.png^default_wood.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
inventory_image = "default_wood.png^[mask:mesecons_button_wield_mask.png", inventory_image = "mesecons_button_wield_mask.png^default_wood.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=1}, wield_scale = { x=1, y=1, z=1},
paramtype = "light", paramtype = "light",
paramtype2 = "wallmounted", paramtype2 = "wallmounted",
@ -178,8 +178,8 @@ minetest.register_node("mesecons_button:button_wood_off", {
minetest.register_node("mesecons_button:button_wood_on", { minetest.register_node("mesecons_button:button_wood_on", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = {"default_wood.png"}, tiles = {"default_wood.png"},
wield_image = "default_wood.png^[mask:mesecons_button_wield_mask.png", wield_image = "mesecons_button_wield_mask.png^default_wood.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
inventory_image = "default_wood.png^[mask:mesecons_button_wield_mask.png", inventory_image = "mesecons_button_wield_mask.png^default_wood.png^mesecons_button_wield_mask.png^[makealpha:255,126,126",
wield_scale = { x=1, y=1, z=0.5}, wield_scale = { x=1, y=1, z=0.5},
paramtype = "light", paramtype = "light",
paramtype2 = "wallmounted", paramtype2 = "wallmounted",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 B

After

Width:  |  Height:  |  Size: 115 B

@ -781,7 +781,7 @@ local piston_get_stopper = function (node, dir, stack, stackid)
if minetest.registered_nodes[node.name].mesecons_piston.pusher == pushernode.name then if minetest.registered_nodes[node.name].mesecons_piston.pusher == pushernode.name then
for _, s in ipairs(stack) do for _, s in ipairs(stack) do
if mesecon.cmpPos(s.pos, pusherpos) -- pusher is also to be pushed if vector.equals(s.pos, pusherpos) -- pusher is also to be pushed
and s.node.param2 == node.param2 then and s.node.param2 == node.param2 then
return false return false
end end

@ -22,17 +22,17 @@ local function destruct_bed(pos, n)
end end
end end
local beddesc = "Beds allow you to sleep at night and waste some time. Survival in this world does not demand sleep, but sleeping might have some other uses. " local beddesc = "Beds allow you to sleep at night and make the time pass faster."
local beduse = "Right-click on the bed to try to sleep in it. This only works when the sun sets or at night." local beduse = "Right-click on the bed to sleep in it. This only works when the sun sets, at night or during a thunderstorm."
if minetest.settings:get_bool("enable_bed_respawn") == false then if minetest.settings:get_bool("enable_bed_respawn") == false then
beddesc = beddesc .. "In local folklore, legends are told of other worlds where setting the start point for your next would be possible. But this world is not one of them. " beddesc = beddesc .. "\n" .. "In local folklore, legends are told of other worlds where setting the start point for your next would be possible. But this world is not one of them."
else else
beddesc = beddesc .. "By sleeping in a bed, you set the starting point for your next life. " beddesc = beddesc .. "\n" .. "By sleeping in a bed, you set the starting point for your next life."
end end
if minetest.settings:get_bool("enable_bed_night_skip") == false then if minetest.settings:get_bool("enable_bed_night_skip") == false then
beddesc = beddesc .. "In this strange world, the time will not pass faster for you when you sleep." beddesc = beddesc .. "\n" .. "In this strange world, going to bed won't skip the night, but you can skip thunderstorms."
else else
beddesc = beddesc .. "Going into bed seems to make time pass faster: The night will be skipped when you go sleep and you're alone in this world. If you're not alone, the night is skipped when all players in this world went to sleep." beddesc = beddesc .. "\n" .. "Sleeping allows you to skip the night if you're the only player in this world. If you're not alone, the night is skipped when all players in this world went to sleep. Thunderstorms can be skipped in the same manner."
end end
local default_sounds local default_sounds

@ -3,3 +3,4 @@ mcl_util?
mcl_wool? mcl_wool?
mcl_dye? mcl_dye?
mcl_tnt? mcl_tnt?
mcl_weather?

@ -5,6 +5,7 @@ local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
if enable_respawn == nil then if enable_respawn == nil then
enable_respawn = true enable_respawn = true
end end
local weather_mod = minetest.get_modpath("mcl_weather") ~= nil
-- Helper functions -- Helper functions
@ -121,9 +122,19 @@ local function update_formspecs(finished)
end end
end end
-- Public functions -- Public functions
-- Handle environment stuff related to sleeping: skip night and thunderstorm
function mcl_beds.sleep()
local storm_skipped = mcl_beds.skip_thunderstorm()
if is_night_skip_enabled() then
if not storm_skipped then
mcl_beds.skip_night()
end
mcl_beds.kick_players()
end
end
function mcl_beds.kick_players() function mcl_beds.kick_players()
for name, _ in pairs(mcl_beds.player) do for name, _ in pairs(mcl_beds.player) do
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
@ -135,7 +146,22 @@ function mcl_beds.skip_night()
minetest.set_timeofday(0.25) -- tod = 6000 minetest.set_timeofday(0.25) -- tod = 6000
end end
function mcl_beds.skip_thunderstorm()
-- Skip thunderstorm
if weather_mod and mcl_weather.get_weather() == "thunder" then
mcl_weather.change_weather("none")
-- Sleep for a half day (=minimum thunderstorm duration)
minetest.set_timeofday((minetest.get_timeofday() + 0.5) % 1)
return true
end
return false
end
function mcl_beds.on_rightclick(pos, player) function mcl_beds.on_rightclick(pos, player)
-- Anti-Inception: Don't allow to sleep while you're sleeping
if player:get_attribute("mcl_beds:sleeping") == "true" then
return
end
if minetest.get_modpath("mcl_init") then if minetest.get_modpath("mcl_init") then
local _, dim = mcl_util.y_to_layer(pos.y) local _, dim = mcl_util.y_to_layer(pos.y)
if dim == "nether" or dim == "end" then if dim == "nether" or dim == "end" then
@ -152,11 +178,11 @@ function mcl_beds.on_rightclick(pos, player)
local tod = minetest.get_timeofday() * 24000 local tod = minetest.get_timeofday() * 24000
-- Values taken from Minecraft Wiki with offset of +6000 -- Values taken from Minecraft Wiki with offset of +6000
if tod < 18541 and tod > 5458 then if tod < 18541 and tod > 5458 and (not weather_mod or (mcl_weather.get_weather() ~= "thunder")) then
if mcl_beds.player[name] then if mcl_beds.player[name] then
lay_down(player, nil, nil, false) lay_down(player, nil, nil, false)
end end
minetest.chat_send_player(name, "You can only sleep at night.") minetest.chat_send_player(name, "You can only sleep at night or during a thunderstorm.")
return return
end end
@ -178,10 +204,7 @@ function mcl_beds.on_rightclick(pos, player)
if not is_sp then if not is_sp then
update_formspecs(is_night_skip_enabled()) update_formspecs(is_night_skip_enabled())
end end
if is_night_skip_enabled() then mcl_beds.sleep()
mcl_beds.skip_night()
mcl_beds.kick_players()
end
end) end)
end end
end end
@ -207,10 +230,7 @@ minetest.register_on_leaveplayer(function(player)
if check_in_beds() then if check_in_beds() then
minetest.after(2, function() minetest.after(2, function()
update_formspecs(is_night_skip_enabled()) update_formspecs(is_night_skip_enabled())
if is_night_skip_enabled() then mcl_beds.sleep()
mcl_beds.skip_night()
mcl_beds.kick_players()
end
end) end)
end end
end) end)
@ -226,9 +246,6 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if fields.force then if fields.force then
update_formspecs(is_night_skip_enabled()) update_formspecs(is_night_skip_enabled())
if is_night_skip_enabled() then mcl_beds.sleep()
mcl_beds.skip_night()
mcl_beds.kick_players()
end
end end
end) end)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 403 B

@ -645,7 +645,7 @@ local grass_spread_randomizer = PseudoRandom(minetest.get_mapgen_setting("seed")
minetest.register_abm({ minetest.register_abm({
label = "Grass Block and Mycelium spread", label = "Grass Block and Mycelium spread",
nodenames = {"mcl_core:dirt"}, nodenames = {"mcl_core:dirt"},
neighbors = {"air", "mcl_core:dirt_with_grass", "mcl_core:mycelium"}, neighbors = {"air", "group:grass_block_no_snow", "mcl_core:mycelium"},
interval = 30, interval = 30,
chance = 20, chance = 20,
catch_up = false, catch_up = false,
@ -1190,12 +1190,22 @@ end
-- of the snowed node. -- of the snowed node.
mcl_core.register_snowed_node = function(itemstring_snowed, itemstring_clear, tiles, sounds) mcl_core.register_snowed_node = function(itemstring_snowed, itemstring_clear, tiles, sounds)
local def = table.copy(minetest.registered_nodes[itemstring_clear]) local def = table.copy(minetest.registered_nodes[itemstring_clear])
local create_doc_alias
if def.description then
create_doc_alias = true
else
create_doc_alias = false
end
-- Just some group clearing -- Just some group clearing
def.description = nil def.description = nil
def._doc_items_longdesc = nil def._doc_items_longdesc = nil
def._doc_items_usagehelp = nil def._doc_items_usagehelp = nil
def._doc_items_create_entry = false def._doc_items_create_entry = false
def.groups.not_in_creative_inventory = 1 def.groups.not_in_creative_inventory = 1
if def.groups.grass_block == 1 then
def.groups.grass_block_no_snow = nil
def.groups.grass_block_snow = 1
end
-- Enderman must never take this because this block is supposed to be always buried below snow. -- Enderman must never take this because this block is supposed to be always buried below snow.
def.groups.enderman_takable = nil def.groups.enderman_takable = nil
@ -1224,7 +1234,7 @@ mcl_core.register_snowed_node = function(itemstring_snowed, itemstring_clear, ti
-- Register stuff -- Register stuff
minetest.register_node(itemstring_snowed, def) minetest.register_node(itemstring_snowed, def)
if minetest.get_modpath("doc") then if create_doc_alias and minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", itemstring_clear, "nodes", itemstring_snowed) doc.add_entry_alias("nodes", itemstring_clear, "nodes", itemstring_snowed)
end end
end end

@ -295,6 +295,7 @@ minetest.register_node("mcl_core:diorite_smooth", {
_mcl_hardness = 1.5, _mcl_hardness = 1.5,
}) })
-- Grass Block
minetest.register_node("mcl_core:dirt_with_grass", { minetest.register_node("mcl_core:dirt_with_grass", {
description = "Grass Block", description = "Grass Block",
_doc_items_longdesc = "A grass block is dirt with a grass cover. Grass blocks are resourceful blocks which allow the growth of all sorts of plants. They can be turned into farmland with a hoe and turned into grass paths with a shovel. In light, the grass slowly spreads onto dirt nearby. Under an opaque block or a liquid, a grass block may turn back to dirt.", _doc_items_longdesc = "A grass block is dirt with a grass cover. Grass blocks are resourceful blocks which allow the growth of all sorts of plants. They can be turned into farmland with a hoe and turned into grass paths with a shovel. In light, the grass slowly spreads onto dirt nearby. Under an opaque block or a liquid, a grass block may turn back to dirt.",
@ -302,17 +303,57 @@ minetest.register_node("mcl_core:dirt_with_grass", {
tiles = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"}, tiles = {"default_grass.png", "default_dirt.png", "default_dirt.png^default_grass_side.png"},
is_ground_content = true, is_ground_content = true,
stack_max = 64, stack_max = 64,
groups = {handy=1,shovely=1, soil=1, soil_sapling=2, soil_sugarcane=1, cultivatable=2, spreading_dirt_type=1, enderman_takable=1, building_block=1}, groups = {handy=1,shovely=1, grass_block=1, grass_block_no_snow=1, soil=1, soil_sapling=2, soil_sugarcane=1, cultivatable=2, spreading_dirt_type=1, enderman_takable=1, building_block=1},
drop = 'mcl_core:dirt',
sounds = mcl_sounds.node_sound_dirt_defaults({
footstep = {name="default_grass_footstep", gain=0.4},
}),
on_construct = function(pos)
local _, dim = mcl_util.y_to_layer(pos.y)
local dry
if dim == "nether" then
dry = true
else
local found_node = minetest.find_node_near(pos, 1, {"mcl_core:dirt_with_dry_grass", "mcl_core:dirt_with_dry_grass_snow"})
if found_node then
dry = true
end
end
if dry then
minetest.set_node(pos, {name="mcl_core:dirt_with_dry_grass"})
end
return mcl_core.on_snowable_construct(pos)
end,
_mcl_snowed = "mcl_core:dirt_with_grass_snow",
_mcl_grass_palette_index = 0,
_mcl_blast_resistance = 3,
_mcl_hardness = 0.6,
})
mcl_core.register_snowed_node("mcl_core:dirt_with_grass_snow", "mcl_core:dirt_with_grass")
-- Grass Block variant for dry biomes
minetest.register_node("mcl_core:dirt_with_dry_grass", {
_doc_items_create_entry = false,
tiles = {"default_dry_grass.png", "default_dirt.png", "default_dirt.png^default_dry_grass_side.png"},
is_ground_content = true,
stack_max = 64,
groups = {handy=1,shovely=1, grass_block=1, grass_block_no_snow=1, soil=1, soil_sapling=2, soil_sugarcane=1, cultivatable=2, spreading_dirt_type=1, enderman_takable=1, building_block=1, not_in_creative_inventory=1},
drop = 'mcl_core:dirt', drop = 'mcl_core:dirt',
sounds = mcl_sounds.node_sound_dirt_defaults({ sounds = mcl_sounds.node_sound_dirt_defaults({
footstep = {name="default_grass_footstep", gain=0.4}, footstep = {name="default_grass_footstep", gain=0.4},
}), }),
on_construct = mcl_core.on_snowable_construct, on_construct = mcl_core.on_snowable_construct,
_mcl_snowed = "mcl_core:dirt_with_grass_snow", _mcl_snowed = "mcl_core:dirt_with_dry_grass_snow",
_mcl_grass_palette_index = 1,
_mcl_blast_resistance = 3, _mcl_blast_resistance = 3,
_mcl_hardness = 0.6, _mcl_hardness = 0.6,
}) })
mcl_core.register_snowed_node("mcl_core:dirt_with_grass_snow", "mcl_core:dirt_with_grass") mcl_core.register_snowed_node("mcl_core:dirt_with_dry_grass_snow", "mcl_core:dirt_with_dry_grass")
if minetest.get_modpath("doc") then
doc.add_entry_alias("nodes", "mcl_core:dirt_with_grass", "nodes", "mcl_core:dirt_with_dry_grass")
doc.add_entry_alias("nodes", "mcl_core:dirt_with_grass", "nodes", "mcl_core:dirt_with_dry_grass_snow")
end
minetest.register_node("mcl_core:grass_path", { minetest.register_node("mcl_core:grass_path", {
tiles = {"mcl_core_grass_path_top.png", "default_dirt.png", "mcl_core_grass_path_side.png"}, tiles = {"mcl_core_grass_path_top.png", "default_dirt.png", "mcl_core_grass_path_side.png"},

@ -89,7 +89,7 @@ minetest.register_node("mcl_core:deadbush", {
walkable = false, walkable = false,
stack_max = 64, stack_max = 64,
buildable_to = true, buildable_to = true,
groups = {dig_immediate=3, flammable=3,attached_node=1,plant=1,non_mycelium_plant=1,dig_by_water=1,destroy_by_lava_flow=1,deco_block=1}, groups = {handy=1,shearsy=1, flammable=3,attached_node=1,plant=1,non_mycelium_plant=1,dig_by_water=1,destroy_by_lava_flow=1,deco_block=1},
drop = { drop = {
max_items = 1, max_items = 1,
items = { items = {
@ -107,7 +107,7 @@ minetest.register_node("mcl_core:deadbush", {
sounds = mcl_sounds.node_sound_leaves_defaults(), sounds = mcl_sounds.node_sound_leaves_defaults(),
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = {-6/16, -8/16, -6/16, 6/16, 8/16, 6/16}, fixed = {-5/16, -8/16, -5/16, 5/16, 1/16, 5/16},
}, },
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_mcl_hardness = 0, _mcl_hardness = 0,

@ -112,7 +112,7 @@ local register_sapling = function(subname, description, longdesc, texture, selbo
local node_below = minetest.get_node_or_nil({x=pos.x,y=pos.y-1,z=pos.z}) local node_below = minetest.get_node_or_nil({x=pos.x,y=pos.y-1,z=pos.z})
if not node_below then return false end if not node_below then return false end
local nn = node_below.name local nn = node_below.name
return (nn=="mcl_core:dirt_with_grass" or nn=="mcl_core:dirt_with_grass_snow" or return ((minetest.get_item_group(nn, "grass_block") == 1) or
nn=="mcl_core:podzol" or nn=="mcl_core:podzol_snow" or nn=="mcl_core:podzol" or nn=="mcl_core:podzol_snow" or
nn=="mcl_core:dirt") nn=="mcl_core:dirt")
end), end),
@ -165,12 +165,12 @@ register_wooden_planks("acaciawood", "Acacia Wood Planks", {"default_acacia_wood
register_wooden_planks("birchwood", "Birch Wood Planks", {"mcl_core_planks_birch.png"}) register_wooden_planks("birchwood", "Birch Wood Planks", {"mcl_core_planks_birch.png"})
register_sapling("sapling", "Oak Sapling", "When placed on soil (such as dirt) and exposed to light, an oak sapling will grow into an oak after some time.", "default_sapling.png", {-6/16, -0.5, -6/16, 6/16, 0.5, 6/16}) register_sapling("sapling", "Oak Sapling", "When placed on soil (such as dirt) and exposed to light, an oak sapling will grow into an oak after some time.", "default_sapling.png", {-5/16, -0.5, -5/16, 5/16, 0.5, 5/16})
register_sapling("darksapling", "Dark Oak Sapling", "Dark oak saplings can grow into dark oaks, but only in groups. A lonely dark oak sapling won't grow. A group of four dark oak saplings grows into a dark oak after some time when they are placed on soil (such as dirt) in a 2×2 square and exposed to light.", "mcl_core_sapling_big_oak.png", {-5.5/16, -0.5, -5.5/16, 5.5/16, 0.5, 5.5/16}) register_sapling("darksapling", "Dark Oak Sapling", "Dark oak saplings can grow into dark oaks, but only in groups. A lonely dark oak sapling won't grow. A group of four dark oak saplings grows into a dark oak after some time when they are placed on soil (such as dirt) in a 2×2 square and exposed to light.", "mcl_core_sapling_big_oak.png", {-5/16, -0.5, -5/16, 5/16, 7/16, 5/16})
register_sapling("junglesapling", "Jungle Sapling", "When placed on soil (such as dirt) and exposed to light, a jungle sapling will grow into a jungle tree after some time. When there are 4 jungle saplings in a 2×2 square, they will grow to a huge jungle tree.", "default_junglesapling.png", {-4/16, -0.5, -4/16, 4/16, 0.5, 4/16}) register_sapling("junglesapling", "Jungle Sapling", "When placed on soil (such as dirt) and exposed to light, a jungle sapling will grow into a jungle tree after some time. When there are 4 jungle saplings in a 2×2 square, they will grow to a huge jungle tree.", "default_junglesapling.png", {-5/16, -0.5, -5/16, 5/16, 0.5, 5/16})
register_sapling("acaciasapling", "Acacia Sapling", "When placed on soil (such as dirt) and exposed to light, an acacia sapling will grow into an acacia after some time.", "default_acacia_sapling.png", {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}) register_sapling("acaciasapling", "Acacia Sapling", "When placed on soil (such as dirt) and exposed to light, an acacia sapling will grow into an acacia after some time.", "default_acacia_sapling.png", {-5/16, -0.5, -5/16, 5/16, 4/16, 5/16})
register_sapling("sprucesapling", "Spruce Sapling", "When placed on soil (such as dirt) and exposed to light, a spruce sapling will grow into a spruce after some time. When there are 4 spruce saplings in a 2×2 square, they will grow to a huge spruce.", "mcl_core_sapling_spruce.png", {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}) register_sapling("sprucesapling", "Spruce Sapling", "When placed on soil (such as dirt) and exposed to light, a spruce sapling will grow into a spruce after some time. When there are 4 spruce saplings in a 2×2 square, they will grow to a huge spruce.", "mcl_core_sapling_spruce.png", {-4/16, -0.5, -4/16, 4/16, 0.5, 4/16})
register_sapling("birchsapling", "Birch Sapling", "When placed on soil (such as dirt) and exposed to light, a birch sapling will grow into a birch after some time.", "mcl_core_sapling_birch.png", {-6/16, -0.5, -6/16, 6/16, 0.5, 6/16}) register_sapling("birchsapling", "Birch Sapling", "When placed on soil (such as dirt) and exposed to light, a birch sapling will grow into a birch after some time.", "mcl_core_sapling_birch.png", {-4/16, -0.5, -4/16, 4/16, 0.5, 4/16})
register_leaves("leaves", "Oak Leaves", "Oak leaves are grown from oak trees.", {"default_leaves.png"}, "mcl_core:sapling", 20, "mcl_core:apple", 200) register_leaves("leaves", "Oak Leaves", "Oak leaves are grown from oak trees.", {"default_leaves.png"}, "mcl_core:sapling", 20, "mcl_core:apple", 200)

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 B

@ -205,7 +205,7 @@ function mcl_doors:register_door(name, def)
end end
minetest.register_node(name.."_b_1", { minetest.register_node(name.."_b_1", {
tiles = {tt[2].."^[transformFY", tt[2], tb[2].."^[transformFX", tb[2], tb[1], tb[1].."^[transformFX"}, tiles = {"blank.png", tt[2].."^[transformFXR90", tb[2], tb[2].."^[transformFX", tb[1], tb[1].."^[transformFX"},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
sunlight_propagates = true, sunlight_propagates = true,
@ -252,7 +252,7 @@ function mcl_doors:register_door(name, def)
end end
minetest.register_node(name.."_t_1", { minetest.register_node(name.."_t_1", {
tiles = {tt[2].."^[transformFY", tt[2], tt[2].."^[transformFX", tt[2], tt[1], tt[1].."^[transformFX"}, tiles = {tt[2].."^[transformR90", "blank.png", tt[2], tt[2].."^[transformFX", tt[1], tt[1].."^[transformFX"},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
sunlight_propagates = true, sunlight_propagates = true,
@ -295,7 +295,7 @@ function mcl_doors:register_door(name, def)
end end
minetest.register_node(name.."_b_2", { minetest.register_node(name.."_b_2", {
tiles = {tt[2].."^[transformFY", tt[2], tb[2].."^[transformFX", tb[2], tb[1].."^[transformFX", tb[1]}, tiles = {"blank.png", tt[2].."^[transformFXR90", tb[2].."^[transformI", tb[2].."^[transformFX", tb[1].."^[transformFX", tb[1]},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
sunlight_propagates = true, sunlight_propagates = true,
@ -342,7 +342,7 @@ function mcl_doors:register_door(name, def)
end end
minetest.register_node(name.."_t_2", { minetest.register_node(name.."_t_2", {
tiles = {tt[2].."^[transformFY", tt[2], tt[2].."^[transformFX", tt[2], tt[1].."^[transformFX", tt[1]}, tiles = {tt[2].."^[transformR90", "blank.png", tt[2].."^[transformI", tt[2].."^[transformFX", tt[1].."^[transformFX", tt[1]},
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
sunlight_propagates = true, sunlight_propagates = true,

@ -1,3 +1,20 @@
-- Wrapper around mintest.pointed_thing_to_face_pos.
local function get_fpos(placer, pointed_thing)
local fpos
-- Workaround: minetest.pointed_thing_to_face_pos crashes in MT 0.4.16 if
-- pointed_thing.under and pointed_thing.above are equal
-- FIXME: Remove this when MT got fixed.
if not vector.equals(pointed_thing.under, pointed_thing.above) then
-- The happy case: Everything is normal
local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
fpos = finepos.y % 1
else
-- Fallback if both above and under are equal
fpos = 0
end
return fpos
end
---- Trapdoor ---- ---- Trapdoor ----
function mcl_doors:register_trapdoor(name, def) function mcl_doors:register_trapdoor(name, def)
@ -91,9 +108,7 @@ function mcl_doors:register_trapdoor(name, def)
param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos))
end end
local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) local fpos = get_fpos(placer, pointed_thing)
local fpos = finepos.y % 1
local origname = itemstack:get_name() local origname = itemstack:get_name()
if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5)

Some files were not shown because too many files have changed in this diff Show More