Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PORT TG][TOOLS][UNIT-TEST] Ports AutoWiki. coding cataloging the redux esquire #22518

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/autowiki.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Autowiki
on:
schedule:
- cron: "5 4 * * *"
workflow_dispatch:
permissions:
contents: read

jobs:
autowiki:
runs-on: ubuntu-20.04
steps:
- name: "Check for AUTOWIKI_USERNAME"
id: secrets_set
env:
ENABLER_SECRET: ${{ secrets.AUTOWIKI_USERNAME }}
run: |
unset SECRET_EXISTS
if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
echo "SECRETS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
- name: Checkout
if: steps.secrets_set.outputs.SECRETS_ENABLED
uses: actions/checkout@v4
- name: Restore BYOND cache
if: steps.secrets_set.outputs.SECRETS_ENABLED
uses: actions/cache@v4
with:
path: ~/BYOND
key: ${{ runner.os }}-byond-${{ hashFiles('dependencies.sh') }}
- name: Install rust-g
if: steps.secrets_set.outputs.SECRETS_ENABLED
run: |
bash tools/ci/install_rust_g.sh
- name: Compile and generate Autowiki files
if: steps.secrets_set.outputs.SECRETS_ENABLED
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
tools/build/build --ci autowiki
- name: Run Autowiki
if: steps.secrets_set.outputs.SECRETS_ENABLED
env:
USERNAME: ${{ secrets.AUTOWIKI_USERNAME }}
PASSWORD: ${{ secrets.AUTOWIKI_PASSWORD }}
run: |
cd tools/autowiki
npm install
cd ../..
node tools/autowiki/autowiki.js data/autowiki_edits.txt data/autowiki_files/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,6 @@ tools/MapAtmosFixer/MapAtmosFixer/bin/*

# Running OpenDream locally
tgstation.json

# Autowiki
/tools/autowiki/node_modules
4 changes: 4 additions & 0 deletions code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
// If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between
//#define UNIT_TESTS

/// If this is uncommented, Autowiki will generate edits and shut down the server.
/// Prefer the autowiki build target instead.
//#define AUTOWIKI

// If defined, we will NOT defer asset generation till later in the game, and will instead do it all at once, during initiialize
//#define DO_NOT_DEFER_ASSETS

Expand Down
1 change: 0 additions & 1 deletion code/controllers/configuration/config_entry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
var/modified = FALSE //set to TRUE if the default has been overridden by a config entry

var/deprecated_by //the /datum/config_entry type that supercedes this one

var/protection = NONE
var/abstract_type = /datum/config_entry //do not instantiate if type matches this

Expand Down
3 changes: 2 additions & 1 deletion code/controllers/subsystem/processing/station.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ PROCESSING_SUBSYSTEM_DEF(station)
/datum/controller/subsystem/processing/station/Initialize(timeofday)

//If doing unit tests we don't do none of that trait shit ya know?
#ifndef UNIT_TESTS
// Autowiki also wants consistent outputs, for example making sure the vending machine page always reports the normal products
#if !defined(UNIT_TESTS) && !defined(AUTOWIKI)
SetupTraits()
PrepareReport()
#endif
Expand Down
2 changes: 1 addition & 1 deletion code/game/mecha/mech_fabricator.dm
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@

var/list/part = list(
"name" = D.name,
"desc" = initial(built_item.desc),
"desc" = D.get_description(),
"printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10,
"cost" = cost,
"id" = D.id,
Expand Down
4 changes: 4 additions & 0 deletions code/game/world.dm
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ GLOBAL_VAR(restart_counter)
HandleTestRun()
#endif

#ifdef AUTOWIKI
setup_autowiki()
#endif

/world/proc/HandleTestRun()
//trigger things to run the whole process
Master.sleep_offline_after_initializations = FALSE
Expand Down
33 changes: 33 additions & 0 deletions code/modules/autowiki/autowiki.dm
Original file line number Diff line number Diff line change
@@ -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, GLOBAL_PROC_REF(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
54 changes: 54 additions & 0 deletions code/modules/autowiki/pages/base.dm
Original file line number Diff line number Diff line change
@@ -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, "|", "{{!}}")
59 changes: 59 additions & 0 deletions code/modules/autowiki/pages/techweb.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/datum/autowiki/techweb
page = "Template:Autowiki/Content/TechWeb"

/datum/autowiki/techweb/generate()
var/output = ""

// should be the the item icon we are trying to upload
var/datum/asset/spritesheet/research = get_asset_datum(/datum/asset/spritesheet/research_designs)
// filenames is the name of the icon file
var/filename = "researchables"

for (var/node_id in sort_list(SSresearch.techweb_nodes, GLOBAL_PROC_REF(sort_research_nodes)))
var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
if (!node.show_on_wiki)
continue

output += "\n\n" + include_template("Autowiki/TechwebEntry", list(
"icon" = escape_value(filename),
"name" = escape_value(node.display_name),
"description" = escape_value(node.description),
"prerequisites" = generate_prerequisites(node.prereq_ids),
"designs" = generate_designs(node.design_ids),
))

upload_icon(getFlatIcon(research, no_anim = TRUE), filename)
return output

/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

/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

return sorttext(node_b.display_name, node_a.display_name)
56 changes: 56 additions & 0 deletions code/modules/autowiki/pages/vending.dm
Original file line number Diff line number Diff line change
@@ -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), GLOBAL_PROC_REF(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
8 changes: 7 additions & 1 deletion code/modules/research/designs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ other types of metals and chemistry for reagents).

/datum/design //Datum for object designs, used in construction
var/name = "Name" //Name of the created object.
var/desc = "Desc" //Description of the created object.
var/desc = null //Description of the created object.
var/id = DESIGN_ID_IGNORE //ID of the created object for easy refernece. Alphanumeric, lower-case, no symbols
var/build_type = null //Flag as to what kind machine the design is built in. See defines.
var/list/materials = list() //List of materials. Format: "id" = amount.
Expand Down Expand Up @@ -67,6 +67,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//
////////////////////////////////////////
Expand Down
8 changes: 8 additions & 0 deletions code/modules/research/stock_parts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
var/pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/rped.ogg'
var/alt_sound = null


/obj/item/storage/part_replacer/pre_attack(obj/machinery/T, mob/living/user, params)
if(!istype(T) || (!T.component_parts && !T.works_with_rped_anyways))
return ..()
Expand Down Expand Up @@ -125,6 +126,8 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
icon = 'icons/obj/stock_parts.dmi'
w_class = WEIGHT_CLASS_SMALL
var/rating = 1
///The generic category type that the stock part belongs to. Generic objects that should not be instantiated should have the same type and abstract_type
var/abstract_type = /obj/item/stock_parts

/obj/item/stock_parts/Initialize(mapload)
. = ..()
Expand Down Expand Up @@ -290,6 +293,11 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi

// Subspace stock parts

/obj/item/stock_parts/subspace
name = "subspace stock part"
desc = "What?"
abstract_type = /obj/item/stock_parts/subspace

/obj/item/stock_parts/subspace/ansible
name = "subspace ansible"
icon_state = "subspace_ansible"
Expand Down
6 changes: 5 additions & 1 deletion code/modules/research/techweb/_techweb_node.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
var/ui_x = 805 // It's location - override this in techweb_layout.dm
var/ui_y = 805

/// 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
for(var/id in prereq_ids)
Expand Down
1 change: 1 addition & 0 deletions code/modules/unit_tests/_unit_tests.dm
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#include "timer_sanity.dm"
#include "trait_addition_and_removal.dm"
#include "unit_test.dm"
#include "autowiki.dm"

#undef TEST_ASSERT
#undef TEST_ASSERT_EQUAL
Expand Down
Loading
Loading