mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 13:05:36 +01:00
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/// When the `AUTOWIKI` define is enabled, will generate an output file for tools/autowiki/autowiki.js to consume.
|
||||
/// Autowiki code intentionally still *exists* even without the define, to ensure developers notice
|
||||
/// when they break it immediately, rather than until CI or worse, call time.
|
||||
#if defined(AUTOWIKI) || defined(UNIT_TESTS)
|
||||
/proc/setup_autowiki()
|
||||
Master.sleep_offline_after_initializations = FALSE
|
||||
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, /proc/generate_autowiki))
|
||||
SSticker.start_immediately = TRUE
|
||||
CONFIG_SET(number/round_end_countdown, 0)
|
||||
|
||||
/proc/generate_autowiki()
|
||||
var/output = generate_autowiki_output()
|
||||
rustg_file_write(output, "data/autowiki_edits.txt")
|
||||
qdel(world)
|
||||
#endif
|
||||
|
||||
/// Returns a string of the autowiki output file
|
||||
/proc/generate_autowiki_output()
|
||||
var/total_output = ""
|
||||
|
||||
for (var/datum/autowiki/autowiki_type as anything in subtypesof(/datum/autowiki))
|
||||
var/datum/autowiki/autowiki = new autowiki_type
|
||||
var/output = autowiki.generate()
|
||||
|
||||
if (!istext(output))
|
||||
CRASH("[autowiki_type] does not generate a proper output!")
|
||||
|
||||
total_output += json_encode(list(
|
||||
"title" = autowiki.page,
|
||||
"text" = output,
|
||||
)) + "\n"
|
||||
|
||||
return total_output
|
||||
@@ -0,0 +1,54 @@
|
||||
/// A representation of an automated wiki page.
|
||||
/datum/autowiki
|
||||
/// The page on the wiki to be replaced.
|
||||
/// This should never be a user-facing page, like "Guide to circuits".
|
||||
/// It should always be a template that only Autowiki should touch.
|
||||
/// For example: "Template:Autowiki/CircuitInfo".
|
||||
var/page
|
||||
|
||||
/// Override and return the new text of the page.
|
||||
/// This proc can be impure, usually to call `upload_file`.
|
||||
/datum/autowiki/proc/generate()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
CRASH("[type] does not implement generate()!")
|
||||
|
||||
/// Generates an auto formatted template user.
|
||||
/// Your autowiki should ideally be a *lot* of these.
|
||||
/// It lets wiki editors edit it much easier later, without having to enter repo.
|
||||
/// Parameters will be passed in by name. That means your template should expect
|
||||
/// something that looks like `{{ Autowiki_Circuit|name=Combiner|description=This combines }}`
|
||||
/// Lists, which must be array-like (no keys), will be turned into a flat list with their key and a number,
|
||||
/// such that list("food" = list("fruit", "candy")) -> food1=fruit|food2=candy
|
||||
/datum/autowiki/proc/include_template(name, parameters)
|
||||
var/template_text = "{{[name]"
|
||||
|
||||
var/list/prepared_parameters = list()
|
||||
for (var/key in parameters)
|
||||
var/value = parameters[key]
|
||||
if (islist(value))
|
||||
for (var/index in 1 to length(value))
|
||||
prepared_parameters["[key][index]"] = "[value[index]]"
|
||||
else
|
||||
prepared_parameters[key] = value
|
||||
|
||||
for (var/parameter_name in prepared_parameters)
|
||||
template_text += "|[parameter_name]="
|
||||
template_text += "[prepared_parameters[parameter_name]]"
|
||||
|
||||
template_text += "}}"
|
||||
|
||||
return template_text
|
||||
|
||||
/// Takes an icon and uploads it to Autowiki-name.png.
|
||||
/// Do your best to make sure this is unique, so it doesn't clash with other autowiki icons.
|
||||
/datum/autowiki/proc/upload_icon(icon/icon, name)
|
||||
// Fuck you
|
||||
if (IsAdminAdvancedProcCall())
|
||||
return
|
||||
|
||||
fcopy(icon, "data/autowiki_files/[name].png")
|
||||
|
||||
/// Escape a parameter such that it can be correctly put inside a wiki output
|
||||
/datum/autowiki/proc/escape_value(parameter)
|
||||
// | is a special character in MediaWiki, and must be escaped by...using another template.
|
||||
return replacetextEx(parameter, "|", "{{!}}")
|
||||
@@ -0,0 +1,68 @@
|
||||
/datum/autowiki/techweb
|
||||
page = "Template:Autowiki/Content/Techweb"
|
||||
|
||||
/datum/autowiki/techweb/generate()
|
||||
var/output = ""
|
||||
|
||||
for (var/node_id in sort_list(SSresearch.techweb_nodes, /proc/sort_research_nodes))
|
||||
var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
|
||||
if (!node.show_on_wiki)
|
||||
continue
|
||||
|
||||
if (!valid_node(node))
|
||||
continue
|
||||
|
||||
output += "\n\n" + include_template("Autowiki/TechwebEntry", list(
|
||||
"name" = escape_value(node.display_name),
|
||||
"description" = escape_value(node.description),
|
||||
"prerequisites" = generate_prerequisites(node.prereq_ids),
|
||||
"designs" = generate_designs(node.design_ids),
|
||||
))
|
||||
|
||||
return output
|
||||
|
||||
/datum/autowiki/techweb/proc/valid_node(datum/techweb_node/node)
|
||||
return !node.experimental
|
||||
|
||||
/datum/autowiki/techweb/proc/generate_designs(list/design_ids)
|
||||
var/output = ""
|
||||
|
||||
for (var/design_id in design_ids)
|
||||
var/datum/design/design = SSresearch.techweb_designs[design_id]
|
||||
output += include_template("Autowiki/TechwebEntryDesign", list(
|
||||
"name" = escape_value(design.name),
|
||||
"description" = escape_value(design.get_description()),
|
||||
))
|
||||
|
||||
return output
|
||||
|
||||
/datum/autowiki/techweb/proc/generate_prerequisites(list/prereq_ids)
|
||||
var/output = ""
|
||||
|
||||
for (var/prereq_id in prereq_ids)
|
||||
var/datum/techweb_node/node = SSresearch.techweb_nodes[prereq_id]
|
||||
output += include_template("Autowiki/TechwebEntryPrerequisite", list(
|
||||
"name" = escape_value(node.display_name),
|
||||
))
|
||||
|
||||
return output
|
||||
|
||||
/datum/autowiki/techweb/experimental
|
||||
page = "Template:Autowiki/Content/Techweb/Experimental"
|
||||
|
||||
/datum/autowiki/techweb/experimental/valid_node(datum/techweb_node/node)
|
||||
return node.experimental
|
||||
|
||||
/proc/sort_research_nodes(node_id_a, node_id_b)
|
||||
var/datum/techweb_node/node_a = SSresearch.techweb_nodes[node_id_a]
|
||||
var/datum/techweb_node/node_b = SSresearch.techweb_nodes[node_id_b]
|
||||
|
||||
var/prereq_difference = node_a.prereq_ids.len - node_b.prereq_ids.len
|
||||
if (prereq_difference != 0)
|
||||
return prereq_difference
|
||||
|
||||
var/experiment_difference = node_a.required_experiments.len - node_b.required_experiments.len
|
||||
if (experiment_difference != 0)
|
||||
return experiment_difference
|
||||
|
||||
return sorttext(node_b.display_name, node_a.display_name)
|
||||
@@ -0,0 +1,56 @@
|
||||
/datum/autowiki/vending
|
||||
page = "Template:Autowiki/Content/VendingMachines"
|
||||
|
||||
/datum/autowiki/vending/generate()
|
||||
var/output = ""
|
||||
|
||||
var/list/cached_products = list()
|
||||
|
||||
// `powered()` checks if its in a null loc to say it's not powered.
|
||||
// So we put it inside, something
|
||||
var/obj/parent = new
|
||||
|
||||
for (var/vending_type in sort_list(subtypesof(/obj/machinery/vending), /proc/cmp_typepaths_asc))
|
||||
var/obj/machinery/vending/vending_machine = new vending_type(parent)
|
||||
vending_machine.use_power = FALSE
|
||||
vending_machine.update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
// Technically won't match if product amounts change, but this isn't likely
|
||||
var/products_cache_key = vending_machine.products.Join("-") + "&" + vending_machine.contraband.Join("-") + "&" + vending_machine.premium.Join("-")
|
||||
|
||||
// In the future, this should show all vending machines that have the same products
|
||||
if (products_cache_key in cached_products)
|
||||
qdel(vending_machine)
|
||||
continue
|
||||
|
||||
cached_products += products_cache_key
|
||||
|
||||
var/filename = SANITIZE_FILENAME(escape_value(format_text(vending_machine.name)))
|
||||
|
||||
output += include_template("Autowiki/VendingMachine", list(
|
||||
"icon" = escape_value(filename),
|
||||
"name" = escape_value(format_text(vending_machine.name)),
|
||||
"products" = format_product_list(vending_machine.products),
|
||||
"contraband" = format_product_list(vending_machine.contraband),
|
||||
"premium" = format_product_list(vending_machine.premium),
|
||||
))
|
||||
|
||||
// It would be cool to make this support gifs someday, but not now
|
||||
upload_icon(getFlatIcon(vending_machine, no_anim = TRUE), filename)
|
||||
|
||||
qdel(vending_machine)
|
||||
|
||||
qdel(parent)
|
||||
|
||||
return output
|
||||
|
||||
/datum/autowiki/vending/proc/format_product_list(list/product_list)
|
||||
var/output = ""
|
||||
|
||||
for (var/obj/product_path as anything in product_list)
|
||||
output += include_template("Autowiki/VendingMachineProduct", list(
|
||||
"name" = escape_value(capitalize(format_text(initial(product_path.name)))),
|
||||
"amount" = product_list[product_path],
|
||||
))
|
||||
|
||||
return output
|
||||
@@ -24,7 +24,7 @@ other types of metals and chemistry for reagents).
|
||||
/// Name of the created object
|
||||
var/name = "Name"
|
||||
/// Description of the created object
|
||||
var/desc = "Desc"
|
||||
var/desc = null
|
||||
/// The ID of the design. Used for quick reference. Alphanumeric, lower-case, no symbols
|
||||
var/id = DESIGN_ID_IGNORE
|
||||
/// Bitflags indicating what machines this design is compatable with. ([IMPRINTER]|[AWAY_IMPRINTER]|[PROTOLATHE]|[AWAY_LATHE]|[AUTOLATHE]|[MECHFAB]|[BIOGENERATOR]|[LIMBGROWER]|[SMELTER])
|
||||
@@ -86,6 +86,12 @@ other types of metals and chemistry for reagents).
|
||||
sheet.send(user)
|
||||
return sheet.icon_tag(id)
|
||||
|
||||
/// Returns the description of the design
|
||||
/datum/design/proc/get_description()
|
||||
var/obj/object_build_item_path = build_path
|
||||
|
||||
return isnull(desc) ? initial(object_build_item_path.desc) : desc
|
||||
|
||||
////////////////////////////////////////
|
||||
//Disks for transporting design datums//
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -36,11 +36,14 @@
|
||||
var/list/required_experiments = list()
|
||||
/// If completed, these experiments give a specific point amount discount to the node.area
|
||||
var/list/discount_experiments = list()
|
||||
/// Whether or not this node should show on the wiki
|
||||
var/show_on_wiki = TRUE
|
||||
|
||||
/datum/techweb_node/error_node
|
||||
id = "ERROR"
|
||||
display_name = "ERROR"
|
||||
description = "This usually means something in the database has corrupted. If it doesn't go away automatically, inform Central Command for their techs to fix it ASAP(tm)"
|
||||
show_on_wiki = FALSE
|
||||
|
||||
/datum/techweb_node/proc/Initialize()
|
||||
//Make lists associative for lookup
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "achievements.dm"
|
||||
#include "anchored_mobs.dm"
|
||||
#include "anonymous_themes.dm"
|
||||
#include "autowiki.dm"
|
||||
#include "bespoke_id.dm"
|
||||
#include "binary_insert.dm"
|
||||
#include "bloody_footprints.dm"
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/// Tests that all autowikis generate something without runtiming
|
||||
/datum/unit_test/autowiki
|
||||
|
||||
/datum/unit_test/autowiki/Run()
|
||||
TEST_ASSERT(istext(generate_autowiki_output()), "generate_autowiki_output() did not finish successfully!")
|
||||
|
||||
/// Test that `include_template` produces reasonable results
|
||||
/datum/unit_test/autowiki_include_template
|
||||
|
||||
/datum/unit_test/autowiki_include_template/Run()
|
||||
var/datum/autowiki/autowiki_api = new
|
||||
|
||||
TEST_ASSERT_EQUAL( \
|
||||
autowiki_api.include_template("Template"), \
|
||||
"{{Template}}", \
|
||||
"Basic template did not format correctly" \
|
||||
)
|
||||
|
||||
TEST_ASSERT_EQUAL( \
|
||||
autowiki_api.include_template("Template", list("name" = "Mothblocks")), \
|
||||
"{{Template|name=Mothblocks}}", \
|
||||
"Template with basic arguments did not format correctly" \
|
||||
)
|
||||
|
||||
TEST_ASSERT_EQUAL( \
|
||||
autowiki_api.include_template("Template", list("name" = autowiki_api.escape_value("P|peline"))), \
|
||||
"{{Template|name=P{{!}}peline}}", \
|
||||
"Template with escaped arguments did not format correctly" \
|
||||
)
|
||||
|
||||
TEST_ASSERT_EQUAL( \
|
||||
autowiki_api.include_template("Template", list("food" = list("fruit", "candy"))), \
|
||||
"{{Template|food1=fruit|food2=candy}}", \
|
||||
"Template with array arguments did not format correctly" \
|
||||
)
|
||||
@@ -197,7 +197,7 @@
|
||||
|
||||
var/list/part = list(
|
||||
"name" = D.name,
|
||||
"desc" = D.desc == "Desc" ? initial(built_item.desc) : D.desc,
|
||||
"desc" = D.get_description(),
|
||||
"printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10,
|
||||
"cost" = cost,
|
||||
"id" = D.id,
|
||||
|
||||
Reference in New Issue
Block a user