fix(version): read DR autostarts from UserVars instead of dependency#2277
Merged
mrhoribu merged 3 commits intoelanthia-online:masterfrom Mar 20, 2026
Merged
Conversation
dependency.lic is now run-once (elanthia-online/dr-scripts#7334) and no longer exposes list_autostarts. Autostarts have been migrated from script-scoped Settings to globally-accessible UserVars.autostart_scripts. Read directly from UserVars instead of gating on Script.running?. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughA single-line modification to Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
13 tasks
MahtraDR
added a commit
to elanthia-online/lich-5
that referenced
this pull request
Mar 28, 2026
## Summary
This PR migrates game-agnostic classes from `dependency.lic` into core
lich-5 and introduces **ScriptSync** -- a SHA-based script repository
synchronization system that replaces blind bulk downloads with
incremental, checksum-verified updates. Script repos now auto-sync on
login for both DR and GS.
---
## Part 1: Core Class Migration
Moves four classes from `dependency.lic` into `lib/` so they load at
boot before any script runs:
### ArgParser (`lib/common/arg_parser.rb`)
Script argument parsing with pattern matching and help display. Parses
`--flag`, `--key=value`, and positional arguments into a normalized
hash.
### SetupFiles (`lib/common/setup_files.rb`)
YAML cascade settings engine. Loads per-character, per-class, and base
YAML files, resolves `include:` directives, merges them in priority
order, and caches results. Includes deep-clone protection so scripts
cannot mutate shared settings.
### SettingsTransformer (`lib/common/settings_transformer.rb`)
Data-driven settings enrichment engine with 7 transform phases:
1. Defaults injection
2. Spell enrichment (spell name/abbreviation lookups)
3. List composition (merge/append/prepend from named lists)
4. UserVars fallback (fill missing keys from UserVars)
5. Hometown lookups (resolve town-specific data)
6. Denylists (filter out blocked items)
7. Legacy migrations (rename deprecated keys)
The transformer is fully game-agnostic -- each game provides its own
config hash describing which keys to transform and how.
### DR SettingsConfig (`lib/dragonrealms/dependency/settings_config.rb`)
Frozen config hash with DR-specific transform rules. Loaded by
`gameloader.rb` for DR sessions only.
### Integration
- `lich.rbw` requires ArgParser, SetupFiles, and SettingsTransformer at
boot
- `lib/common/gameloader.rb` requires SettingsConfig for DR sessions
- All classes are namespaced under `Lich::Common` / `Lich::DragonRealms`
and made available at top level via `include Lich::Common` in `lich.rbw`
- `dependency.lic` continues to define these classes inline. The dual
definitions are harmless (Ruby reopens the same class). A follow-up
dr-scripts PR will add `defined?` guards to skip redundant definitions.
---
## Part 2: ScriptSync -- SHA-Based Repository Synchronization
Adds a complete script repository sync system to `Lich::Util::Update`
that replaces the old blind-download approach with SHA-based incremental
sync.
### SCRIPT_REPOS Registry
A frozen hash defining repositories to sync:
- **`dr-scripts`** (`elanthia-online/dr-scripts`): tracking_mode `:all`
-- syncs every `.lic` at root, plus `profiles/` and `data/`
subdirectories. Filtered to DR sessions only via `game_filter: /^DR/`.
- **`scripts`** (`elanthia-online/scripts`): tracking_mode `:explicit`
-- syncs only a default tracked list (alias.lic, go2.lic, map.lic, etc.)
plus user-added scripts. Available for both DR and GS.
### How Sync Works
1. Fetches the GitHub tree API for the repo (cached 60s)
2. Builds a local SHA map by computing git blob SHAs
(`Digest::SHA1.hexdigest("blob #{size}\0#{content}")`) for all local
files
3. Compares remote tree SHAs against local SHAs
4. Downloads only files whose SHA differs (or are missing locally)
5. Writes files atomically via `safe_write` (tmp + rename with rollback
on failure)
### New CLI Commands
```
;lich5-update --sync Sync all repos for current game
;lich5-update --sync=dr-scripts Sync only dr-scripts repo
;lich5-update --sync=scripts Sync only EO/scripts repo
;lich5-update --tracked List tracked scripts for all repos
;lich5-update --tracked=scripts List tracked scripts for one repo
;lich5-update --track=scripts:bigshot.lic Add a script to tracked list
;lich5-update --untrack=scripts:bigshot.lic Remove from tracked list
;lich5-update --script=dr-scripts:hunting-buddy.lic Update script from specific repo
;lich5-update --data=dr-scripts:base-hunting.yaml Update data file from specific repo
```
### Key Methods Added to `Lich::Util::Update`
- `sync_all_repos` / `sync_repo(key)` -- top-level sync entry points
- `sync_subdir(tree, config, name, subconfig)` -- sync subdirectories
(profiles, data)
- `filter_syncable_scripts(tree, config)` -- apply tracking_mode and
patterns
- `build_local_sha_map(dir, pattern)` -- compute local git blob SHAs
- `safe_write(path, content)` -- atomic file write with rollback
- `http_get(url, auth:)` -- Net::HTTP wrapper with optional GitHub token
auth
- `github_token` -- lazy-loads token from `DATA_DIR/githubtoken.txt`
- `update_file_from_repo(type, repo_key, filename)` -- download a
specific file from a named repo with SHA pre-check
- `track_script` / `untrack_script` / `show_tracked` -- manage per-repo
tracked script lists
- `render_sync_summary` -- Terminal::Table formatted sync results
- `respond_mono` -- monospace output for all frontends (Profanity,
Genie, etc.)
### GitHub Token Support
If `DATA_DIR/githubtoken.txt` exists, all GitHub API calls include a
Bearer token. This avoids rate limiting for users who sync frequently.
Unauthenticated access works fine for casual use.
---
## Part 3: Login Auto-Sync for Both DR and GS
### What Changed
- **`games.rb`**: Script repos now sync automatically on login for
**both DR and GS** (previously DR only). Runs in a background thread to
avoid blocking `process_xml_data` and the `XMLData.name` race condition.
Each repo's `game_filter` already scopes which repos sync for which
game.
- **`update.rb`**: Removed `sync_all_repos` call from
`update_core_data_and_scripts`. Since a relog is required after every
`--update` or `--branch` operation, the login auto-sync handles script
updates. This avoids redundant downloads and stops clobbering local
script edits during lich core updates.
- **Help text**: Updated to reflect both-game auto-sync. Removed the
GS-specific `autostart add --sync` suggestion since it is now automatic.
### Why
- The old `--update` path force-downloaded core scripts unconditionally,
overwriting any local edits.
- With auto-sync on login, scripts update via SHA comparison -- only
downloading what actually changed.
- Both games benefit equally: DR syncs dr-scripts + EO/scripts, GS syncs
EO/scripts.
- Users can still manually sync at any time via `;lich5-update --sync`.
---
## Part 4: Branch Tracking Enhancements
- `--branch=owner:branch_name` syntax to install from a fork (e.g.,
`;lich5-update --branch=MahtraDR:some-feature`)
- `--branch` always re-downloads from GitHub, even when already on the
same branch, so newer commits are picked up without manual intervention
- `--status` shows current branch, repository, and last-updated
timestamp
- Branch tracking persists via `LICH_BRANCH` / `LICH_BRANCH_REPO`
constants in `version.rb`
---
## Part 5: UX Polish
- **Display names**: Each repo has a `display_name` (e.g., "DR Scripts")
used in user-facing messages
- **Terminal::Table**: `--tracked` and sync summaries render as
formatted tables
- **Monospace output**: `respond_mono` wraps output in
`Lich::Messaging.mono()` when available, ensuring proper alignment in
Profanity, Genie, and other frontends
- **Vars.save**: Called immediately after `--track`/`--untrack` to
persist changes
---
## Part 6: Code Review Fixes
Fixes addressing CodeRabbit review feedback:
- **`arg_parser.rb`**: Replaced bare `exit` with `raise ArgumentError`
so invalid/help args don't kill the Lich process. Script threads catch
the exception naturally via Lich's thread management. Important since
ArgParser now loads at boot in core rather than inside a script context.
- **`settings_transformer.rb` (denylists)**: Replaced bare `exit` with
`raise ArgumentError`. The exception is caught by the existing `rescue`
block in `transform()`, which logs the error and returns an empty
`OpenStruct` -- strictly better than killing the process.
- **`settings_transformer.rb` (defaults/fallback)**: Replaced `||=` with
`settings.to_h.key?` presence checks in `apply_defaults` and
`apply_uservars_fallback` so explicit `false` values in YAML are
preserved rather than overwritten by defaults. Checks both string and
symbol keys since `OpenStruct.new` converts string keys to symbols.
- **`settings_transformer.rb` (spells)**: Added `is_a?(Hash)` guards in
`apply_tm_prep_defaults` and `apply_battle_cries` to handle malformed
entries gracefully.
- **`settings_transformer.rb` (denylists)**: Fixed `keys.first` bug to
report actual offending key.
- **`settings_transformer.rb` (eval)**: Replaced `eval()` in global
overrides with explicit allowlist of lambdas.
- **`arg_parser.rb`**: Added `Regexp.escape(checkname)` for safe profile
path matching.
- **`setup_files.rb`**: Added missing `require 'set'`.
### Intentionally Not Changed
- **`setup_files.rb` (`unsafe_load_file`)**: Intentionally using
`YAML.unsafe_load_file`. These are user-owned local YAML config files,
not untrusted input. Player YAMLs use features `safe_load` rejects
(anchors, aliases, complex structures). Switching would break existing
configurations across the community.
- **`setup_files.rb` (basename cache keys)**: Profile and data files
have distinct naming conventions and are loaded through separate code
paths. Basename-only keys match existing `dependency.lic` behavior. A
collision would require identical names across directories, which
doesn't happen in the DR/GS ecosystem.
- **`arg_parser.rb` (nil vars TypeError)**: `check_match` handles empty
`vars` safely -- `matches_def(definition, nil)` returns `false`, the
method returns `nil`, and `compact` strips it. This code has worked in
production for years.
---
## Part 7: GS Scripts URL Fix
Fixed two bugs in the `scripts` (EO/scripts) repository sync:
- **Double path prefix**: `raw_base_url` ended with `/scripts` but
GitHub tree API paths already include `scripts/` (e.g.,
`scripts/ewaggle.lic`). The download URL was constructed as
`.../master/scripts/scripts/ewaggle.lic`, producing HTTP 404s. Fixed by
removing the trailing `/scripts` from `raw_base_url`.
- **Single-file tree lookup**: `update_file_from_repo` used bare
filenames (e.g., `ewaggle.lic`) for tree SHA lookups, but tree entries
use full paths (`scripts/ewaggle.lic`). Added `script_prefix` config
field to build the correct lookup path.
- **Branch re-download guard**: `--branch` short-circuited with "Already
on branch" when the user was already tracking the same branch,
preventing them from picking up newer commits (including this fix
itself). Removed the guard so `--branch` always re-downloads the latest
tarball.
---
## Related PRs
- elanthia-online/dr-scripts#7334 (Phase 0: dependency run-once)
- elanthia-online/scripts#2277 (version.lic fix for UserVars autostarts)
## Files Changed
| File | Change |
|------|--------|
| `lich.rbw` | Require ArgParser, SetupFiles, SettingsTransformer at
boot |
| `lib/common/arg_parser.rb` | **New** -- ArgParser class |
| `lib/common/setup_files.rb` | **New** -- SetupFiles class |
| `lib/common/settings_transformer.rb` | **New** -- SettingsTransformer
class |
| `lib/common/gameloader.rb` | Require SettingsConfig for DR |
| `lib/dragonrealms/dependency/settings_config.rb` | **New** -- DR
transform config |
| `lib/update.rb` | ScriptSync system, CLI commands, Net::HTTP, GitHub
token, branch enhancements, URL fix, remove redundant sync from update
path |
| `lib/games.rb` | Auto-sync on login for both DR and GS (removed
DR-only guard) |
| `spec/lib/common/arg_parser_spec.rb` | **New** -- 9 examples |
| `spec/lib/common/setup_files_spec.rb` | **New** -- 18 examples |
| `spec/lib/common/settings_transformer_spec.rb` | **New** -- 22
examples |
| `spec/lib/dragonrealms/dependency/settings_config_spec.rb` | **New**
-- 7 examples |
| `spec/lib/util/update_sync_spec.rb` | **New** -- 13 examples |
## Test Plan
- [x] `rspec spec/lib/common/arg_parser_spec.rb` -- 9 examples
- [x] `rspec spec/lib/common/setup_files_spec.rb` -- 18 examples
- [x] `rspec spec/lib/common/settings_transformer_spec.rb` -- 22
examples
- [x] `rspec spec/lib/dragonrealms/dependency/settings_config_spec.rb`
-- 7 examples
- [x] `rspec spec/lib/util/update_sync_spec.rb` -- 13 examples
- [x] Full suite: `rspec` -- all 3550 examples pass (0 failures)
- [x] Manual: boot lich, verify DR login works, `get_settings` returns
valid data
- [x] Manual: `;lich5-update --sync` downloads only changed files
- [x] Manual: `;lich5-update --tracked` displays formatted table
- [x] Manual: `;lich5-update
--branch=MahtraDR:feat/core-argparser-setupfiles-transformer` installs
from fork
- [x] Manual: `;lich5-update --branch` re-downloads when already on same
branch (picks up newer commits)
- [x] Manual: verify GS login triggers auto-sync of EO/scripts
- [x] Manual: verify `--update` no longer force-downloads scripts
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
UserVars.autostart_scriptsinstead of callinglist_autostartsgated behindScript.running?('dependency')list_autostartsno longer exists and dependency.lic is now run-onceDepends on
Test plan
;versionon a DR character — verify "DR autostarts" shows the correct list;versionon a GS character — verify no errors (line is DR-gated)🤖 Generated with Claude Code