Changelog Overhaul (#13051)
* Changelog Overhaul * SQL Update * This is why I hate merge conflicts * Comment Correction * Farie Fixes + Tested with blank DB * Colours + Titles * Colour tweaks * I fell victim to my own CI Chains! * Cleans up the remains of the old changelogs * Fixes formatting * Kyet Changes * Date
@@ -23,7 +23,6 @@ jobs:
|
||||
- find . -name "*.json" -not -path "./nano/node_modules/*" -print0 | xargs -0 python3 ./tools/travis/json_verifier.py
|
||||
- tools/travis/build_nanoui.sh
|
||||
- tools/travis/check_grep.sh
|
||||
- tools/travis/check_changelogs.sh
|
||||
- python3 tools/travis/check_line_endings.py
|
||||
- ~/dreamchecker
|
||||
|
||||
|
||||
@@ -594,4 +594,18 @@ CREATE TABLE `connection_log` (
|
||||
`ip` varchar(32) NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
--
|
||||
-- Table structure for table `changelog`
|
||||
--
|
||||
DROP TABLE IF EXISTS `changelog`;
|
||||
CREATE TABLE `changelog` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`pr_number` INT(11) NOT NULL,
|
||||
`date_merged` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`author` VARCHAR(32) NOT NULL,
|
||||
`cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL,
|
||||
`cl_entry` TEXT NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -591,4 +591,18 @@ CREATE TABLE `SS13_connection_log` (
|
||||
`ip` varchar(32) NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_changelog`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_changelog`;
|
||||
CREATE TABLE `SS13_changelog` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`pr_number` INT(11) NOT NULL,
|
||||
`date_merged` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`author` VARCHAR(32) NOT NULL,
|
||||
`cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL,
|
||||
`cl_entry` TEXT NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
@@ -38,4 +38,4 @@ ALTER TABLE feedback.population CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4
|
||||
ALTER TABLE feedback.privacy CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE feedback.vpn_whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE feedback.watch CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE feedback.whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE feedback.whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#Updating the SQL from version 11 to version 12. -AffectedArc07
|
||||
#Creating a table for the new changelog system
|
||||
|
||||
DROP TABLE IF EXISTS `changelog`;
|
||||
CREATE TABLE IF NOT EXISTS `changelog` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`pr_number` INT(11) NOT NULL,
|
||||
`date_merged` TIMESTAMP NOT NULL DEFAULT current_timestamp(),
|
||||
`author` VARCHAR(32) NOT NULL,
|
||||
`cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL,
|
||||
`cl_entry` TEXT NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -319,7 +319,7 @@
|
||||
#define INVESTIGATE_BOMB "bombs"
|
||||
|
||||
// The SQL version required by this version of the code
|
||||
#define SQL_VERSION 11
|
||||
#define SQL_VERSION 12
|
||||
|
||||
// Vending machine stuff
|
||||
#define CAT_NORMAL 1
|
||||
|
||||
@@ -4,7 +4,6 @@ GLOBAL_VAR(host)
|
||||
GLOBAL_VAR(join_motd)
|
||||
GLOBAL_VAR(join_tos)
|
||||
GLOBAL_VAR_INIT(game_version, "ParaCode")
|
||||
GLOBAL_VAR_INIT(changelog_hash, md5('html/changelog.html')) //used to check if the CL changed
|
||||
GLOBAL_VAR_INIT(game_year, (text2num(time2text(world.realtime, "YYYY")) + 544))
|
||||
|
||||
GLOBAL_VAR_INIT(aliens_allowed, 1)
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Subsystem core for ParadiseSS13 changelogs
|
||||
Author: AffectedArc07
|
||||
|
||||
Basically this SS extracts changelogs from the past 30 days from the database, and cleanly formats them into HTML that the players can see
|
||||
It only runs the extraction on initialize to ensure that the changelog doesnt change mid round, and to reduce the amount of DB calls that need to be done
|
||||
The changelog entries are generated from the PHP scripts in tools/githubChangelogProcessor.php
|
||||
|
||||
This SS also handles the checking of player CL dates and informing them if it has changed
|
||||
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(changelog)
|
||||
name = "Changelog"
|
||||
flags = SS_NO_FIRE
|
||||
var/current_cl_timestamp = "0" // Timestamp is seconds since UNIX epoch (1st January 1970). ITs also a string because BYOND doesnt like big numbers.
|
||||
var/ss_ready = FALSE // Is the SS ready? We dont want to run procs if we have not generated yet
|
||||
var/list/startup_clients_button = list() // Clients who connected before initialization who need their button color updating
|
||||
var/list/startup_clients_open = list() // Clients who connected before initialization who need the CL opening
|
||||
var/changelogHTML = "" // HTML that the changelog will use to display
|
||||
|
||||
/datum/controller/subsystem/changelog/Initialize()
|
||||
// This entire subsystem relies on SQL being here.
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
return ..()
|
||||
|
||||
var/DBQuery/latest_cl_date = GLOB.dbcon.NewQuery("SELECT UNIX_TIMESTAMP(date_merged) AS ut FROM [format_table_name("changelog")] ORDER BY date_merged DESC LIMIT 1")
|
||||
if(!latest_cl_date.Execute())
|
||||
var/err = latest_cl_date.ErrorMsg()
|
||||
log_game("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n")
|
||||
message_admins("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n")
|
||||
// Abort if we cant do this
|
||||
return ..()
|
||||
|
||||
while(latest_cl_date.NextRow())
|
||||
current_cl_timestamp = latest_cl_date.item[1]
|
||||
|
||||
if(!GenerateChangelogHTML()) // if this failed to generate
|
||||
to_chat(world, "<span class='alert'>WARNING: Changelog failed to generate. Please inform a coder/server dev</span>")
|
||||
return ..()
|
||||
|
||||
ss_ready = TRUE
|
||||
// Now we can alert anyone who wanted to check the changelog
|
||||
for(var/x in startup_clients_button)
|
||||
var/client/C = x
|
||||
UpdatePlayerChangelogButton(C)
|
||||
|
||||
// Now we can alert anyone who wanted to check the changelog
|
||||
for(var/client/C in startup_clients_open)
|
||||
OpenChangelog(C)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogDate(client/C)
|
||||
if(!ss_ready)
|
||||
return // Only return here, we dont have to worry about a queue list because this will be called from ShowChangelog()
|
||||
// Technically this is only for the date but we can also do the UI button at the same time
|
||||
var/datum/preferences/P = GLOB.preferences_datums[C.ckey]
|
||||
if(P.toggles & UI_DARKMODE)
|
||||
winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none")
|
||||
else
|
||||
winset(C, "rpane.changelog", "background-color=none;font-style=none")
|
||||
C.prefs.lastchangelog = current_cl_timestamp
|
||||
var/DBQuery/updatePlayerCLTime = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[sanitizeSQL(current_cl_timestamp)]' WHERE ckey='[C.ckey]'")
|
||||
if(!updatePlayerCLTime.Execute())
|
||||
var/err = updatePlayerCLTime.ErrorMsg()
|
||||
log_game("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n")
|
||||
message_admins("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n")
|
||||
to_chat(C, "Couldn't update your last seen changelog, please try again later.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogButton(client/C)
|
||||
// If SQL aint even enabled, just set the button to default style
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
if(C.prefs.toggles & UI_DARKMODE)
|
||||
winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
|
||||
else
|
||||
winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
|
||||
return
|
||||
|
||||
// If SQL is enabled but we aint ready, queue them up, and use the default style
|
||||
if(!ss_ready)
|
||||
startup_clients_button |= C
|
||||
if(C.prefs.toggles & UI_DARKMODE)
|
||||
winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
|
||||
else
|
||||
winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
|
||||
return
|
||||
|
||||
// If we are ready, process the button style
|
||||
if(C.prefs.lastchangelog != current_cl_timestamp)
|
||||
winset(C, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold")
|
||||
to_chat(C, "<span class='info'>Changelog has changed since your last visit.</span>")
|
||||
else
|
||||
if(C.prefs.toggles & UI_DARKMODE)
|
||||
winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
|
||||
else
|
||||
winset(C, "rpane.changelog", "background-color=none;text-color=#000000")
|
||||
|
||||
|
||||
/datum/controller/subsystem/changelog/proc/OpenChangelog(client/C)
|
||||
// If SQL isnt enabled, dont even queue them, just tell them it wont work
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(C, "<span class='notice'>This server is not running with an SQL backend. Changelog is unavailable.</span>")
|
||||
return
|
||||
|
||||
// If SQL is enabled but we aint ready, queue them up
|
||||
if(!ss_ready)
|
||||
startup_clients_open |= C
|
||||
to_chat(C, "<span class='notice'>The changelog system is still initializing. The changelog will open for you once it has initialized.</span>")
|
||||
return
|
||||
|
||||
UpdatePlayerChangelogDate(C)
|
||||
UpdatePlayerChangelogButton(C)
|
||||
|
||||
var/datum/browser/cl_popup = new(C.mob, "changelog", "Changelog", 700, 800)
|
||||
cl_popup.set_content(changelogHTML)
|
||||
cl_popup.open()
|
||||
|
||||
/client/verb/changes()
|
||||
set name = "Changelog"
|
||||
set desc = "View the changelog."
|
||||
set category = "OOC"
|
||||
// Just invoke the actual CL thing
|
||||
SSchangelog.OpenChangelog(src)
|
||||
|
||||
// Helper to turn CL types into a fontawesome icon instead of an image
|
||||
// The colors are #28a745 for green, #fd7e14 for orange, and #dc3545 for red.
|
||||
// These colours are from bootstrap and look good with black and white
|
||||
/datum/controller/subsystem/changelog/proc/Text2Icon(text)
|
||||
switch(text)
|
||||
if("FIX")
|
||||
return "<i title='Fix' class='fas fa-tools'></i></span>" // Fixes are white because while they are good, they have no negative coutnerpart
|
||||
if("WIP")
|
||||
return "<span style='color: #fd7e14;'><i title='Work In Progress' class='fas fa-hard-hat'></i></span>" // WIP stuff is orange because new code is good but its not done yet
|
||||
if("TWEAK")
|
||||
return "<i title='Tweak' class='fas fa-sliders-h'></i>" // Tweaks are white because they could be good or bad, and theres no specific add or remove
|
||||
if("SOUNDADD")
|
||||
return "<span style='color: #28a745;'><i title='Sound Added' class='fas fa-volume-up'></i></span>" // Sound additions are green because its something new
|
||||
if("SOUNDDEL")
|
||||
return "<span style='color: #dc3545;'><i title='Sound Removed' class='fas fa-volume-mute'></i></span>" // Sound removals are red because something has been removed
|
||||
if("CODEADD")
|
||||
return "<span style='color: #28a745;'><i title='Code Addition' class='fas fa-plus'></i></span>" // Code additions are green because its something new
|
||||
if("CODEDEL")
|
||||
return "<span style='color: #dc3545;'><i title='Code Removal' class='fas fa-minus'></i></span>" // Code removals are red becuase someting has been removed
|
||||
if("IMAGEADD")
|
||||
return "<span style='color: #28a745;'><i title='Image/Sprite Addition' class='fas fa-folder-plus'></i></span>" // Image additions are green because something has been added
|
||||
if("IMAGEDEL")
|
||||
return "<span style='color: #dc3545;'><i title='Image/Sprite Removal' class='fas fa-folder-minus'></i></span>" // Image removals are red because something has been removed
|
||||
if("SPELLCHECK")
|
||||
return "<i title='Spelling/Grammar Fix' class='fas fa-font'></i>" // Spellcheck is white because theres no dedicated negative to it, so theres no red for it to collate with
|
||||
if("EXPERIMENT")
|
||||
return "<span style='color: #fd7e14;'><i title='Experimental' class='fas fa-exclamation-triangle'></i></span>" // Experimental stuff is orange because while its a new feature, its unstable
|
||||
else // Just incase the DB somehow breaks
|
||||
return "<span style='color: #28a745;'><i title='Code Addition' class='fas fa-plus'></i></span>" // Same here
|
||||
|
||||
// This proc is the star of the show
|
||||
/datum/controller/subsystem/changelog/proc/GenerateChangelogHTML()
|
||||
// Modify the code below to modify the header of the changelog
|
||||
var/changelog_header = {"
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" rel="stylesheet">
|
||||
<title>ParadiseSS13 Changelog</title>
|
||||
<base target='_blank' />
|
||||
<link rel='styelsheet' href='fontawesome.min.css'>
|
||||
<center>
|
||||
<p style='font-size: 20px'><b>Paradise Station Changelog</b></p>
|
||||
<p><a href='[config.forum_link_url]'>Forum</a> - <a href='[config.wikiurl]'>Wiki</a> - <a href='[config.githuburl]'>GitHub</a></p>
|
||||
</center>
|
||||
"}
|
||||
|
||||
var/list/prs_to_process = list()
|
||||
// Grab all from last 30 days
|
||||
var/DBQuery/pr_list_query = GLOB.dbcon.NewQuery("SELECT DISTINCT pr_number FROM changelog WHERE date_merged BETWEEN NOW() - INTERVAL 30 DAY AND NOW() ORDER BY date_merged DESC")
|
||||
if(!pr_list_query.Execute())
|
||||
var/err = pr_list_query.ErrorMsg()
|
||||
log_game("SQL ERROR during CL generation L143. Error: \[[err]\]\n")
|
||||
message_admins("SQL ERROR during CL generation L143. Error: \[[err]\]\n")
|
||||
return FALSE
|
||||
|
||||
while(pr_list_query.NextRow())
|
||||
prs_to_process += text2num(pr_list_query.item[1])
|
||||
|
||||
// Load in the header
|
||||
changelogHTML += changelog_header
|
||||
|
||||
// Make blocks for all the PRs
|
||||
for(var/pr_number in prs_to_process)
|
||||
// Initial declarations
|
||||
var/pr_block = "" // HTML for the changelog section
|
||||
var/author = "" // Author of the PR
|
||||
var/merge_date = "" // Timestamp of when the PR was merged
|
||||
|
||||
// Now we gather the data from the DB
|
||||
// Also we probably dont need to sanitize the PR number but you never know
|
||||
var/DBQuery/pr_meta = GLOB.dbcon.NewQuery("SELECT author,DATE(date_merged) AS date FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)] LIMIT 1")
|
||||
if(!pr_meta.Execute())
|
||||
var/err = pr_meta.ErrorMsg()
|
||||
log_game("SQL ERROR during CL generation L190. Error: \[[err]\]\n")
|
||||
message_admins("SQL ERROR during CL generation L190. Error: \[[err]\]\n")
|
||||
return FALSE
|
||||
|
||||
while(pr_meta.NextRow())
|
||||
author = pr_meta.item[1]
|
||||
merge_date = pr_meta.item[2]
|
||||
|
||||
// Now for each actual entry
|
||||
var/DBQuery/db_entries = GLOB.dbcon.NewQuery("SELECT cl_type, cl_entry FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)]")
|
||||
if(!db_entries.Execute())
|
||||
var/err = db_entries.ErrorMsg()
|
||||
log_game("SQL ERROR during CL generation L204. Error: \[[err]\]\n")
|
||||
message_admins("SQL ERROR during CL generation L204. Error: \[[err]\]\n")
|
||||
return FALSE
|
||||
|
||||
|
||||
// Now we make a changelog block
|
||||
pr_block += "<div class='statusDisplay'>"
|
||||
// If the github URL in the config has a trailing slash, it doesnt matter here, thankfully github accepts having a double slash: https://github.com/org/repo//pull/1
|
||||
pr_block += "<p class='white'><a href='[config.githuburl]/pull/[pr_number]'>#[pr_number]</a> by <b>[author]</b> (Merged on [merge_date])</span>"
|
||||
|
||||
while(db_entries.NextRow())
|
||||
pr_block += "<p>[Text2Icon(db_entries.item[1])] [db_entries.item[2]]</p>"
|
||||
|
||||
pr_block += "</div><br>"
|
||||
|
||||
changelogHTML += pr_block
|
||||
|
||||
// Make sure we return TRUE so we know it worked
|
||||
return TRUE
|
||||
@@ -373,13 +373,11 @@
|
||||
send_resources()
|
||||
|
||||
if(prefs.toggles & UI_DARKMODE) // activates dark mode if its flagged. -AA07
|
||||
if(establish_db_connection())
|
||||
activate_darkmode()
|
||||
activate_darkmode()
|
||||
else
|
||||
// activate_darkmode() calls the CL update button proc, so we dont want it double called
|
||||
SSchangelog.UpdatePlayerChangelogButton(src)
|
||||
|
||||
if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP
|
||||
if(establish_db_connection())
|
||||
to_chat(src, "<span class='info'>Changelog has changed since your last visit.</span>")
|
||||
update_changelog_button()
|
||||
|
||||
if(prefs.toggles & DISABLE_KARMA) // activates if karma is disabled
|
||||
if(establish_db_connection())
|
||||
@@ -825,7 +823,7 @@
|
||||
// IF YOU CHANGE ANYTHING IN ACTIVATE, MAKE SURE IT HAS A DEACTIVATE METHOD, -AA07
|
||||
/client/proc/activate_darkmode()
|
||||
///// BUTTONS /////
|
||||
update_changelog_button()
|
||||
SSchangelog.UpdatePlayerChangelogButton(src)
|
||||
/* Rpane */
|
||||
winset(src, "rpane.textb", "background-color=#40628a;text-color=#FFFFFF")
|
||||
winset(src, "rpane.infob", "background-color=#40628a;text-color=#FFFFFF")
|
||||
@@ -857,7 +855,7 @@
|
||||
|
||||
/client/proc/deactivate_darkmode()
|
||||
///// BUTTONS /////
|
||||
update_changelog_button()
|
||||
SSchangelog.UpdatePlayerChangelogButton(src)
|
||||
/* Rpane */
|
||||
winset(src, "rpane.textb", "background-color=none;text-color=#000000")
|
||||
winset(src, "rpane.infob", "background-color=none;text-color=#000000")
|
||||
@@ -887,22 +885,6 @@
|
||||
///// NOTIFY USER /////
|
||||
to_chat(src, "<span class='notice'>Darkmode Disabled</span>") // what a sick fuck
|
||||
|
||||
// Better changelog button handling
|
||||
/client/proc/update_changelog_button()
|
||||
if(establish_db_connection())
|
||||
if(prefs.lastchangelog != GLOB.changelog_hash)
|
||||
winset(src, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold")
|
||||
else
|
||||
if(prefs.toggles & UI_DARKMODE)
|
||||
winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
|
||||
else
|
||||
winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
|
||||
else
|
||||
if(prefs.toggles & UI_DARKMODE)
|
||||
winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF")
|
||||
else
|
||||
winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
|
||||
|
||||
/client/proc/generate_clickcatcher()
|
||||
if(!void)
|
||||
void = new()
|
||||
|
||||
@@ -79,7 +79,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
var/last_id
|
||||
|
||||
//game-preferences
|
||||
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
||||
var/lastchangelog = "1" //Saved changlog timestamp (unix epoch) to detect if there was a change. Dont set this to 0 unless you want the last changelog date to be 4x longer than the expected lifespan of the universe.
|
||||
var/exp
|
||||
var/ooccolor = "#b82e00"
|
||||
var/list/be_special = list() //Special role selection
|
||||
|
||||
@@ -491,18 +491,3 @@
|
||||
load_character(C,pick(saves))
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/SetChangelog(client/C,hash)
|
||||
lastchangelog=hash
|
||||
var/datum/preferences/P = GLOB.preferences_datums[C.ckey]
|
||||
if(P.toggles & UI_DARKMODE)
|
||||
winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none")
|
||||
else
|
||||
winset(C, "rpane.changelog", "background-color=none;font-style=none")
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'")
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
log_game("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n")
|
||||
message_admins("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n")
|
||||
to_chat(C, "Couldn't update your last seen changelog, please try again later.")
|
||||
return
|
||||
return 1
|
||||
|
||||
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
@@ -0,0 +1 @@
|
||||
This directory has the old changelog system, no longer used
|
||||
|
Before Width: | Height: | Size: 657 B After Width: | Height: | Size: 657 B |
|
Before Width: | Height: | Size: 727 B After Width: | Height: | Size: 727 B |
@@ -11811,3 +11811,45 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
- tweak: Cult whispering now uses your real name
|
||||
- bugfix: Fixed the invisible blob zombies
|
||||
- bugfix: A runtime in blob/factory/run_action
|
||||
2020-04-26:
|
||||
Cazdon:
|
||||
- bugfix: Admin Roles no longer appear on manifest.
|
||||
- tweak: Central Command PDA's no longer appear on the messenger list.
|
||||
- bugfix: Potential Convertee's being unable to be converted.
|
||||
Drakeven:
|
||||
- bugfix: Fixed mislabeled traitor and mindslave special role.
|
||||
Ionward:
|
||||
- tweak: Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific
|
||||
fits for soft space suits.
|
||||
- tweak: Vox can now wear soft space suits, such as EVA (Clown and Mime included),
|
||||
NASA Void, and Syndicate suits.
|
||||
- imageadd: Added Vox soft suit sprites.
|
||||
JKnutson101:
|
||||
- tweak: Combined the Rite of Tribute and Rite of Enlightenment into one Rite of
|
||||
Offering.
|
||||
- bugfix: Sacrificing now properly puts victims that have at one point had CKeys
|
||||
into soul stones, or polls dead-chat to do so.
|
||||
Kyep:
|
||||
- tweak: Tweaked Greater Hellhound, added more non-violent options and one unique
|
||||
combat spell.
|
||||
SteelSlayer:
|
||||
- bugfix: Fixes the "List SSDs and AFKs panel" showing everyone as the target of
|
||||
an assassinate objective
|
||||
- bugfix: The global objectives list is now viewable in the MC Globals menu
|
||||
- bugfix: Reverts some terrible changes that are causing some bugs with traitors
|
||||
- bugfix: Fixes AIs with the combat module not being able to hack APCs
|
||||
TDSSS:
|
||||
- rscdel: duplicate mecha definitions
|
||||
- bugfix: blobbernaut vision blur now clears as intended.
|
||||
- bugfix: fixed a bug preventing ticket system from working under some circumstances.
|
||||
VeteranKyl:
|
||||
- bugfix: DNA Samplers now check if the target species has DNA.
|
||||
- bugfix: Fixed the envenomed blob's spore toxin not causing harm.
|
||||
craftxbox:
|
||||
- bugfix: fixed colors not working without regex
|
||||
- bugfix: fixed text panel not loading when an invalid regex is added
|
||||
- rscadd: polyfilled string.prototype.includes
|
||||
moxian:
|
||||
- bugfix: being in a locker no longer interferes with tracking implant tracking
|
||||
- bugfix: locator no longer locates tracking implants on other z levels.
|
||||
- bugfix: fixed singulo being unable to expand when placed next to containment wall
|
||||
|
Before Width: | Height: | Size: 495 B After Width: | Height: | Size: 495 B |
|
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 498 B |
|
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 651 B |
|
Before Width: | Height: | Size: 678 B After Width: | Height: | Size: 678 B |
|
Before Width: | Height: | Size: 535 B After Width: | Height: | Size: 535 B |
|
Before Width: | Height: | Size: 580 B After Width: | Height: | Size: 580 B |
|
Before Width: | Height: | Size: 403 B After Width: | Height: | Size: 403 B |
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 462 B |
@@ -0,0 +1,10 @@
|
||||
body {padding:0px;margin:0px;}
|
||||
#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;}
|
||||
#main {position:relative;top:50px;left:3%;width:96%;text-align:center;z-index:0;}
|
||||
#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";}
|
||||
tr.norm {background-color:#f4f4f4;}
|
||||
tr.title {background-color:#ccc;}
|
||||
tr.alt {background-color:#e7e7e7;}
|
||||
.small {font-size:80%;}
|
||||
a {text-decoration:none;color:#a0a;}
|
||||
a:hover {color:#d3d;}
|
||||
@@ -0,0 +1,33 @@
|
||||
function selectTextField(){
|
||||
var filter_text = document.getElementById('filter');
|
||||
filter_text.focus();
|
||||
filter_text.select();
|
||||
}
|
||||
function updateSearch(){
|
||||
var input_form = document.getElementById('filter');
|
||||
var filter = input_form.value.toLowerCase();
|
||||
input_form.value = filter;
|
||||
var table = document.getElementById('searchable');
|
||||
var alt_style = 'norm';
|
||||
for(var i = 0; i < table.rows.length; i++){
|
||||
try{
|
||||
var row = table.rows[i];
|
||||
if(row.className == 'title') continue;
|
||||
var found=0;
|
||||
for(var j = 0; j < row.cells.length; j++){
|
||||
var cell = row.cells[j];
|
||||
if(cell.innerText.toLowerCase().indexOf(filter) != -1){
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found == 0) row.style.display='none';
|
||||
else{
|
||||
row.style.display='block';
|
||||
row.className = alt_style;
|
||||
if(alt_style == 'alt') alt_style = 'norm';
|
||||
else alt_style = 'alt';
|
||||
}
|
||||
}catch(err) { }
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 509 B |
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 684 B |
@@ -1,4 +0,0 @@
|
||||
author: "Kyep"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Tweaked Greater Hellhound, added more non-violent options and one unique combat spell."
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "JKnutson101"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Combined the Rite of Tribute and Rite of Enlightenment into one Rite of Offering."
|
||||
- bugfix: "Sacrificing now properly puts victims that have at one point had CKeys into soul stones, or polls dead-chat to do so."
|
||||
@@ -1,6 +0,0 @@
|
||||
author: "Ionward"
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific fits for soft space suits."
|
||||
- tweak: "Vox can now wear soft space suits, such as EVA (Clown and Mime included), NASA Void, and Syndicate suits."
|
||||
- imageadd: "Added Vox soft suit sprites."
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "SteelSlayer"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixes the \"List SSDs and AFKs panel\" showing everyone as the target of an assassinate objective"
|
||||
- bugfix: "The global objectives list is now viewable in the MC Globals menu"
|
||||
@@ -1,6 +0,0 @@
|
||||
author: "craftxbox"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "fixed colors not working without regex"
|
||||
- bugfix: "fixed text panel not loading when an invalid regex is added"
|
||||
- rscadd: "polyfilled string.prototype.includes"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "TDSSS"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscdel: "duplicate mecha definitions"
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "moxian"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "being in a locker no longer interferes with tracking implant tracking"
|
||||
- bugfix: "locator no longer locates tracking implants on other z levels."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "moxian"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "fixed singulo being unable to expand when placed next to containment wall"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "TDSSS"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "blobbernaut vision blur now clears as intended."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "Drakeven"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixed mislabeled traitor and mindslave special role."
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "Cazdon"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Admin Roles no longer appear on manifest."
|
||||
- tweak: "Central Command PDA's no longer appear on the messenger list."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "TDSSS"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "fixed a bug preventing ticket system from working under some circumstances."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "SteelSlayer"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Reverts some terrible changes that are causing some bugs with traitors"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "VeteranKyl"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "DNA Samplers now check if the target species has DNA."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "SteelSlayer"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixes AIs with the combat module not being able to hack APCs"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "VeteranKyl"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixed the envenomed blob's spore toxin not causing harm."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "Cazdon"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Potential Convertee's being unable to be converted."
|
||||
@@ -13,35 +13,6 @@
|
||||
to_chat(src, "<span class='danger'>The wiki URL is not set in the server configuration.</span>")
|
||||
return
|
||||
|
||||
/client/verb/changes()
|
||||
set name = "Changelog"
|
||||
set desc = "View the changelog."
|
||||
set hidden = 1
|
||||
|
||||
getFiles(
|
||||
'html/88x31.png',
|
||||
'html/bug-minus.png',
|
||||
'html/cross-circle.png',
|
||||
'html/hard-hat-exclamation.png',
|
||||
'html/image-minus.png',
|
||||
'html/image-plus.png',
|
||||
'html/music-minus.png',
|
||||
'html/music-plus.png',
|
||||
'html/tick-circle.png',
|
||||
'html/wrench-screwdriver.png',
|
||||
'html/spell-check.png',
|
||||
'html/burn-exclamation.png',
|
||||
'html/chevron.png',
|
||||
'html/chevron-expand.png',
|
||||
'html/changelog.css',
|
||||
'html/changelog.js',
|
||||
'html/changelog.html'
|
||||
)
|
||||
src << browse('html/changelog.html', "window=changes;size=675x650")
|
||||
update_changelog_button()
|
||||
if(prefs.lastchangelog != GLOB.changelog_hash) //if it's already opened, no need to tell them they have unread changes
|
||||
prefs.SetChangelog(src, GLOB.changelog_hash)
|
||||
|
||||
/client/verb/forum()
|
||||
set name = "forum"
|
||||
set desc = "Visit the forum."
|
||||
|
||||
@@ -216,6 +216,7 @@
|
||||
#include "code\controllers\subsystem\alarm.dm"
|
||||
#include "code\controllers\subsystem\assets.dm"
|
||||
#include "code\controllers\subsystem\atoms.dm"
|
||||
#include "code\controllers\subsystem\changelog.dm"
|
||||
#include "code\controllers\subsystem\chat.dm"
|
||||
#include "code\controllers\subsystem\events.dm"
|
||||
#include "code\controllers\subsystem\fires.dm"
|
||||
|
||||
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
/*
|
||||
* Github webhook In-game PR Announcer and SQL Changelog Generator for ParadiseSS13
|
||||
* Modified for Paradise by: AffectedArc07
|
||||
* Original code by: MrStonedOne
|
||||
*
|
||||
* For documentation on the changelog generator see https://tgstation13.org/phpBB/viewtopic.php?f=5&t=5157
|
||||
* To hide prs from being announced in game, place a [s] in front of the title
|
||||
* All runtime errors are echo'ed to the webhook's logs in github
|
||||
*/
|
||||
|
||||
/**CREDITS:
|
||||
* GitHub webhook handler template.
|
||||
*
|
||||
* @see https://developer.github.com/webhooks/
|
||||
* @author Miloslav Hula (https://github.com/milo)
|
||||
*/
|
||||
|
||||
|
||||
//CONFIG START (all defaults are random examples, do change them)
|
||||
//Use single quotes for config options that are strings.
|
||||
|
||||
//Github lets you have it sign the message with a secret that you can validate. This prevents people from faking events.
|
||||
//This var should match the secret you configured for this webhook on github.
|
||||
//This is required as otherwise somebody could trick the script into leaking variables.
|
||||
$hookSecret = '08ajh0qj93209qj90jfq932j32r';
|
||||
|
||||
// To store PR changelogs, this script requires access to the game database
|
||||
// Making an account just for this service is highly recommended
|
||||
// For maximum security, grant it INSERT on `changelog` ONLY.
|
||||
$dbServer = "localhost"; // Hostname of the database server (default localhost)
|
||||
$dbPort = "3306"; // Port of the database server (default 3306) | MUST BE A STRING
|
||||
$dbUser = "root"; // Database username (default root)
|
||||
$dbPassword = ""; // Database password (default blank)
|
||||
$dbDatabase = "feedback"; // Database name (default feedback)
|
||||
|
||||
//servers to announce PRs to.
|
||||
$servers = array();
|
||||
/*
|
||||
$servers[0] = array();
|
||||
$servers[0]['address'] = 'game.tgstation13.org';
|
||||
$servers[0]['port'] = '1337';
|
||||
$servers[0]['comskey'] = '89aj90cq2fm0amc90832mn9rm90';
|
||||
$servers[1] = array();
|
||||
$servers[1]['address'] = 'game.tgstation13.org';
|
||||
$servers[1]['port'] = '2337';
|
||||
$servers[1]['comskey'] = '89aj90cq2fm0amc90832mn9rm90';
|
||||
*/
|
||||
|
||||
//CONFIG END
|
||||
set_error_handler(function($severity, $message, $file, $line) {
|
||||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||||
});
|
||||
set_exception_handler(function($e) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
echo "Error on line {$e->getLine()}: " . htmlSpecialChars($e->getMessage());
|
||||
die();
|
||||
});
|
||||
$rawPost = NULL;
|
||||
if (!$hookSecret || $hookSecret == '08ajh0qj93209qj90jfq932j32r')
|
||||
throw new \Exception("Hook secret is required and can not be default");
|
||||
if (!isset($_SERVER['HTTP_X_HUB_SIGNATURE'])) {
|
||||
throw new \Exception("HTTP header 'X-Hub-Signature' is missing.");
|
||||
} elseif (!extension_loaded('hash')) {
|
||||
throw new \Exception("Missing 'hash' extension to check the secret code validity.");
|
||||
}
|
||||
list($algo, $hash) = explode('=', $_SERVER['HTTP_X_HUB_SIGNATURE'], 2) + array('', '');
|
||||
if (!in_array($algo, hash_algos(), TRUE)) {
|
||||
throw new \Exception("Hash algorithm '$algo' is not supported.");
|
||||
}
|
||||
$rawPost = file_get_contents('php://input');
|
||||
if ($hash !== hash_hmac($algo, $rawPost, $hookSecret)) {
|
||||
throw new \Exception('Hook secret does not match.');
|
||||
}
|
||||
|
||||
$contenttype = null;
|
||||
//apache and nginx/fastcgi/phpfpm call this two different things.
|
||||
if (!isset($_SERVER['HTTP_CONTENT_TYPE'])) {
|
||||
if (!isset($_SERVER['CONTENT_TYPE']))
|
||||
throw new \Exception("Missing HTTP 'Content-Type' header.");
|
||||
else
|
||||
$contenttype = $_SERVER['CONTENT_TYPE'];
|
||||
} else {
|
||||
$contenttype = $_SERVER['HTTP_CONTENT_TYPE'];
|
||||
}
|
||||
if (!isset($_SERVER['HTTP_X_GITHUB_EVENT'])) {
|
||||
throw new \Exception("Missing HTTP 'X-Github-Event' header.");
|
||||
}
|
||||
switch ($contenttype) {
|
||||
case 'application/json':
|
||||
$json = $rawPost ?: file_get_contents('php://input');
|
||||
break;
|
||||
case 'application/x-www-form-urlencoded':
|
||||
$json = $_POST['payload'];
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Unsupported content type: $contenttype");
|
||||
}
|
||||
# Payload structure depends on triggered event
|
||||
# https://developer.github.com/v3/activity/events/types/
|
||||
$payload = json_decode($json, true);
|
||||
|
||||
switch (strtolower($_SERVER['HTTP_X_GITHUB_EVENT'])) {
|
||||
case 'ping':
|
||||
echo 'pong';
|
||||
break;
|
||||
case 'pull_request':
|
||||
handle_pr($payload);
|
||||
break;
|
||||
default:
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
echo "Event:$_SERVER[HTTP_X_GITHUB_EVENT] Payload:\n";
|
||||
print_r($payload); # For debug only. Can be found in GitHub hook log.
|
||||
die();
|
||||
}
|
||||
function handle_pr($payload) {
|
||||
$action = 'opened';
|
||||
switch ($payload["action"]) {
|
||||
case 'opened':
|
||||
case 'reopened':
|
||||
$action = $payload['action'];
|
||||
break;
|
||||
case 'closed':
|
||||
if (!$payload['pull_request']['merged']) {
|
||||
$action = 'closed';
|
||||
}
|
||||
else {
|
||||
$action = 'merged';
|
||||
checkchangelog($payload, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (strtolower(substr($payload['pull_request']['title'], 0, 3)) == '[s]') {
|
||||
echo "PR Announcement Halted; Secret tag detected.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$msg = 'Pull Request '.$action.' by '.htmlSpecialChars($payload['sender']['login']).': <a href="'.$payload['pull_request']['html_url'].'">'.htmlSpecialChars('#'.$payload['pull_request']['number'].' '.$payload['pull_request']['user']['login'].' - '.$payload['pull_request']['title']).'</a>';
|
||||
sendtoallservers('?announce='.urlencode($msg));
|
||||
|
||||
}
|
||||
|
||||
function checkchangelog($payload, $merge = false) {
|
||||
global $dbServer, $dbUser, $dbPassword, $dbDatabase, $dbPort;
|
||||
if (!$merge)
|
||||
return;
|
||||
if (!isset($payload['pull_request']) || !isset($payload['pull_request']['body'])) {
|
||||
return;
|
||||
}
|
||||
if (!isset($payload['pull_request']['user']) || !isset($payload['pull_request']['user']['login'])) {
|
||||
return;
|
||||
}
|
||||
$body = $payload['pull_request']['body'];
|
||||
$prNumber = $payload['pull_request']['number'];
|
||||
$body = str_replace("\r\n", "\n", $body);
|
||||
$body = explode("\n", $body);
|
||||
$username = $payload['pull_request']['user']['login'];
|
||||
$incltag = false;
|
||||
$changelogbody = array();
|
||||
$currentchangelogblock = array();
|
||||
$foundcltag = false;
|
||||
foreach ($body as $line) {
|
||||
$line = trim($line);
|
||||
if (substr($line,0,4) == ':cl:' || substr($line,0,4) == '🆑') {
|
||||
$incltag = true;
|
||||
$foundcltag = true;
|
||||
$pos = strpos($line, " ");
|
||||
if ($pos)
|
||||
$username = substr($line, $pos+1);
|
||||
continue;
|
||||
} else if (substr($line,0,5) == '/:cl:' || substr($line,0,6) == '/ :cl:' || substr($line,0,5) == ':/cl:' || substr($line,0,5) == '/🆑' || substr($line,0,6) == '/ 🆑' ) {
|
||||
$incltag = false;
|
||||
$changelogbody = array_merge($changelogbody, $currentchangelogblock);
|
||||
continue;
|
||||
}
|
||||
if (!$incltag)
|
||||
continue;
|
||||
|
||||
$firstword = explode(' ', $line)[0];
|
||||
$pos = strpos($line, " ");
|
||||
$item = '';
|
||||
if ($pos) {
|
||||
$firstword = trim(substr($line, 0, $pos));
|
||||
$item = trim(substr($line, $pos+1));
|
||||
} else {
|
||||
$firstword = $line;
|
||||
}
|
||||
|
||||
if (!strlen($firstword)) {
|
||||
$currentchangelogblock[count($currentchangelogblock)-1]['body'] .= "\n";
|
||||
continue;
|
||||
}
|
||||
//not a prefix line.
|
||||
//so we add it to the last changelog entry as a separate line
|
||||
if (!strlen($firstword) || $firstword[strlen($firstword)-1] != ':') {
|
||||
if (count($currentchangelogblock) <= 0)
|
||||
continue;
|
||||
$currentchangelogblock[count($currentchangelogblock)-1]['body'] .= "\n".$line;
|
||||
continue;
|
||||
}
|
||||
$cltype = strtolower(substr($firstword, 0, -1));
|
||||
switch ($cltype) {
|
||||
case 'fix':
|
||||
case 'fixes':
|
||||
case 'bugfix':
|
||||
$currentchangelogblock[] = array('type' => 'FIX', 'body' => $item);
|
||||
break;
|
||||
case 'wip':
|
||||
$currentchangelogblock[] = array('type' => 'WIP', 'body' => $item);
|
||||
break;
|
||||
case 'rsctweak':
|
||||
case 'tweaks':
|
||||
case 'tweak':
|
||||
$currentchangelogblock[] = array('type' => 'TWEAK', 'body' => $item);
|
||||
break;
|
||||
case 'soundadd':
|
||||
$currentchangelogblock[] = array('type' => 'SOUNDADD', 'body' => $item);
|
||||
break;
|
||||
case 'sounddel':
|
||||
$currentchangelogblock[] = array('type' => 'SOUNDDEL', 'body' => $item);
|
||||
break;
|
||||
case 'add':
|
||||
case 'adds':
|
||||
case 'rscadd':
|
||||
$currentchangelogblock[] = array('type' => 'CODEADD', 'body' => $item);
|
||||
break;
|
||||
case 'del':
|
||||
case 'dels':
|
||||
case 'rscdel':
|
||||
$currentchangelogblock[] = array('type' => 'CODEDEL', 'body' => $item);
|
||||
break;
|
||||
case 'imageadd':
|
||||
$currentchangelogblock[] = array('type' => 'IMAGEADD', 'body' => $item);
|
||||
break;
|
||||
case 'imagedel':
|
||||
$currentchangelogblock[] = array('type' => 'IMAGEDEL', 'body' => $item);
|
||||
break;
|
||||
case 'typo':
|
||||
case 'spellcheck':
|
||||
$currentchangelogblock[] = array('type' => 'SPELLCHECK', 'body' => $item);
|
||||
break;
|
||||
case 'experimental':
|
||||
case 'experiment':
|
||||
$currentchangelogblock[] = array('type' => 'EXPERIMENT', 'body' => $item);
|
||||
break;
|
||||
default:
|
||||
//we add it to the last changelog entry as a separate line
|
||||
if (count($currentchangelogblock) > 0)
|
||||
$currentchangelogblock[count($currentchangelogblock)-1]['body'] .= "\n".$line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!count($changelogbody))
|
||||
return;
|
||||
|
||||
$conn = new PDO("mysql:host=$dbServer;dbname=$dbDatabase;port=$dbPort", $dbUser, $dbPassword); // Initialises DB connection
|
||||
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
foreach($changelogbody as $changelogEntry) {
|
||||
// Throw all changelogs into the DB
|
||||
$stmt = $conn->prepare("INSERT INTO changelog (pr_number, author, cl_type, cl_entry) VALUES (?, ?, ?, ?)");
|
||||
$stmt->bindParam(1, $prNumber, PDO::PARAM_INT);
|
||||
$stmt->bindParam(2, $username, PDO::PARAM_STR);
|
||||
$stmt->bindParam(3, $changelogEntry["type"], PDO::PARAM_STR);
|
||||
$stmt->bindParam(4, $changelogEntry["body"], PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$conn = null; // Close the DB connection
|
||||
|
||||
}
|
||||
|
||||
function sendtoallservers($str) {
|
||||
global $servers;
|
||||
foreach ($servers as $serverid => $server) {
|
||||
if (isset($server['comskey']))
|
||||
$rtn = export($server['address'], $server['port'], $str.'&key='.$server['comskey']);
|
||||
else
|
||||
$rtn = export($server['address'], $server['port'], $str);
|
||||
|
||||
echo "Server Number $serverid replied: $rtn\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function export($addr, $port, $str) {
|
||||
global $error;
|
||||
// All queries must begin with a question mark (ie "?players")
|
||||
if($str{0} != '?') $str = ('?' . $str);
|
||||
|
||||
/* --- Prepare a packet to send to the server (based on a reverse-engineered packet structure) --- */
|
||||
$query = "\x00\x83" . pack('n', strlen($str) + 6) . "\x00\x00\x00\x00\x00" . $str . "\x00";
|
||||
|
||||
/* --- Create a socket and connect it to the server --- */
|
||||
$server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP) or exit("ERROR");
|
||||
socket_set_option($server, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 2, 'usec' => 0)); //sets connect and send timeout to 2 seconds
|
||||
if(!socket_connect($server,$addr,$port)) {
|
||||
$error = true;
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
|
||||
/* --- Send bytes to the server. Loop until all bytes have been sent --- */
|
||||
$bytestosend = strlen($query);
|
||||
$bytessent = 0;
|
||||
while ($bytessent < $bytestosend) {
|
||||
//echo $bytessent.'<br>';
|
||||
$result = socket_write($server,substr($query,$bytessent),$bytestosend-$bytessent);
|
||||
//echo 'Sent '.$result.' bytes<br>';
|
||||
if ($result===FALSE) die(socket_strerror(socket_last_error()));
|
||||
$bytessent += $result;
|
||||
}
|
||||
|
||||
/* --- Idle for a while until recieved bytes from game server --- */
|
||||
$result = socket_read($server, 10000, PHP_BINARY_READ);
|
||||
socket_close($server); // we don't need this anymore
|
||||
|
||||
if($result != "") {
|
||||
if($result{0} == "\x00" || $result{1} == "\x83") { // make sure it's the right packet format
|
||||
|
||||
// Actually begin reading the output:
|
||||
$sizebytes = unpack('n', $result{2} . $result{3}); // array size of the type identifier and content
|
||||
$size = $sizebytes[1] - 1; // size of the string/floating-point (minus the size of the identifier byte)
|
||||
|
||||
if($result{4} == "\x2a") { // 4-byte big-endian floating-point
|
||||
$unpackint = unpack('f', $result{5} . $result{6} . $result{7} . $result{8}); // 4 possible bytes: add them up together, unpack them as a floating-point
|
||||
return $unpackint[1];
|
||||
}
|
||||
else if($result{4} == "\x06") { // ASCII string
|
||||
$unpackstr = ""; // result string
|
||||
$index = 5; // string index
|
||||
|
||||
while($size > 0) { // loop through the entire ASCII string
|
||||
$size--;
|
||||
$unpackstr .= $result{$index}; // add the string position to return string
|
||||
$index++;
|
||||
}
|
||||
return $unpackstr;
|
||||
}
|
||||
}
|
||||
}
|
||||
//if we get to this point, something went wrong;
|
||||
$error = true;
|
||||
return "ERROR";
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
rem Cheridan asked for this. - N3X
|
||||
call python ss13_genchangelog.py ../html/changelog.html ../html/changelogs
|
||||
pause
|
||||
@@ -0,0 +1,3 @@
|
||||
# Old Changelog System
|
||||
|
||||
This directory contains all the data for the old changelog system
|
||||
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
rem Cheridan asked for this. - N3X
|
||||
rem This has been updated to use the old changelog directories as of PR #13051 -AA
|
||||
call python ss13_genchangelog.py ../../html/archived_changelog/changelog.html ../../html/archived_changelog/changelogs
|
||||
pause
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
md5sum -c - <<< "6dc1b6bf583f3bd4176b6df494caa5f1 *html/changelogs/example.yml"
|
||||
python tools/ss13_genchangelog.py html/changelog.html html/changelogs
|
||||