Compare commits
No commits in common. "master" and "maven" have entirely different histories.
73 changed files with 279 additions and 1531 deletions
27
.github/workflows/build.yml
vendored
27
.github/workflows/build.yml
vendored
|
@ -1,27 +0,0 @@
|
|||
name: Gradle Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '8.0.312'
|
||||
architecture: x64
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
./gradlew build -iS
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Package
|
||||
path: build/libs
|
59
.github/workflows/publication.yml
vendored
59
.github/workflows/publication.yml
vendored
|
@ -1,59 +0,0 @@
|
|||
name: Publication
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: '8.0.312'
|
||||
architecture: x64
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
IS_PUBLICATION: true
|
||||
run: |
|
||||
git clone -b maven https://github.com/ZekerZhayard/ForgeWrapper.git ./build/maven
|
||||
rm -rf ./build/maven/.git/*
|
||||
chmod +x ./gradlew
|
||||
./gradlew publish -iS
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Package
|
||||
path: build/libs
|
||||
- name: Get tag version
|
||||
id: get_version
|
||||
uses: olegtarasov/get-tag@v2.1
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Package
|
||||
path: build/libs
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ steps.get_version.outputs.tag }}
|
||||
release_name: ${{ steps.get_version.outputs.tag }}
|
||||
body: ''
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload release binaries
|
||||
uses: alexellis/upload-assets@0.2.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
asset_paths: '["./build/libs/*"]'
|
||||
- name: Upload to Maven
|
||||
uses: JamesIves/github-pages-deploy-action@4.1.4
|
||||
with:
|
||||
branch: maven
|
||||
folder: build/maven
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,15 +0,0 @@
|
|||
.gradle
|
||||
build
|
||||
|
||||
# eclipse
|
||||
.settings
|
||||
.classpath
|
||||
.project
|
||||
bin
|
||||
|
||||
# idea
|
||||
.idea
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
out
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) ZekerZhayard
|
||||
|
||||
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.
|
30
README.md
30
README.md
|
@ -1,30 +0,0 @@
|
|||
# ForgeWrapper
|
||||
|
||||
Allow [MultiMC](https://github.com/MultiMC/MultiMC5) to launch Minecraft 1.13+ with Forge.
|
||||
|
||||
**ForgeWrapper has been adopted by MultiMC, you do not need to perform the following steps manually. (2020-03-29)**
|
||||
|
||||
## For other launchers
|
||||
1. ForgeWrapper provides some java properties since 1.4.2:
|
||||
- `forgewrapper.librariesDir` : a path to libraries folder (e.g. -Dforgewrapper.librariesDir=/home/xxx/.minecraft/libraries)
|
||||
- `forgewrapper.installer` : a path to forge installer (e.g. -Dforgewrapper.installer=/home/xxx/forge-1.14.4-28.2.0-installer.jar)
|
||||
- `forgewrapper.minecraft` : a path to the vanilla minecraft jar (e.g. -Dforgewrapper.minecraft=/home/xxx/.minecraft/versions/1.14.4/1.14.4.jar)
|
||||
|
||||
2. ForgeWrapper also provides an interface [`IFileDetector`](https://github.com/ZekerZhayard/ForgeWrapper/blob/master/src/main/java/io/github/zekerzhayard/forgewrapper/installer/detector/IFileDetector.java), you can implement it and custom your own detecting rules. To load it, you should make another jar which contains `META-INF/services/io.github.zekerzhayard.forgewrapper.installer.detector.IFileDetector` within the full implementation class name and add the jar to class path.
|
||||
|
||||
## How to use (Outdated)
|
||||
|
||||
1. Download Forge installer for Minecraft 1.13+ [here](https://files.minecraftforge.net/).
|
||||
2. Download ForgeWrapper jar file at the [release](https://github.com/ZekerZhayard/ForgeWrapper/releases) page.
|
||||
3. Since ForgeWrapper 1.5.1, it no longer includes the json converter, so you need to build it by yourself:
|
||||
- [Download](https://github.com/ZekerZhayard/ForgeWrapper/archive/refs/heads/master.zip) ForgeWrapper sources.
|
||||
- Extract the zip and open terminal in the extracted folder.
|
||||
- Run `./gradlew converter:build` command in terminal and get the jar from `./converter/build/libs`
|
||||
3. Run the below command in terminal:
|
||||
```
|
||||
java -jar <ForgeWrapper.jar> --installer=<forge-installer.jar> [--instance=<instance-path>]
|
||||
```
|
||||
*Notice: If you don't specify a MultiMC instance path, ForgeWrapper will create the instance folder in current working space.*
|
||||
|
||||
4. If the instance folder which just created is not in `MultiMC/instances` folder, you just need to move to the `MultiMC/instances` folder.
|
||||
5. Run MultiMC, and you will see a new instance named `forge-<mcVersion>-<forgeVersion>`.
|
95
build.gradle
95
build.gradle
|
@ -1,95 +0,0 @@
|
|||
|
||||
plugins {
|
||||
id "java"
|
||||
id "eclipse"
|
||||
id "maven-publish"
|
||||
}
|
||||
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
version = "${fw_version}${-> getVersionSuffix()}"
|
||||
group = "io.github.zekerzhayard"
|
||||
archivesBaseName = rootProject.name
|
||||
|
||||
configurations {
|
||||
provided {
|
||||
implementation.extendsFrom provided
|
||||
}
|
||||
multirelase {
|
||||
implementation.extendsFrom multirelase
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://maven.minecraftforge.net/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly "com.google.code.gson:gson:2.8.7"
|
||||
compileOnly "cpw.mods:modlauncher:8.0.9"
|
||||
compileOnly "net.minecraftforge:installer:2.2.7"
|
||||
compileOnly "net.sf.jopt-simple:jopt-simple:5.0.4"
|
||||
|
||||
provided project(":common")
|
||||
provided project(":legacy")
|
||||
multirelase project(":jigsaw")
|
||||
}
|
||||
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest.attributes([
|
||||
"Specification-Title": "${project.name}",
|
||||
"Specification-Vendor": "ZekerZhayard",
|
||||
"Specification-Version": "${project.version}".split("-")[0],
|
||||
"Implementation-Title": "${project.name}",
|
||||
"Implementation-Version": "${project.version}",
|
||||
"Implementation-Vendor" :"ZekerZhayard",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
"Automatic-Module-Name": "${project.group}.${project.archivesBaseName}".toString().toLowerCase(),
|
||||
"Multi-Release": "true",
|
||||
"GitCommit": String.valueOf(System.getenv("GITHUB_SHA"))
|
||||
])
|
||||
|
||||
from configurations.provided.files.collect {
|
||||
zipTree(it)
|
||||
}
|
||||
|
||||
into "META-INF/versions/9", {
|
||||
from configurations.multirelase.files.collect {
|
||||
zipTree(it)
|
||||
}
|
||||
exclude "META-INF/**"
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId "${project.group}"
|
||||
artifactId "${project.archivesBaseName}"
|
||||
version "${project.version}"
|
||||
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url = layout.buildDirectory.dir("maven")
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.publish.dependsOn build
|
||||
|
||||
static String getVersionSuffix() {
|
||||
return ""
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
plugins {
|
||||
id "java"
|
||||
id "eclipse"
|
||||
id "maven-publish"
|
||||
}
|
||||
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.util;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CheckedLambdaUtil {
|
||||
public static <T> Consumer<T> wrapConsumer(CheckedConsumer<T> consumer) {
|
||||
return consumer;
|
||||
}
|
||||
|
||||
public static <T, U> BiConsumer<T, U> wrapBiConsumer(CheckedBiConsumer<T, U> biconsumer) {
|
||||
return biconsumer;
|
||||
}
|
||||
|
||||
public interface CheckedConsumer<T> extends Consumer<T> {
|
||||
void checkedAccept(T t) throws Throwable;
|
||||
|
||||
@Override
|
||||
default void accept(T t) {
|
||||
try {
|
||||
this.checkedAccept(t);
|
||||
} catch (Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface CheckedBiConsumer<T, U> extends BiConsumer<T, U> {
|
||||
void checkedAccept(T t, U u) throws Throwable;
|
||||
|
||||
@Override
|
||||
default void accept(T t, U u) {
|
||||
try {
|
||||
this.checkedAccept(t, u);
|
||||
} catch (Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
org.gradle.daemon = false
|
||||
|
||||
fw_version = mmc5
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +0,0 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
234
gradlew
vendored
234
gradlew
vendored
|
@ -1,234 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
89
gradlew.bat
vendored
89
gradlew.bat
vendored
|
@ -1,89 +0,0 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
41889b31cb86400ad7053037e006407a
|
|
@ -0,0 +1 @@
|
|||
5ecf7d1102a4a0e82ad82b4a5499130c0bf7102b
|
|
@ -0,0 +1 @@
|
|||
6d8efdbda45653934d0a28797987c8783710026f7c42b3ea5e2c3f7117a7af70
|
|
@ -0,0 +1 @@
|
|||
fac731ea67b9d44822afbc3d21346be4efef68e6445124195566674d48c180c7e1143bffe9b985a890f8631173356d1bac2e72b94d30f0fe89242a312abfe60f
|
BIN
io/github/zekerzhayard/ForgeWrapper/1.5.1/ForgeWrapper-1.5.1.jar
Normal file
BIN
io/github/zekerzhayard/ForgeWrapper/1.5.1/ForgeWrapper-1.5.1.jar
Normal file
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
919e2d600b673fce7be6ac2d0ed1b62f
|
|
@ -0,0 +1 @@
|
|||
90104e9aaa8fbedf6c3d1f6d0b90cabce080b5a9
|
|
@ -0,0 +1 @@
|
|||
d608aad3a92d69c1c9f93c019d671b7242a4383451edeb728bb2482d2b900164
|
|
@ -0,0 +1 @@
|
|||
a64e471f5f7487cace9cf7d531a554edc1977b9e5f4fc28ddcfa7a8ec4e2de9af0f5fd9aa8466eab596222f5fd3b6c43e029234498132f61eabbb386877b9f34
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"formatVersion": "1.1",
|
||||
"component": {
|
||||
"group": "io.github.zekerzhayard",
|
||||
"module": "ForgeWrapper",
|
||||
"version": "1.5.1",
|
||||
"attributes": {
|
||||
"org.gradle.status": "release"
|
||||
}
|
||||
},
|
||||
"createdBy": {
|
||||
"gradle": {
|
||||
"version": "7.1.1"
|
||||
}
|
||||
},
|
||||
"variants": [
|
||||
{
|
||||
"name": "apiElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "library",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.jvm.version": 8,
|
||||
"org.gradle.libraryelements": "jar",
|
||||
"org.gradle.usage": "java-api"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.1.jar",
|
||||
"url": "ForgeWrapper-1.5.1.jar",
|
||||
"size": 29892,
|
||||
"sha512": "a64e471f5f7487cace9cf7d531a554edc1977b9e5f4fc28ddcfa7a8ec4e2de9af0f5fd9aa8466eab596222f5fd3b6c43e029234498132f61eabbb386877b9f34",
|
||||
"sha256": "d608aad3a92d69c1c9f93c019d671b7242a4383451edeb728bb2482d2b900164",
|
||||
"sha1": "90104e9aaa8fbedf6c3d1f6d0b90cabce080b5a9",
|
||||
"md5": "919e2d600b673fce7be6ac2d0ed1b62f"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "runtimeElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "library",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.jvm.version": 8,
|
||||
"org.gradle.libraryelements": "jar",
|
||||
"org.gradle.usage": "java-runtime"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.1.jar",
|
||||
"url": "ForgeWrapper-1.5.1.jar",
|
||||
"size": 29892,
|
||||
"sha512": "a64e471f5f7487cace9cf7d531a554edc1977b9e5f4fc28ddcfa7a8ec4e2de9af0f5fd9aa8466eab596222f5fd3b6c43e029234498132f61eabbb386877b9f34",
|
||||
"sha256": "d608aad3a92d69c1c9f93c019d671b7242a4383451edeb728bb2482d2b900164",
|
||||
"sha1": "90104e9aaa8fbedf6c3d1f6d0b90cabce080b5a9",
|
||||
"md5": "919e2d600b673fce7be6ac2d0ed1b62f"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sourcesElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "documentation",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.docstype": "sources",
|
||||
"org.gradle.usage": "java-runtime"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.1-sources.jar",
|
||||
"url": "ForgeWrapper-1.5.1-sources.jar",
|
||||
"size": 11159,
|
||||
"sha512": "fac731ea67b9d44822afbc3d21346be4efef68e6445124195566674d48c180c7e1143bffe9b985a890f8631173356d1bac2e72b94d30f0fe89242a312abfe60f",
|
||||
"sha256": "6d8efdbda45653934d0a28797987c8783710026f7c42b3ea5e2c3f7117a7af70",
|
||||
"sha1": "5ecf7d1102a4a0e82ad82b4a5499130c0bf7102b",
|
||||
"md5": "41889b31cb86400ad7053037e006407a"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
8364e8fb861af074298cfd2b0515fbf6
|
|
@ -0,0 +1 @@
|
|||
35a5933bba957f90603795b96311417aa5e589bd
|
|
@ -0,0 +1 @@
|
|||
700a7015e64e078dbd537221253336ad10714f85c93ed7695684e22e6b95fe2e
|
|
@ -0,0 +1 @@
|
|||
1e2108a899a30c9d05ac6485e598753839ec1fc2434d9c3d398614b77aec77e93a2dc8f5d1bbac3943f3a34f2c1e60753aa6f02890ecc5230c568587ec022e83
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<!-- This module was also published with a richer model, Gradle metadata, -->
|
||||
<!-- which should be used instead. Do not delete the following line which -->
|
||||
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
|
||||
<!-- that they should prefer consuming it instead. -->
|
||||
<!-- do_not_remove: published-with-gradle-metadata -->
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.zekerzhayard</groupId>
|
||||
<artifactId>ForgeWrapper</artifactId>
|
||||
<version>1.5.1</version>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
5cc4dce491edbbfb72a2e4c4bf7ea0a0
|
|
@ -0,0 +1 @@
|
|||
fe75a10e3a7c222e481a7f9e8a366c7c1a73f397
|
|
@ -0,0 +1 @@
|
|||
0f1746d3c6c7dccc87f0973d0e94723141483f13ae72cf746f42796dc8da9a00
|
|
@ -0,0 +1 @@
|
|||
23cc1112881f0d28aed622038a90fa755559dcde659d356188721318fd513946a020b40465d43b42fe1017be21c7d5b960c26d9a6a839fc31e1dfb6289fd8e42
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
b39d7be0ba9c39f4e8de4e6d1b57407b
|
|
@ -0,0 +1 @@
|
|||
591fbc653b4a1e6f5c138f30600aad4c72478e00
|
|
@ -0,0 +1 @@
|
|||
9bb6df432f8aff1b99775055e92564f408b4150ed06e3ea26e8b61e7594152fd
|
|
@ -0,0 +1 @@
|
|||
f08531024141fc6a17b28635851e7e6d470652979ed3986cf8104a46a6133741abadfb01d51ecb2544fb1ed5c23f8d64f4d003a5fc7215b494e3d76ef07ea9de
|
BIN
io/github/zekerzhayard/ForgeWrapper/1.5.2/ForgeWrapper-1.5.2.jar
Normal file
BIN
io/github/zekerzhayard/ForgeWrapper/1.5.2/ForgeWrapper-1.5.2.jar
Normal file
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
c0e7e25903cfb7dd6e671f12687abc4d
|
|
@ -0,0 +1 @@
|
|||
6930ac286c079a9df5b766974020ef7ad1fc5d3b
|
|
@ -0,0 +1 @@
|
|||
4343dd57b6494042ae975314d3a7b788777c18741e81bfae1352d7e46e79db43
|
|
@ -0,0 +1 @@
|
|||
4dbebbbc4eaeb5c8596717876c98a469066891ce619ac651d8ae15237200c8c51d8d1398c11c73fc101eef89624711331c5cadba236b521b746c8ae07ba1bc1b
|
|
@ -0,0 +1,103 @@
|
|||
{
|
||||
"formatVersion": "1.1",
|
||||
"component": {
|
||||
"group": "io.github.zekerzhayard",
|
||||
"module": "ForgeWrapper",
|
||||
"version": "1.5.2",
|
||||
"attributes": {
|
||||
"org.gradle.status": "release"
|
||||
}
|
||||
},
|
||||
"createdBy": {
|
||||
"gradle": {
|
||||
"version": "7.1.1"
|
||||
}
|
||||
},
|
||||
"variants": [
|
||||
{
|
||||
"name": "apiElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "library",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.jvm.version": 8,
|
||||
"org.gradle.libraryelements": "jar",
|
||||
"org.gradle.usage": "java-api"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.2.jar",
|
||||
"url": "ForgeWrapper-1.5.2.jar",
|
||||
"size": 34217,
|
||||
"sha512": "4dbebbbc4eaeb5c8596717876c98a469066891ce619ac651d8ae15237200c8c51d8d1398c11c73fc101eef89624711331c5cadba236b521b746c8ae07ba1bc1b",
|
||||
"sha256": "4343dd57b6494042ae975314d3a7b788777c18741e81bfae1352d7e46e79db43",
|
||||
"sha1": "6930ac286c079a9df5b766974020ef7ad1fc5d3b",
|
||||
"md5": "c0e7e25903cfb7dd6e671f12687abc4d"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "runtimeElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "library",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.jvm.version": 8,
|
||||
"org.gradle.libraryelements": "jar",
|
||||
"org.gradle.usage": "java-runtime"
|
||||
},
|
||||
"dependencies": [
|
||||
{
|
||||
"group": "ForgeWrapper",
|
||||
"module": "common",
|
||||
"version": {
|
||||
"requires": "unspecified"
|
||||
}
|
||||
},
|
||||
{
|
||||
"group": "ForgeWrapper",
|
||||
"module": "legacy",
|
||||
"version": {
|
||||
"requires": "unspecified"
|
||||
}
|
||||
},
|
||||
{
|
||||
"group": "ForgeWrapper",
|
||||
"module": "jigsaw",
|
||||
"version": {
|
||||
"requires": "unspecified"
|
||||
}
|
||||
}
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.2.jar",
|
||||
"url": "ForgeWrapper-1.5.2.jar",
|
||||
"size": 34217,
|
||||
"sha512": "4dbebbbc4eaeb5c8596717876c98a469066891ce619ac651d8ae15237200c8c51d8d1398c11c73fc101eef89624711331c5cadba236b521b746c8ae07ba1bc1b",
|
||||
"sha256": "4343dd57b6494042ae975314d3a7b788777c18741e81bfae1352d7e46e79db43",
|
||||
"sha1": "6930ac286c079a9df5b766974020ef7ad1fc5d3b",
|
||||
"md5": "c0e7e25903cfb7dd6e671f12687abc4d"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sourcesElements",
|
||||
"attributes": {
|
||||
"org.gradle.category": "documentation",
|
||||
"org.gradle.dependency.bundling": "external",
|
||||
"org.gradle.docstype": "sources",
|
||||
"org.gradle.usage": "java-runtime"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"name": "ForgeWrapper-1.5.2-sources.jar",
|
||||
"url": "ForgeWrapper-1.5.2-sources.jar",
|
||||
"size": 10991,
|
||||
"sha512": "f08531024141fc6a17b28635851e7e6d470652979ed3986cf8104a46a6133741abadfb01d51ecb2544fb1ed5c23f8d64f4d003a5fc7215b494e3d76ef07ea9de",
|
||||
"sha256": "9bb6df432f8aff1b99775055e92564f408b4150ed06e3ea26e8b61e7594152fd",
|
||||
"sha1": "591fbc653b4a1e6f5c138f30600aad4c72478e00",
|
||||
"md5": "b39d7be0ba9c39f4e8de4e6d1b57407b"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
20d43d76411b60cf6b5e4bf2f0b29ee1
|
|
@ -0,0 +1 @@
|
|||
b705958a45e34838ca8960b92aeb004102703430
|
|
@ -0,0 +1 @@
|
|||
2b45aa3253a33e7c974b0b117ecd145ac1d576b7e0e44a301c282329809be60f
|
|
@ -0,0 +1 @@
|
|||
f74f2f5004b7def67bea597620cbd60d580d20a3e481f0067a39a3f31dd1e169449e55b48ad43c28bb75905db2c41e9db54aeae934873d5ffbfa739f0f9e1eda
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<!-- This module was also published with a richer model, Gradle metadata, -->
|
||||
<!-- which should be used instead. Do not delete the following line which -->
|
||||
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
|
||||
<!-- that they should prefer consuming it instead. -->
|
||||
<!-- do_not_remove: published-with-gradle-metadata -->
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.zekerzhayard</groupId>
|
||||
<artifactId>ForgeWrapper</artifactId>
|
||||
<version>1.5.2</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ForgeWrapper</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>unspecified</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ForgeWrapper</groupId>
|
||||
<artifactId>legacy</artifactId>
|
||||
<version>unspecified</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ForgeWrapper</groupId>
|
||||
<artifactId>jigsaw</artifactId>
|
||||
<version>unspecified</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
fb70106ce9159b84433ba4b2d1a77620
|
|
@ -0,0 +1 @@
|
|||
ae262432af313ca91bf7964dad024141941fb49f
|
|
@ -0,0 +1 @@
|
|||
88919ff705ede755d192fac2b1eff8cea3f557f6874a8b09ebc5862d2616ab30
|
|
@ -0,0 +1 @@
|
|||
2904338de4bd110750b4d1c440118545ceefd10b451af76123b8ce3c18c59656dd02499138dd7b91f919ca2909c3ec00ffef419e56908ac4234836242d3e0ce3
|
14
io/github/zekerzhayard/ForgeWrapper/maven-metadata.xml
Normal file
14
io/github/zekerzhayard/ForgeWrapper/maven-metadata.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>io.github.zekerzhayard</groupId>
|
||||
<artifactId>ForgeWrapper</artifactId>
|
||||
<versioning>
|
||||
<latest>1.5.2</latest>
|
||||
<release>1.5.2</release>
|
||||
<versions>
|
||||
<version>1.5.1</version>
|
||||
<version>1.5.2</version>
|
||||
</versions>
|
||||
<lastUpdated>20210813145125</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
|
@ -0,0 +1 @@
|
|||
7c5893df39f20bee0aa0ebc574569b30
|
|
@ -0,0 +1 @@
|
|||
4ae15411c53571d1834d004d5c2148c828cd0e98
|
|
@ -0,0 +1 @@
|
|||
fff3fdc18b163259a42b5426d47ffefdfabbb3b9d425bfacce6725cb339e8a06
|
|
@ -0,0 +1 @@
|
|||
103393c6705b2794ea6be7165a739ca80d88d337b577b7e6e5e72dce4d89c638dd3f526f0c0745a461e650b081246e3aa8783a35a78d8bd4130464b899c02ec0
|
|
@ -1,32 +0,0 @@
|
|||
|
||||
plugins {
|
||||
id "java"
|
||||
id "eclipse"
|
||||
}
|
||||
|
||||
compileJava {
|
||||
if (JavaVersion.current() < JavaVersion.VERSION_1_9) {
|
||||
javaCompiler = javaToolchains.compilerFor {
|
||||
languageVersion = JavaLanguageVersion.of(9)
|
||||
}
|
||||
}
|
||||
sourceCompatibility = 9
|
||||
targetCompatibility = 9
|
||||
}
|
||||
|
||||
configurations {
|
||||
apiElements {
|
||||
attributes {
|
||||
attribute TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8
|
||||
}
|
||||
}
|
||||
runtimeElements {
|
||||
attributes {
|
||||
attribute TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":common")
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.github.zekerzhayard.forgewrapper.util.CheckedLambdaUtil;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class ModuleUtil {
|
||||
private final static MethodHandles.Lookup IMPL_LOOKUP = getImplLookup();
|
||||
|
||||
private static MethodHandles.Lookup getImplLookup() {
|
||||
try {
|
||||
// Get theUnsafe
|
||||
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
Unsafe unsafe = (Unsafe) unsafeField.get(null);
|
||||
|
||||
// Get IMPL_LOOKUP
|
||||
Field implLookupField = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
|
||||
return (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(implLookupField), unsafe.staticFieldOffset(implLookupField));
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add module-path at runtime
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void addModules(String modulePath) throws Throwable {
|
||||
// Find all extra modules, exclude all existing modules
|
||||
ModuleFinder finder = ModuleFinder.of(Stream.of(modulePath.split(File.pathSeparator)).map(Paths::get).filter(p -> ModuleFinder.of(p).findAll().stream().noneMatch(mref -> ModuleLayer.boot().findModule(mref.descriptor().name()).isPresent())).toArray(Path[]::new));
|
||||
MethodHandle loadModuleMH = IMPL_LOOKUP.findVirtual(Class.forName("jdk.internal.loader.BuiltinClassLoader"), "loadModule", MethodType.methodType(void.class, ModuleReference.class));
|
||||
|
||||
// Resolve modules to a new config and load all extra modules in system class loader (unnamed modules for now)
|
||||
Configuration config = Configuration.resolveAndBind(finder, List.of(ModuleLayer.boot().configuration()), finder, finder.findAll().stream().filter(mref -> !ModuleLayer.boot().findModule(mref.descriptor().name()).isPresent()).peek(CheckedLambdaUtil.wrapConsumer(mref -> loadModuleMH.invokeWithArguments(ClassLoader.getSystemClassLoader(), mref))).map(mref -> mref.descriptor().name()).collect(Collectors.toList()));
|
||||
|
||||
// Copy the new config graph to boot module layer config
|
||||
MethodHandle graphGetter = IMPL_LOOKUP.findGetter(Configuration.class, "graph", Map.class);
|
||||
HashMap<ResolvedModule, Set<ResolvedModule>> graphMap = new HashMap<>((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(config));
|
||||
MethodHandle cfSetter = IMPL_LOOKUP.findSetter(ResolvedModule.class, "cf", Configuration.class);
|
||||
// Reset all extra resolved modules config to boot module layer config
|
||||
graphMap.forEach(CheckedLambdaUtil.wrapBiConsumer((k, v) -> {
|
||||
cfSetter.invokeWithArguments(k, ModuleLayer.boot().configuration());
|
||||
v.forEach(CheckedLambdaUtil.wrapConsumer(m -> cfSetter.invokeWithArguments(m, ModuleLayer.boot().configuration())));
|
||||
}));
|
||||
graphMap.putAll((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
|
||||
IMPL_LOOKUP.findSetter(Configuration.class, "graph", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(graphMap));
|
||||
|
||||
// Reset boot module layer resolved modules as new config resolved modules to prepare define modules
|
||||
Set<ResolvedModule> oldBootModules = ModuleLayer.boot().configuration().modules();
|
||||
MethodHandle modulesSetter = IMPL_LOOKUP.findSetter(Configuration.class, "modules", Set.class);
|
||||
HashSet<ResolvedModule> modulesSet = new HashSet<>(config.modules());
|
||||
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
|
||||
|
||||
// Prepare to add all the new config "nameToModule" to boot module layer config
|
||||
MethodHandle nameToModuleGetter = IMPL_LOOKUP.findGetter(Configuration.class, "nameToModule", Map.class);
|
||||
HashMap<String, ResolvedModule> nameToModuleMap = new HashMap<>((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
|
||||
nameToModuleMap.putAll((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(config));
|
||||
IMPL_LOOKUP.findSetter(Configuration.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(nameToModuleMap));
|
||||
|
||||
// Define all extra modules and add all the new config "nameToModule" to boot module layer config
|
||||
((Map<String, Module>) IMPL_LOOKUP.findGetter(ModuleLayer.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot())).putAll((Map<String, Module>) IMPL_LOOKUP.findStatic(Module.class, "defineModules", MethodType.methodType(Map.class, Configuration.class, Function.class, ModuleLayer.class)).invokeWithArguments(ModuleLayer.boot().configuration(), (Function<String, ClassLoader>) name -> ClassLoader.getSystemClassLoader(), ModuleLayer.boot()));
|
||||
|
||||
// Add all of resolved modules
|
||||
modulesSet.addAll(oldBootModules);
|
||||
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
|
||||
|
||||
// Reset cache of boot module layer
|
||||
IMPL_LOOKUP.findSetter(ModuleLayer.class, "modules", Set.class).invokeWithArguments(ModuleLayer.boot(), null);
|
||||
IMPL_LOOKUP.findSetter(ModuleLayer.class, "servicesCatalog", Class.forName("jdk.internal.module.ServicesCatalog")).invokeWithArguments(ModuleLayer.boot(), null);
|
||||
|
||||
// Add reads from extra modules to jdk modules
|
||||
MethodHandle implAddReadsMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddReads", MethodType.methodType(void.class, Module.class));
|
||||
config.modules().forEach(rm -> ModuleLayer.boot().findModule(rm.name()).ifPresent(m -> oldBootModules.forEach(brm -> ModuleLayer.boot().findModule(brm.name()).ifPresent(CheckedLambdaUtil.wrapConsumer(bm -> implAddReadsMH.invokeWithArguments(m, bm))))));
|
||||
}
|
||||
|
||||
public static void addExports(List<String> exports) {
|
||||
TypeToAdd.EXPORTS.implAdd(exports);
|
||||
}
|
||||
|
||||
public static void addOpens(List<String> opens) {
|
||||
TypeToAdd.OPENS.implAdd(opens);
|
||||
}
|
||||
|
||||
public static ClassLoader getPlatformClassLoader() {
|
||||
return ClassLoader.getPlatformClassLoader();
|
||||
}
|
||||
|
||||
private enum TypeToAdd {
|
||||
EXPORTS("Exports"),
|
||||
OPENS("Opens");
|
||||
|
||||
private final MethodHandle implAddMH;
|
||||
private final MethodHandle implAddToAllUnnamedMH;
|
||||
|
||||
TypeToAdd(String name) {
|
||||
try {
|
||||
this.implAddMH = IMPL_LOOKUP.findVirtual(Module.class, "implAdd" + name, MethodType.methodType(void.class, String.class, Module.class));
|
||||
this.implAddToAllUnnamedMH = IMPL_LOOKUP.findVirtual(Module.class, "implAdd" + name + "ToAllUnnamed", MethodType.methodType(void.class, String.class));
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
void implAdd(List<String> extras) {
|
||||
extras.stream().map(ModuleUtil::parseModuleExtra).filter(Optional::isPresent).map(Optional::get).forEach(CheckedLambdaUtil.wrapConsumer(data -> ModuleLayer.boot().findModule(data.module).ifPresent(CheckedLambdaUtil.wrapConsumer(m -> {
|
||||
if ("ALL-UNNAMED".equals(data.target)) {
|
||||
this.implAddToAllUnnamedMH.invokeWithArguments(m, data.packages);
|
||||
} else {
|
||||
ModuleLayer.boot().findModule(data.target).ifPresent(CheckedLambdaUtil.wrapConsumer(tm -> this.implAddMH.invokeWithArguments(m, data.packages, tm)));
|
||||
}
|
||||
}))));
|
||||
}
|
||||
}
|
||||
|
||||
// <module>/<package>=<target>
|
||||
private static Optional<ParserData> parseModuleExtra(String extra) {
|
||||
String[] all = extra.split("=", 2);
|
||||
if (all.length < 2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String[] source = all[0].split("/", 2);
|
||||
if (source.length < 2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new ParserData(source[0], source[1], all[1]));
|
||||
}
|
||||
|
||||
private static class ParserData {
|
||||
final String module;
|
||||
final String packages;
|
||||
final String target;
|
||||
|
||||
ParserData(String module, String packages, String target) {
|
||||
this.module = module;
|
||||
this.packages = packages;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setupClassPath(Path libraryDir, List<String> paths) throws Throwable {
|
||||
Class<?> urlClassPathClass = Class.forName("jdk.internal.loader.URLClassPath");
|
||||
Object ucp = IMPL_LOOKUP.findGetter(Class.forName("jdk.internal.loader.BuiltinClassLoader"), "ucp", urlClassPathClass).invokeWithArguments(ClassLoader.getSystemClassLoader());
|
||||
MethodHandle addURLMH = IMPL_LOOKUP.findVirtual(urlClassPathClass, "addURL", MethodType.methodType(void.class, URL.class));
|
||||
for (String path : paths) {
|
||||
addURLMH.invokeWithArguments(ucp, libraryDir.resolve(path).toUri().toURL());
|
||||
}
|
||||
}
|
||||
|
||||
// ForgeWrapper need some extra settings to invoke BootstrapLauncher.
|
||||
public static Class<?> setupBootstrapLauncher(Class<?> mainClass) throws Throwable {
|
||||
if (!mainClass.getModule().isOpen(mainClass.getPackageName(), ModuleUtil.class.getModule())) {
|
||||
TypeToAdd.OPENS.implAddMH.invokeWithArguments(mainClass.getModule(), mainClass.getPackageName(), ModuleUtil.class.getModule());
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
plugins {
|
||||
id "java"
|
||||
id "eclipse"
|
||||
}
|
||||
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://maven.minecraftforge.net/"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly "net.minecraftforge:installer:2.0.24"
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.util;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraftforge.installer.actions.ProgressCallback;
|
||||
import net.minecraftforge.installer.json.Install;
|
||||
|
||||
public abstract class AbstractInstaller {
|
||||
public abstract Install loadInstallProfile();
|
||||
|
||||
public abstract boolean runClientInstall(Install profile, ProgressCallback monitor, File libraryDir, File minecraftJar, File installerJar);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.minecraftforge.installer.actions.ClientInstall;
|
||||
import net.minecraftforge.installer.actions.ProgressCallback;
|
||||
import net.minecraftforge.installer.json.Install;
|
||||
import net.minecraftforge.installer.json.Util;
|
||||
|
||||
public class InstallerV0 extends AbstractInstaller {
|
||||
@Override
|
||||
public Install loadInstallProfile() {
|
||||
return Util.loadInstallProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runClientInstall(Install profile, ProgressCallback monitor, File libraryDir, File minecraftJar, File installerJar) {
|
||||
return new ClientInstall4MultiMC(profile, monitor, libraryDir, minecraftJar).run(null, input -> true);
|
||||
}
|
||||
|
||||
public static class ClientInstall4MultiMC extends ClientInstall {
|
||||
protected File libraryDir;
|
||||
protected File minecraftJar;
|
||||
|
||||
public ClientInstall4MultiMC(Install profile, ProgressCallback monitor, File libraryDir, File minecraftJar) {
|
||||
super(profile, monitor);
|
||||
this.libraryDir = libraryDir;
|
||||
this.minecraftJar = minecraftJar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean run(File target, Predicate<String> optionals) {
|
||||
return this.processors.process(this.libraryDir, this.minecraftJar);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
rootProject.name = 'ForgeWrapper'
|
||||
|
||||
include 'common'
|
||||
include 'legacy'
|
||||
include 'jigsaw'
|
|
@ -1,70 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.zekerzhayard.forgewrapper.installer.util.ModuleUtil;
|
||||
|
||||
public class Bootstrap {
|
||||
public static void bootstrap(List<String> jvmArgs, String minecraftJar, String libraryDir) throws Throwable {
|
||||
// Replace all placeholders
|
||||
List<String> replacedJvmArgs = new ArrayList<>();
|
||||
for (String arg : jvmArgs) {
|
||||
replacedJvmArgs.add(arg.replace("${classpath}", System.getProperty("java.class.path").replace(File.separator, "/")).replace("${classpath_separator}", File.pathSeparator).replace("${library_directory}", libraryDir).replace("${version_name}", minecraftJar.substring(0, minecraftJar.lastIndexOf('.'))));
|
||||
}
|
||||
jvmArgs = replacedJvmArgs;
|
||||
|
||||
// Remove NewLaunch.jar from property to prevent Forge from adding it to the module path
|
||||
StringBuilder newCP = new StringBuilder();
|
||||
for (String path : System.getProperty("java.class.path").split(File.pathSeparator)) {
|
||||
if (!path.endsWith("NewLaunch.jar")) {
|
||||
newCP.append(path).append(File.pathSeparator);
|
||||
}
|
||||
}
|
||||
System.setProperty("java.class.path", newCP.substring(0, newCP.length() - 1));
|
||||
|
||||
String modulePath = null;
|
||||
List<String> addExports = new ArrayList<>();
|
||||
List<String> addOpens = new ArrayList<>();
|
||||
for (int i = 0; i < jvmArgs.size(); i++) {
|
||||
String arg = jvmArgs.get(i);
|
||||
|
||||
if (arg.equals("-p") || arg.equals("--module-path")) {
|
||||
modulePath = jvmArgs.get(i + 1);
|
||||
} else if (arg.startsWith("--module-path=")) {
|
||||
modulePath = arg.split("=", 2)[1];
|
||||
}
|
||||
|
||||
if (arg.equals("--add-exports")) {
|
||||
addExports.add(jvmArgs.get(i + 1));
|
||||
} else if (arg.startsWith("--add-exports=")) {
|
||||
addExports.add(arg.split("=", 2)[1]);
|
||||
}
|
||||
|
||||
if (arg.equals("--add-opens")) {
|
||||
addOpens.add(jvmArgs.get(i + 1));
|
||||
} else if (arg.startsWith("--add-opens=")) {
|
||||
addOpens.add(arg.split("=", 2)[1]);
|
||||
}
|
||||
|
||||
// Java properties
|
||||
if (arg.startsWith("-D")) {
|
||||
String[] prop = arg.substring(2).split("=", 2);
|
||||
|
||||
if (prop[0].equals("ignoreList")) {
|
||||
// The default ignoreList may cause some problems, so we define it more precisely.
|
||||
System.setProperty(prop[0], prop[1] + ",NewLaunch.jar,ForgeWrapper-," + minecraftJar);
|
||||
} else {
|
||||
System.setProperty(prop[0], prop[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modulePath != null) {
|
||||
ModuleUtil.addModules(modulePath);
|
||||
}
|
||||
ModuleUtil.addExports(addExports);
|
||||
ModuleUtil.addOpens(addOpens);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import io.github.zekerzhayard.forgewrapper.installer.util.AbstractInstaller;
|
||||
import io.github.zekerzhayard.forgewrapper.installer.util.InstallerV0;
|
||||
import io.github.zekerzhayard.forgewrapper.installer.util.InstallerV1;
|
||||
import net.minecraftforge.installer.actions.ProgressCallback;
|
||||
import net.minecraftforge.installer.json.Install;
|
||||
import net.minecraftforge.installer.json.InstallV1;
|
||||
import net.minecraftforge.installer.json.Util;
|
||||
|
||||
public class Installer {
|
||||
public static boolean install(File libraryDir, File minecraftJar, File installerJar) {
|
||||
AbstractInstaller installer = createInstaller();
|
||||
ProgressCallback monitor = ProgressCallback.withOutputs(System.out);
|
||||
Install profile = installer.loadInstallProfile();
|
||||
if (System.getProperty("java.net.preferIPv4Stack") == null) {
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
}
|
||||
String vendor = System.getProperty("java.vendor", "missing vendor");
|
||||
String javaVersion = System.getProperty("java.version", "missing java version");
|
||||
String jvmVersion = System.getProperty("java.vm.version", "missing jvm version");
|
||||
monitor.message(String.format("JVM info: %s - %s - %s", vendor, javaVersion, jvmVersion));
|
||||
monitor.message("java.net.preferIPv4Stack=" + System.getProperty("java.net.preferIPv4Stack"));
|
||||
return installer.runClientInstall(profile, monitor, libraryDir, minecraftJar, installerJar);
|
||||
}
|
||||
|
||||
private static AbstractInstaller createInstaller() {
|
||||
try {
|
||||
Class<?> installerClass = Util.class.getMethod("loadInstallProfile").getReturnType();
|
||||
if (installerClass.equals(Install.class)) {
|
||||
return new InstallerV0();
|
||||
} else if (installerClass.equals(InstallV1.class)) {
|
||||
return new InstallerV1();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unable to determine the installer version. (" + installerClass + ")");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
import io.github.zekerzhayard.forgewrapper.installer.detector.DetectorLoader;
|
||||
import io.github.zekerzhayard.forgewrapper.installer.detector.IFileDetector;
|
||||
import io.github.zekerzhayard.forgewrapper.installer.util.ModuleUtil;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
// --fml.neoForgeVersion 20.2.20-beta --fml.fmlVersion 1.0.2 --fml.mcVersion 1.20.2 --fml.neoFormVersion 20231019.002635 --launchTarget forgeclient
|
||||
|
||||
List<String> argsList = Stream.of(args).collect(Collectors.toList());
|
||||
// NOTE: this is only true for NeoForge versions past 20.2.x
|
||||
// early versions of NeoForge (for 1.20.1) are not supposed to be covered here
|
||||
boolean isNeoForge = argsList.contains("--fml.neoForgeVersion");
|
||||
|
||||
String mcVersion = argsList.get(argsList.indexOf("--fml.mcVersion") + 1);
|
||||
String forgeGroup = argsList.contains("--fml.forgeGroup") ? argsList.get(argsList.indexOf("--fml.forgeGroup") + 1) : "net.neoforged";
|
||||
String forgeArtifact = isNeoForge ? "neoforge" : "forge";
|
||||
String forgeVersionKey = isNeoForge ? "--fml.neoForgeVersion" : "--fml.forgeVersion";
|
||||
String forgeVersion = argsList.get(argsList.indexOf(forgeVersionKey) + 1);
|
||||
String forgeFullVersion = isNeoForge ? forgeVersion : mcVersion + "-" + forgeVersion;
|
||||
|
||||
IFileDetector detector = DetectorLoader.loadDetector();
|
||||
try {
|
||||
Bootstrap.bootstrap(detector.getJvmArgs(forgeGroup, forgeArtifact, forgeFullVersion), detector.getMinecraftJar(mcVersion).getFileName().toString(), detector.getLibraryDir().toAbsolutePath().toString());
|
||||
} catch (Throwable ignored) {
|
||||
// Avoid this bunch of hacks that nuke the whole wrapper.
|
||||
}
|
||||
if (!detector.checkExtraFiles(forgeGroup, forgeArtifact, forgeFullVersion)) {
|
||||
System.out.println("Some extra libraries are missing! Running the installer to generate them now.");
|
||||
|
||||
// Check installer jar.
|
||||
Path installerJar = detector.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion);
|
||||
if (!IFileDetector.isFile(installerJar)) {
|
||||
throw new RuntimeException("Unable to detect the forge installer!");
|
||||
}
|
||||
|
||||
// Check vanilla Minecraft jar.
|
||||
Path minecraftJar = detector.getMinecraftJar(mcVersion);
|
||||
if (!IFileDetector.isFile(minecraftJar)) {
|
||||
throw new RuntimeException("Unable to detect the Minecraft jar!");
|
||||
}
|
||||
|
||||
try (URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {
|
||||
Main.class.getProtectionDomain().getCodeSource().getLocation(),
|
||||
Launcher.class.getProtectionDomain().getCodeSource().getLocation(),
|
||||
installerJar.toUri().toURL()
|
||||
}, ModuleUtil.getPlatformClassLoader())) {
|
||||
Class<?> installer = ucl.loadClass("io.github.zekerzhayard.forgewrapper.installer.Installer");
|
||||
if (!(boolean) installer.getMethod("install", File.class, File.class, File.class).invoke(null, detector.getLibraryDir().toFile(), minecraftJar.toFile(), installerJar.toFile())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleUtil.setupClassPath(detector.getLibraryDir(), detector.getExtraLibraries(forgeGroup, forgeArtifact, forgeFullVersion));
|
||||
Class<?> mainClass = ModuleUtil.setupBootstrapLauncher(Class.forName(detector.getMainClass(forgeGroup, forgeArtifact, forgeFullVersion)));
|
||||
mainClass.getMethod("main", String[].class).invoke(null, new Object[] { args });
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.detector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public class DetectorLoader {
|
||||
public static IFileDetector loadDetector() {
|
||||
ServiceLoader<IFileDetector> sl = ServiceLoader.load(IFileDetector.class);
|
||||
HashMap<String, IFileDetector> detectors = new HashMap<>();
|
||||
for (IFileDetector detector : sl) {
|
||||
detectors.put(detector.name(), detector);
|
||||
}
|
||||
|
||||
boolean enabled = false;
|
||||
IFileDetector temp = null;
|
||||
for (Map.Entry<String, IFileDetector> detector : detectors.entrySet()) {
|
||||
HashMap<String, IFileDetector> others = new HashMap<>(detectors);
|
||||
others.remove(detector.getKey());
|
||||
if (!enabled) {
|
||||
enabled = detector.getValue().enabled(others);
|
||||
if (enabled) {
|
||||
temp = detector.getValue();
|
||||
}
|
||||
} else if (detector.getValue().enabled(others)) {
|
||||
throw new RuntimeException("There are two or more file detectors are enabled! (" + temp.toString() + ", " + detector.toString() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (temp == null) {
|
||||
throw new RuntimeException("No file detector is enabled!");
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.detector;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import cpw.mods.modlauncher.Launcher;
|
||||
|
||||
public interface IFileDetector {
|
||||
/**
|
||||
* @return The name of the detector.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* If there are two or more detectors are enabled, an exception will be thrown. Removing anything from the map is in vain.
|
||||
* @param others Other detectors.
|
||||
* @return True represents enabled.
|
||||
*/
|
||||
boolean enabled(HashMap<String, IFileDetector> others);
|
||||
|
||||
/**
|
||||
* @return The ".minecraft/libraries" folder for normal. It can also be defined by JVM argument "-Dforgewrapper.librariesDir=<libraries-path>".
|
||||
*/
|
||||
default Path getLibraryDir() {
|
||||
String libraryDir = System.getProperty("forgewrapper.librariesDir");
|
||||
if (libraryDir != null) {
|
||||
return Paths.get(libraryDir).toAbsolutePath();
|
||||
}
|
||||
try {
|
||||
Path launcher = Paths.get(Launcher.class.getProtectionDomain().getCodeSource().getLocation().toURI()).toAbsolutePath();
|
||||
// /<version> /modlauncher/mods /cpw /libraries
|
||||
return launcher.getParent().getParent().getParent().getParent().getParent().toAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forgeGroup Forge package group (e.g. net.minecraftforge).
|
||||
* @param forgeArtifact Forge package artifact (e.g. forge).
|
||||
* @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0).
|
||||
* @return The forge installer jar path. It can also be defined by JVM argument "-Dforgewrapper.installer=<installer-path>".
|
||||
*/
|
||||
default Path getInstallerJar(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
String installer = System.getProperty("forgewrapper.installer");
|
||||
if (installer != null) {
|
||||
return Paths.get(installer).toAbsolutePath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mcVersion Minecraft version (e.g. 1.14.4).
|
||||
* @return The minecraft client jar path. It can also be defined by JVM argument "-Dforgewrapper.minecraft=<minecraft-path>".
|
||||
*/
|
||||
default Path getMinecraftJar(String mcVersion) {
|
||||
String minecraft = System.getProperty("forgewrapper.minecraft");
|
||||
if (minecraft != null) {
|
||||
return Paths.get(minecraft).toAbsolutePath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forgeGroup Forge package group (e.g. net.minecraftforge).
|
||||
* @param forgeArtifact Forge package artifact (e.g. forge).
|
||||
* @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0).
|
||||
* @return The list of jvm args.
|
||||
*/
|
||||
default List<String> getJvmArgs(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> {
|
||||
JsonElement element = e.getAsJsonObject().get("arguments").getAsJsonObject().get("jvm");
|
||||
List<String> args = new ArrayList<>();
|
||||
if (!element.equals(JsonNull.INSTANCE)) {
|
||||
element.getAsJsonArray().iterator().forEachRemaining(je -> args.add(je.getAsString()));
|
||||
}
|
||||
return args;
|
||||
});
|
||||
}
|
||||
|
||||
default List<String> getExtraLibraries(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> {
|
||||
List<String> paths = new ArrayList<>();
|
||||
e.getAsJsonObject().getAsJsonArray("libraries").iterator().forEachRemaining(je -> {
|
||||
JsonObject artifact = je.getAsJsonObject().get("downloads").getAsJsonObject().get("artifact").getAsJsonObject();
|
||||
if (artifact.get("url").getAsString().isEmpty()) {
|
||||
paths.add(artifact.get("path").getAsString());
|
||||
}
|
||||
});
|
||||
return paths;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forgeGroup Forge package group (e.g. net.minecraftforge).
|
||||
* @param forgeArtifact Forge package artifact (e.g. forge).
|
||||
* @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0).
|
||||
* @return The main class.
|
||||
*/
|
||||
default String getMainClass(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "version.json", e -> e.getAsJsonObject().getAsJsonPrimitive("mainClass").getAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forgeGroup Forge package group (e.g. net.minecraftforge).
|
||||
* @param forgeArtifact Forge package artifact (e.g. forge).
|
||||
* @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0).
|
||||
* @return The json object in the-installer-jar-->install_profile.json-->data-->xxx-->client.
|
||||
*/
|
||||
default JsonObject getInstallProfileExtraData(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
return this.getDataFromInstaller(forgeGroup, forgeArtifact, forgeFullVersion, "install_profile.json", e -> e.getAsJsonObject().getAsJsonObject("data"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
default <R> R getDataFromInstaller(String forgeGroup, String forgeArtifact, String forgeFullVersion, String entry, Function<JsonElement, R> function) {
|
||||
Path installer = this.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion);
|
||||
if (isFile(installer)) {
|
||||
try (ZipFile zf = new ZipFile(installer.toFile())) {
|
||||
ZipEntry ze = zf.getEntry(entry);
|
||||
if (ze != null) {
|
||||
try (
|
||||
InputStream is = zf.getInputStream(ze);
|
||||
InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
) {
|
||||
return function.apply(new JsonParser().parse(isr));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Unable to detect the forge installer!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all cached files.
|
||||
* @param forgeGroup Forge package group (e.g. net.minecraftforge).
|
||||
* @param forgeArtifact Forge package artifact (e.g. forge).
|
||||
* @param forgeFullVersion Forge full version (e.g. 1.14.4-28.2.0).
|
||||
* @return True represents all files are ready.
|
||||
*/
|
||||
default boolean checkExtraFiles(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
JsonObject jo = this.getInstallProfileExtraData(forgeGroup, forgeArtifact, forgeFullVersion);
|
||||
if (jo != null) {
|
||||
Map<String, Path> libsMap = new HashMap<>();
|
||||
Map<String, String> hashMap = new HashMap<>();
|
||||
|
||||
// Get all "data/<name>/client" elements.
|
||||
Pattern artifactPattern = Pattern.compile("^\\[(?<groupId>[^:]*):(?<artifactId>[^:]*):(?<version>[^:@]*)(:(?<classifier>[^@]*))?(@(?<type>[^]]*))?]$");
|
||||
for (Map.Entry<String, JsonElement> entry : jo.entrySet()) {
|
||||
String clientStr = entry.getValue().getAsJsonObject().get("client").getAsString();
|
||||
if (entry.getKey().endsWith("_SHA")) {
|
||||
Pattern p = Pattern.compile("^'(?<sha1>[A-Za-z0-9]{40})'$");
|
||||
Matcher m = p.matcher(clientStr);
|
||||
if (m.find()) {
|
||||
hashMap.put(entry.getKey(), m.group("sha1"));
|
||||
}
|
||||
} else {
|
||||
Matcher m = artifactPattern.matcher(clientStr);
|
||||
if (m.find()) {
|
||||
String groupId = nullToDefault(m.group("groupId"), "");
|
||||
String artifactId = nullToDefault(m.group("artifactId"), "");
|
||||
String version = nullToDefault(m.group("version"), "");
|
||||
String classifier = nullToDefault(m.group("classifier"), "");
|
||||
String type = nullToDefault(m.group("type"), "jar");
|
||||
libsMap.put(entry.getKey(), this.getLibraryDir()
|
||||
.resolve(groupId.replace('.', File.separatorChar))
|
||||
.resolve(artifactId)
|
||||
.resolve(version)
|
||||
.resolve(artifactId + "-" + version + (classifier.isEmpty() ? "" : "-") + classifier + "." + type).toAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check all cached libraries.
|
||||
boolean checked = true;
|
||||
for (Map.Entry<String, Path> entry : libsMap.entrySet()) {
|
||||
String sha1 = "";
|
||||
String entryKey = entry.getKey();
|
||||
// NOTE: only used on servers, it's busted
|
||||
if(entryKey.equals("MC_UNPACKED")) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* NOTE: workaround for https://github.com/MultiMC/Launcher/issues/4400
|
||||
* We ignore the hash of the client file and instead just rely on it being 'correct, maybe' if it's present at all
|
||||
*/
|
||||
System.out.println("Checking: " + entryKey);
|
||||
if(!entryKey.equals("PATCHED")) {
|
||||
sha1 = hashMap.get(entryKey + "_SHA");
|
||||
}
|
||||
checked = checkExtraFile(entry.getValue(), sha1);
|
||||
if (!checked) {
|
||||
System.out.println("Missing: " + entry.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return checked;
|
||||
}
|
||||
// Skip installing process if installer profile doesn't exist.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the exact file.
|
||||
* @param path The path of the file to check.
|
||||
* @param sha1 The sha1 defined in installer.
|
||||
* @return True represents the file is ready.
|
||||
*/
|
||||
static boolean checkExtraFile(Path path, String sha1) {
|
||||
if (!isFile(path)) {
|
||||
return false;
|
||||
}
|
||||
if(sha1 == null || sha1.equals("")) {
|
||||
return true;
|
||||
}
|
||||
return sha1.toLowerCase(Locale.ENGLISH).equals(getFileSHA1(path));
|
||||
}
|
||||
|
||||
static boolean isFile(Path path) {
|
||||
return path != null && Files.isRegularFile(path);
|
||||
}
|
||||
|
||||
static String getFileSHA1(Path path) {
|
||||
try {
|
||||
StringBuilder sha1 = new StringBuilder(new BigInteger(1, MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(path))).toString(16));
|
||||
while (sha1.length() < 40) {
|
||||
sha1.insert(0, "0");
|
||||
}
|
||||
return sha1.toString().toLowerCase(Locale.ENGLISH);
|
||||
} catch (IOException | NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static String nullToDefault(String string, String defaultValue) {
|
||||
return string == null ? defaultValue : string;
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.detector;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MultiMCFileDetector implements IFileDetector {
|
||||
protected Path libraryDir = null;
|
||||
protected Path installerJar = null;
|
||||
protected Path minecraftJar = null;
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "MultiMC";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enabled(HashMap<String, IFileDetector> others) {
|
||||
return others.size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getLibraryDir() {
|
||||
if (this.libraryDir == null) {
|
||||
this.libraryDir = IFileDetector.super.getLibraryDir();
|
||||
}
|
||||
return this.libraryDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getInstallerJar(String forgeGroup, String forgeArtifact, String forgeFullVersion) {
|
||||
Path path = IFileDetector.super.getInstallerJar(forgeGroup, forgeArtifact, forgeFullVersion);
|
||||
if (path == null) {
|
||||
if (this.installerJar == null) {
|
||||
Path installerBase = this.getLibraryDir();
|
||||
for (String dir : forgeGroup.split("\\."))
|
||||
installerBase = installerBase.resolve(dir);
|
||||
this.installerJar = installerBase.resolve(forgeArtifact).resolve(forgeFullVersion).resolve(forgeArtifact + "-" + forgeFullVersion + "-installer.jar").toAbsolutePath();
|
||||
}
|
||||
return this.installerJar;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getMinecraftJar(String mcVersion) {
|
||||
Path path = IFileDetector.super.getMinecraftJar(mcVersion);
|
||||
if (path == null) {
|
||||
return this.minecraftJar != null ? this.minecraftJar : (this.minecraftJar = this.getLibraryDir().resolve("com").resolve("mojang").resolve("minecraft").resolve(mcVersion).resolve("minecraft-" + mcVersion + "-client.jar").toAbsolutePath());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import net.minecraftforge.installer.actions.PostProcessors;
|
||||
import net.minecraftforge.installer.actions.ProgressCallback;
|
||||
import net.minecraftforge.installer.json.Install;
|
||||
import net.minecraftforge.installer.json.InstallV1;
|
||||
import net.minecraftforge.installer.json.Util;
|
||||
|
||||
public class InstallerV1 extends AbstractInstaller {
|
||||
@Override
|
||||
public Install loadInstallProfile() {
|
||||
return Util.loadInstallProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runClientInstall(Install profile, ProgressCallback monitor, File libraryDir, File minecraftJar,
|
||||
File installerJar) {
|
||||
PostProcessors processors = new PostProcessors(
|
||||
profile instanceof InstallV1 ? (InstallV1) profile : new InstallV1(profile), true, monitor);
|
||||
|
||||
try {
|
||||
Method method = processors.getClass().getMethod("process", File.class, File.class, File.class, File.class);
|
||||
Object result = method.invoke(processors, libraryDir, minecraftJar, libraryDir.getParentFile(),
|
||||
installerJar);
|
||||
|
||||
if (method.getReturnType() == boolean.class)
|
||||
return (boolean) result;
|
||||
|
||||
return result != null;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package io.github.zekerzhayard.forgewrapper.installer.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class ModuleUtil {
|
||||
public static void addModules(String modulePath) {
|
||||
// nothing to do with Java 8
|
||||
}
|
||||
|
||||
public static void addExports(List<String> exports) {
|
||||
// nothing to do with Java 8
|
||||
}
|
||||
|
||||
public static void addOpens(List<String> opens) {
|
||||
// nothing to do with Java 8
|
||||
}
|
||||
|
||||
public static void setupClassPath(Path libraryDir, List<String> paths) throws Throwable {
|
||||
Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addURLMethod.setAccessible(true);
|
||||
for (String path : paths) {
|
||||
addURLMethod.invoke(ClassLoader.getSystemClassLoader(), libraryDir.resolve(path).toUri().toURL());
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> setupBootstrapLauncher(Class<?> mainClass) {
|
||||
// nothing to do with Java 8
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
public static ClassLoader getPlatformClassLoader() {
|
||||
// PlatformClassLoader does not exist in Java 8
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
io.github.zekerzhayard.forgewrapper.installer.detector.MultiMCFileDetector
|
Loading…
Reference in a new issue