Compare commits
11 Commits
6e205f15b7
...
afc58d0b97
Author | SHA1 | Date |
---|---|---|
trans_soup | afc58d0b97 | |
trans_soup | c5d51e9fe5 | |
trans_soup | d9523dc015 | |
trans_soup | d0a481334a | |
trans_soup | d197e1f1e3 | |
trans_soup | 7df5d33d02 | |
trans_soup | c31d6cf5d0 | |
trans_soup | 45f59f5e03 | |
trans_soup | 5305cc526d | |
trans_soup | 17636dbf87 | |
trans_soup | cca53e76b3 |
|
@ -7,12 +7,13 @@ local blockgame = {}
|
|||
rawset(_G, "blockgame", blockgame)
|
||||
|
||||
load_file("util_table")
|
||||
load_file("util_stringify")
|
||||
load_file("util_string")
|
||||
load_file("util_debug")
|
||||
load_file("util_random")
|
||||
load_file("util_vector")
|
||||
|
||||
load_file("util_node")
|
||||
load_file("util_item")
|
||||
|
||||
load_file("wrappers")
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
function blockgame.item_matches (name, options)
|
||||
return blockgame.any(options, function (option)
|
||||
if name == option then return true end
|
||||
|
||||
if blockgame.starts_with(option, "group:") then
|
||||
local group = string.sub(option, 7)
|
||||
return minetest.get_item_group(name, group) > 0
|
||||
end
|
||||
|
||||
return false
|
||||
end)
|
||||
end
|
|
@ -48,3 +48,37 @@ function blockgame.random_walk (data)
|
|||
end
|
||||
return pos
|
||||
end
|
||||
|
||||
|
||||
|
||||
function blockgame.flood_fill (start, step, max_range)
|
||||
max_range = max_range or 4
|
||||
|
||||
local queue = { { pos = start, range = 0 } }
|
||||
local visited = {}
|
||||
local matches = {}
|
||||
local rejected = {}
|
||||
|
||||
while #queue > 0 do
|
||||
local current = table.remove(queue, 1)
|
||||
local pos = current.pos
|
||||
local range = current.range
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
|
||||
if not visited[hash] and range <= max_range and step(pos, range) then
|
||||
table.insert(matches, pos)
|
||||
|
||||
local neighbors = blockgame.vector.get_neighbors(pos)
|
||||
for _, p in pairs(neighbors) do
|
||||
table.insert(queue, { pos = p, range = range + 1 })
|
||||
end
|
||||
else
|
||||
table.insert(rejected, pos)
|
||||
end
|
||||
|
||||
visited[hash] = true
|
||||
end
|
||||
|
||||
return matches, rejected
|
||||
end
|
||||
|
|
|
@ -15,3 +15,9 @@ function blockgame.stringify (tab)
|
|||
return tab
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function blockgame.starts_with (str, start)
|
||||
return string.sub(str, 1, string.len(start)) == start
|
||||
end
|
|
@ -1,140 +1,9 @@
|
|||
blockgame.crafting = blockgame.crafting or {}
|
||||
local api = blockgame.crafting
|
||||
|
||||
local recipes = {}
|
||||
api.registered_recipes = recipes
|
||||
|
||||
function api.register_stack_recipe (top_node, bottom_node, result, consumes_top)
|
||||
local consumes_top = consumes_top
|
||||
if consumes_top == nil then consumes_top = true end
|
||||
|
||||
recipes[top_node] = recipes[top_node] or {}
|
||||
|
||||
table.insert(recipes[top_node], {
|
||||
["type"] = "stack_two_nodes",
|
||||
index_key = top_node,
|
||||
top_node = top_node,
|
||||
bottom_node = bottom_node,
|
||||
result = result,
|
||||
consumes_top = consumes_top,
|
||||
})
|
||||
end
|
||||
|
||||
function api.handle_placement (pos, new_node, placer, old_node, itemstack, pointed_thing)
|
||||
if recipes[new_node.name] == nil then return false end
|
||||
|
||||
for _, recipe in pairs(recipes[new_node.name]) do
|
||||
local result = api.handle_stack_recipe(recipe, pos, new_node)
|
||||
if result then return not recipe.consumes_top end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function api.handle_stack_recipe (recipe, pos, top_node)
|
||||
if top_node.name ~= recipe.top_node then return false end
|
||||
|
||||
local down = vector.add(pos, vector.new(0, -1, 0))
|
||||
local below = minetest.get_node(down)
|
||||
if below.name ~= recipe.bottom_node then return false end
|
||||
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(down, recipe.result)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- pummeling is heavily based on nodecore by Warr1024 (both the mechanic itself and the code here implementing it).
|
||||
|
||||
local pummel_recipes = {}
|
||||
|
||||
function api.register_pummel_recipe (def)
|
||||
local def = def or {}
|
||||
|
||||
def.label = def.label or "unnamed pummel recipe"
|
||||
|
||||
-- TODO: throw errors when these defs are invalid instead of just returning.
|
||||
if not def.used_item then return false end
|
||||
if not def.target_node then return false end
|
||||
if not type(def.on_success) == "function" then return false end
|
||||
|
||||
local key = def.used_item
|
||||
def.index_key = key
|
||||
|
||||
pummel_recipes[key] = pummel_recipes[key] or {}
|
||||
table.insert(pummel_recipes[key], def)
|
||||
end
|
||||
|
||||
-- TODO: add support for pummel recipes using groups instead of just specific node names.
|
||||
function api.pummel_check (pos, used_item, target_node)
|
||||
local key = used_item
|
||||
if not pummel_recipes[key] then return false end
|
||||
|
||||
local potential_recipes = pummel_recipes[key]
|
||||
for _, def in pairs(potential_recipes) do
|
||||
if def.target_node == target_node.name then
|
||||
if type(def.check) == "function" and not def.check(pos, used_item, target_node) then
|
||||
return false
|
||||
end
|
||||
def.on_success(pos, used_item, target_node)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
api.registered_recipes = {}
|
||||
|
||||
|
||||
local pummeling = {}
|
||||
|
||||
-- NOTE: might wanna change this to somehow store pummels per-node instead of per-player?
|
||||
blockgame.register_on_dignode(function (_, _, digger)
|
||||
if not (digger and digger:is_player()) then return end
|
||||
pummeling[digger:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
blockgame.register_on_punchnode(function (pos, node, puncher, pointed)
|
||||
if (not puncher:is_player()) or puncher:get_player_control().sneak then return end
|
||||
local player_name = puncher:get_player_name()
|
||||
-- if not minetest.interact(player_name) then return end
|
||||
if not minetest.check_player_privs(player_name, "interact") then return end
|
||||
|
||||
node = node or minetest.get_node(pos)
|
||||
local node_def = minetest.registered_items[node.name] or {}
|
||||
if not node_def.pointable then return end
|
||||
|
||||
local wield = puncher:get_wielded_item()
|
||||
local now = minetest.get_us_time() / 1000000
|
||||
|
||||
local pummel_data = {
|
||||
action = "pummel",
|
||||
crafter = puncher,
|
||||
crafter_name = player_name,
|
||||
pos = pos,
|
||||
pointed = pointed,
|
||||
node = node,
|
||||
node_def = node_def,
|
||||
start = now,
|
||||
wield = wield:get_name() .. " " .. wield:get_count(),
|
||||
count = 0,
|
||||
}
|
||||
|
||||
local old_data = pummeling[player_name]
|
||||
local hash = minetest.hash_node_position
|
||||
if old_data and hash(old_data.pos) == hash(pummel_data.pos)
|
||||
and hash(old_data.pointed.above) == hash(pummel_data.pointed.above)
|
||||
and hash(old_data.pointed.under) == hash(pummel_data.pointed.under)
|
||||
and old_data.wield == pummel_data.wield
|
||||
and old_data.last >= (now - 3)
|
||||
then pummel_data = old_data
|
||||
end
|
||||
|
||||
pummel_data.count = pummel_data.count + 1
|
||||
pummel_data.last = now
|
||||
pummel_data.duration = now - pummel_data.start - 1
|
||||
pummeling[player_name] = pummel_data
|
||||
|
||||
if pummel_data.count < 2 then return end
|
||||
|
||||
if api.pummel_check(pos, wield:get_name(), minetest.get_node(pointed.under)) then
|
||||
pummeling[player_name] = nil
|
||||
end
|
||||
end)
|
||||
load_file("stack")
|
||||
load_file("pummel")
|
||||
|
|
|
@ -1,7 +1 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
load_file("api")
|
||||
|
||||
blockgame.register_on_placenode(function (...)
|
||||
return blockgame.crafting.handle_placement(...)
|
||||
end)
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
local api = blockgame.crafting
|
||||
|
||||
-- LOCALS
|
||||
|
||||
local matches = blockgame.item_matches
|
||||
|
||||
-- pummeling is heavily based on nodecore by Warr1024 (both the mechanic itself and the code here implementing it).
|
||||
|
||||
local pummel_recipes = {}
|
||||
|
||||
function api.register_pummel_recipe (def)
|
||||
local def = def or {}
|
||||
|
||||
-- TODO: require `def.name` to be specified and unique.
|
||||
def.label = def.label or "unlabeled pummel recipe"
|
||||
|
||||
-- TODO: throw errors when these defs are invalid instead of just returning.
|
||||
if not def.used then return false end
|
||||
if not def.target then return false end
|
||||
if not type(def.on_success) == "function" then return false end
|
||||
|
||||
def["type"] = "pummel"
|
||||
|
||||
table.insert(pummel_recipes, def)
|
||||
table.insert(api.registered_recipes, def)
|
||||
end
|
||||
|
||||
-- TODO: add support for pummel recipes using groups instead of just specific node names.
|
||||
function api.pummel_check (pos, used, target_node)
|
||||
for _, def in pairs(pummel_recipes) do
|
||||
if matches(used, def.used) and matches(target_node.name, def.target) then
|
||||
if type(def.check) == "function" and not def.check(pos, used, target_node) then
|
||||
return false
|
||||
end
|
||||
def.on_success(pos, used, target_node)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local pummeling = {}
|
||||
|
||||
-- NOTE: might wanna change this to somehow store pummels per-node instead of per-player?
|
||||
blockgame.register_on_dignode(function (_, _, digger)
|
||||
if not (digger and digger:is_player()) then return end
|
||||
pummeling[digger:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
blockgame.register_on_punchnode(function (pos, node, puncher, pointed)
|
||||
if (not puncher:is_player()) or puncher:get_player_control().sneak then return end
|
||||
local player_name = puncher:get_player_name()
|
||||
-- if not minetest.interact(player_name) then return end
|
||||
if not minetest.check_player_privs(player_name, "interact") then return end
|
||||
|
||||
node = node or minetest.get_node(pos)
|
||||
local node_def = minetest.registered_items[node.name] or {}
|
||||
if not node_def.pointable then return end
|
||||
|
||||
local wield = puncher:get_wielded_item()
|
||||
local now = minetest.get_us_time() / 1000000
|
||||
|
||||
local pummel_data = {
|
||||
action = "pummel",
|
||||
crafter = puncher,
|
||||
crafter_name = player_name,
|
||||
pos = pos,
|
||||
pointed = pointed,
|
||||
node = node,
|
||||
node_def = node_def,
|
||||
start = now,
|
||||
wield = wield:get_name() .. " " .. wield:get_count(),
|
||||
count = 0,
|
||||
}
|
||||
|
||||
local old_data = pummeling[player_name]
|
||||
local hash = minetest.hash_node_position
|
||||
if old_data and hash(old_data.pos) == hash(pummel_data.pos)
|
||||
and hash(old_data.pointed.above) == hash(pummel_data.pointed.above)
|
||||
and hash(old_data.pointed.under) == hash(pummel_data.pointed.under)
|
||||
and old_data.wield == pummel_data.wield
|
||||
and old_data.last >= (now - 3)
|
||||
then pummel_data = old_data
|
||||
end
|
||||
|
||||
pummel_data.count = pummel_data.count + 1
|
||||
pummel_data.last = now
|
||||
pummel_data.duration = now - pummel_data.start - 1
|
||||
pummeling[player_name] = pummel_data
|
||||
|
||||
if pummel_data.count < 2 then return end
|
||||
|
||||
if api.pummel_check(pos, wield:get_name(), minetest.get_node(pointed.under)) then
|
||||
pummeling[player_name] = nil
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,50 @@
|
|||
local api = blockgame.crafting
|
||||
|
||||
local stack_recipes = {}
|
||||
|
||||
function api.register_stack_recipe (top_node, bottom_node, result, consumes_top)
|
||||
local consumes_top = consumes_top
|
||||
if consumes_top == nil then consumes_top = true end
|
||||
|
||||
stack_recipes[top_node] = stack_recipes[top_node] or {}
|
||||
|
||||
local def = {
|
||||
["type"] = "stack_two_nodes",
|
||||
index_key = top_node,
|
||||
top_node = top_node,
|
||||
bottom_node = bottom_node,
|
||||
result = result,
|
||||
consumes_top = consumes_top,
|
||||
}
|
||||
|
||||
table.insert(stack_recipes[top_node], def)
|
||||
table.insert(api.registered_recipes, def)
|
||||
end
|
||||
|
||||
function api.handle_stack_recipe (recipe, pos, top_node)
|
||||
if top_node.name ~= recipe.top_node then return false end
|
||||
|
||||
local down = vector.add(pos, vector.new(0, -1, 0))
|
||||
local below = minetest.get_node(down)
|
||||
if below.name ~= recipe.bottom_node then return false end
|
||||
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(down, recipe.result)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function api.handle_placement (pos, new_node, placer, old_node, itemstack, pointed_thing)
|
||||
if stack_recipes[new_node.name] == nil then return false end
|
||||
|
||||
for _, recipe in pairs(stack_recipes[new_node.name]) do
|
||||
local result = api.handle_stack_recipe(recipe, pos, new_node)
|
||||
if result then return not recipe.consumes_top end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
blockgame.register_on_placenode(function (...)
|
||||
return blockgame.crafting.handle_placement(...)
|
||||
end)
|
|
@ -1,57 +0,0 @@
|
|||
local function get_inventory (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return minetest.deserialize(meta:get_string("inventory"))
|
||||
end
|
||||
|
||||
local function set_inventory (pos, inventory)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("inventory", minetest.serialize(inventory))
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function push (pos, value)
|
||||
local inventory = get_inventory(pos)
|
||||
if not inventory then return false end
|
||||
|
||||
table.insert(inventory, value)
|
||||
set_inventory(pos, inventory)
|
||||
return true
|
||||
end
|
||||
|
||||
local function pop (pos)
|
||||
local inventory = get_inventory(pos)
|
||||
if not inventory then return nil end
|
||||
|
||||
local value = table.remove(inventory, 1)
|
||||
set_inventory(pos, inventory)
|
||||
return value
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function place_funnel (itemstack, placed, pointed)
|
||||
local result = minetest.item_place(itemstack, placer, pointed)
|
||||
|
||||
local pos = pointed.above
|
||||
local meta = minetest.get_meta(pos)
|
||||
set_inventory(pos, {})
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function dig_funnel (pos, ...)
|
||||
local result = minetest.node_dig(pos, ...)
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
|
||||
return {
|
||||
get_inventory = get_inventory,
|
||||
set_inventory = set_inventory,
|
||||
place_funnel = place_funnel,
|
||||
dig_funnel = dig_funnel,
|
||||
push = push,
|
||||
pop = pop,
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
local api = load_file("api")
|
||||
|
||||
local function get_meta_table (pos)
|
||||
return minetest.get_meta(pos):to_table()
|
||||
end
|
||||
|
||||
local function set_meta (pos, meta_table)
|
||||
local meta = minetest.get_meta(pos)
|
||||
for key, value in pairs(meta_table) do
|
||||
local fn = nil
|
||||
if type(value) == "string" then fn = "set_string" end
|
||||
if type(value) == "int" then fn = "set_int" end
|
||||
if type(value) == "float" then fn = "set_float" end
|
||||
if fn then
|
||||
meta[fn](key, value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function attempt_input (pos)
|
||||
-- TODO: add max limit for amount of nodes inside funnel inventory.
|
||||
local above = pos + blockgame.vector.dirs.up
|
||||
if minetest.get_node(above).name == "air" then return false end
|
||||
|
||||
local node = minetest.get_node(above)
|
||||
local meta = get_meta_table(above)
|
||||
local value = {
|
||||
node = node,
|
||||
meta = meta,
|
||||
}
|
||||
|
||||
local success = api.push(pos, value)
|
||||
if not success then return false end
|
||||
minetest.remove_node(above)
|
||||
return true
|
||||
end
|
||||
|
||||
local function attempt_output (pos)
|
||||
local below = pos + blockgame.vector.dirs.down
|
||||
if minetest.get_node(below).name ~= "air" then return false end
|
||||
|
||||
local value = api.pop(pos)
|
||||
if not value then return nil end
|
||||
|
||||
local node = value.node
|
||||
local meta = value.meta
|
||||
minetest.set_node(below, node)
|
||||
set_meta(below, meta)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
blockgame.register_abm({
|
||||
label = "funnel nodes",
|
||||
nodenames = {modname .. ":funnel"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
catch_up = false,
|
||||
action = function (pos)
|
||||
-- NOTE: metadata storage might not work, and funnels might not be able to pick up other funnels successfully.
|
||||
attempt_input(pos)
|
||||
attempt_output(pos)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
-- NOTE: the documentation says `register_on_placenode` is "not recommended"; what else could be used for this?
|
||||
minetest.register_on_placenode(function (pos)
|
||||
local below = pos + blockgame.vector.dirs.down
|
||||
if minetest.get_node(below).name ~= modname .. ":funnel" then return end
|
||||
attempt_input(below)
|
||||
end)
|
||||
|
||||
-- NOTE: the documentation says `register_on_dignode` is "not recommended"; what else could be used for this?
|
||||
minetest.register_on_dignode(function (pos)
|
||||
local above = pos + blockgame.vector.dirs.up
|
||||
if minetest.get_node(above).name ~= modname .. ":funnel" then return end
|
||||
attempt_output(above)
|
||||
end)
|
|
@ -1,6 +0,0 @@
|
|||
-- this mod is disabled for now.
|
||||
--[[
|
||||
load_file("node")
|
||||
load_file("recipe")
|
||||
load_file("funnel")
|
||||
]]--
|
|
@ -1,3 +0,0 @@
|
|||
name = bg_funnel
|
||||
description = adds a funnel node to blockgame.
|
||||
depends = bg_terrain, bg_api, bg_tree, bg_woodworking
|
|
@ -1,27 +0,0 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
local api = load_file("api")
|
||||
|
||||
blockgame.register_node(modname .. ":funnel", {
|
||||
description = "Funnel",
|
||||
tiles = {
|
||||
modname .. "_funnel_top.png",
|
||||
modname .. "_funnel_top.png",
|
||||
modname .. "_funnel.png",
|
||||
},
|
||||
groups = {
|
||||
woody = 1,
|
||||
},
|
||||
on_place = function (...)
|
||||
return api.place_funnel(...)
|
||||
end,
|
||||
on_dig = function (...)
|
||||
return api.dig_funnel(...)
|
||||
end,
|
||||
preserve_metadata = function (pos, node, meta, drops)
|
||||
-- TODO: store funnel contents inside dropped item.
|
||||
end,
|
||||
after_place_node = function (pos, placer, item_stack)
|
||||
-- TODO: recreate funnel contents from placed item.
|
||||
end,
|
||||
})
|
|
@ -1,16 +0,0 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
blockgame.crafting.register_pummel_recipe({
|
||||
label = "pummel logs into funnel",
|
||||
used_item = "woodworking:plank",
|
||||
target_node = "bg_tree:log",
|
||||
check = function (pos, used_node, target_node)
|
||||
local below = pos + blockgame.vector.dirs.down
|
||||
return minetest.get_node(below).name == "bg_tree:log"
|
||||
end,
|
||||
on_success = function (pos, used_node, target_node)
|
||||
local below = pos + blockgame.vector.dirs.down
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(below, {name = modname .. ":funnel"})
|
||||
end,
|
||||
})
|
Binary file not shown.
Before Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 766 B |
|
@ -1,13 +1,17 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
local function is_stoney_below (pos)
|
||||
local below_node = minetest.get_node(pos + blockgame.vector.dirs.down)
|
||||
return blockgame.item_matches(below_node.name, {"group:stoney"})
|
||||
end
|
||||
|
||||
blockgame.crafting.register_pummel_recipe({
|
||||
name = modname .. ":craft_tile",
|
||||
label = "pummel stone into tile",
|
||||
used_item = "bg_terrain:cobblestone",
|
||||
target_node = "bg_terrain:cobblestone",
|
||||
used = {"group:stoney"},
|
||||
target = {"bg_terrain:cobblestone"},
|
||||
check = function (pos, used_node, target_node)
|
||||
local below_node = minetest.get_node(pos + blockgame.vector.dirs.down)
|
||||
local stoney_value = minetest.get_item_group(below_node.name, "stoney")
|
||||
return stoney_value ~= 0 and stoney_value ~= nil
|
||||
return is_stoney_below(pos)
|
||||
end,
|
||||
on_success = function (pos, used_node, target_node)
|
||||
minetest.set_node(pos, {name = modname .. ":tile"})
|
||||
|
@ -15,13 +19,12 @@ blockgame.crafting.register_pummel_recipe({
|
|||
})
|
||||
|
||||
blockgame.crafting.register_pummel_recipe({
|
||||
name = modname .. ":craft_bricks",
|
||||
label = "pummel tile into bricks",
|
||||
used_item = "bg_terrain:cobblestone",
|
||||
target_node = modname .. ":tile",
|
||||
used = {"group:stoney"},
|
||||
target = {modname .. ":tile"},
|
||||
check = function (pos, used_node, target_node)
|
||||
local below_node = minetest.get_node(pos + blockgame.vector.dirs.down)
|
||||
local stoney_value = minetest.get_item_group(below_node.name, "stoney")
|
||||
return stoney_value ~= 0 and stoney_value ~= nil
|
||||
return is_stoney_below(pos)
|
||||
end,
|
||||
on_success = function (pos, used_node, target_node)
|
||||
minetest.set_node(pos, {name = modname .. ":bricks"})
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
local function starts_with (str, start)
|
||||
return string.sub(str, 1, string.len(start)) == start
|
||||
end
|
||||
|
||||
-- rename from bg_core to bg_terrain.
|
||||
minetest.register_lbm({
|
||||
name = "bg_terrain:rename_core_mod",
|
||||
|
@ -18,8 +14,8 @@ minetest.register_lbm({
|
|||
run_at_every_load = true,
|
||||
action = function (pos, node)
|
||||
local prefix = ""
|
||||
if starts_with(node.name, "core") then prefix = "core"
|
||||
elseif starts_with(node.name, "bg_core") then prefix = "bg_core" end
|
||||
if blockgame.starts_with(node.name, "core") then prefix = "core"
|
||||
elseif blockgame.starts_with(node.name, "bg_core") then prefix = "bg_core" end
|
||||
|
||||
local name = string.sub(node.name, string.len(prefix) + 1)
|
||||
minetest.set_node(pos, {name = "bg_terrain" .. name})
|
||||
|
|
|
@ -27,20 +27,57 @@ blockgame.register_increasing_abm({
|
|||
end,
|
||||
})
|
||||
|
||||
local decompose_node_scores = {
|
||||
[leaves_decomposing] = 30,
|
||||
}
|
||||
local decompose_group_scores = {
|
||||
dirty = 50,
|
||||
}
|
||||
|
||||
local decompose_cost = 2000
|
||||
|
||||
blockgame.register_increasing_abm({
|
||||
id = modname .. ":decompose",
|
||||
label = "decompose leaves",
|
||||
nodenames = {leaves_decomposing},
|
||||
neighbors = {"group:dirty"},
|
||||
interval = 20,
|
||||
chance = 8,
|
||||
neighbors = {"group:dirty", leaves_decomposing},
|
||||
interval = 30,
|
||||
chance = 10,
|
||||
rate = function (pos, node, data)
|
||||
-- TODO: decompose faster depending on surrounding dirty nodes & other decomposing leaves.
|
||||
-- can probably do that with a flood fill that counts up a "score" depending on the nodes it encounters.
|
||||
return data.value + math.random(1, 9)
|
||||
local score = 100
|
||||
|
||||
local source_pos = pos
|
||||
blockgame.flood_fill(pos, function (pos, distance)
|
||||
if pos == source_pos then return true end
|
||||
|
||||
local name = minetest.get_node(pos).name
|
||||
|
||||
local gain = 0
|
||||
for group, value in pairs(decompose_group_scores) do
|
||||
if minetest.get_item_group(name, group) > 0 then
|
||||
gain = math.max(gain, value)
|
||||
end
|
||||
end
|
||||
|
||||
gain = math.floor(gain / distance)
|
||||
|
||||
if gain > 0 then
|
||||
score = score + gain
|
||||
return true
|
||||
end
|
||||
|
||||
if decompose_node_scores[name] then
|
||||
score = score + math.floor(decompose_node_scores[name] / distance)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end, 4)
|
||||
|
||||
return data.value + score
|
||||
end,
|
||||
check = function (pos, node, data)
|
||||
return data.value >= 25
|
||||
return data.value >= decompose_cost
|
||||
end,
|
||||
action = function (pos, node, data)
|
||||
if blockgame.chance(2) then
|
||||
|
|
|
@ -14,5 +14,5 @@ minetest.register_decoration({
|
|||
},
|
||||
y_min = -31000,
|
||||
y_max = 31000,
|
||||
decoration = modname .. ":leaves",
|
||||
decoration = modname .. ":sapling",
|
||||
})
|
||||
|
|
|
@ -62,18 +62,36 @@ local function reg_leaves (name, def)
|
|||
blockgame.register_node(modname .. ":" .. name, def)
|
||||
end
|
||||
|
||||
local nutty_drops = {
|
||||
max_items = 3,
|
||||
items = {
|
||||
{
|
||||
rarity = 8,
|
||||
items = {modname .. ":nut"},
|
||||
},
|
||||
{
|
||||
rarity = 12,
|
||||
items = {modname .. ":nut 2"},
|
||||
},
|
||||
{
|
||||
rarity = 1,
|
||||
items = {modname .. ":leaves"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
reg_leaves("leaves", {
|
||||
description = "Leaves",
|
||||
})
|
||||
reg_leaves("leaves_growing", {
|
||||
description = "Growing Leaves",
|
||||
drop = modname .. ":leaves",
|
||||
texture = "leaves_alive",
|
||||
drop = nutty_drops,
|
||||
fall_check = leaves_fall_check,
|
||||
})
|
||||
reg_leaves("leaves_alive", {
|
||||
description = "Leaves",
|
||||
drop = modname .. ":leaves",
|
||||
drop = nutty_drops,
|
||||
fall_check = leaves_fall_check,
|
||||
})
|
||||
reg_leaves("leaves_decomposing", {
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
load_file("node")
|
||||
load_file("recipes")
|
||||
load_file("recipe")
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
blockgame.crafting.register_pummel_recipe({
|
||||
label = "pummel log into plank",
|
||||
used_item = "bg_terrain:cobblestone",
|
||||
target_node = "bg_tree:log",
|
||||
name = modname .. ":chop_log",
|
||||
label = "chop log into plank",
|
||||
used = {"group:stoney"},
|
||||
target = {"bg_tree:log"},
|
||||
check = function (pos, used_node, target_node)
|
||||
for _, side in pairs(blockgame.vector.sides) do
|
||||
local output_pos = pos + side
|
Loading…
Reference in New Issue