Started a large refactor project.

The idea is to merge the pummel logic with crafting recipes,
and move them up out of plain old api.
This commit is contained in:
Aaron Suen 2019-02-03 08:58:27 -05:00
parent 0627c22101
commit f98e8be5c2
12 changed files with 454 additions and 12 deletions

View File

@ -13,8 +13,8 @@ ROADMAP (SHORT-TERM)
- Need to make lode ore require same or higher tier tools than
stone, not lower. Should not be hand-diggable in any form.
- Metal casting, annealing, tempering
- Hammer annealed prills -> annealed metal slabs/blocks
- Hammer annealed slabs/blocks -> annealed tool heads
- Axe annealed blocks/slabs -> annealed prills
- Hammer annealed slabs -> annealed tool heads
- Create and use annealed tools
- Heat annealed tool heads -> glowing tool heads
- Quench glowing tool heads -> tempered tool heads
@ -30,6 +30,9 @@ ROADMAP (SHORT-TERM)
- Chop dirt with an axe.
- Hammer together 4 stones instead of 8.
- Pummel tree from the side with a higher tier axe, stone/metal?
- Social features
- Randomize player appearance/colors
- Hardcore names...?
- Plant life stuff
- Better tree growth, i.e. track cumulative time, apply
environmental factors.

View File

@ -114,7 +114,7 @@ minetest.register_on_punchnode(function(pos, node, puncher, pointed)
if pum.count > 1 then
if pum.particles then pum.particles() end
pum.particles = particlefx(pname, pointed, def)
pum.particles = particlefx(pname, pointed, pum.def)
end
if resolve(pos, node, pum) then

View File

@ -0,0 +1,35 @@
-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, pairs
= math, minetest, nodecore, pairs
local math_ceil, math_floor, math_random
= math.ceil, math.floor, math.random
-- LUALOCALS > ---------------------------------------------------------
function nodecore.digparticles(pointed, def)
local img = {}
if def.tiles then
for i = 1, 6 do
img[#img + 1] = def.tiles[i > #def.tiles and #def.tiles or i]
end
elseif def.inventory_image then
img[1] = def.inventory_image
end
if #img < 1 then return minetest.log("no pummel tile images found!") end
img = nodecore.pickrand(img)
if img.name then img = img.name end
def.amount = def.amount and math_ceil(def.amount / 4) or 4
local t = {}
for i = 1, 4 do
def.texture = img .. "^[mask:[combine\\:16x16\\:"
.. math_floor(math_random() * 12) .. ","
.. math_floor(math_random() * 12) .. "=nc_api_pummel.png"
t[#t + 1] = minetest.add_particlespawner(def)
end
return function()
for k, v in pairs(t) do
minetest.delete_particlespawner(v)
end
end
end

View File

@ -4,11 +4,10 @@ local dofile, minetest, rawget, rawset
= dofile, minetest, rawget, rawset
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local nodecore = rawget(_G, "nodecore") or {}
rawset(_G, "nodecore", nodecore)
local modname = minetest.get_current_modname()
local path = minetest.get_modpath(modname)
dofile(path .. "/util_misc.lua")

63
mods/nc_api/match.lua Normal file
View File

@ -0,0 +1,63 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore, pairs, type
= minetest, nodecore, pairs, type
-- LUALOCALS > ---------------------------------------------------------
local match_skip = {
name = true,
param2 = true,
param = true,
groups = true,
inv = true,
count = true,
wear = true
}
function nodecore.match(thing, crit)
local stack = thing.stack
if stack then
thing.name = stack:get_name()
thing.count = stack:get_count()
thing.wear = stack:get_wear()
end
if not thing.name then
thing = nodecore.underride(thing, minetest.get_node(thing))
end
if type(crit) == "string" then crit = {name = crit} end
if crit.name and thing.name ~= crit.name then return end
if crit.param2 and thing.param2 ~= crit.param2 then return end
if crit.param and thing.param ~= crit.param then return end
if crit.count and thing.count ~= crit.count then return end
if crit.wear then
if crit.wear < 1 then crit.wear = crit.wear * 65535 end
if thing.wear > crit.wear then return end
end
local def = minetest.registered_items[thing.name]
if crit.groups then
if not def.groups then return end
for k, v in pairs(crit.groups) do
if v == true then
if not def.groups[k] then return end
elseif v == false then
if def.groups[k] then return end
else
if def.groups[k] ~= v then return end
end
end
end
for k, v in pairs(crit) do
if not match_skip[k] then
if def[k] ~= v then return end
end
end
if crit.inv then
local stack = minetest.get_meta(thing):get_inventory():get_stack("solo", 1)
if not stack or stack:is_empty() then return end
return nodecore.match({stack = stack}, crit.inv)
end
return thing
end

View File

@ -0,0 +1,74 @@
-- LUALOCALS < ---------------------------------------------------------
local ipairs, minetest, nodecore, pairs, type
= ipairs, minetest, nodecore, pairs, type
-- LUALOCALS > ---------------------------------------------------------
local function craftcheck(recipe, pos, node, data, xx, xz, zx, zz)
local function rel(x, y, z)
return {
x = pos.x + xx * x + zx * z,
y = pos.y + y,
z = pos.z + xz * x + zz * z
}
end
if recipe.check and not recipe.check(pos, data, rel) then return end
if recipe.wield and (not data.crafter or not nodecore.match(
{stack = data.crafter:get_wielded_item()}, recipe.wield)) then return end
if recipe.normal then
if data.pointed.type ~= "node" or
recipe.normal.y ~= data.pointed.above.y - data.pointed.under.y then return end
local rx = recipe.normal.x * xx + recipe.normal.z * zx
if rx ~= data.pointed.above.x - data.pointed.under.x then return end
local rz = recipe.normal.x * xz + recipe.normal.z * zz
if rz ~= data.pointed.above.z - data.pointed.under.z then return end
end
for _, v in pairs(recipe.nodes) do
if v ~= recipe.root and v.match then
local p = rel(v.x, v.y, v.z)
if not nodecore.match(p, v.match) then return end
end
end
for _, v in pairs(recipe.nodes) do
if v.replace then
local p = rel(v.x, v.y, v.z)
local r = v.replace
while type(r) == "function" do
r = r(p, v)
end
if r and type(r) == "string" then
r = {name = r}
end
if r then minetest.set_node(p, r) end
end
end
if recipe.items then
for _, v in pairs(recipe.items) do
nodecore.item_eject(rel(v.x or 0, v.y or 0, v.z or 0), v)
end
end
if recipe.after then recipe.after(pos, rel, data) end
return true
end
function nodecore.craft_check(rtype, pos, node, data)
data = data or {}
local function go(xx, xz, zx, zz)
return craftcheck(rc, pos, node, data, xx, xz, zx, zz)
end
for _, rc in ipairs(nodecore.craft_recipes[rtype] or {}) do
if nodecore.match(node, rc.root.match) then
if go(1, 0, 0, 1) then return true end
if not rc.norotate then
if go(0, -1, 1, 0) then return true end
if go(-1, 0, 0, -1) then return true end
if go(0, 1, -1, 0) then return true end
if not rc.nomirror then
if go(-1, 0, 0, 1) then return true end
if go(0, 1, 1, 0) then return true end
if go(1, 0, 0, -1) then return true end
if go(0, -1, -1, 0) then return true end
end
end
end
end
end

View File

@ -0,0 +1 @@
nc_api

View File

@ -0,0 +1,13 @@
-- LUALOCALS < ---------------------------------------------------------
-- SKIP: nodecore
local dofile, minetest
= dofile, minetest
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local path = minetest.get_modpath(modname)
dofile(path .. "/register_craft.lua")
dofile(path .. "/craft_check.lua")
dofile(path .. "/item_place_node.lua")
dofile(path .. "/register_on_punchnode.lua")

View File

@ -0,0 +1,24 @@
-- LUALOCALS < ---------------------------------------------------------
local minetest, nodecore
= minetest, nodecore
-- LUALOCALS > ---------------------------------------------------------
local old_place = minetest.item_place_node
function minetest.item_place_node(itemstack, placer, pointed_thing, ...)
local old_add = minetest.add_node
minetest.add_node = function(pos, node, ...)
local function helper2(...)
nodecore.craft_check("place", pos, node, {
crafter = placer,
pointed = pointed_thing
})
return ...
end
return helper2(old_add(pos, node, ...))
end
local function helper(...)
minetest.add_node = old_add
return ...
end
return helper(old_place(itemstack, placer, pointed_thing, ...))
end

View File

@ -0,0 +1,53 @@
-- LUALOCALS < ---------------------------------------------------------
local error, math, nodecore, pairs, table, type
= error, math, nodecore, pairs, table, type
local math_floor, table_insert
= math.floor, table.insert
-- LUALOCALS > ---------------------------------------------------------
local craft_recipes = {}
nodecore.craft_recipes = craft_recipes
function nodecore.register_craft(recipe)
recipe.type = recipe.type or "place"
local canrot
recipe.nodes = recipe.nodes or {}
for _, v in pairs(recipe.nodes) do
v.x = v.x or 0
v.y = v.y or 0
v.z = v.z or 0
canrot = canrot or v.x ~= 0 or v.z ~= 0
if v.x == 0 and v.y == 0 and v.z == 0 then
recipe.root = v
end
end
if not recipe.root or not recipe.root.match then
error "recipe.nodes must have a match for 0,0,0"
end
if not canrot then recipe.norotate = true end
if recipe.normal then
recipe.normal.x = recipe.normal.x or 0
recipe.normal.y = recipe.normal.y or 0
recipe.normal.z = recipe.normal.z or 0
end
local newp = recipe.priority or 0
local rectype = craft_recipes[recipe.type]
if not rectype then
rectype = {}
craft_recipes[recipe.type] = rt
end
local min = 1
local max = #rectype + 1
while max > min do
local try = math_floor((min + max) / 2)
local oldp = rectype[try].priority or 0
if newp < oldp then
min = try + 1
else
max = try
end
end
table_insert(rectype, min, recipe)
end

View File

@ -0,0 +1,145 @@
-- LUALOCALS < ---------------------------------------------------------
local ipairs, math, minetest, nodecore, pairs, vector
= ipairs, math, minetest, nodecore, pairs, vector
local math_floor, math_random
= math.floor, math.random
-- LUALOCALS > ---------------------------------------------------------
local pummeling = {}
local function fxcore(pname, pointed, img)
img = img .. "^[mask:[combine\\:16x16\\:"
.. math_floor(math_random() * 12) .. ","
.. math_floor(math_random() * 12) .. "=nc_api_pummel.png"
local a = pointed.above
local b = pointed.under
local vel = vector.subtract(a, b)
local mid = vector.multiply(vector.add(a, b), 0.5)
local p1 = {x = vel.y, y = vel.z, z = vel.x}
local p2 = {x = vel.z, y = vel.x, z = vel.y}
local s1 = vector.add(vector.add(mid, vector.multiply(p1, 0.5)), vector.multiply(p2, 0.5))
local s2 = vector.add(vector.add(mid, vector.multiply(p1, -0.5)), vector.multiply(p2, -0.5))
vel = vector.multiply(vel, 0.5)
return minetest.add_particlespawner({
amount = 3,
time = 1.5,
minpos = s1,
maxpos = s2,
minvel = vel,
maxvel = vel,
minexptime = 0.4,
maxexptime = 0.9,
minsize = 1,
maxsize = 5,
texture = img,
playername = pname
})
end
local function particlefx(pname, pointed, def)
local img = {}
if def.tiles then
for i = 1, 6 do
img[#img + 1] = def.tiles[i > #def.tiles and #def.tiles or i]
end
elseif def.inventory_image then
img[1] = def.inventory_image
end
if #img < 1 then return minetest.log("no pummel tile images found!") end
img = nodecore.pickrand(img)
if img.name then img = img.name end
local t = {}
for i = 1, 4 do
t[#t + 1] = fxcore(pname, pointed, img)
end
return function()
for k, v in pairs(t) do
minetest.delete_particlespawner(v)
end
end
end
minetest.register_on_punchnode(function(pos, node, puncher, pointed)
if not puncher:is_player() then return end
local pname = puncher:get_player_name()
node = node or minetest.get_node(pos)
local def = minetest.registered_nodes[node.name]
if not def.pummeldefs then return end
local now = minetest.get_us_time() / 1000000
local pum = {
puncher = puncher,
pname = pname,
pos = pos,
pointed = pointed,
node = node,
def = def,
start = now,
wield = puncher:get_wielded_item():to_string(),
count = 0
}
local old = pummeling[pname]
local hash = minetest.hash_node_position
if old and hash(old.pos) == hash(pum.pos)
and hash(old.pointed.above) == hash(pum.pointed.above)
and hash(old.pointed.under) == hash(pum.pointed.under)
and pum.wield == old.wield
and old.last >= (now - 2)
then pum = old end
pum.count = pum.count + 1
pum.last = now
pum.duration = now - pum.start
pummeling[pname] = pum
local resolve
for i, v in ipairs(def.pummeldefs) do
if not resolve then
local ok = v.check(pos, node, pum)
if ok then
resolve = v.resolve
pum.check = ok
end
end
end
if not resolve then
pummeling[pname] = nil
return
end
if pum.count > 1 then
if pum.particles then pum.particles() end
pum.particles = particlefx(pname, pointed, pum.def)
end
if resolve(pos, node, pum) then
if pum.particles then pum.particles() end
--nodecore.player_knowledge_add(puncher, "pummel:" .. node.name)
pummeling[pname] = nil
end
end)
function nodecore.add_pummel(nodedef, check, resolve)
nodedef.pummeldefs = nodedef.pummeldefs or {}
nodedef.pummeldefs[#nodedef.pummeldefs + 1] = {
check = check,
resolve = resolve
}
end
function nodecore.extend_pummel(name, check, resolve)
nodecore.extend_item(name, function(copy)
return nodecore.add_pummel(copy, check, resolve)
end)
end
function nodecore.pummel_toolspeed(pos, node, stats)
return nodecore.toolspeed(
stats.puncher:get_wielded_item(),
stats.def.groups
)
end

View File

@ -7,7 +7,7 @@ local modname = minetest.get_current_modname()
local hotitems = {}
local function reg(shape, rawdef)
function nodecore.register_lode(shape, rawdef)
for _, temper in pairs({"Hot", "Annealed", "Tempered"}) do
local def = nodecore.underride({}, rawdef)
def = nodecore.underride(def, {
@ -41,11 +41,7 @@ local function reg(shape, rawdef)
end
end
reg("Prill", {
type = "craft",
inventory_image = modname .. "_#.png^[mask:" .. modname .. "_mask_prill.png"
})
reg("Slab", {
nodecore.register_lode("Slab", {
type = "node",
drawtype = "nodebox",
node_box = nodecore.fixedbox(-0.5, -0.5, -0.5, 0.5, 0, 0.5),
@ -54,13 +50,49 @@ reg("Slab", {
light_source = 6,
crush_damage = 1
})
reg("Block", {
nodecore.register_lode("Block", {
type = "node",
tiles = { modname .. "_#.png" },
light_source = 8,
crush_damage = 4
})
nodecore.register_lode("Prill", {
type = "craft",
inventory_image = modname .. "_#.png^[mask:" .. modname .. "_mask_prill.png",
})
nodecore.extend_item(modname .. ":prill_hot", function(def)
def.pummel_stack = 4
end)
nodecore.extend_pummel(modname .. ":prill_hot",
function(pos, node, stats)
return nodecore.toolspeed(
stats.puncher:get_wielded_item(),
{ thumpy = 3 })
end,
function(pos, node, stats)
if stats.duration >= stats.check then
minetest.set_node(pos, {name = modname .. ":slab_hot"})
end
end)
nodecore.extend_pummel(modname .. ":slab_hot",
function(pos, node, stats)
if stats.pointed.above.y <= stats.pointed.under.y then return end
if minetest.get_node(stats.pointed.under).name ~= modname .. ":slab_hot" then return end
return nodecore.toolspeed(
stats.puncher:get_wielded_item(),
{ thumpy = 3 })
end,
function(pos, node, stats)
if stats.duration >= stats.check then
minetest.remove_node(pos)
minetest.set_node({x = pos.x, y = pos.y - 1, z = pos.z},
{name = modname .. ":block_hot"})
end
end)
local flame = {groups = {flame = true}}
local function heated(pos)
if nodecore.quenched(pos) then return end