Compare commits

...

10 Commits

Author SHA1 Message Date
trans_soup bfc036389c fix root growth error.
roots now extend from below the bottom log, instead of from the log
itself.
2023-10-12 11:13:44 +02:00
trans_soup 9133c0d5c4 minor tree growth changes.
make trees grow further before dying.
2023-10-12 11:12:21 +02:00
trans_soup 91807870fe miscellaneous refactors & fixes.
move several functions into the api.

fix root growth directions.

clean up root and grass growth code.
2023-10-12 11:09:40 +02:00
trans_soup 203de199a3 increase hand range. 2023-10-12 10:35:40 +02:00
trans_soup a68bed3c70 change stoneworking recipes.
tile and bricks recipes now use cobblestone instead of stone, to make
them available again now that stone drops cobblestone.
2023-10-12 10:26:02 +02:00
trans_soup 3bd1e66e29 improve grass growth.
grass now grows up and down diagonally in the cardinal directions.
2023-10-12 10:25:01 +02:00
trans_soup 7b86727e4b create grass mod.
create a new mod that implements basic grass growth and death.
2023-10-12 08:26:37 +02:00
trans_soup 850d397a97 refactor: minor code style change.
change the way some functions are declared.
2023-10-11 19:12:47 +02:00
trans_soup 7df4ddec1c create woodworking mod and refactor.
move plank registration and recipe out of tree mod into newly created
woodworking mod.

also update plank recipe to require cobblestone instead of stone to be
held while pummeling.
2023-10-11 19:05:38 +02:00
trans_soup 09feb14dbb fix log textures. 2023-10-11 18:26:48 +02:00
23 changed files with 240 additions and 95 deletions

View File

@ -6,7 +6,11 @@ rawset(_G, "load_file", load_file)
local blockgame = {}
rawset(_G, "blockgame", blockgame)
load_file("utils_node")
load_file("utils_table")
load_file("utils_stringify")
load_file("utils_random")
load_file("utils_vector")
load_file("utils_node")
load_file("wrapper_abm")

View File

@ -1,4 +1,4 @@
local reg_simple_node = function (name, desc, groups)
function blockgame.reg_simple_node (name, desc, groups)
local my_modname = minetest.get_current_modname()
return minetest.register_node(my_modname .. ":" .. name, {
description = desc,
@ -9,4 +9,49 @@ local reg_simple_node = function (name, desc, groups)
})
end
blockgame.reg_simple_node = reg_simple_node
-- probably temporary; will probably use groups for this later.
local air_flowable = {
"air",
"tree:leaves",
"tree:leaves_alive",
}
function blockgame.air_flows_through (pos, node)
node = node or minetest.get_node(pos)
local node_name = node.name
for _, name in pairs(air_flowable) do
if name == node_name then return true end
end
return false
end
function blockgame.attempt_place (pos, node)
if minetest.get_node(pos).name ~= "air" then return false end
minetest.set_node(pos, node)
return true
end
function blockgame.random_walk (data)
local pos = vector.copy(data.pos)
local min_steps = data.min_steps or 0
local max_steps = data.max_steps or 8
local check = data.check
local neighborhood = data.neighborhood or blockgame.vector.dirs
local steps = math.random(min_steps, max_steps)
local step = 0
while step < steps do
local dir = blockgame.random_element(neighborhood)
local new_pos = pos + dir
if check(new_pos, minetest.get_node(new_pos)) then pos = new_pos end
step = step + 1
end
return pos
end

View File

@ -1,5 +1,10 @@
local modname = minetest.get_current_modname()
blockgame.chance = function (chance)
function blockgame.chance (chance)
return math.random(chance) == 1
end
function blockgame.random_element (tab)
local keys = blockgame.get_keys(tab)
return tab[keys[math.random(#keys)]]
end

View File

@ -1,4 +1,4 @@
local stringify = function (tab)
function blockgame.stringify (tab)
if type(tab) == "table" then
local result = "{ "
for key, value in pairs(tab) do
@ -9,5 +9,3 @@ local stringify = function (tab)
return tab
end
end
blockgame.stringify = stringify

View File

@ -0,0 +1,17 @@
function blockgame.get_keys (tab)
local keyset = {}
local n = 0
for key, value in pairs(tab) do
n = n + 1
keyset[n] = key
end
return keyset
end
function blockgame.shallow_copy_table (tab)
local result = {}
for key, value in pairs(tab) do
result[key] = value
end
return result
end

View File

@ -1,6 +1,8 @@
blockgame.vector = blockgame.vector or {}
local api = blockgame.vector
-- TODO: replace direct sharing of api variables such as `sides` with functions that return them, to prevent other mods from mutating the shared data.
api.horizontal_directions = {
west = vector.new(-1, 0, 0),
east = vector.new(1, 0, 0),
@ -19,29 +21,16 @@ api.directions = {
}
api.dirs = api.directions
local get_keys = function (tab)
local keyset = {}
local n = 0
for key, value in pairs(tab) do
n = n + 1
keyset[n] = key
end
return keyset
function api.random_dir ()
return blockgame.random_element(api.dirs)
end
local random_element = function (tab)
local keys = get_keys(tab)
return tab[keys[math.random(#keys)]]
function api.random_side ()
return blockgame.random_element(api.sides)
end
api.random_dir = function ()
return random_element(api.dirs)
end
api.random_side = function ()
return random_element(api.sides)
end
api.get_below = function (pos)
function api.get_below (pos)
return pos + api.dirs.down
end

View File

@ -0,0 +1,3 @@
function blockgame.register_abm (...)
return minetest.register_abm(...)
end

View File

@ -1,4 +1,4 @@
local create_group_cap = function (max_level)
local function create_group_cap (max_level)
return {maxlevel = max_level, times={[1] = 1, [2] = 2, [3] = 3}}
end
@ -16,4 +16,5 @@ minetest.register_item(":", {
},
},
node_placement_prediction = "",
range = 5.0,
})

View File

@ -4,7 +4,7 @@ local api = blockgame.crafting
local recipes = {}
api.registered_recipes = recipes
api.register_stack_recipe = function (top_node, bottom_node, result, consumes_top)
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
@ -20,7 +20,7 @@ api.register_stack_recipe = function (top_node, bottom_node, result, consumes_to
})
end
api.handle_placement = function (pos, new_node, placer, old_node, itemstack, pointed_thing)
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
@ -31,7 +31,7 @@ api.handle_placement = function (pos, new_node, placer, old_node, itemstack, poi
return false
end
api.handle_stack_recipe = function (recipe, pos, top_node)
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))
@ -48,7 +48,7 @@ end
local pummel_recipes = {}
api.register_pummel_recipe = function (def)
function api.register_pummel_recipe (def)
local def = def or {}
def.label = def.label or "unnamed pummel recipe"
@ -66,7 +66,7 @@ api.register_pummel_recipe = function (def)
end
-- TODO: add support for pummel recipes using groups instead of just specific node names.
api.pummel_check = function (pos, used_item, target_node)
function api.pummel_check (pos, used_item, target_node)
local key = used_item
if not pummel_recipes[key] then return false end

10
mods/bg_grass/death.lua Normal file
View File

@ -0,0 +1,10 @@
blockgame.register_abm({
nodenames = {"core:grass"},
interval = 15,
chance = 4,
action = function (pos, node)
if blockgame.air_flows_through(pos + blockgame.vector.dirs.up) then return false end
minetest.set_node(pos, {name = "core:dirt"})
return true
end,
})

56
mods/bg_grass/grow.lua Normal file
View File

@ -0,0 +1,56 @@
-- TODO: move these to the general api.
local function listify_table (tab)
local copy = {}
for _, item in pairs(tab) do
table.insert(copy, item)
end
return copy
end
local function shuffle (tab)
tab = listify_table(tab)
local shuffled = {}
repeat
local index = math.random(1, #tab)
local value = tab[index]
table.insert(shuffled, value)
table.remove(tab, index)
until #tab == 0
return shuffled
end
blockgame.register_abm({
nodenames = {"core:grass"},
neighbors = {"core:dirt"},
interval = 15,
chance = 8,
action = function (pos, node)
local sides = listify_table(blockgame.vector.sides)
local diagonally = {}
for _, side in pairs(sides) do
table.insert(diagonally, side + blockgame.vector.dirs.down)
table.insert(diagonally, side + blockgame.vector.dirs.up)
end
sides = shuffle(sides)
diagonally = shuffle(diagonally)
for _, offset in pairs(sides) do
if attempt_spread(pos + offset) then return true end
end
for _, offset in pairs(diagonally) do
if attempt_spread(pos + offset) then return true end
end
return false
end,
})
function attempt_spread (pos)
if minetest.get_node(pos).name ~= "core:dirt" then return false end
if not blockgame.air_flows_through(pos + blockgame.vector.dirs.up) then return false end
minetest.set_node(pos, {name = "core:grass"})
return true
end

2
mods/bg_grass/init.lua Normal file
View File

@ -0,0 +1,2 @@
load_file("grow")
load_file("death")

3
mods/bg_grass/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = grass
description = adds grass spreading and related mechanics to blockgame.
depends = core, api

View File

@ -2,8 +2,8 @@ local modname = minetest.get_current_modname()
blockgame.crafting.register_pummel_recipe({
label = "pummel stone into tile",
used_item = "core:stone",
target_node = "core:stone",
used_item = "core:cobblestone",
target_node = "core: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")
@ -16,7 +16,7 @@ blockgame.crafting.register_pummel_recipe({
blockgame.crafting.register_pummel_recipe({
label = "pummel tile into bricks",
used_item = "core:stone",
used_item = "core:cobblestone",
target_node = modname .. ":tile",
check = function (pos, used_node, target_node)
local below_node = minetest.get_node(pos + blockgame.vector.dirs.down)

View File

@ -3,7 +3,7 @@ local modname = minetest.get_current_modname()
blockgame.tree = blockgame.tree or {}
local api = blockgame.tree
api.find_bottom_log = function (pos, max_height)
function api.find_bottom_log (pos, max_height)
local pos = vector.copy(pos)
local step = 0
while step < max_height do

View File

@ -11,45 +11,43 @@ local leaves_alive = modname .. ":leaves_alive"
local root = modname .. ":root"
-- END OF NODE NAMES
-- LOCALS CACHE
local attempt_place = function (pos, node)
if minetest.get_node(pos).name ~= "air" then return false end
return minetest.set_node(pos, node)
end
local all_sides_except_up = blockgame.shallow_copy_table(blockgame.vector.dirs)
all_sides_except_up.up = nil
-- END OF LOCALS CACHE
local extend_leaves_from = function (pos)
local function extend_leaves_from (pos)
local side = vec.random_side()
attempt_place(pos + side, {name = leaves_alive})
blockgame.attempt_place(pos + side, {name = leaves_alive})
end
local random_walk = function (pos, steps, check)
local pos = vector.copy(pos)
local step = 0
while step < steps do
local dir = vec.random_dir()
local new_pos = pos + dir
if check(new_pos) then pos = new_pos end
step = step + 1
end
return pos
end
local spread_roots_from = function (source)
local root_pos = random_walk(source, 2, function (pos)
if minetest.get_node(pos).name == log_alive then return true end
if minetest.get_node(pos).name == root then return true end
return false
end)
local function spread_roots_from (source)
local root_pos = blockgame.random_walk({
pos = source,
check = function (pos)
local name = minetest.get_node(pos).name
if name == log_alive then return true end
if name == root then return true end
return false
end,
neighborhood = all_sides_except_up,
})
if not root_pos then return false end
local root_node = minetest.get_node(root_pos)
if minetest.get_node(root_pos + vector.new(0, 1, 0)).name == log_alive then
if minetest.get_node(root_pos + blockgame.vector.dirs.up).name == log_alive then
minetest.set_node(root_pos, {name = root})
return true
end
local side = vec.random_side()
local side = blockgame.random_element(all_sides_except_up)
local target_pos = root_pos + side
if blockgame.chance(2) then target_pos = vec.get_below(root_pos) end
@ -73,7 +71,7 @@ minetest.register_abm({
if blockgame.chance(4) then
local root_source = api.find_bottom_log(pos, 8)
if root_source ~= nil then
spread_roots_from(root_source)
spread_roots_from(root_source + blockgame.vector.dirs.down)
end
end
@ -88,7 +86,7 @@ minetest.register_abm({
local side = vec.random_side()
local target = pos + side
attempt_place(target, {name = log_alive})
blockgame.attempt_place(target, {name = log_alive})
if blockgame.chance(2) then
extend_leaves_from(target)
@ -98,9 +96,9 @@ minetest.register_abm({
if blockgame.chance(4) then
minetest.set_node(pos, {name = log_alive})
if minetest.get_node(below).name == log_alive and blockgame.chance(2) then return end
if minetest.get_node(below).name == log_alive and blockgame.chance(4) then return end
attempt_place(pos + vector.new(0, 1, 0), {name = modname .. ":sapling"})
blockgame.attempt_place(pos + vector.new(0, 1, 0), {name = modname .. ":sapling"})
end
end,
})

View File

@ -1,12 +1,21 @@
local modname = minetest.get_current_modname()
blockgame.reg_simple_node("log", "Log", {
woody = 1,
minetest.register_node(modname .. ":log", {
description = "Log",
tiles = {
modname .. "_log_top.png",
modname .. "_log_top.png",
modname .. "_log.png",
},
groups = {
woody = 1,
},
})
minetest.register_node(modname .. ":log_alive", {
description = "Growing Log",
tiles = {
modname .. "_log_top.png",
modname .. "_log_top_alive.png",
modname .. "_log_top_alive.png",
modname .. "_log_alive.png",
},
groups = {
@ -20,11 +29,6 @@ blockgame.reg_simple_node("sapling", "Sapling", {
planty = 1,
})
-- TODO: move this to the woodworking mod.
blockgame.reg_simple_node("plank", "Plank", {
woody = 1,
})
minetest.register_node(modname .. ":leaves", {
description = "Leaves",
drawtype = "glasslike",

View File

@ -13,24 +13,3 @@ blockgame.crafting.register_pummel_recipe({
minetest.set_node(pos, {name = "core:dirt"})
end,
})
-- TODO: move this to the woodworking mod.
blockgame.crafting.register_pummel_recipe({
label = "pummel log into plank",
used_item = "core:stone",
target_node = modname .. ":log",
check = function (pos, used_node, target_node)
for _, side in pairs(blockgame.vector.sides) do
local output_pos = pos + side
if minetest.get_node(output_pos).name ~= "air" then return false end
end
return true
end,
on_success = function (pos, used_node, target_node)
minetest.remove_node(pos)
for _, side in pairs(blockgame.vector.sides) do
local output_pos = pos + side
minetest.set_node(output_pos, {name = modname .. ":plank"})
end
end,
})

View File

@ -0,0 +1,2 @@
load_file("node")
load_file("recipes")

View File

@ -0,0 +1,3 @@
name = woodworking
description = blockgame wood related recipes and stuff.
depends = core, crafting, api, tree

View File

@ -0,0 +1,5 @@
local modname = minetest.get_current_modname()
blockgame.reg_simple_node("plank", "Plank", {
woody = 1,
})

View File

@ -0,0 +1,21 @@
local modname = minetest.get_current_modname()
blockgame.crafting.register_pummel_recipe({
label = "pummel log into plank",
used_item = "core:cobblestone",
target_node = "tree:log",
check = function (pos, used_node, target_node)
for _, side in pairs(blockgame.vector.sides) do
local output_pos = pos + side
if minetest.get_node(output_pos).name ~= "air" then return false end
end
return true
end,
on_success = function (pos, used_node, target_node)
minetest.remove_node(pos)
for _, side in pairs(blockgame.vector.sides) do
local output_pos = pos + side
minetest.set_node(output_pos, {name = modname .. ":plank"})
end
end,
})

View File

Before

Width:  |  Height:  |  Size: 218 B

After

Width:  |  Height:  |  Size: 218 B