diff --git a/crates/byondapi-rs/Cargo.toml b/crates/byondapi-rs/Cargo.toml
index e02950e..c3ef9e0 100644
--- a/crates/byondapi-rs/Cargo.toml
+++ b/crates/byondapi-rs/Cargo.toml
@@ -20,5 +20,5 @@ walkdir = "2.4.0"
 inventory = "0.3.13"
 
 [features]
-default = ["byond-515-1620"]
-byond-515-1620 = []
+default = ["byond-515-1621"]
+byond-515-1621 = []
diff --git a/crates/byondapi-rs/src/lib.rs b/crates/byondapi-rs/src/lib.rs
index 2860032..d8671a2 100644
--- a/crates/byondapi-rs/src/lib.rs
+++ b/crates/byondapi-rs/src/lib.rs
@@ -10,7 +10,6 @@ pub use error::Error;
 
 pub mod byond_string;
 pub mod global_call;
-pub mod list;
 pub mod prelude;
 pub mod typecheck_trait;
 pub mod value;
@@ -50,10 +49,15 @@ pub struct InitFunc(pub fn() -> ());
 #[macro_export]
 macro_rules! byond_string {
     ($s:literal) => {{
-        thread_local! {
-            static STRING_ID: ::std::cell::OnceCell<u32> = ::std::cell::OnceCell::new();
-        };
-        STRING_ID
-            .with(|cell| *cell.get_or_init(|| ::byondapi::byond_string::str_id_of($s).unwrap()))
+        static STRING_ID: ::std::sync::OnceLock<u32> = ::std::sync::OnceLock::new();
+        *STRING_ID.get_or_init(|| ::byondapi::byond_string::str_id_of($s).unwrap())
+    }};
+}
+
+#[macro_export]
+macro_rules! byond_string_internal {
+    ($s:literal) => {{
+        static STRING_ID: ::std::sync::OnceLock<u32> = ::std::sync::OnceLock::new();
+        *STRING_ID.get_or_init(|| crate::byond_string::str_id_of($s).unwrap())
     }};
 }
diff --git a/crates/byondapi-rs/src/map.rs b/crates/byondapi-rs/src/map.rs
index c2fd384..d46fdfe 100644
--- a/crates/byondapi-rs/src/map.rs
+++ b/crates/byondapi-rs/src/map.rs
@@ -56,7 +56,6 @@ pub fn byond_block(corner1: ByondXYZ, corner2: ByondXYZ) -> Result<Vec<ByondValu
                     ))?
                 };
 
-                println!("len after second block is {len}");
                 // Safety: buffer should be written to at this point
                 unsafe { buff.set_len(len as usize) };
                 Ok(std::mem::take(buff))
diff --git a/crates/byondapi-rs/src/prelude.rs b/crates/byondapi-rs/src/prelude.rs
index 8dbabb1..e698d61 100644
--- a/crates/byondapi-rs/src/prelude.rs
+++ b/crates/byondapi-rs/src/prelude.rs
@@ -37,4 +37,5 @@ pub use byondapi_sys::ByondValueType as InternalByondValueType;
 pub use byondapi_sys::CByondValue as InternalByondValue;
 
 // As well as our own types.
+pub use crate::byond_string;
 pub use crate::value::ByondValue;
diff --git a/crates/byondapi-rs/src/typecheck_trait.rs b/crates/byondapi-rs/src/typecheck_trait.rs
index d38ece8..7514f2e 100644
--- a/crates/byondapi-rs/src/typecheck_trait.rs
+++ b/crates/byondapi-rs/src/typecheck_trait.rs
@@ -17,5 +17,5 @@ pub trait ByondTypeCheck {
     /// Check if this is a pointer.
     fn is_ptr(&self) -> bool;
     //// Check if this is true-ish.
-    //fn is_true(&self) -> bool;
+    fn is_true(&self) -> bool;
 }
diff --git a/crates/byondapi-rs/src/value/constructors.rs b/crates/byondapi-rs/src/value/constructors.rs
index 0fd88cd..1460b38 100644
--- a/crates/byondapi-rs/src/value/constructors.rs
+++ b/crates/byondapi-rs/src/value/constructors.rs
@@ -47,6 +47,16 @@ impl ByondValue {
         })
     }
 
+    pub fn new_global_ref() -> Self {
+        Self(CByondValue {
+            type_: 0x0E,
+            junk1: 0,
+            junk2: 0,
+            junk3: 0,
+            data: byondapi_sys::ByondValueData { ref_: 1 },
+        })
+    }
+
     pub fn new_str<S: Into<Vec<u8>>>(s: S) -> Result<Self, Error> {
         let c_str = CString::new(s.into()).unwrap();
         let str_id = unsafe { byond().Byond_AddGetStrId(c_str.as_ptr()) };
diff --git a/crates/byondapi-rs/src/value/functions.rs b/crates/byondapi-rs/src/value/functions.rs
index 24387f6..0d68523 100644
--- a/crates/byondapi-rs/src/value/functions.rs
+++ b/crates/byondapi-rs/src/value/functions.rs
@@ -235,8 +235,22 @@ impl ByondValue {
     }
 }
 
-/// # List operations by key instead of indices (why are they even here lumlum?????)
-impl ByondValue {}
+/// # Refcount operations
+impl ByondValue {
+    pub fn increment_ref(&mut self) {
+        unsafe { byond().ByondValue_IncRef(&self.0) }
+    }
+
+    pub fn decrement_ref(&mut self) {
+        unsafe { byond().ByondValue_DecRef(&self.0) }
+    }
+
+    pub fn get_refcount(&self) -> Result<u32, Error> {
+        let mut result = 0u32;
+        unsafe { map_byond_error!(byond().Byond_Refcount(&self.0, &mut result))? };
+        Ok(result)
+    }
+}
 
 /// # Builtins
 impl ByondValue {
diff --git a/crates/byondapi-rs/src/list.rs b/crates/byondapi-rs/src/value/list.rs
similarity index 92%
rename from crates/byondapi-rs/src/list.rs
rename to crates/byondapi-rs/src/value/list.rs
index 7f84761..905c095 100644
--- a/crates/byondapi-rs/src/list.rs
+++ b/crates/byondapi-rs/src/value/list.rs
@@ -1,7 +1,10 @@
-use crate::{static_global::byond, typecheck_trait::ByondTypeCheck, value::ByondValue, Error};
+use crate::{
+    byond_string_internal, static_global::byond, typecheck_trait::ByondTypeCheck,
+    value::ByondValue, Error,
+};
 /// List stuff goes here, Keep in mind that all indexing method starts at zero instead of one like byondland
 impl ByondValue {
-    /// Gets an array of all the list elements, this includes both keys and values for assoc lists, in an arbitrary order
+    /// Gets an array of all the list elements, this means keys for assoc lists and values for regular lists
     pub fn get_list(&self) -> Result<Vec<ByondValue>, Error> {
         use std::cell::RefCell;
         if !self.is_list() {
@@ -103,7 +106,7 @@ impl ByondValue {
         if !self.is_list() {
             return Err(Error::NotAList);
         }
-        self.call("Add", &[value])?;
+        self.call_id(byond_string_internal!("Add"), &[value])?;
         Ok(())
     }
 
@@ -117,7 +120,7 @@ impl ByondValue {
             return Ok(None);
         }
         let value = self.read_list_index(len as f32)?;
-        self.call("Remove", &[value])?;
+        self.call_id(byond_string_internal!("Remove"), &[value])?;
         Ok(Some(value))
     }
 }
diff --git a/crates/byondapi-rs/src/value/mod.rs b/crates/byondapi-rs/src/value/mod.rs
index fadf956..ca0f883 100644
--- a/crates/byondapi-rs/src/value/mod.rs
+++ b/crates/byondapi-rs/src/value/mod.rs
@@ -15,6 +15,7 @@ unsafe impl Send for ByondValue {}
 pub mod constructors;
 pub mod conversion;
 pub mod functions;
+pub mod list;
 pub mod pointer;
 pub mod trait_impls;
 
@@ -55,8 +56,8 @@ impl ByondTypeCheck for ByondValue {
         is_pointer_shim(self)
     }
 
-    // fn is_true(&self) -> bool {
-    //     // Safety: This operation only fails if our CByondValue is invalid, which cannot happen.
-    //     unsafe { byond().ByondValue_IsTrue(&self.0) }
-    // }
+    fn is_true(&self) -> bool {
+        // Safety: This operation only fails if our CByondValue is invalid, which cannot happen.
+        unsafe { byond().ByondValue_IsTrue(&self.0) }
+    }
 }
diff --git a/crates/byondapi-sys/Cargo.toml b/crates/byondapi-sys/Cargo.toml
index 22e3ef1..b744140 100644
--- a/crates/byondapi-sys/Cargo.toml
+++ b/crates/byondapi-sys/Cargo.toml
@@ -25,5 +25,5 @@ rustc_version = "0.4.0"
 walkdir = "2.4.0"
 
 [features]
-default = ["byond-515-1620"]
-byond-515-1620 = []
+default = ["byond-515-1621"]
+byond-515-1621 = []
diff --git a/crates/byondapi-sys/headers/515-1621/byondapi.h b/crates/byondapi-sys/headers/515-1621/byondapi.h
new file mode 100644
index 0000000..4e76454
--- /dev/null
+++ b/crates/byondapi-sys/headers/515-1621/byondapi.h
@@ -0,0 +1,609 @@
+#ifndef BYONDAPI_H
+#define BYONDAPI_H
+
+/*
+	BYOND public API version 515.1621
+
+	Because for some reason nobody can get their ducks in a row, all of the
+	exported functions from byondcore.dll/libbyond.so are limited to C
+	conventions only. A header and source file for C++ wrappers is available
+	for inclusion in your projects.
+ */
+
+#if defined(WIN32) || defined(WIN64)
+#define IS_WINDOWS
+#else
+#define IS_LINUX
+#endif
+
+
+// See https://github.com/cpredef/predef/blob/master/Architectures.md
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__X86__)
+#define _X86
+#define _X86ORX64
+#define DM_32BIT
+#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || defined(_WIN64) || defined(WIN64)
+#define _X64
+#define _X86ORX64
+#define DM_64BIT
+#elif defined(__arm__) || defined(_M_ARM)
+#define _ARM
+#if defined(__LP64__) || defined(_LP64)
+#define DM_64BIT
+#else
+#define DM_32BIT
+#endif
+#endif
+
+
+
+/*types*/
+typedef unsigned char  u1c;
+typedef signed   char  s1c;
+typedef unsigned short u2c;
+typedef signed   short s2c;
+#ifdef DM_64BIT
+typedef unsigned int   u4c;
+typedef signed   int   s4c;
+#else
+typedef unsigned long  u4c;
+typedef signed   long  s4c;
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+  typedef __int64 s8c;
+  typedef unsigned __int64 u8c;
+#else
+  typedef long long int s8c;
+  typedef unsigned long long int u8c;
+#endif
+
+union u4cOrPointer {
+	u4c num;
+	void *ptr;
+};
+
+#ifdef __GNUC__
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#else
+#define GCC_VERSION 0
+#endif
+
+
+// determine if move-constructor and move-assignment are supported
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+#define _SUPPORT_MOVES
+#elif defined(__GNUC__) && GCC_VERSION >= 50000
+#define _SUPPORT_MOVES
+#endif
+
+
+#define u1cMASK ((u1c)0xff)
+#define u2cMASK ((u2c)0xffff)
+#define u3cMASK ((u4c)0xffffffL)
+#define u4cMASK ((u4c)0xffffffffL)
+
+#define u1cMAX u1cMASK
+#define u2cMAX u2cMASK
+#define u3cMAX u3cMASK
+#define u4cMAX u4cMASK
+
+#define s1cMAX 0x7f
+#define s1cMIN (-0x7f)
+#define s2cMAX 0x7fff
+#define s2cMIN (-0x7fff)
+#define s4cMAX 0x7fffffffL
+#define s4cMIN (-0x7fffffffL)
+
+#define NONE u2cMAX
+#define NOCH u1cMAX
+
+#ifdef WIN32
+#define THREAD_VAR __declspec(thread)
+#else
+#define THREAD_VAR __thread
+#endif
+
+/* dll export stuff */
+#ifdef WIN32
+#define DUNGPUB    __declspec(dllimport)
+#define BYOND_EXPORT __declspec(dllexport)	// for functions in user-defined DLLs for use with call_ext()
+#else // unix/g++, combine with -fvisibility=hidden to hide non-exported symbols
+#define DUNGPUB
+#define BYOND_EXPORT __attribute__ ((visibility("default")))	// for functions in user-defined .so libraries for use with call_ext()
+#endif
+
+
+// ByondValue
+
+/*
+	Many of the routines in this library return a bool value. If true, the
+	operation succeeded. If false, it failed and calling Byond_LastError() will
+	return an error string.
+
+	The C++ wrappers change this true/false behavior to raise exceptions instead.
+	This would be preferable across the board but throwing exceptions across
+	module boundaries is bad juju.
+ */
+
+extern "C" {
+
+/**
+ * Gets the last error from a failed call
+ * The result is a static string that does not need to be freed.
+ * @return Error message
+ */
+DUNGPUB char const *Byond_LastError();
+
+/**
+ * Gets the current BYOND version
+ * @param version Pointer to the major version number
+ * @param build Pointer to the build number
+ */
+DUNGPUB void Byond_GetVersion(u4c *version, u4c *build);
+
+/**
+ * Gets the DMB version
+ * @return Version number the .dmb was built with
+ */
+DUNGPUB u4c Byond_GetDMBVersion();
+
+typedef u1c ByondValueType;
+union ByondValueData {
+	u4c ref;	//!< 4-byte reference ID
+	float num;	//!< floating-point number
+};
+
+struct CByondValue {
+	ByondValueType type;	//!< 1-byte intrinsic data type
+	u1c junk1, junk2, junk3;	//!< padding
+	ByondValueData data;	//!< 4-byte reference ID or floating point number
+};
+
+/**
+ * Fills a CByondValue struct with a null value.
+ * @param v Pointer to CByondValue
+ */
+DUNGPUB void ByondValue_Clear(CByondValue *v);
+
+/**
+ * Reads CByondVale's 1-byte data type
+ * @param v Pointer to CByondValue
+ * @return Type of value
+ */
+DUNGPUB ByondValueType ByondValue_Type(CByondValue const *v);
+
+/**
+ * @param v Pointer to CByondValue
+ * @return True if value is null
+ */
+DUNGPUB bool ByondValue_IsNull(CByondValue const *v);
+/**
+ * @param v Pointer to CByondValue
+ * @return True if value is a numeric type
+ */
+DUNGPUB bool ByondValue_IsNum(CByondValue const *v);
+/**
+ * @param v Pointer to CByondValue
+ * @return True if value is a string
+ */
+DUNGPUB bool ByondValue_IsStr(CByondValue const *v);
+/**
+ * @param v Pointer to CByondValue
+ * @return True if value is a list (any list type, not just user-defined)
+ */
+DUNGPUB bool ByondValue_IsList(CByondValue const *v);
+
+/**
+ * Determines if a value is logically true or false
+ *
+ * @param v Pointer to CByondValue
+ * @return Truthiness of value
+ */
+DUNGPUB bool ByondValue_IsTrue(CByondValue const *v);
+
+/**
+ * @param v Pointer to CByondValue
+ * @return Floating point number for v, or 0 if not numeric
+ */
+DUNGPUB float ByondValue_GetNum(CByondValue const *v);
+/**
+ * @param v Pointer to CByondValue
+ * @return Reference ID if value is a reference type, or 0 otherwise
+ */
+DUNGPUB u4c ByondValue_GetRef(CByondValue const *v);
+
+/**
+ * Fills a CByondValue struct with a floating point number.
+ * @param v Pointer to CByondValue
+ * @param f Floating point number
+ */
+DUNGPUB void ByondValue_SetNum(CByondValue *v, float f);
+/**
+ * Creates a string and sets CByondValue to a temporary reference to that string.
+ * Blocks if not on the main thread. If string creation fails, the struct is set to null.
+ * @param v Pointer to CByondValue
+ * @param str Null-terminated UTF-8 string
+ * @see Byond_AddGetStrId()
+ */
+DUNGPUB void ByondValue_SetStr(CByondValue *v, char const *str);
+/**
+ * Fills a CByondValue struct with a reference (object) type. Does not validate.
+ * @param v Pointer to CByondValue
+ * @param type 1-byte teference type
+ * @param ref 4-byte reference ID; for most types, an ID of NONE is invalid
+ * @see Byond_TestRef()
+ */
+DUNGPUB void ByondValue_SetRef(CByondValue *v, ByondValueType type, u4c ref);
+
+/**
+ * Compares two values for equality
+ * @param a Pointer to CByondValue
+ * @param b Pointer to CByondValue
+ * @return True if values are equal
+ */
+DUNGPUB bool ByondValue_Equals(CByondValue const *a, CByondValue const *b);
+
+// Other useful structs
+
+struct CByondXYZ {
+	s2c x, y, z;	//!< signed 2-byte integer coordinates
+	s2c junk;		//!< padding
+};
+
+/*
+	In the following functions, anything that fills a result value (e.g.,
+	ReadVar, CallProc) will create a temporary reference to the value. So if
+	the result is an object or list or such, it will remain valid until the
+	end of the current tick unless something explicitly deletes it. You can
+	also let go of the temporary reference early by calling Byond_DecRef().
+
+	If the validity of a reference is ever in doubt, call Byond_TestRef().
+
+	Thread safety:
+
+	Anything called outside of the main	thread will block, unless otherwise
+	noted.
+ */
+
+typedef CByondValue (*ByondCallback)(void *);
+/**
+ * Runs a function as a callback on the main thread (or right away if already there)
+ * Blocking is optional. If already on the main thread, the block parameter is meaningless.
+ * @param callback Function pointer to CByondValue function(void*)
+ * @param data Void pointer (argument to function)
+ * @param block True if this call should block while waiting for the callback to finish; false if not
+ * @return CByondValue returned by the function (if it blocked; null if not)
+ */
+DUNGPUB CByondValue Byond_ThreadSync(ByondCallback callback, void *data, bool block=false);
+
+/**
+ * Returns a reference to an existing string ID, but does not create a new string ID.
+ * Blocks if not on the main thread.
+ * @param str Null-terminated string
+ * @return ID of string; NONE if string does not exist
+ */
+DUNGPUB u4c Byond_GetStrId(char const *str);	// does not add a string to the tree if not found; returns NONE if no string match
+/**
+ * Returns a reference to an existing string ID or creates a new string ID with a temporary reference.
+ * Blocks if not on the main thread.
+ * @param str Null-terminated string
+ * @return ID of string; NONE if string creation failed
+ */
+DUNGPUB u4c Byond_AddGetStrId(char const *str);	// adds a string to the tree if not found
+
+/**
+ * Reads an object variable by name.
+ * Blocks if not on the main thread.
+ * @param loc Object that owns the var
+ * @param varname Var name as null-terminated string
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_ReadVar(CByondValue const *loc, char const *varname, CByondValue *result);
+/**
+ * Reads an object variable by the string ID of its var name.
+ * ID can be cached ahead of time for performance.
+ * Blocks if not on the main thread.
+ * @param loc Object that owns the var
+ * @param varname Var name as string ID
+ * @param result Pointer to accept result
+ * @return True on success
+ * @see Byond_GetStrId()
+ */
+DUNGPUB bool Byond_ReadVarByStrId(CByondValue const *loc, u4c varname, CByondValue *result);
+/**
+ * Writes an object variable by name.
+ * Blocks if not on the main thread.
+ * @param loc Object that owns the var
+ * @param varname Var name as null-terminated string
+ * @param val New value
+ * @return True on success
+ */
+DUNGPUB bool Byond_WriteVar(CByondValue const *loc, char const *varname, CByondValue const *val);
+/**
+ * Writes an object variable by the string ID of its var name.
+ * ID can be cached ahead of time for performance.
+ * Blocks if not on the main thread.
+ * @param loc Object that owns the var
+ * @param varname Var name as string ID
+ * @param val New value
+ * @return True on success
+ */
+DUNGPUB bool Byond_WriteVarByStrId(CByondValue const *loc, u4c varname, CByondValue const *val);
+
+/**
+ * Creates an empty list with a temporary reference. Equivalent to list().
+ * Blocks if not on the main thread.
+ * @param result Result
+ * @return True on success
+ */
+DUNGPUB bool Byond_CreateList(CByondValue *result);
+
+/**
+ * Reads items from a list.
+ * Blocks if not on the main thread. 
+ * @param loc The list to read
+ * @param list CByondValue array, allocated by caller (can be null if querying length)
+ * @param len Pointer to length of array (in items); receives the number of items read on success, or required length of array if not big enough
+ * @return True on success; false with *len=0 for failure; false with *len=required size if array is not big enough
+ */
+DUNGPUB bool Byond_ReadList(CByondValue const *loc, CByondValue *list, u4c *len);
+
+/**
+ * Writes items to a list, in place of old contents.
+ * Blocks if not on the main thread. 
+ * @param loc The list to fill
+ * @param list CByondValue array of items to write
+ * @param len Number of items to write
+ * @return True on success
+ */
+DUNGPUB bool Byond_WriteList(CByondValue const *loc, CByondValue const *list, u4c len);
+
+/**
+ * Reads items as key,value pairs from an associative list, storing them sequentially as key1, value1, key2, value2, etc.
+ * Blocks if not on the main thread. 
+ * @param loc The list to read
+ * @param list CByondValue array, allocated by caller (can be null if querying length)
+ * @param len Pointer to length of array (in items); receives the number of items read on success, or required length of array if not big enough
+ * @return True on success; false with *len=0 for failure; false with *len=required size if array is not big enough
+ */
+DUNGPUB bool Byond_ReadListAssoc(CByondValue const *loc, CByondValue *list, u4c *len);
+
+/**
+ * Reads an item from a list.
+ * Blocks if not on the main thread. 
+ * @param loc The list
+ * @param idx The index in the list (may be a number, or a non-number if using associative lists)
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_ReadListIndex(CByondValue const *loc, CByondValue const *idx, CByondValue *result);
+/**
+ * Writes an item to a list.
+ * Blocks if not on the main thread. 
+ * @param loc The list
+ * @param idx The index in the list (may be a number, or a non-number if using associative lists)
+ * @param val New value
+ * @return True on success
+ */
+DUNGPUB bool Byond_WriteListIndex(CByondValue const *loc, CByondValue const *idx, CByondValue const *val);
+
+/**
+ * Reads from a BYOND pointer
+ * Blocks if not on the main thread. 
+ * @param ptr The BYOND pointer
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_ReadPointer(CByondValue const *ptr, CByondValue *result);
+/**
+ * Writes to a BYOND pointer
+ * Blocks if not on the main thread. 
+ * @param ptr The BYOND pointer
+ * @param val New value
+ * @return True on success
+ */
+DUNGPUB bool Byond_WritePointer(CByondValue const *ptr, CByondValue const *val);
+
+/*
+	Proc calls:
+
+	arg is an array of arguments; can be null arg_count is 0.
+
+	The call is implicitly a waitfor=0 call; if the callee sleeps it will return
+	immediately and finish later.
+ */
+
+/**
+ * Calls an object proc by name.
+ * The proc call is treated as waitfor=0 and will return immediately on sleep.
+ * Blocks if not on the main thread. 
+ * @param src The object that owns the proc
+ * @param name Proc name as null-terminated string
+ * @param arg Array of arguments
+ * @param arg_count Number of arguments
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_CallProc(CByondValue const *src, char const *name, CByondValue const *arg, u4c arg_count, CByondValue *result);
+/**
+ * Calls an object proc by name, where the name is a string ID.
+ * The proc call is treated as waitfor=0 and will return immediately on sleep.
+ * Blocks if not on the main thread. 
+ * @param src The object that owns the proc
+ * @param name Proc name as string ID
+ * @param arg Array of arguments
+ * @param arg_count Number of arguments
+ * @param result Pointer to accept result
+ * @return True on success
+ * @see Byond_GetStrId()
+ */
+DUNGPUB bool Byond_CallProcByStrId(CByondValue const *src, u4c name, CByondValue const *arg, u4c arg_count, CByondValue *result);
+
+/**
+ * Calls a global proc by name.
+ * The proc call is treated as waitfor=0 and will return immediately on sleep.
+ * Blocks if not on the main thread. 
+ * @param name Proc name as null-terminated string
+ * @param arg Array of arguments
+ * @param arg_count  Number of arguments
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_CallGlobalProc(char const *name, CByondValue const *arg, u4c arg_count, CByondValue *result);	// result MUST be initialized first!
+/**
+ * Calls a global proc by name, where the name is a string ID.
+ * The proc call is treated as waitfor=0 and will return immediately on sleep.
+ * Blocks if not on the main thread. 
+ * @param name Proc name as string ID
+ * @param arg Array of arguments
+ * @param arg_count Number of arguments
+ * @param result Pointer to accept result
+ * @return True on success
+ * @see Byond_GetStrId()
+ */
+DUNGPUB bool Byond_CallGlobalProcByStrId(u4c name, CByondValue const *arg, u4c arg_count, CByondValue *result);	// result MUST be initialized first!
+
+/**
+ * Uses BYOND's internals to represent a value as text
+ * Blocks if not on the main thread. 
+ * @param src The value to convert to text
+ * @param buf char array, allocated by caller (can be null if querying length)
+ * @param buflen Pointer to length of array in bytes; receives the string length (including trailing null) on success, or required length of array if not big enough
+ * @return True on success; false with *buflen=0 for failure; false with *buflen=required size if array is not big enough
+ */
+DUNGPUB bool Byond_ToString(CByondValue const *src, char *buf, u4c *buflen);
+
+// Other builtins
+
+/**
+ * Equivalent to calling block(x1,y1,z1, x2,y2,z2).
+ * Blocks if not on the main thread. 
+ * @param corner1 One corner of the block
+ * @param corner2 Another corner of the block
+ * @param list CByondValue array, allocated by caller (can be null if querying length)
+ * @param len Pointer to length of array (in items); receives the number of items read on success, or required length of array if not big enough
+ * @return True on success; false with *len=0 for failure; false with *len=required size if array is not big enough
+ */
+DUNGPUB bool Byond_Block(CByondXYZ const *corner1, CByondXYZ const *corner2, CByondValue *list, u4c *len);
+
+/**
+ * Equivalent to calling length(value).
+ * Blocks if not on the main thread. 
+ * @param src The value
+ * @param result Pointer to accept result as a CByondValue (intended for future possible override of length)
+ * @return True on success
+ */
+DUNGPUB bool Byond_Length(CByondValue const *src, CByondValue *result);
+
+/**
+ * Equivalent to calling locate(type), or locate(type) in list.
+ * Blocks if not on the main thread. 
+ * @param type The type to locate
+ * @param list The list to locate in; can be a null pointer instead of a CByondValue to locate(type) without a list
+ * @param result Pointer to accept result; can be null if nothing is found
+ * @return True on success (including if nothing is found); false on error
+ */
+DUNGPUB bool Byond_LocateIn(CByondValue const *type, CByondValue const *list, CByondValue *result);
+
+/**
+ * Equivalent to calling locate(x,y,z)
+ * Blocks if not on the main thread.
+ * Result is null if coords are invalid.
+ * @param xyz The x,y,z coords
+ * @param result Pointer to accept result
+ * @return True (always)
+ */
+DUNGPUB bool Byond_LocateXYZ(CByondXYZ const *xyz, CByondValue *result);
+
+/**
+ * Equivalent to calling new type(...)
+ * Blocks if not on the main thread. 
+ * @param type The type to create (type path or string)
+ * @param arg Array of arguments
+ * @param arg_count Number of arguments
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_New(CByondValue const *type, CByondValue const *arg, u4c arg_count, CByondValue *result);
+
+/**
+ * Equivalent to calling new type(arglist)
+ * Blocks if not on the main thread. 
+ * @param type The type to create (type path or string)
+ * @param arglist Arguments, as a reference to an arglist
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_NewArglist(CByondValue const *type, CByondValue const *arglist, CByondValue *result);	// result MUST be initialized first!
+
+/**
+ * Equivalent to calling refcount(value)
+ * Blocks if not on the main thread. 
+ * @param src The object to refcount
+ * @param result Pointer to accept result
+ * @return True on success
+ */
+DUNGPUB bool Byond_Refcount(CByondValue const *src, u4c *result);	// result MUST be initialized first!
+
+/**
+ * Get x,y,z coords of an atom
+ * Blocks if not on the main thread. 
+ * @param src The object to read
+ * @param xyz Pointer to accept CByondXYZ result
+ * @return True on success
+ */
+DUNGPUB bool Byond_XYZ(CByondValue const *src, CByondXYZ *xyz);	// still returns true if the atom is off-map, but xyz will be 0,0,0
+
+/*
+	Generally you don't want to mess with inc/decref calls, except that for
+	temporary references you can use Byond_DecRef() to let go of the temporary
+	reference.
+
+	Call ByondValue_IncRef() to create a permanent reference to an object
+	within Byondapi. It will exist until ByondValue_DecRef() removes it or the
+	object is hard-deleted.
+
+	ByondValue_DecRef() will remove a permanent reference created by Byondapi.
+	If there is no permanent reference, it will remove any temporary
+	reference that was set to expire when the tick ends. If Byondapi has no
+	references to the object, the call will be ignored.
+
+	These only apply to ref types, not null/num/string. Any runtime errors
+	caused by decref (if the object is deleted or another object ends up
+	getting deleted as an indirect result) are ignored.
+ */
+
+/**
+ * Mark a reference as in use by Byondapi
+ * This should be done for any temporary references returned from other calls, if they need to be saved awhile.
+ * Blocks if not on the main thread. 
+ * @param src The object to incref
+ */
+DUNGPUB void ByondValue_IncRef(CByondValue const *src);
+
+/**
+ * Mark a reference as no longer in use by Byondapi
+ * This can be used for temporary references to let them go immediately.
+ * Blocks if not on the main thread. 
+ * @param src The object to decref
+ */
+DUNGPUB void ByondValue_DecRef(CByondValue const *src);
+
+/**
+ * Test if a reference-type CByondValue is valid
+ * Blocks if not on the main thread. 
+ * @param src Pointer to the reference to test; will be filled with null if the reference is invalid
+ * @return True if ref is valid; false if not
+ */
+// Returns true if the ref is valid.
+// Returns false if the ref was not valid and had to be changed to null.
+// This only applies to ref types, not null/num/string which are always valid.
+DUNGPUB bool Byond_TestRef(CByondValue *src);
+
+};	// extern "C"
+
+
+
+#endif	// BYONDAPI_H
diff --git a/crates/byondapi-sys/src/lib.rs b/crates/byondapi-sys/src/lib.rs
index 8a9d1a2..1582a52 100644
--- a/crates/byondapi-sys/src/lib.rs
+++ b/crates/byondapi-sys/src/lib.rs
@@ -17,8 +17,8 @@ compile_error!("BYOND API only supports Windows and Linux");
 // Include byondapi-c bindings (generated by build.rs)
 #[allow(dead_code)]
 mod byond_rawbind {
-    #[cfg(feature = "byond-515-1620")]
-    include!(concat!(env!("OUT_DIR"), "/bindings_515_1620.rs"));
+    #[cfg(feature = "byond-515-1621")]
+    include!(concat!(env!("OUT_DIR"), "/bindings_515_1621.rs"));
 }
 
 /// we must simply hope this never changes
@@ -117,9 +117,9 @@ impl ByondApi {
     pub unsafe fn ByondValue_IsList(&self, v: *const CByondValue) -> bool {
         self.internal.ByondValue_IsList(v)
     }
-    //pub unsafe fn ByondValue_IsTrue(&self, v: *const CByondValue) -> bool {
-    //    self.internal.ByondValue_IsTrue(v)
-    //}
+    pub unsafe fn ByondValue_IsTrue(&self, v: *const CByondValue) -> bool {
+        self.internal.ByondValue_IsTrue(v)
+    }
     pub unsafe fn ByondValue_GetNum(&self, v: *const CByondValue) -> f32 {
         self.internal.ByondValue_GetNum(v)
     }
diff --git a/tools/setup_byond_linux.sh b/tools/setup_byond_linux.sh
index b634912..34c256e 100644
--- a/tools/setup_byond_linux.sh
+++ b/tools/setup_byond_linux.sh
@@ -2,7 +2,7 @@
 set -euo pipefail
 
 BYOND_MAJOR=515
-BYOND_MINOR=1620
+BYOND_MINOR=1621
 
 if [ -d "$HOME/BYOND/byond/bin" ] && grep -Fxq "${BYOND_MAJOR}.${BYOND_MINOR}" $HOME/BYOND/version.txt;
 then
diff --git a/tools/setup_byond_windows.sh b/tools/setup_byond_windows.sh
index a087016..c12a956 100644
--- a/tools/setup_byond_windows.sh
+++ b/tools/setup_byond_windows.sh
@@ -2,7 +2,7 @@
 set -euo pipefail
 
 BYOND_MAJOR=515
-BYOND_MINOR=1620
+BYOND_MINOR=1621
 
 if [ -d "$HOME/BYOND/byond/bin" ] && grep -Fxq "${BYOND_MAJOR}.${BYOND_MINOR}" $HOME/BYOND/version.txt;
 then