diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm index ed8b1cb4bfd007..d20ab946e3f9e1 100644 --- a/code/__DEFINES/rust_g.dm +++ b/code/__DEFINES/rust_g.dm @@ -48,6 +48,7 @@ /// Gets the version of rust_g /proc/rustg_get_version() return RUSTG_CALL(RUST_G, "get_version")() +// Aho-Corasick Replace // /** * Sets up the Aho-Corasick automaton with its default options. @@ -91,6 +92,8 @@ */ #define rustg_acreplace_with_replacements(key, text, replacements) RUSTG_CALL(RUST_G, "acreplace_with_replacements")(key, text, json_encode(replacements)) +// Cellular Noise // + /** * This proc generates a cellular automata noise grid which can be used in procedural generation methods. * @@ -107,6 +110,8 @@ #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) +// Grid Perlin Noise // + /** * This proc generates a grid of perlin-like noise * @@ -124,6 +129,8 @@ RUSTG_CALL(RUST_G, "dbp_generate")(seed, accuracy, stamp_size, world_size, lower_range, upper_range) +// DMI Operations // + #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) @@ -134,6 +141,8 @@ */ #define rustg_dmi_icon_states(fname) RUSTG_CALL(RUST_G, "dmi_icon_states")(fname) +// File Operations // + #define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname) #define rustg_file_exists(fname) (RUSTG_CALL(RUST_G, "file_exists")(fname) == "true") #define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname) @@ -146,14 +155,50 @@ #define text2file(text, fname) rustg_file_append(text, "[fname]") #endif +// Git Operations // + /// Returns the git hash of the given revision, ex. "HEAD". #define rustg_git_revparse(rev) RUSTG_CALL(RUST_G, "rg_git_revparse")(rev) /** - * Returns the date of the given revision in the format YYYY-MM-DD. - * Returns null if the revision is invalid. + * Returns the date of the given revision using the provided format. + * Defaults to returning %F which is YYYY-MM-DD. */ -#define rustg_git_commit_date(rev) RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev) +/proc/rustg_git_commit_date(rev, format = "%F") + return RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev, format) + +/** + * Returns the formatted datetime string of HEAD using the provided format. + * Defaults to returning %F which is YYYY-MM-DD. + * This is different to rustg_git_commit_date because it only needs the logs directory. + */ +/proc/rustg_git_commit_date_head(format = "%F") + return RUSTG_CALL(RUST_G, "rg_git_commit_date_head")(format) + +// Hashing Functions // + +#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" + +/// Encode a given string into base64 +#define rustg_encode_base64(str) rustg_hash_string(RUSTG_HASH_BASE64, str) +/// Decode a given base64 string +#define rustg_decode_base64(str) RUSTG_CALL(RUST_G, "decode_base64")(str) + +#ifdef RUSTG_OVERRIDE_BUILTINS + #define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing)) +#endif + +// HTTP Operations // #define RUSTG_HTTP_METHOD_GET "get" #define RUSTG_HTTP_METHOD_PUT "put" @@ -167,17 +212,186 @@ /proc/rustg_create_async_http_client() return RUSTG_CALL(RUST_G, "start_http_client")() /proc/rustg_close_async_http_client() return RUSTG_CALL(RUST_G, "shutdown_http_client")() +// Icon forge operations // + +/// Generates a spritesheet at: [file_path][spritesheet_name]_[size_id].png +/// The resulting spritesheet arranges icons in a random order, with the position being denoted in the "sprites" return value. +/// All icons have the same y coordinate, and their x coordinate is equal to `icon_width * position`. +/// +/// hash_icons is a boolean (0 or 1), and determines if the generator will spend time creating hashes for the output field dmi_hashes. +/// These hashes can be heplful for 'smart' caching (see rustg_iconforge_cache_valid), but require extra computation. +/// +/// Spritesheet will contain all sprites listed within "sprites". +/// "sprites" format: +/// list( +/// "sprite_name" = list( // <--- this list is a [SPRITE_OBJECT] +/// icon_file = 'icons/path_to/an_icon.dmi', +/// icon_state = "some_icon_state", +/// dir = SOUTH, +/// frame = 1, +/// transform = list([TRANSFORM_OBJECT], ...) +/// ), +/// ..., +/// ) +/// TRANSFORM_OBJECT format: +/// list("type" = RUSTG_ICONFORGE_BLEND_COLOR, "color" = "#ff0000", "blend_mode" = ICON_MULTIPLY) +/// list("type" = RUSTG_ICONFORGE_BLEND_ICON, "icon" = [SPRITE_OBJECT], "blend_mode" = ICON_OVERLAY) +/// list("type" = RUSTG_ICONFORGE_SCALE, "width" = 32, "height" = 32) +/// list("type" = RUSTG_ICONFORGE_CROP, "x1" = 1, "y1" = 1, "x2" = 32, "y2" = 32) // (BYOND icons index from 1,1 to the upper bound, inclusive) +/// +/// Returns a SpritesheetResult as JSON, containing fields: +/// list( +/// "sizes" = list("32x32", "64x64", ...), +/// "sprites" = list("sprite_name" = list("size_id" = "32x32", "position" = 0), ...), +/// "dmi_hashes" = list("icons/path_to/an_icon.dmi" = "d6325c5b4304fb03", ...), +/// "sprites_hash" = "a2015e5ff403fb5c", // This is the xxh64 hash of the INPUT field "sprites". +/// "error" = "[A string, empty if there were no errors.]" +/// ) +/// In the case of an unrecoverable panic from within Rust, this function ONLY returns a string containing the error. +#define rustg_iconforge_generate(file_path, spritesheet_name, sprites, hash_icons) RUSTG_CALL(RUST_G, "iconforge_generate")(file_path, spritesheet_name, sprites, "[hash_icons]") +/// Returns a job_id for use with rustg_iconforge_check() +#define rustg_iconforge_generate_async(file_path, spritesheet_name, sprites, hash_icons) RUSTG_CALL(RUST_G, "iconforge_generate_async")(file_path, spritesheet_name, sprites, "[hash_icons]") +/// Returns the status of an async job_id, or its result if it is completed. See RUSTG_JOB DEFINEs. +#define rustg_iconforge_check(job_id) RUSTG_CALL(RUST_G, "iconforge_check")("[job_id]") +/// Clears all cached DMIs and images, freeing up memory. +/// This should be used after spritesheets are done being generated. +#define rustg_iconforge_cleanup RUSTG_CALL(RUST_G, "iconforge_cleanup") +/// Takes in a set of hashes, generate inputs, and DMI filepaths, and compares them to determine cache validity. +/// input_hash: xxh64 hash of "sprites" from the cache. +/// dmi_hashes: xxh64 hashes of the DMIs in a spritesheet, given by `rustg_iconforge_generate` with `hash_icons` enabled. From the cache. +/// sprites: The new input that will be passed to rustg_iconforge_generate(). +/// Returns a CacheResult with the following structure: list( +/// "result": "1" (if cache is valid) or "0" (if cache is invalid) +/// "fail_reason": "" (emtpy string if valid, otherwise a string containing the invalidation reason or an error with ERROR: prefixed.) +/// ) +/// In the case of an unrecoverable panic from within Rust, this function ONLY returns a string containing the error. +#define rustg_iconforge_cache_valid(input_hash, dmi_hashes, sprites) RUSTG_CALL(RUST_G, "iconforge_cache_valid")(input_hash, dmi_hashes, sprites) +/// Returns a job_id for use with rustg_iconforge_check() +#define rustg_iconforge_cache_valid_async(input_hash, dmi_hashes, sprites) RUSTG_CALL(RUST_G, "iconforge_cache_valid_async")(input_hash, dmi_hashes, sprites) + +#define RUSTG_ICONFORGE_BLEND_COLOR "BlendColor" +#define RUSTG_ICONFORGE_BLEND_ICON "BlendIcon" +#define RUSTG_ICONFORGE_CROP "Crop" +#define RUSTG_ICONFORGE_SCALE "Scale" + +// Jobs Defines // + #define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET" #define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB" #define RUSTG_JOB_ERROR "JOB PANICKED" +// JSON Operations // + #define rustg_json_is_valid(text) (RUSTG_CALL(RUST_G, "json_is_valid")(text) == "true") +// Logging Operations // #define rustg_log_write(fname, text, format) RUSTG_CALL(RUST_G, "log_write")(fname, text, format) /proc/rustg_log_close_all() return RUSTG_CALL(RUST_G, "log_close_all")() +// Noise Operations // + #define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y) +/** + * Generates a 2D poisson disk distribution ('blue noise'), which is relatively uniform. + * + * params: + * `seed`: str + * `width`: int, width of the noisemap (see world.maxx) + * `length`: int, height of the noisemap (see world.maxy) + * `radius`: int, distance between points on the noisemap + * + * returns: + * a width*length length string of 1s and 0s representing a 2D poisson sample collapsed into a 1D string + */ +#define rustg_noise_poisson_map(seed, width, length, radius) RUSTG_CALL(RUST_G, "noise_poisson_map")(seed, width, length, radius) + +// AStar Operations // + +/** + * 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_astar(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]") + +// Redis PubSub Operations // + +#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) + +// Redis Reliable Queue Operations // + +/** + * 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) + /* * Takes in a string and json_encode()"d lists to produce a sanitized string. * This function operates on whitelists, there is currently no way to blacklist. @@ -188,6 +402,8 @@ */ #define rustg_sanitize_html(text, attribute_whitelist_json, tag_whitelist_json) RUSTG_CALL(RUST_G, "sanitize_html")(text, attribute_whitelist_json, tag_whitelist_json) +// SQL Operations // + #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) @@ -195,6 +411,13 @@ #define rustg_sql_disconnect_pool(handle) RUSTG_CALL(RUST_G, "sql_disconnect_pool")(handle) #define rustg_sql_check_query(job_id) RUSTG_CALL(RUST_G, "sql_check_query")("[job_id]") +// Text Operations // + +#define rustg_cyrillic_to_latin(text) RUSTG_CALL(RUST_G, "cyrillic_to_latin")("[text]") +#define rustg_latin_to_cyrillic(text) RUSTG_CALL(RUST_G, "latin_to_cyrillic")("[text]") + +// Time Tracking Functions // + #define rustg_time_microseconds(id) text2num(RUSTG_CALL(RUST_G, "time_microseconds")(id)) #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) @@ -203,6 +426,12 @@ /proc/rustg_unix_timestamp() return RUSTG_CALL(RUST_G, "unix_timestamp")() +// Toast Operations // + +#define rustg_create_toast(title, body) RUSTG_CALL(RUST_G, "create_toast")(title, body) + +// TOML Operations // + #define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null") /proc/rustg_read_toml_file(path) @@ -221,6 +450,13 @@ else CRASH(output["content"]) +// ZIP File Operations // + +#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]") + +// URL Operations // + #define rustg_url_encode(text) RUSTG_CALL(RUST_G, "url_encode")("[text]") #define rustg_url_decode(text) RUSTG_CALL(RUST_G, "url_decode")(text) @@ -229,3 +465,22 @@ #define url_decode(text) rustg_url_decode(text) #endif +// Worley Noise Operations // + +/** + * 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/dependencies.sh b/dependencies.sh index 1cd8d6f5dc5881..519f3a1a4ddf2c 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -8,7 +8,7 @@ export BYOND_MAJOR=515 export BYOND_MINOR=1637 #rust_g git tag -export RUST_G_VERSION=3.0.0-ss220 +export RUST_G_VERSION=3.3.0-ss220 #node version export NODE_VERSION_LTS=20.13.0 diff --git a/rust_g.dll b/rust_g.dll index df1aca145f46fd..c77db3ec9c65e5 100644 Binary files a/rust_g.dll and b/rust_g.dll differ