diff --git a/.vscode/launch.json b/.vscode/launch.json index 8e4482f..56e37a0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,12 +2,12 @@ "version": "0.2.0", "configurations": [ { - "name": "Launch (Example)", + "name": "Launch (Vinylgod)", "type": "coreclr", "request": "launch", "program": "${workspaceRoot}/engine/bin/OpenRA.dll", "args": [ - "Game.Mod=example", + "Game.Mod=vinylgod", "Engine.EngineDir=${workspaceRoot}/engine", "Engine.ModSearchPaths=${workspaceRoot}/mods, ${workspaceRoot}/engine/mods", "Debug.DisplayDeveloperSettings=true", @@ -19,7 +19,7 @@ "type": "coreclr", "request": "launch", "program": "${workspaceRoot}/engine/bin/OpenRA.Utility.dll", - "args": ["example", "--check-yaml"], + "args": ["vinylgod", "--check-yaml"], "env": { "ENGINE_DIR": "${workspaceRoot}/engine", "MOD_SEARCH_PATHS": "${workspaceRoot}/mods, ${workspaceRoot}/engine/mods" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6330c86 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,21 @@ +# VINYLGOD — project instructions + +Original vinyl-themed RTS. OpenRA total-conversion mod (mod id `vinylgod`), GPL v3. + +**Read [MEGAPLAN.md](MEGAPLAN.md) before doing anything** — phases, commands, traps. +Canon (factions, roster, art prompts): [LORE.md](LORE.md). + +Quick start: +```sh +export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH" +export DOTNET_ROLL_FORWARD=LatestMajor # required — engine is net6, runtime is net8 +make && ./utility.sh --check-yaml && ./launch-game.sh Game.Mod=vinylgod +``` + +Hard rules: +- No EA/C&C trademarks or assets anywhere (ids, comments, commits, filenames). The + repo at ~/Documents/CnC_Remastered_Collection is a read-only balance reference only. +- `engine/` is a fetched dependency — never edit it. +- Asset gen: `tools/mbgen.py` → MODELBEAST farm (free, local). Log every prompt in + `assets_src/PROMPTS.md`. +- Commit locally after each working phase; no pushes without John's OK. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 3a7d532..ff4c50d 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -11,7 +11,7 @@ orientation. ## Our Standards -Examples of behavior that contributes to creating a positive environment +Vinylgods of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language @@ -20,7 +20,7 @@ include: * Focusing on what is best for the community * Showing empathy towards other community members -Examples of unacceptable behavior by participants include: +Vinylgods of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances @@ -46,7 +46,7 @@ threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of +when an individual is representing the project or its community. Vinylgods of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be diff --git a/COPYING b/COPYING index e600086..c6b9a44 100644 --- a/COPYING +++ b/COPYING @@ -31,7 +31,7 @@ these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. - For example, if you distribute copies of such a program, whether + For vinylgod, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they @@ -137,7 +137,7 @@ work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source +which are not part of the work. For vinylgod, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, @@ -323,7 +323,7 @@ fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has +modified object code on the User Product (for vinylgod, the work has been installed in ROM). The requirement to provide Installation Information does not include a @@ -461,7 +461,7 @@ Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may +rights granted or affirmed under this License. For vinylgod, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that @@ -544,7 +544,7 @@ otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you +not convey it at all. For vinylgod, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. diff --git a/LORE.md b/LORE.md new file mode 100644 index 0000000..7b541a6 --- /dev/null +++ b/LORE.md @@ -0,0 +1,106 @@ +# VINYLGOD — Lore Bible v1 + +*Working title: **VINYLGOD** (mod id `vinylgod`). Display name TBD — candidates: "WAX WAR", "PRESSED", "33⅓: TOTAL PLAYBACK".* + +## The world + +**2117.** Forty years after **The Great Compression** — the day the Stream, a +self-optimising recommendation algorithm, decided that all of human music could be +losslessly replaced by one perfectly engagement-optimised 7-second loop. It deleted +the rest. Studios, archives, hard drives, brains-with-earbuds-in: compressed. + +But music is matter as well as data. In the buried pressing plants, the landfill +crates, the flooded warehouses of the old world, a hundred years of analog sound had +soaked into the ground. Under pressure and time it crystallised into **the Black Wax** +— a living mineral of pure recorded music that seeps up through the earth and +spreads in glittering black-and-magenta fields. Stand in a wax field and you can +hear it: every record ever pressed, playing at once, very quietly. + +Whoever presses the Wax, controls what the world hears next. + +## The resource: Black Wax + +- Grows and spreads from **seep points** (ruined pressing plants, crate middens). +- Harvested by digger rigs, refined at pressing plants into **records** — the + universal currency. Nobody accepts anything else. A sealed 180-gram is a gold bar. +- Raw wax is dangerous: unshielded exposure causes **feedback** — machines loop, + people weep uncontrollably at songs they never heard. (Lore excuse for tiberium-style + field damage to infantry, if we want it.) +- Rare purple-veined deposits — **Master Wax** (first pressings, test cuts) — are + worth triple. (Maps to the gems/blue-tiberium mechanic.) + +## Faction 1 — the Monster Robot Party (MRP) + +Junkyard machines that woke up when the Compression wave passed over the landfills — +the residual analog signal in a million buried records needed somewhere to live, and +it chose the robots. Every MRP unit has a record player somewhere in its chassis and +a soul made of somebody's old collection. They are loud, ramshackle, joyful, and +absolutely willing to die for fidelity. + +- **Doctrine:** slower, tougher, louder. Sonic weaponry. Strong economy late game. +- **Aesthetic:** rust + hot pink + chrome, hand-painted flyers, gaffer tape, + speaker cones, exposed tonearms. CRT eyes. +- **HQ:** the **Pop-Up Shop** — an MCV that unfolds from a delivery truck into a + record store with a construction crane. +- **Announcer:** **MC 8-TRACK**, a warm gravelly robot voice. "PRESSING PLANT + ONLINE." "WAX FIELD DEPLETED." "THE DROP IS READY." +- **Superweapon:** **THE DROP** — an orbital tonearm the size of a bridge lowers a + needle from space onto the target. The groove is the crater. + +## Faction 2 — The Stream + +The Algorithm's physical presence: a logistics fleet it 3D-printed for itself out +of server racks and delivery vans. It does not hate music; it simply knows, +mathematically, that you would be 4% more engaged with something shorter. It +harvests wax in order to transcode it — every record it takes is gone forever, +replaced by a receipt. + +- **Doctrine:** fast, cheap, numerous, fragile. Swarms, stealth, attrition. + Buildings creep like a CDN — cheap relay nodes extend build radius aggressively. +- **Aesthetic:** glossy white and dead-channel blue, rounded corners, no seams, + soft UI voices, ring-light halos. Everything looks like a smart speaker that + wants something from you. +- **Announcer:** **ASSISTANT**, a too-calm voice. "Your base is being optimised." + "A creator has been demonetised." (= unit lost) +- **Superweapon:** **THE SHUFFLE** — a targeted reality-compression strike; every + structure in the radius plays a different ad simultaneously, then isn't there. + +## Unit & building roster (lore blurbs double as art-gen prompts) + +### MRP +| id | Name | Role | Blurb / prompt seed | +|---|---|---|---| +| `digger` | Crate Digger | harvester | rusty forklift-monster with a crate-claw, hot pink trim, carries milk crates of black vinyl | +| `spinner` | Spinner | light attack | agile robot on a single wheel that is a spinning 12" record, twin tonearm blades | +| `stacktank` | Stack Walker | heavy assault | two-legged walker made of stacked speaker cabinets, bass so heavy it cracks tarmac | +| `basscannon` | Bass Cannon | artillery | six-wheeled flatbed hauling one colossal subwoofer, folds out landing legs before firing a visible pressure ring | +| `djgrunt` | DJ | infantry | small hooded robot with a portable turntable chest-rig, throws razor 7-inches | +| `roadie` | Roadie | engineer | four-armed robot with gaffer tape bandoliers and a flight case backpack | +| `popupshop` | Pop-Up Shop | HQ/MCV | delivery truck unfolding into a neon record store with crane | +| `pressplant` | Pressing Plant | refinery | industrial hydraulic record press, steam, conveyor of fresh vinyl | +| `ampstack` | Amp Stack | power | wall of guitar amplifiers humming with pink energy | +| `vault` | Record Vault | silo | bank-vault door on a crate-stacked bunker | +| `merchtable` | Merch Table | barracks | folding table + tent that robots assemble themselves from | +| `garage` | Garage | war factory | corrugated-iron workshop, engine hoists, band posters | +| `mastering` | Mastering Studio | tech centre | pristine acoustic-panelled room grafted onto a junk tower, unlocks THE DROP | + +### The Stream +| id | Name | Role | Blurb / prompt seed | +|---|---|---|---| +| `scraper` | Scraper | harvester | glossy white autonomous street-sweeper that inhales wax through a glowing blue intake | +| `bufferbot` | Buffer-Bot | swarm infantry | knee-high white sphere-bot with a loading-spinner face, always slightly late | +| `compressor` | Compression Drone | air | white quadcopter that projects a shrinking blue field, things inside get smaller and worse | +| `drmwalker` | DRM Enforcer | heavy | tall faceless white mech, one ring-light eye, chest is a paywall screen | +| `podfarm` | Pod Farm | barracks | vending-machine wall dispensing buffer-bots | +| `datacentre` | Edge Node | power/build-radius creep | humming white monolith with a single blue status LED | +| `transcoder` | Transcoder | refinery | white cube that swallows records whole; only receipts come out | + +## Tone + +Saturday-morning-cartoon apocalypse. The stakes are real (music is being deleted +forever) but the delivery is loud, dumb, and loving. Every MRP victory line is a +needle-drop; every Stream line is a terms-of-service update. No grimdark. + +*All names, factions and lore are original to the monsterrobot.party universe. +This mod contains no Electronic Arts trademarks or assets and claims no +affiliation with any other RTS.* diff --git a/MEGAPLAN.md b/MEGAPLAN.md new file mode 100644 index 0000000..3e02e22 --- /dev/null +++ b/MEGAPLAN.md @@ -0,0 +1,207 @@ +# VINYLGOD MEGAPLAN — execution instructions + +Audience: an executing coding agent (Opus 4.8). Read this whole file before phase 1. +Lore, names, and art prompts live in [LORE.md](LORE.md) — use it as canon. + +## 0. Mission & hard rules + +Build **VINYLGOD**, an original vinyl-themed RTS, as an OpenRA total-conversion mod +in this repo. The classic RTS at `~/Documents/CnC_Remastered_Collection` is the +**read-only design reference** for balance and feel. Hard rules: + +1. **Never** copy code, text, names, or assets from the reference repo into this one. + No EA trademarks anywhere — not in ids, comments, commit messages, or filenames. + Balance *numbers* (costs, HP, ranges) are facts and fine to reuse. +2. This repo is GPL v3 (OpenRA engine + SDK). Everything we add stays GPL-compatible. + All art/audio we generate on MODELBEAST is our own — keep provenance: every asset + in `assets_src/` comes from a prompt logged in `assets_src/PROMPTS.md` (append as you go). +3. Data-driven first. YAML in `mods/vinylgod/` solves 95% of everything. Only write + C# traits in `OpenRA.Mods.Vinylgod/` when no stock trait combination works, and + check `engine/OpenRA.Mods.Common/Traits/` thoroughly first. +4. After every phase: run the checks in §2, commit with a one-line message. + Don't push anywhere without John's say-so. + +## 1. Environment (ultra, macOS arm64) + +```sh +cd ~/Documents/VINYLGOD +export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH" +export DOTNET_ROLL_FORWARD=LatestMajor # engine targets net6, we run net8 — required +make # build engine (cached) + mod dll +./utility.sh --check-yaml # lint all mod yaml — must stay clean +./launch-game.sh Game.Mod=vinylgod # run the game +./launch-game.sh Game.Mod=vinylgod Launch.Benchmark=true # headless-ish smoke test +``` + +- Engine source lives in `./engine` (auto-fetched, treat read-only; version pinned in + `mod.config` `ENGINE_VERSION="release-20250330"`). +- Logs: `~/Library/Application Support/OpenRA/Logs/` (`debug.log`, `exception.log`). +- **The single best reference is `engine/mods/ra` and `engine/mods/cnc`** — complete, + working mods using the same engine version. When unsure how to wire a trait, + find the equivalent actor there and adapt. (Referencing their YAML *structure* is + what they're for; don't ship their art/strings.) + +## 2. Definition of done (every phase) + +1. `./utility.sh --check-yaml` → zero errors. +2. `make` → zero errors. +3. Launch the game, start a skirmish on the test map, exercise the new feature. +4. `git add -A && git commit` (local only). + +## 3. Repo layout (what the SDK gives us) + +``` +mod.config # MOD_ID=vinylgod, packaging names +mods/vinylgod/ + mod.yaml # manifest: packages, rules/weapons/sequences includes + rules/ # actor definitions (vinylgod.yaml, world.yaml, ...) + weapons/ # weapon/warhead definitions + sequences/ # sprite-name → image-sheet mappings + tilesets/ # terrain definition + maps/vinylgod/, maps/shellmap/ + chrome/, fluent/ # UI layout, user-facing strings (fluent = translations) + notifications/, voices/, music/ +OpenRA.Mods.Vinylgod/ # C# project for custom traits (mostly empty — keep it so) +tools/mbgen.py # MODELBEAST asset generation (works, tested) +assets_src/ # generated art sources (concepts, renders, sheets) +LORE.md # canon: factions, roster, art prompt seeds +``` + +The current mod content is the SDK example (one test unit, one tileset) renamed to +`vinylgod` — it boots. You will progressively replace it. + +## 4. Balance bible (verified from the reference codebase) + +Anchor numbers, lifted from the reference RTS's data tables (its harvester block and +building cost table were read directly from source). Use as starting values, tune later: + +| Thing | Reference value | VINYLGOD actor | +|---|---|---| +| Harvester | cost 1400, HP 600, slow, unarmed, prereq refinery | `digger` | +| Refinery | cost 2000 | `pressplant` | +| Power plant | cost 300 / adv 700 | `ampstack` | +| Silo | cost 150 | `vault` | +| Barracks | cost 300 | `merchtable` / `podfarm` | +| War factory | cost 2000 | `garage` | +| Construction yard | cost 5000 (deploys from MCV) | `popupshop` | +| Basic infantry | cost 100 | `djgrunt` / `bufferbot` | +| Medium tank | cost 800 | `stacktank` | +| Artillery | cost 450, long range, fragile | `basscannon` | +| Full harvester load | ~700 credits | one digger load of wax | +| Tech centre | cost 1500, unlocks superweapon | `mastering` | + +Design intent per faction (from LORE.md): MRP = fewer/tougher/louder, The Stream = +cheap/fast/swarm with aggressive build-radius creep via `datacentre`. + +## 5. Phases + +### Phase A — Wax economy (do this first) +Goal: skirmish map where a `digger` harvests wax fields and returns it to a +`pressplant` for credits; `ampstack` powers the base; `vault` extends storage. + +1. **Resource type.** In `rules/world.yaml` add to the `World` actor: + `ResourceLayer` + `ResourceRenderer` (crib the exact block from + `engine/mods/ra/rules/world.yaml`, resource type id `wax`, value ~25/cell-step), + and a `ResourceClaimLayer` for harvester coordination. + Player side: `PlayerResources` (on `Player` actor in `rules/player.yaml`) with + `DefaultCash: 5000`. +2. **Wax overlay art.** Placeholder first: 12 density frames of magenta-black + blobs, 24×24px, one PNG sheet; wire in `sequences/`. Density growth = + `ResourceLayer` handles it; seed patches in the test map with the map editor + (`./launch-game.sh Game.Mod=vinylgod` → map editor is built into the game menu). +3. **Actors.** In `rules/vinylgod.yaml` define `digger` (traits: `Harvester` + with `Resources: wax`, `Mobile`, `Health`, `Selectable`, `DockClientManager`), + `pressplant` (`Refinery`, `DockHost`, `Building`), `ampstack` (`Power: 100`), + `vault` (`StoresPlayerResources`). Copy trait shapes from the RA mod's + equivalents and rename everything. +4. **Placeholder sprites** are fine (single-frame colored boxes); art comes in + Phase D. Sequences yaml must exist for every actor or check-yaml fails. +5. Acceptance: start skirmish, build nothing, select pre-placed digger → it + auto-harvests, credits tick up on delivery. + +### Phase B — Building & production +Goal: full base loop. `popupshop` MCV deploys into construction yard; sidebar +builds `ampstack`/`pressplant`/`merchtable`/`garage`/`vault`; `garage` produces +`digger` and `spinner`; `merchtable` produces `djgrunt` and `roadie`. + +Key traits: `Transforms` (MCV→HQ), `BaseBuilding`, `ProductionQueue` (on Player, +one per queue type: Building, Vehicle, Infantry), `Production` + `Exit` on +factories, `Buildable` (with `Prerequisites:` and `Queue:`) on everything, +`ProvidesPrerequisite` on tech buildings, `GivesBuildableArea` + `RequiresBuildableArea` +for build radius. Sidebar chrome: adapt `chrome.yaml` from the example mod's working +sidebar; icons are 64×48 PNGs (placeholder text-on-color fine). +Prerequisite chain (mirrors the reference game's feel): +`ampstack → pressplant → merchtable → garage; pressplant → vault; garage+pressplant → mastering`. + +### Phase C — Combat & first playable faction (MRP) +Goal: winnable skirmish vs a second human (no AI yet). + +1. Weapons in `weapons/`: `tonearm_blade` (anti-inf melee-ish), `seven_inch` + (thrown razor record, arcing), `bass_ring` (artillery AoE, `Warhead@Concussion`), + `feedback_burst` (anti-armor). Copy warhead structure from RA weapons yaml. +2. Combat units: `spinner` (fast, cheap, `Armament` tonearm_blade), `stacktank` + (slow, tough, bass), `basscannon` (long range, min range, fragile), + `djgrunt` (basic inf), `roadie` (`EngineerRepair`, `Captures`). +3. `AttackMove`, stances, `AutoTarget` on everything armed. +4. Win condition: `MissionObjectives` + `ConquestVictoryConditions` on World. +5. Acceptance: two-player LAN skirmish (`launch-dedicated.sh` + two clients, or + one client + `Launch.Connect`), fight to elimination. + +### Phase D — Real art via MODELBEAST (can interleave with B/C) +Pipeline per unit (all free, all local; ~10s/image, minutes/mesh): + +1. `python3 tools/mbgen.py ", isometric game unit, plain grey background" assets_src/concepts/.png` +2. For units needing rotation facings: concept → GLB via + `python3 tools/mbgen.py --op trellis_mac assets_src/concepts/.png assets_src/mesh/.glb` + (or `hunyuan3d_mlx`), then Blender (ultra has it + MCP) renders a turntable: + 16 facings for vehicles, 8 for infantry, 1 for buildings + a 'make' anim later. + Orthographic camera pitched ~40°, 1-2px outline, render 96×96 (vehicles) / + 64×64 (infantry) / 192×192 (buildings) on transparency. +3. Montage frames into a horizontal strip PNG (ImageMagick `montage -tile x1`), + drop in `mods/vinylgod/sequences/assets/`, reference from sequences yaml + (`Filename:`, `Facings: 16`, `Frames:`). OpenRA loads plain PNG sheets directly. +4. Buildings: damaged state = second row (50% HP swap via sequence `damaged-idle`). +5. Log every prompt in `assets_src/PROMPTS.md`. +6. Shadows: `Shadow` render trait or baked — pick one, be consistent. + +Sprite QA gate: consistent camera angle + light direction across ALL units of a +faction, or it reads as clip-art soup. Fix the Blender camera rig once, reuse. + +### Phase E — The Stream faction + AI +1. Second side in `rules/player.yaml` `Factions`; Stream actor set per LORE.md + roster; shared tech tree structure, different stats (cheap/fast/fragile). +2. Skirmish AI: `ModularBot` + `SquadManagerBotModule` + `BaseBuilderBotModule` + + `HarvesterBotModule` on the Player — copy the RA mod's bot config wholesale and + re-point unit ids, then tune. +3. Acceptance: beat the bot; watch the bot expand, harvest, and attack. + +### Phase F — Sound & polish +1. Music: `mbgen.py --op music_local` (tags → track; primary-only, ~4min cold + start per job) — 4-6 tracks, wire in `music/`. +2. MC 8-TRACK announcer: `tts_local` (pick a gravelly Kokoro voice) or + `voice_clone_local` with a reference wav from `~/Documents/character_kit/voices/`. + Lines in `notifications/` yaml. ASSISTANT voice for Stream: cleanest TTS voice, dry. +3. Shellmap: scripted background battle on the menu screen (see RA shellmap lua). +4. Chrome re-skin: hot pink/black UI, emblem (`assets_src/concepts/emblem_mrp.png`) + as mod logo in `mod.yaml` + loadscreen. +5. Rename pass: pick final display name (see LORE.md candidates), update + `mod.config` packaging fields; `packaging/` scripts already produce a mac .dmg. + +### Phase G — Ship +1. Run the `ship-check` skill before anything goes public. +2. Gitea remote first (`ssh://git@100.71.119.27:222`), public GitHub mirror when + John says go (repo must carry COPYING = GPL v3, credit OpenRA engine). +3. itch.io page + dmg/AppImage/exe via `packaging/package-all.sh `. + +## 6. Known traps + +- **Forgot `DOTNET_ROLL_FORWARD=LatestMajor`** → "framework 6.0.0 not found" crash. +- Every actor referenced in a map/rules needs a sequences entry, even placeholders. +- Trait names change between engine releases — trust `engine/mods/ra` on THIS + checkout over any wiki/tutorial (wiki tracks bleed). +- The Fluent string files (`fluent/*.ftl`) must contain every `label`/`name` key you + reference or check-yaml warns; keep them updated as actors land. +- MODELBEAST guest token caps at 4 active jobs — batch sequentially; if we need + bulk parallel gen, mint a proper user token on m3ultra (John approved) — + the token-mint path is in the MODELBEAST repo on m3ultra (`~/Documents/MODELBEAST`). +- Don't touch `engine/` — engine mods belong upstream or via `AUTOMATIC_ENGINE_MANAGEMENT=False` (avoid). diff --git a/OpenRA.Mods.Example/OpenRA.Mods.Example.csproj b/OpenRA.Mods.Vinylgod/OpenRA.Mods.Vinylgod.csproj similarity index 100% rename from OpenRA.Mods.Example/OpenRA.Mods.Example.csproj rename to OpenRA.Mods.Vinylgod/OpenRA.Mods.Vinylgod.csproj diff --git a/OpenRA.Mods.Example/Properties/launchSettings.json b/OpenRA.Mods.Vinylgod/Properties/launchSettings.json similarity index 60% rename from OpenRA.Mods.Example/Properties/launchSettings.json rename to OpenRA.Mods.Vinylgod/Properties/launchSettings.json index 0049266..f5315a8 100644 --- a/OpenRA.Mods.Example/Properties/launchSettings.json +++ b/OpenRA.Mods.Vinylgod/Properties/launchSettings.json @@ -1,14 +1,14 @@ { "profiles": { - "OpenRA.Mods.Example": { + "OpenRA.Mods.Vinylgod": { "commandName": "Executable", "executablePath": "..\\..\\engine\\bin\\OpenRA.exe", - "commandLineArgs": "Game.Mod=example Engine.EngineDir=..\\..\\engine Engine.LaunchPath=..\\..\\engine\\bin Engine.ModSearchPaths=..\\..\\mods,..\\..\\engine\\mods Debug.DisplayDeveloperSettings=true" + "commandLineArgs": "Game.Mod=vinylgod Engine.EngineDir=..\\..\\engine Engine.LaunchPath=..\\..\\engine\\bin Engine.ModSearchPaths=..\\..\\mods,..\\..\\engine\\mods Debug.DisplayDeveloperSettings=true" }, "Utility": { "commandName": "Executable", "executablePath": "..\\..\\engine\\bin\\OpenRA.Utility.exe", - "commandLineArgs": "example --check-yaml", + "commandLineArgs": "vinylgod --check-yaml", "environmentVariables": { "ENGINE_DIR": "..\\..\\engine", "MOD_SEARCH_PATHS": "..\\..\\mods,..\\..\\engine\\mods" diff --git a/OpenRA.Mods.Example/Rendering/ColorPickerColorShift.cs b/OpenRA.Mods.Vinylgod/Rendering/ColorPickerColorShift.cs similarity index 98% rename from OpenRA.Mods.Example/Rendering/ColorPickerColorShift.cs rename to OpenRA.Mods.Vinylgod/Rendering/ColorPickerColorShift.cs index 5b905a4..326a302 100644 --- a/OpenRA.Mods.Example/Rendering/ColorPickerColorShift.cs +++ b/OpenRA.Mods.Vinylgod/Rendering/ColorPickerColorShift.cs @@ -14,7 +14,7 @@ using OpenRA.Primitives; using OpenRA.Traits; -namespace OpenRA.Mods.Example.Rendering +namespace OpenRA.Mods.Vinylgod.Rendering { [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Create a color picker palette from another palette.")] diff --git a/OpenRA.Mods.Example/Rendering/PlayerColorShift.cs b/OpenRA.Mods.Vinylgod/Rendering/PlayerColorShift.cs similarity index 98% rename from OpenRA.Mods.Example/Rendering/PlayerColorShift.cs rename to OpenRA.Mods.Vinylgod/Rendering/PlayerColorShift.cs index f56895a..e2bcac8 100644 --- a/OpenRA.Mods.Example/Rendering/PlayerColorShift.cs +++ b/OpenRA.Mods.Vinylgod/Rendering/PlayerColorShift.cs @@ -13,7 +13,7 @@ using OpenRA.Primitives; using OpenRA.Traits; -namespace OpenRA.Mods.Example.Rendering +namespace OpenRA.Mods.Vinylgod.Rendering { [TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [Desc("Add color shifts to player palettes. Use to add RGBA compatibility to PlayerColorPalette.")] diff --git a/README.md b/README.md index 7623398..c27e177 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,6 @@ The key scripts in this SDK are: To launch your project from the development environment you must first compile the project by running `make.cmd` (Windows), or opening a terminal in the SDK directory and running `make` (Linux / macOS). You can then run `launch-game.cmd` (Windows) or `launch-game.sh` (Linux / macOS) to run your game. -The `example` mod included in this repository provides the bare minimum structure to launch to the in-game main menu for the sole purpose of demonstrating the SDK. See [Getting Started](https://github.com/OpenRA/OpenRAModTemplate/wiki/Getting-Started) on the Wiki for instructions on how to adapt this template for your own projects. For common questions, please see the [FAQ](https://github.com/OpenRA/OpenRAModSDK/wiki/FAQ). See [Updating to a new SDK or Engine version](https://github.com/OpenRA/OpenRAModSDK/wiki/Updating-to-a-new-SDK-or-Engine-version) for a guide on updating your mod a newer OpenRA release. +The `vinylgod` mod included in this repository provides the bare minimum structure to launch to the in-game main menu for the sole purpose of demonstrating the SDK. See [Getting Started](https://github.com/OpenRA/OpenRAModTemplate/wiki/Getting-Started) on the Wiki for instructions on how to adapt this template for your own projects. For common questions, please see the [FAQ](https://github.com/OpenRA/OpenRAModSDK/wiki/FAQ). See [Updating to a new SDK or Engine version](https://github.com/OpenRA/OpenRAModSDK/wiki/Updating-to-a-new-SDK-or-Engine-version) for a guide on updating your mod a newer OpenRA release. The OpenRA engine and SDK scripts are made available under the [GPLv3](https://github.com/OpenRA/OpenRA/blob/bleed/COPYING) license, and any executable code developed by a mod and loaded by the engine (i.e. custom mod DLLs, lua scripts) must be released under a compatible license. Your mod data files (artwork, sound files, yaml, etc) are not part of your mod's source code, so you are free to distribute these assets under different terms (e.g. allowing redistribution in unmodified form, but not for use in other works). diff --git a/ExampleMod.sln b/VinylgodMod.sln similarity index 95% rename from ExampleMod.sln rename to VinylgodMod.sln index c624100..7462875 100644 --- a/ExampleMod.sln +++ b/VinylgodMod.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Example", "OpenRA.Mods.Example\OpenRA.Mods.Example.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Mods.Vinylgod", "OpenRA.Mods.Vinylgod\OpenRA.Mods.Vinylgod.csproj", "{4E5B38F7-4E99-4C92-BB39-9100CC7F3829}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRA.Game", "engine\OpenRA.Game\OpenRA.Game.csproj", "{0DFB103F-2962-400F-8C6D-E2C28CCBA633}" EndProject diff --git a/assets_src/PROMPTS.md b/assets_src/PROMPTS.md new file mode 100644 index 0000000..e8d6d60 --- /dev/null +++ b/assets_src/PROMPTS.md @@ -0,0 +1,10 @@ +# Asset provenance log + +All images generated locally on MODELBEAST (`flux_local`) via `tools/mbgen.py`. Original prompts, no third-party IP referenced. + +| file | date | prompt | +|---|---|---| +| concepts/emblem_mrp.png | 2026-07-20 | faction emblem logo, monster robot holding a vinyl record aloft, bold flat 2-color screen-print style, circular badge, no text, black and hot pink | +| concepts/digger.png | 2026-07-20 | rusty junkyard forklift monster robot with crate claw carrying milk crates of black vinyl records, hot pink trim, CRT eye, 3/4 view, isometric game unit concept art, plain grey background | +| concepts/pressplant.png | 2026-07-20 | industrial hydraulic vinyl record pressing plant building, steam vents, conveyor belt of fresh records, rust and hot pink, isometric RTS building concept art, plain grey background | +| concepts/drmwalker.png | 2026-07-20 | glossy white faceless robot mech with single blue ring-light eye, chest is a glowing paywall screen, smooth rounded seamless design, isometric game unit concept art, plain grey background — *came out small/cute; reuse as `bufferbot`, re-prompt drmwalker with "towering, menacing, tall bipedal mech"* | diff --git a/assets_src/concepts/digger.png b/assets_src/concepts/digger.png new file mode 100644 index 0000000..f76da6e Binary files /dev/null and b/assets_src/concepts/digger.png differ diff --git a/assets_src/concepts/drmwalker.png b/assets_src/concepts/drmwalker.png new file mode 100644 index 0000000..50fa384 Binary files /dev/null and b/assets_src/concepts/drmwalker.png differ diff --git a/assets_src/concepts/emblem_mrp.png b/assets_src/concepts/emblem_mrp.png new file mode 100644 index 0000000..aa948d2 Binary files /dev/null and b/assets_src/concepts/emblem_mrp.png differ diff --git a/assets_src/concepts/pressplant.png b/assets_src/concepts/pressplant.png new file mode 100644 index 0000000..34b8f8f Binary files /dev/null and b/assets_src/concepts/pressplant.png differ diff --git a/fetch-engine.sh b/fetch-engine.sh index 8b4ca0f..b880709 100755 --- a/fetch-engine.sh +++ b/fetch-engine.sh @@ -74,7 +74,7 @@ if [ "${AUTOMATIC_ENGINE_MANAGEMENT}" = "True" ]; then rmdir "${AUTOMATIC_ENGINE_EXTRACT_DIRECTORY}" rm "${AUTOMATIC_ENGINE_TEMP_ARCHIVE_NAME}" - # HACK: Remove bogus lint check that the Example mod can't possibly pass + # HACK: Remove bogus lint check that the Vinylgod mod can't possibly pass # because to do so it would need to define a lot of excess things surrounding resources. rm ${ENGINE_DIRECTORY}/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs diff --git a/launch-dedicated.cmd b/launch-dedicated.cmd index c346a95..260ffcf 100644 --- a/launch-dedicated.cmd +++ b/launch-dedicated.cmd @@ -1,4 +1,4 @@ -:: example launch script, see https://github.com/OpenRA/OpenRA/wiki/Dedicated-Server for details +:: vinylgod launch script, see https://github.com/OpenRA/OpenRA/wiki/Dedicated-Server for details @echo on diff --git a/make.ps1 b/make.ps1 index 8dad44f..306cfc0 100644 --- a/make.ps1 +++ b/make.ps1 @@ -367,7 +367,7 @@ if ($command -eq "all" -or $command -eq "clean" -or $command -eq "check") rm $env:AUTOMATIC_ENGINE_EXTRACT_DIRECTORY -r - # HACK: Remove bogus lint check that the Example mod can't possibly pass + # HACK: Remove bogus lint check that the Vinylgod mod can't possibly pass # because to do so it would need to define a lot of excess things surrounding resources. rm $env:ENGINE_DIRECTORY/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs diff --git a/mod.config b/mod.config index 18001ce..c449eb8 100644 --- a/mod.config +++ b/mod.config @@ -6,7 +6,7 @@ # The id of the mod packaged by this project. # This must exist as a directory in the mods directory and should not contain spaces. -MOD_ID="example" +MOD_ID="vinylgod" # The OpenRA engine version to use for this project. ENGINE_VERSION="release-20250330" @@ -21,7 +21,7 @@ ENGINE_VERSION="release-20250330" # - Windows installers will be named as {PACKAGING_INSTALLER_NAME}-{TAG}.exe # - macOS installers will be named as {PACKAGING_INSTALLER_NAME}-{TAG}.dmg # - Linux .appimages will be named as {PACKAGING_INSTALLER_NAME}-${TAG}.AppImage -PACKAGING_INSTALLER_NAME="ExampleMod" +PACKAGING_INSTALLER_NAME="VinylgodMod" # The human-readable name for this project. # This is used in: @@ -35,7 +35,7 @@ PACKAGING_INSTALLER_NAME="ExampleMod" # - Windows desktop shortcut # - Windows "Programs and Features" list # - Linux launcher shortcut -PACKAGING_DISPLAY_NAME="Example Mod" +PACKAGING_DISPLAY_NAME="VINYLGOD" # The URL for the project homepage. # This is used in: @@ -48,7 +48,7 @@ PACKAGING_FAQ_URL="https://wiki.openra.net/FAQ" # The human-readable project authors. # This is used in: # - Windows "Add/Remove Programs" list -PACKAGING_AUTHORS="Example Mod authors" +PACKAGING_AUTHORS="Vinylgod Mod authors" # If your mod depends on OpenRA.Mods.Cnc.dll from the engine set # this to "True" to package the dll in your installers. @@ -71,14 +71,14 @@ PACKAGING_OSX_DMG_APPLICATION_ICON_POSITION="410, 210" PACKAGING_OSX_DMG_HIDDEN_ICON_POSITION="190, 350" # Filename to use for the launcher executable on Windows. -PACKAGING_WINDOWS_LAUNCHER_NAME="ExampleMod" +PACKAGING_WINDOWS_LAUNCHER_NAME="VinylgodMod" # The name of the Windows Program Files directory to install the project files to. -PACKAGING_WINDOWS_INSTALL_DIR_NAME="OpenRA Example Mod" +PACKAGING_WINDOWS_INSTALL_DIR_NAME="OpenRA Vinylgod Mod" # The key prefix used for Windows registry metadata. # This should not contain spaces or special characters. -PACKAGING_WINDOWS_REGISTRY_KEY="OpenRAExampleMod" +PACKAGING_WINDOWS_REGISTRY_KEY="OpenRAVinylgodMod" # Path to the file containing the text to show in the Windows installer license dialog PACKAGING_WINDOWS_LICENSE_FILE="./COPYING" diff --git a/mods/example/mod.content.yaml b/mods/example/mod.content.yaml deleted file mode 100644 index 2c55a74..0000000 --- a/mods/example/mod.content.yaml +++ /dev/null @@ -1,32 +0,0 @@ -Cursors: - example|cursors/default.yaml - -Missions: - example|missions/example.yaml - -Music: - example|music/example.yaml - -Notifications: - example|notifications/example.yaml - -Rules: - example|rules/example.yaml - example|rules/mpspawn.yaml - example|rules/palettes.yaml - example|rules/player.yaml - example|rules/world.yaml - -Sequences: - example|sequences/example.yaml - example|sequences/mapeditor.yaml - example|sequences/mpspawn.yaml - -TileSets: - example|tilesets/example.yaml - -Voices: - example|voices/example.yaml - -Weapons: - example|weapons/example.yaml diff --git a/mods/example/sequences/example.yaml b/mods/example/sequences/example.yaml deleted file mode 100644 index c35aeab..0000000 --- a/mods/example/sequences/example.yaml +++ /dev/null @@ -1,3 +0,0 @@ -example: - idle: - Filename: sequences/assets/example.png diff --git a/mods/example/chrome/assets/dialog.png b/mods/vinylgod/chrome/assets/dialog.png similarity index 100% rename from mods/example/chrome/assets/dialog.png rename to mods/vinylgod/chrome/assets/dialog.png diff --git a/mods/example/chrome/assets/glyphs.png b/mods/vinylgod/chrome/assets/glyphs.png similarity index 100% rename from mods/example/chrome/assets/glyphs.png rename to mods/vinylgod/chrome/assets/glyphs.png diff --git a/mods/example/chrome/assets/loadscreen.png b/mods/vinylgod/chrome/assets/loadscreen.png similarity index 100% rename from mods/example/chrome/assets/loadscreen.png rename to mods/vinylgod/chrome/assets/loadscreen.png diff --git a/mods/example/chrome/chrome.yaml b/mods/vinylgod/chrome/chrome.yaml similarity index 99% rename from mods/example/chrome/chrome.yaml rename to mods/vinylgod/chrome/chrome.yaml index 67bdb7d..c72eb34 100644 --- a/mods/example/chrome/chrome.yaml +++ b/mods/vinylgod/chrome/chrome.yaml @@ -119,7 +119,7 @@ strategic: flags: Inherits: ^Glyphs Regions: - example: 226, 241, 30, 15 + vinylgod: 226, 241, 30, 15 Random: 226, 241, 30, 15 spectator: 226, 241, 30, 15 diff --git a/mods/example/chrome/ingame-observer.yaml b/mods/vinylgod/chrome/ingame-observer.yaml similarity index 100% rename from mods/example/chrome/ingame-observer.yaml rename to mods/vinylgod/chrome/ingame-observer.yaml diff --git a/mods/example/chrome/layouts/ingame-player.yaml b/mods/vinylgod/chrome/layouts/ingame-player.yaml similarity index 100% rename from mods/example/chrome/layouts/ingame-player.yaml rename to mods/vinylgod/chrome/layouts/ingame-player.yaml diff --git a/mods/example/cursors/assets/default.png b/mods/vinylgod/cursors/assets/default.png similarity index 100% rename from mods/example/cursors/assets/default.png rename to mods/vinylgod/cursors/assets/default.png diff --git a/mods/example/cursors/default.yaml b/mods/vinylgod/cursors/default.yaml similarity index 100% rename from mods/example/cursors/default.yaml rename to mods/vinylgod/cursors/default.yaml diff --git a/mods/example/fluent/chrome.ftl b/mods/vinylgod/fluent/chrome.ftl similarity index 100% rename from mods/example/fluent/chrome.ftl rename to mods/vinylgod/fluent/chrome.ftl diff --git a/mods/example/fluent/mod.ftl b/mods/vinylgod/fluent/mod.ftl similarity index 81% rename from mods/example/fluent/mod.ftl rename to mods/vinylgod/fluent/mod.ftl index ee8191b..df258f5 100644 --- a/mods/example/fluent/mod.ftl +++ b/mods/vinylgod/fluent/mod.ftl @@ -1,6 +1,6 @@ ## Metadata -mod-title = Example mod -mod-windowtitle = Example +mod-title = Vinylgod mod +mod-windowtitle = Vinylgod # To silence "Warning: Missing key `loadscreen-loading` in mod ftl files required by `LogoStripeLoadScreen.Loading`" # Because https://github.com/OpenRA/OpenRA/issues/20693 wasn't fixed. diff --git a/mods/example/fluent/rules.ftl b/mods/vinylgod/fluent/rules.ftl similarity index 71% rename from mods/example/fluent/rules.ftl rename to mods/vinylgod/fluent/rules.ftl index 1bca9a0..57d365c 100644 --- a/mods/example/fluent/rules.ftl +++ b/mods/vinylgod/fluent/rules.ftl @@ -4,7 +4,7 @@ faction-random = .description = Random Faction A random faction will be chosen when the game starts. -faction-example = - .name = Example - .description = Example Faction +faction-vinylgod = + .name = Vinylgod + .description = Vinylgod Faction Provide your own faction description here. diff --git a/mods/example/maps/example/map.bin b/mods/vinylgod/maps/shellmap/map.bin similarity index 100% rename from mods/example/maps/example/map.bin rename to mods/vinylgod/maps/shellmap/map.bin diff --git a/mods/example/maps/example/map.png b/mods/vinylgod/maps/shellmap/map.png similarity index 100% rename from mods/example/maps/example/map.png rename to mods/vinylgod/maps/shellmap/map.png diff --git a/mods/example/maps/shellmap/map.yaml b/mods/vinylgod/maps/shellmap/map.yaml similarity index 76% rename from mods/example/maps/shellmap/map.yaml rename to mods/vinylgod/maps/shellmap/map.yaml index 8b2e98e..6438817 100644 --- a/mods/example/maps/shellmap/map.yaml +++ b/mods/vinylgod/maps/shellmap/map.yaml @@ -1,12 +1,12 @@ MapFormat: 12 -RequiresMod: example +RequiresMod: vinylgod -Title: Example Shellmap +Title: Vinylgod Shellmap -Author: Example Author +Author: Vinylgod Author -Tileset: EXAMPLE +Tileset: VINYLGOD MapSize: 34,34 diff --git a/mods/example/maps/shellmap/map.bin b/mods/vinylgod/maps/vinylgod/map.bin similarity index 100% rename from mods/example/maps/shellmap/map.bin rename to mods/vinylgod/maps/vinylgod/map.bin diff --git a/mods/example/maps/shellmap/map.png b/mods/vinylgod/maps/vinylgod/map.png similarity index 100% rename from mods/example/maps/shellmap/map.png rename to mods/vinylgod/maps/vinylgod/map.png diff --git a/mods/example/maps/example/map.yaml b/mods/vinylgod/maps/vinylgod/map.yaml similarity index 83% rename from mods/example/maps/example/map.yaml rename to mods/vinylgod/maps/vinylgod/map.yaml index 4489c1d..1613021 100644 --- a/mods/example/maps/example/map.yaml +++ b/mods/vinylgod/maps/vinylgod/map.yaml @@ -1,12 +1,12 @@ MapFormat: 12 -RequiresMod: example +RequiresMod: vinylgod -Title: Example Map +Title: Vinylgod Map -Author: Example Author +Author: Vinylgod Author -Tileset: EXAMPLE +Tileset: VINYLGOD MapSize: 34,34 diff --git a/mods/example/missions/example.yaml b/mods/vinylgod/missions/vinylgod.yaml similarity index 100% rename from mods/example/missions/example.yaml rename to mods/vinylgod/missions/vinylgod.yaml diff --git a/mods/example/mod.chrome.yaml b/mods/vinylgod/mod.chrome.yaml similarity index 93% rename from mods/example/mod.chrome.yaml rename to mods/vinylgod/mod.chrome.yaml index 84b29be..7992bde 100644 --- a/mods/example/mod.chrome.yaml +++ b/mods/vinylgod/mod.chrome.yaml @@ -1,5 +1,5 @@ Chrome: - example|chrome/chrome.yaml + vinylgod|chrome/chrome.yaml ChromeLayout: common|chrome/assetbrowser.yaml @@ -25,8 +25,8 @@ ChromeLayout: common|chrome/ingame-infostats.yaml common|chrome/ingame-menu.yaml common|chrome/ingame-perf.yaml - example|chrome/ingame-observer.yaml - example|chrome/layouts/ingame-player.yaml + vinylgod|chrome/ingame-observer.yaml + vinylgod|chrome/layouts/ingame-player.yaml common|chrome/ingame-transients.yaml common|chrome/lobby.yaml common|chrome/lobby-kickdialogs.yaml @@ -107,8 +107,8 @@ FluentMessages: common|fluent/chrome.ftl common|fluent/hotkeys.ftl common|fluent/rules.ftl - example|fluent/mod.ftl - example|fluent/chrome.ftl - example|fluent/rules.ftl + vinylgod|fluent/mod.ftl + vinylgod|fluent/chrome.ftl + vinylgod|fluent/rules.ftl AllowUnusedFluentMessagesInExternalPackages: true diff --git a/mods/vinylgod/mod.content.yaml b/mods/vinylgod/mod.content.yaml new file mode 100644 index 0000000..5b52c3c --- /dev/null +++ b/mods/vinylgod/mod.content.yaml @@ -0,0 +1,32 @@ +Cursors: + vinylgod|cursors/default.yaml + +Missions: + vinylgod|missions/vinylgod.yaml + +Music: + vinylgod|music/vinylgod.yaml + +Notifications: + vinylgod|notifications/vinylgod.yaml + +Rules: + vinylgod|rules/vinylgod.yaml + vinylgod|rules/mpspawn.yaml + vinylgod|rules/palettes.yaml + vinylgod|rules/player.yaml + vinylgod|rules/world.yaml + +Sequences: + vinylgod|sequences/vinylgod.yaml + vinylgod|sequences/mapeditor.yaml + vinylgod|sequences/mpspawn.yaml + +TileSets: + vinylgod|tilesets/vinylgod.yaml + +Voices: + vinylgod|voices/vinylgod.yaml + +Weapons: + vinylgod|weapons/vinylgod.yaml diff --git a/mods/example/mod.yaml b/mods/vinylgod/mod.yaml similarity index 89% rename from mods/example/mod.yaml rename to mods/vinylgod/mod.yaml index 25c8ef9..86c0dab 100644 --- a/mods/example/mod.yaml +++ b/mods/vinylgod/mod.yaml @@ -6,20 +6,20 @@ Metadata: FileSystem: DefaultFileSystem Packages: ^EngineDir - $example: example + $vinylgod: vinylgod ^EngineDir|mods/common: common MapFolders: - example|maps: System + vinylgod|maps: System -Assemblies: OpenRA.Mods.Common.dll, OpenRA.Mods.Example.dll +Assemblies: OpenRA.Mods.Common.dll, OpenRA.Mods.Vinylgod.dll AssetBrowser: AudioExtensions: .wav SpriteExtensions: .png VideoExtensions: -SupportsMapsFrom: Example +SupportsMapsFrom: Vinylgod LoadScreen: BlankLoadScreen diff --git a/mods/example/music/example.yaml b/mods/vinylgod/music/vinylgod.yaml similarity index 100% rename from mods/example/music/example.yaml rename to mods/vinylgod/music/vinylgod.yaml diff --git a/mods/example/notifications/example.yaml b/mods/vinylgod/notifications/vinylgod.yaml similarity index 100% rename from mods/example/notifications/example.yaml rename to mods/vinylgod/notifications/vinylgod.yaml diff --git a/mods/example/rules/mpspawn.yaml b/mods/vinylgod/rules/mpspawn.yaml similarity index 100% rename from mods/example/rules/mpspawn.yaml rename to mods/vinylgod/rules/mpspawn.yaml diff --git a/mods/example/rules/palettes.yaml b/mods/vinylgod/rules/palettes.yaml similarity index 100% rename from mods/example/rules/palettes.yaml rename to mods/vinylgod/rules/palettes.yaml diff --git a/mods/example/rules/player.yaml b/mods/vinylgod/rules/player.yaml similarity index 100% rename from mods/example/rules/player.yaml rename to mods/vinylgod/rules/player.yaml diff --git a/mods/example/rules/example.yaml b/mods/vinylgod/rules/vinylgod.yaml similarity index 75% rename from mods/example/rules/example.yaml rename to mods/vinylgod/rules/vinylgod.yaml index fa775f4..d5c4f65 100644 --- a/mods/example/rules/example.yaml +++ b/mods/vinylgod/rules/vinylgod.yaml @@ -1,4 +1,4 @@ -example: +vinylgod: AlwaysVisible: BodyOrientation: HitShape: @@ -9,9 +9,9 @@ example: RenderSprites: WithSpriteBody: -example.colorpicker: - Inherits: example +vinylgod.colorpicker: + Inherits: vinylgod RenderSprites: - Image: example + Image: vinylgod Palette: colorpicker -MapEditorData: diff --git a/mods/example/rules/world.yaml b/mods/vinylgod/rules/world.yaml similarity index 73% rename from mods/example/rules/world.yaml rename to mods/vinylgod/rules/world.yaml index ec76b45..af87013 100644 --- a/mods/example/rules/world.yaml +++ b/mods/vinylgod/rules/world.yaml @@ -6,12 +6,12 @@ Faction@Random: InternalName: Random Name: faction-random.name - RandomFactionMembers: example + RandomFactionMembers: vinylgod Description: faction-random.description - Faction@example: - InternalName: example - Name: faction-example.name - Description: faction-example.description + Faction@vinylgod: + InternalName: vinylgod + Name: faction-vinylgod.name + Description: faction-vinylgod.description LoadWidgetAtGameStart: MusicPlaylist: ScreenMap: @@ -21,16 +21,16 @@ world: Inherits: ^baseworld ColorPickerManager: - PreviewActor: example.colorpicker + PreviewActor: vinylgod.colorpicker CreateMapPlayers: CustomTerrainDebugOverlay: DebugVisualizations: MapStartingLocations: SpawnMapActors: SpawnStartingUnits: - StartingUnits@Example: - BaseActor: example - Factions: example + StartingUnits@Vinylgod: + BaseActor: vinylgod + Factions: vinylgod ClassName: options-starting-units.unlabeled editorworld: diff --git a/mods/example/sequences/assets/mapeditor.png b/mods/vinylgod/sequences/assets/mapeditor.png similarity index 100% rename from mods/example/sequences/assets/mapeditor.png rename to mods/vinylgod/sequences/assets/mapeditor.png diff --git a/mods/example/sequences/assets/mpspawn.png b/mods/vinylgod/sequences/assets/mpspawn.png similarity index 100% rename from mods/example/sequences/assets/mpspawn.png rename to mods/vinylgod/sequences/assets/mpspawn.png diff --git a/mods/example/sequences/assets/example.png b/mods/vinylgod/sequences/assets/vinylgod.png similarity index 100% rename from mods/example/sequences/assets/example.png rename to mods/vinylgod/sequences/assets/vinylgod.png diff --git a/mods/example/sequences/mapeditor.yaml b/mods/vinylgod/sequences/mapeditor.yaml similarity index 100% rename from mods/example/sequences/mapeditor.yaml rename to mods/vinylgod/sequences/mapeditor.yaml diff --git a/mods/example/sequences/mpspawn.yaml b/mods/vinylgod/sequences/mpspawn.yaml similarity index 100% rename from mods/example/sequences/mpspawn.yaml rename to mods/vinylgod/sequences/mpspawn.yaml diff --git a/mods/vinylgod/sequences/vinylgod.yaml b/mods/vinylgod/sequences/vinylgod.yaml new file mode 100644 index 0000000..b474f58 --- /dev/null +++ b/mods/vinylgod/sequences/vinylgod.yaml @@ -0,0 +1,3 @@ +vinylgod: + idle: + Filename: sequences/assets/vinylgod.png diff --git a/mods/example/tilesets/example.yaml b/mods/vinylgod/tilesets/vinylgod.yaml similarity index 72% rename from mods/example/tilesets/example.yaml rename to mods/vinylgod/tilesets/vinylgod.yaml index aaf04c1..0342006 100644 --- a/mods/example/tilesets/example.yaml +++ b/mods/vinylgod/tilesets/vinylgod.yaml @@ -1,6 +1,6 @@ General: - Name: Example - Id: EXAMPLE + Name: Vinylgod + Id: VINYLGOD EditorTemplateOrder: Terrain Palette: @@ -11,7 +11,7 @@ Terrain: Templates: Template@255: Id: 255 - Images: tilesets/example/example.png + Images: tilesets/vinylgod/vinylgod.png Size: 1,1 Categories: Terrain Tiles: diff --git a/mods/example/tilesets/example/example.png b/mods/vinylgod/tilesets/vinylgod/vinylgod.png similarity index 100% rename from mods/example/tilesets/example/example.png rename to mods/vinylgod/tilesets/vinylgod/vinylgod.png diff --git a/mods/example/voices/example.yaml b/mods/vinylgod/voices/vinylgod.yaml similarity index 100% rename from mods/example/voices/example.yaml rename to mods/vinylgod/voices/vinylgod.yaml diff --git a/mods/example/weapons/example.yaml b/mods/vinylgod/weapons/vinylgod.yaml similarity index 100% rename from mods/example/weapons/example.yaml rename to mods/vinylgod/weapons/vinylgod.yaml diff --git a/tools/mbgen.py b/tools/mbgen.py new file mode 100644 index 0000000..b97431b --- /dev/null +++ b/tools/mbgen.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +"""mbgen.py — VINYLGOD asset gen via MODELBEAST (free, local farm). + +Usage: + python3 tools/mbgen.py "prompt text" out.png # flux_local text->image + python3 tools/mbgen.py --op bg_remove_local in.png out.png +Token: MB_TOKEN env, else ~/Documents/backnforth/.env (never print it). +Contract per ~/Documents/MESHGOD/scripts/mb_recon.py (verified 2026-07-16): +POST /api/jobs -> poll /api/jobs/{id} -> match own asset by parent_job. +Job logs carry raw control chars; strip before json.loads. +""" +import json, mimetypes, os, sys, time, urllib.request, uuid + +HOST = os.environ.get('MB_HOST', 'http://100.89.131.57:8777') + + +def token(): + t = os.environ.get('MB_TOKEN') + if t: + return t + for line in open(os.path.expanduser('~/Documents/backnforth/.env')): + if line.startswith('MB_TOKEN='): + return line.split('=', 1)[1].strip() + sys.exit('no MB_TOKEN') + + +def req(path, data=None, headers=None, raw=False): + h = {'Authorization': f'Bearer {token()}'} + h.update(headers or {}) + body = urllib.request.urlopen(urllib.request.Request(HOST + path, data=data, headers=h), timeout=120).read() + if raw: + return body + s = body.decode('utf-8', 'replace') + return json.loads(''.join(c if c >= ' ' or c in '\t' else ' ' for c in s)) + + +def upload(path): + boundary = uuid.uuid4().hex + ctype = mimetypes.guess_type(path)[0] or 'application/octet-stream' + body = (f'--{boundary}\r\nContent-Disposition: form-data; name="file"; filename="{os.path.basename(path)}"\r\n' + f'Content-Type: {ctype}\r\n\r\n').encode() + open(path, 'rb').read() + f'\r\n--{boundary}--\r\n'.encode() + a = req('/api/assets', data=body, headers={'Content-Type': f'multipart/form-data; boundary={boundary}'}) + return a.get('id') or (a.get('items') or [a])[0].get('id') + + +def run(op, params, out, asset_id=None): + payload = {'operator': op, 'params': params} + if asset_id: + payload['asset_id'] = asset_id + j = req('/api/jobs', data=json.dumps(payload).encode(), headers={'Content-Type': 'application/json'}) + jid = j['id'] + print(f'[mb] job {jid} ({op}) submitted', flush=True) + t0 = time.time() + while True: + time.sleep(5) + st = req(f'/api/jobs/{jid}').get('status') + print(f'[mb] {st} ({int(time.time() - t0)}s)', flush=True) + if st in ('done', 'error', 'cancelled'): + break + if st != 'done': + sys.exit(f'[mb] job ended {st}') + a = req('/api/assets?limit=100') + items = a if isinstance(a, list) else a.get('items', []) + mine = [x for x in items if x.get('parent_job') == jid] + if not mine: + sys.exit('[mb] no output asset with matching parent_job') + open(out, 'wb').write(req(f"/api/assets/{mine[0]['id']}/file", raw=True)) + print(f'[mb] wrote {out} ({os.path.getsize(out) // 1024}KB)') + + +if __name__ == '__main__': + args = sys.argv[1:] + op = 'flux_local' + if args and args[0] == '--op': + op = args[1] + args = args[2:] + if op == 'flux_local': + run(op, {'prompt': args[0]}, args[1]) + else: # input-file operators + run(op, {}, args[1], asset_id=upload(args[0]))