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

autowiki port and gun autowiki #4107

Merged
merged 4 commits into from
Aug 12, 2023
Merged
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
52 changes: 52 additions & 0 deletions .github/workflows/autowiki.yml
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/
6 changes: 5 additions & 1 deletion code/game/world.dm
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt")

var/testing_locally = (world.params && world.params["local_test"])
var/running_tests = (world.params && world.params["run_tests"])
#ifdef UNIT_TESTS
#if defined(AUTOWIKI) || defined(UNIT_TESTS)
running_tests = TRUE
#endif
// Only do offline sleeping when the server isn't running unit tests or hosting a local dev test
Expand All @@ -84,6 +84,10 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt")
HandleTestRun()
#endif

#ifdef AUTOWIKI
setup_autowiki()
#endif

update_status()

//Scramble the coords obsfucator
Expand Down
36 changes: 36 additions & 0 deletions code/modules/autowiki/autowiki.dm
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
54 changes: 54 additions & 0 deletions code/modules/autowiki/pages/_page.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, "|", "{{!}}")
118 changes: 118 additions & 0 deletions code/modules/autowiki/pages/guns.dm
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
2 changes: 1 addition & 1 deletion code/modules/projectiles/gun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ As sniper rifles have both and weapon mods can change them as well. ..() deals w
if(in_chamber && in_chamber.ammo)
in_ammo = in_chamber.ammo
else if(current_mag && current_mag.current_rounds > 0)
if(istype(current_mag) && current_mag.chamber_contents[current_mag.chamber_position] != "empty")
if(istype(current_mag) && length(current_mag.chamber_contents) && current_mag.chamber_contents[current_mag.chamber_position] != "empty")
in_ammo = GLOB.ammo_list[current_mag.chamber_contents[current_mag.chamber_position]]
if(!istype(in_ammo))
in_ammo = GLOB.ammo_list[current_mag.default_ammo]
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 @@ -74,6 +74,7 @@
/// A trait source when adding traits through unit tests
#define TRAIT_SOURCE_UNIT_TESTS "unit_tests"

#include "autowiki.dm"
#include "create_and_destroy.dm"
#include "focus_only_tests.dm"
#include "missing_icons.dm"
Expand Down
35 changes: 35 additions & 0 deletions code/modules/unit_tests/autowiki.dm
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" \
)
3 changes: 3 additions & 0 deletions colonialmarines.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,9 @@
#include "code\modules\asset_cache\assets\vending.dm"
#include "code\modules\asset_cache\transports\asset_transport.dm"
#include "code\modules\asset_cache\transports\webroot_transport.dm"
#include "code\modules\autowiki\autowiki.dm"
#include "code\modules\autowiki\pages\_page.dm"
#include "code\modules\autowiki\pages\guns.dm"
#include "code\modules\buildmode\bm-mode.dm"
#include "code\modules\buildmode\buildmode.dm"
#include "code\modules\buildmode\buttons.dm"
Expand Down
Loading