288 lines
8.9 KiB
Lua

local S = minetest.get_translator("advtrains_doc_integration")
local fsescape = minetest.formspec_escape
local function S2(a, b)
return S(a, S(b))
end
local function map(tbl, func)
local t = {}
for k, v in pairs(tbl or {}) do
t[k] = func(v)
end
return t
end
local function quotestring(str)
return string.format("%q", str)
end
if doc then
if doc.sub.items then
local register_factoid = doc.sub.items.register_factoid
local function group_factoid(cat, gr, f)
register_factoid(cat, "groups", function(_, def)
return f(def.groups[gr] or 0) or ""
end)
end
for cat, cinfo in pairs{
nodes = {
not_blocking_trains = S("This block does not block trains."),
save_in_at_nodedb = S("This block is saved in the Advtrains node database."),
},
} do
for group, ginfo in pairs(cinfo) do
local tp = type(ginfo)
if tp == "string" then
group_factoid(cat, group, function(x)
if x > 0 then
return ginfo
end
end)
elseif tp == "function" then
group_factoid(cat, group, ginfo)
end
end
end
register_factoid("nodes", "groups", function(_, ndef)
if ndef.advtrains then
if ndef.advtrains.set_aspect then
return S("This is a signal with a variable aspect.")
elseif ndef.advtrains.get_aspect then
return S("This is a signal with a static aspect.")
end
end
return ""
end)
end
doc.add_category("advtrains_wagons", {
name = S("Wagons"),
build_formspec = doc.entry_builders.formspec,
})
end
local function describe_length(x)
local inch = math.floor(x/0.0254)
local ft = math.floor(inch/12)
inch = inch%12
local st = {}
if ft > 0 then
table.insert(st, ft .. "'")
end
if inch > 0 then
table.insert(st, inch .. '"')
end
if not next(st) then
st = '0"'
end
return string.format("%.2f m (%s)", x, table.concat(st))
end
local function describe_speed(x)
local kmph = x*3.6
local mph = kmph/1.609344
return string.format("%.1f m/s (%.1f km/h; %.1f mph)", x, kmph, mph)
end
local function addlist(lst, tbl, title, fallback1, fallback2, mapf)
if not tbl then
if fallback2 then
table.insert(lst, fallback2)
elseif fallback2 == false and fallback1 then
table.insert(lst, fallback1)
end
elseif next(tbl) ~= nil then
table.insert(lst, title)
for k, v in pairs(tbl) do
if mapf then
k = mapf(k, v)
end
table.insert(lst, "* " .. k)
end
elseif fallback1 then
table.insert(lst, fallback1)
end
end
local function get_coupler_name(n)
return advtrains.coupler_types[n] or n
end
local function dlxtrains_livery_information(prototype)
if not dlxtrains then
return nil
end
local old_update_livery = dlxtrains.update_livery
dlxtrains.update_livery = function(_, _, x)
return coroutine.yield(x)
end
local env = {
coroutine = coroutine,
dlxtrains = table.copy(dlxtrains),
}
local function main(G, f)
setfenv(0, G)
f()
return error()
end
local t = {coroutine.resume(coroutine.create(main), env, prototype.custom_may_destroy or function() end)}
dlxtrains.update_livery = old_update_livery
if not t[1] then
return nil
end
return unpack(t, 2)
end
local function list_itemstring(x)
local item = ItemStack(x)
if item:is_empty() then
return S("Emptyness")
end
return string.format("%s: %d", item:get_short_description(), item:get_count())
end
local function blankline(st)
return table.insert(st, "")
end
local function adjust_wagon_prototype(prototype)
local p = table.copy(prototype)
if p._doc_wagon_longdesc then
p.desc = p._long_wagon_longdesc
end
if type(p.horn_sound) == "string" then
p.horn_sound = {name = prototype.horn_sound}
end
local pax, driver = 0, 0
if p.seats and p.seat_groups then
for _, v in pairs(p.seats) do
if p.seat_groups[v.group].driving_ctrl_access then
driver = driver + 1
else
pax = pax + 1
end
end
end
p.max_passengers = pax
p.max_drivers = driver
return p
end
local function doc_register_wagon(itemname)
local prototype = adjust_wagon_prototype(advtrains.wagon_prototypes[itemname])
local desctext = {}
if prototype._doc_wagon_longdesc then
table.insert(desctext, tostring(prototype._doc_wagon_longdesc))
blankline(desctext)
end
table.insert(desctext, S("Itemstring: @1", quotestring(itemname)))
addlist(desctext, prototype.drops, S("Drops:"), S("Drops nothing"), false, function(_, v) return list_itemstring(v) end)
blankline(desctext)
addlist(desctext, prototype.drives_on, S("Drives on:"))
addlist(desctext, prototype.coupler_types_front, S("Compatible front couplers:"), S2("Front coupler: @1", "Absent"), S2("Front coupler: @1", "Universal"), get_coupler_name)
addlist(desctext, prototype.coupler_types_back, S("Compatible rear couplers:"), S2("Rear coupler: @1", "Absent"), S2("Rear coupler: @1", "Universal"), get_coupler_name)
table.insert(desctext, S("Wagon span: @1", prototype.wagon_span and describe_length(2*prototype.wagon_span) or S("Undefined")))
table.insert(desctext, S("Maximum speed: @1", prototype.max_speed and describe_speed(prototype.max_speed) or S("Undefined")))
table.insert(desctext, S2("Motive power: @1", prototype.is_locomotive and "Present" or "Absent"))
if prototype.horn_seound then
local hornsound = prototype.horn_sound.name
table.insert(desctext, S("Horn sound: @1", hornsound and hornsound ~= "" and quotestring(hornsound) or S("Undefined")))
end
blankline(desctext)
table.insert(desctext, S("Passenger seats: @1", prototype.max_passengers))
table.insert(desctext, S("Driver seats: @1", prototype.max_drivers))
if prototype.has_inventory then
addlist(desctext, prototype.inventory_list_sizes, S("Cargo inventory size:"), S2("Cargo inventory: @1", "Present"), false, function(k, v)
return string.format("%s: %s", k, v)
end)
else
table.insert(desctext, S2("Cargo inventory: @1", "Absent"))
end
blankline(desctext)
table.insert(desctext, S("Mesh: @1", quotestring(prototype.mesh)))
addlist(desctext, prototype.textures, S("Textures:"), S("No textures"), false, function(_, v) return quotestring(v) end)
local bikeliv = S("Unsupported")
local bikelivdesc = nil
if prototype.set_livery then
if multi_component_liveries and prototype.set_livery == multi_component_liveries.set_livery and prototype.livery_definition then
bikeliv = S("Supported by the multi_component_liveries mod")
bikelivdesc = {}
addlist(bikelivdesc, prototype.livery_definition.components, S("Livery components:"), nil, nil, function(_, v) return tostring(v.description) end)
addlist(bikelivdesc, prototype.livery_definition.presets, S("Livery presets:"), nil, nil, function(_, v) return tostring(v.description) end)
bikelivdesc = table.concat(bikelivdesc, "\n")
else
bikeliv = S("Supported")
end
end
table.insert(desctext, S("Livery system with bike painter: @1", bikeliv))
table.insert(desctext, bikelivdesc)
local dlxlivdef = dlxtrains_livery_information(prototype)
table.insert(desctext, S2("DlxTrains livery system: @1", dlxlivdef and "Supported" or "Unsupported"))
local attachment_offset_support = S("Unsupported")
if advtrains_attachment_offset_patch then
local t = advtrains_attachment_offset_patch
if prototype.get_on == t.get_on_override and prototype.get_off == t.get_off_override then
attachment_offset_support = S("Supported")
end
end
blankline(desctext)
table.insert(desctext, S("Proper player attachment positioning: @1", attachment_offset_support))
for k, v in pairs {
custom_on_activate = "Custom instantiation callback",
custom_on_step = "Custom step function",
custom_on_velocity_change = "Custom velocity change callback",
} do
table.insert(desctext, S2(v .. ": @1", prototype[k] and "Defined" or "Undefined"))
end
local x0, y0 = doc.FORMSPEC.ENTRY_START_X+0.25, doc.FORMSPEC.ENTRY_START_Y
local x1, y1 = doc.FORMSPEC.ENTRY_END_X+0.75, doc.FORMSPEC.ENTRY_END_Y+0.625
local width, height = x1-x0, y1-y0
local mside = height/2
local mesh = fsescape(prototype.mesh or "")
local textures = table.concat(map(prototype.textures, fsescape), ",")
if dlxlivdef then
textures = fsescape(string.format("%s_%s.png", dlxlivdef.filename_prefix, dlxlivdef[0].code))
end
local fstext = {
string.format("textarea[%f,%f;%f,%f;;;%s]", x0, y0, width-mside, height+0.875, fsescape(table.concat(desctext, "\n"))),
string.format("item_image[%f,%f;%f,%f;%s]", x1-mside, y0+0.0625, mside, mside, fsescape(itemname)),
string.format("model[%f,%f;%f,%f;%s;%s;%s;%f,%f]",
x1-mside, y1-mside, mside, mside, "wagon_model", mesh, textures, -30, 135),
}
minetest.override_item(itemname, {_doc_items_create_entry = false})
doc.add_entry("advtrains_wagons", itemname, {
name = ItemStack(itemname):get_short_description(),
data = table.concat(fstext),
})
end
if doc then
for k in pairs(advtrains.wagon_prototypes) do
doc_register_wagon(k)
end
end
local _register_wagon = advtrains.register_wagon
function advtrains.register_wagon(...)
_register_wagon(...)
local name = ...
if not string.find(name, ":") then
name = "advtrains:" .. name
end
if doc then
doc_register_wagon(name)
end
end
advtrains_doc_integration = {}