-
Notifications
You must be signed in to change notification settings - Fork 223
feat: 🎉 Go Rewrite of MSM #448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
erikpaasonen
wants to merge
63
commits into
msmhq:master
Choose a base branch
from
erikpaasonen:main
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Conversation
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
Remaining (Acceptable): | Pattern | Reason | |---------------------------------|-----------------------------------------------------------| | defer file.Close() on reads | Standard Go pattern - close errors on reads rarely matter | | os.RemoveAll in tests | Test cleanup - acceptable to ignore | | s.Say/SaveOff/SaveOn in backups | Best-effort server notifications - non-critical | Code Quality Improvements: - Config parsing now logs warnings for invalid integer values - Server config parsing now logs warnings for invalid values - Screen PID parsing now properly handles parse errors - All SendCommand calls in allowlist/blocklist now log failures
also dropped pre-1.7 Minecraft support due to a different log file and format, to avoid complexity
Key Features 1. Wrapper architecture: Fabric is a per-server flag, not a jar group type 2. Version detection: Automatically extracts MC version from jar filenames 3. Upgrade protection: Blocks MC version changes if Fabric doesn't support them (with --force override) 4. Caching: API responses cached with configurable TTL; JAR files cached indefinitely 5. Minimal API calls: Only on version changes or explicit commands, never on start/stop
| Test | Result | |--------------------------------------------|-------------------------------------------------------| | msm fabric versions - list MC versions | ✅ Fetches from meta.fabricmc.net | | msm fabric versions 1.21.11 - list loaders | ✅ Returns loader versions | | Cache persistence | ✅ cache.json created and populated | | Version detection from jar filename | ✅ Detected 1.21.11 from minecraft_server.1.21.11.jar | | msm fabric status | ✅ Shows MC version, loader status, cached JAR | | msm fabric update - JAR download | ✅ Downloaded 175KB Fabric launcher JAR | | Downloaded JAR validity | ✅ Valid ZIP/JAR with Fabric classes | | Upgrade protection | ✅ Blocked upgrade to unsupported version 99.0.0 | | --force override | ✅ Bypasses protection |
- After=network.target local-fs.target - Proper boot ordering - Wants=network.target - Soft dependency (won't fail if network is slow) - TimeoutStopSec=120 - Graceful shutdown window for player warnings + world saves The Type=oneshot with RemainAfterExit=yes is correct for this use case since the actual Minecraft processes run in screen sessions, not as direct systemd children.
- Requirements moved to top (before installation) - Prerequisites section with OS-specific package install commands - System setup section (creating minecraft user and directories) - "From Source (Recommended)" with note about automatic setup - Pre-built binaries section with trade-off callout - Common Commands section (trimmed essentials) - Full command reference linked to separate file - Upgrading from Bash MSM moved toward bottom
for use with multiple host hardware admin users with access to create/manage their own MC worlds, all started/stopped at boot time by the systemd service.
| Check | Action if needed | |-------------------------------|---------------------------------| | Group doesn't exist | Create it | | User doesn't exist | Create it | | User not in minecraft group | usermod -aG minecraft minecraft | | User's primary group wrong | usermod -g minecraft minecraft | | User's home dir wrong | usermod -d /opt/msm minecraft | | Directories missing | Create them | | Directory ownership wrong | Fix only affected directories | | Permissions wrong on servers/ | Fix setgid |
| Command | Before (ambiguous) | After (explicit) | |-------------|------------------------------------------|-----------------------------------------| | RAM status | msm worlds ram <s> <w> (toggled!) | msm worlds ram <s> <w> (shows status) | | RAM enable | (same command toggled) | msm worlds ram on <s> <w> | | RAM disable | (same command toggled) | msm worlds ram off <s> <w> | | Jar status | N/A | msm jar <server> (shows current) | | Jar link | msm jar <s> <group> (looked like GET) | msm jar link <s> <group> | | Config get | msm server config <s> [key] | msm server config <s> [key] (unchanged) | | Config set | msm server config <s> <k> <v> (implicit) | msm server config set <s> <k> <v> |
Status is almost always '(active)' which might imply running to some people, when in fact it only means that it's the world in 'worldstorage' and not 'worldstorage_inactive', which is a legacy carryover from the bash scripts implementation we might remove. instead, it's easier to think of 1:1 servers to worlds and just create more servers as needed.
The game mode setting in level.dat can override the MSM setting when new players join, this enforces that the setting managed by the MSM admin applies to all new players joining the server. also fixes 'msm server init' cmd to inject (merge) this setting into existing already-imported server.properties files.
Author
|
I'll pull this back into Draft for a while longer so I can flush out e.g. behavioral inconsistencies. I'm happy to squash this branch down to "tell the story" if iterating through commits like this is too noisy, just let me know. 👍 Edit to clarify using the Draft state, i.e. when out of Draft I consider this ready. |
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.
Hello! 👋
I recently discovered MSM while looking for tooling to run Minecraft worlds from RAM. The RAM disk feature was exactly what I needed, but I also needed Fabric mod loader support, which MSM doesn't currently have. Rather than extending the bash scripts, I chose to reimplement MSM in Go — partly because that's where I'm more comfortable, and partly because I wanted static typing and easier testing for the features I was adding.
I want to be upfront: I have no expectation that you'll want this merged. Rewriting a project in a different language is a big decision with maintenance implications, not the least of which is the ~6.5K lines of Go (~2.4K tests, ~2.2K docs) vs. the ~4K lines of shell script. I completely understand if bash is the right choice for MSM's future. I'm happy maintaining my own fork for my own personal use if this isn't a direction you want to take.
New features:
What's preserved:
What would change:
If you're interested, I'm happy to discuss or make adjustments. If not, no hard feelings!