Massive backend updoot: Juke Build, TGUI upgrades, Soft Ping, and too much to list! (#3990)

* Time to become our TGUI God.

* Visually sprucing the copyrights.

These shouldn't be ignored :)

* babababa

* https://github.com/tgstation/tgstation/pull/50422

* dooootdooot

* Holy fuck

Updates the tools folder
Updates our build tooling
Updates TGUI MASSIVELY
I'm going to go scream in a hole now

* ??

* Was it this dum thing?

* orrrr

* It's this isn't it

* Did it manually

* hubah

* TGUI Changelog

* oops

* What if I use the original?

* Lets try this again

* Shit commenting out for now

* asdasd

* Fuck it use the old one and remember to replace later

* Updates yarn.lock

* Lets try something horrid

* Nope it HATES THAT

* fucc

* The great eslinting

* HOLY SHIT

* Final?

* ?

* asd

tgstation/tgstation/pull/59914
tgstation/tgstation/pull/66317

* Improved Asset handling.

* Oops

* Subsystem stuff

* Recompiles the Changelong again.

* Finally Fixed Communicators

* Compiled Changelogs... AGAIN
This commit is contained in:
Zandario
2022-05-09 20:02:09 -05:00
committed by GitHub
parent ed8a67db1c
commit ed27a01b58
826 changed files with 26042 additions and 23085 deletions

View File

@@ -4,6 +4,7 @@ indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[*.yml]
indent_style = space
@@ -11,3 +12,9 @@ indent_size = 2
[*.py]
indent_style = space
[*.md]
trim_trailing_whitespace = false
[Dockerfile]
indent_style = space

16
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,16 @@
#Ignores big formatting commits when checking blame.
#To make use of this file by default, run 'git config blame.ignoreRevsFile .git-blame-ignore-revs'
#in the project folder
## Line ending conversions
# Force LF line endings with gitattributes and convert repo
62676e72a85cd23e7a87d94adff96d17859dbdc5
# Line ending apocalypse
134a76cc8f5517bdc1bba5a8cbe01dc820df1c2a
# Initial pass to convert LF to CRLF
8af8a43d6f27e342e79d4aacb22b7668cbdc8559
# Many changes
931da9e7ef8c0f52a768eed7998e7e62ccdefcdc
# Remove hideous inline tab indentation, and bans it in contributing guidelines
0f435d5dff0a7957e8cba60a41a7fc10439064c3

8
.gitattributes vendored
View File

@@ -2,14 +2,13 @@
## Enforce text mode and LF line breaks
*.bat text eol=lf
*.css text eol=lf
*.cjs text eol=lf
*.css text eol=lf
*.dm text eol=lf
*.dme text eol=lf
*.dmf text eol=lf
*.htm text eol=lf
*.html text eol=lf
*.html text eol=lf
*.js text eol=lf
*.json text eol=lf
*.jsx text eol=lf
@@ -40,8 +39,5 @@
*.dmm text eol=lf merge=dmm
*.dmi binary merge=dmi
## Force changelog merging to use union
html/changelog.html text eol=lf merge=union
## Force tab indents on dm files
*dm whitespace=indent-with-non-tab
*.dm whitespace=indent-with-non-tab

15
.github/CODEOWNERS vendored
View File

@@ -4,6 +4,19 @@
# In the event that multiple org members are to be informed of changes
# to the same file or dir, add them to the end under Multiple Owners
#LetterJay
# LetterJay
/code/modules/client/preference_setup/loadout/loadout_donator.dm @LetterJay
/SQL/database_changelog.txt @LetterJay
# Zandario
/code/__DEFINES/chat.dm @Zandario
/code/__DEFINES/tgui.dm @Zandario
/code/controllers/subsystem/chat.dm @Zandario
/code/controllers/subsystem/ping.dm @Zandario
/code/controllers/subsystem/tgui.dm @Zandario
/code/modules/tgchat @Zandario
/code/modules/tgui @Zandario
/code/modules/tgui_panel @Zandario
/tgui @Zandario

View File

@@ -6,7 +6,7 @@ about: Create a report to help reproduce and fix the issue
## Round ID:
<!--- **INCLUDE THE ROUND ID**
If you discovered this issue from playing tgstation hosted servers:
If you discovered this issue from playing Citadel hosted servers:
[Round ID]: # (It can be found in the Status panel or retrieved from https://atlantaned.space/statbus/round.php ! The round id let's us look up valuable information and logs for the round the bug happened.)-->
## Testmerges:

19
.github/guides/DOWNLOADING.md vendored Normal file
View File

@@ -0,0 +1,19 @@
## DOWNLOADING
There are a number of ways to download the source code. Some are described here.
Option 1: The more complicated and easier to update method is using git.
You'll need to download git or some client from [here](http://git-scm.com/).
When that's installed, right click in any folder and click on "Git Bash".
When that opens, type in:
```
git clone https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
```
(hint: hold down ctrl and press insert to paste into git bash)
This will take a while to download, but it provides an easier method for updating.
Option 2: Download the source code as a zip by clicking the ZIP button in the
code tab of <https://github.com/Citadel-Station-13/Citadel-Station-13-RP>
(note: this will use a lot of bandwidth if you wish to update and is a lot of
hassle if you want to make any changes at all, so it's not recommended.)

View File

@@ -18,6 +18,14 @@ jobs:
with:
path: $HOME/SpacemanDMM
key: ${{ runner.os }}-spacemandmm
- name: Restore Yarn cache
uses: actions/cache@v2
with:
path: $HOME/tgui/.yarn/cache
key: ${{ runner.os }}-yarn-${{ hashFiles('tgui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-
${{ runner.os }}-
- name: Install Tools
run: |
pip3 install setuptools
@@ -28,11 +36,9 @@ jobs:
run: |
bash tools/ci/check_filedirs.sh vorestation.dme
bash tools/ci/check_changelogs.sh
find . -name "*.php" -print0 | xargs -0 -n1 php -l
find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
tgui/bin/tgui --lint
tgui/bin/tgui --test
bash tools/ci/check_grep.sh
bash tools/ci/check_misc.sh
tools/build/build --ci lint tgui-test
tools/bootstrap/python -m dmi.test
tools/bootstrap/python -m mapmerge2.dmm_test
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
@@ -57,10 +63,7 @@ jobs:
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
python3 tools/ci/template_dm_generator.py
tools/build/build
env:
CBT_BUILD_MODE : ALL_MAPS
tools/build/build --ci dm -DCIBUILDING -DCITESTING -DALL_MAPS
run_all_tests:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
@@ -76,7 +79,7 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v2
- name: Setup cache
- name: Restore BYOND cache
uses: actions/cache@v2
with:
path: $HOME/BYOND
@@ -98,7 +101,7 @@ jobs:
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
tools/build/build
tools/build/build --ci dm -DCIBUILDING
bash tools/ci/run_server.sh
env:
CBT_BUILD_MODE: TEST_RUN
@@ -109,6 +112,14 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Restore Yarn cache
uses: actions/cache@v2
with:
path: $HOME/tgui/.yarn/cache
key: ${{ runner.os }}-yarn-${{ hashFiles('tgui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-
${{ runner.os }}-
- name: Compile
run: pwsh tools/ci/build.ps1
env:

View File

@@ -36,7 +36,7 @@ jobs:
- name: "Compile"
if: steps.value_holder.outputs.CL_ENABLED
run: |
python tools/ss13_genchangelog.py html/changelog.html html/changelogs
python tools/ss13_genchangelog.py html/changelogs.html html/changelogs
- name: "Convert Lineendings"
if: steps.value_holder.outputs.CL_ENABLED
run: |

6
.gitignore vendored
View File

@@ -12,8 +12,11 @@
#Ignore compiled files and other files generated during compilation.
*.mdme
*.mdme.*
*.dmb
*.rsc
*.m.dme
*.test.dme
*.lk
*.int
*.backup
@@ -193,3 +196,6 @@ Temporary Items
/tools/LinuxOneShot/TGS_Config
/tools/LinuxOneShot/TGS_Instances
/tools/LinuxOneShot/TGS_Logs
# Autowiki
/tools/autowiki/node_modules

37
.vscode/launch.json vendored
View File

@@ -1,21 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "byond",
"request": "launch",
"name": "Launch DreamSeeker",
"preLaunchTask": "Build All",
"dmb": "${workspaceFolder}/${command:CurrentDMB}"
},
{
"type": "byond",
"request": "launch",
"name": "Launch DreamDaemon",
"preLaunchTask": "Build All",
"dmb": "${workspaceFolder}/${command:CurrentDMB}",
"dreamDaemon": true
}
]
"version": "0.2.0",
"configurations": [
{
"type": "byond",
"request": "launch",
"name": "Launch DreamSeeker",
"preLaunchTask": "Build All",
"dmb": "${workspaceFolder}/${command:CurrentDMB}"
},
{
"type": "byond",
"request": "launch",
"name": "Launch DreamDaemon",
"preLaunchTask": "Build All",
"dmb": "${workspaceFolder}/${command:CurrentDMB}",
"dreamDaemon": true
}
]
}

View File

@@ -16,6 +16,7 @@
"*.dmi": "imagePreview.previewEditor"
},
"files.eol": "\n",
"files.insertFinalNewline": true,
"gitlens.advanced.blame.customArguments": ["-w"],
"tgstationTestExplorer.project.resultsType": "json",
"[javascript]": {

51
.vscode/tasks.json vendored
View File

@@ -26,18 +26,23 @@
},
{
"type": "dreammaker",
"dme": "vorestation.dme",
"dme": "tgstation.dme",
"problemMatcher": [
"$dreammaker"
],
"group": "build",
"label": "dm: build - vorestation.dme"
"label": "dm: build - tgstation.dme"
},
{
"command": "${command:dreammaker.reparse}",
"group": "build",
"label": "dm: reparse"
},
{
"type": "shell",
"command": "tgui/bin/tgui",
"command": "bin/tgui-build",
"windows": {
"command": ".\\tgui\\bin\\tgui.bat"
"command": ".\\bin\\tgui-build.cmd"
},
"problemMatcher": [
"$tsc",
@@ -47,9 +52,43 @@
"label": "tgui: build"
},
{
"command": "${command:dreammaker.reparse}",
"type": "shell",
"command": "bin/tgui-dev",
"windows": {
"command": ".\\bin\\tgui-dev.cmd"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
"group": "build",
"label": "dm: reparse"
"label": "tgui: dev server"
},
{
"type": "shell",
"command": "bin/tgui-bench",
"windows": {
"command": ".\\bin\\tgui-bench.cmd"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
"group": "build",
"label": "tgui: bench"
},
{
"type": "shell",
"command": "bin/tgui-sonar",
"windows": {
"command": ".\\bin\\tgui-sonar.cmd"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
"group": "build",
"label": "tgui: sonar"
}
]
}

2
BUILD.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\tools\build\build.bat" --wait-on-error build %*

View File

@@ -1,7 +1,7 @@
Polaris
Copyright (C) 2010-2015 Polaris, Baystation12, and tgstation13.
CitadelRP
Copyright (C) 2010-2022 Virgo, Polaris, Baystation12, and tgstation13.
Polaris is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
CitadelRP is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
All commits whose authorship dates are not prior to `1420675200 +0000` are assumed to be licensed under AGPL v3, if you wish to license under GPL v3 please make this clear in the commit message and any added files.

View File

@@ -15,32 +15,27 @@
* **Wiki:** <https://citadel-station.net/wiki/index.php?title=Main_Page>
* **Forums:** <http://citadel-station.net/forum>
* **Ban Appeals:** <http://citadel-station.net/forum/forumdisplay.php?fid=8>
* **Discord:** <https://discord.gg/E6SQuhz>
* **Discord:** <https://discord.gg/citadelstation>
Going to make a Pull Request? Make sure you read the [CONTRIBUTING.md](.github/CONTRIBUTING.md) first!
Citadel Station 13 - RP was originally a fork of VOREStation, which separated on 01/25/2019. VOREStation is a fork of the Polaris code branch, itself a fork of the Baystation12 code branch, for the game Space Station 13.
## DOWNLOADING
[Downloading](.github/DOWNLOADING.md)
There are a number of ways to download the source code. Some are described here.
Option 1: The more complicated and easier to update method is using git.
You'll need to download git or some client from [here](http://git-scm.com/).
When that's installed, right click in any folder and click on "Git Bash".
When that opens, type in:
## :exclamation: How to compile :exclamation:
```
git clone https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
```
On **2021-01-04** we have changed the way to compile the codebase.
(hint: hold down ctrl and press insert to paste into git bash)
This will take a while to download, but it provides an easier method for updating.
**The quick way**. Find `bin/server.cmd` in this folder and double click it to automatically build and host the server on port 1337.
Option 2: Download the source code as a zip by clicking the ZIP button in the
code tab of <https://github.com/Citadel-Station-13/Citadel-Station-13-RP>
(note: this will use a lot of bandwidth if you wish to update and is a lot of
hassle if you want to make any changes at all, so it's not recommended.)
**The long way**. Find `bin/build.cmd` in this folder, and double click it to initiate the build. It consists of multiple steps and might take around 1-5 minutes to compile. If it closes, it means it has finished its job. You can then [setup the server](.github/RUNNING_A_SERVER.md) normally by opening `tgstation.dmb` in DreamDaemon.
**Building CitadelRP in DreamMaker directly is now deprecated and might produce errors**, such as `'tgui.bundle.js': cannot find file`.
**[How to compile in VSCode and other build options](tools/build/README.md)
## INSTALLATION

2
bin/build.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error build %*

2
bin/clean.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error clean-all %*

2
bin/server.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error server %*

2
bin/test.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error dm-test %*

3
bin/tgui-bench.cmd Normal file
View File

@@ -0,0 +1,3 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-bench %*
pause

2
bin/tgui-build.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui tgui-lint tgui-test %*

2
bin/tgui-dev.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-dev %*

2
bin/tgui-sonar.cmd Normal file
View File

@@ -0,0 +1,2 @@
@echo off
call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-sonar %*

View File

@@ -1,8 +1,9 @@
/*!
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
/**
*! Copyright (c) 2020 Aleksej Komarov
*! SPDX-License-Identifier: MIT
*/
//! ## Message Types
#define MESSAGE_TYPE_SYSTEM "system"
#define MESSAGE_TYPE_LOCALCHAT "localchat"
#define MESSAGE_TYPE_RADIO "radio"
@@ -19,7 +20,7 @@
#define MESSAGE_TYPE_ATTACKLOG "attacklog"
#define MESSAGE_TYPE_DEBUG "debug"
//debug printing macros (for development and testing)
//! ## Debug printing macros (for development and testing)
/// Used for debug messages to the world
#define debug_world(msg) if (GLOB.Debug2) to_chat(world, \
type = MESSAGE_TYPE_DEBUG, \

View File

@@ -159,13 +159,14 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_PING 5
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_NIGHTSHIFT 6
#define FIRE_PRIORITY_PLANTS 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
#define FIRE_PRIORITY_PING 10
#define FIRE_PRIORITY_VIS 10
#define FIRE_PRIORITY_SERVER_MAINT 10
#define FIRE_PRIORITY_GARBAGE 15

25
code/__DEFINES/fonts.dm Normal file
View File

@@ -0,0 +1,25 @@
//FONTS: Used by Paper, PhotoCopier, PDA's Notekeeper, NewsCaster, NewsPaper, ModularComputers (and PaperBin once a year).
/// Font used by regular pens
#define PEN_FONT "Verdana"
/// Font used by fancy pens
#define FOUNTAIN_PEN_FONT "Segoe Script"
/// Font used by crayons
#define CRAYON_FONT "Comic Sans MS"
/// Font used by printers
#define PRINTER_FONT "Times New Roman"
/// Font used when a player signs their name
#define SIGNFONT "Times New Roman"
/// Font used by charcoal pens
#define CHARCOAL_FONT "Candara"
//pda fonts
#define MONO "Monospaced"
#define VT "VT323"
#define ORBITRON "Orbitron"
#define SHARE "Share Tech Mono"
////GLOBAL_LIST_INIT(pda_styles, sort_list(list(MONO, VT, ORBITRON, SHARE)))
/// Emoji icon set
#define EMOJI_SET 'icons/ui_icons/emoji/emoji.dmi'
#define EMOJI_SET32 'icons/emoji_32.dmi'

59
code/__DEFINES/text.dm Normal file
View File

@@ -0,0 +1,59 @@
/*
/// Does 4 spaces. Used as a makeshift tabulator.
#define FOURSPACES "&nbsp;&nbsp;&nbsp;&nbsp;"
/// Prepares a text to be used for maptext. Use this so it doesn't look hideous.
#define MAPTEXT(text) {"<span class='maptext'>[##text]</span>"}
/// Macro from Lummox used to get height from a MeasureText proc
#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1))
*/
/// Removes characters incompatible with file names.
#define SANITIZE_FILENAME(text) (GLOB.filename_forbidden_chars.Replace(text, ""))
/*
/// Simply removes the < and > characters, and limits the length of the message.
#define STRIP_HTML_SIMPLE(text, limit) (GLOB.angular_brackets.Replace(copytext(text, 1, limit), ""))
///Index access defines for paper/var/add_info_style
#define ADD_INFO_COLOR 1
#define ADD_INFO_FONT 2
#define ADD_INFO_SIGN 3
///Adds a html style to a text string. Hacky, but that's how inputted text appear on paper sheets after going through the UI.
#define PAPER_MARK_TEXT(text, color, font) "<span style=\"color:[color];font-family:'[font]';\">[text]</span>\n \n"
/// Folder directory for strings
#define STRING_DIRECTORY "strings"
// JSON text files found in the tgstation/strings folder
/// File location for brain damage traumas
#define BRAIN_DAMAGE_FILE "traumas.json"
/// File location for AI ion laws
#define ION_FILE "ion_laws.json"
/// File location for pirate names
#define PIRATE_NAMES_FILE "pirates.json"
/// File location for redpill questions
#define REDPILL_FILE "redpill.json"
/// File location for arcade names
#define ARCADE_FILE "arcade.json"
/// File location for boomer meme catchphrases
#define BOOMER_FILE "boomer.json"
/// File location for locations on the station
#define LOCATIONS_FILE "locations.json"
/// File location for wanted posters messages
#define WANTED_FILE "wanted_message.json"
/// File location for really dumb suggestions memes
#define VISTA_FILE "steve.json"
/// File location for flesh wound descriptions
#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json"
/// File location for bone wound descriptions
#define BONE_SCAR_FILE "wounds/bone_scar_desc.json"
/// File location for scar wound descriptions
#define SCAR_LOC_FILE "wounds/scar_loc.json"
/// File location for exodrone descriptions
#define EXODRONE_FILE "exodrone.json"
/// File location for clown honk descriptions
#define CLOWN_NONSENSE_FILE "clown_nonsense.json"
/// File location for cult shuttle curse descriptions
#define CULT_SHUTTLE_CURSE "cult_shuttle_curse.json"
*/

View File

@@ -348,29 +348,29 @@
/world/proc/TgsChatChannelInfo()
return
/*
The MIT License
Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* The MIT License
*
*! Copyright (c) 2017 Jordan Brown
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to
* deal in the Software without restriction, including
* without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom
* the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

View File

@@ -78,10 +78,11 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
var/time_clock = num2hex(TICK_DELTA_TO_MS(world.tick_usage), 3)
return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}"
// \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
// If it ever becomes necesary to get a more performant REF(), this lies here in wait
// #define REF(thing) (thing && istype(thing, /datum) && (thing:datum_flags & DF_USE_TAG) && thing:tag ? "[thing:tag]" : REF(thing))
/**
* \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
* If it ever becomes necesary to get a more performant REF(), this lies here in wait
* #define REF(thing) (thing && istype(thing, /datum) && (thing:datum_flags & DF_USE_TAG) && thing:tag ? "[thing:tag]" : "\ref[thing]")
**/
/proc/REF(input)
if(istype(input, /datum))
var/datum/thing = input

View File

@@ -560,3 +560,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
var/charcount = count - length_char(text)
var/list/chars_to_add[max(charcount + 1, 0)]
return text + jointext(chars_to_add, char)
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
/proc/sanitize_css_class_name(name)
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
return replacetext(name, regex, "")

View File

@@ -1,2 +1,19 @@
//These are a bunch of regex datums for use /((any|every|no|some|head|foot)where(wolf)?\sand\s)+(\.[\.\s]+\s?where\?)?/i
GLOBAL_DATUM_INIT(is_http_protocol, /regex, regex("^https?://"))
GLOBAL_DATUM_INIT(is_website, /regex, regex("http|www.|\[a-z0-9_-]+.(com|org|net|mil|edu)+", "i"))
GLOBAL_DATUM_INIT(is_email, /regex, regex("\[a-z0-9_-]+@\[a-z0-9_-]+.\[a-z0-9_-]+", "i"))
GLOBAL_DATUM_INIT(is_alphanumeric, /regex, regex("\[a-z0-9]+", "i"))
GLOBAL_DATUM_INIT(is_punctuation, /regex, regex("\[.!?]+", "i"))
GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$"))
//finds text strings recognized as links on discord. Mainly used to stop embedding.
GLOBAL_DATUM_INIT(has_discord_embeddable_links, /regex, regex("(https?://\[^\\s|<\]{2,})"))
//All < and > characters
GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g"))
//All characters forbidden by filenames: ", \, \n, \t, /, ?, %, *, :, |, <, >, ..
GLOBAL_DATUM_INIT(filename_forbidden_chars, /regex, regex(@{""|[\\\n\t/?%*:|<>]|\.\."}, "g"))
GLOBAL_PROTECT(filename_forbidden_chars)
// had to use the OR operator for quotes instead of putting them in the character class because it breaks the syntax highlighting otherwise.

2
code/_globalvars/tgui.dm Normal file
View File

@@ -0,0 +1,2 @@
//GLOBAL_DATUM(crew_manifest_tgui, /datum/crew_manifest)
GLOBAL_DATUM(changelog_tgui, /datum/changelog)

View File

@@ -1,11 +1,11 @@
//this function places received data into element with specified id.
var/const/js_byjax = {"
#define js_byjax {"
function replaceContent() {
var args = Array.prototype.slice.call(arguments);
var id = args\[0\];
var content = args\[1\];
var callback = null;
var callback = null;
if(args\[2\]){
callback = args\[2\];
if(args\[3\]){
@@ -34,7 +34,7 @@ callback_args - arguments for callback function
Be sure to include required js functions in your page, or it'll raise an exception.
*/
proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null)
/proc/send_byjax(receiver, control_id, target_element, new_content=null, callback=null, list/callback_args=null)
if(receiver && target_element && control_id) // && winexists(receiver, control_id))
var/list/argums = list(target_element, new_content)
if(callback)
@@ -42,9 +42,6 @@ proc/send_byjax(receiver, control_id, target_element, new_content=null, callback
if(callback_args)
argums += callback_args
argums = list2params(argums)
/* if(callback_args)
argums += "&[list2params(callback_args)]"
*/
receiver << output(argums,"[control_id]:replaceContent")
return

37
code/_js/menus.dm Normal file
View File

@@ -0,0 +1,37 @@
#define js_dropdowns {"
function dropdowns() {
var divs = document.getElementsByTagName('div');
var headers = new Array();
var links = new Array();
for(var i=0;i<divs.length;i++){
if(divs\[i\].className=='header') {
divs\[i\].className='header closed';
divs\[i\].innerHTML = divs\[i\].innerHTML+' +';
headers.push(divs\[i\]);
}
if(divs\[i\].className=='links') {
divs\[i\].className='links hidden';
links.push(divs\[i\]);
}
}
for(var i=0;i<headers.length;i++){
if(typeof(links\[i\])!== 'undefined' && links\[i\]!=null) {
headers\[i\].onclick = (function(elem) {
return function() {
if(elem.className.search('visible')>=0) {
elem.className = elem.className.replace('visible','hidden');
this.className = this.className.replace('open','closed');
this.innerHTML = this.innerHTML.replace('-','+');
}
else {
elem.className = elem.className.replace('hidden','visible');
this.className = this.className.replace('closed','open');
this.innerHTML = this.innerHTML.replace('+','-');
}
return false;
}
})(links\[i\]);
}
}
}
"}

View File

@@ -40,3 +40,6 @@
config_entry_value = "<br><small><a href='https://discord.gg/citadelstation'>Roleplay focused 18+ server with extensive species choices.</a></small></br>"
/datum/config_entry/flag/usetaglinestrings
/datum/config_entry/flag/cache_assets
default = TRUE

View File

@@ -9,3 +9,11 @@
/datum/config_entry/number/lobby_gamemode_vote_delay
config_entry_value = 120
min_val = -1 //-1 for disabled
/// if the game appears on the hub or not
/datum/config_entry/flag/hub
/datum/config_entry/number/max_hub_pop //At what pop to take hub off the server
config_entry_value = 0 //0 means disabled
integer = TRUE
min_val = 0

View File

@@ -1,36 +1,93 @@
/datum/controller/subsystem
// Metadata; you should define these.
name = "fire coderbus" //name of the subsystem
var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Can be decimal and negative values.
var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep
var/flags = 0 //see MC.dm in __DEFINES Most flags must be set on world start to take full effect. (You can also restart the mc to force them to process again)
var/subsystem_initialized = FALSE //set to TRUE after it has been initialized, will obviously never be set if the subsystem doesn't initialize
var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
/// Name of the subsystem - you must change this
name = "fire coderbus"
//set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
// use the SS_NO_FIRE flag instead for systems that never fire to keep it from even being added to the list
/// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file.
var/init_order = INIT_ORDER_DEFAULT
/// Time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/wait = 20
/// Priority Weight: When mutiple subsystems need to run in the same tick, higher priority subsystems will be given a higher share of the tick before MC_TICK_CHECK triggers a sleep, higher priority subsystems also run before lower priority subsystems
var/priority = FIRE_PRIORITY_DEFAULT
/// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again)
var/flags = NONE
/// Which stage does this subsystem init at. Earlier stages can fire while later stages init.
//var/init_stage = INITSTAGE_MAIN
/// This var is set to TRUE after the subsystem has been initialized.
var/initialized = FALSE
/// Set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
/// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick
var/can_fire = TRUE
// Bookkeeping variables; probably shouldn't mess with these.
var/last_fire = 0 //last world.time we called fire()
var/next_fire = 0 //scheduled world.time for next fire()
var/cost = 0 //average time to execute
var/tick_usage = 0 //average tick usage
var/tick_overrun = 0 //average tick overrun
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
var/paused_ticks = 0 //ticks this ss is taking to run right now.
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
var/ticks = 1 //how many ticks does this ss take to run on avg.
var/times_fired = 0 //number of times we have called fire()
var/queued_time = 0 //time we entered the queue, (for timing and priority reasons)
var/queued_priority //we keep a running total to make the math easier, if priority changes mid-fire that would break our running total, so we store it here
//linked list stuff for the queue
///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details.
var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
/*
* The following variables are managed by the MC and should not be modified directly.
*/
/// Last world.time the subsystem completed a run (as in wasn't paused by [MC_TICK_CHECK])
var/last_fire = 0
/// Scheduled world.time for next fire()
var/next_fire = 0
/// Running average of the amount of milliseconds it takes the subsystem to complete a run (including all resumes but not the time spent paused)
var/cost = 0
/// Running average of the amount of tick usage in percents of a tick it takes the subsystem to complete a run
var/tick_usage = 0
/// Running average of the amount of tick usage (in percents of a game tick) the subsystem has spent past its allocated time without pausing
var/tick_overrun = 0
/// How much of a tick (in percents of a tick) were we allocated last fire.
var/tick_allocation_last = 0
/// How much of a tick (in percents of a tick) do we get allocated by the mc on avg.
var/tick_allocation_avg = 0
/// Tracks the current execution state of the subsystem. Used to handle subsystems that sleep in fire so the mc doesn't run them again while they are sleeping
var/state = SS_IDLE
/// Tracks how many fires the subsystem has consecutively paused on in the current run
var/paused_ticks = 0
/// Tracks how much of a tick the subsystem has consumed in the current run
var/paused_tick_usage
/// Tracks how many fires the subsystem takes to complete a run on average.
var/ticks = 1
/// Tracks the amount of completed runs for the subsystem
var/times_fired = 0
/// How many fires have we been requested to postpone
var/postponed_fires = 0
/// Time the subsystem entered the queue, (for timing and priority reasons)
var/queued_time = 0
/// Priority at the time the subsystem entered the queue. Needed to avoid changes in priority (by admins and the like) from breaking things.
var/queued_priority
/// How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
var/static/list/failure_strikes
/// Next subsystem in the queue of subsystems to run this tick
var/datum/controller/subsystem/queue_next
/// Previous subsystem in the queue of subsystems to run this tick
var/datum/controller/subsystem/queue_prev
var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out!
//Do not blindly add vars here to the bottom, put it where it goes above
//If your var only has two values, put it in as a flag.
//Do not override
///datum/controller/subsystem/New()
@@ -41,9 +98,15 @@
/datum/controller/subsystem/proc/PreInit()
return
//This is used so the mc knows when the subsystem sleeps. do not override.
/// This is used so the mc knows when the subsystem sleeps. do not override.
/datum/controller/subsystem/proc/ignite(resumed = 0)
set waitfor = 0
SHOULD_NOT_OVERRIDE(TRUE)
set waitfor = FALSE
. = SS_IDLE
tick_allocation_last = Master.current_ticklimit-(TICK_USAGE)
tick_allocation_avg = MC_AVERAGE(tick_allocation_avg, tick_allocation_last)
. = SS_SLEEPING
fire(resumed)
. = state
@@ -60,13 +123,14 @@
//Sleeping in here prevents future fires until returned.
/datum/controller/subsystem/proc/fire(resumed = 0)
flags |= SS_NO_FIRE
throw EXCEPTION("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
CRASH("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
/datum/controller/subsystem/Destroy()
dequeue()
can_fire = 0
flags |= SS_NO_FIRE
Master.subsystems -= src
if (Master)
Master.subsystems -= src
return ..()
//Queue it to run.
@@ -160,7 +224,7 @@
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
subsystem_initialized = TRUE
initialized = TRUE
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
to_chat(world, "<span class='boldannounce'>[msg]</span>")

View File

@@ -2,7 +2,7 @@ SUBSYSTEM_DEF(assets)
name = "Assets"
init_order = INIT_ORDER_ASSETS
flags = SS_NO_FIRE
var/list/cache = list()
var/list/datum/asset_cache_item/cache = list()
var/list/preload = list()
var/datum/asset_transport/transport = new()
@@ -31,3 +31,7 @@ SUBSYSTEM_DEF(assets)
transport.Initialize(cache)
..()
/datum/controller/subsystem/assets/Recover()
cache = SSassets.cache
preload = SSassets.preload

View File

@@ -17,15 +17,15 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/Initialize(timeofday)
//GLOB.fire_overlay.appearance_flags = RESET_COLOR
//setupGenetics() //to set the mutations' sequence
subsystem_initialized = INITIALIZATION_INNEW_MAPLOAD
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
return ..()
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms)
if(subsystem_initialized == INITIALIZATION_INSSATOMS)
if(initialized == INITIALIZATION_INSSATOMS)
return
subsystem_initialized = INITIALIZATION_INNEW_MAPLOAD
initialized = INITIALIZATION_INNEW_MAPLOAD
LAZYINITLIST(late_loaders)
@@ -49,7 +49,7 @@ SUBSYSTEM_DEF(atoms)
testing("Initialized [count] atoms")
pass(count)
subsystem_initialized = INITIALIZATION_INNEW_REGULAR
initialized = INITIALIZATION_INNEW_REGULAR
if(late_loaders.len)
for(var/I in late_loaders)
@@ -94,15 +94,15 @@ SUBSYSTEM_DEF(atoms)
return qdeleted || QDELING(A)
/datum/controller/subsystem/atoms/proc/map_loader_begin()
old_subsystem_initialized = subsystem_initialized
subsystem_initialized = INITIALIZATION_INSSATOMS
old_subsystem_initialized = initialized
initialized = INITIALIZATION_INSSATOMS
/datum/controller/subsystem/atoms/proc/map_loader_stop()
subsystem_initialized = old_subsystem_initialized
initialized = old_subsystem_initialized
/datum/controller/subsystem/atoms/Recover()
subsystem_initialized = SSatoms.subsystem_initialized
if(subsystem_initialized == INITIALIZATION_INNEW_MAPLOAD)
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
old_subsystem_initialized = SSatoms.old_subsystem_initialized
BadInitializeCalls = SSatoms.BadInitializeCalls

View File

@@ -1,6 +1,6 @@
/**
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*! Copyright (c) 2020 Aleksej Komarov
*! SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(chat)

View File

@@ -21,7 +21,7 @@ SUBSYSTEM_DEF(input)
/datum/controller/subsystem/input/Initialize()
setup_macrosets()
subsystem_initialized = TRUE
initialized = TRUE
refresh_client_macro_sets()

View File

@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(lighting)
return ..()
/datum/controller/subsystem/lighting/Initialize(timeofday)
if(!subsystem_initialized)
if(!initialized)
if (CONFIG_GET(number/starlight))
for(var/I in GLOB.sortedAreas)
var/area/A = I
@@ -21,7 +21,7 @@ SUBSYSTEM_DEF(lighting)
A.luminosity = 0
create_all_lighting_objects()
subsystem_initialized = TRUE
initialized = TRUE
fire(FALSE, TRUE)
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
MC_SPLIT_TICK_INIT(3)
var/i = 0
// why do we split logic?
// because here on citrp, code standards like "don't delete shit during init" is often not enforced
// meaning the subsystem will crash out of this loop if something is deleted mid-process, which can happen if CHECK_TICK is running in init
@@ -99,5 +99,5 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Recover()
subsystem_initialized = SSlighting.subsystem_initialized
initialized = SSlighting.initialized
..()

View File

@@ -45,7 +45,7 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/Initialize(timeofday)
HACK_LoadMapConfig()
if(subsystem_initialized)
if(initialized)
return
if(config.defaulted)
var/old_config = config
@@ -197,7 +197,7 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
if(clearing_reserved_turfs || !subsystem_initialized) //in either case this is just not needed.
if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
return
clearing_reserved_turfs = TRUE
// SSshuttle.transit_requesters.Cut()
@@ -286,7 +286,7 @@ SUBSYSTEM_DEF(mapping)
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
UNTIL(subsystem_initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things.
UNTIL(initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things.
for(var/i in turf_reservations)
var/datum/turf_reservation/TR = i
if(!QDELETED(TR))

View File

@@ -17,7 +17,7 @@ SUBSYSTEM_DEF(overlays)
stats = list()
/datum/controller/subsystem/overlays/Initialize()
subsystem_initialized = TRUE
initialized = TRUE
fire(mc_check = FALSE)
..()

View File

@@ -14,6 +14,6 @@ SUBSYSTEM_DEF(overmaps)
H.get_known_sectors()
/datum/controller/subsystem/overmaps/proc/queue_helm_computer_rebuild()
if(!subsystem_initialized)
if(!initialized)
return
addtimer(CALLBACK(src, .proc/rebuild_helm_computers), 0, TIMER_UNIQUE)

View File

@@ -0,0 +1,39 @@
/**
*! Copyright (c) 2022 Aleksej Komarov
*! SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(ping)
name = "Ping"
priority = FIRE_PRIORITY_PING
wait = 4 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
/datum/controller/subsystem/ping/stat_entry()
..("P:[GLOB.clients.len]")
/datum/controller/subsystem/ping/fire(resumed = FALSE)
// Prepare the new batch of clients
if (!resumed)
src.currentrun = GLOB.clients.Copy()
// De-reference the list for sanic speeds
var/list/currentrun = src.currentrun
while (currentrun.len)
var/client/client = currentrun[currentrun.len]
currentrun.len--
if (client?.tgui_panel?.is_ready())
// Send a soft ping
client.tgui_panel.window.send_message("ping/soft", list(
// Slightly less than the subsystem timer (somewhat arbitrary)
// to prevent incoming pings from resetting the afk state
"afk" = client.is_afk(3.5 SECONDS),
))
if (MC_TICK_CHECK)
return

View File

@@ -84,4 +84,15 @@ SUBSYSTEM_DEF(server_maint)
SSblackbox.record_feedback("text", "server_tools", 1, tgsversion)
*/
/datum/controller/subsystem/server_maint/proc/UpdateHubStatus()
if(!CONFIG_GET(flag/hub) || !CONFIG_GET(number/max_hub_pop))
return FALSE //no point, hub / auto hub controls are disabled
var/max_pop = CONFIG_GET(number/max_hub_pop)
if(GLOB.clients.len > max_pop)
world.update_hub_visibility(FALSE)
else
world.update_hub_visibility(TRUE)
#undef PING_BUFFER_TIME

View File

@@ -1,10 +1,13 @@
/**
*! Copyright (c) 2020 Aleksej Komarov
*! SPDX-License-Identifier: MIT
*/
/**
* tgui subsystem
*
* Contains all tgui state and subsystem code.
*
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(tgui)
@@ -25,6 +28,10 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui/public/tgui.html')
// Inject inline polyfills
var/polyfill = file2text('tgui/public/tgui-polyfill.min.js')
polyfill = "<script>\n[polyfill]\n</script>"
basehtml = replacetextEx(basehtml, "<!-- tgui:inline-polyfill -->", polyfill)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()

View File

@@ -0,0 +1,32 @@
/datum/changelog
var/static/list/changelog_items = list()
/datum/changelog/ui_state()
return GLOB.always_state
/datum/changelog/ui_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/ui_act(action, list/params, datum/tgui/ui, datum/ui_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/ui_static_data()
var/list/data = list( "dates" = list() )
var/regex/ymlRegex = regex(@"\.yml", "g")
for(var/archive_file in flist("[global.config.directory]/../html/changelogs/archive/"))
var/archive_date = ymlRegex.Replace(archive_file, "")
data["dates"] = list(archive_date) + data["dates"]
return data

View File

@@ -1,13 +1,13 @@
/*!
This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
Variables:
amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
max_amount - max raw amount of mineral this container can hold.
sheet_type - type of the mineral sheet the container handles, used for output.
parent - object that this container is being used by, used for output.
MAX_STACK_SIZE - size of a stack of mineral sheets. Constant.
*/
/**
*! This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
*
** Variables:
** - amount - Raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
** - max_amount - Max raw amount of mineral this container can hold.
** - sheet_type - Type of the mineral sheet the container handles, used for output.
** - parent - Object that this container is being used by, used for output.
** - MAX_STACK_SIZE - Size of a stack of mineral sheets. Constant.
*/
/datum/component/material_container
var/total_amount = 0
@@ -137,7 +137,7 @@
return primary_mat
/// Proc for putting a stack inside of the container
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
if(isnull(amt))
amt = S.amount
@@ -160,7 +160,7 @@
return amt
/// For inserting an amount of material
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
if(!istype(mat))
mat = getmaterialref(mat)
if(amt > 0 && has_space(amt))
@@ -175,7 +175,7 @@
return FALSE
/// Uses an amount of a specific material, effectively removing it.
/datum/component/material_container/proc/use_amount_mat(amt, var/datum/material/mat)
/datum/component/material_container/proc/use_amount_mat(amt, var/datum/material/mat)
if(!istype(mat))
mat = getmaterialref(mat)
var/amount = materials[mat]
@@ -187,7 +187,7 @@
return FALSE
/// Proc for transfering materials to another container.
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, var/datum/material/mat)
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, var/datum/material/mat)
if(!istype(mat))
mat = getmaterialref(mat)
if((amt==0)||(!T)||(!mat))
@@ -216,7 +216,7 @@
/datum/component/material_container/proc/use_materials(list/mats, multiplier=1)
if(!mats || !length(mats))
return FALSE
var/list/mats_to_remove = list() //Assoc list MAT | AMOUNT
for(var/x in mats) //Loop through all required materials
@@ -230,7 +230,7 @@
return FALSE //Can't afford it
mats_to_remove[req_mat] += amount_required //Add it to the assoc list of things to remove
continue
var/total_amount_save = total_amount
for(var/i in mats_to_remove)
@@ -239,7 +239,7 @@
return total_amount_save - total_amount
/// For spawning mineral sheets at a specific location. Used by machines to output sheets.
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, var/datum/material/M, target = null)
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, var/datum/material/M, target = null)
if(!M.sheet_type)
return 0 //Add greyscale sheet handling here later
if(sheet_amt <= 0)
@@ -263,7 +263,7 @@
/// Proc to get all the materials and dump them as sheets
/datum/component/material_container/proc/retrieve_all(target = null)
/datum/component/material_container/proc/retrieve_all(target = null)
var/result = 0
for(var/MAT in materials)
var/amount = materials[MAT]
@@ -297,7 +297,7 @@
return TRUE
/// Returns all the categories in a recipe.
/datum/component/material_container/proc/get_categories(list/mats)
/datum/component/material_container/proc/get_categories(list/mats)
var/list/categories = list()
for(var/x in mats) //Loop through all required materials
if(!istext(x)) //This means its not a category
@@ -307,12 +307,12 @@
/// Returns TRUE if you have enough of the specified material.
/datum/component/material_container/proc/has_enough_of_material(var/datum/material/req_mat, amount, multiplier=1)
/datum/component/material_container/proc/has_enough_of_material(var/datum/material/req_mat, amount, multiplier=1)
if(!materials[req_mat]) //Do we have the resource?
return FALSE //Can't afford it
var/amount_required = amount * multiplier
if(materials[req_mat] >= amount_required) // do we have enough of the resource?
return TRUE
return TRUE
return FALSE //Can't afford it
/// Returns TRUE if you have enough of a specified material category (Which could be multiple materials)
@@ -324,7 +324,7 @@
return FALSE
/// Turns a material amount into the amount of sheets it should output
/datum/component/material_container/proc/amount2sheet(amt)
/datum/component/material_container/proc/amount2sheet(amt)
if(amt >= MINERAL_MATERIAL_AMOUNT)
return round(amt / MINERAL_MATERIAL_AMOUNT)
return FALSE
@@ -346,7 +346,7 @@
return material_amount
/// Returns the amount of a specific material in this container.
/datum/component/material_container/proc/get_material_amount(var/datum/material/mat)
/datum/component/material_container/proc/get_material_amount(var/datum/material/mat)
if(!istype(mat))
mat = getmaterialref(mat)
return(materials[mat])

View File

@@ -134,7 +134,7 @@
if(datum_flags & DF_USE_TAG)
GenerateTag()
var/do_initialize = SSatoms.subsystem_initialized
var/do_initialize = SSatoms.initialized
if(do_initialize != INITIALIZATION_INSSATOMS)
args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD
if(SSatoms.InitAtom(src, args))

View File

@@ -141,7 +141,7 @@ GLOBAL_LIST_INIT(multiz_hole_baseturfs, typecacheof(list(
air_master.mark_for_update(src)
// restore lighting
if(SSlighting.subsystem_initialized)
if(SSlighting.initialized)
recalc_atom_opacity()
lighting_object = old_lighting_object
affecting_lights = old_affecting_lights

View File

@@ -206,7 +206,8 @@ GLOBAL_REAL_VAR(world_log_redirected) = FALSE
start_log(GLOB.tgui_log)
start_log(GLOB.subsystem_log)
GLOB.changelog_hash = md5('html/changelog.html') //for telling if the changelog has changed recently
var/latest_changelog = file("[global.config.directory]/../html/changelogs/archive/" + time2text(world.timeofday, "YYYY-MM") + ".yml")
GLOB.changelog_hash = fexists(latest_changelog) ? md5(latest_changelog) : 0 //for telling if the changelog has changed recently
if(fexists(GLOB.config_error_log))
fcopy(GLOB.config_error_log, "[GLOB.log_directory]/config_error.log")
fdel(GLOB.config_error_log)

View File

@@ -1,37 +0,0 @@
var/const/js_dropdowns = {"
function dropdowns() {
var divs = document.getElementsByTagName('div');
var headers = new Array();
var links = new Array();
for(var i=0;i<divs.length;i++){
if(divs\[i\].className=='header') {
divs\[i\].className='header closed';
divs\[i\].innerHTML = divs\[i\].innerHTML+' +';
headers.push(divs\[i\]);
}
if(divs\[i\].className=='links') {
divs\[i\].className='links hidden';
links.push(divs\[i\]);
}
}
for(var i=0;i<headers.length;i++){
if(typeof(links\[i\])!== 'undefined' && links\[i\]!=null) {
headers\[i\].onclick = (function(elem) {
return function() {
if(elem.className.search('visible')>=0) {
elem.className = elem.className.replace('visible','hidden');
this.className = this.className.replace('open','closed');
this.innerHTML = this.innerHTML.replace('-','+');
}
else {
elem.className = elem.className.replace('hidden','visible');
this.className = this.className.replace('closed','open');
this.innerHTML = this.innerHTML.replace('+','-');
}
return false;
}
})(links\[i\]);
}
}
}
"}

View File

@@ -1,33 +0,0 @@
function updateSearch() {
var filter_text = document.getElementById('filter');
var filter = filter_text.value.toLowerCase();
var vars_ol = document.getElementById('vars');
var lis = vars_ol.children;
// the above line can be changed to vars_ol.getElementsByTagName("li") to filter child lists too
// potential todo: implement a per-admin toggle for this
for(var i = 0; i < lis.length; i++) {
var li = lis[i];
if(filter == "" || li.innerText.toLowerCase().indexOf(filter) != -1) {
li.style.display = "block";
} else {
li.style.display = "none";
}
}
}
function selectTextField() {
var filter_text = document.getElementById('filter');
filter_text.focus();
filter_text.select();
}
function loadPage(list) {
if(list.options[list.selectedIndex].value == "") {
return;
}
location.href=list.options[list.selectedIndex].value;
list.selectedIndex = 0;
}

View File

@@ -4,13 +4,12 @@ var/global/floorIsLava = 0
////////////////////////////////
/proc/message_admins(var/msg)
msg = "<span class='log_message'><span class='prefix'>ADMIN LOG:</span> <span class='message'>[msg]</span></span>"
//log_adminwarn(msg) //log_and_message_admins is for this
for(var/client/C in admins)
if((R_ADMIN|R_MOD) & C.holder.rights)
to_chat(C, msg)
/proc/message_admins(msg)
msg = SPAN_ADMIN("<span class=\"prefix\">ADMIN LOG:</span> <span class=\"message\">[msg]</span>")
to_chat(GLOB.admins,
type = MESSAGE_TYPE_ADMINLOG,
html = msg,
confidential = TRUE)
/proc/msg_admin_attack(var/text) //Toggleable Attack Messages
var/rendered = "<span class='log_message><span class='prefix'>ATTACK:</span> <span class='message'>[text]</span></span>"
@@ -1536,12 +1535,12 @@ datum/admins/var/obj/item/paper/admin/faxreply // var to hold fax replies in
log_admin("[key_name(src.owner)] replied to a fax message from [key_name(P.sender)]")
for(var/client/C in admins)
if((R_ADMIN | R_MOD) & C.holder.rights)
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(P.sender)] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
to_chat(C, "<span class='admin'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(P.sender)] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
else
log_admin("[key_name(src.owner)] has sent a fax message to [destination.department]")
for(var/client/C in admins)
if((R_ADMIN | R_MOD) & C.holder.rights)
to_chat(C, "<span class='log_message'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] has sent a fax message to [destination.department] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
to_chat(C, "<span class='admin'><span class='prefix'>FAX LOG:</span>[key_name_admin(src.owner)] has sent a fax message to [destination.department] (<a href='?_src_=holder;AdminFaxView=\ref[rcvdcopy]'>VIEW</a>)</span>")
else
to_chat(src.owner, "<span class='warning'>Message reply failed.</span>")

View File

@@ -2,17 +2,21 @@
set category = "Admin"
set name = "Permissions Panel"
set desc = "Edit admin permissions"
if(!check_rights(R_PERMISSIONS)) return
if(!check_rights(R_PERMISSIONS))
return
usr.client.holder.edit_admin_permissions()
/datum/admins/proc/edit_admin_permissions()
if(!check_rights(R_PERMISSIONS)) return
if(!check_rights(R_PERMISSIONS))
return
var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/group/permissions)
asset_cache_datum.send(usr)
var/output = {"<!DOCTYPE html>
<html>
<head>
<title>Permissions Panel</title>
<script type='text/javascript' src='search.js'></script>
<script type='text/javascript' src='[SSassets.transport.get_asset_url("search.js")]'></script>
<link rel='stylesheet' type='text/css' href='panels.css'>
</head>
<body onload='selectTextField();updateSearch();'>

View File

@@ -1,3 +1,4 @@
#define ASSET_CROSS_ROUND_CACHE_DIRECTORY "tmp/assets"
//These datums are used to populate the asset cache, the proc "register()" does this.
//Place any asset datums you create in asset_list_items.dm
@@ -11,6 +12,16 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset
var/_abstract = /datum/asset
var/cached_serialized_url_mappings
var/cached_serialized_url_mappings_transport_type
/// Whether or not this asset should be loaded in the "early assets" SS
var/early = FALSE
/// Whether or not this asset can be cached across rounds of the same commit under the `CACHE_ASSETS` config.
/// This is not a *guarantee* the asset will be cached. Not all asset subtypes respect this field, and the
/// config can, of course, be disabled.
var/cross_round_cachable = FALSE
/datum/asset/New()
GLOB.asset_datums[type] = src
@@ -19,12 +30,23 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/proc/get_url_mappings()
return list()
/// Returns a cached tgui message of URL mappings
/datum/asset/proc/get_serialized_url_mappings()
if (isnull(cached_serialized_url_mappings) || cached_serialized_url_mappings_transport_type != SSassets.transport.type)
cached_serialized_url_mappings = TGUI_CREATE_MESSAGE("asset/mappings", get_url_mappings())
cached_serialized_url_mappings_transport_type = SSassets.transport.type
return cached_serialized_url_mappings
/datum/asset/proc/register()
return
/datum/asset/proc/send(client)
return
/// Returns whether or not the asset should attempt to read from cache
/datum/asset/proc/should_refresh()
return !cross_round_cachable || !CONFIG_GET(flag/cache_assets)
/// If you don't need anything complicated.
/datum/asset/simple
@@ -59,7 +81,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
for (var/asset_name in assets)
.[asset_name] = SSassets.transport.get_asset_url(asset_name, assets[asset_name])
// For registering or sending multiple others at once
/datum/asset/group
_abstract = /datum/asset/group
@@ -94,10 +115,33 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/name
var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped)
var/list/sprites = list() // "foo_bar" -> list("32x32", 5)
var/list/cached_spritesheets_needed
var/generating_cache = FALSE
/datum/asset/spritesheet/should_refresh()
if (..())
return TRUE
// Static so that the result is the same, even when the files are created, for this run
var/static/should_refresh = null
if (isnull(should_refresh))
// `fexists` seems to always fail on static-time
should_refresh = !fexists("[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css")
return should_refresh
/datum/asset/spritesheet/register()
SHOULD_NOT_OVERRIDE(TRUE)
if (!name)
CRASH("spritesheet [type] cannot register without a name")
if (!should_refresh() && read_from_cache())
return
create_spritesheets()
ensure_stripped()
for(var/size_id in sizes)
var/size = sizes[size_id]
@@ -109,23 +153,32 @@ GLOBAL_LIST_EMPTY(asset_datums)
SSassets.transport.register_asset(res_name, fcopy_rsc(fname))
fdel(fname)
/datum/asset/spritesheet/send(client/C)
if (CONFIG_GET(flag/cache_assets) && cross_round_cachable)
write_to_cache()
/datum/asset/spritesheet/send(client/client)
if (!name)
return
if (!should_refresh())
return send_from_cache(client)
var/all = list("spritesheet_[name].css")
for(var/size_id in sizes)
all += "[name]_[size_id].png"
. = SSassets.transport.send_assets(C, all)
. = SSassets.transport.send_assets(client, all)
/datum/asset/spritesheet/get_url_mappings()
if (!name)
return
if (!should_refresh())
return get_cached_url_mappings()
. = list("spritesheet_[name].css" = SSassets.transport.get_asset_url("spritesheet_[name].css"))
for(var/size_id in sizes)
.["[name]_[size_id].png"] = SSassets.transport.get_asset_url("[name]_[size_id].png")
/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes)
for(var/size_id in sizes_to_strip)
var/size = sizes[size_id]
@@ -147,7 +200,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
for (var/size_id in sizes)
var/size = sizes[size_id]
var/icon/tiny = size[SPRSZ_ICON]
out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[SSassets.transport.get_asset_url("[name]_[size_id].png")]') no-repeat;}"
out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[get_background_url("[name]_[size_id].png")]') no-repeat;}"
for (var/sprite_id in sprites)
var/sprite = sprites[sprite_id]
@@ -165,10 +218,70 @@ GLOBAL_LIST_EMPTY(asset_datums)
return out.Join("\n")
/datum/asset/spritesheet/proc/read_from_cache()
var/replaced_css = file2text("[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css")
var/regex/find_background_urls = regex(@"background:url\('%(.+?)%'\)", "g")
while (find_background_urls.Find(replaced_css))
var/asset_id = find_background_urls.group[1]
var/asset_cache_item = SSassets.transport.register_asset(asset_id, "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[asset_id]")
var/asset_url = SSassets.transport.get_asset_url(asset_cache_item = asset_cache_item)
replaced_css = replacetext(replaced_css, find_background_urls.match, "background:url('[asset_url]')")
LAZYADD(cached_spritesheets_needed, asset_id)
var/replaced_css_filename = "data/spritesheets/spritesheet_[name].css"
rustg_file_write(replaced_css, replaced_css_filename)
SSassets.transport.register_asset("spritesheet_[name].css", replaced_css_filename)
fdel(replaced_css_filename)
return TRUE
/datum/asset/spritesheet/proc/send_from_cache(client/client)
if (isnull(cached_spritesheets_needed))
stack_trace("cached_spritesheets_needed was null when sending assets from [type] from cache")
cached_spritesheets_needed = list()
return SSassets.transport.send_assets(client, cached_spritesheets_needed + "spritesheet_[name].css")
/// Returns the URL to put in the background:url of the CSS asset
/datum/asset/spritesheet/proc/get_background_url(asset)
if (generating_cache)
return "%[asset]%"
else
return SSassets.transport.get_asset_url(asset)
/datum/asset/spritesheet/proc/write_to_cache()
for (var/size_id in sizes)
fcopy(SSassets.cache["[name]_[size_id].png"].resource, "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name]_[size_id].png")
generating_cache = TRUE
var/mock_css = generate_css()
generating_cache = FALSE
rustg_file_write(mock_css, "[ASSET_CROSS_ROUND_CACHE_DIRECTORY]/spritesheet.[name].css")
/datum/asset/spritesheet/proc/get_cached_url_mappings()
var/list/mappings = list()
mappings["spritesheet_[name].css"] = SSassets.transport.get_asset_url("spritesheet_[name].css")
for (var/asset_name in cached_spritesheets_needed)
mappings[asset_name] = SSassets.transport.get_asset_url(asset_name)
return mappings
/// Override this in order to start the creation of the spritehseet.
/// This is where all your Insert, InsertAll, etc calls should be inside.
/datum/asset/spritesheet/proc/create_spritesheets()
SHOULD_CALL_PARENT(FALSE)
CRASH("create_spritesheets() not implemented for [type]!")
/datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE)
I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving)
if (!I || !length(icon_states(I))) // that direction or state doesn't exist
return
//any sprite modifications we want to do (aka, coloring a greyscaled asset)
I = ModifyInserted(I)
var/size_id = "[I.Width()]x[I.Height()]"
var/size = sizes[size_id]
@@ -185,6 +298,15 @@ GLOBAL_LIST_EMPTY(asset_datums)
sizes[size_id] = size = list(1, I, null)
sprites[sprite_name] = list(size_id, 0)
/**
* A simple proc handing the Icon for you to modify before it gets turned into an asset.
*
* Arguments:
* * I: icon being turned into an asset
*/
/datum/asset/spritesheet/proc/ModifyInserted(icon/pre_asset)
return pre_asset
/datum/asset/spritesheet/proc/InsertAll(prefix, icon/I, list/directions)
if (length(prefix))
prefix = "[prefix]-"
@@ -208,7 +330,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
if (!sprite)
return null
var/size_id = sprite[SPR_SIZE]
return {"<span class="[name][size_id] [sprite_name]"></span>"}
return {"<span class='[name][size_id] [sprite_name]'></span>"}
/datum/asset/spritesheet/proc/icon_class_name(sprite_name)
var/sprite = sprites[sprite_name]
@@ -217,6 +339,19 @@ GLOBAL_LIST_EMPTY(asset_datums)
var/size_id = sprite[SPR_SIZE]
return {"[name][size_id] [sprite_name]"}
/**
* Returns the size class (ex design32x32) for a given sprite's icon
*
* Arguments:
* * sprite_name - The sprite to get the size of
*/
/datum/asset/spritesheet/proc/icon_size_id(sprite_name)
var/sprite = sprites[sprite_name]
if (!sprite)
return null
var/size_id = sprite[SPR_SIZE]
return "[name][size_id]"
#undef SPR_SIZE
#undef SPR_IDX
#undef SPRSZ_COUNT
@@ -224,14 +359,31 @@ GLOBAL_LIST_EMPTY(asset_datums)
#undef SPRSZ_STRIPPED
/datum/asset/changelog_item
_abstract = /datum/asset/changelog_item
var/item_filename
/datum/asset/changelog_item/New(date)
item_filename = SANITIZE_FILENAME("[date].yml")
SSassets.transport.register_asset(item_filename, file("html/changelogs/archive/" + item_filename))
/datum/asset/changelog_item/send(client)
if (!item_filename)
return
. = SSassets.transport.send_assets(client, item_filename)
/datum/asset/changelog_item/get_url_mappings()
if (!item_filename)
return
. = list("[item_filename]" = SSassets.transport.get_asset_url(item_filename))
/datum/asset/spritesheet/simple
_abstract = /datum/asset/spritesheet/simple
var/list/assets
/datum/asset/spritesheet/simple/register()
/datum/asset/spritesheet/simple/create_spritesheets()
for (var/key in assets)
Insert(key, assets[key])
..()
//Generates assets based on iconstates of a single icon
/datum/asset/simple/icon_states
@@ -252,7 +404,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
continue
asset = fcopy_rsc(asset) //dedupe
var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]." : ""
var/asset_name = sanitize_filename("[prefix].[prefix2][icon_state_name].png")
var/asset_name = SANITIZE_FILENAME("[prefix].[prefix2][icon_state_name].png")
if (generic_icon_names)
asset_name = "[generate_asset_name(asset)].png"
@@ -315,3 +467,30 @@ GLOBAL_LIST_EMPTY(asset_datums)
/datum/asset/simple/namespaced/proc/get_htmlloader(filename)
return url2htmlloader(SSassets.transport.get_asset_url(filename, assets[filename]))
/// A subtype to generate a JSON file from a list
/datum/asset/json
_abstract = /datum/asset/json
/// The filename, will be suffixed with ".json"
var/name
/datum/asset/json/send(client)
return SSassets.transport.send_assets(client, "[name].json")
/datum/asset/json/get_url_mappings()
return list(
"[name].json" = SSassets.transport.get_asset_url("[name].json"),
)
/datum/asset/json/register()
var/filename = "data/[name].json"
fdel(filename)
text2file(json_encode(generate()), filename)
SSassets.transport.register_asset("[name].json", fcopy_rsc(filename))
fdel(filename)
/// Returns the data that will be JSON encoded
/datum/asset/json/proc/generate()
SHOULD_CALL_PARENT(FALSE)
CRASH("generate() not implemented for [type]!")
#undef ASSET_CROSS_ROUND_CACHE_DIRECTORY

View File

@@ -1,571 +0,0 @@
//DEFINITIONS FOR ASSET DATUMS START HERE.
//DEFINITIONS FOR ASSET DATUMS START HERE.
/datum/asset/simple/tgui
keep_local_name = TRUE
assets = list(
"tgui.bundle.js" = 'tgui/public/tgui.bundle.js',
"tgui.bundle.css" = 'tgui/public/tgui.bundle.css',
)
/datum/asset/simple/tgui_panel
keep_local_name = TRUE
assets = list(
"tgui-panel.bundle.js" = 'tgui/public/tgui-panel.bundle.js',
"tgui-panel.bundle.css" = 'tgui/public/tgui-panel.bundle.css',
)
/*
/datum/asset/simple/headers
assets = list(
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
"charging.gif" = 'icons/program_icons/charging.gif',
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
)
/datum/asset/simple/radar_assets
assets = list(
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
)
*/
/datum/asset/spritesheet/simple/pda
name = "pda"
assets = list(
"atmos" = 'icons/pda_icons/pda_atmos.png',
"back" = 'icons/pda_icons/pda_back.png',
"bell" = 'icons/pda_icons/pda_bell.png',
"blank" = 'icons/pda_icons/pda_blank.png',
"boom" = 'icons/pda_icons/pda_boom.png',
"bucket" = 'icons/pda_icons/pda_bucket.png',
"medibot" = 'icons/pda_icons/pda_medibot.png',
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
"crate" = 'icons/pda_icons/pda_crate.png',
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
"eject" = 'icons/pda_icons/pda_eject.png',
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
"honk" = 'icons/pda_icons/pda_honk.png',
"mail" = 'icons/pda_icons/pda_mail.png',
"medical" = 'icons/pda_icons/pda_medical.png',
"menu" = 'icons/pda_icons/pda_menu.png',
"mule" = 'icons/pda_icons/pda_mule.png',
"notes" = 'icons/pda_icons/pda_notes.png',
"power" = 'icons/pda_icons/pda_power.png',
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
"reagent" = 'icons/pda_icons/pda_reagent.png',
"refresh" = 'icons/pda_icons/pda_refresh.png',
"scanner" = 'icons/pda_icons/pda_scanner.png',
"signaler" = 'icons/pda_icons/pda_signaler.png',
"skills" = 'icons/pda_icons/pda_skills.png',
"status" = 'icons/pda_icons/pda_status.png',
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
"emoji" = 'icons/pda_icons/pda_emoji.png'
)
/*
/datum/asset/spritesheet/simple/paper
name = "paper"
assets = list(
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png',
"stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
"stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
"stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
"stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
)
/datum/asset/simple/IRV
assets = list(
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
)
/datum/asset/group/IRV
children = list(
/datum/asset/simple/jquery,
/datum/asset/simple/IRV
)
*/
/datum/asset/simple/namespaced/changelog
assets = list(
"88x31.png" = 'html/88x31.png',
"bug-minus.png" = 'html/bug-minus.png',
"cross-circle.png" = 'html/cross-circle.png',
"hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
"image-minus.png" = 'html/image-minus.png',
"image-plus.png" = 'html/image-plus.png',
"music-minus.png" = 'html/music-minus.png',
"music-plus.png" = 'html/music-plus.png',
"tick-circle.png" = 'html/tick-circle.png',
"wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
"spell-check.png" = 'html/spell-check.png',
"burn-exclamation.png" = 'html/burn-exclamation.png',
"chevron.png" = 'html/chevron.png',
"chevron-expand.png" = 'html/chevron-expand.png',
"scales.png" = 'html/scales.png',
"coding.png" = 'html/coding.png',
"ban.png" = 'html/ban.png',
"chrome-wrench.png" = 'html/chrome-wrench.png',
"changelog.css" = 'html/changelog.css'
)
parents = list("changelog.html" = 'html/changelog.html')
/datum/asset/simple/namespaced/nanoui
keep_local_name = TRUE
/datum/asset/simple/namespaced/nanoui/register()
var/list/static_dirs = list(
"nano/css/",
"nano/images/",
"nano/images/status_icons/",
"nano/images/modular_computers/",
)
var/list/parent_dirs = list(
"nano/js/",
"nano/templates/"
)
var/list/filenames = null
for(var/path in static_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) == "/") // filenames which end in "/" are actually directories, which we want to ignore
continue
if(fexists(path + filename))
assets[filename] = file(path + filename)
for(var/path in parent_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) == "/") // filenames which end in "/" are actually directories, which we want to ignore
continue
if(fexists(path + filename))
parents[filename] = file(path + filename)
. = ..()
/datum/asset/simple/jquery
legacy = TRUE
assets = list(
"jquery.min.js" = 'html/jquery.min.js',
)
/datum/asset/simple/namespaced/fontawesome
legacy = TRUE
assets = list(
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
)
parents = list("font-awesome.css" = 'html/font-awesome/css/all.min.css')
/datum/asset/simple/namespaced/tgfont
assets = list(
"tgfont.eot" = 'tgui/packages/tgfont/dist/tgfont.eot',
"tgfont.woff2" = 'tgui/packages/tgfont/dist/tgfont.woff2',
)
parents = list("tgfont.css" = 'tgui/packages/tgfont/dist/tgfont.css')
/datum/asset/spritesheet/chat
name = "chat"
/datum/asset/spritesheet/chat/register()
InsertAll("emoji", 'icons/emoji.dmi')
InsertAll("emoji", 'icons/emoji_32.dmi')
/*
// pre-loading all lanugage icons also helps to avoid meta
InsertAll("language", 'icons/misc/language.dmi')
// catch languages which are pulling icons from another file
for(var/path in typesof(/datum/language))
var/datum/language/L = path
var/icon = initial(L.icon)
if (icon != 'icons/misc/language.dmi')
var/icon_state = initial(L.icon_state)
Insert("language-[icon_state]", icon, icon_state=icon_state)
*/
..()
/*
/datum/asset/simple/lobby
assets = list(
"playeroptions.css" = 'html/browser/playeroptions.css'
)
*/
/datum/asset/simple/namespaced/common
assets = list("padlock.png" = 'html/padlock.png')
parents = list("common.css" = 'html/browser/common.css')
/datum/asset/simple/permissions
assets = list(
"search.js" = 'html/admin/search.js',
"panels.css" = 'html/admin/panels.css'
)
/datum/asset/group/permissions
children = list(
/datum/asset/simple/permissions,
/datum/asset/simple/namespaced/common
)
/datum/asset/simple/vstation_misc
legacy = TRUE
assets = list(
"loading.gif" = 'html/images/loading.gif',
"ntlogo.png" = 'html/images/ntlogo.png',
"sglogo.png" = 'html/images/sglogo.png',
"talisman.png" = 'html/images/talisman.png',
"paper_bg.png" = 'html/images/paper_bg.png',
"no_image32.png" = 'html/images/no_image32.png'
)
/datum/asset/simple/vstation_spideros
legacy = TRUE
assets = list(
"sos_1.png" = 'icons/spideros_icons/sos_1.png',
"sos_2.png" = 'icons/spideros_icons/sos_2.png',
"sos_3.png" = 'icons/spideros_icons/sos_3.png',
"sos_4.png" = 'icons/spideros_icons/sos_4.png',
"sos_5.png" = 'icons/spideros_icons/sos_5.png',
"sos_6.png" = 'icons/spideros_icons/sos_6.png',
"sos_7.png" = 'icons/spideros_icons/sos_7.png',
"sos_8.png" = 'icons/spideros_icons/sos_8.png',
"sos_9.png" = 'icons/spideros_icons/sos_9.png',
"sos_10.png" = 'icons/spideros_icons/sos_10.png',
"sos_11.png" = 'icons/spideros_icons/sos_11.png',
"sos_12.png" = 'icons/spideros_icons/sos_12.png',
"sos_13.png" = 'icons/spideros_icons/sos_13.png',
"sos_14.png" = 'icons/spideros_icons/sos_14.png'
)
/*
/datum/asset/simple/notes
assets = list(
"high_button.png" = 'html/high_button.png',
"medium_button.png" = 'html/medium_button.png',
"minor_button.png" = 'html/minor_button.png',
"none_button.png" = 'html/none_button.png',
)
/datum/asset/simple/arcade
assets = list(
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
)
*//*
/datum/asset/spritesheet/simple/achievements
name ="achievements"
assets = list(
"default" = 'icons/UI_Icons/Achievements/default.png',
"basemisc" = 'icons/UI_Icons/Achievements/basemisc.png',
"baseboss" = 'icons/UI_Icons/Achievements/baseboss.png',
"baseskill" = 'icons/UI_Icons/Achievements/baseskill.png',
"bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png',
"colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png',
"hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png',
"legion" = 'icons/UI_Icons/Achievements/Boss/legion.png',
"miner" = 'icons/UI_Icons/Achievements/Boss/miner.png',
"swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png',
"tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png',
"featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png',
"helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png',
"jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png',
"meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png',
"timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png',
"upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png',
"clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png',
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
"assistant" = 'icons/UI_Icons/Achievements/Mafia/assistant.png',
"changeling" = 'icons/UI_Icons/Achievements/Mafia/changeling.png',
"chaplain" = 'icons/UI_Icons/Achievements/Mafia/chaplain.png',
"clown" = 'icons/UI_Icons/Achievements/Mafia/clown.png',
"detective" = 'icons/UI_Icons/Achievements/Mafia/detective.png',
"fugitive" = 'icons/UI_Icons/Achievements/Mafia/fugitive.png',
"hated" = 'icons/UI_Icons/Achievements/Mafia/hated.png',
"hop" = 'icons/UI_Icons/Achievements/Mafia/hop.png',
"lawyer" = 'icons/UI_Icons/Achievements/Mafia/lawyer.png',
"md" = 'icons/UI_Icons/Achievements/Mafia/md.png',
"nightmare" = 'icons/UI_Icons/Achievements/Mafia/nightmare.png',
"obsessed" = 'icons/UI_Icons/Achievements/Mafia/obsessed.png',
"psychologist" = 'icons/UI_Icons/Achievements/Mafia/psychologist.png',
"thoughtfeeder" = 'icons/UI_Icons/Achievements/Mafia/thoughtfeeder.png',
"traitor" = 'icons/UI_Icons/Achievements/Mafia/traitor.png',
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png'
)
*/
/*
/datum/asset/spritesheet/simple/minesweeper
name = "minesweeper"
assets = list(
"1" = 'icons/UI_Icons/minesweeper_tiles/one.png',
"2" = 'icons/UI_Icons/minesweeper_tiles/two.png',
"3" = 'icons/UI_Icons/minesweeper_tiles/three.png',
"4" = 'icons/UI_Icons/minesweeper_tiles/four.png',
"5" = 'icons/UI_Icons/minesweeper_tiles/five.png',
"6" = 'icons/UI_Icons/minesweeper_tiles/six.png',
"7" = 'icons/UI_Icons/minesweeper_tiles/seven.png',
"8" = 'icons/UI_Icons/minesweeper_tiles/eight.png',
"empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png',
"flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png',
"hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png',
"mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png',
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
)
/datum/asset/spritesheet/simple/pills
name ="pills"
assets = list(
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
)
//this exists purely to avoid meta by pre-loading all language icons.
/datum/asset/language/register()
for(var/path in typesof(/datum/language))
set waitfor = FALSE
var/datum/language/L = new path ()
L.get_icon()
*/
/datum/asset/spritesheet/pipes
name = "pipes"
/datum/asset/spritesheet/pipes/register()
for(var/each in list('icons/obj/pipe-item.dmi', 'icons/obj/pipes/disposal.dmi'))
InsertAll("", each, GLOB.alldirs)
..()
/*
// Representative icons for each research design
/datum/asset/spritesheet/research_designs
name = "design"
/datum/asset/spritesheet/research_designs/register()
for (var/path in subtypesof(/datum/design))
var/datum/design/D = path
var/icon_file
var/icon_state
var/icon/I
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
icon_file = initial(D.research_icon)
icon_state = initial(D.research_icon_state)
if(!(icon_state in icon_states(icon_file)))
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
else
// construct the icon and slap it into the resource cache
var/atom/item = initial(D.build_path)
if (!ispath(item, /atom))
// biogenerator outputs to beakers by default
if (initial(D.build_type) & BIOGENERATOR)
item = /obj/item/reagent_containers/glass/beaker/large
else
continue // shouldn't happen, but just in case
// circuit boards become their resulting machines or computers
if (ispath(item, /obj/item/circuitboard))
var/obj/item/circuitboard/C = item
var/machine = initial(C.build_path)
if (machine)
item = machine
icon_file = initial(item.icon)
icon_state = initial(item.icon_state)
if(!(icon_state in icon_states(icon_file)))
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
// computers (and snowflakes) get their screen and keyboard sprites
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
var/obj/machinery/computer/C = item
var/screen = initial(C.icon_screen)
var/keyboard = initial(C.icon_keyboard)
var/all_states = icon_states(icon_file)
if (screen && (screen in all_states))
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
if (keyboard && (keyboard in all_states))
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
Insert(initial(D.id), I)
return ..()
/datum/asset/spritesheet/vending
name = "vending"
/datum/asset/spritesheet/vending/register()
for (var/k in GLOB.vending_products)
var/atom/item = k
if (!ispath(item, /atom))
continue
var/icon_file = initial(item.icon)
var/icon_state = initial(item.icon_state)
var/icon/I
var/icon_states_list = icon_states(icon_file)
if(icon_state in icon_states_list)
I = icon(icon_file, icon_state, SOUTH)
var/c = initial(item.color)
if (!isnull(c) && c != "#FFFFFF")
I.Blend(c, ICON_MULTIPLY)
else
var/icon_states_string
for (var/an_icon_state in icon_states_list)
if (!icon_states_string)
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
else
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
I = icon('icons/turf/floors.dmi', "", SOUTH)
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
Insert(imgid, I)
return ..()
/datum/asset/simple/genetics
assets = list(
"dna_discovered.gif" = 'html/dna_discovered.gif',
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
"dna_extra.gif" = 'html/dna_extra.gif'
)
/datum/asset/simple/orbit
assets = list(
"ghost.png" = 'html/ghost.png'
)
/datum/asset/simple/vv
assets = list(
"view_variables.css" = 'html/admin/view_variables.css'
)
*/
/datum/asset/spritesheet/sheetmaterials
name = "sheetmaterials"
/datum/asset/spritesheet/sheetmaterials/register()
InsertAll("", 'icons/obj/stacks.dmi')
..()
/*
/datum/asset/spritesheet/mafia
name = "mafia"
/datum/asset/spritesheet/mafia/register()
InsertAll("", 'icons/obj/mafia.dmi')
..()
*/
//Pill sprites for UIs
/datum/asset/simple/namespaced/chem_master
keep_local_name = TRUE
/datum/asset/simple/namespaced/chem_master/register()
for(var/i = 1 to 24)
assets["pill[i].png"] = icon('icons/obj/chemical.dmi', "pill[i]")
for(var/i = 1 to 4)
assets["bottle-[i].png"] = icon('icons/obj/chemical.dmi', "bottle-[i]")
return ..()
// Nanomaps
/datum/asset/simple/nanomaps
// It REALLY doesnt matter too much if these arent up to date
// They are relatively big
assets = list(
// VOREStation Edit: We don't need Southern Cross
// "southern_cross_nanomap_z1.png" = 'icons/_nanomaps/southern_cross_nanomap_z1.png',
// "southern_cross_nanomap_z10.png" = 'icons/_nanomaps/southern_cross_nanomap_z10.png',
// "southern_cross_nanomap_z2.png" = 'icons/_nanomaps/southern_cross_nanomap_z2.png',
// "southern_cross_nanomap_z3.png" = 'icons/_nanomaps/southern_cross_nanomap_z3.png',
// "southern_cross_nanomap_z5.png" = 'icons/_nanomaps/southern_cross_nanomap_z5.png',
// "southern_cross_nanomap_z6.png" = 'icons/_nanomaps/southern_cross_nanomap_z6.png',
"tether_nanomap_z1.png" = 'icons/_nanomaps/tether_nanomap_z1.png',
"tether_nanomap_z2.png" = 'icons/_nanomaps/tether_nanomap_z2.png',
"tether_nanomap_z3.png" = 'icons/_nanomaps/tether_nanomap_z3.png',
"tether_nanomap_z4.png" = 'icons/_nanomaps/tether_nanomap_z4.png',
"tether_nanomap_z5.png" = 'icons/_nanomaps/tether_nanomap_z5.png',
"tether_nanomap_z6.png" = 'icons/_nanomaps/tether_nanomap_z6.png',
"tether_nanomap_z7.png" = 'icons/_nanomaps/tether_nanomap_z7.png',
"tether_nanomap_z8.png" = 'icons/_nanomaps/tether_nanomap_z8.png',
"tether_nanomap_z9.png" = 'icons/_nanomaps/tether_nanomap_z9.png',
"tether_nanomap_z10.png" = 'icons/_nanomaps/tether_nanomap_z10.png',
"tether_nanomap_z13.png" = 'icons/_nanomaps/tether_nanomap_z13.png',
"tether_nanomap_z14.png" = 'icons/_nanomaps/tether_nanomap_z14.png',
// VOREStation Edit End
)

View File

@@ -0,0 +1,9 @@
/datum/asset/simple/arcade
assets = list(
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
"boss4.gif" = 'icons/ui_icons/arcade/boss4.gif',
"boss5.gif" = 'icons/ui_icons/arcade/boss5.gif',
"boss6.gif" = 'icons/ui_icons/arcade/boss6.gif',
)

View File

@@ -0,0 +1,17 @@
/datum/asset/spritesheet/chat
name = "chat"
/datum/asset/spritesheet/chat/create_spritesheets()
InsertAll("emoji", EMOJI_SET)
InsertAll("emoji_32", EMOJI_SET32)
/*
// pre-loading all lanugage icons also helps to avoid meta
InsertAll("language", 'icons/misc/language.dmi')
// catch languages which are pulling icons from another file
for(var/path in typesof(/datum/language))
var/datum/language/L = path
var/icon = initial(L.icon)
if (icon != 'icons/misc/language.dmi')
var/icon_state = initial(L.icon_state)
Insert("language-[icon_state]", icon, icon_state=icon_state)
*/

View File

@@ -0,0 +1,4 @@
/datum/asset/simple/circuit_assets
assets = list(
"grid_background.png" = 'icons/ui_icons/tgui/grid_background.png'
)

View File

@@ -0,0 +1,3 @@
/datum/asset/simple/namespaced/common
assets = list("padlock.png" = 'icons/ui_icons/common/padlock.png')
parents = list("common.css" = 'html/browser/common.css')

View File

@@ -0,0 +1,20 @@
/datum/asset/spritesheet/simple/condiments
name = "condiments"
assets = list(
CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png',
"enzyme" = 'icons/ui_icons/condiments/enzyme.png',
"flour" = 'icons/ui_icons/condiments/flour.png',
"mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png',
"milk" = 'icons/ui_icons/condiments/milk.png',
"blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png',
"rice" = 'icons/ui_icons/condiments/rice.png',
"sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png',
"soymilk" = 'icons/ui_icons/condiments/soymilk.png',
"soysauce" = 'icons/ui_icons/condiments/soysauce.png',
"sugar" = 'icons/ui_icons/condiments/sugar.png',
"ketchup" = 'icons/ui_icons/condiments/ketchup.png',
"capsaicin" = 'icons/ui_icons/condiments/hotsauce.png',
"frostoil" = 'icons/ui_icons/condiments/coldsauce.png',
"bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png',
"cornoil" = 'icons/ui_icons/condiments/oliveoil.png',
)

View File

@@ -0,0 +1,7 @@
/datum/asset/simple/contracts
assets = list(
"bluespace.png" = 'icons/ui_icons/contracts/bluespace.png',
"destruction.png" = 'icons/ui_icons/contracts/destruction.png',
"healing.png" = 'icons/ui_icons/contracts/healing.png',
"robeless.png" = 'icons/ui_icons/contracts/robeless.png',
)

View File

@@ -0,0 +1,12 @@
/datum/asset/spritesheet/fish
name = "fish"
/datum/asset/spritesheet/fish/create_spritesheets()
for (var/path in subtypesof(/datum/aquarium_behaviour/fish))
var/datum/aquarium_behaviour/fish/fish_type = path
var/fish_icon = initial(fish_type.icon)
var/fish_icon_state = initial(fish_type.icon_state)
var/id = sanitize_css_class_name("[fish_icon][fish_icon_state]")
if(sprites[id]) //no dupes
continue
Insert(id, fish_icon, fish_icon_state)

View File

@@ -0,0 +1,9 @@
/datum/asset/simple/namespaced/fontawesome
assets = list(
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css',
)
parents = list("font-awesome.css" = 'html/font-awesome/css/all.min.css')

View File

@@ -0,0 +1,6 @@
/datum/asset/simple/genetics
assets = list(
"dna_discovered.gif" = 'icons/ui_icons/dna/dna_discovered.gif',
"dna_undiscovered.gif" = 'icons/ui_icons/dna/dna_undiscovered.gif',
"dna_extra.gif" = 'icons/ui_icons/dna/dna_extra.gif'
)

View File

@@ -0,0 +1,31 @@
/datum/asset/simple/headers
assets = list(
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
"charging.gif" = 'icons/program_icons/charging.gif',
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif',
"robotact.gif" = 'icons/program_icons/robotact.gif'
)

View File

@@ -0,0 +1,20 @@
/datum/asset/simple/inventory
assets = list(
"inventory-glasses.png" = 'icons/ui_icons/inventory/glasses.png',
"inventory-head.png" = 'icons/ui_icons/inventory/head.png',
"inventory-neck.png" = 'icons/ui_icons/inventory/neck.png',
"inventory-mask.png" = 'icons/ui_icons/inventory/mask.png',
"inventory-ears.png" = 'icons/ui_icons/inventory/ears.png',
"inventory-uniform.png" = 'icons/ui_icons/inventory/uniform.png',
"inventory-suit.png" = 'icons/ui_icons/inventory/suit.png',
"inventory-gloves.png" = 'icons/ui_icons/inventory/gloves.png',
"inventory-hand_l.png" = 'icons/ui_icons/inventory/hand_l.png',
"inventory-hand_r.png" = 'icons/ui_icons/inventory/hand_r.png',
"inventory-shoes.png" = 'icons/ui_icons/inventory/shoes.png',
"inventory-suit_storage.png" = 'icons/ui_icons/inventory/suit_storage.png',
"inventory-id.png" = 'icons/ui_icons/inventory/id.png',
"inventory-belt.png" = 'icons/ui_icons/inventory/belt.png',
"inventory-back.png" = 'icons/ui_icons/inventory/back.png',
"inventory-pocket.png" = 'icons/ui_icons/inventory/pocket.png',
"inventory-collar.png" = 'icons/ui_icons/inventory/collar.png',
)

View File

@@ -0,0 +1,5 @@
/datum/asset/simple/jquery
legacy = TRUE
assets = list(
"jquery.min.js" = 'html/jquery/jquery.min.js',
)

View File

@@ -0,0 +1,9 @@
//this exists purely to avoid meta by pre-loading all language icons.
/datum/asset/language
/datum/asset/language/register()
set waitfor = FALSE
for(var/path in typesof(/datum/language))
var/datum/language/language = new path()
language.get_icon()

View File

@@ -0,0 +1,25 @@
/datum/asset/simple/nanomaps
// It REALLY doesnt matter too much if these arent up to date
// They are relatively big
assets = list(
// VOREStation Edit: We don't need Southern Cross
// "southern_cross_nanomap_z1.png" = 'icons/_nanomaps/southern_cross_nanomap_z1.png',
// "southern_cross_nanomap_z10.png" = 'icons/_nanomaps/southern_cross_nanomap_z10.png',
// "southern_cross_nanomap_z2.png" = 'icons/_nanomaps/southern_cross_nanomap_z2.png',
// "southern_cross_nanomap_z3.png" = 'icons/_nanomaps/southern_cross_nanomap_z3.png',
// "southern_cross_nanomap_z5.png" = 'icons/_nanomaps/southern_cross_nanomap_z5.png',
// "southern_cross_nanomap_z6.png" = 'icons/_nanomaps/southern_cross_nanomap_z6.png',
"tether_nanomap_z1.png" = 'icons/_nanomaps/tether_nanomap_z1.png',
"tether_nanomap_z2.png" = 'icons/_nanomaps/tether_nanomap_z2.png',
"tether_nanomap_z3.png" = 'icons/_nanomaps/tether_nanomap_z3.png',
"tether_nanomap_z4.png" = 'icons/_nanomaps/tether_nanomap_z4.png',
"tether_nanomap_z5.png" = 'icons/_nanomaps/tether_nanomap_z5.png',
"tether_nanomap_z6.png" = 'icons/_nanomaps/tether_nanomap_z6.png',
"tether_nanomap_z7.png" = 'icons/_nanomaps/tether_nanomap_z7.png',
"tether_nanomap_z8.png" = 'icons/_nanomaps/tether_nanomap_z8.png',
"tether_nanomap_z9.png" = 'icons/_nanomaps/tether_nanomap_z9.png',
"tether_nanomap_z10.png" = 'icons/_nanomaps/tether_nanomap_z10.png',
"tether_nanomap_z13.png" = 'icons/_nanomaps/tether_nanomap_z13.png',
"tether_nanomap_z14.png" = 'icons/_nanomaps/tether_nanomap_z14.png',
// VOREStation Edit End
)

View File

@@ -0,0 +1,32 @@
/datum/asset/simple/namespaced/nanoui
keep_local_name = TRUE
/datum/asset/simple/namespaced/nanoui/register()
var/list/static_dirs = list(
"nano/css/",
"nano/images/",
"nano/images/status_icons/",
"nano/images/modular_computers/",
)
var/list/parent_dirs = list(
"nano/js/",
"nano/templates/"
)
var/list/filenames = null
for(var/path in static_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) == "/") // filenames which end in "/" are actually directories, which we want to ignore
continue
if(fexists(path + filename))
assets[filename] = file(path + filename)
for(var/path in parent_dirs)
filenames = flist(path)
for(var/filename in filenames)
if(copytext(filename, length(filename)) == "/") // filenames which end in "/" are actually directories, which we want to ignore
continue
if(fexists(path + filename))
parents[filename] = file(path + filename)
. = ..()

View File

@@ -0,0 +1,29 @@
/datum/asset/simple/vstation_misc
legacy = TRUE
assets = list(
"loading.gif" = 'html/images/loading.gif',
"ntlogo.png" = 'html/images/ntlogo.png',
"sglogo.png" = 'html/images/sglogo.png',
"talisman.png" = 'html/images/talisman.png',
"paper_bg.png" = 'html/images/paper_bg.png',
"no_image32.png" = 'html/images/no_image32.png'
)
/datum/asset/simple/vstation_spideros
legacy = TRUE
assets = list(
"sos_1.png" = 'icons/spideros_icons/sos_1.png',
"sos_2.png" = 'icons/spideros_icons/sos_2.png',
"sos_3.png" = 'icons/spideros_icons/sos_3.png',
"sos_4.png" = 'icons/spideros_icons/sos_4.png',
"sos_5.png" = 'icons/spideros_icons/sos_5.png',
"sos_6.png" = 'icons/spideros_icons/sos_6.png',
"sos_7.png" = 'icons/spideros_icons/sos_7.png',
"sos_8.png" = 'icons/spideros_icons/sos_8.png',
"sos_9.png" = 'icons/spideros_icons/sos_9.png',
"sos_10.png" = 'icons/spideros_icons/sos_10.png',
"sos_11.png" = 'icons/spideros_icons/sos_11.png',
"sos_12.png" = 'icons/spideros_icons/sos_12.png',
"sos_13.png" = 'icons/spideros_icons/sos_13.png',
"sos_14.png" = 'icons/spideros_icons/sos_14.png'
)

View File

@@ -0,0 +1,7 @@
/datum/asset/simple/notes
assets = list(
"high_button.png" = 'icons/ui_icons/notes/high_button.png',
"medium_button.png" = 'icons/ui_icons/notes/medium_button.png',
"minor_button.png" = 'icons/ui_icons/notes/minor_button.png',
"none_button.png" = 'icons/ui_icons/notes/none_button.png',
)

View File

@@ -0,0 +1,4 @@
/datum/asset/simple/orbit
assets = list(
"ghost.png" = 'icons/ui_icons/orbit/ghost.png'
)

View File

@@ -0,0 +1,19 @@
/datum/asset/spritesheet/simple/paper
name = "paper"
assets = list(
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png',
"stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png',
"stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png',
"stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png',
"stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png'
)

View File

@@ -0,0 +1,8 @@
/datum/asset/spritesheet/simple/patches
name = "patches"
assets = list(
"bandaid" = 'icons/ui_icons/patches/bandaid.png',
"bandaid_brute" = 'icons/ui_icons/patches/bandaid_brute.png',
"bandaid_burn" = 'icons/ui_icons/patches/bandaid_burn.png',
"bandaid_both" = 'icons/ui_icons/patches/bandaid_both.png'
)

View File

@@ -0,0 +1,34 @@
/datum/asset/spritesheet/simple/pda
name = "pda"
assets = list(
"atmos" = 'icons/pda_icons/pda_atmos.png',
"back" = 'icons/pda_icons/pda_back.png',
"bell" = 'icons/pda_icons/pda_bell.png',
"blank" = 'icons/pda_icons/pda_blank.png',
"boom" = 'icons/pda_icons/pda_boom.png',
"bucket" = 'icons/pda_icons/pda_bucket.png',
"medibot" = 'icons/pda_icons/pda_medibot.png',
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
"crate" = 'icons/pda_icons/pda_crate.png',
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
"eject" = 'icons/pda_icons/pda_eject.png',
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
"honk" = 'icons/pda_icons/pda_honk.png',
"mail" = 'icons/pda_icons/pda_mail.png',
"medical" = 'icons/pda_icons/pda_medical.png',
"menu" = 'icons/pda_icons/pda_menu.png',
"mule" = 'icons/pda_icons/pda_mule.png',
"notes" = 'icons/pda_icons/pda_notes.png',
"power" = 'icons/pda_icons/pda_power.png',
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
"reagent" = 'icons/pda_icons/pda_reagent.png',
"refresh" = 'icons/pda_icons/pda_refresh.png',
"scanner" = 'icons/pda_icons/pda_scanner.png',
"signaler" = 'icons/pda_icons/pda_signaler.png',
"skills" = 'icons/pda_icons/pda_skills.png',
"status" = 'icons/pda_icons/pda_status.png',
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
"emoji" = 'icons/pda_icons/pda_emoji.png',
"droneblacklist" = 'icons/pda_icons/pda_droneblacklist.png',
)

View File

@@ -0,0 +1,11 @@
/datum/asset/simple/permissions
assets = list(
"search.js" = 'html/admin/search.js',
"panels.css" = 'html/admin/panels.css'
)
/datum/asset/group/permissions
children = list(
/datum/asset/simple/permissions,
/datum/asset/simple/namespaced/common
)

View File

@@ -0,0 +1,40 @@
/datum/asset/simple/namespaced/chem_master
keep_local_name = TRUE
/datum/asset/simple/namespaced/chem_master/register()
for(var/i = 1 to 24)
assets["pill[i].png"] = icon('icons/obj/chemical.dmi', "pill[i]")
for(var/i = 1 to 4)
assets["bottle-[i].png"] = icon('icons/obj/chemical.dmi', "bottle-[i]")
return ..()
/*
/datum/asset/spritesheet/simple/pills
name = "pills"
assets = list(
"pill1" = 'icons/ui_icons/pills/pill1.png',
"pill2" = 'icons/ui_icons/pills/pill2.png',
"pill3" = 'icons/ui_icons/pills/pill3.png',
"pill4" = 'icons/ui_icons/pills/pill4.png',
"pill5" = 'icons/ui_icons/pills/pill5.png',
"pill6" = 'icons/ui_icons/pills/pill6.png',
"pill7" = 'icons/ui_icons/pills/pill7.png',
"pill8" = 'icons/ui_icons/pills/pill8.png',
"pill9" = 'icons/ui_icons/pills/pill9.png',
"pill10" = 'icons/ui_icons/pills/pill10.png',
"pill11" = 'icons/ui_icons/pills/pill11.png',
"pill12" = 'icons/ui_icons/pills/pill12.png',
"pill13" = 'icons/ui_icons/pills/pill13.png',
"pill14" = 'icons/ui_icons/pills/pill14.png',
"pill15" = 'icons/ui_icons/pills/pill15.png',
"pill16" = 'icons/ui_icons/pills/pill16.png',
"pill17" = 'icons/ui_icons/pills/pill17.png',
"pill18" = 'icons/ui_icons/pills/pill18.png',
"pill19" = 'icons/ui_icons/pills/pill19.png',
"pill20" = 'icons/ui_icons/pills/pill20.png',
"pill21" = 'icons/ui_icons/pills/pill21.png',
"pill22" = 'icons/ui_icons/pills/pill22.png',
)
*/

View File

@@ -0,0 +1,7 @@
/datum/asset/spritesheet/pipes
name = "pipes"
/datum/asset/spritesheet/pipes/create_spritesheets()
for(var/each in list('icons/obj/pipe-item.dmi', 'icons/obj/pipes/disposal.dmi'))
////for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi'))
InsertAll("", each, GLOB.alldirs)

View File

@@ -0,0 +1,12 @@
/datum/asset/simple/portraits
assets = list()
/datum/asset/simple/portraits/New()
if(!length(SSpersistent_paintings.paintings))
return
for(var/datum/painting/portrait as anything in SSpersistent_paintings.paintings)
var/png = "data/paintings/images/[portrait.md5].png"
if(fexists(png))
var/asset_name = "paintings_[portrait.md5]"
assets[asset_name] = png
..() //this is where it registers all these assets we added to the list

View File

@@ -0,0 +1,6 @@
/datum/asset/simple/radar_assets
assets = list(
"ntosradarbackground.png" = 'icons/ui_icons/tgui/ntosradar_background.png',
"ntosradarpointer.png" = 'icons/ui_icons/tgui/ntosradar_pointer.png',
"ntosradarpointerS.png" = 'icons/ui_icons/tgui/ntosradar_pointer_S.png'
)

View File

@@ -0,0 +1,63 @@
// Representative icons for each research design
/datum/asset/spritesheet/research_designs
name = "design"
/datum/asset/spritesheet/research_designs/create_spritesheets()
for (var/path in subtypesof(/datum/design))
var/datum/design/D = path
var/icon_file
var/icon_state
var/icon/I
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
icon_file = initial(D.research_icon)
icon_state = initial(D.research_icon_state)
if(!(icon_state in icon_states(icon_file)))
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
else
// construct the icon and slap it into the resource cache
var/atom/item = initial(D.build_path)
if (!ispath(item, /atom))
// biogenerator outputs to beakers by default
if (initial(D.build_type) & BIOGENERATOR)
item = /obj/item/reagent_containers/glass/beaker/large
else
continue // shouldn't happen, but just in case
// circuit boards become their resulting machines or computers
if (ispath(item, /obj/item/circuitboard))
var/obj/item/circuitboard/C = item
var/machine = initial(C.build_path)
if (machine)
item = machine
// Check for GAGS support where necessary
var/greyscale_config = initial(item.greyscale_config)
var/greyscale_colors = initial(item.greyscale_colors)
if (greyscale_config && greyscale_colors)
icon_file = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
else
icon_file = initial(item.icon)
icon_state = initial(item.icon_state)
if(!(icon_state in icon_states(icon_file)))
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
continue
I = icon(icon_file, icon_state, SOUTH)
// computers (and snowflakes) get their screen and keyboard sprites
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
var/obj/machinery/computer/C = item
var/screen = initial(C.icon_screen)
var/keyboard = initial(C.icon_keyboard)
var/all_states = icon_states(icon_file)
if (screen && (screen in all_states))
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
if (keyboard && (keyboard in all_states))
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
Insert(initial(D.id), I)

View File

@@ -0,0 +1,4 @@
/datum/asset/simple/safe
assets = list(
"safe_dial.png" = 'icons/ui_icons/safe/safe_dial.png'
)

View File

@@ -0,0 +1,9 @@
/datum/asset/spritesheet/sheetmaterials
name = "sheetmaterials"
/datum/asset/spritesheet/sheetmaterials/create_spritesheets()
InsertAll("", 'icons/obj/stacks.dmi')
//InsertAll("", 'icons/obj/stack_objects.dmi')
// Special case to handle Bluespace Crystals
Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal")

View File

@@ -0,0 +1,27 @@
/datum/asset/spritesheet/supplypods
name = "supplypods"
/datum/asset/spritesheet/supplypods/create_spritesheets()
for (var/style in 1 to length(GLOB.podstyles))
if (style == STYLE_SEETHROUGH)
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi' , "seethrough-icon"))
continue
var/base = GLOB.podstyles[style][POD_BASE]
if (!base)
Insert("pod_asset[style]", icon('icons/obj/supplypods.dmi', "invisible-icon"))
continue
var/icon/podIcon = icon('icons/obj/supplypods.dmi', base)
var/door = GLOB.podstyles[style][POD_DOOR]
if (door)
door = "[base]_door"
podIcon.Blend(icon('icons/obj/supplypods.dmi', door), ICON_OVERLAY)
var/shape = GLOB.podstyles[style][POD_SHAPE]
if (shape == POD_SHAPE_NORML)
var/decal = GLOB.podstyles[style][POD_DECAL]
if (decal)
podIcon.Blend(icon('icons/obj/supplypods.dmi', decal), ICON_OVERLAY)
var/glow = GLOB.podstyles[style][POD_GLOW]
if (glow)
glow = "pod_glow_[glow]"
podIcon.Blend(icon('icons/obj/supplypods.dmi', glow), ICON_OVERLAY)
Insert("pod_asset[style]", podIcon)

View File

@@ -0,0 +1,8 @@
/datum/asset/simple/namespaced/tgfont
assets = list(
"tgfont.eot" = file("tgui/packages/tgfont/static/tgfont.eot"),
"tgfont.woff2" = file("tgui/packages/tgfont/static/tgfont.woff2"),
)
parents = list(
"tgfont.css" = file("tgui/packages/tgfont/static/tgfont.css"),
)

View File

@@ -0,0 +1,13 @@
/datum/asset/simple/tgui
keep_local_name = TRUE
assets = list(
"tgui.bundle.js" = file("tgui/public/tgui.bundle.js"),
"tgui.bundle.css" = file("tgui/public/tgui.bundle.css"),
)
/datum/asset/simple/tgui_panel
keep_local_name = TRUE
assets = list(
"tgui-panel.bundle.js" = file("tgui/public/tgui-panel.bundle.js"),
"tgui-panel.bundle.css" = file("tgui/public/tgui-panel.bundle.css"),
)

View File

@@ -0,0 +1,39 @@
/// Sends information needed for uplinks
/datum/asset/json/uplink
name = "uplink"
/datum/asset/json/uplink/generate()
var/list/data = list()
var/list/categories = list()
var/list/items = list()
for(var/datum/uplink_category/category as anything in subtypesof(/datum/uplink_category))
categories += category
categories = sortTim(categories, .proc/cmp_uplink_category_desc)
var/list/new_categories = list()
for(var/datum/uplink_category/category as anything in categories)
new_categories += initial(category.name)
categories = new_categories
for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item))
var/datum/uplink_item/item = new item_path()
if(item.item) {
items += list(list(
"id" = item_path,
"name" = item.name,
"cost" = item.cost,
"desc" = item.desc,
"category" = item.category? initial(item.category.name) : null,
"purchasable_from" = item.purchasable_from,
"restricted" = item.restricted,
"limited_stock" = item.limited_stock,
"restricted_roles" = item.restricted_roles,
"progression_minimum" = item.progression_minimum,
))
}
SStraitor.uplink_items += item
SStraitor.uplink_items_by_type[item_path] = item
data["items"] = items
data["categories"] = categories
return data

View File

@@ -0,0 +1,36 @@
/datum/asset/spritesheet/vending
name = "vending"
/datum/asset/spritesheet/vending/create_spritesheets()
for (var/k in GLOB.vending_products)
var/atom/item = k
if (!ispath(item, /atom))
continue
var/icon_file
if (initial(item.greyscale_colors) && initial(item.greyscale_config))
icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
else
icon_file = initial(item.icon)
var/icon_state = initial(item.icon_state)
var/icon/I
var/icon_states_list = icon_states(icon_file)
if(icon_state in icon_states_list)
I = icon(icon_file, icon_state, SOUTH)
var/c = initial(item.color)
if (!isnull(c) && c != "#FFFFFF")
I.Blend(c, ICON_MULTIPLY)
else
var/icon_states_string
for (var/an_icon_state in icon_states_list)
if (!icon_states_string)
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
else
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
I = icon('icons/turf/floors.dmi', "", SOUTH)
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
Insert(imgid, I)

View File

@@ -0,0 +1,4 @@
/datum/asset/simple/vv
assets = list(
"view_variables.css" = 'html/admin/view_variables.css'
)

View File

@@ -24,7 +24,7 @@ Call .get_url_mappings() to get an associated list with the urls your assets can
See the documentation for `/datum/asset_transport` for the backend api the asset datums utilize.
The global variable `SSassets.transport` contains the currently configured transport.
The global variable `SSassets.transport` contains the currently configured transport.
@@ -32,6 +32,6 @@ The global variable `SSassets.transport` contains the currently configured trans
Because byond browse() calls use non-blocking queues, if your code uses output() (which bypasses all of these queues) to invoke javascript functions you will need to first have the javascript announce to the server it has loaded before trying to invoke js functions.
To make your code work with any CDNs configured by the server, you must make sure assets are referenced from the url returned by `get_url_mappings()` or by asset_transport's `get_asset_url()`. (TGUI also has helpers for this.) If this can not be easily done, you can bypass the cdn using legacy assets, see the simple asset datum for details.
To make your code work with any CDNs configured by the server, you must make sure assets are referenced from the url returned by `get_url_mappings()` or by asset_transport's `get_asset_url()`. (TGUI also has helpers for this.) If this can not be easily done, you can bypass the cdn using legacy assets, see the simple asset datum for details.
CSS files that use url() can be made to use the CDN without needing to rewrite all url() calls in code by using the namespaced helper datum. See the documentation for `/datum/asset/simple/namespaced` for details.

View File

@@ -115,7 +115,7 @@
if (unreceived.len)
if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
to_chat(client, "Sending Resources...")
to_chat(client, SPAN_INFOPLAIN("Sending Resources..."))
for (var/asset_name in unreceived)
var/new_asset_name = asset_name
@@ -137,7 +137,7 @@
/// Precache files without clogging up the browse() queue, used for passively sending files on connection start.
/datum/asset_transport/proc/send_assets_slow(client/client, list/files, filerate = 3)
/datum/asset_transport/proc/send_assets_slow(client/client, list/files, filerate = 6)
var/startingfilerate = filerate
for (var/file in files)
if (!client)

View File

@@ -17,7 +17,7 @@
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
var status = xhr.status;
if (status >= 200 && status < 400) {
if (status >= 200 && status < 400) {
sendbyond('asset_cache_preload_data=' + encodeURIComponent(xhr.responseText));
}
}

View File

@@ -171,6 +171,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
tgui_panel = new(src)
GLOB.ahelp_tickets.ClientLogin(src)
SSserver_maint.UpdateHubStatus()
var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
//Admin Authorisation
holder = admin_datums[ckey]
@@ -289,7 +290,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
disconnect_with_message("Your version of BYOND ([byond_version].[byond_build]) is blacklisted for the following reason: [GLOB.blacklisted_builds[num2text(byond_build)]]. Please download a new version of byond. If [byond_build] is the latest, you can go to <a href=\"https://secure.byond.com/download/build\">BYOND's website</a> to download other versions.")
return
if(SSinput.subsystem_initialized)
if(SSinput.initialized)
set_macros()
update_movement_keys()
@@ -370,7 +371,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
to_chat(src, "<span class='info'>You have unread updates in the changelog.</span>")
winset(src, "infowindow.changelog", "background-color=#eaeaea;font-style=bold")
if(config_legacy.aggressive_changelog)
src.changes()
changelog()
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
to_chat(src, "<span class='warning'>Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.</span>")
@@ -399,12 +400,17 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.directory -= ckey
log_access("Logout: [key_name(src)]")
GLOB.ahelp_tickets.ClientLogout(src)
SSserver_maint.UpdateHubStatus()
if(holder)
holder.owner = null
admins -= src
GLOB.admins -= src //delete them on the managed one too
if(using_perspective)
set_perspective(null)
active_mousedown_item = null
SSping.currentrun -= src
. = ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening
return QDEL_HINT_HARDDEL_NOW

View File

@@ -356,4 +356,3 @@ datum/client_preference/debug/age_verified
key = "EXAMINE_LOOK"
enabled_description = "Show"
disabled_description = "Hide"

Some files were not shown because too many files have changed in this diff Show More