develop #35
27 changed files with 1486 additions and 372 deletions
|
@ -446,12 +446,22 @@ question is already loaded, or false if not.
|
|||
|
||||
|
||||
=====
|
||||
dbg(string)
|
||||
dbg(string, level)
|
||||
|
||||
This is a simple debug output function which takes one string parameter. It
|
||||
just checks if DEBUG is true and outputs the phrase "[Plantlife] " followed by
|
||||
the supplied string, via the print() function, if so.
|
||||
|
||||
'level' is a number that, if supplied, dictates the lowest 'biome_lib_debug'
|
||||
can be set to in minetest.conf for this message to be displayed. Both the
|
||||
default log level and the default message level are 0, thus always showing the
|
||||
supplied message.
|
||||
|
||||
Although it's not set in stone, a good practice is to use a level of 0 (or
|
||||
just omit the value) for anything that generally important enough that it
|
||||
ought always be shown, 1 for errors, 2 for warnings, 3 for info, 4 for verbose
|
||||
spammy stuff.
|
||||
|
||||
=====
|
||||
biome_lib:generate_tree(pos, treemodel)
|
||||
biome_lib:grow_tree(pos, treemodel)
|
||||
|
|
|
@ -4,37 +4,42 @@
|
|||
-- Splizard's snow mod.
|
||||
--
|
||||
|
||||
biome_lib = {}
|
||||
|
||||
-- Boilerplate to support localized strings if intllib mod is installed.
|
||||
local S
|
||||
if minetest.global_exists("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
S = intllib.make_gettext_pair()
|
||||
else
|
||||
S = intllib.Getter()
|
||||
end
|
||||
else
|
||||
S = function(s) return s end
|
||||
end
|
||||
biome_lib.intllib = S
|
||||
|
||||
-- Various settings - most of these probably won't need to be changed
|
||||
|
||||
biome_lib = {}
|
||||
biome_lib.air = {name = "air"}
|
||||
|
||||
biome_lib.blocklist_aircheck = {}
|
||||
biome_lib.blocklist_no_aircheck = {}
|
||||
|
||||
biome_lib.surface_nodes_aircheck = {}
|
||||
biome_lib.surface_nodes_no_aircheck = {}
|
||||
|
||||
biome_lib.surfaceslist_aircheck = {}
|
||||
biome_lib.surfaceslist_no_aircheck = {}
|
||||
|
||||
biome_lib.actioncount_aircheck = {}
|
||||
biome_lib.actioncount_no_aircheck = {}
|
||||
biome_lib.block_log = {}
|
||||
biome_lib.block_recheck_list = {}
|
||||
biome_lib.run_block_recheck_list = false
|
||||
|
||||
biome_lib.actionslist_aircheck = {}
|
||||
biome_lib.actionslist_no_aircheck = {}
|
||||
|
||||
biome_lib.surfaceslist_aircheck = {}
|
||||
biome_lib.surfaceslist_no_aircheck = {}
|
||||
|
||||
biome_lib.modpath = minetest.get_modpath("biome_lib")
|
||||
|
||||
biome_lib.total_no_aircheck_calls = 0
|
||||
|
||||
biome_lib.queue_run_ratio = tonumber(minetest.settings:get("biome_lib_queue_run_ratio")) or 100
|
||||
|
||||
local function tableize(s)
|
||||
return string.split(string.trim(string.gsub(s, " ", "")))
|
||||
end
|
||||
|
||||
local c1 minetest.settings:get("biome_lib_default_grow_through_nodes")
|
||||
local c1 = minetest.settings:get("biome_lib_default_grow_through_nodes")
|
||||
biome_lib.default_grow_through_nodes = {["air"] = true}
|
||||
if c1 then
|
||||
for _, i in ipairs(tableize(c1)) do
|
||||
|
@ -44,7 +49,7 @@ else
|
|||
biome_lib.default_grow_through_nodes["default:snow"] = true
|
||||
end
|
||||
|
||||
local c2 minetest.settings:get("biome_lib_default_water_nodes")
|
||||
local c2 = minetest.settings:get("biome_lib_default_water_nodes")
|
||||
biome_lib.default_water_nodes = {}
|
||||
if c2 then
|
||||
for _, i in ipairs(tableize(c2)) do
|
||||
|
@ -65,27 +70,25 @@ biome_lib.default_wet_surfaces = c3 and tableize(c3) or {"default:dirt", "defaul
|
|||
biome_lib.default_ground_nodes = c4 and tableize(c4) or {"default:dirt_with_grass"}
|
||||
biome_lib.default_grow_nodes = c5 and tableize(c5) or {"default:dirt_with_grass"}
|
||||
|
||||
-- Boilerplate to support localized strings if intllib mod is installed.
|
||||
local S
|
||||
if minetest.global_exists("intllib") then
|
||||
if intllib.make_gettext_pair then
|
||||
S = intllib.make_gettext_pair()
|
||||
else
|
||||
S = intllib.Getter()
|
||||
end
|
||||
else
|
||||
S = function(s) return s end
|
||||
end
|
||||
biome_lib.intllib = S
|
||||
biome_lib.debug_log_level = tonumber(minetest.settings:get("biome_lib_debug_log_level")) or 0
|
||||
|
||||
local DEBUG = minetest.settings:get_bool("biome_lib_debug", false)
|
||||
local rr = tonumber(minetest.settings:get("biome_lib_queue_run_ratio")) or -100
|
||||
biome_lib.queue_run_ratio = 100 - rr
|
||||
biome_lib.entries_per_step = math.max(-rr, 1)
|
||||
|
||||
function biome_lib:dbg(msg)
|
||||
if DEBUG then
|
||||
print("[Biome Lib] "..msg)
|
||||
minetest.log("verbose", "[Biome Lib] "..msg)
|
||||
end
|
||||
end
|
||||
-- the timer that manages the block timeout is in microseconds, but the timer
|
||||
-- that manages the queue wakeup call has to be in seconds, and works best if
|
||||
-- it takes a fraction of the block timeout interval.
|
||||
|
||||
local t = tonumber(minetest.settings:get("biome_lib_block_timeout")) or 300
|
||||
|
||||
biome_lib.block_timeout = t * 1000000
|
||||
|
||||
-- we don't want the wakeup function to trigger TOO often,
|
||||
-- in case the user's block timeout setting is really low
|
||||
biome_lib.block_queue_wakeup_time = math.min(t/2, math.max(20, t/10))
|
||||
|
||||
local time_speed = tonumber(minetest.settings:get("time_speed"))
|
||||
|
||||
biome_lib.plantlife_seed_diff = 329 -- needs to be global so other mods can see it
|
||||
|
||||
|
@ -104,7 +107,6 @@ local humidity_persistence = 0.5
|
|||
local humidity_scale = 250
|
||||
|
||||
local time_scale = 1
|
||||
local time_speed = tonumber(minetest.settings:get("time_speed"))
|
||||
|
||||
if time_speed and time_speed > 0 then
|
||||
time_scale = 72 / time_speed
|
||||
|
@ -117,6 +119,14 @@ biome_lib.perlin_humidity = PerlinNoise(humidity_seeddiff, humidity_octaves, hum
|
|||
|
||||
-- Local functions
|
||||
|
||||
function biome_lib.dbg(msg, level)
|
||||
local l = tonumber(level) or 0
|
||||
if biome_lib.debug_log_level >= l then
|
||||
print("[Biome Lib] "..msg)
|
||||
minetest.log("verbose", "[Biome Lib] "..msg)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_biome_data(pos, perlin_fertile)
|
||||
local fertility = perlin_fertile:get_2d({x=pos.x, y=pos.z})
|
||||
|
||||
|
@ -187,17 +197,17 @@ function biome_lib:register_generate_plant(biomedef, nodes_or_function_or_model)
|
|||
if type(nodes_or_function_or_model) == "string"
|
||||
and string.find(nodes_or_function_or_model, ":")
|
||||
and not minetest.registered_nodes[nodes_or_function_or_model] then
|
||||
biome_lib:dbg("Warning: Ignored registration for undefined spawn node: "..dump(nodes_or_function_or_model))
|
||||
biome_lib.dbg("Warning: Ignored registration for undefined spawn node: "..dump(nodes_or_function_or_model), 2)
|
||||
return
|
||||
end
|
||||
|
||||
if type(nodes_or_function_or_model) == "string"
|
||||
and not string.find(nodes_or_function_or_model, ":") then
|
||||
biome_lib:dbg("Warning: Registered function call using deprecated string method: "..dump(nodes_or_function_or_model))
|
||||
biome_lib.dbg("Warning: Registered function call using deprecated string method: "..dump(nodes_or_function_or_model), 2)
|
||||
end
|
||||
|
||||
if biomedef.check_air == false then
|
||||
biome_lib:dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model))
|
||||
biome_lib.dbg("Register no-air-check mapgen hook: "..dump(nodes_or_function_or_model), 3)
|
||||
biome_lib.actionslist_no_aircheck[#biome_lib.actionslist_no_aircheck + 1] = { biomedef, nodes_or_function_or_model }
|
||||
local s = biomedef.surface
|
||||
if type(s) == "string" then
|
||||
|
@ -206,7 +216,7 @@ function biome_lib:register_generate_plant(biomedef, nodes_or_function_or_model)
|
|||
biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s
|
||||
end
|
||||
else
|
||||
biome_lib:dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s))
|
||||
biome_lib.dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s), 2)
|
||||
end
|
||||
else
|
||||
for i = 1, #biomedef.surface do
|
||||
|
@ -216,12 +226,12 @@ function biome_lib:register_generate_plant(biomedef, nodes_or_function_or_model)
|
|||
biome_lib.surfaceslist_no_aircheck[#biome_lib.surfaceslist_no_aircheck + 1] = s
|
||||
end
|
||||
else
|
||||
biome_lib:dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s))
|
||||
biome_lib.dbg("Warning: Ignored no-air-check registration for undefined surface node: "..dump(s), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
biome_lib:dbg("Register with-air-checking mapgen hook: "..dump(nodes_or_function_or_model))
|
||||
biome_lib.dbg("Register with-air-checking mapgen hook: "..dump(nodes_or_function_or_model), 3)
|
||||
biome_lib.actionslist_aircheck[#biome_lib.actionslist_aircheck + 1] = { biomedef, nodes_or_function_or_model }
|
||||
local s = biomedef.surface
|
||||
if type(s) == "string" then
|
||||
|
@ -230,7 +240,7 @@ function biome_lib:register_generate_plant(biomedef, nodes_or_function_or_model)
|
|||
biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s
|
||||
end
|
||||
else
|
||||
biome_lib:dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s))
|
||||
biome_lib.dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s), 2)
|
||||
end
|
||||
else
|
||||
for i = 1, #biomedef.surface do
|
||||
|
@ -240,7 +250,7 @@ function biome_lib:register_generate_plant(biomedef, nodes_or_function_or_model)
|
|||
biome_lib.surfaceslist_aircheck[#biome_lib.surfaceslist_aircheck + 1] = s
|
||||
end
|
||||
else
|
||||
biome_lib:dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s))
|
||||
biome_lib.dbg("Warning: Ignored with-air-checking registration for undefined surface node: "..dump(s), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -328,7 +338,7 @@ local function populate_single_surface(biome, pos, perlin_fertile_area, checkair
|
|||
return true
|
||||
end
|
||||
|
||||
function biome_lib:populate_surfaces(biome, nodes_or_function_or_model, snodes, checkair)
|
||||
function biome_lib.populate_surfaces(biome, nodes_or_function_or_model, snodes, checkair)
|
||||
local items_added = 0
|
||||
|
||||
biome_lib:set_defaults(biome)
|
||||
|
@ -392,13 +402,16 @@ function biome_lib:populate_surfaces(biome, nodes_or_function_or_model, snodes,
|
|||
if objtype == "table" then
|
||||
if nodes_or_function_or_model.axiom then
|
||||
biome_lib:generate_tree(p_top, nodes_or_function_or_model)
|
||||
biome_lib.dbg("An L-tree was spawned at "..minetest.pos_to_string(p_top), 4)
|
||||
spawned = true
|
||||
else
|
||||
local fdir = nil
|
||||
if biome.random_facedir then
|
||||
fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
|
||||
end
|
||||
minetest.swap_node(p_top, { name = nodes_or_function_or_model[math.random(#nodes_or_function_or_model)], param2 = fdir })
|
||||
local n=nodes_or_function_or_model[math.random(#nodes_or_function_or_model)]
|
||||
minetest.swap_node(p_top, { name = n, param2 = fdir })
|
||||
biome_lib.dbg("Node \""..n.."\" was randomly picked from a list and placed at "..minetest.pos_to_string(p_top), 4)
|
||||
spawned = true
|
||||
end
|
||||
elseif objtype == "string" and
|
||||
|
@ -408,15 +421,18 @@ function biome_lib:populate_surfaces(biome, nodes_or_function_or_model, snodes,
|
|||
fdir = math.random(biome.random_facedir[1], biome.random_facedir[2])
|
||||
end
|
||||
minetest.swap_node(p_top, { name = nodes_or_function_or_model, param2 = fdir })
|
||||
biome_lib.dbg("Node \""..nodes_or_function_or_model.."\" was placed at "..minetest.pos_to_string(p_top), 4)
|
||||
spawned = true
|
||||
elseif objtype == "function" then
|
||||
nodes_or_function_or_model(pos)
|
||||
biome_lib.dbg("A function was run on surface node at "..minetest.pos_to_string(pos), 4)
|
||||
spawned = true
|
||||
elseif objtype == "string" and pcall(loadstring(("return %s(...)"):
|
||||
format(nodes_or_function_or_model)),pos) then
|
||||
spawned = true
|
||||
biome_lib.dbg("An obsolete string-specified function was run on surface node at "..minetest.pos_to_string(p_top), 4)
|
||||
else
|
||||
biome_lib:dbg("Warning: Ignored invalid definition for object "..dump(nodes_or_function_or_model).." that was pointed at {"..dump(pos).."}")
|
||||
biome_lib.dbg("Warning: Ignored invalid definition for object "..dump(nodes_or_function_or_model).." that was pointed at {"..dump(pos).."}", 2)
|
||||
end
|
||||
else
|
||||
tries = tries + 1
|
||||
|
@ -427,134 +443,196 @@ function biome_lib:populate_surfaces(biome, nodes_or_function_or_model, snodes,
|
|||
return items_added
|
||||
end
|
||||
|
||||
-- Primary mapgen spawner, for mods that can work with air checking enabled on
|
||||
-- a surface during the initial map read stage.
|
||||
-- Primary log read-out/mapgen spawner
|
||||
|
||||
function biome_lib:generate_block_with_air_checking()
|
||||
if not biome_lib.blocklist_aircheck[1] then
|
||||
return
|
||||
local function confirm_block_surroundings(p)
|
||||
local n=minetest.get_node_or_nil(p)
|
||||
if not n or n.name == "ignore" then return false end
|
||||
|
||||
for x = -32,32,64 do -- step of 64 causes it to only check the 8 corner blocks
|
||||
for y = -32,32,64 do
|
||||
for z = -32,32,64 do
|
||||
local n=minetest.get_node_or_nil({x=p.x + x, y=p.y + y, z=p.z + z})
|
||||
if not n or n.name == "ignore" then return false end
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local minp = biome_lib.blocklist_aircheck[1][1]
|
||||
local maxp = biome_lib.blocklist_aircheck[1][2]
|
||||
function biome_lib.generate_block(shutting_down)
|
||||
|
||||
-- use the block hash as a unique key into the surface nodes
|
||||
-- tables, so that we can write the tables thread-safely.
|
||||
|
||||
local blockhash = minetest.hash_node_position(minp)
|
||||
|
||||
if not biome_lib.surface_nodes_aircheck.blockhash then -- read it into the block cache
|
||||
biome_lib.surface_nodes_aircheck.blockhash =
|
||||
minetest.find_nodes_in_area_under_air(minp, maxp, biome_lib.surfaceslist_aircheck)
|
||||
biome_lib.actioncount_aircheck.blockhash = 1
|
||||
if #biome_lib.surface_nodes_aircheck.blockhash > 0 then
|
||||
biome_lib:dbg("Mapblock at "..minetest.pos_to_string(minp).." added, with "..#biome_lib.surface_nodes_aircheck.blockhash.." surface nodes detected.")
|
||||
if shutting_down then
|
||||
if #biome_lib.block_recheck_list > 0 then
|
||||
for i = 1, #biome_lib.block_recheck_list do
|
||||
biome_lib.block_log[#biome_lib.block_log + 1] = biome_lib.block_recheck_list[i]
|
||||
end
|
||||
elseif not minetest.get_node_or_nil(minp) then
|
||||
minetest.load_area(minp)
|
||||
biome_lib.block_recheck_list = {}
|
||||
end
|
||||
biome_lib.run_block_recheck_list = false
|
||||
else
|
||||
if biome_lib.actionslist_aircheck[biome_lib.actioncount_aircheck.blockhash] then
|
||||
-- [1] is biome, [2] is node/function/model
|
||||
local added = biome_lib:populate_surfaces(
|
||||
biome_lib.actionslist_aircheck[biome_lib.actioncount_aircheck.blockhash][1],
|
||||
biome_lib.actionslist_aircheck[biome_lib.actioncount_aircheck.blockhash][2],
|
||||
biome_lib.surface_nodes_aircheck.blockhash, true)
|
||||
if biome_lib.run_block_recheck_list
|
||||
and not biome_lib.block_recheck_list[1] then
|
||||
biome_lib.run_block_recheck_list = false
|
||||
end
|
||||
end
|
||||
|
||||
local blocklog = biome_lib.run_block_recheck_list
|
||||
and biome_lib.block_recheck_list
|
||||
or biome_lib.block_log
|
||||
|
||||
if not blocklog[1] then return end
|
||||
|
||||
local minp = blocklog[1][1]
|
||||
local maxp = blocklog[1][2]
|
||||
local airflag = blocklog[1][3]
|
||||
local pos_hash = minetest.hash_node_position(minp)
|
||||
|
||||
if not biome_lib.pos_hash then -- we need to read the maplock and get the surfaces list
|
||||
local now = minetest.get_us_time()
|
||||
biome_lib.pos_hash = {}
|
||||
minetest.load_area(minp)
|
||||
if not confirm_block_surroundings(minp)
|
||||
and not shutting_down
|
||||
and (blocklog[1][4] + biome_lib.block_timeout) > now then -- if any neighbors appear not to be loaded and the block hasn't expired yet, defer it
|
||||
|
||||
if biome_lib.run_block_recheck_list then
|
||||
biome_lib.block_log[#biome_lib.block_log + 1] = table.copy(biome_lib.block_recheck_list[1])
|
||||
table.remove(biome_lib.block_recheck_list, 1)
|
||||
else
|
||||
biome_lib.block_recheck_list[#biome_lib.block_recheck_list + 1] = table.copy(biome_lib.block_log[1])
|
||||
table.remove(biome_lib.block_log, 1)
|
||||
end
|
||||
biome_lib.pos_hash = nil
|
||||
biome_lib.dbg("Mapblock at "..minetest.pos_to_string(minp)..
|
||||
" had a neighbor not fully emerged, skipped it for now.", 4)
|
||||
return
|
||||
else
|
||||
biome_lib.pos_hash.surface_node_list = airflag
|
||||
and minetest.find_nodes_in_area_under_air(minp, maxp, biome_lib.surfaceslist_aircheck)
|
||||
or minetest.find_nodes_in_area(minp, maxp, biome_lib.surfaceslist_no_aircheck)
|
||||
biome_lib.pos_hash.action_index = 1
|
||||
if #biome_lib.pos_hash.surface_node_list > 0 then
|
||||
biome_lib.dbg("Mapblock at "..minetest.pos_to_string(minp)..
|
||||
" has "..#biome_lib.pos_hash.surface_node_list..
|
||||
" surface nodes to work on (airflag="..dump(airflag)..")", 4)
|
||||
end
|
||||
end
|
||||
elseif not (airflag and biome_lib.actionslist_aircheck[biome_lib.pos_hash.action_index])
|
||||
and not (not airflag and biome_lib.actionslist_no_aircheck[biome_lib.pos_hash.action_index]) then
|
||||
-- the block is finished, remove it
|
||||
if #biome_lib.pos_hash.surface_node_list > 0 then
|
||||
biome_lib.dbg("Deleted mapblock "..minetest.pos_to_string(minp).." from the block log", 4)
|
||||
end
|
||||
table.remove(blocklog, 1)
|
||||
biome_lib.pos_hash = nil
|
||||
else
|
||||
-- below, [1] is biome, [2] is the thing to be added
|
||||
local added = 0
|
||||
if airflag then
|
||||
if biome_lib.actionslist_aircheck[biome_lib.pos_hash.action_index] then
|
||||
added = biome_lib.populate_surfaces(
|
||||
biome_lib.actionslist_aircheck[biome_lib.pos_hash.action_index][1],
|
||||
biome_lib.actionslist_aircheck[biome_lib.pos_hash.action_index][2],
|
||||
biome_lib.pos_hash.surface_node_list, true)
|
||||
biome_lib.pos_hash.action_index = biome_lib.pos_hash.action_index + 1
|
||||
end
|
||||
else
|
||||
if biome_lib.actionslist_no_aircheck[biome_lib.pos_hash.action_index] then
|
||||
added = biome_lib.populate_surfaces(
|
||||
biome_lib.actionslist_no_aircheck[biome_lib.pos_hash.action_index][1],
|
||||
biome_lib.actionslist_no_aircheck[biome_lib.pos_hash.action_index][2],
|
||||
biome_lib.pos_hash.surface_node_list, false)
|
||||
biome_lib.pos_hash.action_index = biome_lib.pos_hash.action_index + 1
|
||||
end
|
||||
end
|
||||
if added > 0 then
|
||||
biome_lib:dbg("Ran biome_lib:populate_surfaces for block at "..minetest.pos_to_string(minp)..
|
||||
". Entry #"..biome_lib.actioncount_aircheck.blockhash.." added "..added.." items.")
|
||||
end
|
||||
biome_lib.actioncount_aircheck.blockhash = biome_lib.actioncount_aircheck.blockhash + 1
|
||||
else
|
||||
table.remove(biome_lib.blocklist_aircheck, 1)
|
||||
biome_lib.surface_nodes_aircheck.blockhash = nil
|
||||
biome_lib.actioncount_aircheck.blockhash = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Secondary mapgen spawner, for mods that require disabling of
|
||||
-- checking for air during the initial map read stage.
|
||||
|
||||
function biome_lib:generate_block_no_aircheck()
|
||||
if not biome_lib.blocklist_no_aircheck[1] then
|
||||
return
|
||||
end
|
||||
|
||||
local minp = biome_lib.blocklist_no_aircheck[1][1]
|
||||
local maxp = biome_lib.blocklist_no_aircheck[1][2]
|
||||
|
||||
local blockhash = minetest.hash_node_position(minp)
|
||||
|
||||
if not biome_lib.surface_nodes_no_aircheck.blockhash then
|
||||
biome_lib.surface_nodes_no_aircheck.blockhash =
|
||||
minetest.find_nodes_in_area(minp, maxp, biome_lib.surfaceslist_no_aircheck)
|
||||
biome_lib.actioncount_no_aircheck.blockhash = 1
|
||||
elseif not minetest.get_node_or_nil(minp) then
|
||||
minetest.load_area(minp)
|
||||
else
|
||||
if biome_lib.actionslist_no_aircheck[biome_lib.actioncount_no_aircheck.blockhash] then
|
||||
biome_lib:populate_surfaces(
|
||||
biome_lib.actionslist_no_aircheck[biome_lib.actioncount_no_aircheck.blockhash][1],
|
||||
biome_lib.actionslist_no_aircheck[biome_lib.actioncount_no_aircheck.blockhash][2],
|
||||
biome_lib.surface_nodes_no_aircheck.blockhash, false)
|
||||
biome_lib.actioncount_no_aircheck.blockhash = biome_lib.actioncount_no_aircheck.blockhash + 1
|
||||
else
|
||||
table.remove(biome_lib.blocklist_no_aircheck, 1)
|
||||
biome_lib.surface_nodes_no_aircheck.blockhash = nil
|
||||
biome_lib.actioncount_no_aircheck.blockhash = nil
|
||||
biome_lib.dbg("biome_lib.populate_surfaces ran on mapblock at "..
|
||||
minetest.pos_to_string(minp)..". Entry #"..
|
||||
(biome_lib.pos_hash.action_index-1).." added "..added.." items.", 4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- "Play" them back, populating them with new stuff in the process
|
||||
|
||||
local step_duration = tonumber(minetest.settings:get("dedicated_server_step"))
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if dtime >= step_duration + 0.1 -- don't attempt to populate if lag is already too high
|
||||
or math.random(100) > biome_lib.queue_run_ratio
|
||||
or (#biome_lib.blocklist_aircheck == 0 and #biome_lib.blocklist_no_aircheck == 0) then
|
||||
return
|
||||
end
|
||||
if not biome_lib.block_log[1] then return end -- the block log is empty
|
||||
|
||||
biome_lib.globalstep_start_time = minetest.get_us_time()
|
||||
biome_lib.globalstep_runtime = 0
|
||||
while (#biome_lib.blocklist_aircheck > 0 or #biome_lib.blocklist_no_aircheck > 0)
|
||||
and biome_lib.globalstep_runtime < 200000 do -- 0.2 seconds, in uS.
|
||||
if #biome_lib.blocklist_aircheck > 0 then
|
||||
biome_lib:generate_block_with_air_checking()
|
||||
end
|
||||
if #biome_lib.blocklist_no_aircheck > 0 then
|
||||
biome_lib:generate_block_no_aircheck()
|
||||
end
|
||||
biome_lib.globalstep_runtime = minetest.get_us_time() - biome_lib.globalstep_start_time
|
||||
if math.random(100) > biome_lib.queue_run_ratio then return end
|
||||
for s = 1, biome_lib.entries_per_step do
|
||||
biome_lib.generate_block()
|
||||
end
|
||||
end)
|
||||
|
||||
-- Periodically wake-up the queue to give old blocks a chance to time-out
|
||||
-- if the player isn't currently exploring (i.e. they're just playing in one area)
|
||||
|
||||
function biome_lib.wake_up_queue()
|
||||
if #biome_lib.block_recheck_list > 1
|
||||
and #biome_lib.block_log == 0 then
|
||||
biome_lib.block_log[#biome_lib.block_log + 1] =
|
||||
table.copy(biome_lib.block_recheck_list[#biome_lib.block_recheck_list])
|
||||
biome_lib.block_recheck_list[#biome_lib.block_recheck_list] = nil
|
||||
biome_lib.run_block_recheck_list = true
|
||||
biome_lib.dbg("Woke-up the map queue to give old blocks a chance to time-out.", 3)
|
||||
end
|
||||
minetest.after(biome_lib.block_queue_wakeup_time, biome_lib.wake_up_queue)
|
||||
end
|
||||
|
||||
biome_lib.wake_up_queue()
|
||||
|
||||
-- Play out the entire log all at once on shutdown
|
||||
-- to prevent unpopulated map areas
|
||||
|
||||
local function format_time(t)
|
||||
if t > 59999999 then
|
||||
return os.date("!%M minutes and %S seconds", math.ceil(t/1000000))
|
||||
else
|
||||
return os.date("!%S seconds", math.ceil(t/1000000))
|
||||
end
|
||||
end
|
||||
|
||||
function biome_lib.check_remaining_time()
|
||||
if minetest.get_us_time() > (biome_lib.shutdown_last_timestamp + 10000000) then -- report progress every 10s
|
||||
biome_lib.shutdown_last_timestamp = minetest.get_us_time()
|
||||
|
||||
local entries_remaining = #biome_lib.block_log + #biome_lib.block_recheck_list
|
||||
|
||||
local total_purged = biome_lib.starting_count - entries_remaining
|
||||
local elapsed_time = biome_lib.shutdown_last_timestamp - biome_lib.shutdown_start_time
|
||||
biome_lib.dbg(string.format("%i entries, approximately %s remaining.",
|
||||
entries_remaining, format_time(elapsed_time/total_purged * entries_remaining)))
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
if #biome_lib.blocklist_aircheck == 0 then
|
||||
biome_lib.shutdown_start_time = minetest.get_us_time()
|
||||
biome_lib.shutdown_last_timestamp = minetest.get_us_time()+1
|
||||
|
||||
biome_lib.starting_count = #biome_lib.block_log + #biome_lib.block_recheck_list
|
||||
|
||||
if biome_lib.starting_count == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
print("[biome_lib] Stand by, playing out the rest of the aircheck mapblock log")
|
||||
print("(there are "..#biome_lib.blocklist_aircheck.." entries)...")
|
||||
while #biome_lib.blocklist_aircheck > 0 do
|
||||
biome_lib:generate_block_with_air_checking(0.1)
|
||||
end
|
||||
end)
|
||||
biome_lib.dbg("Stand by, purging the mapblock log "..
|
||||
"(there are "..(#biome_lib.block_log + #biome_lib.block_recheck_list).." entries) ...", 0)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
if #biome_lib.blocklist_aircheck == 0 then
|
||||
return
|
||||
while #biome_lib.block_log > 0 do
|
||||
biome_lib.generate_block(true)
|
||||
biome_lib.check_remaining_time()
|
||||
end
|
||||
|
||||
print("[biome_lib] Stand by, playing out the rest of the no-aircheck mapblock log")
|
||||
print("(there are "..#biome_lib.blocklist_no_aircheck.." entries)...")
|
||||
while #biome_lib.blocklist_no_aircheck > 0 do
|
||||
biome_lib:generate_block_no_aircheck(0.1)
|
||||
if #biome_lib.block_recheck_list > 0 then
|
||||
biome_lib.block_log = table.copy(biome_lib.block_recheck_list)
|
||||
while #biome_lib.block_log > 0 do
|
||||
biome_lib.generate_block(true)
|
||||
biome_lib.check_remaining_time()
|
||||
end
|
||||
end
|
||||
biome_lib.dbg("Log purge completed after "..
|
||||
format_time(minetest.get_us_time() - biome_lib.shutdown_start_time)..".", 0)
|
||||
end)
|
||||
|
||||
-- The spawning ABM
|
||||
|
@ -747,29 +825,34 @@ function biome_lib:get_nodedef_field(nodename, fieldname)
|
|||
return minetest.registered_nodes[nodename][fieldname]
|
||||
end
|
||||
|
||||
if DEBUG then
|
||||
biome_lib.last_count_air = 0
|
||||
biome_lib.last_count_no_air = 0
|
||||
if biome_lib.debug_log_level >= 3 then
|
||||
biome_lib.last_count = 0
|
||||
|
||||
function biome_lib.show_pending_block_counts()
|
||||
if biome_lib.last_count_air ~= #biome_lib.blocklist_aircheck
|
||||
or biome_lib.last_count_no_air ~= #biome_lib.blocklist_no_aircheck then
|
||||
biome_lib:dbg(string.format("Pending block counts, air: %-7i no-air: %i",
|
||||
#biome_lib.blocklist_aircheck, #biome_lib.blocklist_no_aircheck))
|
||||
|
||||
biome_lib.last_count_air = #biome_lib.blocklist_aircheck
|
||||
biome_lib.last_count_no_air = #biome_lib.blocklist_no_aircheck
|
||||
function biome_lib.show_pending_block_count()
|
||||
if biome_lib.last_count ~= #biome_lib.block_log then
|
||||
biome_lib.dbg(string.format("Pending block counts - ready to process: %-8icurrently deferred: %i",
|
||||
#biome_lib.block_log, #biome_lib.block_recheck_list), 3)
|
||||
biome_lib.last_count = #biome_lib.block_log
|
||||
biome_lib.queue_idle_flag = false
|
||||
elseif not biome_lib.queue_idle_flag then
|
||||
if #biome_lib.block_recheck_list > 0 then
|
||||
biome_lib.dbg("Mapblock queue only contains blocks that can't yet be processed.", 3)
|
||||
biome_lib.dbg("Idling the queue until new blocks arrive or the next wake-up call occurs.", 3)
|
||||
else
|
||||
biome_lib.dbg("Mapblock queue has run dry.", 3)
|
||||
biome_lib.dbg("Idling the queue until new blocks arrive.", 3)
|
||||
end
|
||||
minetest.after(1, biome_lib.show_pending_block_counts)
|
||||
biome_lib.queue_idle_flag = true
|
||||
end
|
||||
minetest.after(1, biome_lib.show_pending_block_count)
|
||||
end
|
||||
|
||||
biome_lib.show_pending_block_counts()
|
||||
biome_lib.show_pending_block_count()
|
||||
end
|
||||
|
||||
minetest.after(0, function()
|
||||
print("Registered a total of "..(#biome_lib.surfaceslist_aircheck)+(#biome_lib.surfaceslist_no_aircheck).." surface types to be evaluated, spread")
|
||||
print("across "..#biome_lib.actionslist_aircheck.." actions with air-checking and "..#biome_lib.actionslist_no_aircheck.." actions without.")
|
||||
biome_lib.dbg("Registered a total of "..(#biome_lib.surfaceslist_aircheck)+(#biome_lib.surfaceslist_no_aircheck).." surface types to be evaluated, spread", 0)
|
||||
biome_lib.dbg("across "..#biome_lib.actionslist_aircheck.." actions with air-checking and "..#biome_lib.actionslist_no_aircheck.." actions without.", 0)
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
print("[Biome Lib] Loaded")
|
||||
biome_lib.dbg("[Biome Lib] Loaded", 0)
|
||||
|
|
|
@ -56,6 +56,7 @@ end
|
|||
-- split into individual mapblocks to reduce lag
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, blockseed)
|
||||
local timestamp = minetest.get_us_time()
|
||||
for x = 0, 4 do
|
||||
local minx = minp.x + x*16
|
||||
for y = 0, 4 do
|
||||
|
@ -65,10 +66,10 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
|
|||
|
||||
local bmin = {x=minx, y=miny, z=minz}
|
||||
local bmax = {x=minx + 15, y=miny + 15, z=minz + 15}
|
||||
|
||||
biome_lib.blocklist_aircheck[#biome_lib.blocklist_aircheck + 1] = { bmin, bmax }
|
||||
biome_lib.blocklist_no_aircheck[#biome_lib.blocklist_no_aircheck + 1] = { bmin, bmax }
|
||||
biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, true, timestamp }
|
||||
biome_lib.block_log[#biome_lib.block_log + 1] = { bmin, bmax, false, timestamp }
|
||||
end
|
||||
end
|
||||
end
|
||||
biome_lib.run_block_recheck_list = true
|
||||
end)
|
||||
|
|
|
@ -639,3 +639,25 @@ minetest.register_craft({
|
|||
{"group:food_skillet", "farming:skillet"}
|
||||
}
|
||||
})
|
||||
|
||||
-- Mochi
|
||||
|
||||
minetest.register_craftitem("farming:mochi", {
|
||||
description = S("Mochi"),
|
||||
inventory_image = "farming_mochi.png",
|
||||
on_use = minetest.item_eat(3),
|
||||
groups = {flammable = 2},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "farming:mochi",
|
||||
recipe = {
|
||||
"group:food_mortar_pestle", "group:food_rice", "group:food_rice",
|
||||
"group:food_sugar", "bucket:bucket_river_water"
|
||||
},
|
||||
replacements = {
|
||||
{"group:food_mortar_pestle", "farming:mortar_pestle"},
|
||||
{"bucket:bucket_river_water", "bucket:bucket_empty"}
|
||||
}
|
||||
})
|
||||
|
|
BIN
mods/farming/textures/farming_mochi.png
Normal file
BIN
mods/farming/textures/farming_mochi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 212 B |
|
@ -138,7 +138,7 @@ mobs:register_arrow("mobs_animal:egg_entity", {
|
|||
end,
|
||||
|
||||
hit_mob = function(self, player)
|
||||
player:punch(minetest.get_player_by_name(self.playername) or self.object, 1.0, {
|
||||
player:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 1},
|
||||
}, nil)
|
||||
|
@ -213,6 +213,7 @@ local mobs_shoot_egg = function (item, player, pointed_thing)
|
|||
|
||||
ent.velocity = egg_VELOCITY -- needed for api internal timing
|
||||
ent.switch = 1 -- needed so that egg doesn't despawn straight away
|
||||
ent._is_arrow = true -- tell advanced mob protection this is an arrow
|
||||
|
||||
obj:setvelocity({
|
||||
x = dir.x * egg_VELOCITY,
|
||||
|
|
|
@ -8,7 +8,7 @@ local use_cmi = minetest.global_exists("cmi")
|
|||
|
||||
mobs = {
|
||||
mod = "redo",
|
||||
version = "20210405",
|
||||
version = "20210407",
|
||||
intllib = S,
|
||||
invis = minetest.global_exists("invisibility") and invisibility or {}
|
||||
}
|
||||
|
@ -4499,8 +4499,9 @@ function mobs:capture_mob(self, clicker, chance_hand, chance_net,
|
|||
return false
|
||||
end
|
||||
|
||||
-- cannot pick up if not owner
|
||||
if self.owner ~= name and force_take == false then
|
||||
-- cannot pick up if not owner (unless player has protection_bypass priv)
|
||||
if not minetest.check_player_privs(name, "protection_bypass")
|
||||
and self.owner ~= name and force_take == false then
|
||||
|
||||
minetest.chat_send_player(name, S("@1 is owner!", self.owner))
|
||||
|
||||
|
@ -4729,12 +4730,12 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
|
|||
end
|
||||
|
||||
local item = clicker:get_wielded_item()
|
||||
local name = clicker:get_player_name()
|
||||
|
||||
-- if mob has been tamed you can name it with a nametag
|
||||
if item:get_name() == "mobs:nametag"
|
||||
and clicker:get_player_name() == self.owner then
|
||||
|
||||
local name = clicker:get_player_name()
|
||||
and (name == self.owner
|
||||
or minetest.check_player_privs(name, "protection_bypass")) then
|
||||
|
||||
-- store mob and nametag stack in external variables
|
||||
mob_obj[name] = self
|
||||
|
|
|
@ -29,7 +29,10 @@ local dropbox = gen_def({
|
|||
return 0
|
||||
end
|
||||
return stack_count
|
||||
end
|
||||
end,
|
||||
allow_metadata_inventory_take = actions.get_allow_metadata_inventory_take({
|
||||
"dropbox", check_privs = actions.has_locked_chest_privilege
|
||||
}),
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ for i in ipairs(moretrees.treelist) do
|
|||
grow_function = "moretrees.grow_"..treename
|
||||
end
|
||||
|
||||
biome_lib:dbg(dump(moretrees[tree_biome].surface))
|
||||
biome_lib.dbg(dump(moretrees[tree_biome].surface), 4)
|
||||
|
||||
biome_lib:grow_plants({
|
||||
grow_delay = moretrees.sapling_interval,
|
||||
|
|
|
@ -7,6 +7,8 @@ local mname = "cavestuff"
|
|||
-- support for i18n
|
||||
local S = minetest.get_translator("cavestuff")
|
||||
|
||||
cavestuff = {}
|
||||
|
||||
dofile(minetest.get_modpath("cavestuff").."/nodes.lua")
|
||||
dofile(minetest.get_modpath("cavestuff").."/mapgen.lua")
|
||||
|
||||
|
|
|
@ -1,52 +1,39 @@
|
|||
--Map Generation Stuff
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
if maxp.y >= 2 and minp.y <= 0 then
|
||||
-- Generate pebbles
|
||||
local perlin1 = minetest.get_perlin(329, 3, 0.6, 100)
|
||||
-- Assume X and Z lengths are equal
|
||||
local divlen = 16
|
||||
local divs = (maxp.x-minp.x)/divlen+1;
|
||||
for divx=0,divs-1 do
|
||||
for divz=0,divs-1 do
|
||||
local x0 = minp.x + math.floor((divx+0)*divlen)
|
||||
local z0 = minp.z + math.floor((divz+0)*divlen)
|
||||
local x1 = minp.x + math.floor((divx+1)*divlen)
|
||||
local z1 = minp.z + math.floor((divz+1)*divlen)
|
||||
-- Determine pebble amount from perlin noise
|
||||
local pebble_amount = math.floor(perlin1:get2d({x=x0, y=z0}) ^ 2 * 2)
|
||||
-- Find random positions for pebbles based on this random
|
||||
local pr = PseudoRandom(seed+1)
|
||||
for i=0,pebble_amount do
|
||||
local x = pr:next(x0, x1)
|
||||
local z = pr:next(z0, z1)
|
||||
-- Find ground level (0...15)
|
||||
local ground_y = nil
|
||||
for y=30,0,-1 do
|
||||
if minetest.get_node({x=x,y=y,z=z}).name ~= "air" then
|
||||
ground_y = y
|
||||
break
|
||||
end
|
||||
end
|
||||
biome_lib:register_generate_plant(
|
||||
{
|
||||
surface = {
|
||||
"default:dirt_with_grass",
|
||||
"default:gravel",
|
||||
"default:stone",
|
||||
"default:permafrost_with_stones"
|
||||
},
|
||||
max_count = 50,
|
||||
rarity = 0,
|
||||
plantlife_limit = -1,
|
||||
check_air = true,
|
||||
random_facedir = {0, 3}
|
||||
},
|
||||
{
|
||||
"cavestuff:pebble_1",
|
||||
"cavestuff:pebble_2"
|
||||
}
|
||||
)
|
||||
|
||||
if ground_y then
|
||||
local p = {x=x,y=ground_y+1,z=z}
|
||||
local nn = minetest.get_node(p).name
|
||||
-- Check if the node can be replaced
|
||||
if minetest.registered_nodes[nn] and
|
||||
minetest.registered_nodes[nn].buildable_to then
|
||||
nn = minetest.get_node({x=x,y=ground_y,z=z}).name
|
||||
-- If desert sand, add dry shrub
|
||||
if nn == "default:dirt_with_grass" then
|
||||
minetest.swap_node(p,{name="cavestuff:pebble_"..pr:next(1,2), param2=math.random(0,3)})
|
||||
elseif nn == "default:desert_sand" then
|
||||
minetest.swap_node(p,{name="cavestuff:desert_pebble_"..pr:next(1,2), param2=math.random(0,3)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
biome_lib:register_generate_plant(
|
||||
{
|
||||
surface = {
|
||||
"default:desert_sand",
|
||||
"default:desert_stone"
|
||||
},
|
||||
max_count = 50,
|
||||
rarity = 0,
|
||||
plantlife_limit = -1,
|
||||
check_air = true,
|
||||
random_facedir = {0, 3}
|
||||
},
|
||||
{
|
||||
"cavestuff:desert_pebble_1",
|
||||
"cavestuff:desert_pebble_2"
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
name = cavestuff
|
||||
depends = default
|
||||
depends = default,biome_lib
|
||||
|
|
|
@ -7,16 +7,8 @@
|
|||
-- Looked at code from: default
|
||||
-----------------------------------------------------------------------------------------------
|
||||
|
||||
abstract_dryplants.grow_grass = function(pos)
|
||||
local right_here = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
local grass_size = math.random(1,5)
|
||||
if minetest.get_node(right_here).name == "air" -- instead of check_air = true,
|
||||
or minetest.get_node(right_here).name == "default:junglegrass" then
|
||||
minetest.swap_node(right_here, {name="default:grass_"..grass_size})
|
||||
end
|
||||
end
|
||||
|
||||
biome_lib:register_generate_plant({
|
||||
biome_lib:register_generate_plant(
|
||||
{
|
||||
surface = {
|
||||
"default:dirt_with_grass",
|
||||
"stoneage:grass_with_silex",
|
||||
|
@ -27,6 +19,12 @@ biome_lib:register_generate_plant({
|
|||
rarity = 101 - TALL_GRASS_RARITY,
|
||||
min_elevation = 1, -- above sea level
|
||||
plantlife_limit = -0.9,
|
||||
check_air = true,
|
||||
},
|
||||
abstract_dryplants.grow_grass
|
||||
{ "default:grass_1",
|
||||
"default:grass_2",
|
||||
"default:grass_3",
|
||||
"default:grass_4",
|
||||
"default:grass_5"
|
||||
}
|
||||
)
|
||||
|
|
|
@ -20,6 +20,7 @@ https://forum.minetest.net/viewtopic.php?t=10090&p=153667
|
|||
- 1.2 - Added POVA support, tweaked code slightly
|
||||
- 1.3 - Add setting under Advanced to enable older sneak glitch movement
|
||||
- 1.4 - Add minetest 5.0 check for knockback y_offset
|
||||
- 1.5 - Use Minetext 5.x functions for proper player knockback
|
||||
|
||||
API:
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ minetest.register_globalstep(function(dtime)
|
|||
time = 0
|
||||
|
||||
-- define locals outside loop
|
||||
local name, pos, ndef, def, nslow, nfast
|
||||
local name, pos, ndef, def, nslow, nfast, prop
|
||||
|
||||
-- get list of players
|
||||
local players = minetest.get_connected_players()
|
||||
|
@ -66,8 +66,8 @@ if name and playerplus[name] then
|
|||
pos = player:get_pos()
|
||||
|
||||
-- what is around me?
|
||||
pos.y = pos.y - 0.1 -- standing on
|
||||
playerplus[name].nod_stand = node_ok(pos)
|
||||
playerplus[name].nod_stand = node_ok({
|
||||
x = pos.x, y = pos.y - 0.1, z = pos.z})
|
||||
|
||||
-- Does the node below me have an on_walk_over function set?
|
||||
ndef = minetest.registered_nodes[playerplus[name].nod_stand]
|
||||
|
@ -75,13 +75,15 @@ if name and playerplus[name] then
|
|||
ndef.on_walk_over(pos, ndef, player)
|
||||
end
|
||||
|
||||
pos.y = pos.y + 1.5 -- head level
|
||||
playerplus[name].nod_head = node_ok(pos)
|
||||
prop = player:get_properties()
|
||||
|
||||
pos.y = pos.y - 1.2 -- feet level
|
||||
playerplus[name].nod_feet = node_ok(pos)
|
||||
-- node at eye level
|
||||
playerplus[name].nod_head = node_ok({
|
||||
x = pos.x, y = pos.y + prop.eye_height, z = pos.z})
|
||||
|
||||
pos.y = pos.y - 0.2 -- reset pos
|
||||
-- node at foot level
|
||||
playerplus[name].nod_feet = node_ok({
|
||||
x = pos.x, y = pos.y + 0.2, z = pos.z})
|
||||
|
||||
-- get player physics
|
||||
def = player:get_physics_override()
|
||||
|
@ -247,29 +249,19 @@ minetest.register_privilege("no_knockback", {
|
|||
-- is player knock-back effect enabled?
|
||||
if minetest.settings:get_bool("player_knockback") == true then
|
||||
|
||||
minetest.register_entity("playerplus:temp", {
|
||||
physical = true,
|
||||
collisionbox = {-0.20, -1, -0.20, 0.20, 1, 0.20},
|
||||
visual_size = {x = 0, y = 0},
|
||||
visual = "sprite",
|
||||
textures = {"trans.png"},
|
||||
stepheight = 0.6,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
|
||||
self.timer = (self.timer or 0) + dtime
|
||||
|
||||
if self.timer > 1 then
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
-- player knock-back function
|
||||
local punchy = function(
|
||||
player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
|
||||
if not dir then return end
|
||||
|
||||
-- check if player has 'no_knockback' privelage
|
||||
local privs = minetest.get_player_privs(player:get_player_name())
|
||||
|
||||
if privs["no_knockback"] then
|
||||
return
|
||||
end
|
||||
|
||||
local damage = 0
|
||||
|
||||
-- get tool damage
|
||||
|
@ -289,7 +281,6 @@ local punchy = function(
|
|||
end
|
||||
|
||||
damage = damage + (tool_capabilities.damage_groups[group] or 0) * tmp
|
||||
|
||||
end
|
||||
|
||||
-- check for knockback value
|
||||
|
@ -302,48 +293,12 @@ local punchy = function(
|
|||
|
||||
-- print ("---", player:get_player_name(), damage)
|
||||
|
||||
if not dir then return end
|
||||
|
||||
-- check if player has 'no_knockback' privelage
|
||||
local privs = minetest.get_player_privs(player:get_player_name())
|
||||
|
||||
if privs["no_knockback"] then
|
||||
return
|
||||
end
|
||||
|
||||
local y_offset = mt50 and -10 or 0
|
||||
local vel = damage * 2
|
||||
local pos = player:get_pos() ; pos.y = pos.y + 1.0
|
||||
local ent = minetest.add_entity(pos, "playerplus:temp")
|
||||
local obj = ent:get_luaentity()
|
||||
local yaw = player:get_look_horizontal() or 0 ; yaw = -yaw * (180 / 3.14) -- pi
|
||||
|
||||
if obj and not player:get_attach() then
|
||||
|
||||
player:set_attach(ent, "", {x = 0, y = y_offset, z = 0}, {x = 0, y = yaw, z = 0})
|
||||
|
||||
ent:set_velocity({
|
||||
x = dir.x * vel,
|
||||
-- knock back player
|
||||
player:add_velocity({
|
||||
x = dir.x * (damage * 2),
|
||||
y = -1,
|
||||
z = dir.z * vel
|
||||
z = dir.z * (damage * 2)
|
||||
})
|
||||
|
||||
ent:set_acceleration({
|
||||
x = dir.x * -1,
|
||||
y = 0,
|
||||
z = dir.z * -1
|
||||
})
|
||||
|
||||
minetest.after(0.25, function()
|
||||
|
||||
player:set_detach()
|
||||
|
||||
ent:remove()
|
||||
end)
|
||||
|
||||
else
|
||||
ent:remove()
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_punchplayer(punchy)
|
||||
|
|
|
@ -544,7 +544,7 @@ minetest.register_node("protector:chest", {
|
|||
local inv = meta:get_inventory()
|
||||
|
||||
meta:set_string("infotext", S("Protected Chest"))
|
||||
meta:set_string("name", "")
|
||||
meta:set_string("name", S("Protected Chest"))
|
||||
inv:set_size("main", 8 * 4)
|
||||
end,
|
||||
|
||||
|
@ -575,7 +575,8 @@ minetest.register_node("protector:chest", {
|
|||
minetest.pos_to_string(pos))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
on_metadata_inventory_move = function(
|
||||
pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
minetest.log("action", player:get_player_name() ..
|
||||
" moves stuff inside protected chest at " ..
|
||||
|
@ -600,7 +601,8 @@ minetest.register_node("protector:chest", {
|
|||
return stack:get_count()
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
allow_metadata_inventory_move = function(
|
||||
pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
|
@ -645,15 +647,39 @@ minetest.register_node("protector:chest", {
|
|||
on_blast = function() end,
|
||||
})
|
||||
|
||||
-- Container transfer helper
|
||||
local to_from = function(src, dst)
|
||||
|
||||
local stack, item, leftover
|
||||
local size = dst:get_size("main")
|
||||
|
||||
for i = 1, size do
|
||||
|
||||
stack = src:get_stack("main", i)
|
||||
item = stack:get_name()
|
||||
|
||||
if item ~= "" and dst:room_for_item("main", item) then
|
||||
|
||||
leftover = dst:add_item("main", stack)
|
||||
|
||||
if leftover and not leftover:is_empty() then
|
||||
src:set_stack("main", i, leftover)
|
||||
else
|
||||
src:set_stack("main", i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Protected Chest formspec buttons
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
|
||||
if string.sub(formname, 0, string.len("protector:chest_")) ~= "protector:chest_" then
|
||||
if string.sub(formname, 0, 16) ~= "protector:chest_" then
|
||||
return
|
||||
end
|
||||
|
||||
local pos_s = string.sub(formname,string.len("protector:chest_") + 1)
|
||||
local pos_s = string.sub(formname, 17)
|
||||
local pos = minetest.string_to_pos(pos_s)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
|
@ -663,43 +689,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
local meta = minetest.get_meta(pos) ; if not meta then return end
|
||||
local chest_inv = meta:get_inventory() ; if not chest_inv then return end
|
||||
local player_inv = player:get_inventory()
|
||||
local leftover
|
||||
|
||||
-- copy contents of player inventory to chest
|
||||
if fields.toup then
|
||||
|
||||
-- copy contents of players inventory to chest
|
||||
for i, v in ipairs(player_inv:get_list("main") or {}) do
|
||||
|
||||
if chest_inv:room_for_item("main", v) then
|
||||
|
||||
leftover = chest_inv:add_item("main", v)
|
||||
|
||||
player_inv:remove_item("main", v)
|
||||
|
||||
if leftover
|
||||
and not leftover:is_empty() then
|
||||
player_inv:add_item("main", v)
|
||||
end
|
||||
end
|
||||
end
|
||||
to_from(player_inv, chest_inv)
|
||||
|
||||
-- copy contents of chest to player inventory
|
||||
elseif fields.todn then
|
||||
|
||||
-- copy contents of chest to players inventory
|
||||
for i, v in ipairs(chest_inv:get_list("main") or {}) do
|
||||
|
||||
if player_inv:room_for_item("main", v) then
|
||||
|
||||
leftover = player_inv:add_item("main", v)
|
||||
|
||||
chest_inv:remove_item("main", v)
|
||||
|
||||
if leftover
|
||||
and not leftover:is_empty() then
|
||||
chest_inv:add_item("main", v)
|
||||
end
|
||||
end
|
||||
end
|
||||
to_from(chest_inv, player_inv)
|
||||
|
||||
elseif fields.chestname then
|
||||
|
||||
|
@ -707,9 +706,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
if fields.chestname ~= "" then
|
||||
|
||||
meta:set_string("name", fields.chestname)
|
||||
meta:set_string("infotext",
|
||||
S("Protected Chest (@1)", fields.chestname))
|
||||
meta:set_string("infotext", fields.chestname)
|
||||
else
|
||||
meta:set_string("name", S("Protected Chest"))
|
||||
meta:set_string("infotext", S("Protected Chest"))
|
||||
end
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ read_globals = {
|
|||
"ItemStack", "datastorage",
|
||||
|
||||
"hb",
|
||||
"doors",
|
||||
}
|
||||
|
||||
files["callbacks.lua"].ignore = { "player", "draw_lite_mode" }
|
||||
|
|
|
@ -19,6 +19,8 @@ minetest.register_on_joinplayer(function(player)
|
|||
unified_inventory.active_search_direction[player_name] = "nochange"
|
||||
unified_inventory.apply_filter(player, "", "nochange")
|
||||
unified_inventory.current_searchbox[player_name] = ""
|
||||
unified_inventory.current_category[player_name] = "all"
|
||||
unified_inventory.current_category_scroll[player_name] = 0
|
||||
unified_inventory.alternate[player_name] = 1
|
||||
unified_inventory.current_item[player_name] = nil
|
||||
unified_inventory.current_craft_direction[player_name] = "recipe"
|
||||
|
@ -69,6 +71,41 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
unified_inventory.current_searchbox[player_name] = fields.searchbox
|
||||
end
|
||||
|
||||
|
||||
local clicked_category
|
||||
for name, value in pairs(fields) do
|
||||
local category_name = string.match(name, "^category_(.+)$")
|
||||
if category_name then
|
||||
clicked_category = category_name
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if clicked_category
|
||||
and clicked_category ~= unified_inventory.current_category[player_name] then
|
||||
unified_inventory.current_category[player_name] = clicked_category
|
||||
unified_inventory.apply_filter(player, unified_inventory.current_searchbox[player_name], "nochange")
|
||||
unified_inventory.set_inventory_formspec(player,
|
||||
unified_inventory.current_page[player_name])
|
||||
end
|
||||
|
||||
if fields.next_category then
|
||||
local scroll = math.min(#unified_inventory.category_list-ui_peruser.pagecols, unified_inventory.current_category_scroll[player_name] + 1)
|
||||
if scroll ~= unified_inventory.current_category_scroll[player_name] then
|
||||
unified_inventory.current_category_scroll[player_name] = scroll
|
||||
unified_inventory.set_inventory_formspec(player,
|
||||
unified_inventory.current_page[player_name])
|
||||
end
|
||||
end
|
||||
if fields.prev_category then
|
||||
local scroll = math.max(0, unified_inventory.current_category_scroll[player_name] - 1)
|
||||
if scroll ~= unified_inventory.current_category_scroll[player_name] then
|
||||
unified_inventory.current_category_scroll[player_name] = scroll
|
||||
unified_inventory.set_inventory_formspec(player,
|
||||
unified_inventory.current_page[player_name])
|
||||
end
|
||||
end
|
||||
|
||||
for i, def in pairs(unified_inventory.buttons) do
|
||||
if fields[def.name] then
|
||||
def.action(player)
|
||||
|
@ -126,6 +163,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
clicked_item = unified_inventory.demangle_for_formspec(mangled_item)
|
||||
if string.sub(clicked_item, 1, 6) == "group:" then
|
||||
-- Change search filter to this group
|
||||
unified_inventory.current_category[player_name] = "all"
|
||||
apply_new_filter(player, clicked_item, new_dir)
|
||||
return
|
||||
end
|
||||
|
|
149
mods/unified_inventory/category.lua
Normal file
149
mods/unified_inventory/category.lua
Normal file
|
@ -0,0 +1,149 @@
|
|||
local S = minetest.get_translator("unified_inventory")
|
||||
|
||||
unified_inventory.registered_categories = {}
|
||||
unified_inventory.registered_category_items = {}
|
||||
unified_inventory.category_list = {}
|
||||
|
||||
local function char_to_sort_index(char_code)
|
||||
if char_code <= 32 then
|
||||
-- Command codes, no thanks
|
||||
return 0
|
||||
end
|
||||
if char_code <= 64 then
|
||||
-- Sorts numbers, and some punctuation, after letters
|
||||
return char_code
|
||||
end
|
||||
if char_code >= 158 then
|
||||
-- Out of sortable range
|
||||
return 0
|
||||
end
|
||||
if char_code > 122 then
|
||||
-- Avoids overlap with {, |, } and ~
|
||||
return char_code - 58
|
||||
end
|
||||
if char_code > 96 then
|
||||
-- Normalises lowercase with uppercase
|
||||
return char_code - 96
|
||||
end
|
||||
return char_code - 64
|
||||
end
|
||||
|
||||
local function string_to_sort_index(str)
|
||||
local max_chars = 5
|
||||
local power = 100
|
||||
local index = 0
|
||||
for i=1,math.min(#str, max_chars) do
|
||||
index = index + (char_to_sort_index(string.byte(str, i))/(power^i))
|
||||
end
|
||||
return index
|
||||
end
|
||||
|
||||
function update_category_list()
|
||||
local category_list = {}
|
||||
table.insert(category_list, {
|
||||
name = "all",
|
||||
label = S("All Items"),
|
||||
symbol = "ui_category_all.png",
|
||||
index = -2,
|
||||
})
|
||||
table.insert(category_list, {
|
||||
name = "uncategorized",
|
||||
label = S("Misc. Items"),
|
||||
symbol = "ui_category_none.png",
|
||||
index = -1,
|
||||
})
|
||||
for category, def in pairs(unified_inventory.registered_categories) do
|
||||
table.insert(category_list, {
|
||||
name = category,
|
||||
label = def.label or category,
|
||||
symbol = def.symbol,
|
||||
index = def.index or -- sortby defined order
|
||||
string_to_sort_index(category) -- or do a rudimentary alphabetical sort
|
||||
})
|
||||
end
|
||||
table.sort(category_list, function (a,b)
|
||||
return a.index < b.index
|
||||
end)
|
||||
unified_inventory.category_list = category_list
|
||||
end
|
||||
|
||||
local function ensure_category_exists(category_name)
|
||||
if not unified_inventory.registered_categories[category_name] then
|
||||
unified_inventory.registered_categories[category_name] = {
|
||||
symbol = "default:stick",
|
||||
label = category_name
|
||||
}
|
||||
end
|
||||
if not unified_inventory.registered_category_items[category_name] then
|
||||
unified_inventory.registered_category_items[category_name] = {}
|
||||
end
|
||||
end
|
||||
|
||||
function unified_inventory.register_category(category_name, config)
|
||||
ensure_category_exists(category_name)
|
||||
if config and config.symbol then
|
||||
unified_inventory.set_category_symbol(category_name, config.symbol)
|
||||
end
|
||||
if config and config.label then
|
||||
unified_inventory.set_category_label(category_name, config.label)
|
||||
end
|
||||
if config and config.index then
|
||||
unified_inventory.set_category_index(category_name, config.index)
|
||||
end
|
||||
if config and config.items then
|
||||
unified_inventory.add_category_items(category_name, config.items)
|
||||
end
|
||||
update_category_list()
|
||||
end
|
||||
function unified_inventory.set_category_symbol(category_name, symbol)
|
||||
ensure_category_exists(category_name)
|
||||
unified_inventory.registered_categories[category_name].symbol = symbol
|
||||
update_category_list()
|
||||
end
|
||||
function unified_inventory.set_category_label(category_name, label)
|
||||
ensure_category_exists(category_name)
|
||||
unified_inventory.registered_categories[category_name].label = label
|
||||
update_category_list()
|
||||
end
|
||||
function unified_inventory.set_category_index(category_name, index)
|
||||
ensure_category_exists(category_name)
|
||||
unified_inventory.registered_categories[category_name].index = index
|
||||
update_category_list()
|
||||
end
|
||||
function unified_inventory.add_category_item(category_name, item)
|
||||
ensure_category_exists(category_name)
|
||||
unified_inventory.registered_category_items[category_name][item] = true
|
||||
end
|
||||
function unified_inventory.add_category_items(category_name, items)
|
||||
for _,item in ipairs(items) do
|
||||
unified_inventory.add_category_item(category_name, item)
|
||||
end
|
||||
end
|
||||
|
||||
function unified_inventory.remove_category_item(category_name, item)
|
||||
unified_inventory.registered_category_items[category_name][item] = nil
|
||||
end
|
||||
function unified_inventory.remove_category(category_name)
|
||||
unified_inventory.registered_categories[category_name] = nil
|
||||
unified_inventory.registered_category_items[category_name] = nil
|
||||
update_category_list()
|
||||
end
|
||||
|
||||
function unified_inventory.find_category(item)
|
||||
-- Returns the first category the item exists in
|
||||
-- Best for checking if an item has any category at all
|
||||
for category, items in pairs(unified_inventory.registered_category_items) do
|
||||
if items[item] then return category end
|
||||
end
|
||||
end
|
||||
function unified_inventory.find_categories(item)
|
||||
-- Returns all the categories the item exists in
|
||||
-- Best for listing all categories
|
||||
local categories = {}
|
||||
for category, items in pairs(unified_inventory.registered_category_items) do
|
||||
if items[item] then
|
||||
table.insert(categories, category)
|
||||
end
|
||||
end
|
||||
return categories
|
||||
end
|
704
mods/unified_inventory/default-categories.lua
Normal file
704
mods/unified_inventory/default-categories.lua
Normal file
|
@ -0,0 +1,704 @@
|
|||
local S = minetest.get_translator("unified_inventory")
|
||||
|
||||
unified_inventory.register_category('plants', {
|
||||
symbol = "flowers:tulip",
|
||||
label = S("Plant Life")
|
||||
})
|
||||
unified_inventory.register_category('building', {
|
||||
symbol = "default:brick",
|
||||
label = S("Building Materials")
|
||||
})
|
||||
unified_inventory.register_category('tools', {
|
||||
symbol = "default:pick_diamond",
|
||||
label = S("Tools")
|
||||
})
|
||||
unified_inventory.register_category('minerals', {
|
||||
symbol = "default:iron_lump",
|
||||
label = S("Minerals and Metals")
|
||||
})
|
||||
unified_inventory.register_category('environment', {
|
||||
symbol = "default:dirt_with_grass",
|
||||
label = S("Environment and Worldgen")
|
||||
})
|
||||
unified_inventory.register_category('lighting', {
|
||||
symbol = "default:torch",
|
||||
label = S("Lighting")
|
||||
})
|
||||
|
||||
|
||||
if unified_inventory.automatic_categorization then
|
||||
minetest.register_on_mods_loaded(function()
|
||||
|
||||
-- Add biome nodes to environment category
|
||||
for _,def in pairs(minetest.registered_biomes) do
|
||||
local env_nodes = {
|
||||
def.node_riverbed, def.node_top, def.node_filler, def.node_dust,
|
||||
}
|
||||
for i,node in pairs(env_nodes) do
|
||||
if node then
|
||||
unified_inventory.add_category_item('environment', node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add minable ores to minerals and everything else (pockets of stone & sand variations) to environment
|
||||
for _,item in pairs(minetest.registered_ores) do
|
||||
if item.ore_type == "scatter" then
|
||||
local drop = minetest.registered_nodes[item.ore].drop
|
||||
if drop and drop ~= "" then
|
||||
unified_inventory.add_category_item('minerals', item.ore)
|
||||
unified_inventory.add_category_item('minerals', drop)
|
||||
else
|
||||
unified_inventory.add_category_item('environment', item.ore)
|
||||
end
|
||||
else
|
||||
unified_inventory.add_category_item('environment', item.ore)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add items by item definition
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
local group = def.groups or {}
|
||||
if not group.not_in_creative_inventory then
|
||||
if group.stair or
|
||||
group.slab or
|
||||
group.wall or
|
||||
group.fence then
|
||||
unified_inventory.add_category_item('building', name)
|
||||
elseif group.flora or
|
||||
group.flower or
|
||||
group.seed or
|
||||
group.leaves or
|
||||
group.sapling or
|
||||
group.tree then
|
||||
unified_inventory.add_category_item('plants', name)
|
||||
elseif def.type == 'tool' then
|
||||
unified_inventory.add_category_item('tools', name)
|
||||
elseif def.liquidtype == 'source' then
|
||||
unified_inventory.add_category_item('environment', name)
|
||||
elseif def.light_source and def.light_source > 0 then
|
||||
unified_inventory.add_category_item('lighting', name)
|
||||
elseif group.door or
|
||||
minetest.global_exists("doors") and (
|
||||
doors.registered_doors and doors.registered_doors[name..'_a'] or
|
||||
doors.registered_trapdoors and doors.registered_trapdoors[name]
|
||||
) then
|
||||
unified_inventory.add_category_item('building', name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- [[
|
||||
unified_inventory.add_category_items('plants', {
|
||||
"default:dry_grass_5",
|
||||
"default:acacia_sapling",
|
||||
"default:blueberry_bush_sapling",
|
||||
"default:grass_2",
|
||||
"default:pine_bush_stem",
|
||||
"default:leaves",
|
||||
"default:pine_needles",
|
||||
"default:cactus",
|
||||
"default:junglegrass",
|
||||
"default:pine_sapling",
|
||||
"default:sapling",
|
||||
"default:bush_stem",
|
||||
"default:dry_grass_2",
|
||||
"default:fern_1",
|
||||
"default:grass_3",
|
||||
"default:marram_grass_1",
|
||||
"default:pine_tree",
|
||||
"default:dry_grass_3",
|
||||
"default:dry_shrub",
|
||||
"default:grass_4",
|
||||
"default:marram_grass_2",
|
||||
"default:jungleleaves",
|
||||
"default:apple",
|
||||
"default:tree",
|
||||
"default:aspen_tree",
|
||||
"default:bush_sapling",
|
||||
"default:grass_5",
|
||||
"default:blueberry_bush_leaves_with_berries",
|
||||
"default:acacia_bush_sapling",
|
||||
"default:grass_1",
|
||||
"default:aspen_leaves",
|
||||
"default:marram_grass_3",
|
||||
"default:large_cactus_seedling",
|
||||
"default:junglesapling",
|
||||
"default:dry_grass_4",
|
||||
"default:acacia_bush_stem",
|
||||
"default:papyrus",
|
||||
"default:pine_bush_needles",
|
||||
"default:bush_leaves",
|
||||
"default:fern_3",
|
||||
"default:aspen_sapling",
|
||||
"default:acacia_tree",
|
||||
"default:apple_mark",
|
||||
"default:acacia_leaves",
|
||||
"default:jungletree",
|
||||
"default:dry_grass_1",
|
||||
"default:acacia_bush_leaves",
|
||||
"default:emergent_jungle_sapling",
|
||||
"default:fern_2",
|
||||
"default:blueberries",
|
||||
"default:sand_with_kelp",
|
||||
"default:blueberry_bush_leaves",
|
||||
"default:pine_bush_sapling",
|
||||
|
||||
"farming:cotton",
|
||||
"farming:cotton_1",
|
||||
"farming:cotton_2",
|
||||
"farming:cotton_3",
|
||||
"farming:cotton_4",
|
||||
"farming:cotton_5",
|
||||
"farming:cotton_6",
|
||||
"farming:cotton_7",
|
||||
"farming:cotton_8",
|
||||
"farming:cotton_wild",
|
||||
"farming:seed_cotton",
|
||||
"farming:seed_wheat",
|
||||
"farming:straw",
|
||||
"farming:wheat",
|
||||
"farming:wheat_1",
|
||||
"farming:wheat_2",
|
||||
"farming:wheat_3",
|
||||
"farming:wheat_4",
|
||||
"farming:wheat_5",
|
||||
"farming:wheat_6",
|
||||
"farming:wheat_7",
|
||||
"farming:wheat_8",
|
||||
|
||||
"flowers:chrysanthemum_green",
|
||||
"flowers:dandelion_white",
|
||||
"flowers:dandelion_yellow",
|
||||
"flowers:geranium",
|
||||
"flowers:mushroom_brown",
|
||||
"flowers:mushroom_red",
|
||||
"flowers:rose",
|
||||
"flowers:tulip",
|
||||
"flowers:tulip_black",
|
||||
"flowers:viola",
|
||||
"flowers:waterlily",
|
||||
"flowers:waterlily_waving",
|
||||
})
|
||||
|
||||
unified_inventory.add_category_items('tools', {
|
||||
"default:sword_diamond",
|
||||
"default:axe_diamond",
|
||||
"default:shovel_diamond",
|
||||
"default:axe_steel",
|
||||
"default:shovel_mese",
|
||||
"default:sword_wood",
|
||||
"default:pick_bronze",
|
||||
"default:axe_stone",
|
||||
"default:sword_stone",
|
||||
"default:pick_stone",
|
||||
"default:shovel_stone",
|
||||
"default:sword_mese",
|
||||
"default:shovel_bronze",
|
||||
"default:sword_bronze",
|
||||
"default:axe_bronze",
|
||||
"default:shovel_steel",
|
||||
"default:sword_steel",
|
||||
"default:axe_mese",
|
||||
"default:shovel_wood",
|
||||
"default:pick_mese",
|
||||
"default:axe_wood",
|
||||
"default:pick_diamond",
|
||||
"default:pick_wood",
|
||||
"default:pick_steel",
|
||||
|
||||
"farming:hoe_bronze",
|
||||
"farming:hoe_diamond",
|
||||
"farming:hoe_mese",
|
||||
"farming:hoe_steel",
|
||||
"farming:hoe_stone",
|
||||
"farming:hoe_wood",
|
||||
|
||||
"fire:flint_and_steel",
|
||||
"map:mapping_kit",
|
||||
"screwdriver:screwdriver",
|
||||
|
||||
"fireflies:bug_net",
|
||||
"bucket:bucket_empty",
|
||||
|
||||
"binoculars:binoculars",
|
||||
"default:skeleton_key",
|
||||
})
|
||||
|
||||
unified_inventory.add_category_items('minerals', {
|
||||
"default:stone_with_copper",
|
||||
"default:stone_with_gold",
|
||||
"default:stone_with_iron",
|
||||
"default:copper_ingot",
|
||||
"default:copper_lump",
|
||||
"default:gold_lump",
|
||||
"default:diamondblock",
|
||||
"default:stone_with_diamond",
|
||||
"default:stone_with_mese",
|
||||
"default:steel_ingot",
|
||||
"default:gold_ingot",
|
||||
"default:iron_lump",
|
||||
"default:tinblock",
|
||||
"default:tin_lump",
|
||||
"default:stone_with_tin",
|
||||
"default:mese_crystal",
|
||||
"default:diamond",
|
||||
"default:bronze_ingot",
|
||||
"default:mese",
|
||||
"default:mese_crystal_fragment",
|
||||
"default:copperblock",
|
||||
"default:stone_with_coal",
|
||||
"default:steelblock",
|
||||
"default:tin_ingot",
|
||||
"default:coalblock",
|
||||
"default:coal_lump",
|
||||
"default:bronzeblock",
|
||||
"default:goldblock",
|
||||
|
||||
"stairs:slab_bronzeblock",
|
||||
"stairs:slab_copperblock",
|
||||
"stairs:slab_steelblock",
|
||||
"stairs:slab_tinblock",
|
||||
"stairs:stair_bronzeblock",
|
||||
"stairs:stair_copperblock",
|
||||
"stairs:stair_inner_bronzeblock",
|
||||
"stairs:stair_inner_copperblock",
|
||||
"stairs:stair_inner_steelblock",
|
||||
"stairs:stair_inner_tinblock",
|
||||
"stairs:stair_outer_bronzeblock",
|
||||
"stairs:stair_outer_copperblock",
|
||||
"stairs:stair_outer_steelblock",
|
||||
"stairs:stair_outer_tinblock",
|
||||
"stairs:stair_steelblock",
|
||||
"stairs:stair_tinblock",
|
||||
})
|
||||
|
||||
unified_inventory.add_category_items('building', {
|
||||
"default:fence_rail_aspen_wood",
|
||||
"default:fence_rail_acacia_wood",
|
||||
"default:fence_junglewood",
|
||||
"default:fence_rail_junglewood",
|
||||
"default:fence_aspen_wood",
|
||||
"default:fence_pine_wood",
|
||||
"default:fence_rail_wood",
|
||||
"default:fence_rail_pine_wood",
|
||||
"default:fence_acacia_wood",
|
||||
"default:junglewood",
|
||||
"default:acacia_wood",
|
||||
"default:aspen_wood",
|
||||
"default:fence_wood",
|
||||
"default:pine_wood",
|
||||
"default:silver_sandstone",
|
||||
"default:desert_sandstone",
|
||||
"default:sandstone_block",
|
||||
"default:desert_sandstone_brick",
|
||||
"default:stone_block",
|
||||
"default:stonebrick",
|
||||
"default:obsidian_glass",
|
||||
"default:desert_sandstone_block",
|
||||
"default:silver_sandstone_brick",
|
||||
"default:brick",
|
||||
"default:obsidianbrick",
|
||||
"default:sandstonebrick",
|
||||
"default:sandstone",
|
||||
"default:desert_stone_block",
|
||||
"default:silver_sandstone_block",
|
||||
"default:wood",
|
||||
"default:obsidian_block",
|
||||
"default:glass",
|
||||
"default:clay_brick",
|
||||
"default:desert_stonebrick",
|
||||
"default:desert_cobble",
|
||||
"default:cobble",
|
||||
"default:mossycobble",
|
||||
|
||||
"doors:door_glass",
|
||||
"doors:door_glass_a",
|
||||
"doors:door_glass_b",
|
||||
"doors:door_glass_c",
|
||||
"doors:door_glass_d",
|
||||
"doors:door_obsidian_glass",
|
||||
"doors:door_obsidian_glass_a",
|
||||
"doors:door_obsidian_glass_b",
|
||||
"doors:door_obsidian_glass_c",
|
||||
"doors:door_obsidian_glass_d",
|
||||
"doors:door_steel",
|
||||
"doors:door_steel_a",
|
||||
"doors:door_steel_b",
|
||||
"doors:door_steel_c",
|
||||
"doors:door_steel_d",
|
||||
"doors:door_wood",
|
||||
"doors:door_wood_a",
|
||||
"doors:door_wood_b",
|
||||
"doors:door_wood_c",
|
||||
"doors:door_wood_d",
|
||||
"doors:gate_acacia_wood_closed",
|
||||
"doors:gate_acacia_wood_open",
|
||||
"doors:gate_aspen_wood_closed",
|
||||
"doors:gate_aspen_wood_open",
|
||||
"doors:gate_junglewood_closed",
|
||||
"doors:gate_junglewood_open",
|
||||
"doors:gate_pine_wood_closed",
|
||||
"doors:gate_pine_wood_open",
|
||||
"doors:gate_wood_closed",
|
||||
"doors:gate_wood_open",
|
||||
"doors:hidden",
|
||||
"doors:trapdoor",
|
||||
"doors:trapdoor_open",
|
||||
"doors:trapdoor_steel",
|
||||
"doors:trapdoor_steel_open",
|
||||
|
||||
"stairs:slab_bronzeblock",
|
||||
"stairs:slab_copperblock",
|
||||
"stairs:slab_steelblock",
|
||||
"stairs:slab_tinblock",
|
||||
"stairs:stair_bronzeblock",
|
||||
"stairs:stair_copperblock",
|
||||
"stairs:stair_inner_bronzeblock",
|
||||
"stairs:stair_inner_copperblock",
|
||||
"stairs:stair_inner_steelblock",
|
||||
"stairs:stair_inner_tinblock",
|
||||
"stairs:stair_outer_bronzeblock",
|
||||
"stairs:stair_outer_copperblock",
|
||||
"stairs:stair_outer_steelblock",
|
||||
"stairs:stair_outer_tinblock",
|
||||
"stairs:stair_steelblock",
|
||||
"stairs:stair_tinblock",
|
||||
|
||||
"stairs:slab_acacia_wood",
|
||||
"stairs:slab_aspen_wood",
|
||||
"stairs:slab_brick",
|
||||
"stairs:slab_cobble",
|
||||
"stairs:slab_desert_cobble",
|
||||
"stairs:slab_desert_sandstone",
|
||||
"stairs:slab_desert_sandstone_block",
|
||||
"stairs:slab_desert_sandstone_brick",
|
||||
"stairs:slab_desert_stone",
|
||||
"stairs:slab_desert_stone_block",
|
||||
"stairs:slab_desert_stonebrick",
|
||||
"stairs:slab_glass",
|
||||
"stairs:slab_goldblock",
|
||||
"stairs:slab_ice",
|
||||
"stairs:slab_junglewood",
|
||||
"stairs:slab_mossycobble",
|
||||
"stairs:slab_obsidian",
|
||||
"stairs:slab_obsidian_block",
|
||||
"stairs:slab_obsidian_glass",
|
||||
"stairs:slab_obsidianbrick",
|
||||
"stairs:slab_pine_wood",
|
||||
"stairs:slab_sandstone",
|
||||
"stairs:slab_sandstone_block",
|
||||
"stairs:slab_sandstonebrick",
|
||||
"stairs:slab_silver_sandstone",
|
||||
"stairs:slab_silver_sandstone_block",
|
||||
"stairs:slab_silver_sandstone_brick",
|
||||
"stairs:slab_snowblock",
|
||||
"stairs:slab_stone",
|
||||
"stairs:slab_stone_block",
|
||||
"stairs:slab_stonebrick",
|
||||
"stairs:slab_straw",
|
||||
"stairs:slab_wood",
|
||||
"stairs:stair_acacia_wood",
|
||||
"stairs:stair_aspen_wood",
|
||||
"stairs:stair_brick",
|
||||
"stairs:stair_cobble",
|
||||
"stairs:stair_desert_cobble",
|
||||
"stairs:stair_desert_sandstone",
|
||||
"stairs:stair_desert_sandstone_block",
|
||||
"stairs:stair_desert_sandstone_brick",
|
||||
"stairs:stair_desert_stone",
|
||||
"stairs:stair_desert_stone_block",
|
||||
"stairs:stair_desert_stonebrick",
|
||||
"stairs:stair_glass",
|
||||
"stairs:stair_goldblock",
|
||||
"stairs:stair_ice",
|
||||
"stairs:stair_inner_acacia_wood",
|
||||
"stairs:stair_inner_aspen_wood",
|
||||
"stairs:stair_inner_brick",
|
||||
"stairs:stair_inner_cobble",
|
||||
"stairs:stair_inner_desert_cobble",
|
||||
"stairs:stair_inner_desert_sandstone",
|
||||
"stairs:stair_inner_desert_sandstone_block",
|
||||
"stairs:stair_inner_desert_sandstone_brick",
|
||||
"stairs:stair_inner_desert_stone",
|
||||
"stairs:stair_inner_desert_stone_block",
|
||||
"stairs:stair_inner_desert_stonebrick",
|
||||
"stairs:stair_inner_glass",
|
||||
"stairs:stair_inner_goldblock",
|
||||
"stairs:stair_inner_ice",
|
||||
"stairs:stair_inner_junglewood",
|
||||
"stairs:stair_inner_mossycobble",
|
||||
"stairs:stair_inner_obsidian",
|
||||
"stairs:stair_inner_obsidian_block",
|
||||
"stairs:stair_inner_obsidian_glass",
|
||||
"stairs:stair_inner_obsidianbrick",
|
||||
"stairs:stair_inner_pine_wood",
|
||||
"stairs:stair_inner_sandstone",
|
||||
"stairs:stair_inner_sandstone_block",
|
||||
"stairs:stair_inner_sandstonebrick",
|
||||
"stairs:stair_inner_silver_sandstone",
|
||||
"stairs:stair_inner_silver_sandstone_block",
|
||||
"stairs:stair_inner_silver_sandstone_brick",
|
||||
"stairs:stair_inner_snowblock",
|
||||
"stairs:stair_inner_stone",
|
||||
"stairs:stair_inner_stone_block",
|
||||
"stairs:stair_inner_stonebrick",
|
||||
"stairs:stair_inner_straw",
|
||||
"stairs:stair_inner_wood",
|
||||
"stairs:stair_junglewood",
|
||||
"stairs:stair_mossycobble",
|
||||
"stairs:stair_obsidian",
|
||||
"stairs:stair_obsidian_block",
|
||||
"stairs:stair_obsidian_glass",
|
||||
"stairs:stair_obsidianbrick",
|
||||
"stairs:stair_outer_acacia_wood",
|
||||
"stairs:stair_outer_aspen_wood",
|
||||
"stairs:stair_outer_brick",
|
||||
"stairs:stair_outer_cobble",
|
||||
"stairs:stair_outer_desert_cobble",
|
||||
"stairs:stair_outer_desert_sandstone",
|
||||
"stairs:stair_outer_desert_sandstone_block",
|
||||
"stairs:stair_outer_desert_sandstone_brick",
|
||||
"stairs:stair_outer_desert_stone",
|
||||
"stairs:stair_outer_desert_stone_block",
|
||||
"stairs:stair_outer_desert_stonebrick",
|
||||
"stairs:stair_outer_glass",
|
||||
"stairs:stair_outer_goldblock",
|
||||
"stairs:stair_outer_ice",
|
||||
"stairs:stair_outer_junglewood",
|
||||
"stairs:stair_outer_mossycobble",
|
||||
"stairs:stair_outer_obsidian",
|
||||
"stairs:stair_outer_obsidian_block",
|
||||
"stairs:stair_outer_obsidian_glass",
|
||||
"stairs:stair_outer_obsidianbrick",
|
||||
"stairs:stair_outer_pine_wood",
|
||||
"stairs:stair_outer_sandstone",
|
||||
"stairs:stair_outer_sandstone_block",
|
||||
"stairs:stair_outer_sandstonebrick",
|
||||
"stairs:stair_outer_silver_sandstone",
|
||||
"stairs:stair_outer_silver_sandstone_block",
|
||||
"stairs:stair_outer_silver_sandstone_brick",
|
||||
"stairs:stair_outer_snowblock",
|
||||
"stairs:stair_outer_stone",
|
||||
"stairs:stair_outer_stone_block",
|
||||
"stairs:stair_outer_stonebrick",
|
||||
"stairs:stair_outer_straw",
|
||||
"stairs:stair_outer_wood",
|
||||
"stairs:stair_pine_wood",
|
||||
"stairs:stair_sandstone",
|
||||
"stairs:stair_sandstone_block",
|
||||
"stairs:stair_sandstonebrick",
|
||||
"stairs:stair_silver_sandstone",
|
||||
"stairs:stair_silver_sandstone_block",
|
||||
"stairs:stair_silver_sandstone_brick",
|
||||
"stairs:stair_snowblock",
|
||||
"stairs:stair_stone",
|
||||
"stairs:stair_stone_block",
|
||||
"stairs:stair_stonebrick",
|
||||
"stairs:stair_straw",
|
||||
"stairs:stair_wood",
|
||||
|
||||
"xpanes:bar",
|
||||
"xpanes:bar_flat",
|
||||
"xpanes:door_steel_bar",
|
||||
"xpanes:door_steel_bar_a",
|
||||
"xpanes:door_steel_bar_b",
|
||||
"xpanes:door_steel_bar_c",
|
||||
"xpanes:door_steel_bar_d",
|
||||
"xpanes:obsidian_pane",
|
||||
"xpanes:obsidian_pane_flat",
|
||||
"xpanes:pane",
|
||||
"xpanes:pane_flat",
|
||||
"xpanes:trapdoor_steel_bar",
|
||||
"xpanes:trapdoor_steel_bar_open",
|
||||
|
||||
"walls:cobble",
|
||||
"walls:desertcobble",
|
||||
"walls:mossycobble",
|
||||
})
|
||||
|
||||
unified_inventory.add_category_items('environment', {
|
||||
"air",
|
||||
"default:cave_ice",
|
||||
"default:dirt_with_rainforest_litter",
|
||||
"default:gravel",
|
||||
"default:dry_dirt_with_dry_grass",
|
||||
"default:permafrost",
|
||||
"default:desert_stone",
|
||||
"default:ice",
|
||||
"default:dry_dirt",
|
||||
"default:obsidian",
|
||||
"default:sand",
|
||||
"default:river_water_source",
|
||||
"default:dirt_with_snow",
|
||||
"default:dirt_with_grass",
|
||||
"default:water_flowing",
|
||||
"default:dirt",
|
||||
"default:desert_sand",
|
||||
"default:permafrost_with_moss",
|
||||
"default:dirt_with_coniferous_litter",
|
||||
"default:water_source",
|
||||
"default:dirt_with_dry_grass",
|
||||
"default:river_water_flowing",
|
||||
"default:stone",
|
||||
"default:snow",
|
||||
"default:lava_flowing",
|
||||
"default:lava_source",
|
||||
"default:permafrost_with_stones",
|
||||
"default:dirt_with_grass_footsteps",
|
||||
"default:silver_sand",
|
||||
"default:snowblock",
|
||||
"default:clay",
|
||||
|
||||
"farming:desert_sand_soil",
|
||||
"farming:desert_sand_soil_wet",
|
||||
"farming:dry_soil",
|
||||
"farming:dry_soil_wet",
|
||||
"farming:soil",
|
||||
"farming:soil_wet",
|
||||
})
|
||||
|
||||
unified_inventory.add_category_items('lighting', {
|
||||
"default:mese_post_light_junglewood",
|
||||
"default:torch_ceiling",
|
||||
"default:meselamp",
|
||||
"default:torch",
|
||||
"default:mese_post_light_acacia_wood",
|
||||
"default:mese_post_light",
|
||||
"default:torch_wall",
|
||||
"default:mese_post_light_pine_wood",
|
||||
"default:mese_post_light_aspen_wood"
|
||||
})
|
||||
--]]
|
||||
|
||||
|
||||
--[[ UNCATEGORISED
|
||||
|
||||
"farming:string",
|
||||
|
||||
"beds:bed_bottom",
|
||||
"beds:bed_top",
|
||||
"beds:fancy_bed_bottom",
|
||||
"beds:fancy_bed_top",
|
||||
"boats:boat",
|
||||
"bones:bones",
|
||||
|
||||
"bucket:bucket_lava",
|
||||
"bucket:bucket_river_water",
|
||||
"bucket:bucket_water",
|
||||
|
||||
"butterflies:butterfly_red",
|
||||
"butterflies:butterfly_violet",
|
||||
"butterflies:butterfly_white",
|
||||
"butterflies:hidden_butterfly_red",
|
||||
"butterflies:hidden_butterfly_violet",
|
||||
"butterflies:hidden_butterfly_white",
|
||||
|
||||
"carts:brakerail",
|
||||
"carts:cart",
|
||||
"carts:powerrail",
|
||||
"carts:rail",
|
||||
|
||||
"default:book",
|
||||
"default:book_written",
|
||||
"default:bookshelf",
|
||||
"default:chest",
|
||||
"default:chest_locked",
|
||||
"default:chest_locked_open",
|
||||
"default:chest_open",
|
||||
"default:clay_lump",
|
||||
"default:cloud",
|
||||
"default:coral_brown",
|
||||
"default:coral_cyan",
|
||||
"default:coral_green",
|
||||
"default:coral_orange",
|
||||
"default:coral_pink",
|
||||
"default:coral_skeleton",
|
||||
"default:flint",
|
||||
"default:furnace",
|
||||
"default:furnace_active",
|
||||
"default:key",
|
||||
"default:ladder_steel",
|
||||
"default:ladder_wood",
|
||||
"default:obsidian_shard",
|
||||
"default:paper",
|
||||
"default:sign_wall_steel",
|
||||
"default:sign_wall_wood",
|
||||
"default:stick",
|
||||
|
||||
"fire:basic_flame",
|
||||
"fire:permanent_flame",
|
||||
"fireflies:firefly",
|
||||
"fireflies:firefly_bottle",
|
||||
"fireflies:hidden_firefly",
|
||||
|
||||
"ignore",
|
||||
"unknown",
|
||||
|
||||
"tnt:boom",
|
||||
"tnt:gunpowder",
|
||||
"tnt:gunpowder_burning",
|
||||
"tnt:tnt",
|
||||
"tnt:tnt_burning",
|
||||
"tnt:tnt_stick",
|
||||
|
||||
"vessels:drinking_glass",
|
||||
"vessels:glass_bottle",
|
||||
"vessels:glass_fragments",
|
||||
"vessels:shelf",
|
||||
"vessels:steel_bottle",
|
||||
|
||||
"dye:black",
|
||||
"dye:blue",
|
||||
"dye:brown",
|
||||
"dye:cyan",
|
||||
"dye:dark_green",
|
||||
"dye:dark_grey",
|
||||
"dye:green",
|
||||
"dye:grey",
|
||||
"dye:magenta",
|
||||
"dye:orange",
|
||||
"dye:pink",
|
||||
"dye:red",
|
||||
"dye:violet",
|
||||
"dye:white",
|
||||
"dye:yellow",
|
||||
|
||||
"wool:black",
|
||||
"wool:blue",
|
||||
"wool:brown",
|
||||
"wool:cyan",
|
||||
"wool:dark_green",
|
||||
"wool:dark_grey",
|
||||
"wool:green",
|
||||
"wool:grey",
|
||||
"wool:magenta",
|
||||
"wool:orange",
|
||||
"wool:pink",
|
||||
"wool:red",
|
||||
"wool:violet",
|
||||
"wool:white",
|
||||
"wool:yellow",
|
||||
|
||||
"unified_inventory:bag_large",
|
||||
"unified_inventory:bag_medium",
|
||||
"unified_inventory:bag_small",
|
||||
--]]
|
||||
|
||||
--[[ LIST UNCATEGORIZED AFTER LOAD
|
||||
minetest.register_on_mods_loaded(function()
|
||||
minetest.after(1, function ( )
|
||||
local l = {}
|
||||
for name,_ in pairs(minetest.registered_items) do
|
||||
if not unified_inventory.find_category(name) then
|
||||
-- minetest.log("error", minetest.serialize(minetest.registered_items[name]))
|
||||
table.insert(l, name)
|
||||
end
|
||||
end
|
||||
table.sort(l)
|
||||
minetest.log(table.concat(l, '",'.."\n"..'"'))
|
||||
end)
|
||||
end)
|
||||
--]]
|
|
@ -101,3 +101,72 @@ Register a non-standard craft recipe:
|
|||
-- ^ Same as `minetest.register_recipe`
|
||||
})
|
||||
|
||||
|
||||
Categories
|
||||
----------
|
||||
|
||||
Register a new category:
|
||||
The config table (second argument) is optional, and all its members are optional
|
||||
See the unified_inventory.set_category_* functions for more details on the members of the config table
|
||||
|
||||
unified_inventory.register_category("category_name", {
|
||||
symbol = "mod_name:item_name" or "texture.png",
|
||||
label = "Human Readable Label",
|
||||
index = 5,
|
||||
items = {
|
||||
"mod_name:item_name",
|
||||
"another_mod:different_item"
|
||||
}
|
||||
})
|
||||
|
||||
Add / override the symbol for a category:
|
||||
The category does not need to exist first
|
||||
The symbol can be an item name or a texture image
|
||||
If unset this will default to "default:stick"
|
||||
|
||||
unified_inventory.set_category_symbol("category_name", "mod_name:item_name" or "texture.png")
|
||||
|
||||
Add / override the human readable label for a category:
|
||||
If unset this will default to the category name
|
||||
|
||||
unified_inventory.set_category_label("category_name", "Human Readable Label")
|
||||
|
||||
Add / override the sorting index of the category:
|
||||
Must be a number, can also be negative (-5) or fractional (2.345)
|
||||
This determines the position the category appears in the list of categories
|
||||
The "all" meta-category has index -2, the "misc"/"uncategorized" meta-category has index -1, use a negative number smaller than these to make a category appear before these in the list
|
||||
By default categories are sorted alphabetically with an index between 0.0101(AA) and 0.2626(ZZ)
|
||||
|
||||
unified_inventory.set_category_index("category_name", 5)
|
||||
|
||||
Add a single item to a category:
|
||||
|
||||
unified_inventory.add_category_item("category_name", "mod_name:item_name")
|
||||
|
||||
Add multiple items to a category:
|
||||
|
||||
unified_inventory.add_category_items("category_name", {
|
||||
"mod_name:item_name",
|
||||
"another_mod:different_item"
|
||||
})
|
||||
|
||||
Remove an item from a category:
|
||||
|
||||
unified_inventory.remove_category_item("category_name", "mod_name:item_name")
|
||||
|
||||
Remove a category entirely:
|
||||
|
||||
unified_inventory.remove_category("category_name")
|
||||
|
||||
Finding existing items in categories:
|
||||
This will find the first category an item exists in
|
||||
It should be used for checking if an item is catgorised
|
||||
Returns "category_name" or nil
|
||||
|
||||
unified_inventory.find_category("mod_name:item_name")
|
||||
|
||||
|
||||
This will find all the categories an item exists in
|
||||
Returns a number indexed table (list) of category names
|
||||
|
||||
unified_inventory.find_categories("mod_name:item_name")
|
||||
|
|
|
@ -10,6 +10,8 @@ unified_inventory = {
|
|||
alternate = {},
|
||||
current_page = {},
|
||||
current_searchbox = {},
|
||||
current_category = {},
|
||||
current_category_scroll = {},
|
||||
current_index = {},
|
||||
current_item = {},
|
||||
current_craft_direction = {},
|
||||
|
@ -33,6 +35,9 @@ unified_inventory = {
|
|||
-- "Lite" mode
|
||||
lite_mode = minetest.settings:get_bool("unified_inventory_lite"),
|
||||
|
||||
-- Items automatically added to categories based on item definitions
|
||||
automatic_categorization = (minetest.settings:get_bool("unified_inventory_automatic_categorization") ~= false),
|
||||
|
||||
-- Trash enabled
|
||||
trash_enabled = (minetest.settings:get_bool("unified_inventory_trash") ~= false),
|
||||
imgscale = 1.25,
|
||||
|
@ -52,9 +57,9 @@ ui.style_full = {
|
|||
formw = 17.75,
|
||||
formh = 12.25,
|
||||
pagecols = 8,
|
||||
pagerows = 10,
|
||||
pagerows = 9,
|
||||
page_x = 10.75,
|
||||
page_y = 1.45,
|
||||
page_y = 2.30,
|
||||
craft_x = 2.8,
|
||||
craft_y = 1.15,
|
||||
craftresult_x = 7.8,
|
||||
|
@ -85,9 +90,9 @@ ui.style_lite = {
|
|||
formw = 14,
|
||||
formh = 9.75,
|
||||
pagecols = 4,
|
||||
pagerows = 6,
|
||||
pagerows = 5,
|
||||
page_x = 10.5,
|
||||
page_y = 1.25,
|
||||
page_y = 2.15,
|
||||
craft_x = 2.6,
|
||||
craft_y = 0.75,
|
||||
craftresult_x = 5.75,
|
||||
|
@ -100,9 +105,9 @@ ui.style_lite = {
|
|||
craft_guide_resultstr_y = 0.35,
|
||||
give_btn_x = 0.15,
|
||||
main_button_x = 10.5,
|
||||
main_button_y = 7.9,
|
||||
main_button_y = 8.15,
|
||||
page_buttons_x = 10.5,
|
||||
page_buttons_y = 6.3,
|
||||
page_buttons_y = 6.15,
|
||||
searchwidth = 1.6,
|
||||
form_header_x = 0.2,
|
||||
form_header_y = 0.2,
|
||||
|
@ -149,6 +154,8 @@ if sfinv then
|
|||
end
|
||||
|
||||
dofile(modpath.."/group.lua")
|
||||
dofile(modpath.."/category.lua")
|
||||
dofile(modpath.."/default-categories.lua")
|
||||
dofile(modpath.."/internal.lua")
|
||||
dofile(modpath.."/callbacks.lua")
|
||||
dofile(modpath.."/match_craft.lua")
|
||||
|
|
|
@ -25,6 +25,20 @@ function ui.get_per_player_formspec(player_name)
|
|||
return table.copy(draw_lite_mode and ui.style_lite or ui.style_full), draw_lite_mode
|
||||
end
|
||||
|
||||
local function formspec_button(ui_peruser, name, image, offset, pos, scale, label)
|
||||
local element = 'image_button'
|
||||
if minetest.registered_items[image] then
|
||||
element = 'item_image_button'
|
||||
end
|
||||
local spc = (1-scale)*ui_peruser.btn_size/2
|
||||
local size = ui_peruser.btn_size*scale
|
||||
return string.format("%s[%f,%f;%f,%f;%s;%s;]", element,
|
||||
(offset.x or offset[1]) + ( ui_peruser.btn_spc * (pos.x or pos[1]) ) + spc,
|
||||
(offset.y or offset[2]) + ( ui_peruser.btn_spc * (pos.y or pos[2]) ) + spc,
|
||||
size, size, image, name) ..
|
||||
string.format("tooltip[%s;%s]", name, F(label or name))
|
||||
end
|
||||
|
||||
function ui.get_formspec(player, page)
|
||||
|
||||
if not player then
|
||||
|
@ -107,6 +121,48 @@ function ui.get_formspec(player, page)
|
|||
return table.concat(formspec, "")
|
||||
end
|
||||
|
||||
-- Category filters
|
||||
|
||||
local categories_pos = { ui_peruser.page_x, ui_peruser.page_y-ui_peruser.btn_spc-0.5 }
|
||||
local categories_scroll_pos = { ui_peruser.page_x, ui_peruser.form_header_y-(draw_lite_mode and 0 or 0.2) }
|
||||
|
||||
formspec[n] = string.format("background9[%f,%f;%f,%f;%s;false;3]",
|
||||
ui_peruser.page_x-0.1, categories_scroll_pos[2],
|
||||
(ui_peruser.btn_spc * ui_peruser.pagecols) + 0.13, 1.4+(draw_lite_mode and 0 or 0.2),
|
||||
"ui_smallbg_9_sliced.png")
|
||||
n = n + 1
|
||||
|
||||
formspec[n] = string.format("label[%f,%f;%s]", ui_peruser.page_x, ui_peruser.form_header_y+(draw_lite_mode and 0.3 or 0.2), "Category:")
|
||||
n = n + 1
|
||||
|
||||
local scroll_offset = 0
|
||||
local category_count = #unified_inventory.category_list
|
||||
if category_count > ui_peruser.pagecols then
|
||||
scroll_offset = unified_inventory.current_category_scroll[player_name]
|
||||
end
|
||||
|
||||
for index, category in ipairs(unified_inventory.category_list) do
|
||||
local column = index - scroll_offset
|
||||
if column > 0 and column <= ui_peruser.pagecols then
|
||||
local scale = 0.8
|
||||
if unified_inventory.current_category[player_name] == category.name then
|
||||
scale = 1
|
||||
end
|
||||
formspec[n] = formspec_button(ui_peruser, "category_"..category.name, category.symbol, categories_pos, {column-1, 0}, scale, category.label)
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
if category_count > ui_peruser.pagecols and scroll_offset > 0 then
|
||||
-- prev
|
||||
formspec[n] = formspec_button(ui_peruser, "prev_category", "ui_left_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 2, 0}, 0.8, S("Scroll categories left"))
|
||||
n = n + 1
|
||||
end
|
||||
if category_count > ui_peruser.pagecols and category_count - scroll_offset > ui_peruser.pagecols then
|
||||
-- next
|
||||
formspec[n] = formspec_button(ui_peruser, "next_category", "ui_right_icon.png", categories_scroll_pos, {ui_peruser.pagecols - 1, 0}, 0.8, S("Scroll categories right"))
|
||||
n = n + 1
|
||||
end
|
||||
|
||||
-- Search box
|
||||
formspec[n] = "field_close_on_enter[searchbox;false]"
|
||||
|
||||
|
@ -205,16 +261,16 @@ function ui.get_formspec(player, page)
|
|||
end
|
||||
end
|
||||
formspec[n] = string.format("label[%f,%f;%s: %s]",
|
||||
ui_peruser.page_x, ui_peruser.form_header_y,
|
||||
ui_peruser.page_buttons_x + ui_peruser.btn_spc * (draw_lite_mode and 1 or 2),
|
||||
ui_peruser.page_buttons_y + 0.1 + ui_peruser.btn_spc * 2,
|
||||
F(S("Page")), S("@1 of @2",page2,pagemax))
|
||||
end
|
||||
n= n+1
|
||||
|
||||
if ui.activefilter[player_name] ~= "" then
|
||||
formspec[n] = string.format("label[%f,%f;%s:]",
|
||||
ui_peruser.page_x, ui_peruser.page_y - 0.65, F(S("Filter")))
|
||||
formspec[n+1] = string.format("label[%f,%f;%s]",
|
||||
ui_peruser.page_x, ui_peruser.page_y - 0.25, F(ui.activefilter[player_name]))
|
||||
formspec[n] = string.format("label[%f,%f;%s: %s]",
|
||||
ui_peruser.page_x, ui_peruser.page_y - 0.25,
|
||||
F(S("Filter")), F(ui.activefilter[player_name]))
|
||||
end
|
||||
return table.concat(formspec, "")
|
||||
end
|
||||
|
@ -225,6 +281,13 @@ function ui.set_inventory_formspec(player, page)
|
|||
end
|
||||
end
|
||||
|
||||
local function valid_def(def)
|
||||
return (not def.groups.not_in_creative_inventory
|
||||
or def.groups.not_in_creative_inventory == 0)
|
||||
and def.description
|
||||
and def.description ~= ""
|
||||
end
|
||||
|
||||
--apply filter to the inventory list (create filtered copy of full one)
|
||||
function ui.apply_filter(player, filter, search_dir)
|
||||
if not player then
|
||||
|
@ -256,15 +319,32 @@ function ui.apply_filter(player, filter, search_dir)
|
|||
end
|
||||
end
|
||||
ui.filtered_items_list[player_name]={}
|
||||
local category = ui.current_category[player_name] or 'all'
|
||||
if category == 'all' then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not def.groups.not_in_creative_inventory
|
||||
or def.groups.not_in_creative_inventory == 0)
|
||||
and def.description
|
||||
and def.description ~= ""
|
||||
if valid_def(def)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
end
|
||||
end
|
||||
elseif category == 'uncategorized' then
|
||||
for name, def in pairs(minetest.registered_items) do
|
||||
if (not ui.find_category(name))
|
||||
and valid_def(def)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
end
|
||||
end
|
||||
else
|
||||
for name,exists in pairs(ui.registered_category_items[category]) do
|
||||
local def = minetest.registered_items[name]
|
||||
if exists and def
|
||||
and valid_def(def)
|
||||
and ffilter(name, def) then
|
||||
table.insert(ui.filtered_items_list[player_name], name)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(ui.filtered_items_list[player_name])
|
||||
ui.filtered_items_list_size[player_name] = #ui.filtered_items_list[player_name]
|
||||
ui.current_index[player_name] = 1
|
||||
|
|
|
@ -9,3 +9,6 @@ unified_inventory_bags (Enable bags) bool true
|
|||
#If enabled, the trash slot can be used by those without both creative
|
||||
#and the give privilege.
|
||||
unified_inventory_trash (Enable trash) bool true
|
||||
|
||||
|
||||
unified_inventory_automatic_categorization (Items automatically added to categories) bool true
|
BIN
mods/unified_inventory/textures/ui_category_all.png
Normal file
BIN
mods/unified_inventory/textures/ui_category_all.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
BIN
mods/unified_inventory/textures/ui_category_none.png
Normal file
BIN
mods/unified_inventory/textures/ui_category_none.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
BIN
mods/unified_inventory/textures/ui_smallbg_9_sliced.png
Normal file
BIN
mods/unified_inventory/textures/ui_smallbg_9_sliced.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 139 B |
Loading…
Reference in a new issue