Skip to content
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

Version 4.1.0 #184

Merged
merged 16 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 15 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 .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
github: mindstorm38
ko_fi: theorozier
51 changes: 30 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ It also includes fast installation of common mod loaders such as Fabric, Forge a
- [Commands](#commands)
- [Start Minecraft](#start-minecraft)
- [Authentication](#authentication)
- [Offline mode](#offline-mode)
- [Username and UUID](#username-and-uuid)
- [Custom JVM](#custom-jvm)
- [Server auto-connect](#server-auto-connect)
- [LWJGL version and ARM support](#lwjgl-version-and-arm-support)
- [Fix unsupported systems](#fix-unsupported-systems)
- [Miscellaneous](#miscellaneous)
- [Search for versions](#search-for-versions)
- [Authentication sessions](#authentication-sessions)
- [Log4J exploit](#log4j-exploit)
- [Offline support](#offline-support)
- [Certifi support](#certifi-support)
- [Contribute](#contribute)
- [Setup environment](#setup-environment)
Expand Down Expand Up @@ -54,7 +54,7 @@ For example `portablemc [global-args] <cmd> [args]`.
You can use `-h` argument to display help *(also works for every command)*.

By default the launcher will run any command from the OS standard `.minecraft` directory
([check wiki for more information](https://minecraft.gamepedia.com/.minecraft)). You can
([check wiki for more information](https://minecraft.wiki/w/.minecraft)). You can
change this directory using `--main-dir <path>` global argument.

You may also need `--work-dir <path>` to change the directory where your saves, resource
Expand Down Expand Up @@ -87,17 +87,18 @@ The first thing you may want to do is install and start Minecraft, to do so you
the `portablemc start [args] [version]` command. This command will install every component
needed by the version before launching it. If you provide no version, the latest release
is started, but you can specify a version to launch, or a version alias: `release`
or `snapshot` for the latest version of their type:
or `snapshot` for the latest version of their type.

In addition to Mojang's vanilla versions, the launcher natively supports common mod
loaders such as **Fabric**, **Forge** and **Quilt**. To start such versions, you can
prefix the version with either `fabric:`, `forge:` or `quilt:` (or `vanilla:` to
explicitly choose a vanilla version).
loaders such as **Fabric**, **Forge**, **NeoForge** and **Quilt**. To start such versions,
you can prefix the version with either `fabric:`, `forge:`, `neoforge:` or `quilt:` (or
`vanilla:` to explicitly choose a vanilla version).
Depending on the mod loader, the version you put after the colon is different:
- For Fabric and Quilt, you can directly specify the vanilla version, optionally followed
by `:<loader_version>`.
- For Forge, you can put either a vanilla game version, optionally followed by `-latest`
or `-recommended`, or `-<loader_version>`.
- For Forge and NeoForge, you can put either a vanilla game version, optionally followed
by `-<loader_version>`. Forge also supports `-latest` and `-recommended`, but NeoForge
will always take the latest loader.

*You can search for versions using the [search command](#search-for-versions).*

Expand All @@ -113,6 +114,7 @@ portablemc start 1.20.1
portablemc start fabric:
portablemc start quilt:
portablemc start forge:
portablemc start neoforge:
# Start Fabric for 1.20.1
portablemc start fabric:1.20.1
# Start Fabric for 1.20.1 with loader 0.11.2
Expand All @@ -122,6 +124,8 @@ portablemc start forge:1.20.1-latest
portablemc start forge:1.20.1-recommended
# Start Forge for 1.20.1 with loader 46.0.14
portablemc start forge:1.20-46.0.14
# Start NeoForge for 1.20.1
portablemc start neoforge:1.20.1
```

#### Authentication
Expand All @@ -146,7 +150,7 @@ However, if you use this, make sure that you either use an alias or a variable w
*[Check below](#authentication-sessions) for more information about authentication
sessions.*

#### Offline mode
#### Username and UUID
If you need fake offline accounts you can use `-u <username>` (`--username`) to define the
username and/or `-i <uuid>` (`--uuid`) to define your player's
[UUID](https://wikipedia.org/wiki/Universally_unique_identifier).
Expand All @@ -157,9 +161,8 @@ characters of the UUID are used for it.

#### Custom JVM
The launcher uses Java Virtual Machine to run the game, by default the launcher downloads
and uses the official JVM [distributed by Mojang](https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json)
which is adapted to the running version. The JVM is installed in a sub-directory called
`jvm` inside the main directory.
and uses the official JVM distributed by Mojang which is compatible with the game version.
The JVM is installed in a sub-directory called `jvm` inside the main directory.
You can change it by providing a path to the `java` binary with the
`--jvm <path_to/bin/java>` argument. By default, the launcher starts the JVM with default
arguments, these are the following and are the same as the Mojang launcher:
Expand All @@ -179,12 +182,12 @@ To do so you can use `-s <addr>` (`--server`) for the server address
defaults to 25565.

*Modern releases use the quick play arguments rather than arguments specified above, the
behavior remains the same.*
behavior remains the same, singleplayer and realm are not yet supported by the launcher.*

#### LWJGL version and ARM support
With `--lwjgl {3.2.3,3.3.0,3.3.1}` you can update the LWJGL version used when starting the
game. This can be used to support ARM architectures, but this may only work with modern
versions which are already using LWJGL 3. This argument works by dynamically rewriting the
With `--lwjgl VERSION` you can update the LWJGL version used when starting the game. This
can be used to support ARM architectures, but this may only work with modern versions
which are already using LWJGL 3. This argument works by dynamically rewriting the
version's metadata, the new metadata is dumped in the version directory.

Using these versions on ARM is unstable and can show you an error with `GLXBadFBConfig`,
Expand Down Expand Up @@ -253,10 +256,16 @@ you need to log into an old Mojang account (being phased out by Mojang).
**Your password is not saved!** Only tokens are saved *(the official launcher also does
that)* in the file `portablemc_auth.json` in the working directory.

## Log4j exploit
The launcher is safe to Log4j exploit since v2.2.0, if you are running an older version,
please update or read the following issue for a temporary fix:
[#52](https://github.com/mindstorm38/portablemc/issues/52).
## Offline support
This launcher can be used without internet access under certain conditions. Launching
versions is possible if all required resources are locally installed, it is also possible
to search for versions *(only Mojang, not Forge/Fabric/Quilt)* if the version manifest
is locally cached, this can be forced by just running the search or start commands with
internet access, you can also copy the relevant files from an online computer to your
offline one.
*Authentication commands and arguments are however not supported while offline.*

An example use case has been documented in issue [#178](https://github.com/mindstorm38/portablemc/issues/178#issuecomment-1752102655).

## Certifi support
The launcher supports [certifi](https://pypi.org/project/certifi/) when installed.
Expand Down
2 changes: 1 addition & 1 deletion portablemc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"""

LAUNCHER_NAME = "portablemc"
LAUNCHER_VERSION = "4.0.3"
LAUNCHER_VERSION = "4.1.0"
LAUNCHER_AUTHORS = ["Théo Rozier <contact@theorozier.fr>", "Github contributors"]
LAUNCHER_COPYRIGHT = "PortableMC Copyright (C) 2021-2023 Théo Rozier"
LAUNCHER_URL = "https://github.com/mindstorm38/portablemc"
33 changes: 24 additions & 9 deletions portablemc/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

from portablemc.fabric import FabricVersion, FabricResolveEvent
from portablemc.forge import ForgeVersion, ForgeResolveEvent, ForgePostProcessingEvent, \
ForgePostProcessedEvent, ForgeInstallError
ForgePostProcessedEvent, ForgeInstallError, _FORGE_REPO, _NEO_FORGE_REPO

from typing import cast, Optional, List, Union, Dict, Callable, Any, Tuple

Expand Down Expand Up @@ -142,10 +142,19 @@ def cmd(handler: CommandHandler, ns: RootNs):
sys.exit(EXIT_OK)

except ValueError as error:
ns.out.task("FAILED", None)
ns.out.finish()
for arg in error.args:
ns.out.task(None, "echo", echo=arg)
if len(error.args):
for i, arg in enumerate(error.args):
ns.out.task("FAILED" if i == 0 else None, "echo", echo=arg)
ns.out.finish()
else:
ns.out.task("FAILED", "echo", echo="programming error")
ns.out.finish()

if ns.verbose >= 1:
import traceback
traceback.print_exc()
else:
ns.out.task("INFO", "suggest_verbose")
ns.out.finish()

except KeyboardInterrupt:
Expand Down Expand Up @@ -447,17 +456,22 @@ def cmd_start_handler(ns: StartNs, kind: str, parts: List[str]) -> Optional[Vers
ns.socket_error_tips.append(f"{kind}_loader_version")
return constructor(version, parts[1] if len(parts) == 2 else None, context=ns.context, prefix=prefix)

elif kind == "forge":
elif kind in ("forge", "neoforge"):
if len(parts) != 1:
return None
return ForgeVersion(version, context=ns.context, prefix=ns.forge_prefix)
repo = _FORGE_REPO if kind == "forge" else _NEO_FORGE_REPO
prefix = ns.forge_prefix if kind == "forge" else ns.neoforge_prefix
return ForgeVersion(version, context=ns.context, prefix=prefix, _forge_repo=repo)
mindstorm38 marked this conversation as resolved.
Show resolved Hide resolved

else:
return None


def cmd_login(ns: LoginNs):
session = prompt_authenticate(ns, ns.email_or_username, True, ns.auth_service)
if session is not None:
ns.out.task("INFO", "login.tip.remember_start_login", email=ns.email_or_username)
ns.out.finish()
sys.exit(EXIT_FAILURE if session is None else EXIT_OK)


Expand Down Expand Up @@ -748,10 +762,11 @@ def fabric_resolve(e: FabricResolveEvent) -> None:
ns.out.finish()

def forge_resolve(e: ForgeResolveEvent) -> None:
api = "forge" if e._forge_repo == _FORGE_REPO else "neoforge"
if e.alias:
ns.out.task("..", "start.forge.resolving", version=e.forge_version)
ns.out.task("..", "start.forge.resolving", api=api, version=e.forge_version)
else:
ns.out.task("OK", "start.forge.resolved", version=e.forge_version)
ns.out.task("OK", "start.forge.resolved", api=api, version=e.forge_version)
mindstorm38 marked this conversation as resolved.
Show resolved Hide resolved
ns.out.finish()

super().__init__({
Expand Down
12 changes: 8 additions & 4 deletions portablemc/cli/lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def get(key: str, **kwargs) -> str:
"args.start.version.fabric": "fabric:[<vanilla-version>[:<loader-version>]]",
"args.start.version.quilt": "quilt:[<vanilla-version>[:<loader-version>]]",
"args.start.version.forge": "forge:[<forge-version>] (forge-version >= 1.5.2)",
"args.start.version.neoforge": "neoforge:[<neoforge-version>] (neoforge-version >= 1.20.1)",
"args.start.dry": "Simulate game starting.",
"args.start.disable_multiplayer": "Disable the multiplayer buttons (>= 1.16).",
"args.start.disable_chat": "Disable the online chat (>= 1.16).",
Expand All @@ -75,8 +76,9 @@ def get(key: str, **kwargs) -> str:
"args.start.fabric_prefix": "Change the prefix of the version ID when starting with Fabric (<prefix>-<vanilla-version>-<loader-version>).",
"args.start.quilt_prefix": "Change the prefix of the version ID when starting with Quilt (<prefix>-<vanilla-version>-<loader-version>).",
"args.start.forge_prefix": "Change the prefix of the version ID when starting with Forge (<prefix>-<forge-version>).",
"args.start.lwjgl": "Change the default LWJGL version used by Minecraft. "
"This argument makes additional changes in order to support additional architectures such as Arm. "
"args.start.neoforge_prefix": "Change the prefix of the version ID when starting with NeoForge (<prefix>-<neoforge-version>).",
"args.start.lwjgl": "Change the default LWJGL version used by Minecraft (LWJGL >= 3.2.3). "
"This argument makes additional changes in order to support processor architectures such as ARM. "
"It's not guaranteed to work with every version of Minecraft and downgrading LWJGL version is not recommended.",
"args.start.exclude_lib": "Specify Java libraries to exclude from the classpath (and download) "
"before launching the game. Follow this pattern to specify libraries: <artifact>[:[<version>][:<classifier>]]. "
Expand Down Expand Up @@ -130,6 +132,8 @@ def get(key: str, **kwargs) -> str:
"search.flags": "Flags",
"search.flags.local": "local",
"search.loader_version": "Loader version",
# Command login
"login.tip.remember_start_login": "Remember to start the game with '-l {email}' if you want to be authenticated in-game.",
# Command logout
"logout.yggdrasil.pending": "Logging out {email} from Mojang...",
"logout.microsoft.pending": "Logging out {email} from Microsoft...",
Expand Down Expand Up @@ -191,8 +195,8 @@ def get(key: str, **kwargs) -> str:
"start.fabric.resolving": "Resolving {api} loader for {vanilla_version}...",
"start.fabric.resolved": "Resolved {api} loader {loader_version} for {vanilla_version}",
# Command start (forge)
"start.forge.resolving": "Resolving forge alias {version}...",
"start.forge.resolved": "Resolved forge {version}",
"start.forge.resolving": "Resolving {api} alias {version}...",
"start.forge.resolved": "Resolved {api} {version}",
"start.forge.post_processing": "Forge post processing: {task}...",
"start.forge.post_processed": "Forge post processing done",
f"start.forge.install_error.{ForgeInstallError.INSTALL_PROFILE_NOT_FOUND}": "Install profile not found in the forge installer.",
Expand Down
6 changes: 4 additions & 2 deletions portablemc/cli/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class StartNs(RootNs):
fabric_prefix: str
quilt_prefix: str
forge_prefix: str
neoforge_prefix: str
lwjgl: Optional[str]
exclude_lib: Optional[List[LibrarySpecifierFilter]]
include_bin: Optional[List[str]]
Expand Down Expand Up @@ -115,7 +116,8 @@ def register_start_arguments(parser: ArgumentParser) -> None:
parser.add_argument("--fabric-prefix", help=_("args.start.fabric_prefix"), default="fabric", metavar="PREFIX")
parser.add_argument("--quilt-prefix", help=_("args.start.quilt_prefix"), default="quilt", metavar="PREFIX")
parser.add_argument("--forge-prefix", help=_("args.start.forge_prefix"), default="forge", metavar="PREFIX")
parser.add_argument("--lwjgl", help=_("args.start.lwjgl"), choices=["3.2.3", "3.3.0", "3.3.1", "3.3.2"])
parser.add_argument("--neoforge-prefix", help=_("args.start.neoforge_prefix"), default="neoforge", metavar="PREFIX")
parser.add_argument("--lwjgl", help=_("args.start.lwjgl"))
parser.add_argument("--exclude-lib", help=_("args.start.exclude_lib"), action="append", metavar="SPEC", type=LibrarySpecifierFilter.from_str)
parser.add_argument("--include-bin", help=_("args.start.include_bin"), action="append", metavar="PATH")
parser.add_argument("--auth-anonymize", help=_("args.start.auth_anonymize"), action="store_true")
Expand All @@ -126,7 +128,7 @@ def register_start_arguments(parser: ArgumentParser) -> None:
parser.add_argument("-i", "--uuid", help=_("args.start.uuid"))
parser.add_argument("-s", "--server", help=_("args.start.server"))
parser.add_argument("-p", "--server-port", type=int, help=_("args.start.server_port"), metavar="PORT")
parser.add_argument("version", nargs="?", default="release", help=_("args.start.version", formats=", ".join(map(lambda s: _(f"args.start.version.{s}"), ("standard", "fabric", "quilt", "forge")))))
parser.add_argument("version", nargs="?", default="release", help=_("args.start.version", formats=", ".join(map(lambda s: _(f"args.start.version.{s}"), ("standard", "fabric", "quilt", "forge", "neoforge")))))


def register_login_arguments(parser: ArgumentParser) -> None:
Expand Down
Loading
Loading