Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
936 commits
Select commit Hold shift + click to select a range
2f6f877
Archived old ones.
datvm Mar 6, 2026
1c1e94b
T4UI 10.2.0
datvm Mar 7, 2026
855b5f3
MHA WIP
datvm Mar 9, 2026
b414733
MHA WIP
datvm Mar 13, 2026
dab5a4b
ESD 10.0.2
datvm Mar 13, 2026
36d4e41
Added CNT
datvm Mar 16, 2026
547a83b
Added BWS
datvm Mar 17, 2026
5129b5e
WIP MHA
datvm Mar 17, 2026
873f1a5
Tool hotkeys now select associated tool groups and parent hierarchy
HMChadwick Mar 17, 2026
4c68791
MHA WIP
datvm Mar 18, 2026
d720f70
Updated version and various styling consistency.
datvm Mar 18, 2026
a09c6d6
Merge pull request #15 from HMChadwick/open-button-tree
datvm Mar 18, 2026
ecdb628
XPNC 10.2.0
datvm Mar 19, 2026
4d9bc03
MW 10.1.0
datvm Mar 20, 2026
9d97996
SB&BR 10.0.0
datvm Mar 20, 2026
bd86d95
RHP 10.0.0
datvm Mar 22, 2026
b7782f1
CfgP 10.1.3
datvm Mar 23, 2026
ec2b811
BBb 10.0.0
datvm Mar 24, 2026
dcd1288
RP 10.0.1
datvm Mar 26, 2026
8611ffa
MTA 10.1.1
datvm Mar 26, 2026
e77274d
MHA WIP
datvm Mar 26, 2026
5414ed6
Add files via upload
SergeiDevelp Mar 28, 2026
5d5fcbc
Add files via upload
SergeiDevelp Mar 28, 2026
a93c47b
MA WIP
datvm Apr 2, 2026
da98add
MA WIP
datvm Apr 2, 2026
5dad96e
MA WIP
datvm Apr 2, 2026
c0291a1
T4UX 10.1.6
datvm Apr 2, 2026
1fa91ab
MA WIP
datvm Apr 2, 2026
725fefa
MTA 10.2.0
datvm Apr 2, 2026
0c23e1b
MA WIP
datvm Apr 2, 2026
80532be
MA v10.0.0
datvm Apr 2, 2026
4be8cd8
RP 10.0.2
datvm Apr 2, 2026
bf28a52
BR 10.0.2
datvm Apr 6, 2026
bae8f33
BBn v10.0.0
datvm Apr 6, 2026
b0155a4
PT 10.2.0
datvm Apr 6, 2026
b597220
MTA 10.2.1 + T4M 10.1.0
datvm Apr 6, 2026
ac13957
Merge pull request #18 from SergeiDevelp/master
datvm Apr 7, 2026
b5c330d
SC 10.0.6
datvm Apr 7, 2026
83e97b8
SIB v10.0.1
datvm Apr 7, 2026
f9ee09f
SP v10.0.2
datvm Apr 7, 2026
d4b456b
BD 10.0.1
datvm Apr 7, 2026
4c759b5
TI 10.2.0
datvm Apr 18, 2026
b9fed7d
EML v10.1.0
datvm Apr 18, 2026
95e72cc
MTG 10.4.6
datvm Apr 18, 2026
3c14aea
HO v10.1.1
datvm Apr 20, 2026
56b8eed
TUI v10.1.4
datvm Apr 20, 2026
2edccf7
DS WIP
datvm Apr 20, 2026
bb387c7
DS 10.0.0
datvm Apr 20, 2026
fba993b
Archived OB & QB.
datvm Apr 21, 2026
e1daf39
T4UX 10.2.0
datvm Apr 23, 2026
24ffef2
DS 10.0.1
datvm Apr 23, 2026
5328f63
CTG 10.5.0
datvm Apr 25, 2026
211f9e6
RT 10.0.0
datvm Apr 25, 2026
877a793
BC WIP
datvm Apr 26, 2026
d3f1f95
TBMM v10.0.0
datvm Apr 28, 2026
ae1b669
TBMM 10.0.1
datvm Apr 28, 2026
348c220
DTB WIP
datvm Apr 30, 2026
6422c94
DTB 10.0.0
datvm May 1, 2026
9eaf485
RT 10.0.1
datvm May 4, 2026
92124e3
WIP
datvm May 5, 2026
652542b
DTB 10.0.0
datvm May 6, 2026
8493c2e
DTB v10.0.1
datvm May 6, 2026
973b182
WIP
datvm May 10, 2026
98f5166
DTB 10.0.2
datvm May 11, 2026
ffabe4b
BC WIP
datvm May 12, 2026
1f56027
BC WIP
datvm May 12, 2026
18f430a
BCCF
datvm May 13, 2026
0ba8193
BC v10.0.1
datvm May 15, 2026
647a355
WIP
datvm May 15, 2026
a584b3d
MO WIP
datvm May 16, 2026
7630a44
MHA WIP
datvm May 16, 2026
be4fbda
WIP
datvm May 17, 2026
17ccb55
MHA 10.0.0
datvm May 19, 2026
e56c54e
Add workflow to build and deploy TimberLive
datvm May 19, 2026
2faab42
Fixed root path.
datvm May 19, 2026
fd83b18
Update publish workflow and add fingerprint validation
datvm May 19, 2026
54f8cb4
TImprove v10.2.1
datvm May 20, 2026
a847c0a
WIP MT with Test
datvm Jun 1, 2026
cb9b0e6
Added more tests.
datvm Jun 1, 2026
871005e
Various updates.
datvm Jun 2, 2026
4d6565f
WIP
datvm Jun 8, 2026
b59cd92
BC WIP
datvm Jun 8, 2026
ab6582f
Add consumer documentation for ModdableTimberborn
everboom Jun 8, 2026
b6e6f40
Add per-folder READMEs for ModdableTimberborn
everboom Jun 8, 2026
a5eaff7
Docs: address review feedback on ModdableTimberborn guides
everboom Jun 8, 2026
e6ff07b
Merge pull request #25 from everboom/docs/moddabletimberborn-guides
datvm Jun 8, 2026
c9cc042
Updated Stats docs.
datvm Jun 8, 2026
64b509a
Add TimberUi consumer documentation
everboom Jun 8, 2026
65e42b7
Fix TimberUi doc audit findings
everboom Jun 8, 2026
4cf1f4a
Add three TimberUi tutorials: HUD/menus, dev tools, prefab decorators
everboom Jun 9, 2026
bade6ee
WIP
datvm Jun 9, 2026
7b85847
Address third-pass audit; add composite-widgets section
everboom Jun 9, 2026
4a93d9b
Add per-folder README documentation for TimberUi
everboom Jun 9, 2026
3b90d00
WIP
datvm Jun 9, 2026
acfd4d5
Merge pull request #27 from everboom/docs/timberui-guides
datvm Jun 9, 2026
0cdef9b
Apply suggestions from code review
datvm Jun 9, 2026
483e366
Merge pull request #26 from everboom/docs/moddabletimberborn-readmes
datvm Jun 9, 2026
7821403
Merge branch 'master' of https://github.com/datvm/TimberbornMods
datvm Jun 9, 2026
f53471e
WIP
datvm Jun 9, 2026
1f35fb4
Apply suggestions from code review
datvm Jun 9, 2026
ff539f8
Merge pull request #28 from everboom/docs/timberui-readmes
datvm Jun 9, 2026
a3e6e26
WIP
datvm Jun 9, 2026
41b7247
Merge branch 'master' of https://github.com/datvm/TimberbornMods
datvm Jun 9, 2026
fb3fd73
Cleaning up.
datvm Jun 9, 2026
d8b6e81
WIP
datvm Jun 11, 2026
0caf92d
SIB v10.1.0
datvm Jun 11, 2026
d06b075
WYLATL v10.0.0
datvm Jun 12, 2026
a0cdf73
WIP
datvm Jun 12, 2026
a598c4a
WIP
datvm Jun 12, 2026
90cf2d1
WIP
datvm Jun 13, 2026
6909963
Unify and extend entity buff system for all targets
datvm Jun 13, 2026
6b9ec3a
WIP
datvm Jun 13, 2026
6147374
WIP
datvm Jun 13, 2026
668b2d9
Fixed Tubeway speed modifier
nightw Jun 14, 2026
0988744
WIP
datvm Jun 14, 2026
c877910
Merge pull request #30 from nightw/master
datvm Jun 14, 2026
0995202
Merge branch 'master' of https://github.com/datvm/TimberbornMods
datvm Jun 14, 2026
2eef2df
WIP
datvm Jun 14, 2026
54857de
WIP
datvm Jun 15, 2026
f9f87d2
WIP
datvm Jun 15, 2026
ac7d763
WIP
datvm Jun 15, 2026
269d5fc
WIP
datvm Jul 1, 2026
9a8c618
WIP
datvm Jul 3, 2026
8d1d170
RL 11.0.0
datvm Jul 3, 2026
9c69d76
WIP
datvm Jul 3, 2026
bd815fb
WBG 11.0.0
datvm Jul 3, 2026
faba80c
feat(ModdableTimberborn): add FillValveSettings for building duplication
babs Jul 3, 2026
d675bdf
Merge pull request #33 from babs/fix/moddable-fillvalve-settings
datvm Jul 4, 2026
8c9cd93
RS 11.0.0
datvm Jul 4, 2026
4a5ace8
Merge branch 'master' of https://github.com/datvm/TimberbornMods
datvm Jul 4, 2026
80ab462
RP v11.0.0
datvm Jul 4, 2026
81f9f50
MT 11.0.1
datvm Jul 4, 2026
7d9b478
WIP
datvm Jul 4, 2026
538242a
WIP
datvm Jul 6, 2026
34ff095
WIP
datvm Jul 6, 2026
6616051
Updated Docs
datvm Jul 6, 2026
c2c13cb
BC 11.0.0
datvm Jul 6, 2026
e0e66e1
BC 11.0.1
datvm Jul 7, 2026
b307204
Pin 11.0.0
datvm Jul 7, 2026
f44c8bd
WIP
datvm Jul 8, 2026
02bafae
DH v11.0.0
datvm Jul 9, 2026
144401f
WIP
datvm Jul 9, 2026
37587e4
CB v11.0.0
datvm Jul 9, 2026
e4e37dd
CB v11.1.0
datvm Jul 10, 2026
0feaffd
CB v11.1.1
datvm Jul 10, 2026
2779f9e
WBG v11.0.1
datvm Jul 10, 2026
53ff69e
ABTP
datvm Jul 13, 2026
b3f470e
DS 11.0.0
datvm Jul 13, 2026
f4d7ff5
BB v11.0.0
datvm Jul 13, 2026
fe37c0f
WIP
datvm Jul 13, 2026
f02a3db
UCC 11.0.0
datvm Jul 14, 2026
1e9cfdf
Various update for v1.1.1
datvm Jul 17, 2026
db11115
BB 11.0.1
datvm Jul 17, 2026
4a37a10
BWS v1.1.1
datvm Jul 17, 2026
9fedf6a
SPs v11.0.0
datvm Jul 17, 2026
34cbdb9
PL v11.0.0
datvm Jul 17, 2026
f16002c
WIP
datvm Jul 18, 2026
ba1074f
WIP
datvm Jul 19, 2026
cada7f0
Various updates.
datvm Jul 20, 2026
48d512d
WIP
datvm Jul 20, 2026
ecfdfab
SPs v11.0.0
datvm Jul 20, 2026
6d3b517
Archived Renovations.
datvm Jul 20, 2026
6dcf9fe
WIP
datvm Jul 21, 2026
e0d86e8
PL v11.1.0
datvm Jul 22, 2026
c10f985
WIP
datvm Jul 24, 2026
5a4b4d4
WIP
datvm Jul 26, 2026
8c5393a
BR 11.0.0
datvm Jul 28, 2026
5063c31
EBR v11.0.0
datvm Jul 28, 2026
fc0bf03
MT v11.0.6
datvm Jul 28, 2026
9ae2067
WIP
datvm Jul 28, 2026
35dad4c
MT build chain.
datvm Jul 29, 2026
464bb62
WIP
datvm Jul 29, 2026
15c1303
CL v11.0.0: fix LifeProgressor field for Timberborn 1.1
MateuszT91 Jul 31, 2026
3744235
Merge pull request #36 from MateuszT91/fix/configurable-lifetime-1.1
datvm Jul 31, 2026
ad4bdac
CL v11.0.0
datvm Jul 31, 2026
f2c99e4
FP v11.0.0
datvm Aug 1, 2026
f9a52f8
WIP
datvm Aug 3, 2026
61a113f
Added dedicated Blueprint Reader.
datvm Aug 3, 2026
3499895
Added Blender conversion script.
datvm Aug 3, 2026
329ebb7
Added T2B docs.
datvm Aug 3, 2026
52db503
WIP
datvm Aug 3, 2026
50c52f6
Adding extra hauler target.
datvm Aug 7, 2026
b356dad
CSH v11.0.0
datvm Aug 7, 2026
d4f9705
Added Extra Hauler Docs.
datvm Aug 8, 2026
04e7b68
TMesh 2 JSON
datvm Aug 9, 2026
cdc4d7b
Added MT trace
datvm Aug 9, 2026
2298eca
Revert "Added MT trace"
datvm Aug 9, 2026
2f5b9a8
CSH v11.0.1
datvm Aug 9, 2026
6faf392
MT v11.1.2
datvm Aug 9, 2026
d1a1ee0
4Pillar v11.0.1
datvm Aug 17, 2026
ddeffa8
WIP
datvm Aug 18, 2026
be4828e
WIP
datvm Aug 18, 2026
a5d44ec
Added Docs.
datvm Aug 22, 2026
f1cb0ba
Document Crane mod, improve job queue UI, add demolish spec
datvm Aug 22, 2026
b876872
Restore content to a5d44ec8
datvm Aug 22, 2026
b43ac66
Crane v11.1.0
datvm Aug 22, 2026
62464c0
BR v11.1.0
datvm Aug 22, 2026
70ab9cc
CF v11.1.0
datvm Aug 22, 2026
d240454
WIP
datvm Aug 22, 2026
da17f5a
MFP v11.0.0
datvm Aug 25, 2026
bbd5e9e
WIP
datvm Aug 26, 2026
a46922c
WIP
datvm Sep 1, 2026
65f1836
CH v11.0.0
datvm Sep 2, 2026
042f34f
BC v11.1.0
datvm Sep 2, 2026
58fdaf2
F+ v11.0.0
datvm Sep 2, 2026
0d39c76
WIP
datvm Sep 2, 2026
16ab9e1
PL v11.1.1
datvm Sep 4, 2026
43c8245
WIP
datvm Sep 6, 2026
5de53f3
CfP v11.0.0
datvm Sep 6, 2026
3eb058d
DP v11.0.0
datvm Sep 6, 2026
320378e
CSH v11.0.2
datvm Sep 6, 2026
584a198
WIP
datvm Sep 6, 2026
6cab281
XPNC v11.2.0
datvm Sep 7, 2026
c39b60e
BD & MDG v11.0.0
datvm Sep 7, 2026
dc91b7b
Archived MR.
datvm Sep 8, 2026
55db114
Move archived mods off master onto the archived branch.
datvm Sep 8, 2026
ada0bfb
H&T v11.0.0
datvm Sep 8, 2026
4c8b04d
NBR v11.0.0
datvm Sep 8, 2026
9605071
WIP
datvm Sep 8, 2026
4b88198
MTr v11.0.0
datvm Sep 9, 2026
a41f56d
WIP
datvm Sep 9, 2026
b6b4106
WIP
datvm Sep 12, 2026
1770695
TP v11.0.0
datvm Sep 14, 2026
24fdd4b
MHA v11.0.0
datvm Sep 14, 2026
5283860
TP v11.0.1
datvm Sep 15, 2026
44ece33
CB v11.2.0
datvm Sep 15, 2026
402b680
TP v11.1.0
datvm Sep 16, 2026
f500f73
TP v11.2.0
datvm Sep 18, 2026
1599b51
WIP
datvm Sep 19, 2026
4206d85
BWS v11.0.1
datvm Sep 21, 2026
4479795
PO v11.0.0
datvm Sep 23, 2026
1769c20
T4UI v11.0.0
datvm Sep 23, 2026
d7f0cf0
Remove ConveyorBelt so it can be remade.
datvm Sep 26, 2026
ec59e44
WIP
datvm Sep 26, 2026
d8bb46f
TImprove v10.2.2
datvm Sep 30, 2026
04fc845
MTA v11.0.0
datvm Oct 1, 2026
0f8c38f
Add T pipe junctions
idmytro Oct 4, 2026
454a006
WIP CB
datvm Oct 2, 2026
3f4a3de
Merge pull request #44 from idmytro/pipes-2t
datvm Oct 5, 2026
419549e
TB v11.3.0
datvm Oct 5, 2026
0b918ef
TP v11.3.1
datvm Oct 5, 2026
9cf84f0
WIP
datvm Oct 5, 2026
e94ec19
MFBS v11.0.0
datvm Oct 7, 2026
22434e9
SIB v11.0.0
datvm Oct 7, 2026
2341ddf
CB v11.3.0
datvm Oct 7, 2026
204b342
MT v11.1.3
datvm Oct 7, 2026
9846205
MDG v11.0.1
datvm Oct 7, 2026
5f804c2
BC v11.0.0
datvm Oct 10, 2026
863d244
TP v11.3.2
datvm Oct 10, 2026
cbb4d58
Port Benchmark & Optimizer to Timberborn 1.1 with isolated CSV and in…
tharbad08 Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[*.cs]
dotnet_style_require_accessibility_modifiers = omit_if_default:warning
dotnet_diagnostic.IDE0040.severity = warning
15 changes: 15 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# These are supported funding model platforms

github: datvm
patreon: # Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
31 changes: 31 additions & 0 deletions .github/copilot-instructions.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copilot Instructions

## General Guidelines
- When validating changes, build only the projects containing modified files instead of building the whole solution.
- Do not run `dotnet build` when changes are limited to JavaScript and CSS files only.

## Code Style
- Always use code blocks even for single conditional or loop statements. For example:
```cs
if (condition) { return; }

// NOT:
if (condition) return;
```
- Always use the latest C# features like pattern matching, switch expressions, and collection initializers. For example:
```cs
List<int> numbers = [];
MyType variable = new();

// NOT:
List<int> numbers = new();
MyType variable = new MyType();
```
- Prefer no access modifier for lowest visibility. Do not use _ to prefix fields. For example:
```cs
int field;
class MyClass {}

// NOT:
private int _field;
internal class MyClass {}
39 changes: 39 additions & 0 deletions .github/workflows/build-benchmark-v11port.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Build BenchmarkAndOptimizerV11Port
on:
push:
branches:
- pr/benchmark-optimizer-v11-port
paths:
- 'BenchmarkAndOptimizerV11Port/**'
- '.github/workflows/build-benchmark-v11port.yml'
pull_request:
paths:
- 'BenchmarkAndOptimizerV11Port/**'
- '.github/workflows/build-benchmark-v11port.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Build CSV profiler
run: dotnet build BenchmarkAndOptimizerV11Port/BenchmarkAndOptimizerV11Port.csproj -c Release
- name: Stage ready-to-install mod
shell: bash
run: |
set -euxo pipefail
ROOT="${RUNNER_TEMP}/timberborn-artifact/BenchmarkAndOptimizerV11Port"
mkdir -p "$ROOT/version-1.1/Scripts"
cp BenchmarkAndOptimizerV11Port/manifest.json "$ROOT/version-1.1/manifest.json"
cp BenchmarkAndOptimizerV11Port/bin/Release/netstandard2.1/BenchmarkAndOptimizerV11.dll "$ROOT/version-1.1/Scripts/"
test -s "$ROOT/version-1.1/Scripts/BenchmarkAndOptimizerV11.dll"
- uses: actions/upload-artifact@v4
with:
name: BenchmarkAndOptimizerV11Port_1.1.103
path: ${{ runner.temp }}/timberborn-artifact/
if-no-files-found: error
76 changes: 76 additions & 0 deletions .github/workflows/publish-timberlive.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Publish TimberLive

on:
workflow_dispatch:

permissions:
contents: write

concurrency:
group: publish-timberlive
cancel-in-progress: false

jobs:
build-and-publish:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Restore dependencies
run: dotnet restore TimberLive/TimberLive.csproj

- name: Publish TimberLive
run: dotnet publish TimberLive/TimberLive.csproj --configuration Release --output /tmp/TimberLive-publish

- name: Verify fingerprint placeholders were replaced
run: |
if grep -R "#\[.{fingerprint}\]" /tmp/TimberLive-publish/wwwroot/index.html; then
echo "Fingerprint placeholder was not replaced in published index.html"
exit 1
fi

- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy /tmp/TimberLive-publish/wwwroot --project-name=timberlive

- name: Checkout or create publish branch
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"

if git ls-remote --exit-code --heads origin TimberLive-publish; then
git fetch origin TimberLive-publish
git switch TimberLive-publish
git reset --hard origin/TimberLive-publish
else
git switch --orphan TimberLive-publish
git rm -rf . || true
fi

- name: Copy published files
run: |
rm -rf TimberLive
mkdir -p TimberLive
cp -a /tmp/TimberLive-publish/wwwroot/. TimberLive/

- name: Commit and push changes
run: |
git add TimberLive
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit -m "chore: publish TimberLive from ${{ github.sha }}"
git push origin TimberLive-publish
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ bld/
[Ll]og/
[Ll]ogs/

# Restore the actual buildings
!ConveyorBelt/Root/Buildings/Conveyors/Log/
!ConveyorBelt/Root/Buildings/Conveyors/Log/**

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"grok.mentionIndexLimit": 500000
}
176 changes: 176 additions & 0 deletions Agents.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# ModDesc.txt

Do not write or update `ModDesc.txt` or `ChangeLog.txt` unless the user explicitly asks. The notes below apply only then.

When asked to write a `ModDesc.txt`, write a Steam Workshop description in Steam BBCode (not Markdown). Match the recent mods (Crane, Fourpillars, ConstructionSiteHauler, BuildingRenovations): player-facing, practical, and compact.

Voice: second person, what the player gets. Colleague tone: explain the mod to another player, not ad copy. No marketing fluff. Mix sentence length. A short sentence is fine when the next one carries the detail. Do not stack fragments. That includes "Not X. Not Y. Just Z." and any run of same-beat punches ("No queue. No repeat. Just science.").

Light humor only in `[i]` flavor lines. Bold names, UI labels, and caveats with `[b]`.

For a new building, keep the three parts separate. Do not fold them into one sentence:

- Lore name: the name on the building.
- Mechanical description: what the player can do with it.
- Flavor: one `[i]` line, and not inside the mechanical description.

BBCode only (Steam tags, not Markdown): `[b]`, `[i]`, `[h1]`/`[h2]`, `[img]url[/img]`, `[url=...]text[/url]`, `[list][*] item[/list]`, `[table]`/`[tr]`/`[th]`/`[td]`, `[spoiler]` only when needed. Place a screenshot soon after the intro and after major sections (Steam UGC URL when available).

End every description with the GitHub footer below. Do not paraphrase it.

Typical order (omit unused sections):

1. 1–2 sentences of what the mod does. Optional `[i]` flavor line.
2. Screenshot.
3. `[h1]`/`[h2]` for buildings, features, settings, how-to, tips, FAQs, extending.
4. If configurable: `Main Menu -> Mods -> Settings button next to the mod name`. Say when defaults leave vanilla unchanged.
5. Stats as dashes (`Unlock`, `Cost`, `Workers`, `Range`, …). Related mods as Steam `[url]`.
6. Footer exactly:

```
===
Mod source code and donation: https://github.com/datvm/TimberbornMods (feel free to use the code for anything).
```

# Versioning

Do not bump a mod's `manifest.json` version, `ChangeLog.txt` version heading, or `IModUpdateNotifier2` version / loc key unless the user explicitly asks to bump the version. Fold new notes into the current version entry. Do not write or update `ChangeLog.txt` itself unless the user explicitly asks.

# Code Style

Always use code block even for single conditional or loop statements. For example:
```cs
if (condition) { return; }

// NOT:
if (condition) return;
```

Always use latest C# features like pattern matching, switch expressions, and collection initializers. For example:
```cs
List<int> numbers = [];
MyType variable = new();

// NOT:
List<int> numbers = new();
MyType variable = new MyType();
```

Prefer no access modifier for lowest visibility. Do not use `_` to prefix fields. For example:
```cs
int field;
class MyClass {}

// NOT:
private int _field;
internal class MyClass {}
```

Info-only types (DTOs, checks, list entries, bags of data with no behavior) should be `readonly record struct`, or `record` if they need reference identity. For example:
```cs
readonly record struct Shot(Vector3Int Dest, GameObject Box, float Started);

// NOT:
sealed class Shot
{
public Vector3Int Dest { get; }
public GameObject Box { get; }
public float Started { get; }
}
```

When a `BaseComponent` needs more than one or two injected services, put those dependencies on a `[BindSingleton]` service instead and inject only that service into the component. Put calculation / orchestration methods on the service. For simple shared deps like `ILoc`, expose a readonly field:

```cs
[BindSingleton]
public class DischargePipeService(IWaterService waterService, IThreadSafeWaterMap waterMap, ILoc t)
{
public readonly ILoc t = t;
// …
}

[AddTemplateModule2(typeof(DischargePipeSpec))]
public class DischargePipe(DischargePipeService service) : BaseComponent // …
```

// NOT: inject IWaterService + IThreadSafeWaterMap + ILoc directly into the component.

# Component lifecycle

On a `BaseComponent`, `Awake` only grabs references (`GetComponent`, injected services already on the constructor). Do computation in `InitializeEntity`: reading specs, asking services for rates, building status toggles, filling ports.

A placement preview runs `Awake` and does not run `InitializeEntity`. That `Awake` can run before other services' `Load`. Work done there can crash the preview. `BeltCarrier` is the pattern: `Awake` stores `BlockObject` and `MechanicalNode`; `InitializeEntity` reads `BeltCarrierSpec`, registers the stuck status, and asks `BeltCarrierService` for items per hour.

# Singleton lifecycle

`ILoadableSingleton.Load` and `IPostLoadableSingleton.PostLoad` run in **dependency order**. If B's constructor injects A, `A.Load` always runs before `B.Load` (same for `PostLoad`). Do not add `EnsureLoaded` / lazy-init sequences to force that order.

# Tests

Keep test method names short and descriptive. Prefer names like `InitializeWithCorrectCharacterType`, `IgnoreWrongCharacterType`, or `ComputeSegments` over long Given/When/Then-style names.

Prefer focused tests with clear arrange/act/assert spacing. Use helpers or factories for repeated setup when Unity or Timberborn types require reflection or publicized DLL setup.

# Tools

Timberborn game source should be read from `ModdingAssetUpdater/out`, which contains decompiled game DLLs. When investigating game behavior, search and read that folder instead of decompiling assemblies on demand.

More exported Timberborn game data is stored at `D:\Personal\Mods\Timberborn\V1Data\ExportedProject\Assets\Resources`. For example, the `Buildings` folder there contains game building blueprints that may be useful when comparing mod blueprints to vanilla behavior.

If `ModdingAssetUpdater/out` does not exist or is empty, ask the user to decompile the game source there first.

Leave `BackwardCompatibleTemplateNames` as `[]`. Do not add old template names unless the user explicitly asks. We are developing; save migration is not needed unless requested.

Game assemblies are publicized for mod projects. It is okay to reference publicized Timberborn types and members directly in code and Harmony patches instead of avoiding `internal` or private members with reflection-only approaches.

Timberborn grid coordinates use **X/Y for the horizontal plane and Z for vertical**. Unity is the opposite: **Y is up**, with X/Z as the horizontal plane. When converting grid coordinates or directions into Unity/world vectors, check `CoordinateSystem` and its namespace code first (`GridToWorld`, `GridToWorldCentered`, and the reverse). It likely already has the conversion needed, so avoid adding local helpers like `ToUnityDirection` unless the built-in conversion does not fit.

## Timbermesh models (read / edit)

When you need to **read or edit** a `.timbermesh` model (node hierarchy, materials, meshes, doors/props, etc.), use the `tmesh2glb` tool from `Timbermesh2Blender` — do **not** try to parse the binary by hand.

Working directory for dumps/packs: **`D:\Temp\TimbermeshModel`**.

```powershell
# From repo root. -c Release is required: the Debug build replaces args with a hardcoded Forester path.
dotnet run -c Release --project Timbermesh2Blender -- dump -i <model-or-folder> -o D:\Temp\TimbermeshModel -f
# Edit the produced *.timbermesh.json
dotnet run -c Release --project Timbermesh2Blender -- pack -i D:\Temp\TimbermeshModel\<name>.timbermesh.json -o D:\Temp\TimbermeshModel -f
```

The installed `tmesh2glb` tool is fine too. It does not have that Debug override.

Notes:

- Default dump keeps vertex attributes as **base64** (lossless). Use `--decode-vertices` only when you need numeric position/normal/uv arrays.
- Prefer structural edits in JSON (delete/rename/reparent nodes, swap material names). Use **glb** export + Blender for real mesh sculpting.
- After packing, you can preview with `tmesh2glb glb -i ... -r <Resources> -o D:\Temp\TimbermeshModel -f`.
- Game Resources path: `D:\Personal\Mods\Timberborn\V1Data\ExportedProject\Assets\Resources`.
- **Folktails first.** Unless the user explicitly asks for Iron Teeth (or both factions), only dump / edit / pack **Folktails** models. Do the Iron Teeth pass later, after the Folktails model is approved.

### UV mapping

A generated building that looks clipped has a bad `uv0` rectangle. The face shows a chopped mix: part of a board, a blank pale patch, a hole, a metal trim cut in half. A pale or white face is the same bug. It is the empty corner of the picture, or another material left on a made-up rectangle. Fix every material on the model, not only the one that looked worst.

The material's picture is a collage of many separate pictures in one square. `uv0` picks a spot in that square. `(0,0)` is one corner of the whole square. `(1,1)` is the opposite corner. A face set to `(0,0)`–`(1,1)` stretches the entire collage across that one face.

Two fixes that still look clipped:

- Any rectangle you invent, even one that sits inside the square. On the belt, a wide patch of the wood picture removed the hole and still cut the grain off at the edge of the face. The metal bar was left on a homemade patch and stayed a pale clipped plate.
- Shrinking the coordinates yourself for the faction atlas. The game already does `uv * UVScale + UVOffset` in `AutoAtlasingPrefabOptimizer`. Write coordinates against the original picture.

What works is one vanilla face's rectangle, copied unchanged, per face:

- Dump a vanilla mesh that uses the same material, with `--decode-vertices`. Read one face's `uv0` and use that exact box.
- Wood (`BaseWood_*`, both factions): `Platform.Full.Folktails` on `BaseWood_Brown.Folktails`. One board is `u 0.7504–0.8128`, `v 0.5001–0.8753`. The next boards on that platform are the same height, stepped across in `u` (`0.8129–0.8753`, `0.8754–0.9378`, `0.9379–0.998`).
- Metal (`BaseMetal.Folktails`): `MetalPlatform3x3.Full.Folktails`. The repeated small plate is `u 0.595–0.656`, `v 0.008–0.242`.
- One face, one rectangle. A wider surface is several faces, each with the next vanilla rectangle. The platform top is a row of boards, not one face covering many boards.
- Stay on the copied numbers. `0.5001` instead of `0.5000` is already in them so the face does not pick up the neighbor.

Before packing, dump with `--decode-vertices` and check every material. A triangle whose `uv0` runs `0–1`, or whose box is larger than the vanilla face you copied, is still clipped.

## Buildings (Folktails first)

Unless the user explicitly asks for Iron Teeth (or both factions), only create and edit **Folktails** buildings. Do not create `<Building>.IronTeeth.blueprint.json` or an Iron Teeth collection until they say they are ready for the IT pass.

When adding a building, copy a placeholder icon **into that building's own folder** (for example `Buildings/Water/Pipes/NewPipe/NewPipeIcon.png`) and point `LabeledEntitySpec.Icon` at that local file. Do not reuse another building's icon path.
7 changes: 7 additions & 0 deletions AirlockChamber/AirlockChamber.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputModFolderName>AirlockChamber</OutputModFolderName>
</PropertyGroup>

<Import Project="../Targets/CommonJson.targets" />
</Project>
Loading