mgctl, lo strumento Moongate
mgctl è l’unico strumento distribuito accanto a mgserver, il server, negli archivi delle versioni e nelle immagini
Docker; l’installatore Linux lo collega come comando mgctl. Le versioni fino a 0.11 chiamavano il server Moongate.Server. Le versioni da 0.7 a 0.11 chiamavano lo strumento
mgboot, che preparava solo la directory radice, e distribuivano le migrazioni e il convertitore come altri due
eseguibili, migration-runner/Moongate.MigrationRunner e mg-uoxconv; in quel caso, leggi
mgboot <root> al posto di mgctl init <root>.
| Comando | Cosa fa |
|---|---|
mgctl init <root> |
Prepara la directory radice del server; questa pagina. mgctl <root> fa lo stesso |
mgctl migrate status|apply --target auth|world |
Elenca o applica l’SQL versionato; vedi Migrazioni della persistenza |
mgctl plugin install|list|remove |
Installa, elenca o rimuove i pacchetti dei plugin; vedi Installare un pacchetto plugin |
mgctl run |
Esegue il server e lo riavvia dopo un restart o un crash; vedi Eseguire il server |
mgctl completion bash|zsh|fish |
Stampa lo script che completa mgctl con TAB; vedi Completamento con TAB |
mgctl --help elenca i comandi e mgctl <command> --help le opzioni di uno di essi.
I convertitori di dati (UOX3 e ModernUO) non fanno più parte di mgctl: sono uno strumento Python, moongate-convert; vedi Migrare da UOX3.
Completamento con TAB
Section titled “Completamento con TAB”mgctl completion <shell> stampa uno script di completamento per bash, zsh o fish. Con esso, TAB
completa i comandi (mgctl mi → migrate), la seconda parola di migrate,
le opzioni del comando e ciò che le segue: directory dopo --root-directory e
simili, auth o world dopo --target, e una directory per
la radice di init.
L’installatore Linux colloca gli script dove le shell li cercano, quindi una nuova shell completa mgctl senza altre operazioni. Altrove, caricalo personalmente:
eval "$(mgctl completion bash)" # bash: add the line to ~/.bashrcsource <(mgctl completion zsh) # zsh: add the line to ~/.zshrc, after compinitmgctl completion fish | source # fish: or save it as ~/.config/fish/completions/mgctl.fishLa riga bash usa eval perché bash 3.2 di macOS non carica nulla da
source <(...); lì, un percorso con uno spazio viene completato senza le relative virgolette.
Lo script fish è generato dallo stesso elenco di comandi degli altri due ma, a differenza di essi, non viene esercitato dai test.
Installare un pacchetto plugin
Section titled “Installare un pacchetto plugin”Un plugin pubblicato come pacchetto .nupkg, come quelli di
moongate-plugins, si installa con
mgctl plugin, senza decomprimerlo a mano. La guida per chi gestisce uno shard, con configurazione,
aggiornamento e rimozione, è Installare e gestire i plugin; questa sezione elenca
cosa controllano i comandi. Ferma prima il server: legge plugins/ una sola volta,
all’avvio.
mgctl plugin install Moongate.Plugins.OpenAi --root-directory /srv/moongatemgctl plugin install MyPlugin --repo myuser/my-plugins --root-directory /srv/moongatemgctl plugin install ./Moongate.Plugins.OpenAi.0.2.1.nupkg --root-directory /srv/moongatemgctl plugin install https://codeberg.org/moongate/moongate-plugins/releases/download/Moongate.Plugins.OpenAi-v0.2.1/Moongate.Plugins.OpenAi.0.2.1.nupkgmgctl plugin list --root-directory /srv/moongatemgctl plugin remove Moongate.Plugins.OpenAi --root-directory /srv/moongateinstall accetta un file di pacchetto, un indirizzo https (uno http semplice viene rifiutato,
tranne per questa macchina, e un reindirizzamento deve rispettare la stessa regola) o un id di plugin,
che cerca in un repository: vedi Installare per id da un repository.
Esegue questi passi in ordine e si ferma al primo che fallisce, lasciando il plugin installato com’era:
- Legge il nuspec: il tipo del pacchetto deve essere
MoongatePlugine l’id un semplice nome di cartella (lettere, cifre e.,-,_tra di esse; niente nomi di dispositivo comeCON). - Controlla la dipendenza esatta da
Moongate.Server.CoreoMoongate.Hosting(un plugin può nominare l’uno, l’altro o entrambi, alla stessa versione): deve essere la versione di questomgctl, cioè quella del server accanto a lui. Un plugin compilato per un’altra versione viene rifiutato qui, prima che possa fallire il caricamento all’avvio. - Controlla il bundle: al massimo 1000 file, nessuna voce che esce dalla cartella del bundle, e
i file
<id>.dlle<id>.deps.jsonche servono al loader. - Mostra l’id, la versione, la versione di Moongate per cui è stato compilato e lo SHA-256 del
pacchetto, e chiede
Install it? [y/N].--yessalta la domanda. Un plugin gira dentro il server con tutti i suoi permessi: installalo solo da una fonte di cui ti fidi. - Decomprime solo la cartella
plugin/del pacchetto, al massimo 100 MB, in una cartella di lavoro dentroplugins/il cui nome inizia con un punto, poi sostituisce<root>/plugins/<id>/con essa. Installare una versione più recente sopra una più vecchia è il modo di aggiornare un plugin; il nuspec resta nella cartella.
Una cartella di lavoro lasciata da un’installazione interrotta viene ignorata dal server e cancellata
dall’installazione successiva; una -old contiene il bundle che si stava sostituendo, e l’installazione
dice dov’è.
list mostra ogni cartella di plugins/ che non inizia con un punto, con la sua versione, la versione di Moongate per cui è stata
compilata e da dove viene: package per un’installazione di mgctl, by hand per un bundle copiato
a mano, la cui versione è letta dal suo assembly. remove <id> cancella la cartella. Le tabelle del
database del plugin restano: le migrazioni vanno solo avanti, quindi eliminale tu se vuoi che spariscano.
La radice viene da --root-directory, poi da MOONGATE_ROOT, poi dalla directory di mgctl,
come per migrate; deve contenere config/moongate.toml, così un percorso sbagliato viene rifiutato invece
di ricevere una cartella plugins/. Nulla viene installato o cambiato per conto del server: non c’è aggiornamento
automatico; il plugin e il repository sono quelli che indichi tu.
Installare per id da un repository
Section titled “Installare per id da un repository”Con un id di plugin al posto di un file, install cerca il plugin in un repository e installa la
build più recente fatta per la versione di Moongate di questo mgctl. Un argomento che finisce
con .nupkg, indica un file esistente o inizia con http:// o https:// è un pacchetto, non un id;
qualunque altra cosa che sia un id valido viene cercata, quindi un nome di file scritto male viene
cercato nel repository.
mgctl plugin install Moongate.Plugins.OpenAi # the community repositorymgctl plugin install MyPlugin --repo myuser/my-plugins # releases of a Codeberg repositorymgctl plugin install MyPlugin --repo https://codeberg.org/myuser/my-plugins # the same, as an addressmgctl plugin install MyPlugin --repo https://github.com/myuser/my-plugins # releases of a GitHub repositorymgctl plugin install MyPlugin --repo ./my-packages # a folder of .nupkg filesmgctl plugin install MyPlugin --repo myuser/my-plugins --version 1.2.0 # an exact version--repo |
Dove cerca |
|---|---|
| assente | moongate/moongate-plugins |
| una cartella | i file <id>.<version>.nupkg che contiene; una cartella scritta come owner/name vuole ./ davanti, altrimenti è presa per un repository Codeberg |
owner/name (sempre su Codeberg), https://codeberg.org/owner/name o https://github.com/owner/name |
le release pubblicate (le 500 più recenti), per gli asset chiamati <id>.<version>.nupkg (il nome che dà dotnet pack); il tag non conta |
- Le versioni si provano dalla più recente, e vince la prima il cui pacchetto dice di essere fatto per questo Moongate; si aprono al massimo le 10 più recenti, e la risposta lo dice se ce ne sono di più. Se nessuna lo è, il comando elenca le versioni trovate e il Moongate per cui è fatta ciascuna. Un pacchetto il cui nuspec nomina un altro id o un’altra versione rispetto al nome del file viene saltato.
- Le prerelease (
2.0.0-beta.1, e le release segnate come prerelease) e le bozze non vengono mai scelte da sole.--versionindica una versione, anche una prerelease, e viene rifiutata come un file se è fatta per un altro Moongate. --repoe--versionvanno solo con un id; con un file o un indirizzo vengono rifiutati.- La richiesta di conferma mostra host e repository accanto a id, versione e SHA-256. Un repository è affidabile quanto il suo proprietario: i controlli qui sopra non rendono sicuro un plugin.
CODEBERG_TOKEN(oGITHUB_TOKENper un repository su GitHub), dall’ambiente e mai dalla riga di comando, raggiunge un repository privato e alza il limite dell’API. Va solo all’host dell’API, mai all’host a cui un download reindirizza, e un indirizzo di asset fuori dall’origine dell’API viene ignorato finché c’è un token.MGCTL_RELEASES_API_URLindirizzamgctla un’altra API delle release, come un mirror o un’altra istanza Forgejo; sostituisce l’API dell’host su cui sta il repository, e il token di quell’host la segue.
Eseguire il server
Section titled “Eseguire il server”mgctl run avvia mgserver come processo figlio e lo tiene attivo:
mgctl run --root-directory ~/moongatemgctl run --root-directory ~/moongate --log-level Debug| Il server esce con | mgctl run |
|---|---|
0 (uno shutdown, Ctrl+C) |
esce con 0 |
75 (un restart) |
lo riavvia subito |
| qualsiasi altro codice | lo riavvia dopo 1, 2, 4… fino a 30 secondi |
Cinque fallimenti di fila, ciascuno entro 60 secondi dal proprio avvio, terminano il launcher con exit code 1, così una configurazione sbagliata non può andare in loop all’infinito; un’esecuzione che dura un minuto è sana e azzera il conteggio.
| Opzione | Significato |
|---|---|
--root-directory <path> |
La radice del server; MOONGATE_ROOT se assente. Viene data anche al server |
--no-init |
Non esegue mgctl init sulla radice prima di ogni avvio |
--server-path <file> |
Il mgserver da eseguire; di default quello accanto a mgctl |
--restart-delay <seconds> |
La prima attesa dopo un crash, da 0 a 30 (default 1) |
Tutto il resto della riga, con o senza un -- davanti, va a mgserver invariato.
Prima di ogni avvio il launcher prepara la radice come fa mgctl init, così un riavvio raccoglie i file di dati che una
nuova build porta; non stampa nulla quando funziona e ciò che init ha detto quando fallisce. Il server tiene il tuo terminale: prompt, completamento con TAB e cronologia funzionano come senza il
launcher.
Arresto. Ctrl+C raggiunge il server attraverso il terminale e il launcher termina con lui. Un SIGTERM o SIGHUP
inviato al solo launcher (docker stop, kill, systemd con KillMode=mixed) viene passato al server una sola volta, e
il launcher lo aspetta: il salvataggio finale di un mondo grande può durare uno o due minuti, e un arresto non viene
mai riavviato, qualunque cosa risponda il server. Il launcher termina con l’ultimo exit code del server. Un terminale
che si chiude manda SIGHUP anche al server, che non lo gestisce: chiudi la sessione con uno shutdown, non chiudendo
la finestra. Su Windows nulla viene inoltrato; la console consegna Ctrl+C a entrambi i processi.
Preparare la directory radice del server
Section titled “Preparare la directory radice del server”mgctl init prepara una directory dati Moongate senza avviare il server né connettersi
a PostgreSQL. È il passo 1 della sequenza del primo avvio.
mgctl init /absolute/path/to/moongate-dataLa directory radice è l’unico argomento posizionale obbligatorio. I percorsi relativi vengono risolti dalla directory di lavoro corrente. Racchiudi tra virgolette i percorsi contenenti spazi:
mgctl init "/srv/my realm"mgctl init --helpmgctl <root>, senza init, è la forma precedente e funziona ancora per una radice scritta come
percorso (/srv/moongate, ./data) o che indica una directory esistente; un nuovo nome semplice come
mgctl data viene rifiutato, così un comando scritto male non diventa mai una directory radice. Una riga di comando
che non indica alcun comando, come mgctl migrate da solo, termina con codice 2.
Su Windows, usa mgctl.exe init C:\MoongateData dalla distribuzione estratta.
Mantieni insieme mgctl e mgserver della stessa versione.
Quando prepara una directory radice, mgctl mostra la stessa intestazione Moongate, versione e nome in codice
del server, seguiti da Root setup. L’output di aiuto e versione omette l’intestazione, così come
mgctl init <root> --no-header: scripts/run_server.sh lo usa perché il server che avvia
subito dopo mostra già l’intestazione.
Generare un certificato di amministrazione
Section titled “Generare un certificato di amministrazione”mgctl init /srv/moongate --generate-admin-certificate \ --admin-certificate-hosts "login.example.test,192.0.2.10"La CLI usa ConsoleAppFramework. --generate-admin-certificate è un flag opzionale
attivato dalla sua presenza. --admin-certificate-hosts è un’unica stringa separata da virgole e
richiede quel flag. Ometti l’opzione degli host per lo sviluppo locale: ogni certificato
include automaticamente localhost, 127.0.0.1 e ::1. Le voci aggiuntive devono
essere nomi DNS o indirizzi IP, senza schemi URL, porte o indirizzi jolly.
Usa i nomi a cui si connettono i client; *, 0.0.0.0 e :: sono indirizzi di ascolto,
non identità del certificato.
L’operazione viene eseguita offline e crea un certificato server RSA autofirmato valido per un anno. Scrive questi file sotto la directory radice:
| File | Contenuto |
|---|---|
certificates/admin.pfx |
Certificato server e chiave privata; nessuna password; lettura/scrittura solo per il proprietario su Unix |
certificates/admin.crt |
Certificato PEM pubblico da considerare attendibile nei client di amministrazione |
Aggiorna queste quattro impostazioni in config/moongate.toml:
[admin_api]enabled = trueallow_insecure_loopback = falsecertificate_path = "certificates/admin.pfx"certificate_password = ""La porta esistente, l’indirizzo di ascolto, le altre impostazioni e i commenti vengono conservati.
Una sezione mancante viene aggiunta; le definizioni admin_api esistenti inline o con chiavi puntate devono
prima essere convertite in una sezione [admin_api] esplicita. Un percorso di certificato personalizzato
non viene mai sostituito implicitamente: cancella esplicitamente quell’impostazione solo se intendi
cambiare identità.
Nessuna porta viene aperta durante la configurazione. L’API parte al successivo avvio normale del server.
L’indirizzo di ascolto predefinito rimane 127.0.0.1:2590; per l’accesso dalla rete privata, configura
un’interfaccia raggiungibile o listen_address = "*" e includi il DNS/IP effettivamente usato dai client
negli host del certificato. Vedi API di amministrazione.
Eseguire di nuovo lo stesso comando riusa una coppia di certificati corrispondenti e non scaduti. Fallisce
senza sovrascrivere la coppia se uno dei file è mancante, non valido, scaduto,
non corrispondente o privo di un nome richiesto. Non esiste rinnovo o rotazione implicita.
Per una sostituzione deliberata, arresta il server, sposta entrambi i file di certificato esistenti
in una posizione di backup protetta, esegui di nuovo la generazione e aggiorna la fiducia dei client prima
di riavviare. Un PFX senza password contiene comunque la chiave privata: conservalo sul server
e limita l’accesso. Su Windows, usa un’ACL appropriata per l’account di servizio.
Distribuisci solo admin.crt; i client devono verificare attendibilità e nome host.
Cosa crea
Section titled “Cosa crea”| Percorso sotto la directory radice | Scopo |
|---|---|
config/moongate.toml |
Valori predefiniti attuali del server serializzati come TOML snake_case; le sezioni dei plugin come [ultima] vengono aggiunte al primo avvio del server |
logs/, plugins/ |
Directory standard del server |
migrations/auth/ |
I file SQL auth principali inclusi nella distribuzione |
migrations/world/ |
Il file SQL World principale incluso nella distribuzione: le tabelle di mobile, oggetti, stato del mondo, prigione, bacheca, allegati dei libri, pagine di aiuto e gilde |
data/ |
I file di dati dello shard inclusi nella distribuzione: mappe, regioni, razze, abilità, messaggi e il resto; vedi File di dati dello shard |
templates/ |
I template di oggetti, bottino, mobile, libri, negozi e altri inclusi nella distribuzione; vedi Template |
scripts/ |
Gli script di esempio per mobile e oggetti inclusi nella distribuzione: gli script mobiles/ e items/ (per esempio mobiles/wander.lua e items/potion.lua) con i moduli condivisi common/ e gli script events/, gumps/ e skills/; il motore scrive qui definitions.lua e .luarc.json all’avvio |
.mgctl.lock |
File conservato per impedire inizializzazioni simultanee |
La nuova configurazione imposta persistence.migrations_directory al percorso assoluto migrations
dentro questa directory radice. Anche il normale avvio del server usa <root>/migrations per impostazione predefinita
quando l’impostazione è assente; mantenere il percorso esplicito fa usare a
mgctl migrate lo stesso catalogo. Gli altri valori rimangono quelli predefiniti del server: generazione automatica delle migrazioni
e sincronizzazione automatica dello schema sono disabilitate. Le credenziali Redis di runtime
devono essere fornite prima di avviare il server.
La directory radice non richiede accesso ai database né file del client Ultima Online per essere preparata.
File di dati, template e script vengono copiati solo se mancanti, quindi un file modificato
rimane com’è. Esegui di nuovo mgctl init dopo un aggiornamento per aggiungere i file introdotti da una nuova
versione; un file esistente nella directory radice non viene mai sostituito, quindi confrontalo con
quello accanto al nuovo binario mgserver (data/, templates/, scripts/) per integrare
le modifiche a monte. Non viene rimosso nulla: un template rinominato o spostato da una versione
rimane nella directory radice accanto alla sua nuova copia e il server si arresta all’avvio per
l’id duplicato, quindi elimina il file obsoleto. Un file distribuito che hai eliminato ritorna alla
successiva esecuzione; svuotalo invece per mantenerlo escluso.
La preparazione delle migrazioni di base copia l’SQL versionato distribuito con Moongate. Non genera nuovo SQL dalle entità, non carica plugin, non crea database e non applica migrazioni. Usa gli strumenti di persistenza per le modifiche alle entità dopo l’inizializzazione.
Directory esistenti
Section titled “Directory esistenti”Eseguire di nuovo il comando senza opzioni di certificato conserva la configurazione e i file esistenti. Le migrazioni distribuite mancanti vengono aggiunte solo quando il catalogo esistente è compatibile. Una migrazione esistente con lo stesso numero di sequenza ma un nome di file o checksum diverso interrompe l’inizializzazione prima che vengano scritti la configurazione o i file SQL. L’errore identifica il file in conflitto. Non eliminare la cronologia delle migrazioni per aggirarlo; riconcilia il catalogo o scegli una nuova directory radice.
Senza --generate-admin-certificate, una configurazione esistente non viene mai riscritta, compresa l’impostazione della directory delle migrazioni.
Controlla personalmente l’impostazione se punta fuori da questa directory radice. Se sposti la directory radice,
aggiorna di conseguenza il percorso assoluto in una configurazione appena generata.
Passi successivi
Section titled “Passi successivi”Prosegui con Avviare un server Moongate: modifica la
configurazione generata, crea i database PostgreSQL, applica l’SQL distribuito con
mgctl migrate apply e avvia il server. Per lo sviluppo, puoi invece abilitare
persistence.auto_generate_migrations dopo aver preparato i database; vedi il
tutorial sulle entità.
Docker
Section titled “Docker”Per un’immagine di una versione:
docker volume create moongate-datadocker run --rm --entrypoint /app/mgctl \ --mount type=volume,source=moongate-data,target=/data \ docker.io/tgiachi/moongate:latest init /dataLe immagini fino a 0.11.0 hanno invece /app/mgboot: usa --entrypoint /app/mgboot e passa
solo /data. L’inizializzazione termina dopo aver preparato la directory radice montata; non apre alcun listener
TCP.
Compilare dai sorgenti
Section titled “Compilare dai sorgenti”Pubblica server e strumento nella stessa directory:
dotnet publish src/Moongate.Server -c Release -r linux-x64 -o dist/moongatedotnet publish src/Moongate.Ctl -c Release -r linux-x64 -o dist/moongate./dist/moongate/mgctl init /absolute/path/to/moongate-dataCambia l’identificatore di runtime per la tua piattaforma. Il server espone inoltre la stessa operazione offline per lo sviluppo dai sorgenti:
dotnet run --project src/Moongate.Server -- --initialize-root --root-directory /absolute/path/to/moongate-dataLe stesse opzioni di certificato funzionano con l’operazione offline del server:
dotnet run --project src/Moongate.Server -- --initialize-root \ --root-directory /srv/moongate --generate-admin-certificate \ --admin-certificate-hosts "login.example.test,192.0.2.10"Il server rifiuta le opzioni di certificato al di fuori di --initialize-root.
MOONGATE_SERVER_EXECUTABLE può sostituire l’eseguibile del server adiacente per i
test locali degli strumenti. Deve riferirsi a un eseguibile compatibile della stessa versione dei sorgenti.
Creato con ❤️ da Tom
