kCraft - Minecraft Launcher (POSIX Shell)
WHAT!? They Put MINECRAFT In POSIX SHELL!?!?!?
We GNU/musl/BusyBox/Linux boomers were in need of real Command-line Minecraft launcher for a long time. Because Graphical user interface on Tiling window managers gives us severe anxiety. So here I announce a new revolutionary Minecraft launcher written purely in POSIX shell WOW!!! This was inspired by Luke Smith and this video:
Oh, yes where can I get it?
Clone it or just scroll down a bit and copy-paste it.
git clone https://gitlab.com/stnby/kcraft.git
Dependencies:
- jq — A lightweight and flexible command-line JSON processor.
- cURL — For downloading stuff…
- aria2 — A lightweight multi-protocol & multi-source command-line download utility.
- Rofi — A window switcher, application launcher and dmenu replacement.
- Coreutils, Findutils — Casual stuff that you just must have.
- OpenJDK — OpenJDK Java Development Kit.
How does this work?
Well just run commands in this order:
./kcraft.sh get-manifest
./kcraft.sh get-metadata
./kcraft.sh get-client 1.16.2
./kcraft.sh get-assets 1.16.2
./kcraft.sh get-libs 1.16.2
./kcraft.sh extract-natives 1.16.2
./kcraft.sh start-client 1.16.2
Code:
See it even fits in this post. Screw Micro$oft.
#!/bin/sh
# Copyright (c) 2020 Stnby <stnby@kernal.eu>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
auth_player_name='Stnby'
game_directory=~/.minecraft
launcher_name='java-minecraft-launcher' # Ha except it's POSIX Shell...
launcher_version='1.6.84-j'
auth_uuid='00000000-0000-0000-0000-000000000000'
auth_access_token='null'
user_type='legacy'
assets_root="${game_directory}/assets"
libraries_root="${game_directory}/libraries"
versions_root="${game_directory}/versions"
case "$1" in
get-manifest) # Downloads info about all client versions.
curl --create-dirs -#o "${game_directory}/version_manifest.json" 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
;;
get-metadata) # Downloads metadata for selected client version.
jq -j '.versions[] | "<b>", .id, "</b> ", .type, "\n"' "${game_directory}/version_manifest.json" \
| rofi -dmenu -p 'version' -markup-rows -format 'i' \
| xargs -I% \
jq -M '.versions[%] | .id, .url' "${game_directory}/version_manifest.json" \
| xargs sh -c \
"echo \"Downloading: 'versions/\$0/\$0.json'\"; curl --create-dirs -C- -#o \"${versions_root}/\$0/\$0.json\" \$1"
;;
get-client) # Downloads 'client.jar'.
version_name="$2"
[ ! -f "${versions_root}/${version_name}/${version_name}.json" ] && echo 'Such version does not exist' && exit 1
echo "Downloading: 'versions/${version_name}/${version_name}.jar'"
jq '.downloads.client.url' "${versions_root}/${version_name}/${version_name}.json" \
| xargs curl -C- -#o "${versions_root}/${version_name}/${version_name}.jar"
;;
get-assets) # Downloads game assets required for the client.
version_name="$2"
[ ! -f "${versions_root}/${version_name}/${version_name}.json" ] && echo 'Such version does not exist' && exit 1
assets_index_name=`jq -r '.assetIndex.id' "${versions_root}/${version_name}/${version_name}.json"`
jq -r '.assetIndex.url' "${versions_root}/${version_name}/${version_name}.json" \
| xargs sh -c \
"echo \"Downloading: 'assets/indexes/${assets_index_name}.json'\"; curl --create-dirs -C- -#o \"${assets_root}/indexes/${assets_index_name}.json\" \$0"
jq '.objects[].hash' "${assets_root}/indexes/${assets_index_name}.json" \
| xargs -n1 sh -c \
"printf 'https://resources.download.minecraft.net/%.2s/%s\n\tout=%.2s/%s\n' \$0 \$0 \$0 \$0" \
| aria2c -i- -x16 -c -d "${assets_root}/objects"
;;
get-libs) # Downloads libraries required for the client.
version_name="$2"
[ ! -f "${versions_root}/${version_name}/${version_name}.json" ] && echo 'Such version does not exist' && exit 1
jq '.libraries[].downloads[] | if has("natives-linux") then ."natives-linux" else if has("url") then . else empty end end | .path, .url' \
"${versions_root}/${version_name}/${version_name}.json" \
| xargs -n2 sh -c "printf '%s\n\tout=%s\n' \$1 \$0" \
| aria2c -i- -x16 -c -d ${libraries_root}
;;
extract-natives) # Extracts native libraries into correct location from previous step.
version_name="$2"
[ ! -f "${versions_root}/${version_name}/${version_name}.json" ] && echo 'Such version does not exist' && exit 1
jq -r '.libraries[].downloads.classifiers."natives-linux".path // empty' "${versions_root}/${version_name}/${version_name}.json" \
| xargs -n1 -I% unzip -n "${libraries_root}/%" -d "${versions_root}/${version_name}/natives"
;;
start-client) # Starts the game. :)
version_name="$2"
[ ! -f "${versions_root}/${version_name}/${version_name}.json" ] && echo 'Such version does not exist' && exit 1
version_type=`jq -r '.type' "${versions_root}/${version_name}/${version_name}.json"`
assets_index_name=`jq -r '.assetIndex.id' "${versions_root}/${version_name}/${version_name}.json"`
natives_directory="${versions_root}/${version_name}/natives"
classpath=`jq -r '.libraries[].downloads[].path // empty' "${versions_root}/${version_name}/${version_name}.json" \
| xargs -n1 -I% printf "${libraries_root}/%:"; echo "${versions_root}/${version_name}/${version_name}.jar"`
main_class=`jq -r '.mainClass' "${versions_root}/${version_name}/${version_name}.json"`
java \
-Xmx2G -Xss1M \
-Dfile.encoding=UTF-8 \
-Djava.library.path=${natives_directory} \
-Dminecraft.launcher.brand=${launcher_name} \
-Dminecraft.launcher.version=${launcher_version} \
-cp ${classpath} ${main_class} \
--username ${auth_player_name} \
--version ${version_name} \
--gameDir ${game_directory} \
--assetsDir ${assets_root} \
--assetIndex ${assets_index_name} \
--uuid ${auth_uuid} \
--accessToken ${auth_access_token} \
--userType ${user_type} \
--versionType ${version_type}
;;
*) echo 'Go ahead and read the source code.'
esac