123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871 |
- local S = minetest.get_translator("advtrains_doc_integration")
- local fsescape = minetest.formspec_escape
- local worldpath = minetest.get_worldpath() .. DIR_DELIM
- advtrains_doc_integration = {}
- local function S2(a, b)
- return S(a, S(b))
- end
- local function Ss(x)
- if type(x) ~= "string" then
- return x
- end
- return minetest.get_translated_string("en", x)
- end
- local function txescape(str)
- return (string.gsub(tostring(str), "[:^\\]", [[\%1]]))
- end
- local function htescape(str)
- return (string.gsub(tostring(str), "([<>])", [[\%1]])) -- clip to one result
- end
- local function latex_escape(str)
- return (string.gsub(str, ".", {
- ["&"] = [[\&]],
- ["%"] = [[\%]],
- ["$"] = [[\$]],
- ["#"] = [[\#]],
- ["_"] = [[\_]],
- ["{"] = [[\{]],
- ["}"] = [[\}]],
- ["~"] = [[\textasciitilde]],
- ["^"] = [[\textasciicircum]],
- ["\\"] = [[\textbackslash]],
- }))
- end
- local function SL(x)
- return latex_escape(Ss(x))
- end
- local function spairs(tbl, sort)
- local keys = {}
- local kn = {}
- for k in pairs(tbl or {}) do
- table.insert(keys, k)
- end
- table.sort(keys, sort)
- for i = 2, #keys do
- kn[keys[i-1]] = keys[i]
- end
- return function(t, n)
- local k = kn[n]
- if n == nil then
- k = keys[1]
- end
- return k, t[k]
- end, tbl, nil
- 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 htmono(str)
- return string.format("<mono>%s</mono>", htescape(str))
- end
- local function htheader(str)
- return string.format("<b>%s</b>", htescape(str))
- end
- local function htaction(action, str, noesc)
- if not noesc then
- str = htescape(str)
- end
- return string.format("<action name=%s><style color=cyan>%s</style></action>", action, str)
- end
- local function describe_conns(conns)
- local connsdesc = {[0] = "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}
- if type(conns) == "table" then
- if conns.c then
- if conns.y and conns.y ~= 0 then
- return ("%s%+d%%"):format(describe_conns(conns.c), conns.y*100)
- else
- return describe_conns(conns.c)
- end
- else
- local cst = map(conns, describe_conns)
- local cstl = #cst
- if cstl == 2 then
- return ("%s - %s"):format(unpack(cst))
- elseif cstl == 3 then
- return ("[%s <-] %s -> %s"):format(cst[3], cst[1], cst[2])
- elseif cstl == 4 then
- return ("%s - %s; %s - %s"):format(unpack(cst))
- elseif cstl == 5 then
- return ("[%s,%s <-] %s -> %s"):format(cst[3], cst[4], cst[1], cst[2])
- end
- end
- else
- return connsdesc[tonumber(conns)]
- end
- end
- advtrains_doc_integration.describe_conns = describe_conns
- local function describe_length(x)
- local inch = x/0.0254
- local infdenom = 32
- local infnum = math.floor(inch*infdenom)%infdenom
- local ft = math.floor(inch/12)
- inch = math.floor(inch)%12
- local st = {}
- if ft > 0 then
- table.insert(st, ft .. "'")
- end
- local infstr = ""
- if infnum > 0 then
- while infnum%2 == 0 do
- infnum, infdenom = infnum/2, infdenom/2
- end
- infstr = string.format(" %d/%d", infnum, infdenom)
- end
- if inch > 0 then
- table.insert(st, string.format(' %s%s"', inch, infstr))
- elseif infnum > 0 then
- table.insert(st, infstr .. '"')
- end
- if not next(st) then
- st = '0"'
- end
- return string.format("%d mm (%s)", 1000*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 ht_coupler_name(n)
- local s = advtrains.coupler_types[n]
- if s then
- return htescape(s)
- else
- return htmono(n)
- end
- 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 advtrains_livery_tools_information
- do -- helper for Marnack's Advtrains livery tools
- local atliv = {}
- function atliv:get_textures_from_design(design)
- local tp = type(design)
- if tp == "string" then
- return self:get_textures_from_design(self.liveries[design])
- elseif tp ~= "table" then
- return
- end
- local template = self.templates[design.livery_template_name]
- if not template then
- return nil
- end
- local odef = template.overlays
- local textures = map(template.base_textures, function(str) return {str} end)
- for _, overlay in spairs(design.overlays) do
- local o = odef[overlay.id]
- local t = textures[(o or {}).slot_idx]
- if t and o then
- local alpha = math.min(255, math.max(0, o.alpha or 255))
- table.insert(t, string.format("(%s^[colorize:%s:%d)", txescape(o.texture), txescape(overlay.color), alpha))
- end
- end
- return map(textures, function(st) return table.concat(st, "^") end)
- end
- local mt = {
- __index = atliv,
- }
- advtrains_livery_tools_information = function(wname)
- if not advtrains_livery_database then
- return nil
- end
- local tnames = advtrains_livery_database.get_livery_template_names_for_wagon(wname)
- if next(tnames) == nil then
- return nil
- end
- local templates = {}
- for _, tname in pairs(tnames) do
- templates[tname] = advtrains_livery_database.get_wagon_livery_template(wname, tname)
- end
- local lnames = advtrains_livery_database.get_predefined_livery_names(wname)
- local lnames_t = {}
- local liveries = {}
- for _, lid in pairs(lnames) do
- local lname = lid.livery_name
- liveries[lname] = advtrains_livery_database.get_predefined_livery(wname, lname)
- table.insert(lnames_t, lname)
- end
- table.sort(tnames)
- table.sort(lnames_t)
- local obj = {
- templates = templates,
- template_names = tnames,
- liveries = liveries,
- livery_names = lnames_t,
- }
- return setmetatable(obj, mt)
- end
- 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 prototype_cache = {}
- advtrains_doc_integration.prototypes = prototype_cache -- ONLY FOR DEBUGGING
- local function adjust_wagon_prototype(itemname, prototype)
- local p = prototype_cache[itemname]
- if p then
- return p
- end
- p = table.copy(prototype)
- if p._doc_wagon_longdesc then
- p.longdesc = p._long_wagon_longdesc
- end
- if type(p.horn_sound) == "string" then
- p.horn_sound = {name = prototype.horn_sound}
- end
- if p.horn_sound and p.horn_sound.name == "" then
- p.horn_sound = nil
- 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
- p.seat_groups[v.group].count = (p.seat_groups[v.group].count or 0) + 1
- end
- end
- p.max_passengers = pax
- p.max_drivers = driver
- p.max_seats = pax+driver
- local bikelivdef = p.livery_definition
- local dlxlivdef = dlxtrains_livery_information(p)
- local atlivdef = advtrains_livery_tools_information(itemname)
- p.dlxtrains_livery = dlxlivdef
- p.advtrains_livery_tools = atlivdef
- local txbase = p.textures
- if dlxlivdef then
- txbase = {string.format("%s_%s.png", dlxlivdef.filename_prefix, dlxlivdef[0].code)}
- end
- p.livery_textures = {[0] = txbase}
- if bikelivdef then
- local slot = p.livery_texture_slot
- local components = bikelivdef.components
- local basefile = bikelivdef.base_texture_file
- for _, pdef in ipairs(bikelivdef.presets) do
- local tx = table.copy(txbase)
- local st = {basefile}
- for _, l in ipairs(pdef.livery_stack.layers) do
- table.insert(st, string.format("(%s^[colorize:%s)", txescape(components[l.component].texture_file), txescape(l.color)))
- end
- tx[slot] = table.concat(st, "^")
- table.insert(p.livery_textures, tx)
- end
- end
- if atlivdef then
- for _, dname in ipairs(atlivdef.livery_names) do
- table.insert(p.livery_textures, atlivdef:get_textures_from_design(dname) or txbase)
- end
- end
- prototype_cache[itemname] = p
- return p
- end
- local function doc_register_wagon(itemname)
- local prototype = adjust_wagon_prototype(itemname, advtrains.wagon_prototypes[itemname])
- prototype.name = itemname
- minetest.override_item(itemname, {_doc_items_create_entry = false})
- doc.add_entry("advtrains_wagons", itemname, {
- name = ItemStack(itemname):get_short_description(),
- data = prototype,
- })
- if doc.sub.identifier then
- doc.sub.identifier.register_object(itemname, "advtrains_wagons", itemname)
- end
- end
- local wlivprev = {}
- local function get_livery_preview_selection(pname, itemname)
- return (wlivprev[pname] or {})[itemname] or 0
- end
- local function get_livery_preview(itemname, id)
- local tx = (prototype_cache[itemname] or {}).livery_textures
- return tx[id] or tx[0]
- end
- local function render_livery_textures(pname, itemname)
- local str = table.concat(map(get_livery_preview(itemname, get_livery_preview_selection(pname, itemname)), fsescape), ",")
- return str
- end
- local function set_livery_preview_selection(pname, itemname, id)
- local t = wlivprev[pname]
- if not t then
- t = {}
- wlivprev[pname] = t
- end
- t[itemname] = id
- end
- local function doc_render_wagon_information(prototype, pname)
- local desctext = {}
- if prototype._doc_wagon_longdesc then
- table.insert(desctext, tostring(prototype._doc_wagon_longdesc))
- blankline(desctext)
- end
- table.insert(desctext, htheader(S("Basic Information")))
- table.insert(desctext, S("Itemstring: @1", htmono(prototype.name)))
- addlist(desctext, prototype.drops, S("Drops:"), S("Drops nothing"), false, function(_, v) return list_itemstring(v) end)
- addlist(desctext, prototype.drives_on, S("Drives on:"), nil, nil, htmono)
- addlist(desctext, prototype.coupler_types_front, S("Compatible front couplers:"), S2("Front coupler: @1", "Absent"), S2("Front coupler: @1", "Universal"), ht_coupler_name)
- addlist(desctext, prototype.coupler_types_back, S("Compatible rear couplers:"), S2("Rear coupler: @1", "Absent"), S2("Rear coupler: @1", "Universal"), ht_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"))
- local hornsound = prototype.horn_sound
- table.insert(desctext, S("Horn sound: @1", hornsound and htaction("playhorn", htmono(hornsound.name)) or S("Undefined")))
- blankline(desctext)
- table.insert(desctext, htheader(S("Wagon Capacity")))
- 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: %d", htmono(k), v)
- end)
- else
- table.insert(desctext, S2("Cargo inventory: @1", "Absent"))
- end
- if techage and prototype.techage_liquid_capacity then
- table.insert(desctext, S("Liquid Capacity (Techage): @1", string.format("%d", prototype.techage_liquid_capacity)))
- end
- blankline(desctext)
- table.insert(desctext, htheader(S("Wagon Appearance")))
- table.insert(desctext, S("Mesh: @1", prototype.mesh and htmono(prototype.mesh) or "None"))
- addlist(desctext, prototype.textures, S("Textures:"), S("No textures"), false, function(_, v) return htmono(v) end)
- local livids = 0
- local function livprev(desc)
- livids = livids+1
- return htaction(string.format("preview_%d", livids), desc)
- end
- local livrst = (get_livery_preview_selection(pname, prototype.name) ~= 0) and " " .. htaction("preview_0", S("[Reset Preview]")) or ""
- local bikeliv = S("Unsupported")
- local bikelivdesc = nil
- if prototype.set_livery then
- if 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 htescape(v.description) end)
- addlist(bikelivdesc, prototype.livery_definition.presets, S("Livery presets:") .. livrst, nil, nil, function(_, v) livids = livids+1 return livprev(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 = prototype.dlxtrains_livery
- table.insert(desctext, S2("DlxTrains livery system: @1", dlxlivdef and "Supported" or "Unsupported"))
- local atlivdef = prototype.advtrains_livery_tools
- table.insert(desctext, S2("Advtrains livery tools (Marnack): @1", atlivdef and "Supported" or "Unsupported"))
- if atlivdef then
- addlist(desctext, atlivdef.template_names, S("Livery templates:"), nil, nil, function(_, v) return htescape(v) end)
- addlist(desctext, atlivdef.livery_names, S("Livery presets:") .. livrst, nil, nil, function(_, v) return livprev(v) end)
- end
- blankline(desctext)
- table.insert(desctext, htheader(S("Implementation Details")))
- 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
- 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 = render_livery_textures(pname, prototype.name)
- local fstext = {
- string.format("hypertext[%f,%f;%f,%f;entry_body;%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(prototype.name)),
- string.format("model[%f,%f;%f,%f;%s;%s;%s;%f,%f]",
- x1-mside, y1-mside, mside, mside, "wagon_model", mesh, textures, -30, 135),
- }
- return table.concat(fstext, "\n")
- end
- if doc then
- minetest.register_on_mods_loaded(function()
- for k in pairs(advtrains.wagon_prototypes) do
- doc_register_wagon(k)
- end
- end)
- 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
- if ndef.at_conns then
- return S("This track has the following conns table by default: @1", describe_conns(ndef.at_conns) or "?")
- end
- return ""
- end)
- end
- doc.add_category("advtrains_wagons", {
- name = S("Wagons"),
- build_formspec = doc_render_wagon_information,
- })
- end
- local function latex_colordesc(cstr)
- local color = string.match(cstr,"^#(%x%x%x%x%x%x)$")
- cstr = SL(cstr)
- if color then
- color = SL(string.upper(color))
- return string.format([[\tikz \definecolor{c}{HTML}{%s} \draw[fill=c] (0,0) rectangle (1em,1em); \texttt{%s}]], color, cstr)
- else
- return string.format([[\texttt{%s}]], cstr)
- end
- end
- function advtrains_doc_integration.write_wagon_info_as_latex(itemname)
- local filename = string.format("%satdoc_wagon_%s.tex", worldpath, itemname:gsub(":", "_"))
- local prototype = adjust_wagon_prototype(advtrains.wagon_prototypes[itemname])
- local wname = ItemStack(itemname):get_short_description()
- local st = {string.format([[
- \documentclass{article}
- \usepackage[a4paper,margin=1in,bottom=1.5in]{geometry}
- \usepackage[T1]{fontenc}
- \usepackage{tikz}
- \usepackage{booktabs,multirow,tabularx}
- \renewcommand{\arraystretch}{1.5}
- \usepackage{hyperref}
- \hypersetup{pdftitle={Wagon Datasheet: %s}}
- \title{Wagon Datasheet}
- \author{%s}
- \setlength{\parindent}{0pt}
- \begin{document}
- \maketitle
- ]], SL(wname), SL(wname))}
- table.insert(st, [[\section{Basic Information}]])
- if prototype.longdesc then
- table.insert(st, SL(prototype.longdesc) .. "\n")
- end
- table.insert(st, [[\begin{tabularx}{\textwidth}{l X}]])
- table.insert(st, string.format([[Itemstring & \texttt{%s}\\]], SL(itemname)))
- if prototype.drives_on then
- local i0 = #st+1
- local count = 0
- for k in pairs(prototype.drives_on) do
- table.insert(st, string.format([[& \texttt{%s}\\]], SL(k)))
- count = count + 1
- end
- if count > 0 then
- st[i0] = string.format([[Drives on %s]], st[i0])
- end
- end
- if prototype.wagon_span then
- table.insert(st, string.format([[Wagon span & %d mm\\]], prototype.wagon_span*2000))
- end
- if prototype.max_speed then
- table.insert(st, string.format([[Maximum speed & %d m/s\\]], prototype.max_speed))
- end
- table.insert(st, string.format([[Motive power & %s\\]], prototype.is_locomotive and "Present" or "Absent"))
- if prototype.horn_sound then
- table.insert(st, string.format([[Horn sound & \texttt{%s}\\]], SL(prototype.horn_sound.name)))
- else
- table.insert(st, [[Horn sound & Undefined\\]])
- end
- if prototype.mesh then
- table.insert(st, string.format([[Mesh & \texttt{%s}\\]], SL(prototype.mesh)))
- end
- if prototype.textures then
- local i0 = #st+1
- local count = 0
- for _, i in pairs(prototype.textures) do
- table.insert(st, string.format([[& \texttt{%s}\\]], SL(i)))
- count = count + 1
- end
- if count > 0 then
- st[i0] = string.format([[Textures %s]], st[i0])
- end
- end
- do
- local i0 = #st+1
- local count = 0
- for _, i in ipairs(prototype.drops or {}) do
- local item = ItemStack(i)
- if not item:is_empty() then
- local desc = string.format([[\texttt{%s}]], SL(item:get_name()))
- if item:is_known() then
- desc = SL(item:get_short_description())
- end
- table.insert(st, string.format([[& %s: %d\\]], desc, item:get_count()))
- count = count + 1
- end
- end
- if count > 0 then
- st[i0] = [[Drops ]] .. st[i0]
- else
- table.insert(st, [[Drops & Nothing \\]])
- end
- end
- table.insert(st, [[\end{tabularx}]])
- table.insert(st, [[\section{Coupler Compatibility}]])
- do
- local fcouplers = prototype.coupler_types_front
- local rcouplers = prototype.coupler_types_back
- local ccouplers = {}
- local lcouplers = {}
- local couplerid = {}
- local flim, rlim
- for k in pairs(fcouplers or {}) do
- flim = true
- ccouplers[k] = true
- end
- for k in pairs(rcouplers or {}) do
- rlim = true
- ccouplers[k] = true
- end
- for k in pairs(ccouplers) do
- local desc = SL(get_coupler_name(k))
- table.insert(lcouplers, desc)
- couplerid[desc] = k
- end
- table.sort(lcouplers)
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c c}
- \toprule
- \multirow[t]{2}{*}{\bfseries Coupler Type} & \multicolumn{2}{c}{\bfseries Compatibility}\\
- \cmidrule(lr){2-3}
- & {\bfseries Front Coupler} & {\bfseries Rear Coupler}\\\midrule
- ]])
- if not (fcouplers and rcouplers) then
- local fd = fcouplers and "" or [[$\bullet$]]
- local rd = rcouplers and "" or [[$\bullet$]]
- table.insert(st, string.format([[\textit{Universal}&%s&%s\\]], fd, rd))
- end
- for i = 1, #lcouplers do
- local cdesc = lcouplers[i]
- local cid = couplerid[cdesc]
- local fd, rd = "", ""
- if flim then
- fd = fcouplers[cid] and [[$\bullet$]] or ""
- elseif not fcouplers then
- fd = [[$\Uparrow$]]
- end
- if rlim then
- rd = rcouplers[cid] and [[$\bullet$]] or ""
- elseif not rcouplers then
- rd = [[$\Uparrow$]]
- end
- table.insert(st, string.format([[%s&%s&%s\\]], cdesc, fd, rd))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- end
- local hasinv = prototype.has_inventory
- local hasseats = prototype.max_seats>0
- local taliquid = prototype.techage_liquid_capacity or 0
- if hasinv or hasseats or taliquid>0 then
- table.insert(st, [[\section{Wagon Capacity}]])
- if hasseats then
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c c}
- \toprule
- {\bfseries Seat Group} & {\bfseries Driver Stand} & {\bfseries Seat Count}\\\midrule
- ]])
- for _, d in pairs(prototype.seat_groups) do
- table.insert(st, string.format([[%s & %s & %d\\]], SL(d.name), d.driving_ctrl_access and [[$\bullet$]] or "", d.count))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- end
- if hasinv then
- if next(prototype.inventory_list_sizes or {}) ~= nil then
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Inventory Name} & {\bfseries Capacity}\\\midrule
- ]])
- for k, v in pairs(prototype.inventory_list_sizes) do
- table.insert(st, string.format([[\texttt{%s} & %d\\]], SL(k), v))
- end
- table.insert(st, [[\bottomrule]])
- table.insert(st, [[\end{tabularx}]])
- else
- table.insert(st, [[This wagon has an inventory of unknown size.]])
- end
- end
- if taliquid > 0 then
- table.insert(st, string.format([[
- \begin{tabularx}{\textwidth}{X l}
- {Liquid Capacity (Techage)} & %d
- \end{tabularx}
- ]], taliquid))
- end
- end
- if prototype.set_livery then
- if prototype.livery_definition then
- table.insert(st, [[\section{Multi-Component Liveries}]])
- local components = prototype.livery_definition.components
- local presets = prototype.livery_definition.presets
- table.insert(st, [[\subsection*{Components}]])
- table.insert(st, [[\begin{itemize}]])
- for _, c in ipairs(components) do
- table.insert(st, string.format([[\item %s]], SL(c.description)))
- end
- table.insert(st, [[\end{itemize}]])
- for _, p in ipairs(presets) do
- table.insert(st, string.format([[\subsection*{Preset: %s}]], SL(p.description)))
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Component} & {\bfseries Color} \\\midrule
- ]])
- for _, c in ipairs(p.livery_stack.layers) do
- local cdesc = SL(components[c.component].description)
- table.insert(st, string.format([[%s & %s\\]], cdesc, latex_colordesc(c.color)))
- end
- table.insert(st, [[
- \bottomrule
- \end{tabularx}
- ]])
- end
- else
- table.insert(st, [[\section{Livery System (Bike Painter)}]])
- table.insert(st, [[This wagon can be painted by the bike painter.]])
- end
- end
- local dlxlivdef = dlxtrains_livery_information(prototype)
- if dlxlivdef then
- table.insert(st, [[
- \section{DlxTrains Livery Sytem}
- This wagon can be customized with DlxTrains' livery system.
- ]])
- end
- local atlivdef = advtrains_livery_tools_information(itemname)
- if atlivdef then
- table.insert(st, [[\section{Advtrains Livery Tool (Marnack)}]])
- for _, tname in ipairs(atlivdef.template_names) do
- local tdef = atlivdef.templates[tname]
- table.insert(st, string.format([[\subsection*{Template: %s}]], SL(tname)))
- table.insert(st, SL(tdef.notes))
- table.insert(st, "")
- table.insert(st, "This template contains the following components:")
- table.insert(st, [[\begin{itemize}]])
- for _, overlay in ipairs(tdef.overlays) do
- table.insert(st, string.format([[\item %s]], SL(overlay.name)))
- end
- table.insert(st, [[\end{itemize}]])
- end
- for _, lname in ipairs(atlivdef.livery_names) do
- local ldef = atlivdef.liveries[lname]
- local tname = ldef.livery_template_name
- table.insert(st, string.format([[\subsection*{Preset: %s}]], SL(lname)))
- table.insert(st, string.format([[Template: %s]], SL(tname)))
- table.insert(st, "")
- table.insert(st, [[
- \begin{tabularx}{\textwidth}{X c}
- \toprule
- {\bfseries Component} & {\bfseries Color}\\\midrule]])
- for _, overlay in pairs(ldef.overlays) do
- local cname = atlivdef.templates[tname].overlays[overlay.id].name
- table.insert(st, string.format([[%s & %s\\]], SL(cname), latex_colordesc(overlay.color)))
- end
- table.insert(st, [[
- \bottomrule
- \end{tabularx}
- ]])
- end
- end
- table.insert(st, [[
- \end{document}
- ]])
- st = table.concat(st, "\n")
- minetest.safe_file_write(filename, st)
- end
- function advtrains_doc_integration.write_all_wagons_as_latex()
- for k in pairs(advtrains.wagon_prototypes) do
- advtrains_doc_integration.write_wagon_info_as_latex(k)
- end
- end
- minetest.register_chatcommand("atdoc_write", {
- params = "",
- description = S("Export Advtrains-related information"),
- privs = {server = true},
- func = function()
- advtrains_doc_integration.write_all_wagons_as_latex()
- end,
- })
- minetest.register_on_player_receive_fields(function(player, formname, fields)
- if formname ~= "doc:entry" then
- return
- end
- local pname = player:get_player_name()
- local cat, ent = doc.get_selection(pname)
- if cat ~= "advtrains_wagons" or ent == nil then
- return
- end
- local act = fields.entry_body
- if not act then
- return
- elseif act == "action:playhorn" then
- local sound = (advtrains.wagon_prototypes[ent] or {}).horn_sound
- if type(sound) == "table" then
- sound = table.copy(sound)
- else
- sound = {name = sound}
- end
- if type(sound.name) ~= "string" or sound.name == "" then
- return
- end
- minetest.sound_play(sound, {to_player = pname}, true)
- else
- local txid = string.match(act, [[^action:preview_(%d+)$]])
- txid = tonumber(txid)
- if txid then
- set_livery_preview_selection(pname, ent, txid)
- doc.show_entry(pname, cat, ent)
- end
- end
- end)
|