Compare commits
10 Commits
c3fb8df14a
...
bfc036389c
Author | SHA1 | Date |
---|---|---|
trans_soup | bfc036389c | |
trans_soup | 9133c0d5c4 | |
trans_soup | 91807870fe | |
trans_soup | 203de199a3 | |
trans_soup | a68bed3c70 | |
trans_soup | 3bd1e66e29 | |
trans_soup | 7b86727e4b | |
trans_soup | 850d397a97 | |
trans_soup | 7df4ddec1c | |
trans_soup | 09feb14dbb |
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
function blockgame.register_abm (...)
|
||||
return minetest.register_abm(...)
|
||||
end
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
})
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
load_file("grow")
|
||||
load_file("death")
|
|
@ -0,0 +1,3 @@
|
|||
name = grass
|
||||
description = adds grass spreading and related mechanics to blockgame.
|
||||
depends = core, api
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
load_file("node")
|
||||
load_file("recipes")
|
|
@ -0,0 +1,3 @@
|
|||
name = woodworking
|
||||
description = blockgame wood related recipes and stuff.
|
||||
depends = core, crafting, api, tree
|
|
@ -0,0 +1,5 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
blockgame.reg_simple_node("plank", "Plank", {
|
||||
woody = 1,
|
||||
})
|
|
@ -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,
|
||||
})
|
Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 218 B |
Loading…
Reference in New Issue