anima-core 0.3.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.reek.yml +27 -1
- data/CHANGELOG.md +4 -0
- data/README.md +219 -25
- data/agents/codebase-analyzer.md +88 -0
- data/agents/codebase-pattern-finder.md +83 -0
- data/agents/documentation-researcher.md +59 -0
- data/agents/thoughts-analyzer.md +102 -0
- data/agents/web-search-researcher.md +71 -0
- data/anima-core.gemspec +4 -1
- data/app/channels/session_channel.rb +76 -28
- data/app/jobs/agent_request_job.rb +24 -0
- data/app/jobs/analytical_brain_job.rb +33 -0
- data/app/jobs/count_event_tokens_job.rb +1 -1
- data/app/models/concerns/event/broadcasting.rb +20 -2
- data/app/models/event.rb +1 -1
- data/app/models/goal.rb +91 -0
- data/app/models/session.rb +347 -22
- data/config/application.rb +2 -0
- data/db/migrate/20260314075248_add_subagent_support_to_sessions.rb +6 -0
- data/db/migrate/20260314112417_add_granted_tools_to_sessions.rb +5 -0
- data/db/migrate/20260314140000_add_name_to_sessions.rb +7 -0
- data/db/migrate/20260314150000_add_viewport_event_ids_to_sessions.rb +7 -0
- data/db/migrate/20260315100000_add_active_skills_to_sessions.rb +7 -0
- data/db/migrate/20260315140843_create_goals.rb +16 -0
- data/db/migrate/20260315144837_add_completed_at_to_goals.rb +5 -0
- data/db/migrate/20260315191105_add_active_workflow_to_sessions.rb +5 -0
- data/lib/agent_loop.rb +65 -9
- data/lib/agents/definition.rb +116 -0
- data/lib/agents/registry.rb +106 -0
- data/lib/analytical_brain/runner.rb +276 -0
- data/lib/analytical_brain/tools/activate_skill.rb +52 -0
- data/lib/analytical_brain/tools/deactivate_skill.rb +43 -0
- data/lib/analytical_brain/tools/deactivate_workflow.rb +34 -0
- data/lib/analytical_brain/tools/everything_is_ready.rb +28 -0
- data/lib/analytical_brain/tools/finish_goal.rb +62 -0
- data/lib/analytical_brain/tools/read_workflow.rb +58 -0
- data/lib/analytical_brain/tools/rename_session.rb +63 -0
- data/lib/analytical_brain/tools/set_goal.rb +60 -0
- data/lib/analytical_brain/tools/update_goal.rb +60 -0
- data/lib/analytical_brain.rb +23 -0
- data/lib/anima/cli/mcp/secrets.rb +76 -0
- data/lib/anima/cli/mcp.rb +197 -0
- data/lib/anima/cli.rb +4 -0
- data/lib/anima/installer.rb +182 -6
- data/lib/anima/settings.rb +226 -0
- data/lib/anima/version.rb +1 -1
- data/lib/anima.rb +9 -0
- data/lib/credential_store.rb +103 -0
- data/lib/environment_probe.rb +232 -0
- data/lib/llm/client.rb +29 -10
- data/lib/mcp/client_manager.rb +86 -0
- data/lib/mcp/config.rb +213 -0
- data/lib/mcp/health_check.rb +77 -0
- data/lib/mcp/secrets.rb +73 -0
- data/lib/mcp/stdio_transport.rb +206 -0
- data/lib/providers/anthropic.rb +8 -7
- data/lib/shell_session.rb +11 -10
- data/lib/skills/definition.rb +97 -0
- data/lib/skills/registry.rb +105 -0
- data/lib/tools/edit.rb +3 -4
- data/lib/tools/mcp_tool.rb +114 -0
- data/lib/tools/read.rb +15 -16
- data/lib/tools/registry.rb +14 -12
- data/lib/tools/request_feature.rb +121 -0
- data/lib/tools/return_result.rb +81 -0
- data/lib/tools/spawn_specialist.rb +109 -0
- data/lib/tools/spawn_subagent.rb +111 -0
- data/lib/tools/subagent_prompts.rb +12 -0
- data/lib/tools/web_get.rb +8 -9
- data/lib/tui/app.rb +332 -43
- data/lib/tui/message_store.rb +20 -0
- data/lib/tui/screens/chat.rb +207 -20
- data/lib/workflows/definition.rb +97 -0
- data/lib/workflows/registry.rb +89 -0
- data/skills/activerecord/SKILL.md +255 -0
- data/skills/activerecord/examples/associations/association_extensions.rb +298 -0
- data/skills/activerecord/examples/associations/basic_associations.rb +118 -0
- data/skills/activerecord/examples/associations/counter_caches.rb +215 -0
- data/skills/activerecord/examples/associations/polymorphic_associations.rb +217 -0
- data/skills/activerecord/examples/associations/self_referential.rb +302 -0
- data/skills/activerecord/examples/associations/through_associations.rb +203 -0
- data/skills/activerecord/examples/basics/crud_operations.rb +209 -0
- data/skills/activerecord/examples/basics/dirty_tracking.rb +218 -0
- data/skills/activerecord/examples/basics/inheritance.rb +377 -0
- data/skills/activerecord/examples/basics/type_casting.rb +317 -0
- data/skills/activerecord/examples/callbacks/alternatives_to_callbacks.rb +447 -0
- data/skills/activerecord/examples/callbacks/conditional_callbacks.rb +353 -0
- data/skills/activerecord/examples/callbacks/lifecycle_callbacks.rb +280 -0
- data/skills/activerecord/examples/callbacks/transaction_callbacks.rb +340 -0
- data/skills/activerecord/examples/migrations/indexes_and_constraints.rb +337 -0
- data/skills/activerecord/examples/migrations/reversible_patterns.rb +403 -0
- data/skills/activerecord/examples/migrations/safe_patterns.rb +420 -0
- data/skills/activerecord/examples/migrations/schema_changes.rb +277 -0
- data/skills/activerecord/examples/querying/batch_processing.rb +226 -0
- data/skills/activerecord/examples/querying/eager_loading.rb +259 -0
- data/skills/activerecord/examples/querying/finder_methods.rb +170 -0
- data/skills/activerecord/examples/querying/optimization.rb +275 -0
- data/skills/activerecord/examples/querying/scopes.rb +260 -0
- data/skills/activerecord/examples/validations/built_in_validators.rb +277 -0
- data/skills/activerecord/examples/validations/conditional_validations.rb +288 -0
- data/skills/activerecord/examples/validations/custom_validators.rb +381 -0
- data/skills/activerecord/examples/validations/database_constraints.rb +432 -0
- data/skills/activerecord/examples/validations/validation_contexts.rb +367 -0
- data/skills/activerecord/references/associations.md +709 -0
- data/skills/activerecord/references/basics.md +622 -0
- data/skills/activerecord/references/callbacks.md +738 -0
- data/skills/activerecord/references/migrations.md +657 -0
- data/skills/activerecord/references/querying.md +655 -0
- data/skills/activerecord/references/validations.md +596 -0
- data/skills/dragonruby/SKILL.md +250 -0
- data/skills/dragonruby/examples/audio/audio_events.rb +55 -0
- data/skills/dragonruby/examples/audio/background_music.rb +29 -0
- data/skills/dragonruby/examples/audio/crossfade.rb +51 -0
- data/skills/dragonruby/examples/audio/music_controls.rb +51 -0
- data/skills/dragonruby/examples/audio/sound_effects.rb +30 -0
- data/skills/dragonruby/examples/core/coordinate_system.rb +27 -0
- data/skills/dragonruby/examples/core/hello_world.rb +24 -0
- data/skills/dragonruby/examples/core/labels.rb +22 -0
- data/skills/dragonruby/examples/core/sprites.rb +35 -0
- data/skills/dragonruby/examples/core/state_management.rb +29 -0
- data/skills/dragonruby/examples/distribution/background_pause.rb +42 -0
- data/skills/dragonruby/examples/distribution/build_workflow.sh +26 -0
- data/skills/dragonruby/examples/distribution/cvars_production.txt +16 -0
- data/skills/dragonruby/examples/distribution/game_metadata_hd.txt +23 -0
- data/skills/dragonruby/examples/distribution/game_metadata_minimal.txt +9 -0
- data/skills/dragonruby/examples/distribution/game_metadata_mobile.txt +31 -0
- data/skills/dragonruby/examples/distribution/platform_detection.rb +36 -0
- data/skills/dragonruby/examples/distribution/steam_metadata.txt +19 -0
- data/skills/dragonruby/examples/entities/collision_detection.rb +43 -0
- data/skills/dragonruby/examples/entities/entity_lifecycle.rb +68 -0
- data/skills/dragonruby/examples/entities/entity_storage.rb +38 -0
- data/skills/dragonruby/examples/entities/factory_methods.rb +45 -0
- data/skills/dragonruby/examples/entities/random_spawning.rb +50 -0
- data/skills/dragonruby/examples/game-logic/reset_patterns.rb +98 -0
- data/skills/dragonruby/examples/game-logic/save_load.rb +101 -0
- data/skills/dragonruby/examples/game-logic/scoring.rb +104 -0
- data/skills/dragonruby/examples/game-logic/state_transitions.rb +103 -0
- data/skills/dragonruby/examples/game-logic/timers.rb +87 -0
- data/skills/dragonruby/examples/input/action_triggers.rb +36 -0
- data/skills/dragonruby/examples/input/analog_movement.rb +28 -0
- data/skills/dragonruby/examples/input/controller_input.rb +28 -0
- data/skills/dragonruby/examples/input/directional_input.rb +24 -0
- data/skills/dragonruby/examples/input/keyboard_input.rb +28 -0
- data/skills/dragonruby/examples/input/mouse_click.rb +26 -0
- data/skills/dragonruby/examples/input/movement_with_bounds.rb +22 -0
- data/skills/dragonruby/examples/input/normalized_movement.rb +32 -0
- data/skills/dragonruby/examples/rendering/frame_animation.rb +32 -0
- data/skills/dragonruby/examples/rendering/labels.rb +32 -0
- data/skills/dragonruby/examples/rendering/layering.rb +51 -0
- data/skills/dragonruby/examples/rendering/solids.rb +61 -0
- data/skills/dragonruby/examples/rendering/sprites.rb +33 -0
- data/skills/dragonruby/examples/rendering/spritesheet_animation.rb +39 -0
- data/skills/dragonruby/examples/scenes/case_dispatch.rb +60 -0
- data/skills/dragonruby/examples/scenes/class_based.rb +150 -0
- data/skills/dragonruby/examples/scenes/pause_overlay.rb +100 -0
- data/skills/dragonruby/examples/scenes/safe_transitions.rb +68 -0
- data/skills/dragonruby/examples/scenes/scene_transitions.rb +98 -0
- data/skills/dragonruby/examples/scenes/send_dispatch.rb +88 -0
- data/skills/dragonruby/references/audio.md +396 -0
- data/skills/dragonruby/references/core.md +385 -0
- data/skills/dragonruby/references/distribution.md +434 -0
- data/skills/dragonruby/references/entities.md +516 -0
- data/skills/dragonruby/references/game-logic/persistence.md +386 -0
- data/skills/dragonruby/references/game-logic/state.md +389 -0
- data/skills/dragonruby/references/input.md +414 -0
- data/skills/dragonruby/references/rendering/animation.md +467 -0
- data/skills/dragonruby/references/rendering/primitives.md +403 -0
- data/skills/dragonruby/references/scenes.md +443 -0
- data/skills/draper-decorators/SKILL.md +344 -0
- data/skills/draper-decorators/examples/application_decorator.rb +61 -0
- data/skills/draper-decorators/examples/decorator_spec.rb +253 -0
- data/skills/draper-decorators/examples/model_decorator.rb +152 -0
- data/skills/draper-decorators/references/anti-patterns.md +640 -0
- data/skills/draper-decorators/references/patterns.md +507 -0
- data/skills/draper-decorators/references/testing.md +559 -0
- data/skills/gh-issue.md +182 -0
- data/skills/mcp-server/SKILL.md +177 -0
- data/skills/mcp-server/examples/dynamic_tools.rb +36 -0
- data/skills/mcp-server/examples/file_manager_tool.rb +85 -0
- data/skills/mcp-server/examples/http_client.rb +48 -0
- data/skills/mcp-server/examples/http_server.rb +97 -0
- data/skills/mcp-server/examples/rails_integration.rb +88 -0
- data/skills/mcp-server/examples/stdio_server.rb +108 -0
- data/skills/mcp-server/examples/streaming_client.rb +95 -0
- data/skills/mcp-server/references/gotchas.md +183 -0
- data/skills/mcp-server/references/prompts.md +98 -0
- data/skills/mcp-server/references/resources.md +53 -0
- data/skills/mcp-server/references/server.md +140 -0
- data/skills/mcp-server/references/tools.md +146 -0
- data/skills/mcp-server/references/transport.md +104 -0
- data/skills/ratatui-ruby/SKILL.md +315 -0
- data/skills/ratatui-ruby/references/core-concepts.md +340 -0
- data/skills/ratatui-ruby/references/events.md +387 -0
- data/skills/ratatui-ruby/references/frameworks.md +522 -0
- data/skills/ratatui-ruby/references/layout.md +423 -0
- data/skills/ratatui-ruby/references/styling.md +268 -0
- data/skills/ratatui-ruby/references/testing.md +433 -0
- data/skills/ratatui-ruby/references/widgets.md +532 -0
- data/skills/rspec/SKILL.md +340 -0
- data/skills/rspec/examples/core/basic_structure.rb +69 -0
- data/skills/rspec/examples/core/configuration.rb +126 -0
- data/skills/rspec/examples/core/hooks.rb +126 -0
- data/skills/rspec/examples/core/memoized_helpers.rb +139 -0
- data/skills/rspec/examples/core/metadata_filtering.rb +144 -0
- data/skills/rspec/examples/core/shared_examples.rb +145 -0
- data/skills/rspec/examples/factory_bot/associations.rb +314 -0
- data/skills/rspec/examples/factory_bot/build_strategies.rb +272 -0
- data/skills/rspec/examples/factory_bot/callbacks.rb +320 -0
- data/skills/rspec/examples/factory_bot/custom_construction.rb +328 -0
- data/skills/rspec/examples/factory_bot/factory_definition.rb +191 -0
- data/skills/rspec/examples/factory_bot/inheritance.rb +314 -0
- data/skills/rspec/examples/factory_bot/traits.rb +293 -0
- data/skills/rspec/examples/factory_bot/transients.rb +229 -0
- data/skills/rspec/examples/matchers/change.rb +115 -0
- data/skills/rspec/examples/matchers/collections.rb +154 -0
- data/skills/rspec/examples/matchers/comparisons.rb +79 -0
- data/skills/rspec/examples/matchers/composing.rb +155 -0
- data/skills/rspec/examples/matchers/custom_matchers.rb +197 -0
- data/skills/rspec/examples/matchers/equality.rb +58 -0
- data/skills/rspec/examples/matchers/errors.rb +136 -0
- data/skills/rspec/examples/matchers/output.rb +103 -0
- data/skills/rspec/examples/matchers/predicates.rb +87 -0
- data/skills/rspec/examples/matchers/truthiness.rb +101 -0
- data/skills/rspec/examples/matchers/types.rb +82 -0
- data/skills/rspec/examples/matchers/yield.rb +147 -0
- data/skills/rspec/examples/mocks/any_instance.rb +172 -0
- data/skills/rspec/examples/mocks/argument_matchers.rb +206 -0
- data/skills/rspec/examples/mocks/constants.rb +177 -0
- data/skills/rspec/examples/mocks/doubles.rb +139 -0
- data/skills/rspec/examples/mocks/expectations.rb +137 -0
- data/skills/rspec/examples/mocks/message_chains.rb +173 -0
- data/skills/rspec/examples/mocks/ordering.rb +144 -0
- data/skills/rspec/examples/mocks/receive_counts.rb +181 -0
- data/skills/rspec/examples/mocks/responses.rb +223 -0
- data/skills/rspec/examples/mocks/spies.rb +149 -0
- data/skills/rspec/examples/mocks/stubbing.rb +133 -0
- data/skills/rspec/examples/rails/channels.rb +250 -0
- data/skills/rspec/examples/rails/controller_specs.rb +302 -0
- data/skills/rspec/examples/rails/helper_specs.rb +245 -0
- data/skills/rspec/examples/rails/job_specs.rb +256 -0
- data/skills/rspec/examples/rails/mailer_specs.rb +228 -0
- data/skills/rspec/examples/rails/matchers.rb +374 -0
- data/skills/rspec/examples/rails/model_specs.rb +193 -0
- data/skills/rspec/examples/rails/request_specs.rb +275 -0
- data/skills/rspec/examples/rails/routing_specs.rb +276 -0
- data/skills/rspec/examples/rails/system_specs.rb +294 -0
- data/skills/rspec/examples/rails/transactions.rb +254 -0
- data/skills/rspec/examples/rails/view_specs.rb +252 -0
- data/skills/rspec/references/core.md +816 -0
- data/skills/rspec/references/factory_bot.md +641 -0
- data/skills/rspec/references/matchers.md +516 -0
- data/skills/rspec/references/mocks.md +381 -0
- data/skills/rspec/references/rails.md +528 -0
- data/templates/soul.md +40 -0
- data/workflows/commit.md +45 -0
- data/workflows/create_handoff.md +98 -0
- data/workflows/create_note.md +82 -0
- data/workflows/create_plan.md +457 -0
- data/workflows/decompose_ticket.md +109 -0
- data/workflows/feature.md +91 -0
- data/workflows/implement_plan.md +87 -0
- data/workflows/iterate_plan.md +247 -0
- data/workflows/research_codebase.md +210 -0
- data/workflows/resume_handoff.md +217 -0
- data/workflows/review_pr.md +320 -0
- data/workflows/thoughts_init.md +71 -0
- data/workflows/validate_plan.md +166 -0
- metadata +284 -2
- data/.mise.toml +0 -2
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Distribution
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
DragonRuby builds cross-platform with one command via `dragonruby-publish`.
|
|
6
|
+
|
|
7
|
+
| Platform | Output Format | Notes |
|
|
8
|
+
|----------|---------------|-------|
|
|
9
|
+
| Windows | `.exe` | 64-bit only |
|
|
10
|
+
| macOS | `.app` bundle | Intel + Apple Silicon |
|
|
11
|
+
| Linux | Binary | Including SteamOS |
|
|
12
|
+
| HTML5 | `.zip` | Requires SharedArrayBuffer |
|
|
13
|
+
| Android | `.apk` / `.aab` | Requires signing |
|
|
14
|
+
| iOS | `.ipa` | Requires signing |
|
|
15
|
+
|
|
16
|
+
## game_metadata.txt
|
|
17
|
+
|
|
18
|
+
Located at `mygame/metadata/game_metadata.txt`. **All fields required.**
|
|
19
|
+
|
|
20
|
+
```txt
|
|
21
|
+
devid=youritchusername
|
|
22
|
+
devtitle=Your Studio Name
|
|
23
|
+
gameid=my-game-slug
|
|
24
|
+
gametitle=My Game Title
|
|
25
|
+
version=0.1
|
|
26
|
+
icon=metadata/icon.png
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Field | Purpose | Notes |
|
|
30
|
+
|-------|---------|-------|
|
|
31
|
+
| `devid` | itch.io username | Lowercase, no spaces |
|
|
32
|
+
| `devtitle` | Developer display name | Can have spaces |
|
|
33
|
+
| `gameid` | itch.io project URL slug | Must match exactly |
|
|
34
|
+
| `gametitle` | Game display name | Can have spaces |
|
|
35
|
+
| `version` | Release version | MAJOR.MINOR format |
|
|
36
|
+
| `icon` | Path to icon | Relative to mygame/ |
|
|
37
|
+
|
|
38
|
+
**Optional fields:**
|
|
39
|
+
|
|
40
|
+
```txt
|
|
41
|
+
# Mobile package ID (required for Android/iOS)
|
|
42
|
+
packageid=com.yourstudio.mygame
|
|
43
|
+
|
|
44
|
+
# Exclude directories from builds
|
|
45
|
+
ignore_directories=saves,debug
|
|
46
|
+
ignore_directories_recursively=true
|
|
47
|
+
|
|
48
|
+
# High-DPI support
|
|
49
|
+
hd=true
|
|
50
|
+
highdpi=true
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Version Numbering
|
|
54
|
+
|
|
55
|
+
Simple `MAJOR.MINOR` scheme:
|
|
56
|
+
|
|
57
|
+
| Phase | Version | When to increment |
|
|
58
|
+
|-------|---------|-------------------|
|
|
59
|
+
| Development | `0.1` → `0.2` → `0.3` | Each development milestone |
|
|
60
|
+
| Initial Release | `1.0` | Game is complete |
|
|
61
|
+
| Updates | `1.1` → `1.2` | Bug fixes, content updates |
|
|
62
|
+
| Major Overhaul | `2.0` | Significant changes |
|
|
63
|
+
|
|
64
|
+
## dragonruby-publish Tool
|
|
65
|
+
|
|
66
|
+
**Package only (creates builds/):**
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
./dragonruby-publish --only-package
|
|
70
|
+
# OR
|
|
71
|
+
./dragonruby-publish --package mygame
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Package and upload to itch.io:**
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
./dragonruby-publish mygame
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Requires `gameid` to match itch.io project slug exactly.
|
|
81
|
+
|
|
82
|
+
**Build output location:** `./builds/` directory
|
|
83
|
+
|
|
84
|
+
## Pre-Release Checklist
|
|
85
|
+
|
|
86
|
+
Before running `dragonruby-publish`:
|
|
87
|
+
|
|
88
|
+
1. **Delete player-specific data:**
|
|
89
|
+
```sh
|
|
90
|
+
rm -f mygame/high-score.txt
|
|
91
|
+
rm -f mygame/saves/*
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
2. **Verify metadata:**
|
|
95
|
+
- All 6 required fields filled
|
|
96
|
+
- `gameid` matches itch.io project
|
|
97
|
+
- Version incremented
|
|
98
|
+
|
|
99
|
+
3. **Test local build:**
|
|
100
|
+
- Run platform-appropriate binary from `builds/`
|
|
101
|
+
- Verify game plays correctly
|
|
102
|
+
|
|
103
|
+
## itch.io Deployment
|
|
104
|
+
|
|
105
|
+
### First-Time Setup
|
|
106
|
+
|
|
107
|
+
1. Create project at https://itch.io/game/new
|
|
108
|
+
2. Set **Project URL** (becomes `gameid`)
|
|
109
|
+
3. Select **HTML** as project type (supports web + downloads)
|
|
110
|
+
4. Run `./dragonruby-publish --only-package`
|
|
111
|
+
5. Upload builds manually
|
|
112
|
+
|
|
113
|
+
### HTML5 Configuration (Critical)
|
|
114
|
+
|
|
115
|
+
| Setting | Value | Required |
|
|
116
|
+
|---------|-------|----------|
|
|
117
|
+
| "This file will be played in browser" | Checked | Yes |
|
|
118
|
+
| SharedArrayBuffer support | **Enabled** | **Yes** |
|
|
119
|
+
| Viewport width | 1280 | Landscape |
|
|
120
|
+
| Viewport height | 720 | Landscape |
|
|
121
|
+
|
|
122
|
+
**For portrait games:** 540x960
|
|
123
|
+
|
|
124
|
+
**Without SharedArrayBuffer, HTML5 builds will not run.**
|
|
125
|
+
|
|
126
|
+
### Subsequent Updates
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
./dragonruby-publish mygame
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Auto-uploads if `gameid` matches project slug.
|
|
133
|
+
|
|
134
|
+
### Publishing States
|
|
135
|
+
|
|
136
|
+
| State | Visibility | Use Case |
|
|
137
|
+
|-------|------------|----------|
|
|
138
|
+
| Private | Only you | Development |
|
|
139
|
+
| Secret URL | Shared link only | Playtesting |
|
|
140
|
+
| Public | Everyone | Release |
|
|
141
|
+
|
|
142
|
+
## Steam Deployment
|
|
143
|
+
|
|
144
|
+
Requires Steam publisher account and app configuration.
|
|
145
|
+
|
|
146
|
+
**Create `metadata/steam_metadata.txt`:**
|
|
147
|
+
|
|
148
|
+
```txt
|
|
149
|
+
steam.publish=true
|
|
150
|
+
steam.branch=public
|
|
151
|
+
steam.username=YOUR_STEAM_USERNAME
|
|
152
|
+
steam.appid=YOUR_APP_ID
|
|
153
|
+
steam.linux_depotid=LINUX_DEPOT_ID
|
|
154
|
+
steam.windows_depotid=WINDOWS_DEPOT_ID
|
|
155
|
+
steam.mac_depotid=MAC_DEPOT_ID
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Mobile Deployment
|
|
159
|
+
|
|
160
|
+
**Required in game_metadata.txt:**
|
|
161
|
+
|
|
162
|
+
```txt
|
|
163
|
+
packageid=com.yourstudio.mygame
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Uses reverse domain notation.
|
|
167
|
+
|
|
168
|
+
### Build Outputs
|
|
169
|
+
|
|
170
|
+
| Platform | Files | Notes |
|
|
171
|
+
|----------|-------|-------|
|
|
172
|
+
| Android | `APP-android.apk`, `APP-googleplay.aab` | AAB for Play Store |
|
|
173
|
+
| iOS | `.ipa` | Requires Xcode signing |
|
|
174
|
+
|
|
175
|
+
**APK Signing (external tools):**
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
# Generate keystore
|
|
179
|
+
keytool -genkey -v -keystore my-release-key.jks \
|
|
180
|
+
-keyalg RSA -keysize 2048 -validity 10000 \
|
|
181
|
+
-alias my-key-alias
|
|
182
|
+
|
|
183
|
+
# Sign APK
|
|
184
|
+
apksigner sign --ks my-release-key.jks \
|
|
185
|
+
--out signed.apk unsigned.apk
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Platform Detection
|
|
189
|
+
|
|
190
|
+
Runtime platform checks for platform-specific behavior:
|
|
191
|
+
|
|
192
|
+
```ruby
|
|
193
|
+
if args.gtk.platform?(:ios)
|
|
194
|
+
# iOS-specific code
|
|
195
|
+
elsif args.gtk.platform?(:android)
|
|
196
|
+
# Android-specific code
|
|
197
|
+
elsif args.gtk.platform?(:web)
|
|
198
|
+
# HTML5/browser code
|
|
199
|
+
else
|
|
200
|
+
# Desktop (Windows, macOS, Linux)
|
|
201
|
+
end
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Background Pause (Web/Mobile)
|
|
205
|
+
|
|
206
|
+
Handle focus loss gracefully:
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
def tick(args)
|
|
210
|
+
if !args.inputs.keyboard.has_focus &&
|
|
211
|
+
args.gtk.production &&
|
|
212
|
+
Kernel.tick_count != 0
|
|
213
|
+
# Game paused
|
|
214
|
+
args.outputs.background_color = [0, 0, 0]
|
|
215
|
+
args.outputs.labels << {
|
|
216
|
+
x: 640, y: 360,
|
|
217
|
+
text: "Click to resume",
|
|
218
|
+
alignment_enum: 1,
|
|
219
|
+
r: 255, g: 255, b: 255
|
|
220
|
+
}
|
|
221
|
+
return # Skip game logic
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Normal game tick
|
|
225
|
+
tick_game(args)
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Disable via cvars.txt:**
|
|
230
|
+
|
|
231
|
+
```txt
|
|
232
|
+
renderer.background_sleep=0
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## In-Game Rating Prompts
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
def open_rating_page(args)
|
|
239
|
+
if args.gtk.platform?(:ios)
|
|
240
|
+
args.gtk.openurl "itms-apps://itunes.apple.com/app/idYOURGAMEID?action=write-review"
|
|
241
|
+
elsif args.gtk.platform?(:android)
|
|
242
|
+
args.gtk.openurl "https://play.google.com/store/apps/details?id=YOURGAMEID"
|
|
243
|
+
elsif args.gtk.platform?(:web)
|
|
244
|
+
args.gtk.openurl "https://yourusername.itch.io/yourgame/purchase"
|
|
245
|
+
else
|
|
246
|
+
args.gtk.openurl "https://yourusername.itch.io/yourgame/rate?source=game"
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Icon Preparation
|
|
252
|
+
|
|
253
|
+
Default location: `mygame/metadata/icon.png`
|
|
254
|
+
|
|
255
|
+
| Platform | Requirements |
|
|
256
|
+
|----------|-------------|
|
|
257
|
+
| Desktop | Any size, PNG recommended |
|
|
258
|
+
| itch.io | 315x250 cover image separate |
|
|
259
|
+
| Mobile | Multiple sizes via asset catalogs |
|
|
260
|
+
|
|
261
|
+
## Project Structure for Distribution
|
|
262
|
+
|
|
263
|
+
**Recommended .gitignore:**
|
|
264
|
+
|
|
265
|
+
```gitignore
|
|
266
|
+
# Always ignore
|
|
267
|
+
/tmp/
|
|
268
|
+
/logs/
|
|
269
|
+
|
|
270
|
+
# For public/open-source repos
|
|
271
|
+
/builds/
|
|
272
|
+
/samples/
|
|
273
|
+
/docs/
|
|
274
|
+
/.dragonruby/
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Best practice:** Commit entire engine per project. Ensures known-working version years later.
|
|
278
|
+
|
|
279
|
+
## Console Wizard
|
|
280
|
+
|
|
281
|
+
Interactive metadata setup via console:
|
|
282
|
+
|
|
283
|
+
```ruby
|
|
284
|
+
$wizards.itch.start
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Prompts for all required fields, then runs `dragonruby-publish --only-package`.
|
|
288
|
+
|
|
289
|
+
## Common Antipatterns
|
|
290
|
+
|
|
291
|
+
### Shipping with Dev Data
|
|
292
|
+
|
|
293
|
+
```ruby
|
|
294
|
+
# WRONG - players see your high scores/saves
|
|
295
|
+
# (no code cleanup before build)
|
|
296
|
+
|
|
297
|
+
# CORRECT - delete temp files pre-build
|
|
298
|
+
rm -f mygame/high-score.txt
|
|
299
|
+
rm -rf mygame/saves/*
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Why:** Development data (high scores, save files) gets bundled into the release.
|
|
303
|
+
|
|
304
|
+
### Skipping Local Testing
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
# WRONG - publish without testing
|
|
308
|
+
./dragonruby-publish mygame
|
|
309
|
+
|
|
310
|
+
# CORRECT - test each platform build
|
|
311
|
+
./dragonruby-publish --only-package
|
|
312
|
+
# Then run: builds/mygame-windows.exe
|
|
313
|
+
# Then run: builds/mygame-macos.app
|
|
314
|
+
# Then run: builds/mygame-linux
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Why:** Different platforms may have broken builds or missing assets.
|
|
318
|
+
|
|
319
|
+
### Wrong Viewport Size
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
# WRONG - using non-standard dimensions on itch.io
|
|
323
|
+
Viewport: 800x600
|
|
324
|
+
|
|
325
|
+
# CORRECT - use standard dimensions
|
|
326
|
+
Viewport: 1280x720 (landscape)
|
|
327
|
+
Viewport: 540x960 (portrait)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Why:** Mismatched viewport causes layout issues in the itch.io embed.
|
|
331
|
+
|
|
332
|
+
### Forgetting SharedArrayBuffer
|
|
333
|
+
|
|
334
|
+
```ruby
|
|
335
|
+
# WRONG - HTML5 build doesn't run on itch.io
|
|
336
|
+
# (no SharedArrayBuffer enabled)
|
|
337
|
+
|
|
338
|
+
# CORRECT - enable in itch.io settings
|
|
339
|
+
# Project → Edit → SharedArrayBuffer → Enabled
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Why:** DragonRuby HTML5 builds require SharedArrayBuffer to function.
|
|
343
|
+
|
|
344
|
+
### Inconsistent Versioning
|
|
345
|
+
|
|
346
|
+
```ruby
|
|
347
|
+
# WRONG - version never changes
|
|
348
|
+
version=1.0
|
|
349
|
+
|
|
350
|
+
# CORRECT - increment on every release
|
|
351
|
+
version=1.0 # Initial release
|
|
352
|
+
version=1.1 # Bug fixes
|
|
353
|
+
version=1.2 # New content
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Why:** Players can't tell if they have the latest version.
|
|
357
|
+
|
|
358
|
+
### Sharing Engine Folder
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
# WRONG - symlink or shared engine folder
|
|
362
|
+
dragonruby -> /shared/dragonruby
|
|
363
|
+
|
|
364
|
+
# CORRECT - copy engine per project
|
|
365
|
+
cp -r /path/to/dragonruby ./my-game/
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Why:** Shared engines cause path issues and version conflicts between projects.
|
|
369
|
+
|
|
370
|
+
## Decision Tree
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
What platform are you targeting?
|
|
374
|
+
│
|
|
375
|
+
├─► Desktop only (Windows/macOS/Linux)
|
|
376
|
+
│ └─► Use: game_metadata_minimal.txt
|
|
377
|
+
│ • Fill 6 required fields
|
|
378
|
+
│ • Run: ./dragonruby-publish --only-package
|
|
379
|
+
│ • Upload to itch.io or Steam
|
|
380
|
+
│
|
|
381
|
+
├─► Web (HTML5) + Desktop
|
|
382
|
+
│ └─► Use: game_metadata_hd.txt
|
|
383
|
+
│ • Add hd=true, highdpi=true
|
|
384
|
+
│ • CRITICAL: Enable SharedArrayBuffer on itch.io
|
|
385
|
+
│ • Set viewport: 1280x720
|
|
386
|
+
│
|
|
387
|
+
├─► Mobile (Android/iOS)
|
|
388
|
+
│ └─► Use: game_metadata_mobile.txt
|
|
389
|
+
│ • Add packageid=com.studio.game
|
|
390
|
+
│ • Set orientation=portrait or landscape
|
|
391
|
+
│ • Sign APK externally
|
|
392
|
+
│
|
|
393
|
+
└─► Steam Distribution
|
|
394
|
+
└─► Use: steam_metadata.txt
|
|
395
|
+
• Get Steamworks publisher account
|
|
396
|
+
• Configure depot IDs
|
|
397
|
+
• Run: ./dragonruby-publish
|
|
398
|
+
|
|
399
|
+
Publishing workflow?
|
|
400
|
+
│
|
|
401
|
+
├─► First release
|
|
402
|
+
│ ├─► 1. Clean dev data (rm saves/*, high-score.txt)
|
|
403
|
+
│ ├─► 2. Configure game_metadata.txt
|
|
404
|
+
│ ├─► 3. ./dragonruby-publish --only-package
|
|
405
|
+
│ ├─► 4. Test builds locally
|
|
406
|
+
│ ├─► 5. Create itch.io project
|
|
407
|
+
│ ├─► 6. Upload builds manually
|
|
408
|
+
│ └─► See: build_workflow.sh
|
|
409
|
+
│
|
|
410
|
+
└─► Update release
|
|
411
|
+
├─► 1. Increment version in game_metadata.txt
|
|
412
|
+
├─► 2. Clean dev data
|
|
413
|
+
├─► 3. ./dragonruby-publish mygame
|
|
414
|
+
└─► Auto-uploads to itch.io
|
|
415
|
+
|
|
416
|
+
Platform-specific behavior needed?
|
|
417
|
+
│
|
|
418
|
+
├─► Different rating URLs → platform_detection.rb
|
|
419
|
+
├─► Handle tab-away/minimize → background_pause.rb
|
|
420
|
+
└─► Different save paths → platform_detection.rb
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Examples
|
|
424
|
+
|
|
425
|
+
| Example | Purpose |
|
|
426
|
+
|---------|---------|
|
|
427
|
+
| `game_metadata_minimal.txt` | Required fields only |
|
|
428
|
+
| `game_metadata_hd.txt` | HD desktop/web game |
|
|
429
|
+
| `game_metadata_mobile.txt` | Mobile with portrait orientation |
|
|
430
|
+
| `cvars_production.txt` | Production runtime settings |
|
|
431
|
+
| `steam_metadata.txt` | Steam publishing config |
|
|
432
|
+
| `build_workflow.sh` | Complete publishing script |
|
|
433
|
+
| `platform_detection.rb` | Runtime platform checks |
|
|
434
|
+
| `background_pause.rb` | Handle focus loss |
|