Update ModData/About.xml, update various syscalls in Stationpedia

This commit is contained in:
2025-12-07 21:15:58 -07:00
parent 653026d6c1
commit 1b96a17698
6 changed files with 146 additions and 94 deletions

View File

@@ -1,70 +1,114 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ModMetadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ModMetadata xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>StationeersSlang</Name> <Name>StationeersSlang</Name>
<Author>JoeDiertay</Author> <Author>JoeDiertay</Author>
<Version>0.1.0</Version> <Version>0.1.1</Version>
<Description> <Description>
Slang (Stationeers Language) is a high-level programming language that compiles directly into IC10 within the game. [h1]Slang: High-Level Programming for Stationeers[/h1]
Features: Stop writing assembly. Start writing code.
- In-Game Compilation: Write C-style code directly in the IC editor.
- Automatic Register Management: Define variables with 'let' (e.g., let x = 10) without managing r0-r15. Slang (Stationeers Language) brings modern programming to Stationeers. It allows you to write scripts using a familiar C-style syntax (variables, functions, if/else, loops) directly in the in-game editor. When you hit confirm, Slang compiles your code into optimized IC10 MIPS assembly instantly.
- Standard Control Flow: Use if/else, while, loop, break, and continue.
- Functions: Define and call functions with arguments. [b]NOTE: This project is in BETA. Expect updates and changes![/b]
- Smart Editor: Real-time syntax highlighting and error checking (red text for errors).
- Persistent Source: Your high-level source code is saved inside the chip data, so you can edit it later. [h2]Features[/h2]
- Constant Folding: Mathematical operations on constants are calculated at compile time to save instructions. [list]
- Device Aliasing: Easy device mapping (e.g., device sensor = "d0"). [*] [b]In-Game Compilation:[/b] No external tools needed. Write Slang directly in the IC editor.
[*] [b]No More Register Juggling:[/b] Define variables with let (e.g., let temp = 300). The compiler manages r0-r15 for you.
Installation: [*] [b]Control Flow:[/b] Write readable logic with if, else, while, loop, break, and continue.
This is a StationeersLaunchPad Plugin Mod. It requires BepInEx to be installed. [*] [b]Functions:[/b] Create reusable code blocks with arguments.
[*] [b]Smart Editor:[/b] Get real-time syntax highlighting and error checking (red text) as you type.
Usage: [*] [b]Persistent Source:[/b] Your high-level Slang code is saved to the chip, so it's there when you come back.
1. Open any IC10 housing or editor. [*] [b]Optimizations:[/b] Features like Constant Folding calculate math at compile time to save instructions.
2. Write Slang code. [*] [b]Device Aliasing:[/b] Simple mapping: device sensor = "d0".
3. Press Confirm to compile and run. [*] [b]Temperature Literals:[/b] Don't worry about converting Celsius to Kelvin anymore. Define your temperatures as whatever you want and append the proper suffix at the end (ex. 20c, 68f, 293.15k)
</Description> [/list]
<Tags>
<Tag>Logic</Tag> [h2]Installation[/h2]
<Tag>Scripting</Tag> This is a StationeersLaunchPad Plugin Mod.
<Tag>Code</Tag> 1. Install BepInEx (required).
<Tag>BepInEx</Tag> 2. Install StationeersLaunchPad.
<Tag>StationeersLaunchPad</Tag> 3. Subscribe to Slang.
<Tag>Quality of Life</Tag>
</Tags> [h2]Usage[/h2]
<InGameDescription><![CDATA[ 1. Open any IC10 housing or editor in-game.
<size=30><color=#ffff00>Slang - High Level Language Compiler</color></size> 2. Write your Slang code.
A modern programming experience for Stationeers. Write C-style code that compiles to MIPS assembly instantly. 3. Press [b]Confirm[/b]. The mod compiles your code to IC10 and loads it onto the chip.
<color=#ffa500><b>Features</b></color> [h2]Example Code[/h2]
- <b>In-Game Compilation:</b> Write high-level logic directly in the chip editor. [code]
- <b>Automatic Registers:</b> Stop juggling <color=#add8e6>r0-r15</color>. Just use <color=#569cd6>let</color> variables. device airCon = "d0";
- <b>Control Flow:</b> Full support for <color=#c586c0>if</color>, <color=#c586c0>else</color>, <color=#c586c0>while</color>, and <color=#c586c0>loop</color>. device gasSensor = "d1";
- <b>Smart Editor:</b> Integrated syntax highlighting and real-time error checking.
- <b>Persistent Code:</b> Your Slang source code is saved with the chip, so you never lose your work. loop {
- <b>Optimization:</b> The compiler automatically optimizes constant math (e.g., <color=#b5cea8>1 + 2</color> becomes <color=#b5cea8>3</color>). yield();
// yes, ideally you would use a latch here, but this is just a simple example :)
<color=#ffa500><b>Example Code</b></color> airCon.On = gasSensor.Temperature >= 28c;
<color=#569cd6>device</color> sensor = <color=#ce9178>"d0"</color>; }
<color=#569cd6>const</color> MAX_TEMP = <color=#b5cea8>300k</color>; [/code]
<color=#c586c0>loop</color> { [h2]Known Issues (Beta)[/h2]
<color=#569cd6>let</color> temp = sensor.Temperature; [list]
<color=#c586c0>if</color> (temp > MAX_TEMP) { [*] [b]Code Size:[/b] Compiled output is currently more verbose than hand-optimized assembly. Optimization passes are planned.
<color=#6a9955>// Do logic here</color> [*] [b]Stack Access:[/b] Direct stack memory access is disabled to prevent conflicts with the compiler's internal memory management.
} [*] [b]Documentation:[/b] In-game tooltips for syscalls (like load, set) are WIP. Check the "Slang" entry in the Stationpedia (F1) for help.
yield(); [*] [b]Debugging:[/b] Runtime errors currently point to the compiled IC10 line number, not your Slang source line. Source mapping is coming soon.
} [/list]
<b><color=#ffff00>Installation</color></b> [h2]Planned Features[/h2]
This is a <color=#ffa500>StationeersLaunchPad</color> Plugin Mod. It requires BepInEx to be installed. [list]
See: https://github.com/StationeersLaunchPad/StationeersLaunchPad [*] Side-by-side view: Slang vs. Compiled IC10.
[*] Compiler optimizations (dead code elimination, smarter register allocation).
Source Code: https://github.com/dbidwell94/stationeers_lang [*] Enhanced LSP features (Autocomplete, Go to Definition).
]]> [*] Full feature parity with all IC10 instructions.
</InGameDescription> [*] Tutorials and beginner script examples.
<Dependencies> [/list]
<Dependency>IC10Editor</Dependency>
</Dependencies> [h2]FAQ[/h2]
<LoadAfter>IC10Editor</LoadAfter> [b]Q: What is the DLL extracted to my temp folder?[/b]
</ModMetadata> A: The Slang compiler is built in Rust for performance and reliability. It is compiled as a native library and bundled with the mod. It must be extracted temporarily to function within the game's C# environment.
</Description>
<ChangeLog xsi:nil="true" />
<WorkshopHandle>3619985558</WorkshopHandle>
<Tags>
<Tag>Logic</Tag>
<Tag>Scripting</Tag>
<Tag>Code</Tag>
<Tag>BepInEx</Tag>
<Tag>StationeersLaunchPad</Tag>
<Tag>Quality of Life</Tag>
</Tags>
<DependsOn WorkshopHandle="3592775931" />
<OrderBefore WorkshopHandle="3592775931" />
<InGameDescription><![CDATA[
<size=30><color=#ffff00>Slang - High Level Language Compiler</color></size>
A modern programming experience for Stationeers. Write C-style code that compiles to MIPS assembly instantly.
<color=#ffa500><b>Features</b></color>
- <b>In-Game Compilation:</b> Write high-level logic directly in the chip editor.
- <b>Automatic Registers:</b> Stop juggling <color=#add8e6>r0-r15</color>. Just use <color=#569cd6>let</color> variables.
- <b>Control Flow:</b> Full support for <color=#c586c0>if</color>, <color=#c586c0>else</color>, <color=#c586c0>while</color>, and <color=#c586c0>loop</color>.
- <b>Smart Editor:</b> Integrated syntax highlighting and real-time error checking.
- <b>Persistent Code:</b> Your Slang source code is saved with the chip, so you never lose your work.
- <b>Optimization:</b> The compiler automatically optimizes constant math (e.g., <color=#b5cea8>1 + 2</color> becomes <color=#b5cea8>3</color>).
<color=#ffa500><b>Example Code</b></color>
<color=#569cd6>device</color> sensor = <color=#ce9178>"d0"</color>;
<color=#569cd6>const</color> MAX_TEMP = <color=#b5cea8>300k</color>;
<color=#c586c0>loop</color> {
<color=#569cd6>let</color> temp = sensor.Temperature;
<color=#c586c0>if</color> (temp > MAX_TEMP) {
<color=#6a9955>// Do logic here</color>
}
yield();
}
<b><color=#ffff00>Installation</color></b>
This is a <color=#ffa500>StationeersLaunchPad</color> Plugin Mod. It requires BepInEx to be installed.
See: https://github.com/StationeersLaunchPad/StationeersLaunchPad
Source Code: https://github.com/dbidwell94/stationeers_lang
]]></InGameDescription>
</ModMetadata>

View File

@@ -41,7 +41,7 @@ namespace Slang
{ {
public const string PluginGuid = "com.biddydev.slang"; public const string PluginGuid = "com.biddydev.slang";
public const string PluginName = "Slang"; public const string PluginName = "Slang";
public const string PluginVersion = "0.1.0"; public const string PluginVersion = "0.1.1";
public static Mod MOD = new Mod(PluginName, PluginVersion); public static Mod MOD = new Mod(PluginName, PluginVersion);

View File

@@ -5,7 +5,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyName>StationeersSlang</AssemblyName> <AssemblyName>StationeersSlang</AssemblyName>
<Description>Slang Compiler Bridge</Description> <Description>Slang Compiler Bridge</Description>
<Version>0.1.0</Version> <Version>0.1.1</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>

View File

@@ -843,7 +843,7 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]] [[package]]
name = "slang" name = "slang"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "slang" name = "slang"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
[workspace] [workspace]

View File

@@ -9,97 +9,97 @@ documented! {
/// ## IC10 /// ## IC10
/// `acos r? a(r?|num)` /// `acos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).acos();` /// `let item = acos(number|var|expression);`
Acos(Box<Spanned<Expression>>), Acos(Box<Spanned<Expression>>),
/// Returns the angle in radians whose sine is the specified number. /// Returns the angle in radians whose sine is the specified number.
/// ## IC10 /// ## IC10
/// `asin r? a(r?|num)` /// `asin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).asin();` /// `let item = asin(number|var|expression);`
Asin(Box<Spanned<Expression>>), Asin(Box<Spanned<Expression>>),
/// Returns the angle in radians whose tangent is the specified number. /// Returns the angle in radians whose tangent is the specified number.
/// ## IC10 /// ## IC10
/// `atan r? a(r?|num)` /// `atan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).atan();` /// `let item = atan(number|var|expression);`
Atan(Box<Spanned<Expression>>), Atan(Box<Spanned<Expression>>),
/// Returns the angle in radians whose tangent is the quotient of the specified numbers. /// Returns the angle in radians whose tangent is the quotient of the specified numbers.
/// ## IC10 /// ## IC10
/// `atan2 r? a(r?|num) b(r?|num)` /// `atan2 r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).atan2((number|var));` /// `let item = atan2((number|var|expression), (number|var|expression));`
Atan2(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Atan2(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Gets the absolute value of a number. /// Gets the absolute value of a number.
/// ## IC10 /// ## IC10
/// `abs r? a(r?|num)` /// `abs r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).abs();` /// `let item = abs((number|var|expression));`
Abs(Box<Spanned<Expression>>), Abs(Box<Spanned<Expression>>),
/// Rounds a number up to the nearest whole number. /// Rounds a number up to the nearest whole number.
/// ## IC10 /// ## IC10
/// `ceil r? a(r?|num)` /// `ceil r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).ceil();` /// `let item = ceil((number|var|expression));`
Ceil(Box<Spanned<Expression>>), Ceil(Box<Spanned<Expression>>),
/// Returns the cosine of the specified angle in radians. /// Returns the cosine of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `cos r? a(r?|num)` /// `cos r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).cos();` /// `let item = cos((number|var|expression));`
Cos(Box<Spanned<Expression>>), Cos(Box<Spanned<Expression>>),
/// Rounds a number down to the nearest whole number. /// Rounds a number down to the nearest whole number.
/// ## IC10 /// ## IC10
/// `floor r? a(r?|num)` /// `floor r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).floor();` /// `let item = floor((number|var|expression));`
Floor(Box<Spanned<Expression>>), Floor(Box<Spanned<Expression>>),
/// Computes the natural logarithm of a number. /// Computes the natural logarithm of a number.
/// ## IC10 /// ## IC10
/// `log r? a(r?|num)` /// `log r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).log();` /// `let item = log((number|var|expression));`
Log(Box<Spanned<Expression>>), Log(Box<Spanned<Expression>>),
/// Computes the maximum of two numbers. /// Computes the maximum of two numbers.
/// ## IC10 /// ## IC10
/// `max r? a(r?|num) b(r?|num)` /// `max r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).max((number|var));` /// `let item = max((number|var|expression), (number|var|expression));`
Max(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Max(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Computes the minimum of two numbers. /// Computes the minimum of two numbers.
/// ## IC10 /// ## IC10
/// `min r? a(r?|num) b(r?|num)` /// `min r? a(r?|num) b(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).min((number|var));` /// `let item = min((number|var|expression), (number|var|expression));`
Min(Box<Spanned<Expression>>, Box<Spanned<Expression>>), Min(Box<Spanned<Expression>>, Box<Spanned<Expression>>),
/// Gets a random number between 0 and 1. /// Gets a random number between 0 and 1.
/// ## IC10 /// ## IC10
/// `rand r?` /// `rand r?`
/// ## Slang /// ## Slang
/// `rand();` /// `let item = rand();`
Rand, Rand,
/// Returns the sine of the specified angle in radians. /// Returns the sine of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `sin r? a(r?|num)` /// `sin r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).sin();` /// `let item = sin((number|var|expression));`
Sin(Box<Spanned<Expression>>), Sin(Box<Spanned<Expression>>),
/// Computes the square root of a number. /// Computes the square root of a number.
/// ## IC10 /// ## IC10
/// `sqrt r? a(r?|num)` /// `sqrt r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).sqrt();` /// `let item = sqrt((number|var|expression));`
Sqrt(Box<Spanned<Expression>>), Sqrt(Box<Spanned<Expression>>),
/// Returns the tangent of the specified angle in radians. /// Returns the tangent of the specified angle in radians.
/// ## IC10 /// ## IC10
/// `tan r? a(r?|num)` /// `tan r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).tan();` /// `let item = tan((number|var|expression));`
Tan(Box<Spanned<Expression>>), Tan(Box<Spanned<Expression>>),
/// Truncates a number by removing the decimal portion. /// Truncates a number by removing the decimal portion.
/// ## IC10 /// ## IC10
/// `trunc r? a(r?|num)` /// `trunc r? a(r?|num)`
/// ## Slang /// ## Slang
/// `(number|var).trunc();` /// `let item = trunc((number|var|expression));`
Trunc(Box<Spanned<Expression>>), Trunc(Box<Spanned<Expression>>),
} }
} }
@@ -160,7 +160,9 @@ documented! {
/// ## IC10 /// ## IC10
/// `l r? d? var` /// `l r? d? var`
/// ## Slang /// ## Slang
/// `load(deviceType, "LogicType");` /// `let item = load(deviceHash, "LogicType");`
/// `let item = l(deviceHash, "LogicType");`
/// `let item = deviceAlias.LogicType;`
LoadFromDevice(Spanned<LiteralOrVariable>, Spanned<Literal>), LoadFromDevice(Spanned<LiteralOrVariable>, Spanned<Literal>),
/// Function which gets a LogicType from all connected network devices that match /// Function which gets a LogicType from all connected network devices that match
/// the provided device hash and name, aggregating them via a batchMode /// the provided device hash and name, aggregating them via a batchMode
@@ -168,6 +170,7 @@ documented! {
/// `lbn r? deviceHash nameHash logicType batchMode` /// `lbn r? deviceHash nameHash logicType batchMode`
/// ## Slang /// ## Slang
/// `loadBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");` /// `loadBatchedNamed(deviceHash, deviceName, "LogicType", "BatchMode");`
/// `lbn(deviceHash, deviceName, "LogicType", "BatchMode");`
LoadBatchNamed( LoadBatchNamed(
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable>,
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable>,
@@ -180,26 +183,31 @@ documented! {
/// `lb r? deviceHash logicType batchMode` /// `lb r? deviceHash logicType batchMode`
/// ## Slang /// ## Slang
/// `loadBatched(deviceHash, "Variable", "LogicType");` /// `loadBatched(deviceHash, "Variable", "LogicType");`
/// `lb(deviceHash, "Variable", "LogicType");`
LoadBatch(Spanned<LiteralOrVariable>, Spanned<Literal>, Spanned<Literal>), LoadBatch(Spanned<LiteralOrVariable>, Spanned<Literal>, Spanned<Literal>),
/// Represents a function which stores a setting into a specific device. /// Represents a function which stores a setting into a specific device.
/// ## IC10 /// ## IC10
/// `s d? logicType r?` /// `s d? logicType r?`
/// ## Slang /// ## Slang
/// `set(deviceType, "Variable", (number|var));` /// `set(deviceHash, "LogicType", (number|var));`
/// `s(deviceHash, "LogicType", (number|var));`
/// `deviceAlias.LogicType = (number|var);`
SetOnDevice(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>), SetOnDevice(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>),
/// Represents a function which stores a setting to all devices that match /// Represents a function which stores a setting to all devices that match
/// the given deviceHash /// the given deviceHash
/// ## IC10 /// ## IC10
/// `sb deviceHash logicType r?` /// `sb deviceHash logicType r?`
/// ## Slang /// ## Slang
/// `setBatched(deviceHash, "LogicType", (number|var))` /// `setBatched(deviceHash, "LogicType", (number|var));`
/// `sb(deviceHash, "LogicType", (number|var));`
SetOnDeviceBatched(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>), SetOnDeviceBatched(Spanned<LiteralOrVariable>, Spanned<Literal>, Box<Spanned<Expression>>),
/// Represents a function which stores a setting to all devices that match /// Represents a function which stores a setting to all devices that match
/// both the given deviceHash AND the given nameHash /// both the given deviceHash AND the given nameHash
/// ## IC10 /// ## IC10
/// `sbn deviceHash nameHash logicType r?` /// `sbn deviceHash nameHash logicType r?`
/// ## Slang /// ## Slang
/// `setBatchedNamed(deviceHash, nameHash, "LogicType", (number|var))` /// `setBatchedNamed(deviceHash, nameHash, "LogicType", (number|var));`
/// `sbn(deviceHash, nameHash, "LogicType", (number|var));`
SetOnDeviceBatchedNamed( SetOnDeviceBatchedNamed(
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable>,
Spanned<LiteralOrVariable>, Spanned<LiteralOrVariable>,