Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- Download stable/beta versions at the [AutoPlug-Releases](https://github.com/Osiris-Team/AutoPlug-Releases) repo.
- Follow the [AutoPlug-Client-Development](https://bit.ly/acprogress) and see what we are currently working on.
- [Native client dashboard, server browser and launcher](./docs/native-client-dashboard.md), including isolated [MODS/PLUGINS profiles](./docs/unified-profiles.md), CLI commands and verification limits.
- Support the development by [donating](https://www.paypal.com/donate?hosted_button_id=JNXQCWF2TF9W4).
- Issues or questions? Checkout the [FAQ](/docs/FAQ.md) and/or join our [Discord](https://discord.com/invite/GGNmtCC), for live chat/voice
support.
Expand Down
81 changes: 81 additions & 0 deletions docs/native-client-dashboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Native client dashboard and unified profiles

This implementation starts from AutoPlug 10.2.0 master and keeps AutoPlug's MIT license. No HMCL or other launcher source is imported. Minecraft and loader artifacts are downloaded from their published distribution endpoints into the end user's cache; they are not bundled with AutoPlug or this contribution.

## Dashboard

Click the tray icon to open the resizable FlatLaf dashboard. The application also opens its window when a desktop has no system tray. The five views are Server Browser, Singleplayer, Profiles, Server Manager and Settings. Server Manager retains the existing update/configuration panels, adds console output, and dispatches start, restart, stop, backup, task and server-console commands through the existing server services. Closing the window hides it; disabling/recreating the dashboard releases its console listener, cancels that window's pending account sign-in and releases the world view's refresh timer.

Server Browser uses the existing `MineStat` JSON status implementation, with a bounded response and read timeout. It displays MOTD, version/protocol, online/max players and status-query latency. Add or edit a server's **local loader choice** explicitly: vanilla status does not expose a server's required mods or loader. Proxy advertisements containing multiple versions require selecting a profile explicitly rather than guessing.

The dashboard automatically imports vanilla `servers.dat` when the default file exists, without pinging servers or modifying that file. Import adds addresses without overwriting an existing AutoPlug loader choice. Export is optional and user initiated. It replaces the chosen vanilla list, retains unknown root tags and retained servers' icons/settings, checks for changes during preparation and saves a uniquely named backup first. Close Minecraft before exporting to avoid concurrent edits by the game. Default paths cover Windows AppData, macOS Application Support and Linux `.minecraft`. NBT supports all standard tag types, raw and gzip streams, with byte, nesting and collection limits. Unicode strings use Java's NBT modified UTF encoding.

Profiles supports client MODS, server PLUGINS and server MODS_SERVER collections. Create, clone/migrate, delete, mark templates, select default update profiles, check/apply updates and launch client profiles. Each profile lives in `~/.autoplug/instances/<id>`; mutable configuration is copied, while JARs use the shared checksum cache. Server profiles cannot be launched as Minecraft clients. See [unified-profiles.md](unified-profiles.md) for update sources, explicit source identities, transaction/recovery behavior and provider limits.

Singleplayer creates virtual worlds from server profiles, with independent save/config directories, a thumbnail and play/share actions. After an explicit per-world Minecraft EULA choice, it prepares an official Paper/Purpur/Fabric server (or an explicitly supplied matching executable JAR), waits for its MineStat status ping, and launches a matching client at the local port. Closing the client stops its server gracefully. Server-mod worlds require an explicitly matching client profile rather than copying server-only mods into the client. See [the world protocol and lifecycle documentation](../src/main/java/com/osiris/autoplug/client/worlds/PROTOCOL.md) for supported server installation paths and cleanup behavior.

Play & share is an explicit request for a temporary TCP UPnP lease; ordinary local play binds only to loopback. Copy join address reads an existing mapping and never opens a port itself. Router discovery, SOAP control, finite-lease renewal and ownership checks are implemented without new dependencies. Existing mappings are not overwritten, and only an owned mapping can be deleted. A discovery, public-IP/CGNAT or mapping failure retains local play and gives forwarding/tunnel guidance. Lease renewal and explicit Stop cleanup failures remain visible. No real router was configured during contributor tests.

Play first checks the saved server. It selects a matching non-template client profile by exact Minecraft version and the saved local loader. Otherwise it requests confirmation to clone an appropriate client template, resolves releases for the target version using AutoPlug's update services, shows the complete plan, and applies it only after confirmation. Files with no compatible release become `.jar.disabled`. Network/provider errors stop the operation. A declined or failed new clone is removed; the source template remains intact.

Settings selects the default template, optional Java executables, offline/Microsoft account mode, a preferred world port (0 selects an available port) and whether explicit sharing may use UPnP. Invalid preferences do not partially change an account or persisted settings. When no Java path is configured, the launcher selects the major declared in Mojang metadata using AutoPlug's Adoptium API protocol and SHA-256 checked runtime downloads. Overrides are checked with `java -version` before use, including when an installer needs Java. Java 8, 17, 21 and the current Minecraft 26.3 Java 25 requirement are supported.

## Authentication

Offline mode is for local testing and offline-capable servers. It does not provide authentication to online-mode servers. Microsoft mode uses an end-user-initiated OAuth device flow, Xbox Live, XSTS, Minecraft entitlement and profile checks. Configure your own registered Microsoft public-client application ID; Minecraft Services may require application approval. The UI displays the verification URI and user code so the account owner can sign in in their browser. No password is collected. Account access and refresh tokens remain in memory; no token appears in preferences or command logs. Sign-out invalidates pending sign-in attempts. Restarting AutoPlug requires signing in again.

## CLI

The same commands work in the running AutoPlug console and as one-shot startup arguments. Client/profile-only startup commands return without starting the server, recurring tasks, SSH or the online console. Periods in versions and hostnames are preserved. Separate multiple commands by another dot-prefixed command token.

```text
java -jar AutoPlug-Client.jar ".profiles create survival 1.20.4 fabric"
java -jar AutoPlug-Client.jar ".profiles create hub 1.20.4 paper --type plugins"
java -jar AutoPlug-Client.jar ".profiles create servermods 1.20.4 fabric --type mods-server"
java -jar AutoPlug-Client.jar ".profiles list --type mods"
java -jar AutoPlug-Client.jar ".profiles activate survival"
java -jar AutoPlug-Client.jar ".check mods"
java -jar AutoPlug-Client.jar ".update mods --profile survival --confirm-disabling"
java -jar AutoPlug-Client.jar ".profiles clone survival 1.21.1 --confirm-disabling"
java -jar AutoPlug-Client.jar ".client launch survival --server play.example.org:25566"
java -jar AutoPlug-Client.jar ".client servers list"
java -jar AutoPlug-Client.jar ".mc worlds create Workshop hub"
java -jar AutoPlug-Client.jar ".mc worlds list"
# After reviewing the Minecraft EULA, explicitly accept for this world:
java -jar AutoPlug-Client.jar ".mc worlds accept-eula workshop"
java -jar AutoPlug-Client.jar ".mc worlds launch workshop"
# Sharing additionally requires online Microsoft authentication in the same process:
.mc worlds launch workshop --share
```

Default MODS, PLUGINS and MODS_SERVER update profiles are selected independently using `.profiles activate <id>` or the profile view's default-updates button. `.check/.update mods|plugins|mods-server [--profile <id>]` uses that type's active profile when the flag is omitted. Without an active profile, interactive `.check mods/plugins` retains the existing current-directory server behavior; one-shot checks, server-mod checks and `.update` request an explicit profile selection. They do not invent or mutate a current server profile. Deleting an active profile clears its default selection.

Additional commands: `.profiles template <id> true|false`, `.profiles delete <id>`, `.client servers import|export`, `.client auth offline <name>`, `.client auth microsoft <registered-client-id>` and `.client auth signout`. Preferences persist but authentication sessions do not. A one-shot Microsoft auth command ends its session on process exit; use the running console/UI to sign in and then launch in the same process, or supply both commands in one invocation.

## Launch protocols and verification

Mojang version manifests determine client, libraries, assets, native libraries, logging config and Java major. Fabric/Quilt use official loader profile APIs. Forge/NeoForge use their official installers, embedded Maven artifacts and declared client processors, with processor output checks and separate installer working directories. The native engine handles OS/rules, argument substitution and classpaths without using a shell. Direct join uses legacy `--server/--port` before Minecraft 1.20 and the official `--quickPlayMultiplayer` flow from 1.20 onward (introduced in 23w14a).

The contribution contains comprehensive unit/fixture tests plus explicit opt-in public-API probes. `OfflineClientLaunchTest` prepares and starts an original compiled fixture client through the actual `NativeLauncher` and `ProcessBuilder` paths. World lifecycle tests start original dedicated-server/client child JVMs and use the existing MineStat wire protocol. UPnP tests exercise SOAP against an original localhost HTTP fixture, including mapping ownership, renewal and cleanup. These prove the execution paths without claiming that Minecraft was launched or a real router was mapped. `DashboardLayoutTest` renders the actual four client Swing panels at two sizes offscreen; it excludes the server-manager view and is not native desktop/tray acceptance. Real Forge/NeoForge metadata is checked, but fixture processors execute original test code. The actual installers have not been run against the real Minecraft JAR. Final Microsoft-authenticated game joining, public-world connectivity and desktop acceptance require the maintainers' real game/router environment.

Run the deterministic contribution suites on a JDK with Maven:

```text
mvn test -Djava.awt.headless=true -Dtest=NativeLauncherTest,MicrosoftOAuthTest,LoaderInstallerTest,ManagedJavaRuntimeTest,OfflineClientLaunchTest,LauncherCancellationTest,UnifiedProfilesTest,ProfileProviderTest,ServerModProfilesTest,ServerBrowserTest,NativeClientServiceTest,DashboardLayoutTest,WorldStoreTest,WorldServerPreparerTest,VirtualWorldServiceTest,UpnpPortMapperTest,UtilsEnvironmentTest,UtilsStringTest,UtilsFileTest,UtilsMapTest
```

The inherited repository also has live-network/download tests (Google reachability, SteamCMD and server/provider downloads). The command above selects the deterministic contribution and related utility suites explicitly rather than claiming those external integrations were exercised offline. Public metadata probes are separate opt-in programs and never use an owner account.

Primary protocol references:

- [Official Mojang manifest](https://piston-meta.mojang.com/mc/game/version_manifest_v2.json)
- [Minecraft 23w14a Quick Play changes](https://www.minecraft.net/en-us/article/minecraft-snapshot-23w14a)
- [Fabric Meta](https://meta.fabricmc.net/)
- [Quilt Meta](https://meta.quiltmc.org/)
- [NeoForge version format and Java 25](https://neoforged.net/news/26.1release/)
- [Microsoft device authorization](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-device-code)
- [NBT author's format/reader reference](https://github.com/Querz/NBT)
- [UPnP WANIPConnection service](https://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v1-Service.pdf)
- [UPnP device discovery architecture](https://openconnectivity.org/upnp-specs/UPnP-arch-DeviceArchitecture-v2.0-20200417.pdf)

Fixture metadata sources and published archive hashes are recorded in `src/test/resources/native-launcher/sources.json` and `src/test/resources/virtual-worlds/sources.json`. New implementation and verification were performed by AI coding agents, including direct source review and actual test execution; no separate human technical review or live account test is claimed.
75 changes: 75 additions & 0 deletions docs/unified-profiles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Unified client/server profiles

Profiles are stored under `~/.autoplug/profiles` with independent instances under
`~/.autoplug/instances/<id>`. A profile records its id, `MODS` (client), `PLUGINS`
(server plugins), or `MODS_SERVER` (server mods) type, game version, loader and
template status. Client and server mods live in the instance's `mods` directory;
plugins live in `plugins`. Each of the three types has its own independent active
default for update commands. `mods-server` and `mods_server` are supported CLI
aliases for `MODS_SERVER`. Changes never replace the global server updater
configuration or change the process working directory.

Examples:

```text
.profiles create fabric-base 1.20.1 fabric --template
.profiles create paper-base 1.20.1 paper --type plugins --template
.profiles create fabric-server 1.20.1 fabric --type mods-server
.profiles activate fabric-server
.check mods-server
.update mods-server
.profiles list --type plugins
.profiles clone fabric-base 1.21.1 fabric-new
.check mods --profile fabric-new
.update mods --profile fabric-new
.profiles template fabric-new true
.profiles delete fabric-new
```

Clone copies mutable settings and imports jars into the shared content-addressed
cache. It then checks the target release set, including downgrades, required
dependencies and incompatible projects. Unavailable/unknown artifacts appear in
the review summary. CLI migration that would disable them requires
`--confirm-disabling`; without it, an unsuccessful new clone is removed and the
source is preserved. The dashboard presents the same review before applying.

Network or malformed-response failures are errors, not compatibility results.
They stop the entire update and preserve the instance. Artifacts are staged and
their provider hashes and jar format verified before replacement. Original
hashes are checked before and after staging. Per-profile locks, original-file
backups and a journal support rollback and recovery of an interrupted prepared
transaction. Names and paths are checked before installing or deleting files.

Modrinth lookup identifies exact local bytes and resolves releases for the
explicit Minecraft version and loader. Required dependencies are included and
pinned dependency versions are validated. Plugin loader compatibility is
explicit: Bukkit and Spigot profiles do not accept Paper-only artifacts.

Explicit provider project IDs can be recorded in the instance's
`asset-sources.properties` when an artifact is not identifiable by Modrinth hash:

```properties
some-mod.jar.modrinth=project-id-or-slug
another-mod.jar.curseforge=12345
plugin.jar.spigot=12345
worldedit.jar.bukkit=31043
```

Successful migrations preserve provider identities under their new filenames.
CurseForge resolution reuses AutoPlug's configured API client; unavailable keys,
missing authorized download URLs or transport errors stop the migration.
CurseForge loader/game filters, pagination and declared file metadata are checked.
Bukkit files are selected by declared Minecraft version and their supplied MD5
is verified. Spiget only exposes tested versions for its current resource; the
updater does not invent historical version compatibility. If that current
resource does not declare support, the artifact needs explicit disabling or a
separately configured compatible project.

`UnifiedProfilesTest` exercises isolation, clone migration, explicit disabling,
re-enabling, dependency installation, collisions, changed files, failed downloads,
checksums, cache corruption and transaction recovery. `ProfileProviderTest`
uses real local HTTP sockets for transport failures and exercises target-loader
selection and resource-service reuse. `ProfileProviderLiveSmoke` is an opt-in
main class for actual public Modrinth/Bukkit metadata GETs. It downloads no jars,
uses no account and launches no Minecraft process. Live Microsoft-authenticated
launch/join acceptance remains with maintainers, as specified for the bounty.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@ AUTO-GENERATED FILE, CHANGES SHOULD BE DONE IN ./JPM.java or ./src/main/java//JP
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/JPM.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public ThisProject(List<String> args) throws Exception {

// Add custom plugins
plugins.add(new AutoPlugPropertiesPlugin());
// Explicit Jupiter provider: Maven's inherited Surefire version may silently skip JUnit 5.
plugins.add(new JPM.Plugin("org.apache.maven.plugins", "maven-surefire-plugin", "3.6.0"));

// Execute build
File cwd = new File(System.getProperty("user.dir"));
Expand Down
16 changes: 4 additions & 12 deletions src/main/java/com/osiris/autoplug/client/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public static void main(String[] _args) {
List<String> args = new ArrayList<>();
if (_args != null)
Collections.addAll(args, _args);
if (com.osiris.autoplug.client.clientapp.StartupCommands.executeClientOnly(args, System.out::println)) return;
// Check various things to ensure an fully functioning application.
// If one of these checks fails this application is stopped.
long now = System.currentTimeMillis();
Expand Down Expand Up @@ -268,8 +269,8 @@ public static void main(String[] _args) {
try {
if (generalConfig.autoplug_system_tray.asBoolean()) {
now = System.currentTimeMillis();
new MainWindow(generalConfig);
AL.info("Started system-tray GUI, took " + (System.currentTimeMillis() - now) + "ms");
MainWindow.open(generalConfig);
AL.info("Scheduled client dashboard on the Swing event thread");
}
} catch (Exception e) {
AL.warn(e);
Expand Down Expand Up @@ -312,16 +313,7 @@ public static void main(String[] _args) {
Server.start();

// Execute arguments as commands if existing
String argsString = "";
for (String arg : args) {
argsString += arg + " ";
}
if (argsString.contains(".")) {
String[] commands = argsString.split("\\."); // Split by dots
for (String c : commands) {
Commands.execute("." + c);
}
}
for (String startupCommand : com.osiris.autoplug.client.clientapp.StartupCommands.parse(args)) Commands.execute(startupCommand);

// We have to keep this main Thread running.
// If we don't, the NonBlockingPipedInputStream stops working
Expand Down
Loading