Finished Soaking API, converted trees and infusion to it.

This commit is contained in:
Aaron Suen 2019-09-05 22:48:30 -04:00
parent 253ccad3e2
commit cbf035e0d5
6 changed files with 126 additions and 37 deletions

View File

@ -21,7 +21,6 @@ ISSUES: Bugs, Cleanup and Refinements
- Do nothing after return; callback responsible - Do nothing after return; callback responsible
for all transformations. for all transformations.
- Uses: - Uses:
- Tree growth.
- Lux infusion. - Lux infusion.
- Fallen leaves + grass + sunlight decay to nothing. - Fallen leaves + grass + sunlight decay to nothing.
- Fallen leaves buried in leaves decay to dirt. - Fallen leaves buried in leaves decay to dirt.

View File

@ -58,6 +58,7 @@ include("match")
include("fx_digparticles") include("fx_digparticles")
include("register_limited_abm") include("register_limited_abm")
include("register_soaking_abm")
include("register_ambiance") include("register_ambiance")
include("mapgen_shared") include("mapgen_shared")

View File

@ -0,0 +1,75 @@
-- LUALOCALS < ---------------------------------------------------------
local error, math, minetest, nodecore, type
= error, math, minetest, nodecore, type
local math_floor, math_sqrt
= math.floor, math.sqrt
-- LUALOCALS > ---------------------------------------------------------
function nodecore.register_soaking_abm(def)
def.qtyfield = def.qtyfield or "soakqty"
def.timefield = def.timefield or "soaktime"
def.soakinterval = def.soakinterval or ((def.interval or 1) * (def.chance or 1))
if not def.soakrate then error("soaking abm missing soakrate callback") end
if not def.soakcheck then error("soaking abm missing soakcheck callback") end
def.soakvary = def.soakvary or 0.25
if not def.soakrand then
if def.soakvary then
def.soakrand = function(rate, ticks)
return rate * (1 + def.soakvary * nodecore.boxmuller()
/ math_sqrt(ticks)) * ticks
end
else
def.soakrand = function(rate, ticks) return rate * ticks end
end
end
def.action = function(pos, ...)
local now = minetest.get_gametime()
local meta = minetest.get_meta(pos)
local total = meta:get_float(def.qtyfield) or 0
local start = meta:get_float(def.timefield)
start = start and start ~= 0 and start or now
local rate = 0
local delta = 0
if start <= now then
rate = def.soakrate(pos, ...)
if rate == false then
minetest.log("soak abm reset at " .. minetest.pos_to_string(pos))
meta:set_string(def.qtyfield, "")
meta:set_string(def.timefield, "")
return
end
rate = rate or 0
local ticks = 1 + math_floor((now - start) / def.soakinterval)
delta = def.soakrand(rate, ticks)
total = total + delta
start = start + ticks * def.soakinterval
end
minetest.log("soak check at " .. minetest.pos_to_string(pos)
.. ": " .. minetest.serialize({
rate = rate,
delta = delta,
total = total
}))
local set = def.soakcheck({
rate = rate,
delta = delta,
total = total
}, pos, ...)
if set == false then
meta:set_string(def.qtyfield, "")
meta:set_string(def.timefield, "")
return
end
meta:set_float(def.qtyfield, set and type(set) == "number" and set or total)
meta:set_float(def.timefield, start)
end
return nodecore.register_limited_abm(def)
end

View File

@ -1,8 +1,8 @@
-- LUALOCALS < --------------------------------------------------------- -- LUALOCALS < ---------------------------------------------------------
local ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack local ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack
= ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack = ItemStack, ipairs, math, minetest, nodecore, pairs, type, unpack
local math_random local math_cos, math_log, math_pi, math_random, math_sin, math_sqrt
= math.random = math.cos, math.log, math.pi, math.random, math.sin, math.sqrt
-- LUALOCALS > --------------------------------------------------------- -- LUALOCALS > ---------------------------------------------------------
for k, v in pairs(minetest) do for k, v in pairs(minetest) do
@ -72,6 +72,21 @@ function nodecore.pickrand(tbl, weight)
end end
end end
do
local saved
function nodecore.boxmuller()
local old = saved
if old then
saved = nil
return old
end
local r = math_sqrt(-2 * math_log(math_random()))
local t = 2 * math_pi * math_random()
saved = r * math_sin(t)
return r * math_cos(t)
end
end
function nodecore.extend_item(name, func) function nodecore.extend_item(name, func)
local orig = minetest.registered_items[name] or {} local orig = minetest.registered_items[name] or {}
local copy = {} local copy = {}

View File

@ -1,8 +1,8 @@
-- LUALOCALS < --------------------------------------------------------- -- LUALOCALS < ---------------------------------------------------------
local ItemStack, math, minetest, nodecore, pairs, vector local ItemStack, math, minetest, nodecore, pairs, vector
= ItemStack, math, minetest, nodecore, pairs, vector = ItemStack, math, minetest, nodecore, pairs, vector
local math_pow local math_floor, math_pow
= math.pow = math.floor, math.pow
-- LUALOCALS > --------------------------------------------------------- -- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
@ -46,19 +46,19 @@ for _, v in pairs(nodecore.dirs()) do
indirs[#indirs + 1] = v indirs[#indirs + 1] = v
end end
end end
nodecore.register_limited_abm({ nodecore.register_soaking_abm({
label = "Lux Infusion", label = "Lux Infusion",
interval = 1, interval = 2,
chance = 2, chance = 1,
nodenames = {"nc_items:stack"}, nodenames = {"nc_items:stack"},
neighbors = {"group:lux_fluid"}, neighbors = {"group:lux_fluid"},
action = function(pos) soakrate = function(pos)
local stack = nodecore.stack_get(pos) local stack = nodecore.stack_get(pos)
local name = stack:get_name() local name = stack:get_name()
if (not charge[name]) and (not convert[name]) then return end if (not charge[name]) and (not convert[name]) then return false end
local above = vector.add(pos, {x = 0, y = 1, z = 0}) local above = vector.add(pos, {x = 0, y = 1, z = 0})
if not isfluid(above) then return end if not isfluid(above) then return false end
local qty = 1 local qty = 1
for _, v in pairs(indirs) do for _, v in pairs(indirs) do
if isfluid(vector.add(pos, v)) then qty = qty + 1 end if isfluid(vector.add(pos, v)) then qty = qty + 1 end
@ -70,15 +70,22 @@ nodecore.register_limited_abm({
if nn == modname .. ":flux_source" then return d end if nn == modname .. ":flux_source" then return d end
if nn ~= modname .. ":flux_flowing" then return false end if nn ~= modname .. ":flux_flowing" then return false end
end) end)
if not dist then return end if not dist then return false end
return qty * 20 / math_pow(2, dist / 2)
end,
soakcheck = function(data, pos)
local stack = nodecore.stack_get(pos)
local name = stack:get_name()
local dw = math_floor(data.total)
if charge[name] then if charge[name] then
stack:add_wear(-qty * 20 / math_pow(2, dist / 2)) stack:add_wear(-dw)
nodecore.stack_set(pos, stack) nodecore.stack_set(pos, stack)
elseif convert[name] and stack:get_wear() < 3277 then elseif convert[name] and stack:get_wear() < 3277 then
stack = ItemStack(convert[name]) stack = ItemStack(convert[name])
stack:set_wear(65535) stack:set_wear(65535 - dw)
nodecore.stack_set(pos, stack) nodecore.stack_set(pos, stack)
end end
return data.total - dw
end end
}) })

View File

@ -1,8 +1,8 @@
-- LUALOCALS < --------------------------------------------------------- -- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore local math, minetest, nodecore
= math, minetest, nodecore = math, minetest, nodecore
local math_random, math_sqrt local math_sqrt
= math.random, math.sqrt = math.sqrt
-- LUALOCALS > --------------------------------------------------------- -- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname() local modname = minetest.get_current_modname()
@ -68,13 +68,14 @@ minetest.register_node(epname, nodecore.underride({
}, },
minetest.registered_items[ldname] or {})) minetest.registered_items[ldname] or {}))
nodecore.register_limited_abm({ nodecore.register_soaking_abm({
label = "EggCorn Growing", label = "EggCorn Growing",
nodenames = {epname}, nodenames = {epname},
interval = 10, interval = 10,
chance = 1, chance = 1,
action = function(pos) qtyfield = "growth",
local meta = minetest.get_meta(pos) timefield = "start",
soakrate = function(pos)
local d = 0 local d = 0
local w = 1 local w = 1
nodecore.scan_flood(pos, 3, function(p) nodecore.scan_flood(pos, 3, function(p)
@ -93,11 +94,18 @@ nodecore.register_limited_abm({
return false return false
end end
end) end)
local rate = math_sqrt(d * w) return math_sqrt(d * w)
end,
soakcheck = function(data, pos)
if data.total >= 5000 then
local place = {x = pos.x - 2, y = pos.y, z = pos.z - 2}
return minetest.place_schematic(place, nodecore.tree_schematic,
"random", {}, false)
end
local zero = {x = 0, y = 0, z = 0} local zero = {x = 0, y = 0, z = 0}
nodecore.digparticles(minetest.registered_items[modname .. ":leaves"], nodecore.digparticles(minetest.registered_items[modname .. ":leaves"],
{ {
amount = rate, amount = data.rate,
time = 10, time = 10,
minpos = { minpos = {
x = pos.x - 0.3, x = pos.x - 0.3,
@ -116,21 +124,5 @@ nodecore.register_limited_abm({
minsize = 1, minsize = 1,
maxsize = 3, maxsize = 3,
}) })
local g = meta:get_float("growth") or 0
local now = minetest.get_gametime()
local t = meta:get_float("start")
t = t and t > 0 and t or now
while t <= now do
g = g + rate * math_random()
t = t + 10
end
if g >= 5000 then
meta:from_table({})
local place = {x = pos.x - 2, y = pos.y, z = pos.z - 2}
return minetest.place_schematic(place, nodecore.tree_schematic,
"random", {}, false)
end
meta:set_float("growth", g)
meta:set_float("start", t)
end end
}) })