From 77e57e72096ee63676f33610daf3c170dbc99053 Mon Sep 17 00:00:00 2001 From: Selis Date: Mon, 17 Jul 2023 18:54:57 +0200 Subject: [PATCH] feat: Better changelogs --- .gitattributes | 3 - .github/workflows/autochangelog.yml | 1 - code/game/world.dm | 5 +- code/modules/asset_cache/asset_list_items.dm | 2 + code/modules/mob/mob.dm | 11 +- html/changelogs/archive/__example__.yml | 3 + html/changelogs/example.yml | 97 +++-- modular_chomp/code/_global_vars/tgui.dm | 1 + .../code/datums/changelog/changelog.dm | 32 ++ .../code/modules/asset_cache/asset_list.dm | 17 + tgui/packages/tgui_ch/interfaces/Changelog.js | 315 +++++++++++++++ tgui/packages/tgui_ch/package.json | 6 +- tgui/public/tgui.bundle.js | 2 +- tgui/yarn.lock | 25 +- tools/GenerateChangelog/makeChangelog.bat | 8 +- tools/GenerateChangelog/ss13_autochangelog.py | 12 +- tools/GenerateChangelog/ss13_genchangelog.py | 359 ++++++++---------- tools/ci/validate_files.sh | 4 +- vorestation.dme | 5 +- 19 files changed, 641 insertions(+), 267 deletions(-) create mode 100644 html/changelogs/archive/__example__.yml create mode 100644 modular_chomp/code/_global_vars/tgui.dm create mode 100644 modular_chomp/code/datums/changelog/changelog.dm create mode 100644 modular_chomp/code/modules/asset_cache/asset_list.dm create mode 100644 tgui/packages/tgui_ch/interfaces/Changelog.js diff --git a/.gitattributes b/.gitattributes index c5587f6042..71425bd4c7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,6 +11,3 @@ # dmi icon merger hook # needs additional setup, see tools/dmitool/merging.txt *.dmi merge=merge-dmi - -# force changelog merging to use union -html/changelog.html merge=union diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml index c9c628fa29..0fe6d6a851 100644 --- a/.github/workflows/autochangelog.yml +++ b/.github/workflows/autochangelog.yml @@ -34,7 +34,6 @@ jobs: "${{ github.event.pull_request.user.login }}" \ "${{ github.event.pull_request.body }}" python tools/GenerateChangelog/ss13_genchangelog.py \ - html/changelog.html \ html/changelogs - uses: stefanzweifel/git-auto-commit-action@v4 with: diff --git a/code/game/world.dm b/code/game/world.dm index 5d2f9686f2..c7e557364e 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -27,7 +27,10 @@ debug_log = start_log("[log_path]-debug.log") //VOREStation Edit End - changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently + // CHOMPedit Start - Better Changelogs + var/latest_changelog = file("/html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml") + changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently + // CHOMPedit End if(byond_version < RECOMMENDED_VERSION) to_world_log("Your server's byond version does not meet the recommended requirements for this server. Please update BYOND") diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 24ba5c9d00..b6f6e4ed44 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -124,6 +124,7 @@ "no_image32.png" = 'html/images/no_image32.png', ) +/* CHOMPedit Start - Better Changelogs /datum/asset/simple/changelog assets = list( "88x31.png" = 'html/88x31.png', @@ -145,6 +146,7 @@ "changelog.js" = 'html/changelog.js', "changelog.html" = 'html/changelog.html' ) +*/ // CHOMPedit end // /datum/asset/group/goonchat // children = list( diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 744f8b952b..b8bf1bb366 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -433,11 +433,20 @@ /client/verb/changes() set name = "Changelog" set category = "OOC" - src << browse('html/changelog.html', "window=changes;size=675x650") + // CHOMPedit Start - Better Changelog + //src << browse('html/changelog.html', "window=changes;size=675x650") + //return + + if(!GLOB.changelog_tgui) + GLOB.changelog_tgui = new /datum/changelog() + GLOB.changelog_tgui.tgui_interact(usr) + + /* if(prefs.lastchangelog != changelog_hash) prefs.lastchangelog = changelog_hash SScharacter_setup.queue_preferences_save(prefs) winset(src, "rpane.changelog", "background-color=none;font-style=;") + */ // CHOMPedit End /mob/verb/observe() set name = "Observe" diff --git a/html/changelogs/archive/__example__.yml b/html/changelogs/archive/__example__.yml new file mode 100644 index 0000000000..077df7b149 --- /dev/null +++ b/html/changelogs/archive/__example__.yml @@ -0,0 +1,3 @@ +1970-01-01: + ExampleUser: + - tweak: Tweaked something in my example PR! diff --git a/html/changelogs/example.yml b/html/changelogs/example.yml index c34ccdd0a0..856e0719c6 100644 --- a/html/changelogs/example.yml +++ b/html/changelogs/example.yml @@ -1,37 +1,60 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: N3X15 - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - rscadd: "Added a changelog editing system that should cause fewer conflicts and more accurate timestamps." - - rscdel: "Killed innocent kittens." +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# maptweak +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: " + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a changelog editing system that should cause fewer conflicts and more accurate timestamps." + - rscdel: "Killed innocent kittens." diff --git a/modular_chomp/code/_global_vars/tgui.dm b/modular_chomp/code/_global_vars/tgui.dm new file mode 100644 index 0000000000..1a2c46c10d --- /dev/null +++ b/modular_chomp/code/_global_vars/tgui.dm @@ -0,0 +1 @@ +GLOBAL_DATUM(changelog_tgui, /datum/changelog) diff --git a/modular_chomp/code/datums/changelog/changelog.dm b/modular_chomp/code/datums/changelog/changelog.dm new file mode 100644 index 0000000000..8bdd2fb579 --- /dev/null +++ b/modular_chomp/code/datums/changelog/changelog.dm @@ -0,0 +1,32 @@ +/datum/changelog + var/static/list/changelog_items = list() + +/datum/changelog/tgui_state() + return GLOB.tgui_always_state + +/datum/changelog/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "Changelog") + ui.open() + +/datum/changelog/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + if(.) + return + if(action == "get_month") + var/datum/asset/changelog_item/changelog_item = changelog_items[params["date"]] + if (!changelog_item) + changelog_item = new /datum/asset/changelog_item(params["date"]) + changelog_items[params["date"]] = changelog_item + return ui.send_asset(changelog_item) + +/datum/changelog/tgui_static_data() + var/list/data = list( "dates" = list() ) + var/regex/ymlRegex = regex(@"\.yml", "g") + + for(var/archive_file in sortList(flist("html/changelogs/archive/"))) + var/archive_date = ymlRegex.Replace(archive_file, "") + data["dates"] = list(archive_date) + data["dates"] + + return data diff --git a/modular_chomp/code/modules/asset_cache/asset_list.dm b/modular_chomp/code/modules/asset_cache/asset_list.dm new file mode 100644 index 0000000000..b7817fec3b --- /dev/null +++ b/modular_chomp/code/modules/asset_cache/asset_list.dm @@ -0,0 +1,17 @@ +/datum/asset/changelog_item + _abstract = /datum/asset/changelog_item + var/item_filename + +/datum/asset/changelog_item/New(date) + item_filename = sanitize_filename("[date].yml") + register_asset(item_filename, file("html/changelogs/archive/" + item_filename)) + +/datum/asset/changelog_item/send(client) + if (!item_filename) + return + . = send_asset(client, item_filename) + +/datum/asset/changelog_item/get_url_mappings() + if (!item_filename) + return + . = list("[item_filename]" = get_asset_url(item_filename)) diff --git a/tgui/packages/tgui_ch/interfaces/Changelog.js b/tgui/packages/tgui_ch/interfaces/Changelog.js new file mode 100644 index 0000000000..0c0c2f4323 --- /dev/null +++ b/tgui/packages/tgui_ch/interfaces/Changelog.js @@ -0,0 +1,315 @@ +import { classes } from 'common/react'; +import { useBackend } from '../backend'; +import { Component, Fragment } from 'inferno'; +import { Box, Button, Dropdown, Icon, Section, Stack, Table } from '../components'; +import { Window } from '../layouts'; +import { resolveAsset } from '../assets'; +import dateformat from 'dateformat'; +import yaml from 'js-yaml'; + +const icons = { + bugfix: { icon: 'bug', color: 'green' }, + wip: { icon: 'hammer', color: 'orange' }, + qol: { icon: 'hand-holding-heart', color: 'green' }, + soundadd: { icon: 'tg-sound-plus', color: 'green' }, + sounddel: { icon: 'tg-sound-minus', color: 'red' }, + add: { icon: 'check-circle', color: 'green' }, + expansion: { icon: 'check-circle', color: 'green' }, + rscadd: { icon: 'check-circle', color: 'green' }, + rscdel: { icon: 'times-circle', color: 'red' }, + imageadd: { icon: 'tg-image-plus', color: 'green' }, + imagedel: { icon: 'tg-image-minus', color: 'red' }, + spellcheck: { icon: 'spell-check', color: 'green' }, + experiment: { icon: 'radiation', color: 'yellow' }, + balance: { icon: 'balance-scale-right', color: 'yellow' }, + code_imp: { icon: 'code', color: 'green' }, + refactor: { icon: 'tools', color: 'green' }, + config: { icon: 'cogs', color: 'purple' }, + admin: { icon: 'user-shield', color: 'purple' }, + server: { icon: 'server', color: 'purple' }, + tgs: { icon: 'toolbox', color: 'purple' }, + tweak: { icon: 'wrench', color: 'green' }, + unknown: { icon: 'info-circle', color: 'label' }, +}; + +export class Changelog extends Component { + constructor() { + super(); + this.state = { + data: 'Loading changelog data...', + selectedDate: '', + selectedIndex: 0, + }; + this.dateChoices = []; + } + + setData(data) { + this.setState({ data }); + } + + setSelectedDate(selectedDate) { + this.setState({ selectedDate }); + } + + setSelectedIndex(selectedIndex) { + this.setState({ selectedIndex }); + } + + getData = (date, attemptNumber = 1) => { + const { act } = useBackend(this.context); + const self = this; + const maxAttempts = 6; + + if (attemptNumber > maxAttempts) { + return this.setData( + 'Failed to load data after ' + maxAttempts + ' attempts' + ); + } + + act('get_month', { date }); + + fetch(resolveAsset(date + '.yml')).then(async (changelogData) => { + const result = await changelogData.text(); + const errorRegex = /^Cannot find/; + + if (errorRegex.test(result)) { + const timeout = 50 + attemptNumber * 50; + + self.setData('Loading changelog data' + '.'.repeat(attemptNumber + 3)); + setTimeout(() => { + self.getData(date, attemptNumber + 1); + }, timeout); + } else { + self.setData(yaml.load(result, { schema: yaml.CORE_SCHEMA })); + } + }); + }; + + componentDidMount() { + const { + data: { dates = [] }, + } = useBackend(this.context); + + if (dates) { + dates.forEach((date) => + this.dateChoices.push(dateformat(date, 'mmmm yyyy', true)) + ); + this.setSelectedDate(this.dateChoices[0]); + this.getData(dates[0]); + } + } + + render() { + const { data, selectedDate, selectedIndex } = this.state; + const { + data: { dates }, + } = useBackend(this.context); + const { dateChoices } = this; + + const dateDropdown = dateChoices.length > 0 && ( + + + ",$e+='
',$e+='
',$e+="Addons:
"+function(e){var t=[];return null==e||e.forEach((function(e){t.push(''+e+"")})),0===t.length&&t.push("No Addons Set"),t}(m)+"

",$e+="== Descriptions ==
",$e+="Vore Verb:
"+a+"

",$e+="Release Verb:
"+i+"

",$e+='Description:
"'+o+'"

',$e+='Absorbed Description:
"'+r+'"

',$e+="
",$e+="== Messages ==
",$e+='
',$e+='
",$e+='
',$e+='
',$e+='
',null==M||M.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==A||A.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==E||E.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==P||P.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==O||O.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==F||F.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==D||D.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==R||R.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==j||j.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==W||W.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==z||z.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==U||U.forEach((function(e){$e+=e+"
"})),$e+="
",$e+="
",$e+="
",$e+="
",$e+="
= Idle Messages =

",$e+="

Idle Messages (Hold):

",null==G||G.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Hold Absorbed):

",null==q||q.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Digest):

",null==H||H.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Absorb):

",null==K||K.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Unabsorb):

",null==ee||ee.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Drain):

",null==$||$.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Heal):

",null==Y||Y.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Size Steal):

",null==X||X.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Shrink):

",null==J||J.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Grow):

",null==Z||Z.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="
Idle Messages (Encase In Egg):

",null==Q||Q.forEach((function(e){$e+=e+"
"})),$e+="


",$e+="


",$e+="
",$e+='
',$e+='
',$e+='

',$e+='

",$e+='
',$e+='
',$e+='
    ',$e+='
  • Can Taste: '+(b?'Yes':'No')+"
  • ",$e+='
  • Feedable: '+(N?'Yes':'No')+"
  • ",$e+='
  • Contaminates: '+(g?'Yes':'No')+"
  • ",$e+='
  • Contamination Flavor: '+V+"
  • ",$e+='
  • Contamination Color: '+v+"
  • ",$e+='
  • Nutritional Gain: '+_+"%
  • ",$e+='
  • Required Examine Size: '+100*y+"%
  • ",$e+='
  • Display Absorbed Examines: '+(k?'True':'False')+"
  • ",$e+='
  • Save Digest Mode: '+(x?'True':'False')+"
  • ",$e+='
  • Idle Emotes: '+(w?'Active':'Inactive')+"
  • ",$e+='
  • Idle Emote Delay: '+B+" seconds
  • ",$e+='
  • Shrink/Grow Size: '+100*L+"%
  • ",$e+='
  • Vore Spawn Blacklist: '+(S?'Yes':'No')+"
  • ",$e+='
  • Egg Type: '+I+"
  • ",$e+='
  • Selective Mode Preference: '+T+"
  • ",$e+="
",$e+="
",$e+='
',$e+='

',$e+='

",$e+='
',$e+='
',$e+='
    ',$e+='
  • Fleshy Belly: '+(te?'Yes':'No')+"
  • ",$e+='
  • Internal Loop: '+(ne?'Yes':'No')+"
  • ",$e+='
  • Use Fancy Sounds: '+(oe?'Yes':'No')+"
  • ",$e+='
  • Vore Sound: '+re+"
  • ",$e+='
  • Release Sound: '+ae+"
  • ",$e+="
",$e+="
",$e+='
',$e+='

',$e+='

",$e+='
",$e+='
',$e+="Vore Sprites",$e+='
    ',$e+='
  • Affect Vore Sprites: '+(ie?'Yes':'No')+"
  • ",$e+='
  • Count Absorbed prey for vore sprites: '+(ce?'Yes':'No')+"
  • ",$e+='
  • Animation when prey resist: '+(le?'Yes':'No')+"
  • ",$e+='
  • Vore Sprite Size Factor: '+de+"
  • ",$e+='
  • Belly Sprite to affect: '+se+"
  • ",$e+="
",$e+="Belly Fullscreens Preview and Coloring",$e+='
    ',$e+='
  • Color: '+ue+"",$e+="
",$e+="Vore FX",$e+='
    ',$e+='
  • Disable Prey HUD: '+(me?'Yes':'No')+"
  • ",$e+="
",$e+="
",$e+='
',$e+='

',$e+='

",$e+='
',$e+='
',$e+="Belly Interactions ("+(pe?'Enabled':'Disabled')+")",$e+='
    ',$e+='
  • Escape Chance: '+he+"%
  • ",$e+='
  • Escape Time: '+fe/10+"s
  • ",$e+='
  • Transfer Chance: '+Ce+"%
  • ",$e+='
  • Transfer Location: '+be+"
  • ",$e+='
  • Secondary Transfer Chance: '+Ne+"%
  • ",$e+='
  • Secondary Transfer Location: '+ge+"
  • ",$e+='
  • Absorb Chance: '+Ve+"%
  • ",$e+='
  • Digest Chance: '+ve+"%
  • ",$e+="
",$e+="
",$e+="Auto-Transfer Options ("+(Be?'Enabled':'Disabled')+")",$e+='
    ',$e+='
  • Auto-Transfer Time: '+_e/10+"s
  • ",$e+='
  • Auto-Transfer Chance: '+ye+"%
  • ",$e+='
  • Auto-Transfer Location: '+ke+"
  • ",$e+='
  • Auto-Transfer Chance: '+xe+"%
  • ",$e+='
  • Auto-Transfer Location: '+we+"
  • ",$e+='
  • Auto-Transfer Min Amount: '+Le+"
  • ",$e+='
  • Auto-Transfer Max Amount: '+Se+"
  • ",$e+="
",$e+="
",$e+='
',$e+='

',$e+='

",$e+='
',$e+='
',$e+='
    ',$e+='
  • Generate Liquids: '+(Te?'On':'Off')+"
  • ",$e+='
  • Liquid Type: '+Me+"
  • ",$e+='
  • Liquid Name: '+Ae+"
  • ",$e+='
  • Transfer Verb: '+Ee+"
  • ",$e+='
  • Generation Time: '+Pe+"
  • ",$e+='
  • Liquid Capacity: '+Oe+"
  • ",$e+='
  • Slosh Sounds: '+(Fe?'On':'Off')+"
  • ",$e+='
  • Liquid Addons: '+function(e){var t=[];return null==e||e.forEach((function(e){t.push(''+e+"")})),0===t.length&&t.push("No Addons Set"),t}(De)+"
  • ",$e+="
",$e+="
",$e+='
',$e+='

',$e+='

",$e+='
',$e+='
',$e+='
',$e+='
",$e+='
',$e+='
',$e+='
',null==He||He.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==Ge||Ge.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==qe||qe.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==Ke||Ke.forEach((function(e){$e+=e+"
"})),$e+="
",$e+='
',null==Ye||Ye.forEach((function(e){$e+=e+"
"})),$e+="
",$e+="
",$e+="
",$e+="
",$e+="
",$e+="
"},m=function(e,t){var n,o=(0,r.useBackend)(e),a=(o.act,o.data),i=a.db_version,c=a.db_repo,l=a.mob_name,d=a.bellies,s=function(){var e=new Date,t=String(e.getHours());t.length<2&&(t="0"+t);var n=String(e.getMinutes());n.length<2&&(n="0"+n);var o=String(e.getDate());o.length<2&&(o="0"+o);var r=String(e.getMonth()+1);return r.length<2&&(r="0"+r)," "+String(e.getFullYear())+"-"+r+"-"+o+" ("+t+" "+n+")"}(),m=l+s+t;if(".html"===t){n=new Blob([''+d.length+" Exported Bellies (DB_VER: "+c+"-"+i+')

Bellies of '+l+'

Generated on: '+s+'

'],{type:"text/html;charset=utf8"}),d.forEach((function(e,t){n=new Blob([n,u(e,t)],{type:"text/html;charset=utf8"})})),n=new Blob([n,"
",'