2023-02-01 22:44:42 -06:00
--[[
Everness . Never ending discovery in Everness mapgen .
2024-01-03 13:50:17 -06:00
Copyright ( C ) 2024 SaKeL
2023-02-01 22:44:42 -06:00
This library 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 2.1 of the License , or ( at your option ) any later version .
This library 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 .
--]]
2023-03-30 16:05:46 -05:00
local S = minetest.get_translator ( minetest.get_current_modname ( ) )
2024-01-27 16:27:14 -06:00
local rand_global = PcgRandom ( tonumber ( tostring ( os.time ( ) ) : reverse ( ) : sub ( 1 , 9 ) ) )
2023-03-30 16:05:46 -05:00
2023-02-01 22:44:42 -06:00
--- Base class
---@class Everness
Everness = {
bamboo = {
-- based on height
growth_stages = {
--height
[ 1 ] = {
-- next plant
{ name = ' everness:bamboo_1 ' } ,
{ name = ' everness:bamboo_2 ' } ,
} ,
[ 2 ] = {
{ name = ' everness:bamboo_1 ' } ,
{ name = ' everness:bamboo_2 ' } ,
{ name = ' everness:bamboo_2 ' } ,
} ,
[ 3 ] = {
{ name = ' everness:bamboo_3 ' } ,
{ name = ' everness:bamboo_4 ' } ,
{ name = ' everness:bamboo_4 ' } ,
{ name = ' everness:bamboo_5 ' } ,
} ,
[ 4 ] = {
{ name = ' everness:bamboo_3 ' } ,
{ name = ' everness:bamboo_3 ' } ,
{ name = ' everness:bamboo_4 ' } ,
{ name = ' everness:bamboo_5 ' } ,
{ name = ' everness:bamboo_5 ' } ,
} ,
} ,
top_leaves_schem = {
{ name = ' everness:bamboo_4 ' } ,
{ name = ' everness:bamboo_5 ' } ,
{ name = ' everness:bamboo_5 ' } ,
}
} ,
loot_chest = {
2023-03-30 22:30:58 -05:00
default = { } ,
2023-02-01 22:44:42 -06:00
} ,
2023-02-20 10:24:04 -06:00
settings = {
biomes = {
everness_coral_forest = {
enabled = minetest.settings : get_bool ( ' everness_coral_forest ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_coral_forest_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_coral_forest_y_min ' ) ) or 6 ,
} ,
everness_coral_forest_dunes = {
enabled = minetest.settings : get_bool ( ' everness_coral_forest_dunes ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_coral_forest_dunes_y_max ' ) ) or 5 ,
y_min = tonumber ( minetest.settings : get ( ' everness_coral_forest_dunes_y_min ' ) ) or 4 ,
} ,
everness_coral_forest_ocean = {
enabled = minetest.settings : get_bool ( ' everness_coral_forest_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_coral_forest_ocean_y_max ' ) ) or 3 ,
2023-03-18 11:24:42 -05:00
y_min = tonumber ( minetest.settings : get ( ' everness_coral_forest_ocean_y_min ' ) ) or - 10 ,
} ,
everness_coral_forest_deep_ocean = {
enabled = minetest.settings : get_bool ( ' everness_coral_forest_deep_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_coral_forest_deep_ocean_y_max ' ) ) or - 11 ,
y_min = tonumber ( minetest.settings : get ( ' everness_coral_forest_deep_ocean_y_min ' ) ) or - 255 ,
2023-02-20 10:24:04 -06:00
} ,
everness_coral_forest_under = {
enabled = minetest.settings : get_bool ( ' everness_coral_forest_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_coral_forest_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_coral_forest_under_y_min ' ) ) or - 31000 ,
} ,
everness_frosted_icesheet = {
enabled = minetest.settings : get_bool ( ' everness_frosted_icesheet ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_y_min ' ) ) or - 8 ,
} ,
everness_frosted_icesheet_ocean = {
enabled = minetest.settings : get_bool ( ' everness_frosted_icesheet_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_ocean_y_max ' ) ) or - 9 ,
y_min = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_ocean_y_min ' ) ) or - 255 ,
} ,
everness_frosted_icesheet_under = {
enabled = minetest.settings : get_bool ( ' everness_frosted_icesheet_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_frosted_icesheet_under_y_min ' ) ) or - 31000 ,
} ,
everness_cursed_lands = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_y_min ' ) ) or 6 ,
} ,
everness_cursed_lands_dunes = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands_dunes ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_dunes_y_max ' ) ) or 5 ,
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_dunes_y_min ' ) ) or 1 ,
} ,
everness_cursed_lands_swamp = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands_swamp ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_swamp_y_max ' ) ) or 0 ,
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_swamp_y_min ' ) ) or - 1 ,
} ,
everness_cursed_lands_ocean = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_ocean_y_max ' ) ) or - 2 ,
2023-03-18 11:24:42 -05:00
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_ocean_y_min ' ) ) or - 10 ,
} ,
everness_cursed_lands_deep_ocean = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_ocean_y_max ' ) ) or - 11 ,
2023-02-20 10:24:04 -06:00
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_ocean_y_min ' ) ) or - 255 ,
} ,
everness_cursed_lands_under = {
enabled = minetest.settings : get_bool ( ' everness_cursed_lands_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_cursed_lands_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_cursed_lands_under_y_min ' ) ) or - 31000 ,
} ,
everness_crystal_forest = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_y_min ' ) ) or 6 ,
} ,
everness_crystal_forest_dunes = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest_dunes ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_dunes_y_max ' ) ) or 5 ,
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_dunes_y_min ' ) ) or 1 ,
} ,
everness_crystal_forest_shore = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest_shore ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_shore_y_max ' ) ) or 0 ,
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_shore_y_min ' ) ) or - 1 ,
} ,
everness_crystal_forest_ocean = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_ocean_y_max ' ) ) or - 2 ,
2023-03-18 11:24:42 -05:00
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_ocean_y_min ' ) ) or - 10 ,
} ,
everness_crystal_forest_deep_ocean = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest_deep_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_deep_ocean_y_max ' ) ) or - 11 ,
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_deep_ocean_y_min ' ) ) or - 255 ,
2023-02-20 10:24:04 -06:00
} ,
everness_crystal_forest_under = {
enabled = minetest.settings : get_bool ( ' everness_crystal_forest_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_crystal_forest_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_crystal_forest_under_y_min ' ) ) or - 31000 ,
} ,
everness_bamboo_forest = {
enabled = minetest.settings : get_bool ( ' everness_bamboo_forest ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_bamboo_forest_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_bamboo_forest_y_min ' ) ) or 1 ,
} ,
everness_bamboo_forest_under = {
enabled = minetest.settings : get_bool ( ' everness_bamboo_forest_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_bamboo_forest_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_bamboo_forest_under_y_min ' ) ) or - 31000 ,
} ,
everness_forsaken_desert = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_desert ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_y_min ' ) ) or 4 ,
} ,
everness_forsaken_desert_ocean = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_desert_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_ocean_y_max ' ) ) or 3 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_ocean_y_min ' ) ) or - 8 ,
} ,
everness_forsaken_desert_under = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_desert_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_desert_under_y_min ' ) ) or - 31000 ,
} ,
everness_baobab_savanna = {
enabled = minetest.settings : get_bool ( ' everness_baobab_savanna ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_baobab_savanna_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_baobab_savanna_y_min ' ) ) or 1 ,
} ,
everness_forsaken_tundra = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_tundra ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_y_min ' ) ) or 2 ,
} ,
everness_forsaken_tundra_beach = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_tundra_beach ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_beach_y_max ' ) ) or 1 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_beach_y_min ' ) ) or - 3 ,
} ,
everness_forsaken_tundra_ocean = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_tundra_ocean ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_ocean_y_max ' ) ) or - 4 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_ocean_y_min ' ) ) or - 255 ,
} ,
everness_forsaken_tundra_under = {
enabled = minetest.settings : get_bool ( ' everness_forsaken_tundra_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_forsaken_tundra_under_y_min ' ) ) or - 31000 ,
} ,
2024-01-10 22:16:52 -06:00
everness_mineral_waters = {
enabled = minetest.settings : get_bool ( ' everness_mineral_waters ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_mineral_waters_y_max ' ) ) or 31000 ,
y_min = tonumber ( minetest.settings : get ( ' everness_mineral_waters_y_min ' ) ) or 1 ,
} ,
everness_mineral_waters_under = {
enabled = minetest.settings : get_bool ( ' everness_mineral_waters_under ' , true ) ,
y_max = tonumber ( minetest.settings : get ( ' everness_mineral_waters_under_y_max ' ) ) or - 256 ,
y_min = tonumber ( minetest.settings : get ( ' everness_mineral_waters_under_y_min ' ) ) or - 31000 ,
} ,
2023-02-22 19:56:27 -06:00
} ,
features = {
everness_feature_sneak_pickup = minetest.settings : get_bool ( ' everness_feature_sneak_pickup ' , true ) ,
2023-02-25 21:35:35 -06:00
everness_feature_skybox = minetest.settings : get_bool ( ' everness_feature_skybox ' , true ) ,
2023-02-20 10:24:04 -06:00
}
} ,
2024-01-24 09:24:34 -06:00
hammer_cid_data = { } ,
colors = {
brown = ' #DEB887 ' ,
2024-01-25 14:31:55 -06:00
} ,
registered_nodes = { } ,
registered_tools = { } ,
registered_abms = { } ,
registered_lbms = { } ,
registered_craftitems = { } ,
registered_biomes = { } ,
registered_decorations = { } ,
2024-02-07 07:47:36 -06:00
registered_ores = { } ,
on_generated_queue = { }
2023-02-01 22:44:42 -06:00
}
2023-02-15 15:40:37 -06:00
function Everness . grow_cactus ( self , pos , node , params )
2023-03-31 12:31:18 -05:00
local node_copy = table.copy ( node )
2023-02-01 22:44:42 -06:00
if node.param2 >= 4 then
return
end
pos.y = pos.y - 1
2023-03-31 12:31:18 -05:00
if minetest.get_item_group ( minetest.get_node ( pos ) . name , ' sand ' ) == 0
and minetest.get_item_group ( minetest.get_node ( pos ) . name , ' everness_sand ' ) == 0
2023-02-15 15:40:37 -06:00
then
2023-02-01 22:44:42 -06:00
return
end
pos.y = pos.y + 1
local height = 0
2023-02-15 15:40:37 -06:00
while ( node.name == ' everness:cactus_orange ' or node.name == ' everness:cactus_blue ' ) and height < 5 do
2023-02-01 22:44:42 -06:00
height = height + 1
pos.y = pos.y + 1
node = minetest.get_node ( pos )
end
if height == 5 or node.name ~= ' air ' then
return
end
if minetest.get_node_light ( pos ) < 13 then
return
end
2023-03-31 12:31:18 -05:00
minetest.set_node ( pos , { name = node_copy.name } )
2023-02-01 22:44:42 -06:00
return true
end
function Everness . emerge_area ( self , blockpos , action , calls_remaining , param )
if not param.total then
param.total = calls_remaining + 1
param.current = 0
end
param.current = param.current + 1
if param.total == param.current then
param.callback ( param.data )
end
end
-- how often node timers for plants will tick, +/- some random value
function Everness . tick_vine ( self , pos )
minetest.get_node_timer ( pos ) : start ( math.random ( 5 , 10 ) )
end
-- how often a growth failure tick is retried (e.g. too dark)
function Everness . tick_vine_again ( self , pos )
minetest.get_node_timer ( pos ) : start ( math.random ( 40 , 80 ) )
end
-- how often node timers for plants will tick, +/- some random value
function Everness . tick_sulfur_stone ( self , pos )
minetest.get_node_timer ( pos ) : start ( math.random ( 5 , 10 ) )
end
-- how often a growth failure tick is retried (e.g. too dark)
function Everness . tick_sulfur_stone_again ( self , pos )
minetest.get_node_timer ( pos ) : start ( math.random ( 40 , 80 ) )
end
2024-01-29 12:08:45 -06:00
-- Grows vines
-- @param pos {vector}
2023-02-01 22:44:42 -06:00
function Everness . grow_vine ( self , pos , elapsed , params )
local node = minetest.get_node ( pos )
local pos_under = vector.new ( pos.x , pos.y - 1 , pos.z )
local node_under = minetest.get_node ( pos_under )
local node_names = params.node_names
local end_node_name = params.end_node_name
local end_node_param2 = params.end_node_param2
-- get length
local length = 0
local temp_node = node
while minetest.get_item_group ( temp_node.name , ' vine ' ) > 0 and length < 16 do
length = length + 1
temp_node = minetest.get_node ( vector.new ( pos.x , pos.y + length , pos.z ) )
end
-- stop growing - random height between 12 - 16 nodes
if length > 11 and length < 16 then
if math.random ( 1 , 3 ) == 2 then
return
end
end
if length >= 16 then
return
end
if minetest.get_item_group ( node_under.name , ' vine ' ) > 0 then
-- stop timer for gown vine
return
end
if node_under.name ~= ' air ' then
Everness : tick_vine_again ( pos )
return
end
local new_node_name = node_names [ math.random ( 1 , # node_names ) ]
2024-01-29 12:08:45 -06:00
minetest.set_node ( pos , { name = new_node_name , param2 = new_node_name.param2 or 0 } )
2023-02-01 22:44:42 -06:00
-- last hanging vine
minetest.set_node ( pos_under , { name = end_node_name , param2 = end_node_param2 and end_node_param2 or node.param2 } )
Everness : tick_vine ( pos_under )
end
--
-- Sounds
--
2024-01-19 12:03:26 -06:00
function Everness . node_sound_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' ' , gain = 1.0 }
table.dug = table.dug or { name = ' everness_stone_hit ' , gain = 1.0 }
table.place = table.place or { name = ' everness_stone_dug ' , gain = 0.6 }
return table
end
2023-02-01 22:44:42 -06:00
function Everness . node_sound_frosted_snow_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_frosted_snow_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_frosted_snow_hit ' , gain = 0.2 }
table.dug = table.dug or { name = ' everness_frosted_snow_footstep ' , gain = 0.3 }
table.place = table.place or { name = ' everness_frosted_snow_place ' , gain = 0.25 }
2023-02-01 22:44:42 -06:00
return table
end
function Everness . node_sound_crystal_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_crystal_chime ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_crystal_chime ' , gain = 0.3 }
table.dug = table.dug or { name = ' everness_stone_footstep ' , gain = 0.3 }
table.place = table.place or { name = ' everness_crystal_chime ' , gain = 1.0 }
2023-02-01 22:44:42 -06:00
return table
end
function Everness . node_sound_bamboo_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_bamboo_hit ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_bamboo_hit ' , gain = 0.3 }
table.dug = table.dug or { name = ' everness_bamboo_dug ' , gain = 0.1 }
table.place = table.place or { name = ' everness_bamboo_hit ' , gain = 1.0 }
2023-02-01 22:44:42 -06:00
return table
end
2023-02-15 15:40:37 -06:00
function Everness . node_sound_mud_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_mud_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_mud_footstep ' , gain = 0.3 }
table.dug = table.dug or { name = ' everness_mud_footstep ' , gain = 0.1 }
table.place = table.place or { name = ' everness_mud_footstep ' , gain = 1.0 }
2023-02-15 15:40:37 -06:00
return table
end
2023-02-28 14:30:46 -06:00
2023-03-18 11:24:42 -05:00
function Everness . node_sound_grass_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_grass_footstep ' , gain = 0.4 }
table.dig = table.dig or { name = ' everness_grass_hit ' , gain = 1.2 }
table.dug = table.dug or { name = ' everness_dirt_hit ' , gain = 1.0 }
table.place = table.place or { name = ' everness_dirt_hit ' , gain = 1.0 }
2023-03-18 11:24:42 -05:00
return table
end
function Everness . node_sound_dirt_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_dirt_footstep ' , gain = 0.15 }
table.dig = table.dig or { name = ' everness_dirt_hit ' , gain = 0.4 }
table.dug = table.dug or { name = ' everness_dirt_hit ' , gain = 1.0 }
table.place = table.place or { name = ' everness_dirt_hit ' , gain = 1.0 }
2023-03-18 11:24:42 -05:00
return table
end
function Everness . node_sound_ice_defaults ( table )
table = table or { }
2023-03-24 21:36:07 -05:00
table.footstep = table.footstep or { name = ' everness_ice_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_ice_hit ' , gain = 0.4 }
table.dug = table.dug or { name = ' everness_ice_hit ' , gain = 1.0 }
table.place = table.place or { name = ' everness_ice_hit ' , gain = 1.0 }
return table
end
function Everness . node_sound_stone_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_stone_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_stone_hit ' , gain = 1.0 }
table.dug = table.dug or { name = ' everness_stone_dug ' , gain = 0.6 }
table.place = table.place or { name = ' everness_stone_place ' , gain = 1.0 }
return table
end
function Everness . node_sound_leaves_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_leaves_footstep ' , gain = 0.1 }
table.dig = table.dig or { name = ' everness_leaves_hit ' , gain = 0.25 }
table.dug = table.dug or { name = ' everness_leaves_dug ' , gain = 0.5 }
table.place = table.place or { name = ' everness_leaves_place ' , gain = 0.4 }
return table
end
function Everness . node_sound_wood_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_wood_footstep ' , gain = 0.15 }
2023-12-28 11:16:37 -06:00
table.dig = table.dig or { name = ' everness_wood_hit ' , gain = 0.8 }
2023-03-24 21:36:07 -05:00
table.dug = table.dug or { name = ' everness_wood_place ' , gain = 0.1 }
table.place = table.place or { name = ' everness_wood_place ' , gain = 0.15 }
return table
end
function Everness . node_sound_sand_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_sand_footstep ' , gain = 0.1 }
table.dig = table.dig or { name = ' everness_sand_hit ' , gain = 0.5 }
table.dug = table.dug or { name = ' everness_sand_dug ' , gain = 0.1 }
table.place = table.place or { name = ' everness_sand_place ' , gain = 0.15 }
return table
end
function Everness . node_sound_metal_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_metal_footstep ' , gain = 0.1 }
table.dig = table.dig or { name = ' everness_metal_hit ' , gain = 0.5 }
table.dug = table.dug or { name = ' everness_metal_dug ' , gain = 0.1 }
table.place = table.place or { name = ' everness_metal_place ' , gain = 0.15 }
return table
end
function Everness . node_sound_glass_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_glass_footstep ' , gain = 0.02 }
table.dig = table.dig or { name = ' everness_glass_footstep ' , gain = 0.05 }
table.dug = table.dug or { name = ' everness_glass_dug ' , gain = 0.4 }
table.place = table.place or { name = ' everness_glass_place ' , gain = 0.2 }
return table
end
function Everness . node_sound_thin_glass_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_thin_glass_footstep ' , gain = 0.3 }
table.dig = table.dig or { name = ' everness_thin_glass_footstep ' , gain = 0.5 }
table.dug = table.dug or { name = ' everness_break_thin_glass ' , gain = 1.0 }
table.place = table.place or { name = ' everness_glass_place ' , gain = 0.2 }
return table
end
function Everness . node_sound_snow_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_snow_footstep ' , gain = 0.1 }
table.dig = table.dig or { name = ' everness_snow_hit ' , gain = 0.2 }
table.dug = table.dug or { name = ' everness_snow_footstep ' , gain = 0.2 }
table.place = table.place or { name = ' everness_snow_place ' , gain = 0.3 }
2023-03-18 11:24:42 -05:00
return table
end
2024-01-03 11:33:58 -06:00
function Everness . node_sound_gravel_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_gravel_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_gravel_hit ' , gain = 1.0 }
table.dug = table.dug or { name = ' everness_gravel_dug ' , gain = 0.6 }
table.place = table.place or { name = ' everness_gravel_place ' , gain = 1.0 }
return table
end
2024-01-19 12:03:26 -06:00
function Everness . node_sound_ceramic_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_ceramic_footstep ' , gain = 0.2 }
table.dig = table.dig or { name = ' everness_ceramic_hit ' , gain = 1.0 }
table.dug = table.dug or { name = ' everness_ceramic_dug ' , gain = 1.0 }
table.place = table.place or { name = ' everness_ceramic_place ' , gain = 1.0 }
return table
end
function Everness . node_sound_water_defaults ( table )
table = table or { }
table.footstep = table.footstep or { name = ' everness_water_footstep ' , gain = 0.05 }
Everness.node_sound_defaults ( table )
return table
end
2023-02-28 14:30:46 -06:00
--
-- Forsted Cave Icicles
--
function Everness . stack_icicle_recursive ( node , pos_node , incrementer , pos_marker , direction )
local nb = node
local pos = pos_node
local inc = incrementer
local m_pos = pos_marker
while nb.name == ' air ' or nb.name == ' ignore ' do
if nb.name == ' ignore ' then
Everness.emerge_icicle_area_recursive ( pos , inc , m_pos , direction )
break
else
minetest.set_node ( pos , { name = ' everness:frosted_cave_ice_illuminating ' } )
-- Shift 1 down
inc = inc + 1
local y_offset = ( direction == ' down ' ) and ( m_pos.y - inc ) or ( m_pos.y + inc )
pos = vector.new ( m_pos.x , y_offset , m_pos.z )
nb = minetest.get_node ( pos )
end
end
end
function Everness . emerge_icicle_area_recursive ( pos_node , incrementer , pos_marker , direction )
local y_offset = ( direction == ' down ' ) and ( pos_node.y - 16 ) or ( pos_node.y + 16 )
minetest.emerge_area (
vector.new ( pos_node.x - 1 , pos_node.y , pos_node.z - 1 ) ,
vector.new ( pos_node.x + 1 , y_offset , pos_node.z + 1 ) ,
function ( blockpos , action , calls_remaining , param )
Everness : emerge_area ( blockpos , action , calls_remaining , param )
end ,
{
callback = function ( data )
local incrementer_cllbck = data.incrementer
local pos_node_cllbck = data.pos_node
local node_cllbck = minetest.get_node ( pos_node_cllbck )
Everness.stack_icicle_recursive ( node_cllbck , pos_node_cllbck , incrementer_cllbck , pos_marker , direction )
end ,
data = {
incrementer = incrementer ,
pos_node = pos_node
}
}
)
end
2023-03-18 11:24:42 -05:00
function Everness . use_shell_of_underwater_breathing ( self , itemstack , user , pointed_thing )
if not user then
return
end
local pos_player = user : get_pos ( )
if pointed_thing.type == ' node ' then
local pos_pt = minetest.get_pointed_thing_position ( pointed_thing )
if not pos_pt then
return itemstack
end
local pointed_node = minetest.get_node ( pos_pt )
local pointed_node_def = minetest.registered_nodes [ pointed_node.name ]
if not pointed_node or not pointed_node_def then
return itemstack
end
if pointed_node_def.on_rightclick then
return pointed_node_def.on_rightclick ( pos_pt , pointed_node , user , itemstack , pointed_thing )
end
end
local node_head = minetest.get_node (
vector.new (
math.floor ( pos_player.x + 0.5 ) ,
math.ceil ( pos_player.y + 1 ) ,
math.floor ( pos_player.z + 0.5 )
)
)
local breath = user : get_breath ( )
if minetest.get_item_group ( node_head.name , ' water ' ) > 0 and breath < 9 then
-- Under water
user : set_breath ( 9 )
if not minetest.settings : get_bool ( ' creative_mode ' )
or not minetest.check_player_privs ( user : get_player_name ( ) , { creative = true } )
then
2024-01-01 09:29:50 -06:00
local wear_to_add = 65535 / 20
if itemstack : get_wear ( ) + wear_to_add > 65535 then
local itemstack_def = itemstack : get_definition ( )
-- Break tool
minetest.sound_play ( itemstack_def.sound . breaks , {
pos = pos_player ,
gain = 0.5
} , true )
end
itemstack : add_wear ( wear_to_add )
2023-03-18 11:24:42 -05:00
end
minetest.sound_play ( ' everness_underwater_bubbles ' , {
object = user ,
gain = 1.0 ,
max_hear_distance = 16
} )
minetest.add_particlespawner ( {
2024-01-01 09:29:50 -06:00
amount = 40 ,
2023-03-18 11:24:42 -05:00
time = 0.1 ,
pos = {
min = vector.new ( pos_player.x - 0.25 , pos_player.y + 1.25 , pos_player.z - 0.25 ) ,
max = vector.new ( pos_player.x + 0.25 , pos_player.y + 1.5 , pos_player.z + 0.25 )
} ,
vel = {
min = vector.new ( - 0.5 , 0 , - 0.5 ) ,
max = vector.new ( 0.5 , 0 , 0.5 )
} ,
acc = {
min = vector.new ( - 0.5 , 4 , - 0.5 ) ,
max = vector.new ( 0.5 , 1 , 0.5 ) ,
} ,
exptime = {
min = 1 ,
max = 2
} ,
size = {
min = 0.5 ,
max = 2
} ,
texture = {
name = ' everness_bubble.png ' ,
alpha_tween = {
1 , 0 ,
start = 0.75
}
}
} )
end
return itemstack
end
2023-03-24 21:36:07 -05:00
2023-03-30 16:05:46 -05:00
--
-- Sapling 'on place' function to check protection of node and resulting tree volume
-- copy from MTG
--
2023-03-24 21:36:07 -05:00
function Everness . sapling_on_place ( self , itemstack , placer , pointed_thing , props )
2023-03-29 14:35:48 -05:00
if minetest.get_modpath ( ' mcl_util ' ) and minetest.global_exists ( ' mcl_util ' ) then
local on_place_func = mcl_util.generate_on_place_plant_function ( function ( pos , node )
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
local nn = node_below.name
return minetest.get_item_group ( nn , ' grass_block ' ) == 1
2024-01-19 14:41:16 -06:00
or ( nn == ' everness:mineral_sand ' and itemstack : get_name ( ) == ' everness:palm_tree_sapling ' )
2023-03-29 14:35:48 -05:00
or nn == ' mcl_core:podzol '
or nn == ' mcl_core:podzol_snow '
or nn == ' mcl_core:dirt '
or nn == ' mcl_core:mycelium '
or nn == ' mcl_core:coarse_dirt '
end )
return on_place_func ( itemstack , placer , pointed_thing )
else
local _props = props or { }
local sapling_name = _props.sapling_name
-- minp, maxp to be checked, relative to sapling pos
-- minp_relative.y = 1 because sapling pos has been checked
local minp_relative = _props.minp_relative
local maxp_relative = _props.maxp_relative
-- maximum interval of interior volume check
local interval = _props.interval
-- Position of sapling
local pos = pointed_thing.under
local node = minetest.get_node_or_nil ( pos )
local pdef = node and minetest.registered_nodes [ node.name ]
if pdef and node and pdef.on_rightclick
and not ( placer and placer : is_player ( )
and placer : get_player_control ( ) . sneak )
then
return pdef.on_rightclick ( pos , node , placer , itemstack , pointed_thing )
end
2023-03-24 21:36:07 -05:00
2023-03-30 16:05:46 -05:00
if not pdef or not pdef.buildable_to then
2023-03-29 14:35:48 -05:00
pos = pointed_thing.above
node = minetest.get_node_or_nil ( pos )
pdef = node and minetest.registered_nodes [ node.name ]
if not pdef or not pdef.buildable_to then
return itemstack
end
2023-03-24 21:36:07 -05:00
end
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
local player_name = placer and placer : get_player_name ( ) or ' '
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
-- Check sapling position for protection
if minetest.is_protected ( pos , player_name ) then
minetest.record_protection_violation ( pos , player_name )
return itemstack
end
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
-- Check tree volume for protection
if minetest.is_area_protected (
vector.add ( pos , minp_relative ) ,
vector.add ( pos , maxp_relative ) ,
player_name ,
interval
)
then
minetest.record_protection_violation ( pos , player_name )
minetest.chat_send_player (
player_name ,
S ( ' @1 will intersect protection on growth. ' , itemstack : get_definition ( ) . description )
)
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
return itemstack
end
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
Everness.log_player_action ( placer , ' places node ' , sapling_name , ' at ' , pos )
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
local take_item = not minetest.is_creative_enabled ( player_name )
local newnode = { name = sapling_name }
local ndef = minetest.registered_nodes [ sapling_name ]
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
minetest.set_node ( pos , newnode )
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
-- Run callback
if ndef and ndef.after_place_node then
-- Deepcopy place_to and pointed_thing because callback can modify it
if ndef.after_place_node ( table.copy ( pos ) , placer ,
itemstack , table.copy ( pointed_thing ) ) then
take_item = false
end
2023-03-30 16:05:46 -05:00
end
2023-03-29 14:35:48 -05:00
-- Run script hook
for _ , callback in ipairs ( minetest.registered_on_placenodes or { } ) do
-- Deepcopy pos, node and pointed_thing because callback can modify them
if callback ( table.copy ( pos ) , table.copy ( newnode ) ,
placer , table.copy ( node or { } ) ,
itemstack , table.copy ( pointed_thing ) ) then
take_item = false
end
2023-03-30 16:05:46 -05:00
end
2023-03-29 14:35:48 -05:00
if take_item then
itemstack : take_item ( )
end
2023-03-30 16:05:46 -05:00
2023-03-29 14:35:48 -05:00
return itemstack
end
2023-03-29 14:35:48 -05:00
end
--
-- Leafdecay - taken from MTG
--
-- Prevent decay of placed leaves
Everness.after_place_leaves = function ( self , pos , placer , itemstack , pointed_thing )
if placer and placer : is_player ( ) then
local node = minetest.get_node ( pos )
node.param2 = 1
minetest.set_node ( pos , node )
end
end
-- Leafdecay
local function leafdecay_after_destruct ( pos , oldnode , def )
for _ , v in pairs ( minetest.find_nodes_in_area ( vector.subtract ( pos , def.radius ) ,
vector.add ( pos , def.radius ) , def.leaves ) )
do
local node = minetest.get_node ( v )
local timer = minetest.get_node_timer ( v )
2023-05-07 21:57:31 -05:00
if node.param2 ~= 1
and minetest.get_meta ( v ) : get_int ( ' everness_prevent_leafdecay ' ) ~= 1
and not timer : is_started ( )
then
2023-03-29 14:35:48 -05:00
timer : start ( math.random ( 20 , 120 ) / 10 )
end
end
end
local movement_gravity = tonumber ( minetest.settings : get ( ' movement_gravity ' ) ) or 9.81
local function leafdecay_on_timer ( pos , def )
if minetest.find_node_near ( pos , def.radius , def.trunks ) then
return false
end
local node = minetest.get_node ( pos )
local drops = minetest.get_node_drops ( node.name )
for _ , item in ipairs ( drops ) do
local is_leaf
for _ , v in pairs ( def.leaves ) do
if v == item then
is_leaf = true
end
end
if minetest.get_item_group ( item , ' leafdecay_drop ' ) ~= 0
or not is_leaf
then
minetest.add_item ( {
x = pos.x - 0.5 + math.random ( ) ,
y = pos.y - 0.5 + math.random ( ) ,
z = pos.z - 0.5 + math.random ( ) ,
} , item )
end
end
minetest.remove_node ( pos )
minetest.check_for_falling ( pos )
-- spawn a few particles for the removed node
minetest.add_particlespawner ( {
amount = 8 ,
time = 0.001 ,
minpos = vector.subtract ( pos , { x = 0.5 , y = 0.5 , z = 0.5 } ) ,
maxpos = vector.add ( pos , { x = 0.5 , y = 0.5 , z = 0.5 } ) ,
minvel = vector.new ( - 0.5 , - 1 , - 0.5 ) ,
maxvel = vector.new ( 0.5 , 0 , 0.5 ) ,
minacc = vector.new ( 0 , - movement_gravity , 0 ) ,
maxacc = vector.new ( 0 , - movement_gravity , 0 ) ,
minsize = 0 ,
maxsize = 0 ,
node = node ,
} )
end
function Everness . register_leafdecay ( self , def )
assert ( def.leaves )
assert ( def.trunks )
assert ( def.radius )
for _ , v in pairs ( def.trunks ) do
minetest.override_item ( v , {
after_destruct = function ( pos , oldnode )
leafdecay_after_destruct ( pos , oldnode , def )
end ,
} )
end
for _ , v in pairs ( def.leaves ) do
minetest.override_item ( v , {
on_timer = function ( pos )
leafdecay_on_timer ( pos , def )
end ,
} )
end
end
2024-01-25 14:31:55 -06:00
function Everness . register_node ( self , name , def )
2023-03-29 14:35:48 -05:00
local _def = table.copy ( def )
local _name = name
2024-01-24 09:24:34 -06:00
_def.mod_origin = ' everness '
-- X Farming composter description
if minetest.get_modpath ( ' x_farming ' ) and minetest.global_exists ( ' x_farming ' ) then
-- X Farming
if _def.groups and ( _def.groups . compost or 0 ) > 0 then
2024-07-28 10:48:43 -05:00
_def.description = _def.description .. ' \n ' .. S ( ' Compost chance: @1% ' , def.groups . compost )
2024-01-24 09:24:34 -06:00
end
end
2024-01-25 14:31:55 -06:00
self.registered_nodes [ _name ] = _def
2023-03-29 14:35:48 -05:00
minetest.register_node ( _name , _def )
2023-03-24 21:36:07 -05:00
end
2023-03-30 16:05:46 -05:00
2024-01-25 14:31:55 -06:00
function Everness . register_tool ( self , name , def )
local _def = table.copy ( def )
local _name = name
_def.mod_origin = ' everness '
self.registered_tools [ _name ] = _def
minetest.register_tool ( _name , _def )
end
function Everness . register_abm ( self , def )
local _def = table.copy ( def )
local _name = _def.label
self.registered_abms [ _name ] = _def
minetest.register_abm ( _def )
end
function Everness . register_lbm ( self , def )
local _def = table.copy ( def )
local _name = _def.name
self.registered_lbms [ _name ] = _def
minetest.register_lbm ( _def )
end
function Everness . register_craftitem ( self , name , def )
local _def = table.copy ( def )
local _name = name
_def.mod_origin = ' everness '
self.registered_craftitems [ _name ] = _def
minetest.register_craftitem ( _name , _def )
end
function Everness . register_biome ( self , def )
local _def = table.copy ( def )
local _name = _def.name
self.registered_biomes [ _name ] = _def
minetest.register_biome ( _def )
end
function Everness . register_decoration ( self , def )
local _def = table.copy ( def )
local _name = _def.name
self.registered_decorations [ _name ] = _def
minetest.register_decoration ( _def )
end
function Everness . register_ore ( self , def )
local _def = table.copy ( def )
2024-02-14 15:56:55 -06:00
-- @TOTO using `ore` as name here will override the entry when there are multiple ore registrations for the same ore (different noise)
-- using indexed table would be more appropriate here
2024-01-25 14:31:55 -06:00
local _name = _def.ore
self.registered_ores [ _name ] = _def
minetest.register_ore ( _def )
end
2023-03-30 16:05:46 -05:00
--
-- Log API / helpers - copy from MTG
--
local log_non_player_actions = minetest.settings : get_bool ( ' log_non_player_actions ' , false )
local is_pos = function ( v )
return type ( v ) == ' table '
and type ( v.x ) == ' number '
and type ( v.y ) == ' number '
and type ( v.z ) == ' number '
end
function Everness . log_player_action ( player , ... )
local msg = player : get_player_name ( )
if player.is_fake_player or not player : is_player ( ) then
if not log_non_player_actions then
return
end
msg = msg .. ' ( ' .. ( type ( player.is_fake_player ) == ' string '
and player.is_fake_player or ' * ' ) .. ' ) '
end
for _ , v in ipairs ( { ... } ) do
-- translate pos
local part = is_pos ( v ) and minetest.pos_to_string ( v ) or v
-- no leading spaces before punctuation marks
msg = msg .. ( string.match ( part , ' ^[;,.] ' ) and ' ' or ' ' ) .. part
end
minetest.log ( ' action ' , msg )
end
2023-03-30 21:45:16 -05:00
function Everness . set_inventory_action_loggers ( def , name )
def.on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
Everness.log_player_action ( player , ' moves stuff in ' , name , ' at ' , pos )
end
def.on_metadata_inventory_put = function ( pos , listname , index , stack , player )
Everness.log_player_action ( player , ' moves ' , stack : get_name ( ) , ' to ' , name , ' at ' , pos )
end
def.on_metadata_inventory_take = function ( pos , listname , index , stack , player )
Everness.log_player_action ( player , ' takes ' , stack : get_name ( ) , ' from ' , name , ' at ' , pos )
end
end
2023-03-30 16:05:46 -05:00
-- 'can grow' function - copy from MTG
2024-01-10 22:16:52 -06:00
function Everness . can_grow ( pos , groups_under )
2023-03-30 16:05:46 -05:00
local node_under = minetest.get_node_or_nil ( { x = pos.x , y = pos.y - 1 , z = pos.z } )
if not node_under then
return false
end
2024-01-19 14:41:16 -06:00
local _groups_under = groups_under
2024-01-10 22:16:52 -06:00
if not groups_under then
_groups_under = { ' soil ' }
end
local has_fertile_under = false
-- Check is one of the `groups_under` are under the sapling
for i , v in ipairs ( _groups_under ) do
if minetest.get_item_group ( node_under.name , v ) > 0 then
has_fertile_under = true
break
end
end
if not has_fertile_under then
2023-03-30 16:05:46 -05:00
return false
end
local light_level = minetest.get_node_light ( pos )
if not light_level or light_level < 13 then
return false
end
return true
end
2023-03-30 21:45:16 -05:00
--
-- This method may change in future.
-- Copy from MTG
--
function Everness . can_interact_with_node ( player , pos )
if player and player : is_player ( ) then
if minetest.check_player_privs ( player , ' protection_bypass ' ) then
return true
end
else
return false
end
local meta = minetest.get_meta ( pos )
local owner = meta : get_string ( ' owner ' )
if not owner or owner == ' ' or owner == player : get_player_name ( ) then
return true
end
-- Is player wielding the right key?
local item = player : get_wielded_item ( )
if minetest.get_item_group ( item : get_name ( ) , ' key ' ) == 1 then
local key_meta = item : get_meta ( )
if key_meta : get_string ( ' secret ' ) == ' ' then
local key_oldmeta = item : get_metadata ( )
if key_oldmeta == ' ' or not minetest.parse_json ( key_oldmeta ) then
return false
end
key_meta : set_string ( ' secret ' , minetest.parse_json ( key_oldmeta ) . secret )
item : set_metadata ( ' ' )
end
return meta : get_string ( ' key_lock_secret ' ) == key_meta : get_string ( ' secret ' )
end
return false
end
--
-- Optimized helper to put all items in an inventory into a drops list
-- copy from MTG
--
function Everness . get_inventory_drops ( pos , inventory , drops )
local inv = minetest.get_meta ( pos ) : get_inventory ( )
local n = # drops
for i = 1 , inv : get_size ( inventory ) do
local stack = inv : get_stack ( inventory , i )
if stack : get_count ( ) > 0 then
drops [ n + 1 ] = stack : to_table ( )
n = n + 1
end
end
end
2023-03-30 22:30:58 -05:00
function Everness . set_loot_chest_items ( )
local loot_items = { }
for name , def in pairs ( minetest.registered_items ) do
2023-07-10 13:02:54 -05:00
local craft_recipe = minetest.get_craft_recipe ( name )
local mod_name = name : split ( ' : ' ) [ 1 ]
2023-03-30 22:30:58 -05:00
if def.groups
and next ( def.groups )
and ( not def.groups . not_in_creative_inventory or def.groups . not_in_creative_inventory == 0 )
2023-07-10 13:02:54 -05:00
and ( craft_recipe.items or mod_name == ' default ' )
2023-03-30 22:30:58 -05:00
then
table.insert ( loot_items , {
name = name ,
2023-04-05 22:05:48 -05:00
max_count = 10 ,
2023-03-30 22:30:58 -05:00
chance = 25
} )
end
end
Everness.loot_chest . default = table.copy ( loot_items )
end
2023-12-28 10:14:20 -06:00
2024-02-07 13:45:09 -06:00
function Everness . populate_loot_chests ( self , positions , params )
local _params = params or { }
local _loot_chest_items_group = _params.loot_chest_items_group or ' default '
2024-01-27 16:27:14 -06:00
-- Get inventories
local string_positions = ' ' ;
local inventories = { }
for i , pos in ipairs ( positions ) do
local inv = minetest.get_inventory ( { type = ' node ' , pos = pos } )
2024-02-07 13:45:09 -06:00
if not inv then
local chest_def = minetest.registered_nodes [ ' everness:chest ' ]
chest_def.on_construct ( pos )
inv = minetest.get_inventory ( { type = ' node ' , pos = pos } )
end
2024-01-27 16:27:14 -06:00
if inv then
table.insert ( inventories , inv )
string_positions = string_positions .. ' ' .. pos : to_string ( )
else
2024-02-07 13:45:09 -06:00
minetest.log ( ' warning ' , ' [Everness] FAILED to populate loot chests inventory at ' .. pos : to_string ( ) )
2024-01-27 16:27:14 -06:00
end
end
if # inventories > 0 then
for index , value in ipairs ( inventories [ 1 ] : get_list ( ' main ' ) ) do
local rand_idx = rand_global : next ( 1 , # self.loot_chest [ _loot_chest_items_group ] )
local item_def = self.loot_chest [ _loot_chest_items_group ] [ rand_idx ]
if not minetest.registered_items [ item_def.name ] then
return
end
if rand_global : next ( 0 , 100 ) <= item_def.chance then
local stack = ItemStack ( item_def.name )
if minetest.registered_tools [ item_def.name ] then
stack : set_wear ( rand_global : next ( 1 , 65535 ) )
else
stack : set_count ( rand_global : next ( 1 , math.min ( item_def.max_count , stack : get_stack_max ( ) ) ) )
end
local rand_inv = inventories [ rand_global : next ( 1 , # inventories ) ]
rand_inv : set_stack ( ' main ' , index , stack )
end
end
minetest.log ( ' action ' , ' [Everness] Loot chests inventory populated at ' .. string_positions )
end
end
2023-12-28 10:14:20 -06:00
--
-- Hammer
-- Modified version of default:tnt from MT
-- @license MIT
local function rand_pos ( center , pos , radius )
local def
local reg_nodes = minetest.registered_nodes
local i = 0
repeat
-- Give up and use the center if this takes too long
if i > 4 then
pos.x , pos.z = center.x , center.z
break
end
pos.x = center.x + math.random ( - radius , radius )
pos.z = center.z + math.random ( - radius , radius )
def = reg_nodes [ minetest.get_node ( pos ) . name ]
i = i + 1
until def and not def.walkable
end
local function eject_drops ( drops , pos , radius )
local drop_pos = vector.new ( pos )
for _ , item in pairs ( drops ) do
local count = math.min ( item : get_count ( ) , item : get_stack_max ( ) )
while count > 0 do
local take = math.max (
1 ,
math.min (
radius * radius ,
count ,
item : get_stack_max ( )
)
)
-- `drop_pos` is being randomized here
rand_pos ( pos , drop_pos , radius )
local dropitem = ItemStack ( item )
dropitem : set_count ( take )
local obj = minetest.add_item ( drop_pos , dropitem )
if obj then
obj : get_luaentity ( ) . collect = true
obj : set_acceleration ( { x = 0 , y = - 10 , z = 0 } )
obj : set_velocity ( {
x = math.random ( - 2 , 2 ) ,
y = math.random ( 0 , 2 ) ,
z = math.random ( - 2 , 2 )
} )
end
count = count - take
end
end
end
-- Populate `drops` table
local function add_drop ( drops , item )
item = ItemStack ( item )
local name = item : get_name ( )
local drop = drops [ name ]
if drop == nil then
drops [ name ] = item
else
drop : set_count ( drop : get_count ( ) + item : get_count ( ) )
end
end
local function destroy ( drops , npos , cid , c_air , can_dig , owner )
if minetest.is_protected ( npos , owner ) then
return cid
end
local def = Everness.hammer_cid_data [ cid ]
if not def then
return cid
elseif def.can_dig and not def.can_dig ( npos , minetest.get_player_by_name ( owner ) ) then
return cid
else
local node_drops = minetest.get_node_drops ( def.name , ' ' )
for _ , item in pairs ( node_drops ) do
add_drop ( drops , item )
end
return c_air
end
end
2023-12-31 22:07:32 -06:00
-- Draw wear bar texture overlay
function Everness . draw_wear_bar ( itemstack , wear )
local itemstack_meta = itemstack : get_meta ( )
local px_width = 14
local px_one = 65535 / px_width
local px_color = px_width - math.floor ( wear / px_one )
local inventory_overlay = ' [combine:16x16 '
for i = 1 , px_width do
if i > px_color then
inventory_overlay = inventory_overlay .. ' : ' .. i .. ' ,14=[combine \\ :1x1 \\ ^[noalpha \\ ^[colorize \\ :#000000 \\ :255 '
else
local color
if px_color < px_width / 4 then
-- below 25%
color = ' #FF0000 '
elseif px_color < ( px_width / 4 ) * 2 then
-- below 50%
color = ' #FFA500 '
elseif px_color < ( px_width / 4 ) * 3 then
-- below 75%
color = ' #FFFF00 '
else
-- above 75%
color = ' #00FF00 '
end
inventory_overlay = inventory_overlay .. ' : ' .. i .. ' ,14=[combine \\ :1x1 \\ ^[noalpha \\ ^[colorize \\ : ' .. color .. ' \\ :255 '
end
end
itemstack_meta : set_string ( ' inventory_overlay ' , inventory_overlay )
end
2023-12-28 10:14:20 -06:00
function Everness . hammer_after_dig_node ( pos , node , metadata , digger , can_dig )
if not digger then
return
end
local wielditem = digger : get_wielded_item ( )
2023-12-31 22:07:32 -06:00
if not ( wielditem : get_name ( ) == ' everness:hammer ' or wielditem : get_name ( ) == ' everness:hammer_sharp ' ) then
2023-12-28 10:14:20 -06:00
return
end
local radius = 1
local look_dir = vector.round ( digger : get_look_dir ( ) )
local look_dir_multi = vector.round ( vector.multiply ( look_dir , radius / 2 ) )
pos = vector.round ( vector.add ( pos , look_dir_multi ) )
local c_air = minetest.CONTENT_AIR
local c_ignore = minetest.CONTENT_IGNORE
local vm = VoxelManip ( )
local pr = PseudoRandom ( os.time ( ) )
local p1 = vector.subtract ( pos , radius )
local p2 = vector.add ( pos , radius )
local minp , maxp = vm : read_from_map ( p1 , p2 )
local voxel_area = VoxelArea : new ( { MinEdge = minp , MaxEdge = maxp } )
local data = vm : get_data ( )
-- `drops` are being populated in `add_drop` method, called from `destroy` method
local drops = { }
local p_name = digger : get_player_name ( )
2024-01-01 09:29:50 -06:00
if not minetest.settings : get_bool ( ' creative_mode ' ) then
2023-12-28 10:14:20 -06:00
local wielditem_meta = wielditem : get_meta ( )
local wielditem_wear = wielditem_meta : get_int ( ' everness_wear ' )
local node_def = minetest.registered_nodes [ node.name ]
local wielditem_def = wielditem : get_definition ( )
local dig_params = minetest.get_dig_params ( node_def and node_def.groups , wielditem_def and wielditem_def.tool_capabilities , wielditem : get_wear ( ) )
local new_wear = wielditem_wear + dig_params.wear
-- Add wear
wielditem_meta : set_int ( ' everness_wear ' , new_wear )
-- Draw wear bar texture overlay
2023-12-31 22:07:32 -06:00
Everness.draw_wear_bar ( wielditem , new_wear )
2023-12-28 10:14:20 -06:00
if wielditem_wear > 65535 then
-- Break tool
minetest.sound_play ( wielditem_def.sound . breaks , {
pos = pos ,
gain = 0.5
} , true )
2024-01-01 09:29:50 -06:00
if wielditem : get_name ( ) == ' everness:hammer '
or wielditem : get_name ( ) == ' everness:hammer_sharp '
then
digger : set_wielded_item ( ItemStack ( ' ' ) )
end
2023-12-31 22:07:32 -06:00
elseif wielditem : get_name ( ) == ' everness:hammer '
or wielditem : get_name ( ) == ' everness:hammer_sharp '
then
2023-12-28 10:14:20 -06:00
-- Save wear
digger : set_wielded_item ( wielditem )
end
end
-- Digging blast
for z = - radius , radius do
for y = - radius , radius do
local vi = voxel_area : index ( pos.x + ( - radius ) , pos.y + y , pos.z + z )
for x = - radius , radius do
local r = vector.length ( vector.new ( x , y , z ) )
2023-12-31 22:07:32 -06:00
if wielditem : get_name ( ) == ' everness:hammer ' then
if ( radius * radius ) / ( r * r ) >= ( pr : next ( 30 , 60 ) / 100 ) then
local cid = data [ vi ]
local p = vector.new ( pos.x + x , pos.y + y , pos.z + z )
if cid ~= c_air and cid ~= c_ignore then
data [ vi ] = destroy ( drops , p , cid , c_air , can_dig , p_name )
end
end
else
2023-12-28 10:14:20 -06:00
local cid = data [ vi ]
local p = vector.new ( pos.x + x , pos.y + y , pos.z + z )
if cid ~= c_air and cid ~= c_ignore then
data [ vi ] = destroy ( drops , p , cid , c_air , can_dig , p_name )
end
end
vi = vi + 1
end
end
end
vm : set_data ( data )
vm : write_to_map ( )
vm : update_map ( )
vm : update_liquids ( )
-- Call `check_single_for_falling` for everything within 1.5x blast radius
for y = math.round ( - radius * 1.5 ) , math.round ( radius * 1.5 ) do
for z = math.round ( - radius * 1.5 ) , math.round ( radius * 1.5 ) do
for x = math.round ( - radius * 1.5 ) , math.round ( radius * 1.5 ) do
local rad = vector.new ( x , y , z )
local s = vector.add ( pos , rad )
minetest.check_single_for_falling ( s )
end
end
end
eject_drops ( drops , pos , radius )
-- Get texture for particles from majority of the dug nodes
local node_for_particles
local most = 0
for name , stack in pairs ( drops ) do
local count = stack : get_count ( )
if count > most then
most = count
local def = minetest.registered_nodes [ name ]
if def then
node_for_particles = { name = name }
end
-- Play sounds
if def and def.sounds and def.sounds . dug then
for i = 1 , math.random ( 2 , 5 ) do
local drop_pos = vector.new ( pos )
-- `drop_pos` is being randomized here
rand_pos ( pos , drop_pos , radius )
minetest.after (
math.random ( 2 , 8 ) / 10 ,
function ( )
minetest.sound_play ( def.sounds . dug , {
pos = drop_pos ,
pitch = math.random ( 1 , 10 ) / 10
} , true )
end
)
end
end
end
end
if node_for_particles then
minetest.add_particlespawner ( {
amount = 64 ,
time = 0.1 ,
minpos = vector.subtract ( pos , radius / 2 ) ,
maxpos = vector.add ( pos , radius / 2 ) ,
minvel = { x = - 2 , y = 0 , z = - 2 } ,
maxvel = { x = 2 , y = 5 , z = 2 } ,
minacc = { x = 0 , y = - 10 , z = 0 } ,
maxacc = { x = 0 , y = - 10 , z = 0 } ,
minexptime = 0.8 ,
maxexptime = 2.0 ,
minsize = radius * 0.33 ,
maxsize = radius ,
node = node_for_particles ,
collisiondetection = true ,
} )
end
end
2023-12-31 22:07:32 -06:00
-- Function triggered for each qualifying node.
-- `dtime_s` is the in-game time (in seconds) elapsed since the block
-- was last active
function Everness . cool_lava ( pos , node , dtime_s , prev_cool_lava_action )
2024-02-16 10:23:15 -06:00
-- Variant Obsidian
if
node.name == ' default:lava_source '
or node.name == ' mcl_core:lava_source '
or node.name == ' everness:lava_source '
then
2024-01-01 09:29:50 -06:00
if math.random ( 1 , 10 ) == 1 then
2023-12-31 22:07:32 -06:00
local obi_nodes = {
{ name = ' everness:blue_crying_obsidian ' , color = ' #2978A6 ' } ,
{ name = ' everness:blue_weeping_obsidian ' , color = ' #25B8FF ' } ,
{ name = ' everness:weeping_obsidian ' , color = ' #C90FFF ' } ,
}
local rand_node = obi_nodes [ math.random ( 1 , # obi_nodes ) ]
minetest.set_node ( pos , {
name = rand_node.name
} )
minetest.sound_play ( ' everness_cool_lava ' ,
{
pos = pos ,
max_hear_distance = 16 ,
gain = 0.2
} ,
true
)
if minetest.has_feature ( { dynamic_add_media_table = true , particlespawner_tweenable = true } ) then
-- new syntax, after v5.6.0
minetest.add_particlespawner ( {
amount = 80 ,
time = 1 ,
size = {
min = 0.5 ,
max = 1 ,
} ,
exptime = 1 ,
pos = pos ,
glow = 7 ,
attract = {
kind = ' point ' ,
strength = 0.5 ,
origin = pos ,
die_on_contact = true
} ,
radius = 3 ,
texture = {
name = ' everness_particle.png^[colorize: ' .. rand_node.color .. ' :255 ' ,
alpha_tween = {
0 , 1 ,
style = ' fwd ' ,
reps = 1
} ,
scale_tween = {
0.25 , 1 ,
style = ' fwd ' ,
reps = 1
}
}
} )
end
2024-02-16 10:23:15 -06:00
elseif node.name == ' everness:lava_source ' then
-- Lava flowing
minetest.set_node ( pos , { name = ' default:obsidian ' } )
elseif node.name == ' everness:lava_flowing ' then
-- Lava flowing
minetest.set_node ( pos , { name = ' default:stone ' } )
2023-12-31 22:07:32 -06:00
else
prev_cool_lava_action ( pos , node , dtime_s )
end
else
prev_cool_lava_action ( pos , node , dtime_s )
end
end
2024-01-19 12:03:26 -06:00
function Everness . get_pot_formspec ( pos , label , model_texture )
local spos = pos.x .. ' , ' .. pos.y .. ' , ' .. pos.z
local hotbar_bg = ' '
local list_bg = ' '
for i = 0 , 7 , 1 do
hotbar_bg = hotbar_bg .. ' image[ ' .. 0 + i .. ' , ' .. 4.85 .. ' ;1,1;everness_chest_ui_bg_hb_slot.png] '
end
for row = 0 , 2 , 1 do
for i = 0 , 7 , 1 do
list_bg = list_bg .. ' image[ ' .. 0 + i .. ' , ' .. 6.08 + row .. ' ;1,1;everness_chest_ui_bg_slot.png] '
end
end
local model = ' model[0,0.5;2.5,2.5;everness_ceramic_pot;everness_ceramic_pot.obj; ' .. model_texture .. ' ;0,0;true;false;] '
local formspec = {
' size[8,9] ' ,
' listcolors[#FFFFFF00;#FFFFFF1A;#5E5957] ' ,
' background[5,5;1,1;everness_chest_ui_bg.png;true] ' ,
' list[nodemeta: ' .. spos .. ' ;main;0.5,3;1,1;] ' ,
' list[current_player;main;0,4.85;8,1;] ' ,
' list[current_player;main;0,6.08;8,3;8] ' ,
' listring[nodemeta: ' .. spos .. ' ;main] ' ,
' listring[current_player;main] ' ,
list_bg ,
hotbar_bg ,
' image[0.5,3;1,1;everness_chest_ui_bg_hb_slot.png] ' ,
' label[2.5,0.5; ' .. minetest.formspec_escape ( label ) .. ' ] ' ,
model
}
formspec = table.concat ( formspec , ' ' )
return formspec
end
2024-01-25 14:31:55 -06:00
--
-- Encyclopedia
--
local ency_data = {
nodes = { } ,
tools = { } ,
abms = { } ,
lbms = { } ,
craftitems = { } ,
biomes = { } ,
decorations = { } ,
ores = { } ,
}
--
-- Encyclopedia Helpers
--
local function tchelper ( first , rest )
return first : upper ( ) .. rest : lower ( )
end
local function capitalize ( str )
-- Add extra characters to the pattern if you need to. _ and ' are
-- found in the middle of identifiers and English words.
-- We must also put %w_' into [%w_'] to make it handle normal stuff
-- and extra stuff the same.
-- This also turns hex numbers into, eg. 0Xa7d4
return str : gsub ( " (%a)([%w_']*) " , tchelper )
end
local function tech_name_to_pretty_name ( tech_name )
local short_name = tech_name : split ( ' : ' ) [ 2 ]
short_name = short_name : gsub ( ' _ ' , ' ' )
short_name = capitalize ( short_name )
return short_name
end
local function get_model_texture_from_tile_definition ( tile_def )
-- Assumptions its a string
local texture = ' '
for i , v in ipairs ( tile_def ) do
local temp = tile_def [ i ]
if type ( temp ) == ' table ' then
if temp.name then
temp = temp.name
else
temp = temp [ i ]
end
end
texture = texture .. ( i == 1 and ' ' or ' , ' ) .. temp
end
return texture
end
local function get_unordered_list ( tbl , pos , formspec , lvl )
local _formspec = formspec or { }
local _lvl = lvl or 1
for k , v in pairs ( tbl ) do
if type ( v ) == ' table ' then
-- Label
pos.y = pos.y + 0.25
_formspec [ # _formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos.x + 0.25 * _lvl , pos.y , k .. ' : ' )
get_unordered_list ( v , pos , _formspec , _lvl + 1 )
else
if minetest.registered_items [ v ] then
pos.y = pos.y + 0.25
-- Label
_formspec [ # _formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos.x + 0.25 * _lvl , pos.y , k .. ' : ' )
pos.y = pos.y + 0.25
-- Item image
_formspec [ # _formspec + 1 ] = ( ' item_image[%f,%f;1,1;%s] ' ) : format ( pos.x + 0.25 * _lvl , pos.y , v )
-- Tooltip for description
_formspec [ # _formspec + 1 ] = ( ' tooltip[%f,%f;1,1;%s] ' ) : format ( pos.x + 0.25 * _lvl , pos.y , minetest.formspec_escape ( v ) )
pos.y = pos.y + 1
else
pos.y = pos.y + 0.25
-- List "bullet"
_formspec [ # _formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos.x + 0.25 * _lvl , pos.y , k .. ' : ' .. v )
end
end
end
_formspec = table.concat ( _formspec , ' ' )
return _formspec
end
--
-- Encyclopedia API
--
function Everness . encyclopedia_init ( self )
-- Nodes
for name , def in pairs ( self.registered_nodes ) do
if def.groups
and ( not def.groups . not_in_creative_inventory or def.groups . not_in_creative_inventory == 0 )
then
table.insert ( ency_data.nodes , name )
end
end
-- Tools
for name , def in pairs ( self.registered_tools ) do
if def.groups
and ( not def.groups . not_in_creative_inventory or def.groups . not_in_creative_inventory == 0 )
then
table.insert ( ency_data.tools , name )
end
end
-- ABMs
for name , def in pairs ( self.registered_abms ) do
table.insert ( ency_data.abms , name )
end
-- LBMs
for name , def in pairs ( self.registered_lbms ) do
table.insert ( ency_data.lbms , name )
end
-- Craftitems
for name , def in pairs ( self.registered_craftitems ) do
if def.groups
and ( not def.groups . not_in_creative_inventory or def.groups . not_in_creative_inventory == 0 )
then
table.insert ( ency_data.craftitems , name )
end
end
-- Biomes
for name , def in pairs ( self.registered_biomes ) do
table.insert ( ency_data.biomes , name )
end
-- Decorations
for name , def in pairs ( self.registered_decorations ) do
table.insert ( ency_data.decorations , name )
end
-- Ores
for name , def in pairs ( self.registered_ores ) do
table.insert ( ency_data.ores , name )
end
-- Sort alphabetically
table.sort ( ency_data.nodes , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.tools , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.abms , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.lbms , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.craftitems , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.biomes , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.decorations , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
table.sort ( ency_data.ores , function ( a , b )
return tech_name_to_pretty_name ( a ) < tech_name_to_pretty_name ( b )
end )
if minetest.get_modpath ( ' unified_inventory ' ) then
self : encyclopedia_ui_register_page ( )
elseif minetest.get_modpath ( ' i3 ' ) then
self : encyclopedia_i3_register_page ( )
elseif minetest.get_modpath ( ' sfinv ' ) and sfinv.enabled then
self : encyclopedia_sfinv_register_page ( )
end
end
function Everness . encyclopedia_get_formspec ( self , context )
local pos_primary = vector.new ( )
local pos_secondary = vector.new ( )
local pos_secondary_container = vector.new ( )
local primary_selected_idx = context.everness_ency_primary_selected_idx or 1
local dropdown_idx = context.everness_ency_dropdown_idx or 1
context.everness_ency_primary_selected_idx = primary_selected_idx
context.everness_ency_dropdown_idx = dropdown_idx
-- Get dropdown items
local ency_dropdown_items = { }
for k , v in pairs ( ency_data ) do
table.insert ( ency_dropdown_items , k )
end
table.sort ( ency_dropdown_items )
-- Dropdown string value (main category)
local dropdown_value = ency_dropdown_items [ dropdown_idx ]
-- Data to show in secondary container (corresponding to selected index in primary item list)
local primary_list_data = ency_data [ dropdown_value ]
-- Get primary list items (list on the left)
local primary_list_items = { }
for k , v in ipairs ( primary_list_data ) do
table.insert ( primary_list_items , tech_name_to_pretty_name ( v ) )
end
-- Primary list selected item value (item technical name, e.g. 'everness:palm_tree_wood')
local primary_list_selected_value = primary_list_data [ primary_selected_idx ]
local def = self [ ' registered_ ' .. dropdown_value ] [ primary_list_selected_value ]
pos_primary.x = pos_primary.x + 0.25
pos_primary.y = pos_primary.y + 0.5
local formspec = {
-- Title
' real_coordinates[true] ' ,
( ' label[%f,%f;%s] ' ) : format ( pos_primary.x , pos_primary.y , minetest.formspec_escape ( S ( ' Everness Encyclopedia ' ) ) ) ,
}
-- Dropdown (main categories)
pos_primary.y = pos_primary.y + 0.4
formspec [ # formspec + 1 ] = ( ' dropdown[%f,%f;4,0.4;everness_ency_dropdown;%s;%d;true] ' ) : format ( pos_primary.x , pos_primary.y , table.concat ( ency_dropdown_items , ' , ' ) , dropdown_idx )
-- Primary list
pos_primary.y = pos_primary.y + 0.6
formspec [ # formspec + 1 ] = ( ' textlist[%f,%f;4,9;everness_ency_main_list;%s;%d;false] ' ) : format ( pos_primary.x , pos_primary.y , table.concat ( primary_list_items , ' , ' ) , primary_selected_idx )
-- Secondary (details on the right)
pos_secondary.x = pos_secondary.x + 4.5
pos_secondary.y = pos_secondary.y + 1.4
formspec [ # formspec + 1 ] = ( ' scroll_container[%f,%f;5.5,9;everness_ency_detail_view_scrollbar;vertical;0.1] ' ) : format ( pos_secondary.x , pos_secondary.y )
-- Secondary title
pos_secondary_container.y = pos_secondary_container.y + 0.25
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , primary_list_selected_value )
-- Margin
pos_secondary_container.y = pos_secondary_container.y + 0.5
if minetest [ ' registered_ ' .. dropdown_value ] [ primary_list_selected_value ]
and dropdown_value ~= ' biomes '
and dropdown_value ~= ' decorations '
and dropdown_value ~= ' ores '
then
if def.mesh then
-- Item model
formspec [ # formspec + 1 ] = ( ' model[%f,%f;2,2;%s;%s;%s;-30,0;true;true;] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , primary_list_selected_value , def.mesh , get_model_texture_from_tile_definition ( def.tiles ) )
else
-- Item image
formspec [ # formspec + 1 ] = ( ' item_image[%f,%f;2,2;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , primary_list_selected_value )
end
if def.description then
-- Tooltip for description
formspec [ # formspec + 1 ] = ( ' tooltip[%f,%f;2,2;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , minetest.formspec_escape ( def.description ) )
end
pos_secondary_container.y = pos_secondary_container.y + 2
elseif def and def.description then
-- Label description
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , minetest.formspec_escape ( def.description ) )
end
if def and def.label then
pos_secondary_container.y = pos_secondary_container.y + 0.25
-- Label description
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , minetest.formspec_escape ( def.label ) )
end
-- Groups
if def and def.groups and next ( def.groups ) then
pos_secondary_container.y = pos_secondary_container.y + 0.5
-- Title
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , ' Groups: ' )
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( ( def.groups or { } ) , pos_secondary_container )
end
-- Tool capabilities
if def and def.tool_capabilities and next ( def.tool_capabilities ) then
pos_secondary_container.y = pos_secondary_container.y + 0.5
-- Title
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , ' Tool Capabilities: ' )
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( ( def.tool_capabilities or { } ) , pos_secondary_container )
end
-- ABM/LBM nodenames
if def and def.nodenames then
pos_secondary_container.y = pos_secondary_container.y + 0.5
-- Title
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , ' Apply "action" function to these nodes: ' )
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( ( def.nodenames or { } ) , pos_secondary_container )
end
-- ABM neighbors
if def and def.neighbors and next ( def.neighbors ) then
pos_secondary_container.y = pos_secondary_container.y + 0.5
-- Title
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , ' Only apply "action" to nodes that have one of, or any combination of, these neighbors: ' )
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( ( def.neighbors or { } ) , pos_secondary_container )
end
if def and def.run_at_every_load then
pos_secondary_container.y = pos_secondary_container.y + 0.5
formspec [ # formspec + 1 ] = ( ' label[%f,%f;%s] ' ) : format ( pos_secondary_container.x , pos_secondary_container.y , ' Run at every load: ' .. ( def.run_at_every_load and ' yes ' or ' no ' ) )
end
-- Biomes
if def and dropdown_value == ' biomes ' then
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( def , pos_secondary_container )
end
-- Decorations
if def and dropdown_value == ' decorations ' then
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( def , pos_secondary_container )
end
-- Ores
if def and dropdown_value == ' ores ' then
-- Unordered list
formspec [ # formspec + 1 ] = get_unordered_list ( def , pos_secondary_container )
end
-- Close secondary container
formspec [ # formspec + 1 ] = ' scroll_container_end[] '
-- Add scrollbar to secondary container
formspec [ # formspec + 1 ] = ( ' scrollbaroptions[min=0;max=%d;smallstep=10;largestep=100;thumbsize=10;arrows=default] ' ) : format ( math.ceil ( pos_secondary_container.y * 10 ) )
formspec [ # formspec + 1 ] = ( ' scrollbar[%f,%f;0.15,9;vertical;everness_ency_detail_view_scrollbar;] ' ) : format ( pos_secondary.x + 5.5 + 0.15 , pos_secondary.y )
return formspec
end
function Everness . encyclopedia_i3_register_page ( self )
i3.new_tab ( ' everness_encyclopedia ' , {
description = ' Everness ' ,
image = ' everness_logo.png ' ,
slots = false ,
formspec = function ( player , data , fs )
local context = data or { }
local formspec = self : encyclopedia_get_formspec ( context )
formspec = table.concat ( formspec , ' ' )
fs ( formspec )
end ,
fields = function ( player , data , fields )
if fields.everness_ency_main_list then
local main_list_event = minetest.explode_textlist_event ( fields.everness_ency_main_list )
-- Set context data
if main_list_event.type == ' CHG ' then
data.everness_ency_primary_selected_idx = main_list_event.index
end
elseif fields.everness_ency_dropdown then
local prev_everness_ency_dropdown_idx = data.everness_ency_dropdown_idx
local new_everness_ency_dropdown_idx = tonumber ( fields.everness_ency_dropdown )
data.everness_ency_dropdown_idx = new_everness_ency_dropdown_idx
-- Change to 1st primary list item index only when changing dropdown
if prev_everness_ency_dropdown_idx ~= new_everness_ency_dropdown_idx then
data.everness_ency_primary_selected_idx = 1
end
end
end ,
access = function ( player , data )
return minetest.check_player_privs ( player : get_player_name ( ) , ' everness_encyclopedia ' )
end ,
} )
end
function Everness . encyclopedia_ui_register_page ( self )
unified_inventory.register_page ( ' everness:encyclopedia ' , {
get_formspec = function ( player )
local context = unified_inventory.everness_context [ player : get_player_name ( ) ]
local formspec = self : encyclopedia_get_formspec ( context )
return {
formspec = table.concat ( formspec , ' ' ) ,
draw_inventory = false ,
draw_item_list = false
}
end
} )
minetest.register_on_joinplayer ( function ( player )
local pname = player : get_player_name ( )
unified_inventory.everness_context = { }
unified_inventory.everness_context [ pname ] = {
everness_ency_dropdown_idx = 1 ,
everness_ency_primary_selected_idx = 1 ,
}
end )
minetest.register_on_player_receive_fields ( function ( player , formname , fields )
if formname ~= ' ' then
return
end
local pname = player : get_player_name ( )
if fields.everness_ency_main_list then
local main_list_event = minetest.explode_textlist_event ( fields.everness_ency_main_list )
-- Set context data
if main_list_event.type == ' CHG ' then
unified_inventory.everness_context [ pname ] . everness_ency_primary_selected_idx = main_list_event.index
unified_inventory.set_inventory_formspec ( player , unified_inventory.current_page [ pname ] )
end
elseif fields.everness_ency_dropdown then
local prev_everness_ency_dropdown_idx = unified_inventory.everness_context [ pname ] . everness_ency_dropdown_idx
local new_everness_ency_dropdown_idx = tonumber ( fields.everness_ency_dropdown )
unified_inventory.everness_context [ pname ] . everness_ency_dropdown_idx = new_everness_ency_dropdown_idx
-- Change to 1st primary list item index only when changing dropdown
if prev_everness_ency_dropdown_idx ~= new_everness_ency_dropdown_idx then
unified_inventory.everness_context [ pname ] . everness_ency_primary_selected_idx = 1
end
unified_inventory.set_inventory_formspec ( player , unified_inventory.current_page [ pname ] )
end
end )
unified_inventory.register_button ( ' everness:encyclopedia ' , {
type = ' image ' ,
image = ' everness_logo.png ' ,
tooltip = ' Everness Encyclopedia ' ,
condition = function ( player )
return minetest.check_player_privs ( player : get_player_name ( ) , ' everness_encyclopedia ' )
end ,
action = function ( player )
local pname = player : get_player_name ( )
if not minetest.check_player_privs ( pname , ' everness_encyclopedia ' ) then
minetest.chat_send_player ( pname , S ( ' You need "everness_encyclopedia" privilige to access this button. ' ) )
unified_inventory.set_inventory_formspec ( player , unified_inventory.current_page [ pname ] )
return
end
unified_inventory.current_page [ pname ] = ' everness:encyclopedia '
unified_inventory.set_inventory_formspec ( player , unified_inventory.current_page [ pname ] )
end ,
} )
end
function Everness . encyclopedia_sfinv_register_page ( self )
sfinv.register_page ( ' everness:encyclopedia ' , {
title = ' Everness ' ,
is_in_nav = function ( _self , player , context )
return minetest.check_player_privs ( player : get_player_name ( ) , ' everness_encyclopedia ' )
end ,
get = function ( _self , player , context )
local formspec = self : encyclopedia_get_formspec ( context )
return sfinv.make_formspec ( player , context , table.concat ( formspec , ' ' ) )
end ,
on_player_receive_fields = function ( _self , player , context , fields )
if fields.everness_ency_main_list then
local main_list_event = minetest.explode_textlist_event ( fields.everness_ency_main_list )
-- Set context data
if main_list_event.type == ' CHG ' then
context.everness_ency_primary_selected_idx = main_list_event.index
sfinv.set_player_inventory_formspec ( player )
end
end
if fields.everness_ency_dropdown then
local prev_everness_ency_dropdown_idx = context.everness_ency_dropdown_idx
local new_everness_ency_dropdown_idx = tonumber ( fields.everness_ency_dropdown )
context.everness_ency_dropdown_idx = new_everness_ency_dropdown_idx
-- Change to 1st primary list item index only when changing dropdown
if prev_everness_ency_dropdown_idx ~= new_everness_ency_dropdown_idx then
context.everness_ency_primary_selected_idx = 1
end
sfinv.set_player_inventory_formspec ( player )
end
end
} )
end
2024-01-27 16:27:14 -06:00
function Everness . find_content_in_vm_area ( minp , maxp , contentIds , data , area )
local indexes = { }
local id_count = { }
for y = minp.y , maxp.y do
for z = minp.z , maxp.z do
for x = minp.x , maxp.x do
local ai = area : index ( x , y , z )
if table.indexof ( contentIds , data [ ai ] ) ~= - 1 then
id_count [ data [ ai ] ] = ( id_count [ data [ ai ] ] or 0 ) + 1
table.insert ( indexes , ai )
end
end
end
end
return indexes , id_count
end
2024-02-07 07:47:36 -06:00
2024-02-07 13:45:09 -06:00
function Everness . find_content_under_air_in_vm_area ( minp , maxp , contentIds , data , area )
local indexes = { }
local id_count = { }
for y = minp.y , maxp.y do
for z = minp.z , maxp.z do
for x = minp.x , maxp.x do
local ai = area : index ( x , y , z )
if table.indexof ( contentIds , data [ ai ] ) ~= - 1
and data [ ai + area.ystride ] == minetest.CONTENT_AIR
then
id_count [ data [ ai ] ] = ( id_count [ data [ ai ] ] or 0 ) + 1
table.insert ( indexes , ai )
end
end
end
end
return indexes , id_count
end
2024-02-07 07:47:36 -06:00
function Everness . add_to_queue_on_generated ( self , def )
if type ( def ) ~= ' table ' then
minetest.log ( ' warning ' , ' [add_to_queue_on_generated] Callback definition is not a table, not adding to queue! It was type of ' .. type ( def ) )
return
end
table.insert ( self.on_generated_queue , def )
end
2024-02-14 15:56:55 -06:00
2024-02-14 15:59:01 -06:00
---Merge two tables with key/value pair
---@param t1 table
---@param t2 table
---@return table
function Everness . mergeTables ( t1 , t2 )
for k , v in pairs ( t2 ) do t1 [ k ] = v end
return t1
end