Lots of content
This commit is contained in:
Executable
+113
@@ -0,0 +1,113 @@
|
||||
-- Original bounded seasonal appearance. No timers, world lists or clock replay.
|
||||
return function(hearth, api)
|
||||
local S = {COLUMN_HEIGHT = 12, MAX_COLUMN_SWAPS = 12}
|
||||
local variants, canonical, availability = {}, {}, {}
|
||||
local function variant(kind, season, texture, mesh)
|
||||
variants[kind] = variants[kind] or {}
|
||||
local short = kind .. "_" .. season:lower()
|
||||
variants[kind][season] = {name="hearth:"..short, texture=texture, mesh=mesh}
|
||||
canonical["hearth:"..short] = kind
|
||||
end
|
||||
for _, kind in ipairs({"tree_seedling", "young_tree", "mature_tree", "leaves"}) do
|
||||
for _, season in ipairs({"Spring", "Autumn", "Winter"}) do
|
||||
local suffix = season:lower()
|
||||
local mesh = kind ~= "leaves" and ("hearth_"..kind
|
||||
.. (season == "Winter" and kind ~= "tree_seedling" and "_winter" or "") .. ".obj") or nil
|
||||
variant(kind, season, "hearth_" .. (kind == "leaves" and "leaves" or "tree_atlas") .. "_" .. suffix .. ".png", mesh)
|
||||
end
|
||||
end
|
||||
for _, kind in ipairs({"meadow_grass", "fern", "wildflowers"}) do
|
||||
variant(kind, "Winter", "hearth_"..kind.."_dormant.png")
|
||||
if kind == "wildflowers" then variant(kind, "Autumn", "hearth_wildflowers_dormant.png") end
|
||||
end
|
||||
-- Patch nodes and picked food items have different names: never overwrite a
|
||||
-- registered node with a craftitem, and never let picked food reset a patch.
|
||||
variant("spring_greens_patch", "Spring", "hearth_spring_greens.png")
|
||||
variant("autumn_mushrooms_patch", "Autumn", "hearth_autumn_mushrooms.png")
|
||||
for kind in pairs(variants) do canonical["hearth:"..kind] = kind end
|
||||
-- Extensions are installed by botany/diversity before node registration. Missing
|
||||
-- bases in minimal mocks/optional content are skipped, never asserted.
|
||||
function S.add_variants(kind, definitions, active_seasons)
|
||||
assert(type(kind)=="string" and kind:match("^[a-z_]+$"), "invalid flora kind")
|
||||
canonical["hearth:"..kind] = kind
|
||||
for season, def in pairs(definitions or {}) do
|
||||
assert(({Spring=true,Summer=true,Autumn=true,Winter=true})[season], "invalid season")
|
||||
variant(kind, season, assert(def.texture), def.mesh)
|
||||
end
|
||||
availability[kind] = active_seasons
|
||||
end
|
||||
function S.kind(n)
|
||||
local name = type(n) == "table" and n.name or n
|
||||
return type(name) == "string" and (canonical[name] or name:match("^hearth:(.+)$")) or nil
|
||||
end
|
||||
function S.season(now)
|
||||
local climate = hearth.climate_at and hearth.climate_at(now or os.time())
|
||||
return climate and climate.season or "Summer"
|
||||
end
|
||||
function S.name_for(kind, now)
|
||||
kind = S.kind(kind) or kind
|
||||
local v = variants[kind] and variants[kind][S.season(now)]
|
||||
return v and v.name or "hearth:"..kind
|
||||
end
|
||||
function S.available(kind, now)
|
||||
kind = S.kind(kind) or kind
|
||||
local season = S.season(now)
|
||||
if availability[kind] then return availability[kind][season] == true end
|
||||
if kind == "spring_greens_patch" then return season == "Spring" end
|
||||
if kind == "autumn_mushrooms_patch" then return season == "Autumn" end
|
||||
if kind == "wildflowers" then return season == "Spring" or season == "Summer" end
|
||||
return not variants[kind] or season ~= "Winter"
|
||||
end
|
||||
function S.names()
|
||||
local names = {}
|
||||
for name in pairs(canonical) do names[#names+1] = name end
|
||||
return names
|
||||
end
|
||||
function S.reconcile(p, n, now)
|
||||
-- Appearance alone can change a claimed/hand-placed plant, but never its
|
||||
-- provenance, age, harvest deadline, dig permission, drops or inventory.
|
||||
n = n or api.get_node_or_nil(p)
|
||||
if not n or not canonical[n.name] then return false end
|
||||
local protection = hearth.external_protected or api.is_protected
|
||||
if protection and protection(p, "") then return false end
|
||||
local target = S.name_for(canonical[n.name], now)
|
||||
if n.name == target then return false end
|
||||
-- Recheck loaded identity before swapping; no set_node metadata erasure.
|
||||
local current = api.get_node_or_nil(p)
|
||||
if not current or current.name ~= n.name then return false end
|
||||
api.swap_node(p, {name=target, param1=current.param1, param2=current.param2})
|
||||
return true
|
||||
end
|
||||
function S.register()
|
||||
local names = {}
|
||||
for kind, seasons in pairs(variants) do
|
||||
local base_name = "hearth:"..kind
|
||||
local base = (api.registered_nodes or {})[base_name]
|
||||
if base then
|
||||
names[#names+1] = base_name
|
||||
for _, v in pairs(seasons) do
|
||||
local def = {}
|
||||
for k, value in pairs(base) do def[k] = value end
|
||||
def.groups = {}
|
||||
for k, value in pairs(base.groups or {}) do def.groups[k] = value end
|
||||
def.groups.not_in_creative_inventory = 1
|
||||
-- A stage may now be a bark cube rather than the old sculpted
|
||||
-- tree. Recolour foliage/sprites only; never flatten end-grain
|
||||
-- and bark faces or reintroduce an obsolete mesh on a cube.
|
||||
if base.drawtype ~= "normal" then
|
||||
def.tiles = {v.texture}
|
||||
if base.inventory_image then def.inventory_image = v.texture end
|
||||
if base.wield_image then def.wield_image = v.texture end
|
||||
end
|
||||
if base.drawtype == "mesh" and v.mesh then def.mesh = v.mesh end
|
||||
def.drop = base.drop == nil and base_name or base.drop
|
||||
if not api.registered_nodes[v.name] then api.register_node(v.name, def) end
|
||||
names[#names+1] = v.name
|
||||
end
|
||||
end
|
||||
end
|
||||
api.register_lbm({name="hearth:seasonal_flora", label="Reconcile seasonal flora appearance",
|
||||
nodenames=names, run_at_every_load=true, action=function(p) S.reconcile(p) end})
|
||||
end
|
||||
return S
|
||||
end
|
||||
Reference in New Issue
Block a user