-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
autowiki port and gun autowiki (#4107)
MANY thanks to mothblocks of tg on tgstation/tgstation#64417 for this, it's very cool! this ports the autowiki (https://tgstation13.org/wiki/Guide_to_autowiki) and can be used to generate wiki page templates instead of monotonously updating damage values Forever! this is a weird one to changelog so: :cl: mothblocks, harry add: added the backend functionality for autowiki, alongside automating much of the work of maintaining guns on the wiki /:cl:
- Loading branch information
Showing
12 changed files
with
1,447 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
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@v3 | ||
- name: Restore BYOND cache | ||
if: steps.secrets_set.outputs.SECRETS_ENABLED | ||
uses: actions/cache@v3 | ||
with: | ||
path: ~/BYOND | ||
key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }} | ||
- name: Install rust-g | ||
if: steps.secrets_set.outputs.SECRETS_ENABLED | ||
run: | | ||
sudo dpkg --add-architecture i386 | ||
sudo apt update || true | ||
sudo apt install -o APT::Immediate-Configure=false libssl1.1:i386 | ||
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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/// 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 | ||
UNTIL(SSticker.current_state == GAME_STATE_PREGAME) | ||
|
||
//trigger things to run the whole process | ||
SSticker.request_start() | ||
CONFIG_SET(number/round_end_countdown, 0) | ||
SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(generate_autowiki))) | ||
|
||
/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, "|", "{{!}}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/datum/autowiki/guns | ||
page = "Template:Autowiki/Content/GunData" | ||
|
||
|
||
/datum/autowiki/guns/generate() | ||
var/output = "" | ||
|
||
var/list/gun_to_ammo = list() | ||
|
||
for(var/obj/item/ammo_magazine/typepath as anything in subtypesof(/obj/item/ammo_magazine) - subtypesof(/obj/item/ammo_magazine/internal)) | ||
LAZYADD(gun_to_ammo[initial(typepath.gun_type)], typepath) | ||
|
||
for(var/typepath in sort_list(subtypesof(/obj/item/weapon/gun), GLOBAL_PROC_REF(cmp_typepaths_asc))) | ||
var/obj/item/weapon/gun/generating_gun = new typepath() | ||
|
||
var/filename = SANITIZE_FILENAME(escape_value(format_text(generating_gun.name))) | ||
|
||
var/list/gun_data = generating_gun.ui_data() | ||
|
||
var/list/valid_mag_types = list() | ||
for(var/path in gun_to_ammo) | ||
if(!istype(generating_gun, path)) | ||
continue | ||
|
||
valid_mag_types += gun_to_ammo[path] | ||
|
||
var/ammo = "" | ||
var/damage_table = "" | ||
for(var/ammo_typepath in valid_mag_types) | ||
var/obj/item/ammo_magazine/generating_mag = new ammo_typepath() | ||
|
||
var/ammo_filename = SANITIZE_FILENAME(escape_value(format_text(generating_mag.name))) | ||
|
||
if(!fexists("data/autowiki_files/[ammo_filename].png")) | ||
upload_icon(getFlatIcon(generating_mag, no_anim = TRUE), ammo_filename) | ||
|
||
var/datum/ammo/current_ammo = GLOB.ammo_list[generating_mag.default_ammo] | ||
|
||
ammo += include_template("Autowiki/AmmoMagazine", list( | ||
"icon" = escape_value(ammo_filename), | ||
"name" = escape_value(generating_mag.name), | ||
"capacity" = escape_value(generating_mag.max_rounds), | ||
"damage" = escape_value(current_ammo.damage), | ||
"max_range" = escape_value(current_ammo.max_range), | ||
"fall_off" = escape_value(current_ammo.damage_falloff), | ||
"penetration" = escape_value(current_ammo.penetration), | ||
"punch" = escape_value(current_ammo.pen_armor_punch), | ||
)) | ||
|
||
generating_gun.current_mag = generating_mag | ||
|
||
var/list/gun_ammo_data = generating_gun.ui_data() | ||
var/list/armor_data = list() | ||
|
||
var/iterator = 1 | ||
for(var/header in gun_ammo_data["damage_armor_profile_headers"]) | ||
var/damage = gun_ammo_data["damage_armor_profile_marine"][iterator] | ||
armor_data["armor-[header]"] = damage | ||
iterator++ | ||
|
||
var/list/damage = list("ammo_name" = escape_value(generating_mag.name)) | ||
damage += armor_data | ||
|
||
damage_table += include_template("Autowiki/DamageVersusArmorRow", damage) | ||
|
||
qdel(generating_mag) | ||
|
||
gun_data["ammo_types"] = ammo | ||
gun_data["damage_table"] = damage_table | ||
|
||
var/list/attachments_by_slot = list() | ||
for(var/obj/item/attachable/attachment_typepath as anything in generating_gun.attachable_allowed) | ||
LAZYADD(attachments_by_slot[capitalize(initial(attachment_typepath.slot))], attachment_typepath) | ||
|
||
var/attachments = "" | ||
for(var/slot in attachments_by_slot) | ||
var/list/attachments_in_slot = "" | ||
|
||
for(var/attachment_typepath in attachments_by_slot[slot]) | ||
var/obj/item/attachable/generating_attachment = new attachment_typepath() | ||
|
||
var/attachment_filename = SANITIZE_FILENAME(escape_value(format_text(generating_attachment.name))) | ||
|
||
if(!fexists("data/autowiki_files/[attachment_filename].png")) | ||
upload_icon(getFlatIcon(generating_attachment, no_anim = TRUE), attachment_filename) | ||
|
||
attachments_in_slot += include_template("Autowiki/AvailableAttachment", list( | ||
"icon" = escape_value(attachment_filename), | ||
"name" = escape_value(generating_attachment.name), | ||
)) | ||
|
||
qdel(generating_attachment) | ||
|
||
attachments += include_template("Autowiki/AttachmentsBySlot", list( | ||
"slot" = escape_value(slot), | ||
"attachments" = attachments_in_slot, | ||
)) | ||
gun_data["attachments"] = attachments | ||
|
||
|
||
upload_icon(getFlatIcon(generating_gun, no_anim = TRUE), filename) | ||
gun_data["icon"] = filename | ||
|
||
output += include_template("Autowiki/Gun", gun_data) | ||
|
||
qdel(generating_gun) | ||
|
||
return output | ||
|
||
/datum/autowiki/guns/proc/wiki_sanitize_assoc(list/sanitizing_list) | ||
var/list/sanitized = list() | ||
|
||
for(var/key in sanitizing_list) | ||
var/value = sanitizing_list[key] | ||
|
||
sanitized[escape_value(key)] = escape_value(value) | ||
|
||
return sanitized |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" \ | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.