Metadata-Version: 2.4
Name: emusc
Version: 1.0.1
Summary: ScrapComputers Emulation Tool
Author-email: uchstalker <uchstalker0@gmail.com>
License: License text copyright © 2024 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.
        
        Terms
        The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use.
        
        Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate.
        
        If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work.
        
        All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor.
        
        You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work.
        
        Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work.
        
        This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark “Business Source License”, as long as you comply with the Covenants of Licensor below.
        
        Covenants of Licensor
        In consideration of the right to use this License’s text and the “Business Source License” name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor:
        
        To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
        To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text “None” to specify a Change Date. Not to modify this License in any other way.
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pillow>=9.0
Requires-Dist: lupa>=2.0
Dynamic: license-file

# EmuSC

EmuSC is a desktop emulator for [ScrapComputers](https://scrapcomputers.dev), a Lua computer mod for Scrap Mechanic. It lets you run and test ScrapComputers scripts on your machine without launching the game.

Scripts run against simulated hardware: displays render in a window, a terminal handles text I/O, keyboard input is captured, motor physics are ticked, and so on. The Lua environment exposes the same API the mod provides in-game - those are documented at [scrapcomputers.dev/docs](https://scrapcomputers.dev/docs). This README covers the emulator itself: how to run it, how to declare hardware, and where it deviates from the game.

## Installation

```
pip install EmuSC
```

Requires Python 3.10 or newer.

## Usage

```
python -m EmuSC <script.lua> [options]
```

**Options:**

| Flag | Description |
|------|-------------|
| `-H SPEC`, `--hardware SPEC` | Attach a hardware component (repeatable) |
| `-c FILE`, `--config FILE` | Load hardware configuration from a JSON file |
| `-d DIR`, `--data-dir DIR` | Directory for persistent hardware data (default: `.`) |
| `-t HZ`, `--tick-rate HZ` | Simulation ticks per second (default: `40`) |
| `--dev` | Echo Lua `print()` output to stdout in addition to the terminal window |
| `-D`, `--debug` | Open the debugger window (see below) |
| `-B`, `--break-on-start` | Pause before `onLoad` so breakpoints can be set first (implies `--debug`) |
| `-r DIR`, `--require-path DIR` | Directory searched by `require()` (default: directory of the script) |

## Hardware

Components are declared with `-H` flags or via a JSON config file. Both can be combined; the config is loaded first, then `-H` flags are appended.

### Inline syntax

```
-H <type>[:<param>[:<param>...]]
```

### Available components

| Type | Spec | Notes |
|------|------|-------|
| `display` | `display[:WxH[:scale]]` | Renders to a window. Default size is 160x120 at scale 2. `scale` multiplies the window resolution. |
| `display_file` | `display_file[:WxH]` | Writes `{width, height, pixels}` (packed RGB ints) to a `pixels.json` in the data directory instead of opening a window. Useful for headless testing, or custom display runtime. |
| `terminal` | `terminal` | Text I/O window. `send()` writes to it; typed input is queued for `getInput()`. |
| `keyboard` | `keyboard` | Keystroke capture window. |
| `motor` | `motor` | Simulates a bearing or piston with adjustable speed, angle, and length. |
| `gps` | `gps` | Provides position and velocity data, editable in the UI. |
| `radar` | `radar` | Simulates radar returns. |
| `laser` | `laser` | Distance measurement and hit detection. |
| `speaker` | `speaker` | Audio stub (not yet implemented). |
| `light` | `light` | Light control. |
| `hdd` | `hdd[:label]` | Persistent storage backed by a JSON file. The label distinguishes multiple drives. |
| `network` | `network[:channel]` | Channel-based packet messaging between network ports. |
| `antenna` | `antenna` | Long-range relay between network ports. Named via the JSON config. |
| `hologram` | `hologram` | 3D holographic display. |
| `inputreg` | `inputreg[:name[:value]]` | Named numeric input register, editable in the Register Manager window. |
| `outputreg` | `outputreg[:name]` | Named numeric output register, shown as a bar. |

### JSON config format

```json
{
  "hardware": [
    { "type": "display", "width": 320, "height": 240, "scale": 2 },
    { "type": "terminal" },
    { "type": "keyboard" },
    { "type": "hdd", "label": "main" },
    { "type": "antenna", "name": "tower" },
    { "type": "network", "channel": "eth0", "antenna": "tower" },
    { "type": "inputreg", "name": "throttle", "value": 0.5 }
  ]
}
```

```
emusc script.lua -c hardware.json
```

A few components take extra keys that have no inline equivalent: `gps` accepts starting `x`/`y`/`z` and `vx`/`vy`/`vz`, `motor` takes `max_length`, `terminal` takes `max_lines`, `laser` takes `distance`, `max_range` and `has_hit`, and `network` takes `antenna` to link the port to a named antenna.

## Debugger

Run with `-D` / `--debug` to open the debugger window alongside the simulation. It has four tabs:

- **Console** - mirrors all Lua `print()` output and runtime errors (regardless of whether `--dev` is set), and takes commands. Anything that isn't a command gets evaluated as a Lua expression. Up/Down arrows cycle through history.
- **Stack** - the Lua call stack, refreshed on breakpoint hits and errors (or manually).
- **Variables** - lists every global variable defined by your script (updated each tick), with its type and current value. Tables show a key count; functions show the source location. While paused at a breakpoint, the locals captured at that line appear here too.
- **Breakpoints** - enter a line number and click Add (or use `bp` in the console). When execution reaches that line the simulation pauses mid-tick with a snapshot of the locals. Click Resume to continue or Step to advance one tick and pause again.

The console commands, in short:

```
g / p / step      resume, pause, run one tick
bp N  bc N  bl    set / clear / list breakpoints
k                 print the Lua call stack
? <expr>          evaluate a Lua expression
dv [name]         dump all variables, or inspect one
tick              print the tick counter
```

Expression eval is disabled while paused at a breakpoint (the Lua VM is suspended inside the debug hook at that point), use `dv` or the Variables tab instead.

The Pause and Resume buttons in the toolbar also work outside of breakpoints - Pause halts the tick loop at the next tick boundary, Resume restarts it.

Starting with `-B` / `--break-on-start` pauses before `onLoad` runs, so you can place breakpoints before any of your code executes.

## Modules and require()

`require()` in EmuSC takes a direct file reference, extension included:

```lua
-- if your script is at ~/projects/myapp/main.lua,
-- this loads ~/projects/myapp/utils.lua
local utils = require("utils.lua")
```

The `require()` function is identical to ScrapComputer's version of it. However, it resolves against a certain path, root path by default, instead of computer filesystem which, well, doesn't exist.

To resolve against a different root instead, pass `--require-path`:

```
emusc main.lua -H terminal --require-path ./lib
```

## Writing scripts

Scripts use the same structure as in-game ScrapComputers programs:

Scripts are checked against Lua 5.1 syntax before they run: `goto` and labels, floor division, the 5.3 bitwise operators, `<const>`/`<close>` attributes and `\x`/`\z`/`\u{}` string escapes are all rejected with a line number, since the mod's VM would choke on them in-game. A `bit` library is available for bitwise work.

The emulator sets a global `_EmuSC = true` that never exists in-game. Use it to add emulator-only setup or to skip code that requires real hardware:

```lua
function onLoad()
    if _EmuSC then
        print("running in emulator")
    end
end
```

For everything else, component getters, drawing calls, packet formats and so on, the API behaves as the [ScrapComputers docs](https://scrapcomputers.dev/docs) describe.

## What it doesn't do

There is no game world behind the hardware, so anything that would measure the world is fed by hand instead:

- GPS, laser and radar values are whatever you enter in their windows. The GPS integrates velocity into position each tick; its rotation and acceleration fields stay zeroed.
- Holograms are tracked (create, move, delete all work) but nothing renders them.
- The speaker is silent - `playNote()` and similar just flash what would have played in its window.
- Cameras, seat controllers, gravity controllers, power sources and radar warning receivers aren't simulated. Their getters return empty tables, so loops over them are safe.
- `sc.power` reports fixed values; `sc.midi`, `sc.nbs` and `sc.qrcode` return nil; the audio, language, configuration and example managers are stubs.
- `sc.lz4` round-trips its own output but is not wire-compatible with real LZ4, and `sm.noise` is a cheap approximation rather than true Perlin noise.

There is also no timeout or watchdog: if `onUpdate` contains a loop that never exits, the next tick never fires and the emulator freezes in place, matching in-game behavior where the computer simply stops responding. A stuck script stays stuck until you close the window.

## Example

```lua
local display, terminal, keyboard

function onLoad()
    display  = sc.getDisplays()[1]
    terminal = sc.getTerminals()[1]
    keyboard = sc.getKeyboards()[1]
    terminal.send("Ready.\n")
end

function onUpdate(dt)
    local key = keyboard.getLatestKeystroke()
    if key and key ~= "" then
        terminal.send("Key: " .. key .. "\n")
    end

    display.clear(sm.color.new("001122"))
    display.drawText(10, 10, "Hello", sm.color.new("ffffff"), nil)
    display.update()
end
```

```
emusc myscript.lua -H display:320x240:2 -H terminal -H keyboard --dev
```

## Persistent data

Each component gets a folder under `<data-dir>/EmuSC/Hardware/`, named after its type and index. HDDs keep a `data.json` in theirs; `display_file` components write their `pixels.json` to the same tree. The data directory defaults to the current working directory; use `--data-dir` to change it:

```
emusc script.lua -H hdd:main -d ./saves
```

This writes to `./saves/EmuSC/Hardware/hdd_0/data.json`.

## License

License text copyright © 2024 MariaDB plc, All Rights Reserved. “Business Source License” is a trademark of MariaDB plc.

### Terms
The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use.

Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate.

If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work.

All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor.

You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work.

Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work.

This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark “Business Source License”, as long as you comply with the Covenants of Licensor below.

Covenants of Licensor
In consideration of the right to use this License’s text and the “Business Source License” name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor:

To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text “None” to specify a Change Date. Not to modify this License in any other way.
