diff --git a/citadel.dme b/citadel.dme index bf6b35b147f..6bba67870eb 100644 --- a/citadel.dme +++ b/citadel.dme @@ -338,6 +338,7 @@ #include "code\__HELPERS\icons\download.dm" #include "code\__HELPERS\icons\flatten.dm" #include "code\__HELPERS\icons\hologram.dm" +#include "code\__HELPERS\icons\metadata.dm" #include "code\__HELPERS\lists\_string_lists.dm" #include "code\__HELPERS\lists\asset_sorted.dm" #include "code\__HELPERS\lists\associations.dm" diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm index fed30f30472..2d506e79965 100644 --- a/code/__DEFINES/rust_g.dm +++ b/code/__DEFINES/rust_g.dm @@ -107,9 +107,28 @@ #define rustg_cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) \ RUSTG_CALL(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height) +/** + * This proc generates a grid of perlin-like noise + * + * Returns a single string that goes row by row, with values of 1 representing an turned on cell, and a value of 0 representing a turned off cell. + * + * Arguments: + * * seed: seed for the function + * * accuracy: how close this is to the original perlin noise, as accuracy approaches infinity, the noise becomes more and more perlin-like + * * stamp_size: Size of a singular stamp used by the algorithm, think of this as the same stuff as frequency in perlin noise + * * world_size: size of the returned grid. + * * lower_range: lower bound of values selected for. (inclusive) + * * upper_range: upper bound of values selected for. (exclusive) + */ +#define rustg_dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range) \ + RUSTG_CALL(RUST_G, "dbp_generate")(seed, accuracy, stamp_size, world_size, lower_range, upper_range) + + #define rustg_dmi_strip_metadata(fname) RUSTG_CALL(RUST_G, "dmi_strip_metadata")(fname) #define rustg_dmi_create_png(path, width, height, data) RUSTG_CALL(RUST_G, "dmi_create_png")(path, width, height, data) #define rustg_dmi_resize_png(path, width, height, resizetype) RUSTG_CALL(RUST_G, "dmi_resize_png")(path, width, height, resizetype) +/// output: json_encode'd list. json_decode to get a flat list with icon states in the order they're in inside the .dmi +#define rustg_dmi_icon_states(fname) RUSTG_CALL(RUST_G, "dmi_icon_states")(fname) #define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname) #define rustg_file_exists(fname) RUSTG_CALL(RUST_G, "file_exists")(fname) @@ -126,6 +145,22 @@ #define rustg_git_revparse(rev) RUSTG_CALL(RUST_G, "rg_git_revparse")(rev) #define rustg_git_commit_date(rev) RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev) +#define rustg_hash_string(algorithm, text) RUSTG_CALL(RUST_G, "hash_string")(algorithm, text) +#define rustg_hash_file(algorithm, fname) RUSTG_CALL(RUST_G, "hash_file")(algorithm, fname) +#define rustg_hash_generate_totp(seed) RUSTG_CALL(RUST_G, "generate_totp")(seed) +#define rustg_hash_generate_totp_tolerance(seed, tolerance) RUSTG_CALL(RUST_G, "generate_totp_tolerance")(seed, tolerance) + +#define RUSTG_HASH_MD5 "md5" +#define RUSTG_HASH_SHA1 "sha1" +#define RUSTG_HASH_SHA256 "sha256" +#define RUSTG_HASH_SHA512 "sha512" +#define RUSTG_HASH_XXH64 "xxh64" +#define RUSTG_HASH_BASE64 "base64" + +#ifdef RUSTG_OVERRIDE_BUILTINS + #define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing)) +#endif + #define RUSTG_HTTP_METHOD_GET "get" #define RUSTG_HTTP_METHOD_PUT "put" #define RUSTG_HTTP_METHOD_DELETE "delete" @@ -147,6 +182,86 @@ #define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y) +/** + * Register a list of nodes into a rust library. This list of nodes must have been serialized in a json. + * Node {// Index of this node in the list of nodes + * unique_id: usize, + * // Position of the node in byond + * x: usize, + * y: usize, + * z: usize, + * // Indexes of nodes connected to this one + * connected_nodes_id: Vec} + * It is important that the node with the unique_id 0 is the first in the json, unique_id 1 right after that, etc. + * It is also important that all unique ids follow. {0, 1, 2, 4} is not a correct list and the registering will fail + * Nodes should not link across z levels. + * A node cannot link twice to the same node and shouldn't link itself either + */ +#define rustg_register_nodes_astar(json) RUSTG_CALL(RUST_G, "register_nodes_astar")(json) + +/** + * Add a new node to the static list of nodes. Same rule as registering_nodes applies. + * This node unique_id must be equal to the current length of the static list of nodes + */ +#define rustg_add_node_astar(json) RUSTG_CALL(RUST_G, "add_node_astar")(json) + +/**² + * Remove every link to the node with unique_id. Replace that node by null + */ +#define rustg_remove_node_astart(unique_id) RUSTG_CALL(RUST_G, "remove_node_astar")(unique_id) + +/** + * Compute the shortest path between start_node and goal_node using A*. Heuristic used is simple geometric distance + */ +#define rustg_generate_path_astar(start_node_id, goal_node_id) RUSTG_CALL(RUST_G, "generate_path_astar")(start_node_id, goal_node_id) + +#define RUSTG_REDIS_ERROR_CHANNEL "RUSTG_REDIS_ERROR_CHANNEL" + +#define rustg_redis_connect(addr) RUSTG_CALL(RUST_G, "redis_connect")(addr) +/proc/rustg_redis_disconnect() return RUSTG_CALL(RUST_G, "redis_disconnect")() +#define rustg_redis_subscribe(channel) RUSTG_CALL(RUST_G, "redis_subscribe")(channel) +/proc/rustg_redis_get_messages() return RUSTG_CALL(RUST_G, "redis_get_messages")() +#define rustg_redis_publish(channel, message) RUSTG_CALL(RUST_G, "redis_publish")(channel, message) + +/** + * Connects to a given redis server. + * + * Arguments: + * * addr - The address of the server, for example "redis://127.0.0.1/" + */ +#define rustg_redis_connect_rq(addr) RUSTG_CALL(RUST_G, "redis_connect_rq")(addr) +/** + * Disconnects from a previously connected redis server + */ +/proc/rustg_redis_disconnect_rq() return RUSTG_CALL(RUST_G, "redis_disconnect_rq")() +/** + * https://redis.io/commands/lpush/ + * + * Arguments + * * key (string) - The key to use + * * elements (list) - The elements to push, use a list even if there's only one element. + */ +#define rustg_redis_lpush(key, elements) RUSTG_CALL(RUST_G, "redis_lpush")(key, json_encode(elements)) +/** + * https://redis.io/commands/lrange/ + * + * Arguments + * * key (string) - The key to use + * * start (string) - The zero-based index to start retrieving at + * * stop (string) - The zero-based index to stop retrieving at (inclusive) + */ +#define rustg_redis_lrange(key, start, stop) RUSTG_CALL(RUST_G, "redis_lrange")(key, start, stop) +/** + * https://redis.io/commands/lpop/ + * + * Arguments + * * key (string) - The key to use + * * count (string|null) - The amount to pop off the list, pass null to omit (thus just 1) + * + * Note: `count` was added in Redis version 6.2.0 + */ +#define rustg_redis_lpop(key, count) RUSTG_CALL(RUST_G, "redis_lpop")(key, count) + #define rustg_sql_connect_pool(options) RUSTG_CALL(RUST_G, "sql_connect_pool")(options) #define rustg_sql_query_async(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_async")(handle, query, params) #define rustg_sql_query_blocking(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_blocking")(handle, query, params) @@ -158,8 +273,9 @@ #define rustg_time_milliseconds(id) text2num(RUSTG_CALL(RUST_G, "time_milliseconds")(id)) #define rustg_time_reset(id) RUSTG_CALL(RUST_G, "time_reset")(id) +/// Returns the timestamp as a string /proc/rustg_unix_timestamp() - return text2num(RUSTG_CALL(RUST_G, "unix_timestamp")()) + return RUSTG_CALL(RUST_G, "unix_timestamp")() #define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null") @@ -179,6 +295,9 @@ else CRASH(output["content"]) +#define rustg_unzip_download_async(url, unzip_directory) RUSTG_CALL(RUST_G, "unzip_download_async")(url, unzip_directory) +#define rustg_unzip_check(job_id) RUSTG_CALL(RUST_G, "unzip_check")("[job_id]") + #define rustg_url_encode(text) RUSTG_CALL(RUST_G, "url_encode")("[text]") #define rustg_url_decode(text) RUSTG_CALL(RUST_G, "url_decode")(text) @@ -186,3 +305,21 @@ #define url_encode(text) rustg_url_encode(text) #define url_decode(text) rustg_url_decode(text) #endif + +/** + * This proc generates a noise grid using worley noise algorithm + * + * Returns a single string that goes row by row, with values of 1 representing an alive cell, and a value of 0 representing a dead cell. + * + * Arguments: + * * region_size: The size of regions + * * threshold: the value that determines wether a cell is dead or alive + * * node_per_region_chance: chance of a node existiing in a region + * * size: size of the returned grid + * * node_min: minimum amount of nodes in a region (after the node_per_region_chance is applied) + * * node_max: maximum amount of nodes in a region + */ +#define rustg_worley_generate(region_size, threshold, node_per_region_chance, size, node_min, node_max) \ + RUSTG_CALL(RUST_G, "worley_generate")(region_size, threshold, node_per_region_chance, size, node_min, node_max) + + diff --git a/code/__HELPERS/icons/metadata.dm b/code/__HELPERS/icons/metadata.dm new file mode 100644 index 00000000000..31f4eb83e21 --- /dev/null +++ b/code/__HELPERS/icons/metadata.dm @@ -0,0 +1,35 @@ +/** + * icon_states() but doesn't leak memory out the ass + * + * warning: this is actually pretty slow on runtime loaded or created /file and /icon objects. + * try not to use this on those. + */ +/proc/fast_icon_states(what) + #define TEMPORARY_FILE "data/tmp/rustg_icon_states.dmi" + if(isfile(what)) + var/into_path = "[what]" + if(length(into_path)) + // compiled + . = rustg_dmi_icon_states(into_path) + else + // runtime + if(!fcopy(what, TEMPORARY_FILE)) + CRASH("failed to fcopy") + . = rustg_dmi_icon_states(TEMPORARY_FILE) + if(!fdel(TEMPORARY_FILE)) + CRASH("failed to fdel") + else if(isicon(what)) + // always runtime + if(!fcopy(what, TEMPORARY_FILE)) + CRASH("failed to fcopy") + . = rustg_dmi_icon_states(TEMPORARY_FILE) + if(!fdel(TEMPORARY_FILE)) + CRASH("failed to fdel") + else if(istext(what)) + // assume path on server + . = rustg_dmi_icon_states(what) + if(!length(.)) + . = list() + CRASH("failed to run icon states; please check the input / source.") + . = json_decode(.) + #undef TEMPORARY_FILE diff --git a/code/modules/mob/inventory/slot_meta.dm b/code/modules/mob/inventory/slot_meta.dm index 21d96f19f3e..db9702f534b 100644 --- a/code/modules/mob/inventory/slot_meta.dm +++ b/code/modules/mob/inventory/slot_meta.dm @@ -183,7 +183,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache) render_default_icons -= bodytype_str continue var/icon/I = render_default_icons[bodytype_str] - render_state_cache[bodytype_str] = icon_states(I) + render_state_cache[bodytype_str] = fast_icon_states(I) // turn into hash for(var/state in render_state_cache[bodytype_str]) render_state_cache[bodytype_str][state] = TRUE @@ -300,7 +300,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache) render_rolldown_icons -= bodytype_str continue var/icon/I = render_rolldown_icons[bodytype_str] - render_rolldown_states[bodytype_str] = icon_states(I) + render_rolldown_states[bodytype_str] = fast_icon_states(I) // turn into hash for(var/state in render_rolldown_states[bodytype_str]) render_rolldown_states[bodytype_str][state] = TRUE @@ -312,7 +312,7 @@ GLOBAL_LIST_EMPTY(inventory_slot_type_cache) render_rollsleeve_icons -= bodytype_str continue var/icon/I = render_rollsleeve_icons[bodytype_str] - render_rollsleeve_states[bodytype_str] = icon_states(I) + render_rollsleeve_states[bodytype_str] = fast_icon_states(I) // turn into hash for(var/state in render_rollsleeve_states[bodytype_str]) render_rollsleeve_states[bodytype_str][state] = TRUE diff --git a/dependencies.sh b/dependencies.sh index 034ffb8140a..43ab9f9eaf5 100755 --- a/dependencies.sh +++ b/dependencies.sh @@ -8,7 +8,7 @@ export BYOND_MAJOR=514 export BYOND_MINOR=1588 #rust_g git tag -export RUST_G_VERSION=0.7.0 +export RUST_G_VERSION=2.0.1-experimental-1 #node version export NODE_VERSION=14 diff --git a/maps/rift/levels/rift-06-surface3.dmm b/maps/rift/levels/rift-06-surface3.dmm index 97002b83201..78c25f74bd9 100644 --- a/maps/rift/levels/rift-06-surface3.dmm +++ b/maps/rift/levels/rift-06-surface3.dmm @@ -23323,7 +23323,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/fuel{ dir = 4 }, -/obj/overmap/entity/visitable/ship/landable/excursion, +/obj/overmap/entity/visitable/ship/landable/excursion/rift, /obj/effect/shuttle_landmark/rift/deck3/excursion, /obj/structure/cable/orange{ icon_state = "4-8" diff --git a/maps/tether/levels/station2.dmm b/maps/tether/levels/station2.dmm index bc67e90c818..3c8f4c9b320 100644 --- a/maps/tether/levels/station2.dmm +++ b/maps/tether/levels/station2.dmm @@ -6757,7 +6757,7 @@ landmark_tag = "tether_excursion_hangar"; name = "Excursion Shuttle Dock" }, -/obj/overmap/entity/visitable/ship/landable/excursion, +/obj/overmap/entity/visitable/ship/landable/excursion/tether, /turf/simulated/floor/tiled/techmaint, /area/shuttle/excursion/general) "axK" = ( diff --git a/rust_g.dll b/rust_g.dll index be19f57946d..ccce4d80d9a 100644 Binary files a/rust_g.dll and b/rust_g.dll differ diff --git a/tools/ci/install_rust_g.sh b/tools/ci/install_rust_g.sh index c237162d8fa..d53f083b2c9 100755 --- a/tools/ci/install_rust_g.sh +++ b/tools/ci/install_rust_g.sh @@ -4,6 +4,6 @@ set -euo pipefail source dependencies.sh mkdir -p ~/.byond/bin -wget -nv -O ~/.byond/bin/librust_g.so "https://github.com/tgstation/rust-g/releases/download/$RUST_G_VERSION/librust_g.so" +wget -nv -O ~/.byond/bin/librust_g.so "https://github.com/Citadel-Station-13/rust-g/releases/download/$RUST_G_VERSION/librust_g.so" chmod +x ~/.byond/bin/librust_g.so ldd ~/.byond/bin/librust_g.so diff --git a/tools/deploy.sh b/tools/deploy.sh index 9674e83f28d..ac0a4892adc 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -12,8 +12,8 @@ fi mkdir -p \ $1/_mapload \ $1/maps \ - $1/icons/runtime \ - $1/sound/runtime \ + $1/icons \ + $1/sound \ $1/strings \ $1/tgui/public \ $1/tgui/packages/tgfont/dist @@ -24,19 +24,21 @@ if [ -d ".git" ]; then fi cp citadel.dmb citadel.rsc $1/ -# todo: remove _mapload after .jsons are removed. +# mapload: has basemap.dmm, runtime loaded cp -r _mapload/* $1/_mapload/ -# todo: filter out .dm files +# maps: map .dmms and potential assets, runtime loaded cp -r maps/* $1/maps/ -cp -r icons/runtime/* $1/icons/runtime/ -cp -r sound/runtime/* $1/sound/runtime/ +# icons: .dmi assets, runtime loaded +cp -r icons/* $1/icons/ +# sounds: .ogg, etc assets, runtime loaded +cp -r sound/* $1/sound/ +# strings: .txts, .jsons, runtime loaded cp -r strings/* $1/strings/ +# tgui artifacts: sent to clients, should be present at runtime cp -r tgui/public/* $1/tgui/public/ +# tgfont artifacts: sent to clients, should be present at runtime cp -r tgui/packages/tgfont/dist/* $1/tgui/packages/tgfont/dist/ -#this regrettably doesn't work with windows find -#find $1/maps -name "*.dm" -type f -delete - #dlls on windows if [ "$(uname -o)" = "Msys" ]; then cp ./*.dll $1/ diff --git a/tools/tgs4_scripts/PreCompile.sh b/tools/tgs4_scripts/PreCompile.sh index 69a6f35cf64..52aba4457be 100755 --- a/tools/tgs4_scripts/PreCompile.sh +++ b/tools/tgs4_scripts/PreCompile.sh @@ -50,7 +50,7 @@ apt-get install -y lib32z1 pkg-config libssl-dev:i386 libssl-dev libssl1.1:i386 # update rust-g if [ ! -d "rust-g" ]; then echo "Cloning rust-g..." - git clone https://github.com/tgstation/rust-g + git clone https://github.com/Citadel-Station-13/rust-g cd rust-g ~/.cargo/bin/rustup target add i686-unknown-linux-gnu else @@ -62,7 +62,7 @@ fi echo "Deploying rust-g..." git checkout "$RUST_G_VERSION" -env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target=i686-unknown-linux-gnu +env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target=i686-unknown-linux-gnu --all-features mv target/i686-unknown-linux-gnu/release/librust_g.so "$1/librust_g.so" cd ..