summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Sneed <gary@getcobalt.org>2024-10-25 20:23:21 -0700
committerGary Sneed <gary@getcobalt.org>2024-10-25 20:23:21 -0700
commitcf6e194a708d7a43d778a7cb8e31707225f1bb49 (patch)
tree055dbe0a15445541b0e08b8143d32e4a0ff9aec2
Initial commitv1.0
-rw-r--r--README.md43
-rwxr-xr-xget_playtime.sh13
-rwxr-xr-xget_version.sh91
-rwxr-xr-xlaunch.sh130
-rw-r--r--profiles/1.05
-rw-r--r--profiles/1.15
-rw-r--r--profiles/1.10.23
-rw-r--r--profiles/1.11.23
-rw-r--r--profiles/1.12.23
-rw-r--r--profiles/1.13.21
-rw-r--r--profiles/1.14.44
-rw-r--r--profiles/1.15.24
-rw-r--r--profiles/1.16.54
-rw-r--r--profiles/1.17.14
-rw-r--r--profiles/1.18.14
-rw-r--r--profiles/1.19.41
-rw-r--r--profiles/1.2.55
-rw-r--r--profiles/1.20.21
-rw-r--r--profiles/1.3.25
-rw-r--r--profiles/1.4.75
-rw-r--r--profiles/1.5.25
-rw-r--r--profiles/1.6.41
-rw-r--r--profiles/1.7.101
-rw-r--r--profiles/1.8.93
-rw-r--r--profiles/1.9.43
-rw-r--r--profiles/a1.0.41
-rw-r--r--profiles/a1.1.2_015
-rw-r--r--profiles/a1.2.65
-rw-r--r--profiles/b1.3_015
-rw-r--r--profiles/b1.45
-rw-r--r--profiles/b1.4_015
-rw-r--r--profiles/b1.5_015
-rw-r--r--profiles/b1.6.65
-rw-r--r--profiles/b1.7.35
-rw-r--r--profiles/b1.8.15
-rw-r--r--profiles/inf-201006181
-rw-r--r--profiles/rd-1322111
-rw-r--r--profiles/rd-1613481
38 files changed, 396 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5493ec4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,43 @@
+# Command-line Minecraft Launcher
+`minecraft-cli` is a low-overhead Minecraft multi-launcher capable of running almost any Minecraft version, written in POSIX shell.
+
+## Why?
+The other options for Minecraft launchers are massive (e.g. MultiMC) and like many other aspects of the modern Minecraft ecosystem, full of fragmentation and pointless forks. Sometimes you just want to play Minecraft. Enter `minecraft-cli`.
+
+## Features
+- No Microsoft authentication supported (feature, not a bug)
+- Extremely low overhead with few dependencies
+- POSIX-compliant; should run in any shell on Linux or UNIX-based systems.
+- "Officially" supports all major versions up to 1.20.2; Adding new ones is very easy.
+
+## Targeted platforms
+- Linux (all distributions)
+- OpenBSD
+
+## Dependencies
+* `jq`, `curl` and `nickle` - On Debian, you can install with `sudo apt install jq curl nickle`.
+* `uname`, `xargs`, `ls`, `cat`, `tr`, `mkdir`, `tee`, `dirname`, `sha1sum`, `sed`, `basename`, `date`, `xargs` - Listed for good measure, but you should almost certainly have all of these unless you are using an incomplete distribution/operating system.
+* A POSIX-compatible shell - If you are on Linux or a UNIX-based operating system, you almost certainly have one.
+* A Java runtime - Check with your distribution for installing. On Debian-based systems, the package is usually `default-jre` or `openjdk-<version>-jre`.
+* In uncommon situations, a C compiler may be required. See the "On natives" section below for more information.
+* Some knowledge of Java and Java arguments in particular is recommended.
+
+## Configuration
+- The `user.local` file (will be created at launch if it doesn't exist) stores your player name, Java runtime command and additional arguments such as allocated memory for the JVM.
+- The `profiles.local` directory is identical to `profiles`, but we recommend placing your own launch profiles in here to keep them organized.
+- The `libraries.local` directory contains additional libraries needed for custom profiles. This is particularly useful for modded Minecraft installations.
+
+## On natives
+Minecraft requires native code to run specific to your operating system. From 1.13 onwards, these are automatically downloaded from Mojang's servers in the form of a jar file and you don't need to worry about it\*. Any earlier, and you will need to seek the natives yourself. In particular, you need a library called `liblwjgl.so` (`liblwjgl64.so` works too). Obtaining this library can be tricky, but on Debian you can download the `liblwjgl-java-jni` package and the appropriate library will be under `/usr/lib/jni`. You will want to either copy or symlink this to the natives directory, which will be called `natives-<platform>`, e.g. `natives-linux` on Linux. Some older versions also complain about a missing `libjinput-linux64.so` which may be obtained through the `libjinput-jni` package. Despite errors, Minecraft seems to work find without it either way. As a last resort, you will need to compile the necessary natives from source, which will require a C compiler and is beyond the scope of this document. Also note that natives can be loaded as either a shared object or a jar file. The natives folder is only for shared objects.
+
+\* You still need to worry about it for platforms besides Windows, MacOS and Linux.
+
+## Jar patching
+As far as patching jar files is concerned, fully-fledged launchers have their own ways of doing this. In our case, however, you will need to return to the old fashion method of manually inserting the contents into the jar file and possibly deleting META-INF. The recommended way of doing this is with the `jar` program that comes with the JDK. You will find few if any situations where this is necessary.
+
+## Known issues/caveats
+* Sound does not work for Release 1.7.\*, a1.0.4 and inf-20100618.
+* Narrator is unsupported for all versions that include it, as they require a library (Flite) that Mojang doesn't provide, nor do we.
+* Mod loaders work, but we do not currently have official support for any. Documentation will be added later for getting these up and running.
+* Downloading versions is slower and less efficient than it should be - this will be fixed in the future.
+* On OpenBSD (and possibly other obscure platforms), older versions will need to use a newer LWJGL than what the manifest provides, due to legacy LWJGL libraries having limited platform support. This can be easily worked around but isn't done so automatically at the moment.
diff --git a/get_playtime.sh b/get_playtime.sh
new file mode 100755
index 0000000..9ca3e70
--- /dev/null
+++ b/get_playtime.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env sh
+
+IFS=$'\n'
+TOTAL=0
+for I in $(ls -1 playtime 2>/dev/null); do
+ TOTAL=$(echo $(cat "playtime/${I}") + "${TOTAL}" | nickle)
+done
+
+echo Total seconds: ${TOTAL}
+echo Total minutes: $(echo ${TOTAL} / 60 | nickle)
+echo Total hours: $(echo ${TOTAL} / 60 / 60 | nickle)
+echo Total days: $(echo ${TOTAL} / 60 / 60 / 24 | nickle)
+echo Total years: $(echo ${TOTAL} / 60 / 60 / 24 / 365.25 | nickle)
diff --git a/get_version.sh b/get_version.sh
new file mode 100755
index 0000000..8e777eb
--- /dev/null
+++ b/get_version.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env sh
+
+# Only accepts 1 argument: the Minecraft version to download
+LOOOKING_FOR=
+if [ -z "${1}" ]; then
+ echo "ERROR: Requires one argument (the Minecraft instance to launch)"
+ exit 1
+else
+ LOOKING_FOR="${1}"
+fi
+
+PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
+
+MANIFEST_LIST_URL='https://launchermeta.mojang.com/mc/game/version_manifest.json'
+
+mkdir -p assets/indexes
+
+echo 'Retrieving version manifest...'
+VERSION_MANIFEST_URL=$(curl "${MANIFEST_LIST_URL}" 2>/dev/null | jq -r "(.versions.[] | select(.id==\"${LOOKING_FOR}\")).url")
+
+if [ -z "${VERSION_MANIFEST_URL}" ]; then
+ echo "ERROR: Unable to find requested version"
+ exit 1
+fi
+
+mkdir -p manifests
+VERSION_MANIFEST=$(curl ${VERSION_MANIFEST_URL} 2>/dev/null | sed -e 's/\\/\\\\/g' | tee "manifests/${LOOKING_FOR}.json") # Some versions contain illegal escape sequences which will crash some shells such as Ksh; double-escape it just to be safe
+
+# 1.12 and earlier, natives and regular libraries are contained in different elements. For 1.13 and later, an element may contain both.
+echo 'Downloading libraries...'
+for I in $(echo "${VERSION_MANIFEST}" | jq -c .libraries.[]); do
+ if [[ $(echo "${I}" | jq .downloads.artifact) != 'null' ]]; then
+ echo "Library '$(echo ${I} | jq -r .name )' found - downloading..."
+ mkdir -p libraries/$(dirname $(echo ${I} | jq -r .downloads.artifact.path))
+ curl $(echo ${I} | jq -r .downloads.artifact.url) > libraries/$(echo "${I}" | jq -r .downloads.artifact.path) 2>/dev/null
+ fi
+ if [[ $(echo "${I}" | jq .natives) != 'null' ]]; then
+ echo "Downloading native for platform '${PLATFORM}'..."
+ if [[ $(echo ${I} | jq -r ".downloads.classifiers.\"natives-${PLATFORM}\"") == 'null' ]]; then
+ echo "WARNING: Mojang does not distribute a '$(echo ${I} | jq -r .name)' native for this platform. This is probably not an issue unless you are using an obscure platform."
+ else
+ mkdir -p libraries/$(dirname $(echo ${I} | jq -r ".downloads.classifiers.\"natives-${PLATFORM}\".path"))
+ curl $(echo ${I} | jq -r ".downloads.classifiers.\"natives-${PLATFORM}\".url") > libraries/$(echo "${I}" | jq -r ".downloads.classifiers.\"natives-${PLATFORM}\".path") 2>/dev/null
+ fi
+ fi
+done
+
+echo 'Retrieving asset index...'
+ASSET_INDEX=$(echo "${VERSION_MANIFEST}" | jq .assetIndex)
+
+echo 'Retrieving object list...'
+OBJECT_LIST=$(curl $(echo ${ASSET_INDEX} | jq -r .url) 2>/dev/null | tee assets/indexes/$(echo ${ASSET_INDEX} | jq -r .id).json)
+
+HASH_COUNT=$(echo ${OBJECT_LIST} | jq '.objects | length')
+
+echo 'Downloading required assets. This may take a few minutes.'
+MCRESOURCES='https://resources.download.minecraft.net/'
+if [[ "$(echo "${ASSET_INDEX}" | jq -r .id)" == 'pre-1.6' || "$(echo "${ASSET_INDEX}" | jq -r .id)" == 'legacy' ]]; then # Release 1.6 and prior use a different asset layout
+ while read -r LINE; do
+ H=$(echo ${OBJECT_LIST} | jq -r ".objects.[\"${LINE}\"].hash")
+ DIR="${H[0]}${H[1]}/"
+
+ mkdir -p "$(dirname "assets/virtual/legacy/${LINE}")"
+ curl "${MCRESOURCES}${DIR}${H}" > "assets/virtual/legacy/${LINE}" 2>/dev/null
+ echo "Downloaded: assets/virtual/legacy/${LINE}"
+ done <<< "$(echo "${OBJECT_LIST}" | jq -r '.objects | keys[]')"
+else
+ IND=0
+ for I in $(echo "${OBJECT_LIST}" | jq -r .objects.[].hash); do
+ IND=$(echo "${IND}" + 1 | nickle)
+ DIR="$(echo "${I}" | cut -c1-2)/"
+
+ mkdir -p "assets/objects/${DIR}"
+
+ # If file exists, check its integrity with hash and skip if it's good
+ if [[ -f assets/objects/${DIR}${I} && $(cat "assets/objects/${DIR}${I}" | sha1sum | sed -e 's/ (stdin)//') == "${I}" ]]; then # Removing (stdin) is not needed for most sha1sum implementations
+ echo "${IND}/${HASH_COUNT} (${DIR}${I}) is already downloaded; skipping. ($(echo "printf(\"%5l\", ${IND} / ${HASH_COUNT} * 100)" | nickle)%)"
+ continue;
+ fi
+
+ curl "${MCRESOURCES}${DIR}${I}" > "assets/objects/${DIR}${I}" 2>/dev/null
+ echo "Downloading ${IND}/${HASH_COUNT}: ${MCRESOURCES}${DIR}${I} ($(echo "printf(\"%5l\", ${IND} / ${HASH_COUNT} * 100)" | nickle)%)"
+ done
+fi
+
+echo 'Downloading minecraft jar...'
+CLIENT_URL=$(echo "${VERSION_MANIFEST}" | jq -r .downloads.client.url)
+mkdir -p "libraries/com/mojang/minecraft/${LOOKING_FOR}"
+curl "${CLIENT_URL}" > "libraries/com/mojang/minecraft/${LOOKING_FOR}/minecraft-${LOOKING_FOR}-client.jar" 2>/dev/null
+
+echo 'Finished!'
diff --git a/launch.sh b/launch.sh
new file mode 100755
index 0000000..b253720
--- /dev/null
+++ b/launch.sh
@@ -0,0 +1,130 @@
+#!/usr/bin/env sh
+
+PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
+
+# Only accepts 1 argument: the Minecraft profile to launch
+INAME=
+if [ -z "${1}" ]; then
+ echo "ERROR: Requires one argument (the Minecraft instance to launch)"
+ exit 1
+else
+ INAME="${1}"
+fi
+
+# Setup and read configurations
+JAVA=java
+MCUSER=Player
+JARGS='-Xms512M -Xmx1024M'
+
+VERSION=
+
+BLACKLISTED_LIBRARIES=
+BLACKLISTED_NATIVES=
+
+ADDITIONAL_LIBRARIES=
+
+XARGS=
+
+if [ -f 'user.local' ]; then
+ . "./user.local"
+else
+ echo "JAVA=${JAVA}" > user.local
+ echo "MCUSER=${MCUSER}" >> user.local
+ echo "JARGS='${JARGS}'" >> user.local
+fi
+
+if [ -f "profiles.local/${INAME}" ]; then
+ . "profiles.local/${INAME}"
+elif [ -f "profiles/${INAME}" ]; then
+ . "profiles/${INAME}"
+else
+ echo "ERROR: Specified profile does not exist."
+ exit 1
+fi
+
+if [ ! -f "manifests/${VERSION}.json" ]; then
+ echo "Invalid version detected. Either it is mistyped, or you have not downloaded it yet."
+ exit 1
+fi
+
+MINECRAFT_JAR=${MINECRAFT_JAR:=libraries/com/mojang/minecraft/${VERSION}/minecraft-${VERSION}-client.jar}
+
+VERSION_MANIFEST=$(cat "manifests/${VERSION}.json")
+
+# Some libraries included in the manifests are known to cause issues, so we blacklist them here
+# 1.12 and earlier, natives and regular libraries are contained in different elements. For 1.13 and later, an element may contain both.
+CLASSPATH=
+for I in $(echo "${VERSION_MANIFEST}" | jq -c .libraries.[]); do
+ if [[ $(echo "${I}" | jq .downloads.artifact) != 'null' ]]; then
+ for J in ${BLACKLISTED_LIBRARIES}; do
+ if [ ${J} == $(basename $(echo ${I} | jq -r .downloads.artifact.path)) ]; then
+ SKIP=1
+ fi
+ done
+ if [[ ${SKIP} -eq 1 ]]; then
+ SKIP=
+ continue
+ fi
+ JAR=$(echo ${I} | jq -r .downloads.artifact.path)
+ if [ "${JAR}" != 'null' ]; then
+ CLASSPATH="${PWD}/libraries/${JAR}:${CLASSPATH}"
+ fi
+ fi
+ if [[ $(echo "${I}" | jq .natives) != 'null' ]]; then
+ for J in ${BLACKLISTED_NATIVES}; do
+ if [ ${J} == $(basename $(echo ${I} | jq ".downloads.classifiers.\"natives-${PLATFORM}\".path")) ]; then
+ SKIP=1
+ fi
+ done
+ if [[ ${SKIP} -eq 1 ]]; then
+ SKIP=
+ continue
+ fi
+ JAR=$(echo ${I} | jq -r ".downloads.classifiers.\"natives-${PLATFORM}\".path")
+ if [ "${JAR}" != 'null' ]; then
+ CLASSPATH="${PWD}/libraries/${JAR}:${CLASSPATH}"
+ fi
+ fi
+done
+
+for I in ${ADDITIONAL_LIBRARIES}; do
+ CLASSPATH="${CLASSPATH}:${PWD}/${I}"
+done
+
+CLASSPATH="${CLASSPATH}:${PWD}/${MINECRAFT_JAR}"
+
+if [[ $(echo "${VERSION_MANIFEST}" | jq -r .minecraftArguments) != 'null' ]]; then
+ ARGUMENT_LIST=$(echo ${VERSION_MANIFEST} | jq -r .minecraftArguments)
+else
+ for I in $(echo ${VERSION_MANIFEST} | jq -r '.arguments.game[] | select(type=="string")'); do
+ ARGUMENT_LIST="${ARGUMENT_LIST} ${I}"
+ done
+fi
+
+ARGUMENTS="$(echo ${ARGUMENT_LIST} | sed -e "s/\${auth_player_name}/${MCUSER}/" -e "s/\${version_name}/${VERSION}/" -e "s@\${game_directory}@\"${PWD}/instances/${INAME}\"@" -e "s@\${assets_root}@${PWD}/assets@" -e "s/\${assets_index_name}/$(echo ${VERSION_MANIFEST} | jq -r .assetIndex.id)/" -e 's/${auth_uuid}/00000000-0000-0000-0000-000000000000/' -e 's/${auth_access_token}/0/' -e 's/${user_type}/mojang/' -e "s/\${version_type}/$(echo ${VERSION_MANIFEST} | jq -r .type)/" -e 's/${user_properties}/{}/' -e "s@\${game_assets}@${PWD}/assets/virtual/legacy@" -e 's/${auth_session}/0/')"
+
+MAINCLASS=${MAINCLASS:=$(echo ${VERSION_MANIFEST} | jq -r .mainClass)}
+
+INSTANCES="${PWD}/instances"
+if [ -f "playtime/${INAME}" ]; then
+ PRVTOTAL=`cat "playtime/${INAME}"`
+else
+ PRVTOTAL=0
+fi
+STARTTIME=`date +"%s"`
+mkdir -p "${INSTANCES}/${INAME}"
+ORIGDIR="${PWD}"
+cd "${INSTANCES}/${INAME}"
+trap 'echo "Interrupt received"' INT
+
+echo ${ARGUMENTS} ${XARGS} | xargs "${JAVA}" ${JARGS} -Duser.language=en -Djava.library.path="${ORIGDIR}/natives-${PLATFORM}" -cp "${CLASSPATH}" "${MAINCLASS}"
+
+ENDTIME=`date +"%s"`
+cd "${ORIGDIR}"
+
+TOTALSECONDS=`echo ${ENDTIME} - ${STARTTIME} + ${PRVTOTAL} | nickle`
+if [ ! -z ${TOTALSECONDS} ]; then # Prevent playtime from being cleared if nickle is broken/missing
+ mkdir -p playtime
+ echo ${TOTALSECONDS} > "playtime/${INAME}"
+ echo Total playtime: ${ENDTIME} - ${STARTTIME} + ${PRVTOTAL} = ${TOTALSECONDS}
+fi
diff --git a/profiles/1.0 b/profiles/1.0
new file mode 100644
index 0000000..2eb5453
--- /dev/null
+++ b/profiles/1.0
@@ -0,0 +1,5 @@
+VERSION=1.0
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.1 b/profiles/1.1
new file mode 100644
index 0000000..be6bf66
--- /dev/null
+++ b/profiles/1.1
@@ -0,0 +1,5 @@
+VERSION=1.1
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.10.2 b/profiles/1.10.2
new file mode 100644
index 0000000..d594f78
--- /dev/null
+++ b/profiles/1.10.2
@@ -0,0 +1,3 @@
+VERSION=1.10.2
+BLACKLISTED_LIBRARIES='lwjgl_util-2.9.2-nightly-20140822.jar lwjgl-2.9.2-nightly-20140822.jar'
+BLACKLISTED_NATIVES='lwjgl-platform-2.9.2-nightly-20140822-natives.jar'
diff --git a/profiles/1.11.2 b/profiles/1.11.2
new file mode 100644
index 0000000..3727941
--- /dev/null
+++ b/profiles/1.11.2
@@ -0,0 +1,3 @@
+VERSION=1.11.2
+BLACKLISTED_LIBRARIES='lwjgl_util-2.9.2-nightly-20140822.jar lwjgl-2.9.2-nightly-20140822.jar'
+BLACKLISTED_NATIVES='lwjgl-platform-2.9.2-nightly-20140822-natives.jar'
diff --git a/profiles/1.12.2 b/profiles/1.12.2
new file mode 100644
index 0000000..de8e5d1
--- /dev/null
+++ b/profiles/1.12.2
@@ -0,0 +1,3 @@
+VERSION=1.12.2
+BLACKLISTED_LIBRARIES='lwjgl_util-2.9.2-nightly-20140822.jar lwjgl-2.9.2-nightly-20140822.jar'
+BLACKLISTED_NATIVES='lwjgl-platform-2.9.2-nightly-20140822-natives.jar'
diff --git a/profiles/1.13.2 b/profiles/1.13.2
new file mode 100644
index 0000000..f512113
--- /dev/null
+++ b/profiles/1.13.2
@@ -0,0 +1 @@
+VERSION=1.13.2
diff --git a/profiles/1.14.4 b/profiles/1.14.4
new file mode 100644
index 0000000..d0222ec
--- /dev/null
+++ b/profiles/1.14.4
@@ -0,0 +1,4 @@
+VERSION=1.14.4
+
+# Disable old LWJGL version to disable annoying but seemingly harmless errors upon startup
+BLACKLISTED_LIBRARIES='lwjgl-tinyfd-3.2.1.jar lwjgl-stb-3.2.1.jar lwjgl-glfw-3.2.1.jar lwjgl-opengl-3.2.1.jar lwjgl-openal-3.2.1.jar lwjgl-jemalloc-3.2.1.jar lwjgl-3.2.1.jar'
diff --git a/profiles/1.15.2 b/profiles/1.15.2
new file mode 100644
index 0000000..c6ae1ec
--- /dev/null
+++ b/profiles/1.15.2
@@ -0,0 +1,4 @@
+VERSION=1.15.2
+
+# Disable old LWJGL version to disable annoying but seemingly harmless errors upon startup
+BLACKLISTED_LIBRARIES='lwjgl-tinyfd-3.2.1.jar lwjgl-stb-3.2.1.jar lwjgl-glfw-3.2.1.jar lwjgl-opengl-3.2.1.jar lwjgl-openal-3.2.1.jar lwjgl-jemalloc-3.2.1.jar lwjgl-3.2.1.jar'
diff --git a/profiles/1.16.5 b/profiles/1.16.5
new file mode 100644
index 0000000..0e42a1e
--- /dev/null
+++ b/profiles/1.16.5
@@ -0,0 +1,4 @@
+VERSION=1.16.5
+
+# Disable old LWJGL version to disable annoying but seemingly harmless errors upon startup
+BLACKLISTED_LIBRARIES='lwjgl-tinyfd-3.2.1.jar lwjgl-stb-3.2.1.jar lwjgl-glfw-3.2.1.jar lwjgl-opengl-3.2.1.jar lwjgl-openal-3.2.1.jar lwjgl-jemalloc-3.2.1.jar lwjgl-3.2.1.jar'
diff --git a/profiles/1.17.1 b/profiles/1.17.1
new file mode 100644
index 0000000..9a68584
--- /dev/null
+++ b/profiles/1.17.1
@@ -0,0 +1,4 @@
+VERSION=1.17.1
+
+# Disable old LWJGL version to disable annoying but seemingly harmless errors upon startup
+BLACKLISTED_LIBRARIES='lwjgl-tinyfd-3.2.1.jar lwjgl-stb-3.2.1.jar lwjgl-glfw-3.2.1.jar lwjgl-opengl-3.2.1.jar lwjgl-openal-3.2.1.jar lwjgl-jemalloc-3.2.1.jar lwjgl-3.2.1.jar'
diff --git a/profiles/1.18.1 b/profiles/1.18.1
new file mode 100644
index 0000000..5cbc723
--- /dev/null
+++ b/profiles/1.18.1
@@ -0,0 +1,4 @@
+VERSION=1.18.1
+
+# Disable old LWJGL version to disable annoying but seemingly harmless errors upon startup
+BLACKLISTED_LIBRARIES='lwjgl-tinyfd-3.2.1.jar lwjgl-stb-3.2.1.jar lwjgl-glfw-3.2.1.jar lwjgl-opengl-3.2.1.jar lwjgl-openal-3.2.1.jar lwjgl-jemalloc-3.2.1.jar lwjgl-3.2.1.jar'
diff --git a/profiles/1.19.4 b/profiles/1.19.4
new file mode 100644
index 0000000..3ae16db
--- /dev/null
+++ b/profiles/1.19.4
@@ -0,0 +1 @@
+VERSION=1.19.4
diff --git a/profiles/1.2.5 b/profiles/1.2.5
new file mode 100644
index 0000000..9305282
--- /dev/null
+++ b/profiles/1.2.5
@@ -0,0 +1,5 @@
+VERSION=1.2.5
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.20.2 b/profiles/1.20.2
new file mode 100644
index 0000000..7c86899
--- /dev/null
+++ b/profiles/1.20.2
@@ -0,0 +1 @@
+VERSION=1.20.2
diff --git a/profiles/1.3.2 b/profiles/1.3.2
new file mode 100644
index 0000000..69c3dfb
--- /dev/null
+++ b/profiles/1.3.2
@@ -0,0 +1,5 @@
+VERSION=1.3.2
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.4.7 b/profiles/1.4.7
new file mode 100644
index 0000000..de61f75
--- /dev/null
+++ b/profiles/1.4.7
@@ -0,0 +1,5 @@
+VERSION=1.4.7
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.5.2 b/profiles/1.5.2
new file mode 100644
index 0000000..b51df4f
--- /dev/null
+++ b/profiles/1.5.2
@@ -0,0 +1,5 @@
+VERSION=1.5.2
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/1.6.4 b/profiles/1.6.4
new file mode 100644
index 0000000..2e9218d
--- /dev/null
+++ b/profiles/1.6.4
@@ -0,0 +1 @@
+VERSION=1.6.4
diff --git a/profiles/1.7.10 b/profiles/1.7.10
new file mode 100644
index 0000000..ded30c8
--- /dev/null
+++ b/profiles/1.7.10
@@ -0,0 +1 @@
+VERSION=1.7.10
diff --git a/profiles/1.8.9 b/profiles/1.8.9
new file mode 100644
index 0000000..f81746c
--- /dev/null
+++ b/profiles/1.8.9
@@ -0,0 +1,3 @@
+VERSION=1.8.9
+BLACKLISTED_LIBRARIES='lwjgl_util-2.9.2-nightly-20140822.jar lwjgl-2.9.2-nightly-20140822.jar'
+BLACKLISTED_NATIVES='lwjgl-platform-2.9.2-nightly-20140822-natives.jar'
diff --git a/profiles/1.9.4 b/profiles/1.9.4
new file mode 100644
index 0000000..4790939
--- /dev/null
+++ b/profiles/1.9.4
@@ -0,0 +1,3 @@
+VERSION=1.9.4
+BLACKLISTED_LIBRARIES='lwjgl_util-2.9.2-nightly-20140822.jar lwjgl-2.9.2-nightly-20140822.jar'
+BLACKLISTED_NATIVES='lwjgl-platform-2.9.2-nightly-20140822-natives.jar'
diff --git a/profiles/a1.0.4 b/profiles/a1.0.4
new file mode 100644
index 0000000..a30fe93
--- /dev/null
+++ b/profiles/a1.0.4
@@ -0,0 +1 @@
+VERSION=a1.0.4
diff --git a/profiles/a1.1.2_01 b/profiles/a1.1.2_01
new file mode 100644
index 0000000..29fc500
--- /dev/null
+++ b/profiles/a1.1.2_01
@@ -0,0 +1,5 @@
+VERSION=a1.1.2_01
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/a1.2.6 b/profiles/a1.2.6
new file mode 100644
index 0000000..65ab2c6
--- /dev/null
+++ b/profiles/a1.2.6
@@ -0,0 +1,5 @@
+VERSION=a1.2.6
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.3_01 b/profiles/b1.3_01
new file mode 100644
index 0000000..f27593e
--- /dev/null
+++ b/profiles/b1.3_01
@@ -0,0 +1,5 @@
+VERSION=b1.3_01
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.4 b/profiles/b1.4
new file mode 100644
index 0000000..a900d9d
--- /dev/null
+++ b/profiles/b1.4
@@ -0,0 +1,5 @@
+VERSION=b1.4
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.4_01 b/profiles/b1.4_01
new file mode 100644
index 0000000..8fbf29e
--- /dev/null
+++ b/profiles/b1.4_01
@@ -0,0 +1,5 @@
+VERSION=b1.4_01
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.5_01 b/profiles/b1.5_01
new file mode 100644
index 0000000..a041de0
--- /dev/null
+++ b/profiles/b1.5_01
@@ -0,0 +1,5 @@
+VERSION=b1.5_01
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.6.6 b/profiles/b1.6.6
new file mode 100644
index 0000000..15f66eb
--- /dev/null
+++ b/profiles/b1.6.6
@@ -0,0 +1,5 @@
+VERSION=b1.6.6
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.7.3 b/profiles/b1.7.3
new file mode 100644
index 0000000..b05257d
--- /dev/null
+++ b/profiles/b1.7.3
@@ -0,0 +1,5 @@
+VERSION=b1.7.3
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/b1.8.1 b/profiles/b1.8.1
new file mode 100644
index 0000000..5e8060b
--- /dev/null
+++ b/profiles/b1.8.1
@@ -0,0 +1,5 @@
+VERSION=b1.8.1
+
+mkdir -p instances/${INAME}
+[[ ! -L "instances/${INAME}/resources" ]] && rmdir "instances/${INAME}/resources" 2>/dev/null
+ln -sf ../../assets/virtual/legacy "instances/${INAME}/resources"
diff --git a/profiles/inf-20100618 b/profiles/inf-20100618
new file mode 100644
index 0000000..f10ca9f
--- /dev/null
+++ b/profiles/inf-20100618
@@ -0,0 +1 @@
+VERSION=inf-20100618
diff --git a/profiles/rd-132211 b/profiles/rd-132211
new file mode 100644
index 0000000..9a05edb
--- /dev/null
+++ b/profiles/rd-132211
@@ -0,0 +1 @@
+VERSION=rd-132211
diff --git a/profiles/rd-161348 b/profiles/rd-161348
new file mode 100644
index 0000000..b7f52fb
--- /dev/null
+++ b/profiles/rd-161348
@@ -0,0 +1 @@
+VERSION=rd-161348