Reorganize repo: STORY/ as prose source of truth, gen_story.py generator, docs/ ops guides, lang-key single-sourcing

This commit is contained in:
MiTHRAL 2026-08-19 14:54:58 -04:00
parent 09e0b03b80
commit 65de1eb5c8
50 changed files with 1247 additions and 620 deletions

View file

@ -49,13 +49,12 @@ packs: a full client pack and a server-only pack.
``` ```
. .
├── server_pack/ # Server-only packwiz pack (137 mod files) ├── server_pack/ # Server-only packwiz pack (135 mod files)
├── client_pack/ # Full client packwiz pack (146 mod files) ├── client_pack/ # Full client packwiz pack (144 mod files)
│ └── shaderpacks/ # Complementary Reimagined setup guide (4GB VRAM preset) │ └── shaderpacks/ # Complementary Reimagined setup guide (4GB VRAM preset)
├── kubejs/ # (generated inside each pack) story scripts + datapack ├── STORY/ # the story — canon, items, phases, dialogue (edit here)
├── tools/gen_textures.py # regenerates placeholder item/block textures ├── docs/ # operations — setup, server, performance, mods
├── SERVER_MASTER_GUIDE.md # install, server.properties, JVM flags, operations ├── tools/ # gen_story.py, sync_kubejs.sh, gen_textures.py
├── STORY_CANON.md # the lore bible — where story lives & how to extend it
└── README.md └── README.md
``` ```
@ -63,7 +62,8 @@ Both packs are identical except the client pack adds render/shader/visual
mods. Keep them in sync after any change: mods. Keep them in sync after any change:
```bash ```bash
rm -rf client_pack/kubejs && cp -r server_pack/kubejs client_pack/kubejs bash tools/sync_kubejs.sh # kubejs/ → client_pack
python tools/gen_story.py # STORY/*.md → en_us.json (both packs)
``` ```
--- ---
@ -87,7 +87,7 @@ java -Xms4G -Xmx8G -XX:+UseG1GC \
``` ```
Recommended `server.properties`: `view-distance=8`, `simulation-distance=6`. Recommended `server.properties`: `view-distance=8`, `simulation-distance=6`.
Full details in **SERVER_MASTER_GUIDE.md**. Full details in **docs/server.md**.
## Install — client ## Install — client
@ -104,7 +104,7 @@ install via the Modrinth/packwiz installers. Drop a shaderpack into
> **Multiplayer:** players join with the **client pack**; the server runs > **Multiplayer:** players join with the **client pack**; the server runs
> the **server pack**. Never put client-only mods on the server (see the > the **server pack**. Never put client-only mods on the server (see the
> client-only list in SERVER_MASTER_GUIDE.md §2). > client-only list in docs/mods.md).
--- ---
@ -122,8 +122,9 @@ install via the Modrinth/packwiz installers. Drop a shaderpack into
6. **The Doctor connection is atmospheric only** — Renegade Glass, 6. **The Doctor connection is atmospheric only** — Renegade Glass,
*Per Spatium*, portal styling. Never plot-driving. *Per Spatium*, portal styling. Never plot-driving.
Full canon, file map, and a 5-minute "add a story beat" workflow: Full canon, the phase tree, and the 5-minute "add a story beat" workflow:
**STORY_CANON.md**. **STORY/00-index.md**. Story text is generated from STORY/ into `en_us.json`
via `tools/gen_story.py` — edit prose, not scripts.
--- ---

View file

@ -1,247 +0,0 @@
# SERVER MASTER GUIDE — SCICRAFT: The Dark Photon Protocol
**NeoForge 1.21.1 (21.1.248) · packwiz v1.1.0 · version 1.0.0**
---
## 1. The Dark Photon Protocol (Lore)
> In the year 4.2.2.0.5, the universe is burning. The Time Lords sealed a
> collapsing star-empire inside a **Dimensional Door** — but the seal is
> decaying. The **Void Dimension** leaks entropy into the Overworld, and the
> **Deeper and Darker** have begun to answer.
>
> A single broadcast survives the fall: the **Dark Photon Protocol**, a plan
> to stabilize the galaxy by re-binding reality itself. You are the last
> engineer of the Second Renegade Flight. Construct the means, master the
> sciences of **Mekanism, Applied Energistics and Create**, and re-forge the
> photon lattice before the void consumes every world.
### Objective trees (what the pack asks you to build)
1. **Reignite the Ark** — build a base with power (Mekanism turbines /
Flux Networks), storage (AE2 / Sophisticated / Functional Storage),
and logistics (LaserIO / Modular Routers / Entangled / FastPipes).
2. **Walk the Stars** — unlock **Stellaris** rocket tiers; visit Mars,
Venus, and beyond through the rocket menu.
3. **Breach the Doors** — survive **Dimensional Doors**, recover the
**Void Dimension** stabilizer, and descend into the **Deeper and Darker**.
4. **The Protocol** — complete the FTB Quests line and KubeJS advancements.
---
## 2. Packs & Directories
| Path | Contents |
|------|----------|
| `./server_pack/` | Server-only modpack (137 mod files). No shaders, no client render mods. |
| `./client_pack/` | Full client pack (146 mod files). Adds Iris + Sodium (native NeoForge), Cull Leaves, LambDynamicLights, Dynamic FPS, 3D Skin Layers, Visuality, flywheel compat. |
### Key client-only mods (server must NOT have these)
`iris`, `sodium`, `iris-flw-compat`, `cull-leaves`, `lambdynamiclights`,
`dynamic-fps`, `3dskinlayers`, `visuality-forge`, `midnightlib`.
### Bridge layer (both packs)
Sinytra Connector + Forgified Fabric API run a small set of Fabric mods
(Immersive Portals, LambDynamicLights, Waystones-compat). Do not remove
either; the pack will not boot without them.
---
## 3. Install & Update
### Prereqs
- Java 21 (Adoptium Temurin 21 LTS recommended)
- ~12 GB RAM free for client, 8 GB minimum for server
- Disk: keep under **100 GB** total for world + packs
### First-time server setup
```bash
# from this repo root
packwiz install --dir server_pack # downloads all mods into server_pack/
java -Xms2G -Xmx6G -jar server_pack/neoforge-21.1.248-installer.jar --installServer
# accept EULA, then launch:
java -Xms2G -Xmx6G -XX:+UseG1GC -jar server_pack/neoforge-21.1.248-server.jar nogui
```
### Adding a mod (both packs)
```bash
packwiz --dir server_pack curseforge add --addon-id <CF_ID> -y
packwiz --dir client_pack curseforge add --addon-id <CF_ID> -y
packwiz --dir server_pack modrinth add <MR_SLUG_OR_ID> -y
packwiz --dir client_pack modrinth add <MR_SLUG_OR_ID> -y
packwiz --dir server_pack refresh
packwiz --dir client_pack refresh
```
- Always add to **both** packs unless the mod is client- or server-only.
- For Fabric mods that must run through Sinytra, use
`packwiz url add "<Name>" "<URL>" --force` and verify the Sinytra
connector tolerates the version.
---
## 4. Server Properties (view-distance=8, simulation-distance=6)
`server_pack/server.properties` — set these values:
```properties
view-distance=8
simulation-distance=6
max-players=8
motd=SCICRAFT - The Dark Photon Protocol
difficulty=hard
spawn-protection=0
network-compression-threshold=256
enable-command-block=true
online-mode=true
```
`server_pack/eula.txt``eula=true` (after review).
---
## 5. Recommended JVM Flags (server)
```bash
java -Xms4G -Xmx8G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1HeapWastePercent=5 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-Dlog4j2.formatMsgNoLookups=true \
-jar neoforge-21.1.248-server.jar nogui
```
Notes:
- G1 tuning keeps large-tech-server TPS stable under chunk gen (Krypton
Reno + BadOptimizations help server-side).
- `-Xms4G` avoids early GC churn. Cap at 8G; this pack is RAM-hungry
from AE2/Mekanism tick load but does not need 16G.
---
## 6. Shader Tuning for 4GB VRAM (client)
Shader loader is **Iris** (native NeoForge). Recommended shaderpack:
**Complementary Reimagined r5.4** (`client_pack/shaderpacks/`, see README).
Preset for 4GB VRAM:
- Preset: **Fast / Performance**
- Render Distance: **8** (server view-distance)
- Antialiasing: **OFF**
- SSAO: **Fast**, Shadow Quality **1.0x** (0.5x if <30 FPS)
- Shadow Distance: **64**
- Bloom: **OFF/Low**, Clouds: **2D Fast**
- Water Reflections: **Screenspace Fast**
- Colored Light / Block Light: **OFF**
If still under 60 FPS: reduce Shadow Quality to 0.5x, then disable Bloom,
before touching render distance.
---
## 7. Mod Feature Hotspots (Quick Orientation)
| Domain | Mods | Notes |
|--------|------|-------|
| Power | Mekanism (turbine/boiler), Flux Networks | Flux wireless transfer; Mekanism cables for bulk |
| Storage | AE2, Sophisticated Storage, Functional Storage, Sophisticated Backpacks | AE2 for autocraft; Sophisticated for bulk; Functional for drawers |
| Logistics | LaserIO, Modular Routers, Entangled, FastPipes, Create belts | FastPipes adds vanilla pipe QoL |
| Automation | Create + Steam 'n' Rails + Rechiseled + FastPipes | Flywheel + Iris compat bundled |
| Tech Building | Building Gadgets, Hologenica, FramedBlocks, Chipped, Supplementaries | |
| Dimensions | Per Spatium/Stellaris, Dimensional Doors, Void Dimension, Deeper and Darker | Stellaris portal → rockets; Doors are the endgame hook |
| Mobs/Combat | Born in Chaos, Mutant Monsters, Nyf's Spiders, Better Combat, Simply Swords | Hard difficulty |
| UI/QoL | JEI, Jade (+Addons), JourneyMap, Waystones, AppleSkin, IPN, Clumps, Mouse Tweaks | JEI is the recipe source (no EMI) |
| Scripting | KubeJS (+Create, +Mekanism), LootJS, Blocks You Need | Advancements & loot live here |
| Server utils | FTB Chunks/Quests/Teams/Library | Chunk claims + questbook |
---
## 8. Story System (KubeJS + datapack)
Lore is code. All story text lives in the **story bible** and is referenced
from scripts — never hardcoded. See `STORY_CANON.md` for the full
canon, file map, and "add a beat in 5 minutes" workflow.
### File layout (mirrored in BOTH packs under `kubejs/`)
```
kubejs/
├── startup_scripts/registry_blocks.js # photon_core, photon_fragment,
│ # void_stabilizer, quantum_lattice, renegade_glass
├── server_scripts/
│ ├── 00_lore.js # THE STORY BIBLE (edit here first)
│ ├── 01_corruption_tide.js # global Corruption Tide + Lattice re-seal
│ ├── 02_events.js # photon buffs, void/darker hazards
│ ├── 03_recipes_tags.js # crafting chain + ore/ingot tag unification
│ └── 04_loot.js # LootJS: Darker bosses drop Photon Fragments
├── client_scripts/
│ ├── 01_tooltips.js # hover lore on Protocol items
│ └── 02_jei_info.js # JEI "how to obtain" pages
├── data/scicraft/advancements/protocol/*.json # 9-node phase tree (non-terminal)
└── assets/scicraft/ # lang, textures
```
### The phase tree (not a finale — the Protocol is maintained)
1. `root` — The Dark Photon Protocol (on login)
2. `first_signal` — recover a Photon Fragment
3. `the_core` — press 3 fragments → Photon Core
4. `the_seal` — craft the Void Stabilizer
5. `the_lattice` — assemble the Quantum Lattice
6. `the_legacy` — craft Renegade Glass
7. `through_the_doors` — enter Dimensional Doors Limbo
8. `the_wound` / `the_answer` / `per_spatium` — Void, Deeper&Darker, Stellaris
### Global Corruption Tide
- Rises +1 every 60s while Doors stay unsealed (global, all players share).
- Right-click a **Quantum Lattice** with a **Void Stabilizer** to re-seal
a Door: 15 tide.
- ≥30 tide: players get `darkness`. ≥60: `darker_threshold` for future
spawn ramps. 100 = maximum dark. No fail state — soft escalation only.
### Reload rules
- Server scripts / recipes / advancements: `/reload`
- Client tooltips / JEI / textures / lang: `F3+T`
- New items/blocks (`registry_blocks.js`): **full restart**
### Keep both packs in sync
```bash
rm -rf client_pack/kubejs && cp -r server_pack/kubejs client_pack/kubejs
```
---
## 9. Operations & Troubleshooting
### Server start order
1. `packwiz install --dir server_pack` (first time / after changes)
2. Accept EULA.
3. Launch with the JVM flags above.
### Common failures
| Symptom | Fix |
|---------|-----|
| "Mismatched mods" on client join | Run `packwiz refresh` both packs, redeploy. |
| Sinytra connector errors | Update Sinytra Connector + Forgified Fabric API together. |
| Iris black screen | Disable flywheel compat first, then test without shaders. |
| Crash on world gen (Deeper and Darker) | Ensure CF 659011 + its lithostitched data load; update both. |
| TPS lag from many AE2 cells | Check FTB chunk claims; lower `simulation-distance`. |
| Immersive Portals won't load | Must be the Fabric jar added via `url add --force` (Modrinth blocks loader mismatch). |
### Backups
- World: copy `server_pack/world/` (or use FTB Chunks backups).
- Configs: `server_pack/config/` mirrors client defaults; keep both in sync
when changing KubeJS scripts or FTB settings.
---
*Generated for SciCraft Server · packwiz refresh passing on both packs · 146 client / 137 server files.*

73
STORY/00-index.md Normal file
View file

@ -0,0 +1,73 @@
# STORY — SCICRAFT: The Dark Photon Protocol
**This folder is the single source of truth for the pack's story.**
Every piece of player-facing text in the game comes from here.
## How editing works
1. Edit prose and text in `STORY/*.md`.
2. Run the generator:
```bash
python tools/gen_story.py
```
3. It merges every ````lang` JSON block into `en_us.json` in **both** packs
and fails if any referenced lang key is missing.
4. Reload in-game: `/reload` for server text, `F3+T` for client text.
> **Golden rule:** never hand-edit `en_us.json` and never hardcode a story
> string inside a `.js` script. Text lives here (or in the `STORY/*.md`
> prose); scripts only reference lang keys.
## File map
| File | What lives here | Game artifact |
|------|-----------------|---------------|
| `00-index.md` | This index + the editing workflow + verified IDs | — |
| `01-canon.md` | The canon, in one page (the actual story) | — |
| `02-items.md` | Item/block names, hover tooltips, JEI pages | `item.*`, `block.*`, `tooltip.*`, `jei.*` |
| `03-dimensions.md` | Dimension lore + verified dimension IDs | — |
| `04-phases.md` | The advancement phase tree (titles + descriptions) | `advancements.scicraft.protocol.*` |
| `05-dialogue.md` | Player messages: tide warnings, signals, lattice hum | `scicraft.phrases.*` |
| `06-loot.md` | Who drops what, and why | `04_loot.js` (LootJS) |
| `07-todo.md` | Future story beats (drop in whenever) | — |
## The phase tree (non-terminal — the Protocol is maintained)
1. `root` — The Dark Photon Protocol (on login)
2. `first_signal` — recover a Photon Fragment
3. `the_core` — press 3 fragments → Photon Core
4. `the_seal` — craft the Void Stabilizer
5. `the_lattice` — assemble the Quantum Lattice
6. `the_legacy` — craft Renegade Glass
7. `through_the_doors` — enter Dimensional Doors Limbo
8. `the_wound` / `the_answer` / `per_spatium` — Void, Deeper&Darker, Stellaris
## Adding a new story beat (5-minute workflow)
1. **Write the prose** in the right `STORY/*.md` file (canon → `01-canon.md`,
item → `02-items.md`, message → `05-dialogue.md`, goal → `04-phases.md`).
2. **Add the lang keys** to that file's ````lang` block.
3. **If it's a new item/block**: add to `kubejs/startup_scripts/registry_blocks.js`
+ run `tools/gen_textures.py` for a placeholder texture. **Restart** to apply.
4. **Wire the beat** into a script (tide → `01_corruption_tide.js`,
powers → `02_events.js`, craft → `03_recipes_tags.js`, drop → `04_loot.js`).
Use `Text.translate('key')` — never a raw string.
5. Run `python tools/gen_story.py`, then sync:
```bash
bash tools/sync_kubejs.sh
```
6. Reload: `/reload` (server) or `F3+T` (client). Startup items need a restart.
## Verified IDs (do not guess these — they were checked against the jars)
| Thing | Correct ID |
|---|---|
| Limbo (Dimensional Doors) | `dimensionaldoors:limbo` |
| The Wound (Void Dimension) | `thevoiddimension:overworld` |
| The Othersides (Deeper & Darker) | `deeperdarker:otherside` |
| Stellaris moon | `stellaris:moon` (mars/venus/mercury likewise) |
| Warden | `minecraft:warden` |
| Mutant Zombie / Skeleton / Enderman | `mutantmonsters:mutant_zombie` / `mutant_skeleton` / `mutant_enderman` |
| Born in Chaos Dark Vortex / Dread Hound / Nightmare Stalker | `born_in_chaos_v1:dark_vortex` / `dread_hound` / `nightmare_stalker` |
When in doubt, verify against the installed jar before writing an ID into a script.

58
STORY/01-canon.md Normal file
View file

@ -0,0 +1,58 @@
# The Canon — in one page
## The canon
1. **Dark photons are real.** A fifth force the Second Renegade Flight
harnessed. They are the *binding force of the Door* — the pressure that
keeps a collapsed star-empire from unravelling back into reality.
2. **You are a proto-Time-Lord.** Born with the resonance, never finished
training. The signal chose you because only a renegade could read the
Protocol the mortals can't.
3. **The wound.** The Flight sealed the empire inside a Dimensional Door.
The seal is failing. The Void Dimension is the raw wound; the Doors are
scar-tissue; the Deeper and Darker is what's *answering from inside*.
4. **The job.** Rebuild the **Quantum Lattice** — the Protocol's emitter —
and keep it online. The Protocol is never finished; it is maintained.
5. **The tide.** Corruption rises while Doors go unsealed (global, shared by
all players). Re-seal Doors at the Lattice to push it back. No fail state —
just a world that gets darker while you procrastinate.
6. **The Doctor connection is atmospheric only.** TARDIS-blue glass
("Renegade Glass"), the phrase *Per Spatium*, portal styling. Present but
never plot-driving; players who don't care can ignore it entirely.
## The short version (for the README)
1. Dark photons are real — a fifth force the Flight harnessed, the binding
force of the Door.
2. You are a proto-Time-Lord — the only one who can read the Protocol.
3. The wound — the Flight's seal on a collapsed star-empire is failing. The
Void Dimension is the leak; the Deeper and Darker is what answers.
4. The Protocol — rebuild the Quantum Lattice and keep it online.
5. The Corruption Tide — rises while Doors go unsealed (global, shared).
Re-seal Doors at the Lattice with a Void Stabilizer. No fail state.
6. The Doctor connection is atmospheric only — Renegade Glass, *Per Spatium*,
portal styling. Never plot-driving.
## The opening blurb (in-game)
> In the year 4.2.2.0.5, the universe is burning. The Time Lords sealed a
> collapsing star-empire inside a **Dimensional Door** — but the seal is
> decaying. The **Void Dimension** leaks entropy into the Overworld, and the
> **Deeper and Darker** have begun to answer.
>
> A single broadcast survives the fall: the **Dark Photon Protocol**, a plan
> to stabilize the galaxy by re-binding reality itself. You are the last
> engineer of the Second Renegade Flight. Construct the means, master the
> sciences of **Mekanism, Applied Energistics and Create**, and re-forge the
> photon lattice before the void consumes every world.
## Objective trees (what the pack asks you to build)
1. **Reignite the Ark** — build a base with power (Mekanism turbines /
Flux Networks), storage (AE2 / Sophisticated / Functional Storage), and
logistics (LaserIO / Modular Routers / Entangled / FastPipes).
2. **Walk the Stars** — unlock **Stellaris** rocket tiers; visit Mars,
Venus, and beyond through the rocket menu.
3. **Breach the Doors** — survive **Dimensional Doors**, recover the
**Void Dimension** stabilizer, and descend into the **Deeper and Darker**.
4. **The Protocol** — complete the FTB Quests line and KubeJS advancements.

65
STORY/02-items.md Normal file
View file

@ -0,0 +1,65 @@
# Items & Blocks
Every name, tooltip line, and JEI page for the Protocol's items. Keep the
tooltips in the same order they should render (top of list = first line).
## Photon Core
The raw fifth-force crystal. Lattice fuel. Held items let you feel the seals.
## Photon Fragment
Shattered cores recovered from the Darker's remains. Three can be pressed
into a Core.
## Void Stabilizer
The renegades' tool for closing wounds — the "door's key". Right-click a
powered Quantum Lattice with it to re-seal a Door and push back the tide.
## Quantum Lattice
The Protocol's emitter. Must stay powered. It holds the world together.
## Renegade Glass
The TARDIS-blue glass of the Second Renegade Flight. Purely decorative;
some say it hums near Doors.
```lang
{
"item.scicraft.photon_core": "Photon Core",
"item.scicraft.photon_fragment": "Photon Fragment",
"item.scicraft.void_stabilizer": "Void Stabilizer",
"block.scicraft.quantum_lattice": "Quantum Lattice",
"block.scicraft.renegade_glass": "Renegade Glass",
"tooltip.scicraft.photon_core.1": "Dark photons — the binding force of the Door.",
"tooltip.scicraft.photon_core.2": "A sliver of the fifth force the Flight harnessed.",
"tooltip.scicraft.photon_core.3": "Hold it and feel the seals.",
"tooltip.scicraft.photon_fragment.1": "A splinter of light stolen from the collapse.",
"tooltip.scicraft.photon_fragment.2": "Recovered from the Darker's remains.",
"tooltip.scicraft.photon_fragment.3": "Three of these may be pressed into a Core.",
"tooltip.scicraft.void_stabilizer.1": "Per Spatium — the renegades' seal for the wound in the world.",
"tooltip.scicraft.void_stabilizer.2": "Right-click a powered Quantum Lattice to re-seal a Door.",
"tooltip.scicraft.void_stabilizer.3": "It will never break. The work will.",
"tooltip.scicraft.quantum_lattice.1": "The Protocol's emitter. It must stay powered.",
"tooltip.scicraft.quantum_lattice.2": "Feed it steel, circuits, and Photon Cores.",
"tooltip.scicraft.quantum_lattice.3": "Right-click with a Void Stabilizer to push back the tide.",
"tooltip.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"tooltip.scicraft.renegade_glass.2": "Decorative. Some say it hums near Doors.",
"jei.scicraft.photon_fragment.1": "The Darker carry these.",
"jei.scicraft.photon_fragment.2": "Slay Wardens, Mutant Monsters, or Born in Chaos mobs to recover them.",
"jei.scicraft.photon_fragment.3": "You can also extract one from an Echo Shard and Glowstone Dust.",
"jei.scicraft.photon_core.1": "Compress three Photon Fragments in a Create Press,",
"jei.scicraft.photon_core.2": "or smelt an Ender Pearl in the heart of the wound.",
"jei.scicraft.void_stabilizer.1": "The seal of the Flight. Crafted from Photon Cores and an Ender Eye.",
"jei.scicraft.void_stabilizer.2": "Use it on a powered Quantum Lattice to re-seal a Door and lower the Corruption Tide.",
"jei.scicraft.quantum_lattice.1": "The emitter of the Dark Photon Protocol.",
"jei.scicraft.quantum_lattice.2": "Powered by steel, circuits, and Photon Cores, it holds the world together.",
"jei.scicraft.quantum_lattice.3": "Right-click it with a Void Stabilizer to push back the global Corruption Tide.",
"jei.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"jei.scicraft.renegade_glass.2": "Decorative. Crafted around a Photon Fragment."
}
```

33
STORY/03-dimensions.md Normal file
View file

@ -0,0 +1,33 @@
# Dimensions
The geography of the story. Prose lives here; the actual dimension IDs are
verified in `00-index.md` — do not invent new ones.
## The Overworld — the Ark
Where the Protocol must be rebuilt. The Lattice belongs here; doors leak
here. Corruption rises here faster than anywhere.
## Limbo (Dimensional Doors)
The scar-tissue of the Flight's prison — the space *between* the doors.
Entering a Door is entering the memory of the collapse. The first test of
the renegade's nerve.
## The Wound (Void Dimension)
The raw leak of the collapsing star-empire. Physically hostile: entropy
drains the life of anyone inside. The Void Stabilizer is the only tool that
can begin closing it.
## The Othersides (Deeper & Darker)
What is *answering from inside* the prison. The Darker press against the
world here. Carries the worst ambient dread in the pack — and the richest
harvest of Photon Fragments.
## The Stars (Stellaris)
The Flight scattered its data across the worlds of this system. The moon,
Mars, Venus, Mercury — each holds a piece of the Protocol's history and its
own quiet dread. *Per Spatium.*

37
STORY/04-phases.md Normal file
View file

@ -0,0 +1,37 @@
# The Phase Tree
The advancement tree is the player's story spine. Titles and descriptions
are player-facing — write them like lore, not like tech specs. The tree is
non-terminal: the Protocol is maintained, not completed.
Phases in order: `root``first_signal``the_core``the_seal`
`the_lattice``the_legacy``through_the_doors` → (`the_wound`,
`the_answer`, `per_spatium`).
> To add a node: copy `kubejs/data/scicraft/advancements/protocol/the_core.json`,
> change `parent`, rename the file, and add its title/description keys below.
```lang
{
"advancements.scicraft.protocol.root.title": "The Dark Photon Protocol",
"advancements.scicraft.protocol.root.description": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice.",
"advancements.scicraft.protocol.first_signal.title": "The Signal",
"advancements.scicraft.protocol.first_signal.description": "Recover your first Photon Fragment from a creature of the Dark.",
"advancements.scicraft.protocol.the_core.title": "The Core",
"advancements.scicraft.protocol.the_core.description": "Press three Fragments into a Photon Core.",
"advancements.scicraft.protocol.the_seal.title": "The Seal",
"advancements.scicraft.protocol.the_seal.description": "Craft the Void Stabilizer — the renegades' tool for closing wounds.",
"advancements.scicraft.protocol.the_lattice.title": "The Lattice",
"advancements.scicraft.protocol.the_lattice.description": "Assemble the Quantum Lattice — the Protocol's emitter — and keep it powered.",
"advancements.scicraft.protocol.the_legacy.title": "The Legacy",
"advancements.scicraft.protocol.the_legacy.description": "Craft Renegade Glass — rebuild what the Flight left behind.",
"advancements.scicraft.protocol.through_the_doors.title": "Through the Doors",
"advancements.scicraft.protocol.through_the_doors.description": "Enter a Dimensional Door. The scar-tissue of the Flight's prison.",
"advancements.scicraft.protocol.the_wound.title": "The Wound",
"advancements.scicraft.protocol.the_wound.description": "Descend into the Void Dimension — the raw leak of the collapsing empire.",
"advancements.scicraft.protocol.the_answer.title": "The Answer",
"advancements.scicraft.protocol.the_answer.description": "Reach the Othersides of the Deeper and Darker — what answers from inside the prison.",
"advancements.scicraft.protocol.per_spatium.title": "Per Spatium",
"advancements.scicraft.protocol.per_spatium.description": "Launch a rocket. The Flight's data was scattered across the stars."
}
```

22
STORY/05-dialogue.md Normal file
View file

@ -0,0 +1,22 @@
# Dialogue & Player Messages
Every message the player can see. These keys are referenced from scripts via
`Text.translate('scicraft.phrases.<name>')`.
- **signal** — broadcast once on login; the first vision.
- **lattice_hum** — spoken when a Door is re-sealed at the Lattice.
- **tide_low** — the calm phase of the Corruption Tide.
- **tide_mid** — the world is waking; darkness begins.
- **tide_high** — the Darker press against the world.
- **seal_fail** — reserved for when the Lattice can't close a door.
```lang
{
"scicraft.phrases.signal": "The last signal of the Second Renegade Flight hums in your blood.",
"scicraft.phrases.lattice_hum": "The Lattice hums. Reality holds — for now.",
"scicraft.phrases.tide_low": "The seal holds. The tide is calm.",
"scicraft.phrases.tide_mid": "A Door stirs somewhere. The dark is waking.",
"scicraft.phrases.tide_high": "The Darker press against the world. The Protocol calls.",
"scicraft.phrases.seal_fail": "The Lattice sputters. It needs more power — and a Stabilizer."
}
```

25
STORY/06-loot.md Normal file
View file

@ -0,0 +1,25 @@
# Loot & Drops
Who carries Photon Fragments, and why. Implemented in
`kubejs/server_scripts/04_loot.js` (LootJS) — the prose here explains the
*motivation*, the script holds the counts.
## The Warden
A creature of the Deep Dark, now answering the signal. It carries the most
fragments of the overworld's horrors — the Protocol's first real harvest.
## Mutant Monsters
The corrupted remnants of the Flight's containment. Mutant Zombie and
Mutant Skeleton carry fragments; Mutant Enderman, the most corrupted, drops
the richest haul.
## Born in Chaos
The Darker's forward scouts. Dark Vortex and Dread Hound carry a single
fragment each — the first taste of the Dark. Nightmare Stalker, which hunts
silently, carries more.
> The very first fragment should always drop — the player is never locked
> out of the story by bad luck.

18
STORY/07-todo.md Normal file
View file

@ -0,0 +1,18 @@
# Future Story Beats
Drop these in whenever. Beats get promoted to a numbered file once they're
implemented; until then they live here as design.
- [ ] **Door network** — a set of Doors that opens/closes on a schedule, each
carrying its own phrase in `05-dialogue.md` (add `scicraft.phrases.<name>`
keys as they land).
- [ ] **Star fragments** — Stellaris planets each recover a named fragment
("Mars shard", "Venus shard") → new advancement nodes in `04-phases.md`.
- [ ] **Lattice upkeep** — it slowly *consumes* Photon Cores while powered;
running dry raises the tide (ties the tide to real infrastructure).
- [ ] **The Legacy tier** — Renegade Glass builds that hum: block interactions
that whisper one `scicraft.phrases.*` line.
- [ ] **FTB Quests questbook** mirroring the advancement phases in `04-phases.md`.
- [ ] **Tide warning gating** — currently `tide_*` messages broadcast every
200 ticks to all players; gate them to *phase changes* only to avoid
spam. See `kubejs/server_scripts/01_corruption_tide.js`.

View file

@ -1,114 +0,0 @@
# STORY CANON — SCICRAFT: The Dark Photon Protocol
**This is the single source of truth for the pack's story.**
All lore text lives here or is referenced from here. Editing the story means
editing this file (or the files it points to) — nothing else.
---
## The canon, in one page
1. **Dark photons are real.** A fifth force the Second Renegade Flight
harnessed. They are the *binding force of the Door* — the pressure that
keeps a collapsed star-empire from unravelling back into reality.
2. **You are a proto-Time-Lord.** Born with the resonance, never finished
training. The signal chose you because only a renegade could read the
Protocol the mortals can't.
3. **The wound.** The Flight sealed the empire inside a Dimensional Door.
The seal is failing. The Void Dimension is the raw wound; the Doors are
scar-tissue; the Deeper and Darker is what's *answering from inside*.
4. **The job.** Rebuild the **Quantum Lattice** — the Protocol's emitter —
and keep it online. The Protocol is never finished; it is maintained.
5. **The tide.** Corruption rises while Doors go unsealed (global, shared by
all players). Re-seal Doors at the Lattice to push it back. No fail state —
just a world that gets darker while you procrastinate.
6. **The Doctor connection is atmospheric only.** TARDIS-blue glass
("Renegade Glass"), the phrase *Per Spatium*, portal styling. Present but
never plot-driving; players who don't care can ignore it entirely.
---
## Where the story lives (file map)
| What you want to change | Where | Reload |
|---|---|---|
| Global story strings, tide tuning, dimension IDs | `kubejs/server_scripts/00_lore.js` | `/reload` |
| Item/block names + advancement titles/descriptions | `kubejs/assets/scicraft/lang/en_us.json` | resource reload |
| Player messages (tide warnings, signals) | `00_lore.js``scicraft.phrases.*` + `en_us.json` | `/reload` |
| Item tooltips (hover lore) | `kubejs/client_scripts/01_tooltips.js` | `F3+T` |
| JEI info pages | `kubejs/client_scripts/02_jei_info.js` | `F3+T` |
| Crafting chain / gating recipes | `kubejs/server_scripts/03_recipes_tags.js` | `/reload` |
| Corruption tide logic | `kubejs/server_scripts/01_corruption_tide.js` | `/reload` |
| Player powers / void hazards | `kubejs/server_scripts/02_events.js` | `/reload` |
| Boss → Photon Fragment drops | `kubejs/server_scripts/04_loot.js` (LootJS) | `/reload` |
| Advancement phase tree | `kubejs/data/scicraft/advancements/protocol/*.json` | `/reload` |
| Advancement reward loot | `kubejs/data/scicraft/loot_tables/protocol/*.json` | `/reload` |
| Item & block definitions (ID, texture, stats) | `kubejs/startup_scripts/registry_blocks.js` | **restart** |
| Textures | `kubejs/assets/scicraft/textures/{item,block}/*.png` | `F3+T` |
> **Golden rule:** `00_lore.js` is the bible. If you add a new story beat,
> put its strings there first, then reference `SC.<path>` from the other
> scripts. Never hardcode lore text in a script body.
---
## Adding a new story beat (5-minute workflow)
1. **Edit `00_lore.js`** — add your phrase to `phrases`, or your item to
`items`.
2. **Add the lang key** to `en_us.json` (same key you used in `Text.translate`).
3. **If it's a new item/block**: add to `registry_blocks.js` + run
`tools/gen_textures.py` for a placeholder texture. This step needs a
**full restart**.
4. **Add a tooltip / JEI page** if it's a carried item.
5. **Wire the beat into the tide** (if it's an event) or into a recipe
(if it's a gated item) or into an advancement JSON (if it's a goal).
6. **Sync to both packs:**
```bash
rm -rf client_pack/kubejs && cp -r server_pack/kubejs client_pack/kubejs
```
7. Reload: `/reload` (server scripts/advancements/recipes) or `F3+T`
(client assets/tooltips). Startup item changes require a game restart.
---
## Adding a new advancement node
Copy `data/scicraft/advancements/protocol/the_core.json` and change:
- `"parent"` — the node before it
- `"title"`/`"description"` — lore text (also add the matching
`advancements.scicraft.protocol.<name>.title/.description` keys to `en_us.json`)
- `"criteria"` — the trigger (inventory_changed / changed_dimension / tick)
Rename the file `<your_node>.json`. The tree is non-terminal: the Protocol
is maintained, not completed.
---
## Verified IDs (do not guess these — they were checked against the jars)
| Thing | Correct ID |
|---|---|
| Limbo (Dimensional Doors) | `dimensionaldoors:limbo` |
| The Wound (Void Dimension) | `thevoiddimension:overworld` |
| The Othersides (Deeper & Darker) | `deeperdarker:otherside` |
| Stellaris moon | `stellaris:moon` (mars/venus/mercury likewise) |
| Warden | `minecraft:warden` |
| Mutant Zombie / Skeleton / Enderman | `mutantmonsters:mutant_zombie` / `mutant_skeleton` / `mutant_enderman` |
| Born in Chaos Dark Vortex / Dread Hound / Nightmare Stalker | `born_in_chaos_v1:dark_vortex` / `dread_hound` / `nightmare_stalker` |
When in doubt, verify against the installed jar before writing an ID into a script.
---
## TODO — future story beats (drop in whenever)
- [ ] New Doors: a "Door network" that opens/closes on a schedule, each
carrying its own phrase in `00_lore.js`.
- [ ] Star fragments: Stellaris planets each recover a named fragment
("Mars shard", "Venus shard") → new advancement nodes.
- [ ] Lattice upkeep: it slowly *consumes* Photon Cores while powered;
running dry raises the tide (ties tide to real infrastructure).
- [ ] Final "The Legacy" tier of Renegade Glass builds that hum — block
interactions that whisper one `scicraft.phrases.*` line.
- [ ] FTB Quests questbook mirroring the advancement phases.

View file

@ -4,6 +4,32 @@
"item.scicraft.void_stabilizer": "Void Stabilizer", "item.scicraft.void_stabilizer": "Void Stabilizer",
"block.scicraft.quantum_lattice": "Quantum Lattice", "block.scicraft.quantum_lattice": "Quantum Lattice",
"block.scicraft.renegade_glass": "Renegade Glass", "block.scicraft.renegade_glass": "Renegade Glass",
"tooltip.scicraft.photon_core.1": "Dark photons — the binding force of the Door.",
"tooltip.scicraft.photon_core.2": "A sliver of the fifth force the Flight harnessed.",
"tooltip.scicraft.photon_core.3": "Hold it and feel the seals.",
"tooltip.scicraft.photon_fragment.1": "A splinter of light stolen from the collapse.",
"tooltip.scicraft.photon_fragment.2": "Recovered from the Darker's remains.",
"tooltip.scicraft.photon_fragment.3": "Three of these may be pressed into a Core.",
"tooltip.scicraft.void_stabilizer.1": "Per Spatium — the renegades' seal for the wound in the world.",
"tooltip.scicraft.void_stabilizer.2": "Right-click a powered Quantum Lattice to re-seal a Door.",
"tooltip.scicraft.void_stabilizer.3": "It will never break. The work will.",
"tooltip.scicraft.quantum_lattice.1": "The Protocol's emitter. It must stay powered.",
"tooltip.scicraft.quantum_lattice.2": "Feed it steel, circuits, and Photon Cores.",
"tooltip.scicraft.quantum_lattice.3": "Right-click with a Void Stabilizer to push back the tide.",
"tooltip.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"tooltip.scicraft.renegade_glass.2": "Decorative. Some say it hums near Doors.",
"jei.scicraft.photon_fragment.1": "The Darker carry these.",
"jei.scicraft.photon_fragment.2": "Slay Wardens, Mutant Monsters, or Born in Chaos mobs to recover them.",
"jei.scicraft.photon_fragment.3": "You can also extract one from an Echo Shard and Glowstone Dust.",
"jei.scicraft.photon_core.1": "Compress three Photon Fragments in a Create Press,",
"jei.scicraft.photon_core.2": "or smelt an Ender Pearl in the heart of the wound.",
"jei.scicraft.void_stabilizer.1": "The seal of the Flight. Crafted from Photon Cores and an Ender Eye.",
"jei.scicraft.void_stabilizer.2": "Use it on a powered Quantum Lattice to re-seal a Door and lower the Corruption Tide.",
"jei.scicraft.quantum_lattice.1": "The emitter of the Dark Photon Protocol.",
"jei.scicraft.quantum_lattice.2": "Powered by steel, circuits, and Photon Cores, it holds the world together.",
"jei.scicraft.quantum_lattice.3": "Right-click it with a Void Stabilizer to push back the global Corruption Tide.",
"jei.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"jei.scicraft.renegade_glass.2": "Decorative. Crafted around a Photon Fragment.",
"advancements.scicraft.protocol.root.title": "The Dark Photon Protocol", "advancements.scicraft.protocol.root.title": "The Dark Photon Protocol",
"advancements.scicraft.protocol.root.description": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice.", "advancements.scicraft.protocol.root.description": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice.",
"advancements.scicraft.protocol.first_signal.title": "The Signal", "advancements.scicraft.protocol.first_signal.title": "The Signal",
@ -28,5 +54,6 @@
"scicraft.phrases.lattice_hum": "The Lattice hums. Reality holds — for now.", "scicraft.phrases.lattice_hum": "The Lattice hums. Reality holds — for now.",
"scicraft.phrases.tide_low": "The seal holds. The tide is calm.", "scicraft.phrases.tide_low": "The seal holds. The tide is calm.",
"scicraft.phrases.tide_mid": "A Door stirs somewhere. The dark is waking.", "scicraft.phrases.tide_mid": "A Door stirs somewhere. The dark is waking.",
"scicraft.phrases.tide_high": "The Darker press against the world. The Protocol calls." "scicraft.phrases.tide_high": "The Darker press against the world. The Protocol calls.",
} "scicraft.phrases.seal_fail": "The Lattice sputters. It needs more power — and a Stabilizer."
}

View file

@ -1,34 +1,35 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// Client tooltips: the story rides on the items you carry. // Client tooltips: the story rides on the items you carry.
// Text lives in STORY/02-items.md (tooltip.scicraft.* keys) — never hardcode.
ItemEvents.tooltip(event => { ItemEvents.tooltip(event => {
event.add('scicraft:photon_core', [ event.add('scicraft:photon_core', [
'', '',
'§3Dark photons — the binding force of the Door.', Text.translate('tooltip.scicraft.photon_core.1'),
'§7A sliver of the fifth force the Flight harnessed.', Text.translate('tooltip.scicraft.photon_core.2'),
'§8Hold it and feel the seals.' Text.translate('tooltip.scicraft.photon_core.3')
]) ])
event.add('scicraft:photon_fragment', [ event.add('scicraft:photon_fragment', [
'', '',
'§3A splinter of light stolen from the collapse.', Text.translate('tooltip.scicraft.photon_fragment.1'),
'§7Recovered from the Darker\'s remains.', Text.translate('tooltip.scicraft.photon_fragment.2'),
'§8Three of these may be pressed into a Core.' Text.translate('tooltip.scicraft.photon_fragment.3')
]) ])
event.add('scicraft:void_stabilizer', [ event.add('scicraft:void_stabilizer', [
'', '',
'§3Per Spatium — the renegades\' seal for the wound in the world.', Text.translate('tooltip.scicraft.void_stabilizer.1'),
'§7Right-click a powered Quantum Lattice to re-seal a Door.', Text.translate('tooltip.scicraft.void_stabilizer.2'),
'§8It will never break. The work will.' Text.translate('tooltip.scicraft.void_stabilizer.3')
]) ])
event.add('scicraft:quantum_lattice', [ event.add('scicraft:quantum_lattice', [
'', '',
'§3The Protocol\'s emitter. It must stay powered.', Text.translate('tooltip.scicraft.quantum_lattice.1'),
'§7Feed it steel, circuits, and Photon Cores.', Text.translate('tooltip.scicraft.quantum_lattice.2'),
'§8Right-click with a Void Stabilizer to push back the tide.' Text.translate('tooltip.scicraft.quantum_lattice.3')
]) ])
event.add('scicraft:renegade_glass', [ event.add('scicraft:renegade_glass', [
'', '',
'§3The TARDIS-blue glass of the Second Renegade Flight.', Text.translate('tooltip.scicraft.renegade_glass.1'),
'§7Decorative. Some say it hums near Doors.' Text.translate('tooltip.scicraft.renegade_glass.2')
]) ])
}) })

View file

@ -1,27 +1,28 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// JEI info pages: where the story is and where to get the pieces. // JEI info pages: where the story is and where to get the pieces.
// Text lives in STORY/02-items.md (jei.scicraft.* keys) — never hardcode.
JEIEvents.information(event => { JEIEvents.information(event => {
event.addItem('scicraft:photon_fragment', [ event.addItem('scicraft:photon_fragment', [
'The Darker carry these.', Text.translate('jei.scicraft.photon_fragment.1'),
'Slay Wardens, Mutant Monsters, or Born in Chaos mobs to recover them.', Text.translate('jei.scicraft.photon_fragment.2'),
'You can also extract one from an Echo Shard and Glowstone Dust.' Text.translate('jei.scicraft.photon_fragment.3')
]) ])
event.addItem('scicraft:photon_core', [ event.addItem('scicraft:photon_core', [
'Compress three Photon Fragments in a Create Press,', Text.translate('jei.scicraft.photon_core.1'),
'or smelt an Ender Pearl in the heart of the wound.' Text.translate('jei.scicraft.photon_core.2')
]) ])
event.addItem('scicraft:void_stabilizer', [ event.addItem('scicraft:void_stabilizer', [
'The seal of the Flight. Crafted from Photon Cores and an Ender Eye.', Text.translate('jei.scicraft.void_stabilizer.1'),
'Use it on a powered Quantum Lattice to re-seal a Door and lower the Corruption Tide.' Text.translate('jei.scicraft.void_stabilizer.2')
]) ])
event.addItem('scicraft:quantum_lattice', [ event.addItem('scicraft:quantum_lattice', [
'The emitter of the Dark Photon Protocol.', Text.translate('jei.scicraft.quantum_lattice.1'),
'Powered by steel, circuits, and Photon Cores, it holds the world together.', Text.translate('jei.scicraft.quantum_lattice.2'),
'Right-click it with a Void Stabilizer to push back the global Corruption Tide.' Text.translate('jei.scicraft.quantum_lattice.3')
]) ])
event.addItem('scicraft:renegade_glass', [ event.addItem('scicraft:renegade_glass', [
'The TARDIS-blue glass of the Second Renegade Flight.', Text.translate('jei.scicraft.renegade_glass.1'),
'Decorative. Crafted around a Photon Fragment.' Text.translate('jei.scicraft.renegade_glass.2')
]) ])
}) })

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/root", "parent": "scicraft:protocol/root",
"display": { "display": {
"icon": { "item": "scicraft:photon_fragment" }, "icon": {
"title": { "text": "The Signal" }, "item": "scicraft:photon_fragment"
"description": { "text": "Recover your first Photon Fragment from a creature of the Dark." }, },
"title": {
"translate": "advancements.scicraft.protocol.first_signal.title"
},
"description": {
"translate": "advancements.scicraft.protocol.first_signal.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_fragment": { "has_fragment": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:photon_fragment"] }] "items": [
{
"items": [
"scicraft:photon_fragment"
]
}
]
} }
} }
}, },
"requirements": [["has_fragment"]], "requirements": [
"rewards": { "experience": 100 } [
} "has_fragment"
]
],
"rewards": {
"experience": 100
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "stellaris:rocket" }, "icon": {
"title": { "text": "Per Spatium" }, "item": "stellaris:rocket"
"description": { "text": "Launch a rocket. The Flight's data was scattered across the stars." }, },
"title": {
"translate": "advancements.scicraft.protocol.per_spatium.title"
},
"description": {
"translate": "advancements.scicraft.protocol.per_spatium.description"
},
"frame": "goal", "frame": "goal",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"launch_rocket": { "launch_rocket": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "stellaris:moon" } "conditions": {
"to": "stellaris:moon"
}
} }
}, },
"requirements": [["launch_rocket"]], "requirements": [
"rewards": { "experience": 600 } [
} "launch_rocket"
]
],
"rewards": {
"experience": 600
}
}

View file

@ -1,8 +1,14 @@
{ {
"display": { "display": {
"icon": { "item": "scicraft:photon_core" }, "icon": {
"title": { "text": "The Dark Photon Protocol" }, "item": "scicraft:photon_core"
"description": { "text": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice." }, },
"title": {
"translate": "advancements.scicraft.protocol.root.title"
},
"description": {
"translate": "advancements.scicraft.protocol.root.description"
},
"background": "minecraft:textures/block/blackstone.png", "background": "minecraft:textures/block/blackstone.png",
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
@ -15,6 +21,14 @@
"conditions": {} "conditions": {}
} }
}, },
"requirements": [["first_signal"]], "requirements": [
"rewards": { "loot": ["scicraft:protocol/root_reward"] } [
} "first_signal"
]
],
"rewards": {
"loot": [
"scicraft:protocol/root_reward"
]
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "minecraft:sculk_sensor" }, "icon": {
"title": { "text": "The Answer" }, "item": "minecraft:sculk_sensor"
"description": { "text": "Reach the Othersides of the Deeper and Darker — what answers from inside the prison." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_answer.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_answer.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_darker": { "enter_darker": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "deeperdarker:otherside" } "conditions": {
"to": "deeperdarker:otherside"
}
} }
}, },
"requirements": [["enter_darker"]], "requirements": [
"rewards": { "experience": 750 } [
} "enter_darker"
]
],
"rewards": {
"experience": 750
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/first_signal", "parent": "scicraft:protocol/first_signal",
"display": { "display": {
"icon": { "item": "scicraft:photon_core" }, "icon": {
"title": { "text": "The Core" }, "item": "scicraft:photon_core"
"description": { "text": "Press three Fragments into a Photon Core." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_core.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_core.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_core": { "has_core": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:photon_core"] }] "items": [
{
"items": [
"scicraft:photon_core"
]
}
]
} }
} }
}, },
"requirements": [["has_core"]], "requirements": [
"rewards": { "experience": 250 } [
} "has_core"
]
],
"rewards": {
"experience": 250
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_seal", "parent": "scicraft:protocol/the_seal",
"display": { "display": {
"icon": { "item": "scicraft:quantum_lattice" }, "icon": {
"title": { "text": "The Lattice" }, "item": "scicraft:quantum_lattice"
"description": { "text": "Assemble the Quantum Lattice — the Protocol's emitter — and keep it powered." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_lattice.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_lattice.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_lattice": { "has_lattice": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:quantum_lattice"] }] "items": [
{
"items": [
"scicraft:quantum_lattice"
]
}
]
} }
} }
}, },
"requirements": [["has_lattice"]], "requirements": [
"rewards": { "experience": 1000 } [
} "has_lattice"
]
],
"rewards": {
"experience": 1000
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "scicraft:renegade_glass" }, "icon": {
"title": { "text": "The Legacy" }, "item": "scicraft:renegade_glass"
"description": { "text": "Craft Renegade Glass — rebuild what the Flight left behind." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_legacy.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_legacy.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_glass": { "has_glass": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:renegade_glass"] }] "items": [
{
"items": [
"scicraft:renegade_glass"
]
}
]
} }
} }
}, },
"requirements": [["has_glass"]], "requirements": [
"rewards": { "experience": 300 } [
} "has_glass"
]
],
"rewards": {
"experience": 300
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_core", "parent": "scicraft:protocol/the_core",
"display": { "display": {
"icon": { "item": "scicraft:void_stabilizer" }, "icon": {
"title": { "text": "The Seal" }, "item": "scicraft:void_stabilizer"
"description": { "text": "Craft the Void Stabilizer — the renegades' tool for closing wounds." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_seal.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_seal.description"
},
"frame": "goal", "frame": "goal",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_stabilizer": { "has_stabilizer": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:void_stabilizer"] }] "items": [
{
"items": [
"scicraft:void_stabilizer"
]
}
]
} }
} }
}, },
"requirements": [["has_stabilizer"]], "requirements": [
"rewards": { "experience": 500 } [
} "has_stabilizer"
]
],
"rewards": {
"experience": 500
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "minecraft:respawn_anchor" }, "icon": {
"title": { "text": "The Wound" }, "item": "minecraft:respawn_anchor"
"description": { "text": "Descend into the Void Dimension — the raw leak of the collapsing empire." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_wound.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_wound.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_void": { "enter_void": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "thevoiddimension:overworld" } "conditions": {
"to": "thevoiddimension:overworld"
}
} }
}, },
"requirements": [["enter_void"]], "requirements": [
"rewards": { "experience": 750 } [
} "enter_void"
]
],
"rewards": {
"experience": 750
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_seal", "parent": "scicraft:protocol/the_seal",
"display": { "display": {
"icon": { "item": "minecraft:ender_eye" }, "icon": {
"title": { "text": "Through the Doors" }, "item": "minecraft:ender_eye"
"description": { "text": "Enter a Dimensional Door. The scar-tissue of the Flight's prison." }, },
"title": {
"translate": "advancements.scicraft.protocol.through_the_doors.title"
},
"description": {
"translate": "advancements.scicraft.protocol.through_the_doors.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_doors": { "enter_doors": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "dimensionaldoors:limbo" } "conditions": {
"to": "dimensionaldoors:limbo"
}
} }
}, },
"requirements": [["enter_doors"]], "requirements": [
"rewards": { "experience": 400 } [
} "enter_doors"
]
],
"rewards": {
"experience": 400
}
}

View file

@ -1,6 +1,6 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// THE STORY BIBLE. Edit lore here; every script reads from this object. // CONFIG OBJECT. Text lives in STORY/*.md (generated into en_us.json) —
// Reload with /reload after editing (startup items require a restart). // never hardcode story strings here. /reload after editing.
global.SCICRAFT = { global.SCICRAFT = {
items: { items: {
@ -29,14 +29,5 @@ global.SCICRAFT = {
void_dim: 'thevoiddimension:overworld', void_dim: 'thevoiddimension:overworld',
darker_dim: 'deeperdarker:otherside', darker_dim: 'deeperdarker:otherside',
dimensional_doors: 'dimensionaldoors:limbo' dimensional_doors: 'dimensionaldoors:limbo'
},
phrases: {
signal: 'The last signal of the Second Renegade Flight hums in your blood.',
lattice_hum: 'The Lattice hums. Reality holds — for now.',
tide_low: 'The seal holds. The tide is calm.',
tide_mid: 'A Door stirs somewhere. The dark is waking.',
tide_high: 'The Darker press against the world. The Protocol calls.',
seal_fail: 'The Lattice sputters. It needs more power — and a Stabilizer.'
} }
} }

View file

@ -35,11 +35,5 @@ PlayerEvents.tick(event => {
PlayerEvents.loggedIn(event => { PlayerEvents.loggedIn(event => {
event.player.tell(Text.translate('scicraft.phrases.signal')) event.player.tell(Text.translate('scicraft.phrases.signal'))
}) })
// Note: Warden fragment drops are handled in 04_loot.js (LootJS) — do not
// The very first fragment always drops when a Darker falls — never lost. // duplicate them here or players get double drops.
EntityEvents.death(event => {
const ent = event.entity
if (ent.type === 'minecraft:warden') {
ent.level.spawnItem('scicraft:photon_fragment', ent.blockPosition(), { count: 2 })
}
})

View file

@ -1,5 +1,6 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// Custom items & blocks for the Protocol. // Custom items & blocks for the Protocol.
// Names + tooltips come from the lang file (STORY/*.md → en_us.json).
// Startup scripts: requires a full restart to apply. // Startup scripts: requires a full restart to apply.
const SC = global.SCICRAFT const SC = global.SCICRAFT
@ -7,38 +8,31 @@ const SC = global.SCICRAFT
StartupEvents.registry('item', event => { StartupEvents.registry('item', event => {
// Photon Core — the raw fifth-force crystal. Lattice fuel. // Photon Core — the raw fifth-force crystal. Lattice fuel.
event.create('scicraft:photon_core') event.create('scicraft:photon_core')
.displayName('Photon Core')
.texture('scicraft:item/photon_core') .texture('scicraft:item/photon_core')
.maxStackSize(64) .maxStackSize(64)
.tag('scicraft:photon') .tag('scicraft:photon')
.tag('c:gems') .tag('c:gems')
.glow(true) .glow(true)
.tooltip('Dark photons — the binding force of the Door.')
// Photon Fragment — shattered cores recovered from the Darker. // Photon Fragment — shattered cores recovered from the Darker.
event.create('scicraft:photon_fragment') event.create('scicraft:photon_fragment')
.displayName('Photon Fragment')
.texture('scicraft:item/photon_fragment') .texture('scicraft:item/photon_fragment')
.maxStackSize(64) .maxStackSize(64)
.tag('scicraft:photon') .tag('scicraft:photon')
.tag('c:gems') .tag('c:gems')
.glow(true) .glow(true)
.tooltip('A splinter of light stolen from the collapse.')
// Void Stabilizer — the tool that re-seals Doors at the Lattice. // Void Stabilizer — the tool that re-seals Doors at the Lattice.
event.create('scicraft:void_stabilizer') event.create('scicraft:void_stabilizer')
.displayName('Void Stabilizer')
.texture('scicraft:item/void_stabilizer') .texture('scicraft:item/void_stabilizer')
.maxStackSize(1) .maxStackSize(1)
.unbreakable() .unbreakable()
.tag('scicraft:stabilizer') .tag('scicraft:stabilizer')
.tooltip('Per Spatium — the renegades\' seal for the wound in the world.')
}) })
StartupEvents.registry('block', event => { StartupEvents.registry('block', event => {
// Quantum Lattice — the Protocol's emitter. Must stay powered. // Quantum Lattice — the Protocol's emitter. Must stay powered.
event.create('scicraft:quantum_lattice', 'basic') event.create('scicraft:quantum_lattice', 'basic')
.displayName('Quantum Lattice')
.textureAll('scicraft:block/quantum_lattice') .textureAll('scicraft:block/quantum_lattice')
.hardness(5.0) .hardness(5.0)
.resistance(1200.0) .resistance(1200.0)
@ -49,7 +43,6 @@ StartupEvents.registry('block', event => {
// Renegade Glass — the TARDIS-blue glass of the Flight. Purely decorative. // Renegade Glass — the TARDIS-blue glass of the Flight. Purely decorative.
event.create('scicraft:renegade_glass', 'glass') event.create('scicraft:renegade_glass', 'glass')
.displayName('Renegade Glass')
.textureAll('scicraft:block/renegade_glass') .textureAll('scicraft:block/renegade_glass')
.hardness(0.3) .hardness(0.3)
.resistance(0.3) .resistance(0.3)

35
docs/00-index.md Normal file
View file

@ -0,0 +1,35 @@
# Docs Index — SCICRAFT: The Dark Photon Protocol
**NeoForge 1.21.1 (21.1.248) · packwiz v1.1.0 · version 1.0.0**
This folder holds every operational guide. Story/canon content lives in
`STORY/` (see `STORY/00-index.md`); repo overview lives in `README.md`.
## Guides
| File | What it covers |
|------|----------------|
| `setup.md` | Install & update (server + client), adding/removing mods |
| `server.md` | Server properties, JVM flags, operations, troubleshooting |
| `performance.md` | Shader tuning (4GB VRAM preset) and client perf notes |
| `mods.md` | Mod feature hotspots, pack layout, client-only list |
## Quick links
- **Story**`STORY/00-index.md`
- **Repo overview**`README.md`
- **Tools**`tools/` (`gen_story.py`, `sync_kubejs.sh`, `gen_textures.py`)
## The two packs
| Path | Contents |
|------|----------|
| `./server_pack/` | Server-only modpack (135 mod files). No shaders, no client render mods. |
| `./client_pack/` | Full client pack (144 mod files). Adds Iris + Sodium (native NeoForge), Cull Leaves, LambDynamicLights, Dynamic FPS, 3D Skin Layers, Visuality, flywheel compat. |
Keep them in sync after any change:
```bash
bash tools/sync_kubejs.sh # kubejs/ → client_pack
packwiz refresh --dir server_pack && packwiz refresh --dir client_pack
```

27
docs/mods.md Normal file
View file

@ -0,0 +1,27 @@
# Mods — Hotspots & Pack Layout
## Mod Feature Hotspots (Quick Orientation)
| Domain | Mods | Notes |
|--------|------|-------|
| Power | Mekanism (turbine/boiler), Flux Networks | Flux wireless transfer; Mekanism cables for bulk |
| Storage | AE2, Sophisticated Storage, Functional Storage, Sophisticated Backpacks | AE2 for autocraft; Sophisticated for bulk; Functional for drawers |
| Logistics | LaserIO, Modular Routers, Entangled, FastPipes, Create belts | FastPipes adds vanilla pipe QoL |
| Automation | Create + Steam 'n' Rails + Rechiseled + FastPipes | Flywheel + Iris compat bundled |
| Tech Building | Building Gadgets, Hologenica, FramedBlocks, Chipped, Supplementaries | |
| Dimensions | Per Spatium/Stellaris, Dimensional Doors, Void Dimension, Deeper and Darker | Stellaris portal → rockets; Doors are the endgame hook |
| Mobs/Combat | Born in Chaos, Mutant Monsters, Nyf's Spiders, Better Combat, Simply Swords | Hard difficulty |
| UI/QoL | JEI, Jade (+Addons), JourneyMap, Waystones, AppleSkin, IPN, Clumps, Mouse Tweaks | JEI is the recipe source (no EMI) |
| Scripting | KubeJS (+Create, +Mekanism), LootJS, Blocks You Need | Advancements & loot live here |
| Server utils | FTB Chunks/Quests/Teams/Library | Chunk claims + questbook |
## Key client-only mods (server must NOT have these)
`iris`, `sodium`, `iris-flw-compat`, `cull-leaves`, `lambdynamiclights`,
`dynamic-fps`, `3dskinlayers`, `visuality-forge`, `midnightlib`.
## Bridge layer (both packs)
Sinytra Connector + Forgified Fabric API run a small set of Fabric mods
(Immersive Portals, LambDynamicLights, Waystones-compat). Do not remove
either; the pack will not boot without them.

25
docs/performance.md Normal file
View file

@ -0,0 +1,25 @@
# Performance — Client
## Shader Tuning for 4GB VRAM
Shader loader is **Iris** (native NeoForge). Recommended shaderpack:
**Complementary Reimagined r5.4** (`client_pack/shaderpacks/`, see README).
Preset for 4GB VRAM:
- Preset: **Fast / Performance**
- Render Distance: **8** (server view-distance)
- Antialiasing: **OFF**
- SSAO: **Fast**, Shadow Quality **1.0x** (0.5x if <30 FPS)
- Shadow Distance: **64**
- Bloom: **OFF/Low**, Clouds: **2D Fast**
- Water Reflections: **Screenspace Fast**
- Colored Light / Block Light: **OFF**
If still under 60 FPS: reduce Shadow Quality to 0.5x, then disable Bloom,
before touching render distance.
## Reload rules
- Server scripts / recipes / advancements: `/reload`
- Client tooltips / JEI / textures / lang: `F3+T`
- New items/blocks (`registry_blocks.js`): **full restart**

71
docs/server.md Normal file
View file

@ -0,0 +1,71 @@
# Server — Properties, JVM, Operations
## Server properties (view-distance=8, simulation-distance=6)
`server_pack/server.properties` — set these values:
```properties
view-distance=8
simulation-distance=6
max-players=8
motd=SCICRAFT - The Dark Photon Protocol
difficulty=hard
spawn-protection=0
network-compression-threshold=256
enable-command-block=true
online-mode=true
```
`server_pack/eula.txt``eula=true` (after review).
## Recommended JVM Flags (server)
```bash
java -Xms4G -Xmx8G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1HeapWastePercent=5 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-Dlog4j2.formatMsgNoLookups=true \
-jar neoforge-21.1.248-server.jar nogui
```
Notes:
- G1 tuning keeps large-tech-server TPS stable under chunk gen (Krypton
Reno + BadOptimizations help server-side).
- `-Xms4G` avoids early GC churn. Cap at 8G; this pack is RAM-hungry
from AE2/Mekanism tick load but does not need 16G.
## Server start order
1. `packwiz install --dir server_pack` (first time / after changes)
2. Accept EULA.
3. Launch with the JVM flags above.
## Common failures
| Symptom | Fix |
|---------|-----|
| "Mismatched mods" on client join | Run `packwiz refresh` both packs, redeploy. |
| Sinytra connector errors | Update Sinytra Connector + Forgified Fabric API together. |
| Iris black screen | Disable flywheel compat first, then test without shaders. |
| Crash on world gen (Deeper and Darker) | Ensure CF 659011 + its lithostitched data load; update both. |
| TPS lag from many AE2 cells | Check FTB chunk claims; lower `simulation-distance`. |
| Immersive Portals won't load | Must be the Fabric jar added via `url add --force` (Modrinth blocks loader mismatch). |
## Backups
- World: copy `server_pack/world/` (or use FTB Chunks backups).
- Configs: `server_pack/config/` mirrors client defaults; keep both in sync
when changing KubeJS scripts or FTB settings.

61
docs/setup.md Normal file
View file

@ -0,0 +1,61 @@
# Setup — Install & Update
## Prereqs
- Java 21 (Adoptium Temurin 21 LTS recommended)
- ~12 GB RAM free for client, 8 GB minimum for server
- Disk: keep under **100 GB** total for world + packs
## First-time server setup
```bash
# from this repo root
packwiz install --dir server_pack # downloads all mods into server_pack/
java -Xms2G -Xmx6G -jar server_pack/neoforge-21.1.248-installer.jar --installServer
# accept EULA, then launch:
java -Xms2G -Xmx6G -XX:+UseG1GC -jar server_pack/neoforge-21.1.248-server.jar nogui
```
## First-time client setup
```bash
git clone git@git.mithraic.cloud:ad3laid3/SciCraft.git
cd SciCraft
packwiz install --dir client_pack
```
Add `client_pack` as a **packwiz** modpack in your launcher
(Prism/ATLauncher/PolyMC) or use `packwiz serve` from `client_pack` and
install via the Modrinth/packwiz installers. Drop a shaderpack into
`client_pack/shaderpacks/` — see the README there for the 4 GB VRAM preset.
> **Multiplayer:** players join with the **client pack**; the server runs
> the **server pack**. Never put client-only mods on the server (see
> `mods.md`).
## Adding a mod (both packs)
```bash
packwiz --dir server_pack curseforge add --addon-id <CF_ID> -y
packwiz --dir client_pack curseforge add --addon-id <CF_ID> -y
packwiz --dir server_pack modrinth add <MR_SLUG_OR_ID> -y
packwiz --dir client_pack modrinth add <MR_SLUG_OR_ID> -y
packwiz --dir server_pack refresh
packwiz --dir client_pack refresh
```
- Always add to **both** packs unless the mod is client- or server-only.
- For Fabric mods that must run through Sinytra, use
`packwiz url add "<Name>" "<URL>" --force` and verify the Sinytra
connector tolerates the version.
## Editing story text
```bash
# edit STORY/*.md first, then:
python tools/gen_story.py # regenerates en_us.json in BOTH packs
bash tools/sync_kubejs.sh # mirrors server_pack/kubejs → client_pack/kubejs
```
Never hand-edit `en_us.json` — it is generated. Full workflow:
`STORY/00-index.md`.

View file

@ -4,6 +4,32 @@
"item.scicraft.void_stabilizer": "Void Stabilizer", "item.scicraft.void_stabilizer": "Void Stabilizer",
"block.scicraft.quantum_lattice": "Quantum Lattice", "block.scicraft.quantum_lattice": "Quantum Lattice",
"block.scicraft.renegade_glass": "Renegade Glass", "block.scicraft.renegade_glass": "Renegade Glass",
"tooltip.scicraft.photon_core.1": "Dark photons — the binding force of the Door.",
"tooltip.scicraft.photon_core.2": "A sliver of the fifth force the Flight harnessed.",
"tooltip.scicraft.photon_core.3": "Hold it and feel the seals.",
"tooltip.scicraft.photon_fragment.1": "A splinter of light stolen from the collapse.",
"tooltip.scicraft.photon_fragment.2": "Recovered from the Darker's remains.",
"tooltip.scicraft.photon_fragment.3": "Three of these may be pressed into a Core.",
"tooltip.scicraft.void_stabilizer.1": "Per Spatium — the renegades' seal for the wound in the world.",
"tooltip.scicraft.void_stabilizer.2": "Right-click a powered Quantum Lattice to re-seal a Door.",
"tooltip.scicraft.void_stabilizer.3": "It will never break. The work will.",
"tooltip.scicraft.quantum_lattice.1": "The Protocol's emitter. It must stay powered.",
"tooltip.scicraft.quantum_lattice.2": "Feed it steel, circuits, and Photon Cores.",
"tooltip.scicraft.quantum_lattice.3": "Right-click with a Void Stabilizer to push back the tide.",
"tooltip.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"tooltip.scicraft.renegade_glass.2": "Decorative. Some say it hums near Doors.",
"jei.scicraft.photon_fragment.1": "The Darker carry these.",
"jei.scicraft.photon_fragment.2": "Slay Wardens, Mutant Monsters, or Born in Chaos mobs to recover them.",
"jei.scicraft.photon_fragment.3": "You can also extract one from an Echo Shard and Glowstone Dust.",
"jei.scicraft.photon_core.1": "Compress three Photon Fragments in a Create Press,",
"jei.scicraft.photon_core.2": "or smelt an Ender Pearl in the heart of the wound.",
"jei.scicraft.void_stabilizer.1": "The seal of the Flight. Crafted from Photon Cores and an Ender Eye.",
"jei.scicraft.void_stabilizer.2": "Use it on a powered Quantum Lattice to re-seal a Door and lower the Corruption Tide.",
"jei.scicraft.quantum_lattice.1": "The emitter of the Dark Photon Protocol.",
"jei.scicraft.quantum_lattice.2": "Powered by steel, circuits, and Photon Cores, it holds the world together.",
"jei.scicraft.quantum_lattice.3": "Right-click it with a Void Stabilizer to push back the global Corruption Tide.",
"jei.scicraft.renegade_glass.1": "The TARDIS-blue glass of the Second Renegade Flight.",
"jei.scicraft.renegade_glass.2": "Decorative. Crafted around a Photon Fragment.",
"advancements.scicraft.protocol.root.title": "The Dark Photon Protocol", "advancements.scicraft.protocol.root.title": "The Dark Photon Protocol",
"advancements.scicraft.protocol.root.description": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice.", "advancements.scicraft.protocol.root.description": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice.",
"advancements.scicraft.protocol.first_signal.title": "The Signal", "advancements.scicraft.protocol.first_signal.title": "The Signal",
@ -28,5 +54,6 @@
"scicraft.phrases.lattice_hum": "The Lattice hums. Reality holds — for now.", "scicraft.phrases.lattice_hum": "The Lattice hums. Reality holds — for now.",
"scicraft.phrases.tide_low": "The seal holds. The tide is calm.", "scicraft.phrases.tide_low": "The seal holds. The tide is calm.",
"scicraft.phrases.tide_mid": "A Door stirs somewhere. The dark is waking.", "scicraft.phrases.tide_mid": "A Door stirs somewhere. The dark is waking.",
"scicraft.phrases.tide_high": "The Darker press against the world. The Protocol calls." "scicraft.phrases.tide_high": "The Darker press against the world. The Protocol calls.",
} "scicraft.phrases.seal_fail": "The Lattice sputters. It needs more power — and a Stabilizer."
}

View file

@ -1,34 +1,35 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// Client tooltips: the story rides on the items you carry. // Client tooltips: the story rides on the items you carry.
// Text lives in STORY/02-items.md (tooltip.scicraft.* keys) — never hardcode.
ItemEvents.tooltip(event => { ItemEvents.tooltip(event => {
event.add('scicraft:photon_core', [ event.add('scicraft:photon_core', [
'', '',
'§3Dark photons — the binding force of the Door.', Text.translate('tooltip.scicraft.photon_core.1'),
'§7A sliver of the fifth force the Flight harnessed.', Text.translate('tooltip.scicraft.photon_core.2'),
'§8Hold it and feel the seals.' Text.translate('tooltip.scicraft.photon_core.3')
]) ])
event.add('scicraft:photon_fragment', [ event.add('scicraft:photon_fragment', [
'', '',
'§3A splinter of light stolen from the collapse.', Text.translate('tooltip.scicraft.photon_fragment.1'),
'§7Recovered from the Darker\'s remains.', Text.translate('tooltip.scicraft.photon_fragment.2'),
'§8Three of these may be pressed into a Core.' Text.translate('tooltip.scicraft.photon_fragment.3')
]) ])
event.add('scicraft:void_stabilizer', [ event.add('scicraft:void_stabilizer', [
'', '',
'§3Per Spatium — the renegades\' seal for the wound in the world.', Text.translate('tooltip.scicraft.void_stabilizer.1'),
'§7Right-click a powered Quantum Lattice to re-seal a Door.', Text.translate('tooltip.scicraft.void_stabilizer.2'),
'§8It will never break. The work will.' Text.translate('tooltip.scicraft.void_stabilizer.3')
]) ])
event.add('scicraft:quantum_lattice', [ event.add('scicraft:quantum_lattice', [
'', '',
'§3The Protocol\'s emitter. It must stay powered.', Text.translate('tooltip.scicraft.quantum_lattice.1'),
'§7Feed it steel, circuits, and Photon Cores.', Text.translate('tooltip.scicraft.quantum_lattice.2'),
'§8Right-click with a Void Stabilizer to push back the tide.' Text.translate('tooltip.scicraft.quantum_lattice.3')
]) ])
event.add('scicraft:renegade_glass', [ event.add('scicraft:renegade_glass', [
'', '',
'§3The TARDIS-blue glass of the Second Renegade Flight.', Text.translate('tooltip.scicraft.renegade_glass.1'),
'§7Decorative. Some say it hums near Doors.' Text.translate('tooltip.scicraft.renegade_glass.2')
]) ])
}) })

View file

@ -1,27 +1,28 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// JEI info pages: where the story is and where to get the pieces. // JEI info pages: where the story is and where to get the pieces.
// Text lives in STORY/02-items.md (jei.scicraft.* keys) — never hardcode.
JEIEvents.information(event => { JEIEvents.information(event => {
event.addItem('scicraft:photon_fragment', [ event.addItem('scicraft:photon_fragment', [
'The Darker carry these.', Text.translate('jei.scicraft.photon_fragment.1'),
'Slay Wardens, Mutant Monsters, or Born in Chaos mobs to recover them.', Text.translate('jei.scicraft.photon_fragment.2'),
'You can also extract one from an Echo Shard and Glowstone Dust.' Text.translate('jei.scicraft.photon_fragment.3')
]) ])
event.addItem('scicraft:photon_core', [ event.addItem('scicraft:photon_core', [
'Compress three Photon Fragments in a Create Press,', Text.translate('jei.scicraft.photon_core.1'),
'or smelt an Ender Pearl in the heart of the wound.' Text.translate('jei.scicraft.photon_core.2')
]) ])
event.addItem('scicraft:void_stabilizer', [ event.addItem('scicraft:void_stabilizer', [
'The seal of the Flight. Crafted from Photon Cores and an Ender Eye.', Text.translate('jei.scicraft.void_stabilizer.1'),
'Use it on a powered Quantum Lattice to re-seal a Door and lower the Corruption Tide.' Text.translate('jei.scicraft.void_stabilizer.2')
]) ])
event.addItem('scicraft:quantum_lattice', [ event.addItem('scicraft:quantum_lattice', [
'The emitter of the Dark Photon Protocol.', Text.translate('jei.scicraft.quantum_lattice.1'),
'Powered by steel, circuits, and Photon Cores, it holds the world together.', Text.translate('jei.scicraft.quantum_lattice.2'),
'Right-click it with a Void Stabilizer to push back the global Corruption Tide.' Text.translate('jei.scicraft.quantum_lattice.3')
]) ])
event.addItem('scicraft:renegade_glass', [ event.addItem('scicraft:renegade_glass', [
'The TARDIS-blue glass of the Second Renegade Flight.', Text.translate('jei.scicraft.renegade_glass.1'),
'Decorative. Crafted around a Photon Fragment.' Text.translate('jei.scicraft.renegade_glass.2')
]) ])
}) })

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/root", "parent": "scicraft:protocol/root",
"display": { "display": {
"icon": { "item": "scicraft:photon_fragment" }, "icon": {
"title": { "text": "The Signal" }, "item": "scicraft:photon_fragment"
"description": { "text": "Recover your first Photon Fragment from a creature of the Dark." }, },
"title": {
"translate": "advancements.scicraft.protocol.first_signal.title"
},
"description": {
"translate": "advancements.scicraft.protocol.first_signal.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_fragment": { "has_fragment": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:photon_fragment"] }] "items": [
{
"items": [
"scicraft:photon_fragment"
]
}
]
} }
} }
}, },
"requirements": [["has_fragment"]], "requirements": [
"rewards": { "experience": 100 } [
} "has_fragment"
]
],
"rewards": {
"experience": 100
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "stellaris:rocket" }, "icon": {
"title": { "text": "Per Spatium" }, "item": "stellaris:rocket"
"description": { "text": "Launch a rocket. The Flight's data was scattered across the stars." }, },
"title": {
"translate": "advancements.scicraft.protocol.per_spatium.title"
},
"description": {
"translate": "advancements.scicraft.protocol.per_spatium.description"
},
"frame": "goal", "frame": "goal",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"launch_rocket": { "launch_rocket": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "stellaris:moon" } "conditions": {
"to": "stellaris:moon"
}
} }
}, },
"requirements": [["launch_rocket"]], "requirements": [
"rewards": { "experience": 600 } [
} "launch_rocket"
]
],
"rewards": {
"experience": 600
}
}

View file

@ -1,8 +1,14 @@
{ {
"display": { "display": {
"icon": { "item": "scicraft:photon_core" }, "icon": {
"title": { "text": "The Dark Photon Protocol" }, "item": "scicraft:photon_core"
"description": { "text": "The last signal of the Second Renegade Flight has found you. Rebuild the Lattice." }, },
"title": {
"translate": "advancements.scicraft.protocol.root.title"
},
"description": {
"translate": "advancements.scicraft.protocol.root.description"
},
"background": "minecraft:textures/block/blackstone.png", "background": "minecraft:textures/block/blackstone.png",
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
@ -15,6 +21,14 @@
"conditions": {} "conditions": {}
} }
}, },
"requirements": [["first_signal"]], "requirements": [
"rewards": { "loot": ["scicraft:protocol/root_reward"] } [
} "first_signal"
]
],
"rewards": {
"loot": [
"scicraft:protocol/root_reward"
]
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "minecraft:sculk_sensor" }, "icon": {
"title": { "text": "The Answer" }, "item": "minecraft:sculk_sensor"
"description": { "text": "Reach the Othersides of the Deeper and Darker — what answers from inside the prison." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_answer.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_answer.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_darker": { "enter_darker": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "deeperdarker:otherside" } "conditions": {
"to": "deeperdarker:otherside"
}
} }
}, },
"requirements": [["enter_darker"]], "requirements": [
"rewards": { "experience": 750 } [
} "enter_darker"
]
],
"rewards": {
"experience": 750
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/first_signal", "parent": "scicraft:protocol/first_signal",
"display": { "display": {
"icon": { "item": "scicraft:photon_core" }, "icon": {
"title": { "text": "The Core" }, "item": "scicraft:photon_core"
"description": { "text": "Press three Fragments into a Photon Core." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_core.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_core.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_core": { "has_core": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:photon_core"] }] "items": [
{
"items": [
"scicraft:photon_core"
]
}
]
} }
} }
}, },
"requirements": [["has_core"]], "requirements": [
"rewards": { "experience": 250 } [
} "has_core"
]
],
"rewards": {
"experience": 250
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_seal", "parent": "scicraft:protocol/the_seal",
"display": { "display": {
"icon": { "item": "scicraft:quantum_lattice" }, "icon": {
"title": { "text": "The Lattice" }, "item": "scicraft:quantum_lattice"
"description": { "text": "Assemble the Quantum Lattice — the Protocol's emitter — and keep it powered." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_lattice.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_lattice.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_lattice": { "has_lattice": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:quantum_lattice"] }] "items": [
{
"items": [
"scicraft:quantum_lattice"
]
}
]
} }
} }
}, },
"requirements": [["has_lattice"]], "requirements": [
"rewards": { "experience": 1000 } [
} "has_lattice"
]
],
"rewards": {
"experience": 1000
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "scicraft:renegade_glass" }, "icon": {
"title": { "text": "The Legacy" }, "item": "scicraft:renegade_glass"
"description": { "text": "Craft Renegade Glass — rebuild what the Flight left behind." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_legacy.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_legacy.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_glass": { "has_glass": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:renegade_glass"] }] "items": [
{
"items": [
"scicraft:renegade_glass"
]
}
]
} }
} }
}, },
"requirements": [["has_glass"]], "requirements": [
"rewards": { "experience": 300 } [
} "has_glass"
]
],
"rewards": {
"experience": 300
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_core", "parent": "scicraft:protocol/the_core",
"display": { "display": {
"icon": { "item": "scicraft:void_stabilizer" }, "icon": {
"title": { "text": "The Seal" }, "item": "scicraft:void_stabilizer"
"description": { "text": "Craft the Void Stabilizer — the renegades' tool for closing wounds." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_seal.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_seal.description"
},
"frame": "goal", "frame": "goal",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -13,10 +19,22 @@
"has_stabilizer": { "has_stabilizer": {
"trigger": "minecraft:inventory_changed", "trigger": "minecraft:inventory_changed",
"conditions": { "conditions": {
"items": [{ "items": ["scicraft:void_stabilizer"] }] "items": [
{
"items": [
"scicraft:void_stabilizer"
]
}
]
} }
} }
}, },
"requirements": [["has_stabilizer"]], "requirements": [
"rewards": { "experience": 500 } [
} "has_stabilizer"
]
],
"rewards": {
"experience": 500
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_lattice", "parent": "scicraft:protocol/the_lattice",
"display": { "display": {
"icon": { "item": "minecraft:respawn_anchor" }, "icon": {
"title": { "text": "The Wound" }, "item": "minecraft:respawn_anchor"
"description": { "text": "Descend into the Void Dimension — the raw leak of the collapsing empire." }, },
"title": {
"translate": "advancements.scicraft.protocol.the_wound.title"
},
"description": {
"translate": "advancements.scicraft.protocol.the_wound.description"
},
"frame": "challenge", "frame": "challenge",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_void": { "enter_void": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "thevoiddimension:overworld" } "conditions": {
"to": "thevoiddimension:overworld"
}
} }
}, },
"requirements": [["enter_void"]], "requirements": [
"rewards": { "experience": 750 } [
} "enter_void"
]
],
"rewards": {
"experience": 750
}
}

View file

@ -1,9 +1,15 @@
{ {
"parent": "scicraft:protocol/the_seal", "parent": "scicraft:protocol/the_seal",
"display": { "display": {
"icon": { "item": "minecraft:ender_eye" }, "icon": {
"title": { "text": "Through the Doors" }, "item": "minecraft:ender_eye"
"description": { "text": "Enter a Dimensional Door. The scar-tissue of the Flight's prison." }, },
"title": {
"translate": "advancements.scicraft.protocol.through_the_doors.title"
},
"description": {
"translate": "advancements.scicraft.protocol.through_the_doors.description"
},
"frame": "task", "frame": "task",
"show_toast": true, "show_toast": true,
"announce_to_chat": true, "announce_to_chat": true,
@ -12,9 +18,17 @@
"criteria": { "criteria": {
"enter_doors": { "enter_doors": {
"trigger": "minecraft:changed_dimension", "trigger": "minecraft:changed_dimension",
"conditions": { "to": "dimensionaldoors:limbo" } "conditions": {
"to": "dimensionaldoors:limbo"
}
} }
}, },
"requirements": [["enter_doors"]], "requirements": [
"rewards": { "experience": 400 } [
} "enter_doors"
]
],
"rewards": {
"experience": 400
}
}

View file

@ -1,6 +1,6 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// THE STORY BIBLE. Edit lore here; every script reads from this object. // CONFIG OBJECT. Text lives in STORY/*.md (generated into en_us.json) —
// Reload with /reload after editing (startup items require a restart). // never hardcode story strings here. /reload after editing.
global.SCICRAFT = { global.SCICRAFT = {
items: { items: {
@ -29,14 +29,5 @@ global.SCICRAFT = {
void_dim: 'thevoiddimension:overworld', void_dim: 'thevoiddimension:overworld',
darker_dim: 'deeperdarker:otherside', darker_dim: 'deeperdarker:otherside',
dimensional_doors: 'dimensionaldoors:limbo' dimensional_doors: 'dimensionaldoors:limbo'
},
phrases: {
signal: 'The last signal of the Second Renegade Flight hums in your blood.',
lattice_hum: 'The Lattice hums. Reality holds — for now.',
tide_low: 'The seal holds. The tide is calm.',
tide_mid: 'A Door stirs somewhere. The dark is waking.',
tide_high: 'The Darker press against the world. The Protocol calls.',
seal_fail: 'The Lattice sputters. It needs more power — and a Stabilizer.'
} }
} }

View file

@ -35,11 +35,5 @@ PlayerEvents.tick(event => {
PlayerEvents.loggedIn(event => { PlayerEvents.loggedIn(event => {
event.player.tell(Text.translate('scicraft.phrases.signal')) event.player.tell(Text.translate('scicraft.phrases.signal'))
}) })
// Note: Warden fragment drops are handled in 04_loot.js (LootJS) — do not
// The very first fragment always drops when a Darker falls — never lost. // duplicate them here or players get double drops.
EntityEvents.death(event => {
const ent = event.entity
if (ent.type === 'minecraft:warden') {
ent.level.spawnItem('scicraft:photon_fragment', ent.blockPosition(), { count: 2 })
}
})

View file

@ -1,5 +1,6 @@
// SCICRAFT — The Dark Photon Protocol // SCICRAFT — The Dark Photon Protocol
// Custom items & blocks for the Protocol. // Custom items & blocks for the Protocol.
// Names + tooltips come from the lang file (STORY/*.md → en_us.json).
// Startup scripts: requires a full restart to apply. // Startup scripts: requires a full restart to apply.
const SC = global.SCICRAFT const SC = global.SCICRAFT
@ -7,38 +8,31 @@ const SC = global.SCICRAFT
StartupEvents.registry('item', event => { StartupEvents.registry('item', event => {
// Photon Core — the raw fifth-force crystal. Lattice fuel. // Photon Core — the raw fifth-force crystal. Lattice fuel.
event.create('scicraft:photon_core') event.create('scicraft:photon_core')
.displayName('Photon Core')
.texture('scicraft:item/photon_core') .texture('scicraft:item/photon_core')
.maxStackSize(64) .maxStackSize(64)
.tag('scicraft:photon') .tag('scicraft:photon')
.tag('c:gems') .tag('c:gems')
.glow(true) .glow(true)
.tooltip('Dark photons — the binding force of the Door.')
// Photon Fragment — shattered cores recovered from the Darker. // Photon Fragment — shattered cores recovered from the Darker.
event.create('scicraft:photon_fragment') event.create('scicraft:photon_fragment')
.displayName('Photon Fragment')
.texture('scicraft:item/photon_fragment') .texture('scicraft:item/photon_fragment')
.maxStackSize(64) .maxStackSize(64)
.tag('scicraft:photon') .tag('scicraft:photon')
.tag('c:gems') .tag('c:gems')
.glow(true) .glow(true)
.tooltip('A splinter of light stolen from the collapse.')
// Void Stabilizer — the tool that re-seals Doors at the Lattice. // Void Stabilizer — the tool that re-seals Doors at the Lattice.
event.create('scicraft:void_stabilizer') event.create('scicraft:void_stabilizer')
.displayName('Void Stabilizer')
.texture('scicraft:item/void_stabilizer') .texture('scicraft:item/void_stabilizer')
.maxStackSize(1) .maxStackSize(1)
.unbreakable() .unbreakable()
.tag('scicraft:stabilizer') .tag('scicraft:stabilizer')
.tooltip('Per Spatium — the renegades\' seal for the wound in the world.')
}) })
StartupEvents.registry('block', event => { StartupEvents.registry('block', event => {
// Quantum Lattice — the Protocol's emitter. Must stay powered. // Quantum Lattice — the Protocol's emitter. Must stay powered.
event.create('scicraft:quantum_lattice', 'basic') event.create('scicraft:quantum_lattice', 'basic')
.displayName('Quantum Lattice')
.textureAll('scicraft:block/quantum_lattice') .textureAll('scicraft:block/quantum_lattice')
.hardness(5.0) .hardness(5.0)
.resistance(1200.0) .resistance(1200.0)
@ -49,7 +43,6 @@ StartupEvents.registry('block', event => {
// Renegade Glass — the TARDIS-blue glass of the Flight. Purely decorative. // Renegade Glass — the TARDIS-blue glass of the Flight. Purely decorative.
event.create('scicraft:renegade_glass', 'glass') event.create('scicraft:renegade_glass', 'glass')
.displayName('Renegade Glass')
.textureAll('scicraft:block/renegade_glass') .textureAll('scicraft:block/renegade_glass')
.hardness(0.3) .hardness(0.3)
.resistance(0.3) .resistance(0.3)

92
tools/gen_story.py Executable file
View file

@ -0,0 +1,92 @@
#!/usr/bin/env python3
"""SCICRAFT — story generator.
Reads STORY/*.md, merges every ```lang JSON block (in filename order) into
en_us.json, writes it to BOTH packs, and validates that every lang key
referenced from the KubeJS scripts and advancement JSONs resolves.
Usage:
python tools/gen_story.py
Edit the story by editing STORY/*.md, then run this script. Never hand-edit
en_us.json it is a generated artifact.
"""
import json
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
STORY_DIR = ROOT / "STORY"
LANGS = [
ROOT / "server_pack" / "kubejs" / "assets" / "scicraft" / "lang" / "en_us.json",
ROOT / "client_pack" / "kubejs" / "assets" / "scicraft" / "lang" / "en_us.json",
]
KUBEJS_DIRS = [ROOT / "server_pack" / "kubejs"]
ADVANCEMENT_DIR = ROOT / "server_pack" / "kubejs" / "data" / "scicraft" / "advancements"
LANG_BLOCK = re.compile(r"```lang\s*\n(.*?)```", re.S)
def load_lang_files():
merged = {}
order = []
for path in sorted(STORY_DIR.glob("*.md")):
text = path.read_text(encoding="utf-8")
for i, match in enumerate(LANG_BLOCK.finditer(text)):
try:
data = json.loads(match.group(1))
except json.JSONDecodeError as e:
sys.exit(f"BAD JSON in {path.name} block #{i + 1}: {e}")
for key, value in data.items():
if key in merged:
print(f"WARN: duplicate key {key!r} ({path.name} overrides)")
merged[key] = value
order.append(key)
return merged, order
def write_lang(merged, order):
payload = {k: merged[k] for k in order}
for target in LANGS:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(
json.dumps(payload, ensure_ascii=False, indent="\t") + "\n",
encoding="utf-8",
)
print(f"wrote {target.relative_to(ROOT)} ({len(payload)} keys)")
def validate(merged):
missing = set()
def check_key(key, source):
if key not in merged:
missing.add((key, source))
for root_dir in KUBEJS_DIRS:
for script in root_dir.rglob("*.js"):
for key in re.findall(r"Text\.translate\(\s*['\"]([^'\"]+)['\"]\s*(?:\+|\))", script.read_text(encoding="utf-8")):
# Keys followed by ` + msg` are dynamic templates — skip.
if key.endswith("."):
continue
check_key(key, str(script.relative_to(ROOT)))
if ADVANCEMENT_DIR.exists():
for jf in ADVANCEMENT_DIR.rglob("*.json"):
for key in re.findall(r'"translate"\s*:\s*"([^"]+)"', jf.read_text(encoding="utf-8")):
check_key(key, str(jf.relative_to(ROOT)))
if missing:
print("\nMISSING LANG KEYS:")
for key, source in sorted(missing):
print(f" {key} (used in {source})")
sys.exit(1)
print("all referenced lang keys resolve")
if __name__ == "__main__":
merged, order = load_lang_files()
write_lang(merged, order)
validate(merged)

11
tools/sync_kubejs.sh Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# SCICRAFT — sync KubeJS story system from server_pack to client_pack.
# Run after editing anything under server_pack/kubejs (or STORY/*.md → gen_story.py).
set -euo pipefail
cd "$(dirname "$0")/.."
rm -rf client_pack/kubejs
cp -r server_pack/kubejs client_pack/kubejs
echo "kubejs synced to client_pack"
echo "verify: diff -r server_pack/kubejs client_pack/kubejs && echo IDENTICAL"