Skip to content

Commit 077cc27

Browse files
committed
Add minification tool and smoke test for engine validation
- Implemented a Lua minification tool in tools/minify.lua to optimize Lua scripts. - Created a smoke test in tools/smoketest.lua to validate engine subsystems and entry points. - The smoke test checks for the presence of required subsystems and verifies functionality of key engine methods.
1 parent fbea986 commit 077cc27

43 files changed

Lines changed: 5697 additions & 330 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/docs-home.md‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Welcome to the Obsidian Wiki
2+
3+
Obsidian is a 2D game engine for **CC:Tweaked**. It combines an Entity
4+
Component System with a retained renderer, so game logic stays decoupled from
5+
data while drawing keeps the terminal redraws down to what actually changed.
6+
7+
## Features
8+
9+
- **ECS architecture:** entities, components and systems, with a spatial grid
10+
behind rect queries, triggers, raycasting and line-of-sight checks
11+
- **Retained renderer:** z-ordered layers with per-channel transparency,
12+
nested translation and clipping contexts, and dirty-region tracking
13+
- **Colour beyond the 16 slots:** register logical RGB colours and let the
14+
palette mapper assign them to hardware slots per frame
15+
- **Subpixels:** a 2x3 virtual canvas compiled into CC mosaic characters
16+
- **FLIMG images:** a binary image format that keeps RGB and subpixels intact
17+
instead of baking them into terminal cells
18+
- **Scenes and tilemaps:** multi-layer maps with collision, slopes and one-way
19+
platforms, plus static, dynamic and foreground rendering passes
20+
- **Gameplay systems:** physics, particles, tweens, timers, pathfinding, AI
21+
behaviour trees, audio, save/load, and a document store
22+
- **Multiplayer:** a rednet wrapper with heartbeats plus a high-level server
23+
with rooms, middleware and an optional console
24+
- **Developer friendly:**
25+
- LuaLS type information for editor support
26+
- Generated API documentation that stays synchronized with the source
27+
- Source, minified and compressed release bundles
28+
29+
## Installation
30+
31+
The installer places the engine into your computer as `obsidian`, so it is
32+
loaded by name:
33+
34+
```lua
35+
local Engine = require("obsidian")
36+
```
37+
38+
A release bundle works the same way: drop `obsidian.lua` in next to your
39+
program and `require("obsidian")` finds it.
40+
41+
## Quick Start
42+
43+
```lua
44+
local Engine = require("obsidian")
45+
46+
local scene = Engine.scene.new()
47+
scene.name = "Hello"
48+
49+
local player = scene:spawn()
50+
scene:attach(player, "pos", Engine.math.vec2(10, 5))
51+
52+
scene.onDraw = function()
53+
Engine.buffer:drawText(2, 2, "Hello Obsidian", "0", "f")
54+
end
55+
56+
Engine.setScene(scene)
57+
Engine.start()
58+
```
59+
60+
## Where to go next
61+
62+
- [Engine Quickstart](/guides/engine_quickstart) walks through a first project
63+
- [ECS Guide](/guides/ecs_guide) explains entities, components and systems
64+
- The [API Reference](/api/) documents every module, generated from the sources

‎.github/docs-index.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
layout: home
3+
4+
hero:
5+
name: Obsidian
6+
text: 2D game engine for CC:Tweaked
7+
tagline: ECS architecture, a retained renderer with RGB colours and subpixels, and a documented API that stays in sync with the source.
8+
actions:
9+
- theme: brand
10+
text: Get Started
11+
link: /guides/engine_quickstart
12+
- theme: alt
13+
text: API Reference
14+
link: /api/
15+
- theme: alt
16+
text: View on GitHub
17+
link: https://github.com/Pyroxenium/Obsidian
18+
19+
features:
20+
- title: Entity Component System
21+
details: Entities, components and systems with spatial queries, triggers, raycasting and line-of-sight built in.
22+
- title: Retained renderer
23+
details: Layered surfaces with z-ordering, logical RGB colours mapped onto the terminal palette, and a 2x3 subpixel canvas compiled into mosaic characters.
24+
- title: Batteries included
25+
details: Scenes, tilemaps, physics, particles, tweens, timers, pathfinding, audio, networking, an in-game console and a panic screen.
26+
- title: Generated documentation
27+
details: Every page here is produced from the LuaLS annotations in the sources, so the reference cannot drift away from the code.
28+
---

‎.github/vitepress.config.mts‎

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { existsSync, readdirSync } from 'node:fs'
2+
import { basename, resolve } from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
import { defineConfig } from 'vitepress'
5+
6+
// This file is copied into the gh-pages branch as docs/.vitepress/config.mts
7+
// by .github/workflows/docs.yml. Edit it here, never there.
8+
9+
const docsRoot = fileURLToPath(new URL('..', import.meta.url))
10+
const apiRoot = resolve(docsRoot, 'api')
11+
12+
// The API pages are generated by tools/docgen.lua, so the sidebar is built by
13+
// reading the directory instead of listing every module by hand. A new module
14+
// appears in the navigation as soon as it exists in src/.
15+
function apiItems(folder: string) {
16+
const directory = resolve(apiRoot, folder)
17+
if (!existsSync(directory)) return []
18+
19+
return readdirSync(directory)
20+
.filter((file) => file.endsWith('.md'))
21+
.sort((left, right) => left.localeCompare(right))
22+
.map((file) => ({
23+
text: basename(file, '.md'),
24+
link: `/api/${folder}/${basename(file, '.md')}`,
25+
}))
26+
}
27+
28+
export default defineConfig({
29+
title: 'Obsidian',
30+
description: 'Obsidian API documentation for CC:Tweaked',
31+
lang: 'en-US',
32+
// GitHub project site: https://pyroxenium.github.io/Obsidian/
33+
// Change this if the site ever moves to a custom domain.
34+
base: '/Obsidian/',
35+
lastUpdated: true,
36+
37+
themeConfig: {
38+
siteTitle: 'Obsidian',
39+
search: {
40+
provider: 'local',
41+
},
42+
nav: [
43+
{ text: 'Home', link: '/home' },
44+
{ text: 'Guides', link: '/guides/engine_quickstart' },
45+
{ text: 'API Reference', link: '/api/' },
46+
],
47+
sidebar: {
48+
'/guides/': [
49+
{
50+
text: 'Guides',
51+
items: [
52+
{ text: 'Engine Quickstart', link: '/guides/engine_quickstart' },
53+
{ text: 'ECS Guide', link: '/guides/ecs_guide' },
54+
],
55+
},
56+
],
57+
'/api/': [
58+
{
59+
text: 'API Reference',
60+
link: '/api/',
61+
},
62+
{
63+
text: 'Runtime',
64+
items: [{ text: 'engine', link: '/api/engine' }],
65+
},
66+
{
67+
text: 'Core',
68+
collapsed: false,
69+
items: apiItems('core'),
70+
},
71+
{
72+
text: 'UI',
73+
collapsed: false,
74+
items: apiItems('core/ui'),
75+
},
76+
{
77+
text: 'Formats',
78+
items: [{ text: 'flimg', link: '/api/flimg' }],
79+
},
80+
],
81+
},
82+
outline: [2, 3],
83+
docFooter: {
84+
prev: false,
85+
next: false,
86+
},
87+
footer: {
88+
message: 'Released under the MIT License.',
89+
copyright: 'Copyright © 2026 Pyroxenium',
90+
},
91+
socialLinks: [
92+
{
93+
icon: 'github',
94+
link: 'https://github.com/Pyroxenium/Obsidian',
95+
},
96+
],
97+
},
98+
})

‎.github/workflows/ci.yml‎

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Obsidian CI
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: write
14+
15+
jobs:
16+
build:
17+
name: Checks and documentation
18+
runs-on: ubuntu-22.04
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v6
23+
24+
- name: Install build dependencies
25+
run: |
26+
sudo add-apt-repository --yes ppa:jackmacwindows/ppa
27+
sudo apt-get update
28+
sudo apt-get install --yes craftos-pc lua5.4
29+
30+
# ui/events.lua uses goto, so this needs a 5.2+ compiler. luac5.1 would
31+
# reject it. This only parses, it never runs engine code.
32+
- name: Syntax-check all sources
33+
run: |
34+
status=0
35+
for file in $(find src tools -name '*.lua' | sort); do
36+
if ! luac5.4 -p "$file"; then
37+
echo "::error file=$file::syntax error"
38+
status=1
39+
fi
40+
done
41+
exit $status
42+
43+
# Mirrors what the installer produces: src/ lands in the computer as
44+
# "obsidian", user code sits next to it and calls require("obsidian").
45+
# luac only proves a file parses; this proves the engine comes up.
46+
- name: Smoke-test the source install
47+
run: |
48+
mkdir -p "$RUNNER_TEMP/craftos-smoke"
49+
cp tools/smoketest.lua "$RUNNER_TEMP/craftos-smoke/smoketest.lua"
50+
craftos \
51+
--headless \
52+
--directory "$RUNNER_TEMP/craftos-smoke" \
53+
--mount-ro "obsidian=$GITHUB_WORKSPACE/src" \
54+
--exec "local ok = shell.run('smoketest.lua'); os.shutdown(ok and 0 or 1)"
55+
56+
# Only validated here. The pages are generated and published by
57+
# docs.yml into the gh-pages branch, so master carries no docs/.
58+
- name: Validate documentation annotations
59+
run: lua5.4 tools/docgen.lua --check
60+
61+
- name: Build release bundles
62+
run: |
63+
mkdir -p "$RUNNER_TEMP/obsidian-bundle"
64+
lua5.4 tools/bundle-host.lua \
65+
--no-minify "$RUNNER_TEMP/obsidian-bundle/obsidian.lua"
66+
lua5.4 tools/bundle-host.lua \
67+
"$RUNNER_TEMP/obsidian-bundle/obsidian.min.lua"
68+
lua5.4 tools/bundle-host.lua \
69+
--compress "$RUNNER_TEMP/obsidian-bundle/obsidian.compressed.lua"
70+
71+
# The minifier rewrites every identifier, so a bundle that no longer
72+
# parses is the failure mode that matters most here.
73+
- name: Syntax-check release bundles
74+
run: |
75+
status=0
76+
for file in "$RUNNER_TEMP"/obsidian-bundle/*.lua; do
77+
if ! luac5.4 -p "$file"; then
78+
echo "::error::generated bundle does not parse: $file"
79+
status=1
80+
fi
81+
done
82+
exit $status
83+
84+
# Each bundle is dropped in as obsidian.lua, i.e. exactly where the
85+
# installed directory would sit, and has to satisfy the same test. That
86+
# also proves a bundle is a drop-in replacement for the source install.
87+
- name: Smoke-test release bundles
88+
run: |
89+
for variant in obsidian obsidian.min obsidian.compressed; do
90+
workdir="$RUNNER_TEMP/craftos-bundle-$variant"
91+
mkdir -p "$workdir"
92+
cp tools/smoketest.lua "$workdir/smoketest.lua"
93+
cp "$RUNNER_TEMP/obsidian-bundle/$variant.lua" "$workdir/obsidian.lua"
94+
echo "--- $variant.lua ---"
95+
craftos \
96+
--headless \
97+
--directory "$workdir" \
98+
--exec "local ok = shell.run('smoketest.lua'); os.shutdown(ok and 0 or 1)"
99+
done
100+
101+
- name: Update committed bundles
102+
if: github.event_name == 'push'
103+
run: |
104+
mkdir -p bundle
105+
cp "$RUNNER_TEMP"/obsidian-bundle/*.lua bundle/
106+
git add bundle
107+
if git diff --cached --quiet; then
108+
echo "bundles already up to date"
109+
exit 0
110+
fi
111+
git config user.name "github-actions[bot]"
112+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
113+
git commit -m "Build release bundles"
114+
git push
115+
116+
- name: Upload release bundles
117+
uses: actions/upload-artifact@v7
118+
with:
119+
name: obsidian-bundles
120+
path: ${{ runner.temp }}/obsidian-bundle/*.lua
121+
if-no-files-found: error

0 commit comments

Comments
 (0)