mirror of
https://github.com/LegacyModdingMC/UniMixins.git
synced 2026-10-27 06:53:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cc4912c55 | ||
|
|
05878bfde1 | ||
|
|
43ac78f2dc | ||
|
|
1cbd6a0ecd | ||
|
|
a97b3ce85c | ||
|
|
56a008ce92 | ||
|
|
02a9a1a10d | ||
|
|
5fbb67e26f | ||
|
|
918a80ae53 | ||
|
|
5788d7ec1e | ||
|
|
e29c36c603 | ||
|
|
aed49ce829 | ||
|
|
39a31c66da | ||
|
|
d2c55ed6e3 | ||
|
|
614e8b9569 | ||
|
|
45d16b96ab | ||
|
|
3563c869b5 | ||
|
|
64a4084138 | ||
|
|
acdd68819f | ||
|
|
0fff377da8 | ||
|
|
1b130b1314 | ||
|
|
608639acf3 | ||
|
|
44f89624b0 | ||
|
|
4f5d454d03 | ||
|
|
bbed619396 | ||
|
|
d66394b2ea | ||
|
|
220d040ebd | ||
|
|
b42622470f | ||
|
|
3bc74ae73d | ||
|
|
839425440e | ||
|
|
c2e86f3aae | ||
|
|
48d55f2b44 | ||
|
|
de08ce459e | ||
|
|
43a764c055 | ||
|
|
dad688c742 | ||
|
|
f524e7de7f | ||
|
|
181924abd1 | ||
|
|
8bc2051af9 | ||
|
|
87e71b1ba3 | ||
|
|
ae12182d30 | ||
|
|
189bf0b5e9 | ||
|
|
6b528532a2 | ||
|
|
062eab7754 | ||
|
|
c053f33017 | ||
|
|
016cf16396 | ||
|
|
9cff9105af | ||
|
|
41aecb728a | ||
|
|
8a8444d7f8 | ||
|
|
cd232ec4a0 | ||
|
|
14e8ce7cb2 | ||
|
|
6c55d33c18 | ||
|
|
fcd416e31b | ||
|
|
fe11aee64c | ||
|
|
d5c96de372 | ||
|
|
798b3fb1c9 | ||
|
|
ee81c389fa | ||
|
|
1237e86768 | ||
|
|
d268a991ad | ||
|
|
f1a63f392d | ||
|
|
7ee32c62d3 | ||
|
|
ddd608a8f8 | ||
|
|
a4bddd8dbf | ||
|
|
a892f6d119 | ||
|
|
58bb4137f0 | ||
|
|
28b93dd4f7 | ||
|
|
c3af5167df | ||
|
|
9b4bde7e95 | ||
|
|
bbc0b48175 | ||
|
|
27e3058a53 | ||
|
|
24f6c06631 | ||
|
|
bff36c3067 | ||
|
|
108893429f | ||
|
|
3a09260a99 | ||
|
|
9152c1a5ca | ||
|
|
28e98d501f | ||
|
|
80e07234f5 | ||
|
|
2e7893816f | ||
|
|
23e833fd1e | ||
|
|
f0b355c782 | ||
|
|
2409b246b3 | ||
|
|
46a5c6d167 | ||
|
|
b5891061e0 | ||
|
|
ba1f02d541 | ||
|
|
9aa07d509c | ||
|
|
8e17e96c3e | ||
|
|
8e3e7e49e5 | ||
|
|
0e54b7bf08 | ||
|
|
1db6d9b000 | ||
|
|
9354ebd81a | ||
|
|
df12ab3ef3 | ||
|
|
2ae66ed7a6 | ||
|
|
46d1e77770 | ||
|
|
e3c8d83108 | ||
|
|
cec3048ed4 | ||
|
|
f5800a69c2 | ||
|
|
b143241008 | ||
|
|
0daba06b88 | ||
|
|
ba453f04c5 | ||
|
|
8e2d6beb3f | ||
|
|
c0f712fb9d | ||
|
|
2376d1ce50 | ||
|
|
37edc3537a | ||
|
|
618bd0de47 | ||
|
|
d4213cf71a | ||
|
|
92db4df839 | ||
|
|
278edd177d | ||
|
|
1ed02bc811 | ||
|
|
2a331ee00f | ||
|
|
5d5aff4efe | ||
|
|
e54253eb95 | ||
|
|
adfa0b9061 | ||
|
|
12ea25c3f2 | ||
|
|
96fcda3db2 | ||
|
|
524ee60d9a | ||
|
|
4144ea5913 | ||
|
|
b8953cc38c | ||
|
|
f20c78c96b | ||
|
|
f595016981 | ||
|
|
4355a4a481 | ||
|
|
a68db4a990 | ||
|
|
b8830d9375 | ||
|
|
23386a3ea8 | ||
|
|
4b1b1423fd |
No files matched your search
@@ -8,17 +8,24 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
build-scan-publish: true
|
||||
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
|
||||
build-scan-terms-of-use-agree: "yes"
|
||||
validate-wrappers: true
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Set up Gradle build
|
||||
@@ -37,11 +44,11 @@ jobs:
|
||||
mv build/tmp/ci-dev/* build/tmp/ci
|
||||
rm build/tmp/ci/*-common-*.jar
|
||||
mv build/tmp/ci/*-sources.jar build/tmp/ci-sources
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Package
|
||||
path: build/tmp/ci
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Package-sources
|
||||
path: build/tmp/ci-sources
|
||||
@@ -16,25 +16,32 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Set release version
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v3
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
with:
|
||||
build-scan-publish: true
|
||||
build-scan-terms-of-use-url: "https://gradle.com/terms-of-service"
|
||||
build-scan-terms-of-use-agree: "yes"
|
||||
validate-wrappers: true
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Set up Gradle build
|
||||
run: ./gradlew setupCIWorkspace
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build -PnoAltMixin
|
||||
run: ./gradlew build
|
||||
- name: Copy artifacts to a single directory
|
||||
run: |
|
||||
mkdir build/tmp/ci -p
|
||||
@@ -47,11 +54,11 @@ jobs:
|
||||
mv build/tmp/ci-dev/* build/tmp/ci
|
||||
rm build/tmp/ci/*-common-*.jar
|
||||
mv build/tmp/ci/*-sources.jar build/tmp/ci-sources
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Package
|
||||
path: build/tmp/ci
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Package-sources
|
||||
path: build/tmp/ci-sources
|
||||
@@ -63,6 +70,7 @@ jobs:
|
||||
DRAFT_TAG=$(cat /tmp/last-release.json | jq '.tag_name' -r)
|
||||
[ $DRAFT_TAG == $RELEASE_VERSION ] || (echo "Error: Last draft's tag does not match pushed tag" && false)
|
||||
cat /tmp/last-release.json | jq '.body' -r > /tmp/changelog.md
|
||||
[ $(cat /tmp/changelog.md | wc -w) -gt 0 ] || (echo "Error: Draft is missing a changelog" && false)
|
||||
cat /tmp/last-release.json | jq '.id' > /tmp/draft_id.txt
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
@@ -79,6 +87,12 @@ jobs:
|
||||
env:
|
||||
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
|
||||
CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
|
||||
- name: Publish to GTNH maven
|
||||
run: ./gradlew publish
|
||||
env:
|
||||
MAVEN_URL: ${{ secrets.MAVEN_URL }}
|
||||
MAVEN_USER: ${{ secrets.MAVEN_USERNAME }}
|
||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
- name: Delete last draft release
|
||||
run: |
|
||||
gh api -X DELETE "/repos/${GITHUB_REPOSITORY}/releases/$(cat /tmp/draft_id.txt)"
|
||||
|
||||
@@ -2,7 +2,7 @@ UniMixins is licensed under the Unlicense, as specified in LICENSE.UNLICENSE,
|
||||
with the exception of the following modules, which are licensed under different
|
||||
terms.
|
||||
Refer to CREDITS, LICENSE, and README.original.md (whichever of these exist)
|
||||
inside their directories for full information, inluding reproductions of their
|
||||
inside their directories for full information, including reproductions of their
|
||||
original license texts.
|
||||
|
||||
## SpongeMixins
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
[](https://github.com/LegacyModdingMC/UniMixins/releases)
|
||||
[](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
|
||||
[](https://www.curseforge.com/minecraft/mc-mods/unimixins)
|
||||
[](https://modrinth.com/mod/unimixins)
|
||||
[](https://discord.gg/AJxEFs6YBN)
|
||||
[](https://github.com/LegacyModdingMC/UniMixins/releases)
|
||||
[](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
|
||||
[](https://legacy.curseforge.com/minecraft/mc-mods/unimixins)
|
||||
[](https://modrinth.com/mod/unimixins)
|
||||
[](https://discord.gg/AJxEFs6YBN)
|
||||
|
||||
# UniMixins
|
||||
|
||||
UniMixins is a Mixin loader for Minecraft 1.7.10 designed for maximum compatibility. It aims to combine the features of as many mixin loaders as possible, and its modular nature makes it possible to use along other loaders if desired.
|
||||
UniMixins is a Mixin loader for Minecraft 1.7.10 (with partial 1.8.9~1.12.2 support) designed for maximum compatibility. It aims to combine the features of as many mixin loaders as possible, and its modular nature makes it possible to use along other loaders if desired.
|
||||
|
||||
## Background
|
||||
|
||||
Numerous Mixin loaders exist for 1.7.10, and each one provides a differing set of extra features we refer to as *"extras"* on top of providing Mixin.
|
||||
|
||||
Since each of these loaders is monolithic, different ones cannot be used at the same time due to unavoidable feature overlap. To avoid this problem, UniMixins offers each feature as a separate module (but a combined jar is still provided for convenience.)
|
||||
Since each of these loaders is monolithic, different ones cannot be used at the same time due to unavoidable feature overlap. To avoid this problem, UniMixins offers each feature as a separate module (but a combined jar is still provided for convenience).
|
||||
|
||||
## Comparison table
|
||||
|
||||
@@ -32,9 +32,9 @@ Note: A more detailed version of this table is available [here](https://legacymo
|
||||
|
||||
Download the `-all` jar, and put it in your mods directory. Remove any other conflicting Mixin loaders (refer to the above table).
|
||||
|
||||
> **Note**: It's important for the jar to be named so that it comes first alphabetically, to avoid [a sorting issue](https://github.com/tox1cozZ/mixin-booter-legacy/issues/1) with mods that embed Mixin. This is why the jar starts with a `-` character. You may need to change this to a `!` character if you encounter issues with renamed jars.
|
||||
> **Note**: It's important for the jar to be named so that it comes first alphabetically, to avoid [a sorting issue](https://github.com/tox1cozZ/mixin-booter-legacy/issues/1) with mods that embed Mixin. This is why the jar starts with a `+` character. You may need to change this to a `!` character if you encounter issues with renamed jars.
|
||||
>
|
||||
> For reference, here is the sorting order of some notable characters: `!` < `-` < `0` < `[` < `_` < `a`
|
||||
> For reference, here is the sorting order of some notable characters: `!` < `+` < `0` < `[` < `_` < `a`
|
||||
|
||||
### Advanced usage
|
||||
|
||||
@@ -49,7 +49,7 @@ The game will crash if modules are missing dependencies. This can be disabled in
|
||||
|
||||
### Developer usage
|
||||
|
||||
See [docs/developer-usage.md](docs/developer-usage.md) to see how to migrate an existing build script to depend on UniMixins.
|
||||
See [docs/developer-usage.md](docs/developer-usage.md).
|
||||
|
||||
## List of modules
|
||||
|
||||
@@ -58,21 +58,23 @@ All modules depend on the Mixin module. Note that the dependents don't necessari
|
||||
### Included in `all`-jar
|
||||
|
||||
* **Mixin (UniMix)**: Provides [a Mixin fork](https://github.com/LegacyModdingMC/UniMix) maintained by the UniMixins developers, based on [the Fabric fork](https://github.com/FabricMC/Mixin).
|
||||
* **SpongeMixins**: Provides an emulation of [SpongeMixins](https://github.com/GTNewHorizons/SpongeMixins)'s extras.
|
||||
* **MixinBooterLegacy**: Provides an emulation of [MixinBooterLegacy](https://github.com/tox1cozZ/mixin-booter-legacy)'s extras, and a relocated MixinExtras.
|
||||
* **SpongeMixins** <sup>[1.7.10 only]</sup>: Provides an emulation of [SpongeMixins](https://github.com/GTNewHorizons/SpongeMixins)'s extras.
|
||||
* **MixinBooterLegacy** <sup>[1.7.10 only]</sup>: Provides an emulation of [MixinBooterLegacy](https://github.com/tox1cozZ/mixin-booter-legacy)'s extras, and a relocated MixinExtras.
|
||||
* **MixinExtras**: Provides [MixinExtras](https://github.com/LlamaLad7/MixinExtras).
|
||||
* **GasStation**: Provides an emulation of [GasStation](https://github.com/FalsePattern/GasStation)'s extras.
|
||||
* **GasStation** <sup>[1.7.10 only]</sup>: Provides an emulation of [GasStation](https://github.com/FalsePattern/GasStation)'s extras.
|
||||
* Depends on SpongeMixins.
|
||||
* Depends on MixinBooterLegacy.
|
||||
* Depends on MixinExtras
|
||||
* **GTNHMixins**: Provides an emulation of [GTNHMixins](https://github.com/GTNewHorizons/GTNHMixins)'s extras, and a relocated MixinExtras.
|
||||
* **GTNHMixins** <sup>[1.7.10 only]</sup>: Provides an emulation of [GTNHMixins](https://github.com/GTNewHorizons/GTNHMixins)'s extras, and a relocated MixinExtras.
|
||||
* Depends on SpongeMixins.
|
||||
* **Compat**: Improves compatibility by fixing incorrect references to Mixin classes (specifically the shaded ASM) in mods, and adds information about mixins to crash reports.
|
||||
* **Compat**: Various compatibility tweaks:
|
||||
* Remaps invalid references to Mixin classes (specifically the shaded ASM) in mods.
|
||||
* Adds information about mixins to crash reports. <sup>[1.7.10 only]</sup>
|
||||
* **Mixingasm**: Improves Mixin's compatibility with ASM transformers.
|
||||
|
||||
### Optional
|
||||
|
||||
* **DevCompat**: Unsafe compatibility tweaks intended to only be used in dev environments. Not needed if using UniMix or GTNH's Mixin fork.
|
||||
* **Future Compat** <sup>[1.8.9+ only]</sup>: Makes many of the modules usable on 1.8.9+. **Needed to run the mod on 1.8+.** (Not needed for Mixingasm.)
|
||||
|
||||
### Very Optional
|
||||
|
||||
@@ -87,7 +89,9 @@ These are not included in releases, they mainly exist for testing purposes. (Not
|
||||
|
||||
### Why another mixin loader? Haven't you seen that one xkcd strip?
|
||||
|
||||
There is currently far too much fragmentation among Mixin loaders on 1.7.10, with different mods requiring different incompatible loaders. This is partly due to conflicts between their developers, and partly because of technical reasons (the loaders are designed in a monolithic way, which invites incompatibility.) This project has neither of those issues.
|
||||
Before UniMixins was created, there was far too much fragmentation among Mixin loaders on 1.7.10, with different mods requiring different incompatible loaders. This was partly due to conflicts between their developers, and partly because of technical reasons (the loaders were designed in a monolithic way, which invites incompatibility). This project has neither of those issues.
|
||||
|
||||
<img title="Ah yes, just as I remember it." src="docs/images/modularity.png">
|
||||
|
||||
### Why are you using the Fabric fork of Mixin? Isn't this a Forge mod?
|
||||
|
||||
@@ -95,14 +99,17 @@ The Fabric fork of Mixin is more actively maintained than the upstream fork, and
|
||||
|
||||
### What do the "extras" do anyway?
|
||||
|
||||
* SpongeMixins, Grimoire, MixinBooterLegacy, GasStation and GTNHMixins offer various ways to let you mix into the classes of non-coremods (something Mixin does not natively support.)
|
||||
* Mixingasm fixes [a Mixin issue](https://github.com/SpongePowered/Mixin/issues/309) that breaks some ASM transformers due to Mixin altering how they are called.
|
||||
* MixinExtras adds new Mixin features that mods can use to write less intrusive mixins.
|
||||
* SpongeMixins, Grimoire, MixinBooterLegacy, GasStation and GTNHMixins offer various ways to let you mix into the classes of non-coremods. (This is something Mixin does not natively support, since all of its phases occur before Forge discovers non-coremods and puts them on the classpath.)
|
||||
- **MixinBooterLegacy**, **GasStation** and **GTNHMixins** add a "late" mixin phase that is fired right before the first mod construction event is dispatched. At this point all mods have been discovered.
|
||||
- **SpongeMixins** lets you manually add mods to the classpath early using their file names. An old, hacky solution.
|
||||
- We recommend new mods to use **GTNHMixins** as it's the most actively used and maintained option.
|
||||
* **Mixingasm** fixes [a Mixin issue](https://github.com/SpongePowered/Mixin/issues/309) that breaks some ASM transformers due to Mixin altering how they are called.
|
||||
* **MixinExtras** adds new Mixin features that allow mods to write less intrusive mixins.
|
||||
|
||||
### Mixin? mixin? SpongeMixins? SpongePowered? What's the difference?
|
||||
|
||||
* [Mixin](https://github.com/SpongePowered/Mixin): a Java library that lets you transform Java classes in a fluent way.
|
||||
* [SpongePowered](https://spongepowered.org/): the organization that created Mixin (who also developed a modding API called Sponge.)
|
||||
* [SpongePowered](https://spongepowered.org/): the organization that created Mixin (who also developed a modding API called Sponge).
|
||||
* [mixin](https://github.com/SpongePowered/Mixin/wiki/Introduction-to-Mixins---Understanding-Mixin-Architecture#4-only-you-mixins-can-save-mankind): a special Java class defining a "change" that should be applied to a class. These get applied by Mixin.
|
||||
* [SpongeMixins](https://github.com/TimeConqueror/SpongeMixins): a Mixin loader created by TimeConqueror that has a very generic name.
|
||||
|
||||
@@ -110,6 +117,8 @@ The Fabric fork of Mixin is more actively maintained than the upstream fork, and
|
||||
|
||||
When editing the source code of modules, please document your changes in the module's CREDITS file. This allows people to easily see what we have changed, and lets other developers know what changes they have to keep in mind when syncing with upstream.
|
||||
|
||||
The project needs to be compiled using Java 8. For example: `JAVA_HOME=/path/to/jdk8 ./gradlew build`
|
||||
|
||||
### Useful commands
|
||||
|
||||
* `./gradlew module-XXX:build`: builds the module named XXX
|
||||
@@ -117,7 +126,7 @@ When editing the source code of modules, please document your changes in the mod
|
||||
### Build flags
|
||||
* `-Plocal`: use the locally built version of `unimix` when building the Mixin module.
|
||||
* Invoke `./gradlew publishToMavenLocal` in the UniMix repo first to install a local build.
|
||||
* `-PnoAltMixin`: do not build alternate flavors of the Mixin module, only UniMix. Used by the release workflow.
|
||||
* `-PenableAltMixin`: build alternate flavors of the Mixin module, not just UniMix.
|
||||
|
||||
### Roadmap
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Creates a modular zip in the build directory.
|
||||
#
|
||||
# To test with local UniMix, set ALL_BUILD_EXTRA_ARG=-Plocal
|
||||
|
||||
set -e
|
||||
|
||||
./gradlew clean
|
||||
./gradlew build
|
||||
|
||||
mkdir build -p
|
||||
|
||||
OUT_ZIP=build/unimixins-modular-1.7.10-$(git describe --tags --dirty).zip
|
||||
rm -f $OUT_ZIP
|
||||
zip -j $OUT_ZIP $(find -name "-unimixins-*.jar" | grep "build/libs" | grep -v sources | grep -v "module-all" | xargs)
|
||||
+57
-18
@@ -26,11 +26,16 @@ allprojects {
|
||||
apply plugin: 'maven-publish'
|
||||
// For some reason this is needed when using Gradle 6.9 (but not if using 4.4.1)
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
name 'Overmind forge repo mirror'
|
||||
url 'https://gregtech.overminddl1.com/'
|
||||
}
|
||||
mavenLocal()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://maven.minecraftforge.net/"
|
||||
}
|
||||
maven {
|
||||
name = 'sponge'
|
||||
url = 'https://repo.spongepowered.org/maven/'
|
||||
@@ -49,6 +54,20 @@ allprojects {
|
||||
}
|
||||
|
||||
apply from: "${project.rootDir}/buildscript/forge-1.7.gradle"
|
||||
|
||||
def projectVersion = version
|
||||
|
||||
dependencies {
|
||||
// TODO only include IFMLLoadingPlugin, Mod and ComparableVersion
|
||||
compileOnly "net.minecraftforge:forge:1.12.2-14.23.5.2860:universal"
|
||||
}
|
||||
|
||||
// When publishing locally, publish every module and use the -1.7.10 suffix.
|
||||
// Otherwise (for GTNH maven) only publish the -all module and don't use the suffix or the -all name or the unimixins group.
|
||||
ext.localPublish = System.getenv("MAVEN_USER") == null;
|
||||
ext.publishModuleToMaven = project.name == "module-all" || localPublish
|
||||
ext.mavenIdSuffix = localPublish ? "-1.7.10" : ""
|
||||
ext.mavenGroupId = localPublish ? project.group : project.group.replace(".unimixins", "")
|
||||
|
||||
if(project.name.startsWith("module-") && project.name != "module-mixin" && project.name != "module-common") {
|
||||
if(project.name != "module-all") {
|
||||
@@ -59,30 +78,35 @@ allprojects {
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
task devJar(type: Jar) {
|
||||
classifier = 'dev'
|
||||
def jarTask = (jar.enabled ? jar : shadowJar)
|
||||
from zipTree(jarTask.getOutputs().getFiles().getSingleFile())
|
||||
manifest = jarTask.manifest
|
||||
if(project.name != "module-all") {
|
||||
task devJar(type: Jar) {
|
||||
classifier = 'dev'
|
||||
def jarTask = (jar.enabled ? jar : shadowJar)
|
||||
from zipTree(jarTask.getOutputs().getFiles().getSingleFile())
|
||||
manifest = jarTask.manifest
|
||||
|
||||
dependsOn jarTask
|
||||
dependsOn jarTask
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
reobf.dependsOn devJar
|
||||
|
||||
artifacts {
|
||||
archives tasks."sourcesJar"
|
||||
archives tasks."devJar"
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create("maven", MavenPublication) {
|
||||
artifact jar.enabled ? jar : shadowJar
|
||||
artifact source: tasks."sourcesJar", classifier: 'sources'
|
||||
artifact source: tasks."devJar", classifier: 'dev'
|
||||
artifactId = archivesBaseName
|
||||
version = jar.version
|
||||
|
||||
if(publishModuleToMaven) {
|
||||
publishing {
|
||||
publications {
|
||||
create("maven", MavenPublication) {
|
||||
artifact jar.enabled ? jar : shadowJar
|
||||
artifact source: tasks."sourcesJar", classifier: 'sources'
|
||||
artifact source: tasks."devJar", classifier: 'dev'
|
||||
artifactId = archivesBaseName.substring(1).replace("-1.7.10", mavenIdSuffix).replace("-all", localPublish ? "-all" : "")
|
||||
version = projectVersion
|
||||
groupId = mavenGroupId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +118,22 @@ allprojects {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
if (System.getenv("MAVEN_USER") != null) {
|
||||
maven {
|
||||
url = System.getenv("MAVEN_URL")
|
||||
allowInsecureProtocol = System.getenv("MAVEN_URL").startsWith("http://") // Mostly for the GTNH maven
|
||||
credentials {
|
||||
username = System.getenv("MAVEN_USER") ?: "NONE"
|
||||
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put license, credits and readme in jar
|
||||
|
||||
delete "$projectDir/build/tmp/license"
|
||||
|
||||
+31
-57
@@ -1,78 +1,52 @@
|
||||
# Developer usage
|
||||
|
||||
An example mod showcasing the mod's various features is available in the `example-*` branches of the repo:
|
||||
- [`example-fg-g4`](https://github.com/LegacyModdingMC/UniMixins/tree/example-fg-g4) - ForgeGradle-based build script with Gradle 4
|
||||
- [`example-fg-g6`](https://github.com/LegacyModdingMC/UniMixins/tree/example-fg-g6) - ForgeGradle-based build script with Gradle 6
|
||||
|
||||
Below are instructions for migrating build scripts to use UniMixins.
|
||||
|
||||
## RetroFuturaGradle
|
||||
|
||||
The easiest way to use UniMixins is to use [GTNH's ExampleMod](https://github.com/GTNewHorizons/ExampleMod1.7.10), which has UniMixins integration built-in.
|
||||
|
||||
## ForgeGradle
|
||||
|
||||
To migrate a ForgeGradle-based build script to UniMixins, merge the following into your build script.
|
||||
|
||||
```gradle
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
|
||||
def unimixinsVersion = "insert version here"
|
||||
|
||||
dependencies {
|
||||
// with modern Gradle, you'd need to use implementation + annotationProcessor
|
||||
compile("com.github.LegacyModdingMC.UniMixins:-unimixins-all-1.7.10:$unimixinsVersion:dev")
|
||||
}
|
||||
|
||||
// Exclude conflicting transitive dependencies.
|
||||
// Only needed if you depend on a mod that depends on one of these.
|
||||
// This may need to be at the end of the build script.
|
||||
|
||||
configurations.compile.dependencies.each {
|
||||
if (it instanceof ExternalModuleDependency) {
|
||||
it.exclude module: "SpongeMixins"
|
||||
it.exclude module: "SpongePoweredMixin"
|
||||
it.exclude module: "00gasstation-mc1.7.10"
|
||||
it.exclude module: "gtnhmixins"
|
||||
}
|
||||
}
|
||||
|
||||
runClient {
|
||||
arguments += [
|
||||
"--tweakClass", "org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
|
||||
runServer {
|
||||
arguments += [
|
||||
"--tweakClass", "org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
```
|
||||
Refer to the example mod's build script ([Gradle 4](https://github.com/LegacyModdingMC/UniMixins/blob/example-fg-g4/build.gradle#L79) | [Gradle 6](https://github.com/LegacyModdingMC/UniMixins/blob/example-fg-g6/build.gradle#L91)).
|
||||
|
||||
You can also depend on modules individually:
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
// One of these (note: this module doesn't have dev jars)
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixin-1.7.10:$unimixinsVersion+unimix.0.12.1-mixin.0.8.5")
|
||||
//implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixin-1.7.10:$unimixinsVersion+spongepowered.0.8.5")
|
||||
//implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixin-1.7.10:$unimixinsVersion+fabric.0.12.4-mixin.0.8.5")
|
||||
//implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixin-1.7.10:$unimixinsVersion+gasmix.0.8.5-gasstation_7")
|
||||
//implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixin-1.7.10:$unimixinsVersion+gtnh.0.8.5-GTNH-2")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-mixin-1.7.10:$unimixinsVersion")
|
||||
|
||||
// You don't need all the modules, only the ones your mod requires.
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-compat-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-spongemixins-1.7.10:$unimixinsVersion+gtnh.2.0.1:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixinbooterlegacy-1.7.10:$unimixinsVersion+1.2.1:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-gasstation-1.7.10:$unimixinsVersion+0.5.1:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixinextras-1.7.10:$unimixinsVersion+0.1.1:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-gtnhmixins-1.7.10:$unimixinsVersion+2.1.9:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-mixingasm-1.7.10:$unimixinsVersion+0.2.2:dev")
|
||||
|
||||
// Needed if not using UniMix or GTNH's Mixin fork
|
||||
//implementation("com.github.LegacyModdingMC.UniMixins:-unimixins-devcompat-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-compat-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-spongemixins-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-mixinbooterlegacy-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-gasstation-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-mixinextras-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-gtnhmixins-1.7.10:$unimixinsVersion:dev")
|
||||
implementation("com.github.LegacyModdingMC.UniMixins:unimixins-mixingasm-1.7.10:$unimixinsVersion:dev")
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Testing info</summary>
|
||||
|
||||
If you want to depend on a local build, you need to use `io.github.legacymoddingmc.unimixins` instead of `com.github.LegacyModdingMC.UniMixins`.
|
||||
|
||||
And here's how you depend on the Very Optional modules (not published on Jitpack).
|
||||
```gradle
|
||||
//implementation("io.github.legacymoddingmc.unimixins:unimixins-mixin-1.7.10-spongepowered:$unimixinsVersion")
|
||||
//implementation("io.github.legacymoddingmc.unimixins:unimixins-mixin-1.7.10-fabric:$unimixinsVersion")
|
||||
//implementation("io.github.legacymoddingmc.unimixins:unimixins-mixin-1.7.10-gasmix:$unimixinsVersion")
|
||||
//implementation("io.github.legacymoddingmc.unimixins:unimixins-mixin-1.7.10-gtnh:$unimixinsVersion")
|
||||
```
|
||||
|
||||
Note: If you are *not* using UniMix or GTNH's Mixin fork, you will need to add the compat module and set the `-Dunimixins.compat.hackClasspathModDiscovery=true` JVM flag, or Forge may fail to discover your mod or its dependencies.
|
||||
</details>
|
||||
|
||||
## Tricks
|
||||
|
||||
### Hot swapping
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 420 KiB |
@@ -0,0 +1,712 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="272mm"
|
||||
height="98.300003mm"
|
||||
viewBox="0 0 272 98.300003"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="modularity.svg"
|
||||
inkscape:export-filename="modularity.png"
|
||||
inkscape:export-xdpi="300"
|
||||
inkscape:export-ydpi="300"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
height="9.83cm"
|
||||
inkscape:zoom="1.8116734"
|
||||
inkscape:cx="707.08107"
|
||||
inkscape:cy="100.45961"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="false" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<pattern
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Strips1_4"
|
||||
id="pattern73765"
|
||||
patternTransform="matrix(-0.41147911,-0.41147911,2.1055851,-2.1055851,28.02852,-37.612396)" />
|
||||
<pattern
|
||||
inkscape:collect="always"
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="5"
|
||||
height="1"
|
||||
patternTransform="translate(0,0) scale(10,10)"
|
||||
id="Strips1_4"
|
||||
inkscape:stockid="Stripes 1:4"
|
||||
inkscape:isstock="true">
|
||||
<rect
|
||||
style="fill:black;stroke:none"
|
||||
x="0"
|
||||
y="-0.5"
|
||||
width="1"
|
||||
height="2"
|
||||
id="rect2974" />
|
||||
</pattern>
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="217.25429"
|
||||
height="52.39732"
|
||||
id="rect6184" />
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Duochrome"
|
||||
id="filter75351"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1">
|
||||
<feColorMatrix
|
||||
type="luminanceToAlpha"
|
||||
result="colormatrix1"
|
||||
id="feColorMatrix75331" />
|
||||
<feFlood
|
||||
flood-opacity="0.501961"
|
||||
flood-color="rgb(229,229,229)"
|
||||
result="flood1"
|
||||
id="feFlood75333" />
|
||||
<feComposite
|
||||
in2="colormatrix1"
|
||||
operator="out"
|
||||
result="composite1"
|
||||
id="feComposite75335" />
|
||||
<feFlood
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(255,255,0)"
|
||||
result="flood2"
|
||||
id="feFlood75337" />
|
||||
<feComposite
|
||||
in2="colormatrix1"
|
||||
result="composite2"
|
||||
operator="in"
|
||||
id="feComposite75339" />
|
||||
<feComposite
|
||||
in="composite2"
|
||||
in2="composite1"
|
||||
k2="1"
|
||||
k3="1"
|
||||
operator="arithmetic"
|
||||
result="composite3"
|
||||
id="feComposite75341"
|
||||
k1="0"
|
||||
k4="0" />
|
||||
<feColorMatrix
|
||||
in="composite3"
|
||||
type="matrix"
|
||||
values="2 -1 0 0 0 0 2 -1 0 0 -1 0 2 0 0 0 0 0 1 0 "
|
||||
result="colormatrix2"
|
||||
id="feColorMatrix75343" />
|
||||
<feComposite
|
||||
in="colormatrix2"
|
||||
in2="composite3"
|
||||
operator="arithmetic"
|
||||
k2="0"
|
||||
result="composite4"
|
||||
id="feComposite75345"
|
||||
k1="0"
|
||||
k3="0"
|
||||
k4="0" />
|
||||
<feBlend
|
||||
in="composite4"
|
||||
in2="composite3"
|
||||
mode="normal"
|
||||
result="blend"
|
||||
id="feBlend75347" />
|
||||
<feComposite
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
id="feComposite75349" />
|
||||
</filter>
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="191.31142"
|
||||
height="45.221634"
|
||||
id="rect6184-8" />
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="322.4542"
|
||||
height="53.027752"
|
||||
id="rect6184-8-4" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7"
|
||||
width="63.608315"
|
||||
height="8.1022758"
|
||||
x="13.800014"
|
||||
y="46.707821" />
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="36.178707"
|
||||
y="59.424469" />
|
||||
<rect
|
||||
style="display:inline;fill:url(#pattern73765);fill-opacity:1;stroke:none;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter75351);stop-color:#000000"
|
||||
id="rect1104-0-0"
|
||||
width="21.420921"
|
||||
height="8.0959282"
|
||||
x="34.857468"
|
||||
y="46.708447"
|
||||
ry="0" />
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-5"
|
||||
width="21.420921"
|
||||
height="8.0959272"
|
||||
x="34.857468"
|
||||
y="46.708447" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,0.12802956,1.2560112)"
|
||||
id="text6182"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.5px;white-space:pre;shape-inside:url(#rect6184);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="73.532947"
|
||||
y="35.357673"
|
||||
id="tspan326524">EXISTING MIXIN LOADERS
|
||||
</tspan><tspan
|
||||
x="106.52431"
|
||||
y="57.757637"
|
||||
id="tspan326526">ARE MONOLITHIC.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,90.941647,2.4661355)"
|
||||
id="text6182-6"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.5px;white-space:pre;shape-inside:url(#rect6184-8);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="70.094129"
|
||||
y="37.491004"
|
||||
id="tspan326528">UNIMIXINS IS MODULAR.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,166.16598,1.3341978)"
|
||||
id="text6182-6-7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script Bold';text-align:center;letter-spacing:-0.6px;white-space:pre;shape-inside:url(#rect6184-8-4);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="90.91602"
|
||||
y="35.357673"
|
||||
id="tspan326532"><tspan
|
||||
style="font-weight:normal;-inkscape-font-specification:'xkcd Script'"
|
||||
id="tspan326530">UNIMIXINS MODULES CAN EVEN BE </tspan></tspan><tspan
|
||||
x="72.625018"
|
||||
y="57.757637"
|
||||
id="tspan326536"><tspan
|
||||
style="font-weight:normal;-inkscape-font-specification:'xkcd Script'"
|
||||
id="tspan326534">ADDED ON TOP OF ANOTHER LOADER.</tspan></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.185208px;text-anchor:middle;white-space:pre;inline-size:82.321;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="44.71722"
|
||||
y="24.065899"
|
||||
id="text32884"
|
||||
transform="translate(0.52916667,1.5875)"><tspan
|
||||
x="44.71722"
|
||||
y="24.065899"
|
||||
id="tspan326538">THEY CANNOT BE LOADED AT THE SAME TIME DUE TO<tspan
|
||||
y="24.065899"
|
||||
id="tspan326540"> </tspan></tspan><tspan
|
||||
x="44.71722"
|
||||
y="27.770067"
|
||||
id="tspan326542">FEATURE OVERLAP, EVEN THOUGH THEIR INDIVIDUAL FEATURES<tspan
|
||||
y="27.770067"
|
||||
id="tspan326544"> </tspan></tspan><tspan
|
||||
x="44.71722"
|
||||
y="31.474235"
|
||||
id="tspan326546">WOULD BE ABLE TO CO-EXIST.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.132292px;text-anchor:middle;white-space:pre;inline-size:89.1681;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="134.89743"
|
||||
y="23.701571"
|
||||
id="text32884-1"
|
||||
transform="translate(0,1.0583333)"><tspan
|
||||
x="134.89743"
|
||||
y="23.701571"
|
||||
id="tspan326548">EACH FEATURE IS IN ITS OWN "BOX", ALLOWING THEM TO BE<tspan
|
||||
y="23.701571"
|
||||
id="tspan326550"> </tspan></tspan><tspan
|
||||
x="134.89743"
|
||||
y="27.405738"
|
||||
id="tspan326552">COMBINED FREELY WITHOUT ANY ARBITRARY RESTRICTIONS.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.89278px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.132292px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="225.63924"
|
||||
y="24.60577"
|
||||
id="text32884-1-9"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.89278px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;text-anchor:middle;stroke-width:0.264583"
|
||||
x="225.57309"
|
||||
y="24.60577"
|
||||
id="tspan116154-7">(THIS KIND OF SUPPORT IS NOT FULLY IMPLEMENTED THOUGH.)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#3f48cc;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="23.71513"
|
||||
y="42.778732"
|
||||
id="text63580"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#3f48cc;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.71513"
|
||||
y="42.778732">GTNHMIXINS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="27.273415"
|
||||
y="50.070621"
|
||||
id="text63580-6"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="27.273415"
|
||||
y="50.070621"
|
||||
id="tspan76477">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="27.233727"
|
||||
y="53.160957"
|
||||
id="tspan189479">0.8-GTNH</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="45.815434"
|
||||
y="62.721596"
|
||||
id="text63580-6-89"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="45.815434"
|
||||
y="62.721596"
|
||||
id="tspan104620">SPONGEMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="45.775745"
|
||||
y="65.811935"
|
||||
id="tspan199017">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="13.745136"
|
||||
y="72.354515" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="23.381863"
|
||||
y="75.724663"
|
||||
id="text63580-6-89-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.381863"
|
||||
y="75.724663"
|
||||
id="tspan105830">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.342175"
|
||||
y="78.815002"
|
||||
id="tspan195563">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="58.160408"
|
||||
y="72.281502" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="67.79715"
|
||||
y="75.72467"
|
||||
id="text63580-6-89-5-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="67.79715"
|
||||
y="75.72467"
|
||||
id="tspan106818">GASSTATION</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="67.757462"
|
||||
y="78.81501"
|
||||
id="tspan197827">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16634"
|
||||
y="38.274223" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="41.717392"
|
||||
id="text63580-6-89-5-1-2"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="41.717392"
|
||||
id="tspan116603">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="44.807728"
|
||||
id="tspan206609">0.8-UNIMIX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="63.996986"
|
||||
y="50.144955"
|
||||
id="text63580-6-8"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="63.996986"
|
||||
y="50.144955"
|
||||
id="tspan76477-8">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="63.957298"
|
||||
y="53.235291"
|
||||
id="tspan192367">0.8-GASMIX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="50.883247"
|
||||
y="42.739273"
|
||||
id="text63580-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ed1c24;fill-opacity:1;stroke-width:0.264583"
|
||||
x="50.883247"
|
||||
y="42.739273">GASSTATION</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="43.174267"
|
||||
id="text63580-0-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="43.174267">MIXIN MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16634"
|
||||
y="51.642021" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80305"
|
||||
y="55.08519"
|
||||
id="text63580-6-89-5-1-2-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80305"
|
||||
y="55.08519"
|
||||
id="tspan132092">SPONGEMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76336"
|
||||
y="58.175526"
|
||||
id="tspan207303">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59996"
|
||||
y="56.542065"
|
||||
id="text63580-0-3-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59996"
|
||||
y="56.542065">SPONGEMIXINS MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16635"
|
||||
y="64.523148" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="67.966316"
|
||||
id="text63580-6-89-5-1-2-1-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="67.966316"
|
||||
id="tspan126306">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="71.056656"
|
||||
id="tspan207993">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="69.423195"
|
||||
id="text63580-0-3-3-4"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="69.423195">GTNHMIXINS MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3-8"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16635"
|
||||
y="77.124695" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="80.567863"
|
||||
id="text63580-6-89-5-1-2-1-5-7"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="80.567863"
|
||||
id="tspan128146">GASSTATION</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="83.658203"
|
||||
id="tspan208641">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="82.024742"
|
||||
id="text63580-0-3-3-4-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2-5"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="82.024742">GASSTATION MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-0"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60686"
|
||||
y="41.695419" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="45.138588"
|
||||
id="text63580-6-89-5-1-2-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="45.138588"
|
||||
id="tspan116603-60">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.2039"
|
||||
y="48.228924"
|
||||
id="tspan213995">0.7</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="211.10968"
|
||||
y="38.747059"
|
||||
id="text63580-0-3-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-2"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#a349a4;fill-opacity:1;stroke-width:0.264583"
|
||||
x="211.10968"
|
||||
y="38.747059">GRIMOIRE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-5"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60686"
|
||||
y="55.063217" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24358"
|
||||
y="58.506386"
|
||||
id="text63580-6-89-5-1-2-1-2"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24358"
|
||||
y="58.506386"
|
||||
id="tspan138056">GRIMOIRE</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.20389"
|
||||
y="61.596722"
|
||||
id="tspan214617">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3-1"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60687"
|
||||
y="67.944344" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="71.387512"
|
||||
id="text63580-6-89-5-1-2-1-5-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="71.387512"
|
||||
id="tspan126306-5">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.2039"
|
||||
y="74.477852"
|
||||
id="tspan215145">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="231.0405"
|
||||
y="72.844391"
|
||||
id="text63580-0-3-3-4-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2-7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="231.0405"
|
||||
y="72.844391">GTNHMIXINS MODULE</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="134.45549"
|
||||
y="11.566064"
|
||||
id="text109002"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan109000"
|
||||
style="stroke-width:0.264583"
|
||||
x="134.45549"
|
||||
y="11.566064"></tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="1.5918018"
|
||||
y="1.5918018" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836-0"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="92.015823"
|
||||
y="1.5918018" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836-0-8"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="182.40633"
|
||||
y="1.6533977" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Layer 2"
|
||||
sodipodi:insensitive="true">
|
||||
<rect
|
||||
style="display:inline;fill:#3f48cc;fill-opacity:0.17;stroke:#3f48cc;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0"
|
||||
width="45.063374"
|
||||
height="37.911438"
|
||||
x="11.578111"
|
||||
y="44.065044" />
|
||||
<rect
|
||||
style="display:inline;fill:#ed1c24;fill-opacity:0.17;stroke:#ed1c24;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104"
|
||||
width="45.040031"
|
||||
height="37.936855"
|
||||
x="34.465179"
|
||||
y="44.840611" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="36.860748" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="50.228546" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="63.109657" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9-0"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="75.71122" />
|
||||
<rect
|
||||
style="display:inline;fill:#a349a4;fill-opacity:0.17;stroke:#a349a4;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-7"
|
||||
width="23.043869"
|
||||
height="24.047258"
|
||||
x="205.57162"
|
||||
y="40.281944" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9-4"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="205.57162"
|
||||
y="66.530869" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 44 KiB |
+11
-10
@@ -15,8 +15,9 @@ All test cases assume default configs for mods.
|
||||
* Witchery is not a coremod, so if this mixin works, that means [adding it to the classpath early](https://github.com/jss2a98aj/BugTorch/blob/95480e11c5ea922f4cc2a7540ca944ef4a9aeaec/src/main/java/jss/bugtorch/core/BugTorchMixinPlugin.java#L149-L166) was successful.
|
||||
|
||||
* [x] MixinBooterLegacy
|
||||
* ❔ Early loader
|
||||
* No mods are known to use this.
|
||||
* [x] Early loader
|
||||
* [x] [forge-network-fix @ 340585e](https://github.com/tox1cozZ/forge-network-fix/tree/340585e66937fc14df0cf9ac22b19f5b1263c4b7)
|
||||
* [x] `Mixing MixinFMLIndexedMessageToMessageCodec from mixin.forgenetworkfix.json` appears in `fml-server-latest.log`
|
||||
* ❔ Late loader
|
||||
* No mods are known to use this.
|
||||
* ❔ MixinExtras (MixinBooterLegacy package name)
|
||||
@@ -24,7 +25,7 @@ All test cases assume default configs for mods.
|
||||
|
||||
* [x] GasStation
|
||||
* [x] Mod annotation
|
||||
* [x] [RightProperGUIScale 2.0.2](https://github.com/basdxz/RightProperGUIScale/releases/download/2.0.2/rightproperguiscale-mc1.7.10-2.0.2.jar) + [FalsePatternLib 0.10.14](https://github.com/FalsePattern/FalsePatternLib/releases/download/0.10.14/falsepatternlib-mc1.7.10-0.10.14.jar)
|
||||
* [x] [RightProperGUIScale 2.1.0](https://github.com/basdxz/RightProperGUIScale/releases/download/2.1.0/RightProperGUIScale-mc1.7.10-2.1.0.jar) + [FalsePatternLib 0.11.4](https://github.com/FalsePattern/FalsePatternLib/releases/download/0.11.4/falsepatternlib-mc1.7.10-0.11.4.jar)
|
||||
* [x] GUI Scale slider can be set to fractional values.
|
||||
* The mod hard depends on GasStation in [its mod annotation](https://github.com/basdxz/RightProperGUIScale/blob/a14814a00f7f360491f72367c40fcb31341abf7e/src/main/java/com/github/basdxz/rightproperguiscale/Tags.java#L17).
|
||||
* ❔ Early loader
|
||||
@@ -39,24 +40,24 @@ All test cases assume default configs for mods.
|
||||
* [x] GTNHMixins
|
||||
* [x] Mod annotation
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.0.11](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar)
|
||||
* [x] Chat background is transparent
|
||||
* [x] Chat background is transparent when unfocused
|
||||
* The mod hard depends on GTNHMixins in [its mod annotation](https://github.com/GTNewHorizons/Hodgepodge/blob/035015166f138ab56c5d5c5acd8d13dad79f95fc/src/main/java/com/mitchej123/hodgepodge/Hodgepodge.java#L21).
|
||||
* [x] Early loader
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.1.1](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar)
|
||||
* [x] Chat background is transparent
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.0.11](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar)
|
||||
* [x] Chat background is transparent when unfocused
|
||||
* An early loader is used to [load all early mixins](https://github.com/GTNewHorizons/Hodgepodge/blob/035015166f138ab56c5d5c5acd8d13dad79f95fc/src/main/java/com/mitchej123/hodgepodge/core/HodgepodgeCore.java#L35-L50), [including this one](https://github.com/GTNewHorizons/Hodgepodge/blob/2.0.27/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java#L98-L103).
|
||||
* [x] Late loader
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.1.1](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar) + [Baubles 1.0.1.16](https://github.com/GTNewHorizons/Baubles/releases/download/1.0.1.16/Baubles-1.0.1.16.jar)
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.0.11](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar) + [Baubles 1.0.1.16](https://github.com/GTNewHorizons/Baubles/releases/download/1.0.1.16/Baubles-1.0.1.16.jar)
|
||||
* [x] When the inventory is opened while a potion effect is active, the inventory GUI stays centered.
|
||||
* A late loader is used to [load all late mixins](https://github.com/GTNewHorizons/Hodgepodge/blob/2.0.27/src/main/java/com/mitchej123/hodgepodge/HodgepodgeLateMixins.java), [including this one](https://github.com/GTNewHorizons/Hodgepodge/blob/2.0.27/src/main/java/com/mitchej123/hodgepodge/mixins/Mixins.java#L489-L494).
|
||||
* [x] MixinExtras (GTNHMixins package name)
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.1.1](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar)
|
||||
* [x] Chat background is transparent
|
||||
* [x] [Hodgepodge 2.0.27](https://github.com/GTNewHorizons/Hodgepodge/releases/download/2.0.27/hodgepodge-1.7.10-2.0.27.jar) + [GTNHLib 0.0.11](https://github.com/GTNewHorizons/GTNHLib/releases/download/0.0.11/gtnhlib-1.7.10-0.0.11.jar)
|
||||
* [x] Chat background is transparent when unfocused
|
||||
* The [mixin](https://github.com/GTNewHorizons/Hodgepodge/blob/2.0.27/src/main/java/com/mitchej123/hodgepodge/mixins/early/minecraft/MixinGuiNewChat_TransparentChat.java) implementing this feature uses `@WrapWithCondition`.
|
||||
|
||||
* [x] Mixingasm
|
||||
* [x] Transformer exclusion
|
||||
* [x] [GregTech 6](https://gregtech.overminddl1.com/com/gregoriust/gregtech/gregtech_1.7.10/6.14.20/gregtech_1.7.10-6.14.20.jar) + [CoreTweaks 0.3.0.1+nomixin](https://github.com/makamys/CoreTweaks/releases/download/0.3.0.1/CoreTweaks-1.7.10-0.3.0.1+nomixin.jar) + [BugTorch 1.1.8](https://github.com/jss2a98aj/BugTorch/releases/download/1.1.8/bugtorch-1.7.10-1.1.8.jar)
|
||||
* [x] [GregTech 6.14.20](https://gregtech.overminddl1.com/com/gregoriust/gregtech/gregtech_1.7.10/6.14.20/gregtech_1.7.10-6.14.20.jar) + [CoreTweaks 0.3.0.1+nomixin](https://github.com/makamys/CoreTweaks/releases/download/0.3.0.1/CoreTweaks-1.7.10-0.3.0.1+nomixin.jar) + [BugTorch 1.1.8](https://github.com/jss2a98aj/BugTorch/releases/download/1.1.8/bugtorch-1.7.10-1.1.8.jar)
|
||||
* [x] Game reaches title screen
|
||||
* Without Mixingasm, this mod combination causes an early crash.
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Mod properties
|
||||
modid=unimixins
|
||||
archives_base=-unimixins
|
||||
archives_base=+unimixins
|
||||
# http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
group=io.github.legacymoddingmc.unimixins
|
||||
|
||||
|
||||
+84
-66
@@ -5,14 +5,25 @@ archivesBaseName = archivesBaseName.replace("-1.7.10", "-all-1.7.10")
|
||||
// The order of these determines the order embedded core plugins get initialized in
|
||||
ext.moduleNames = ["module-mixin", "module-compat", "module-mixingasm", "module-spongemixins", "module-mixinbooterlegacy", "module-gasstation", "module-gtnhmixins", "module-mixinextras"]
|
||||
|
||||
def getModuleJar(name, source = false) {
|
||||
def jarTaskName = name == "module-mixin" ? ":module-mixin:shadow${source ? 'Sources' : ''}JarUnimix" : ":$name:${source ? 'sourcesJar' : 'devJar'}"
|
||||
|
||||
return tasks.getByPath(jarTaskName).getOutputs().getFiles().getSingleFile()
|
||||
def getJarTaskName(name, classifier) {
|
||||
if(name == "module-mixin") {
|
||||
return ":module-mixin:shadow${classifier == 'sources' ? 'Sources' : ''}JarUnimix"
|
||||
} else {
|
||||
def candidate = ":" + name + ":" + (classifier + "Jar").uncapitalize()
|
||||
if(classifier == 'dev' && (tasks.findByPath(candidate) == null)) {
|
||||
return getJarTaskName(name, '')
|
||||
} else {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getModuleJars(source = false) {
|
||||
return moduleNames.collect { getModuleJar(it, source) }
|
||||
def getModuleJar(name, classifier = '') {
|
||||
return tasks.getByPath(getJarTaskName(name, classifier)).getOutputs().getFiles().getSingleFile()
|
||||
}
|
||||
|
||||
def getModuleJars(classifier = '') {
|
||||
return moduleNames.collect { getModuleJar(it, classifier) }
|
||||
}
|
||||
|
||||
import java.util.jar.Manifest;
|
||||
@@ -75,9 +86,8 @@ task createMergedAnnotationProcessorConfig() {
|
||||
doLast {
|
||||
// MixinExtras's APs have to be registered before Mixin's,
|
||||
// so we manually merge the APs to ensure this is the case.
|
||||
file(path).text = """com.llamalad7.mixinextras.MixinExtrasAP
|
||||
file(path).text = """com.llamalad7.mixinextras.ap.MixinExtrasAP
|
||||
io.github.tox1cozz.mixinextras.MixinExtrasAnnotationProcessor
|
||||
com.gtnewhorizon.mixinextras.MixinExtrasAP
|
||||
org.spongepowered.tools.obfuscation.MixinObfuscationProcessorInjection
|
||||
org.spongepowered.tools.obfuscation.MixinObfuscationProcessorTargets
|
||||
"""
|
||||
@@ -86,79 +96,85 @@ org.spongepowered.tools.obfuscation.MixinObfuscationProcessorTargets
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
shadow(project(":module-common")) {
|
||||
transitive = false
|
||||
}
|
||||
}
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
shadowJar {
|
||||
dependsOn tasks.createMergedMcmodInfo
|
||||
dependsOn tasks.createEmbeddedCorePluginsFile
|
||||
dependsOn tasks.createMergedAnnotationProcessorConfig
|
||||
|
||||
configurations = [project.configurations.shadow]
|
||||
classifier = ''
|
||||
relocate 'io.github.legacymoddingmc.unimixins.common', 'io.github.legacymoddingmc.unimixins.all.repackage.common'
|
||||
|
||||
moduleNames.each {
|
||||
def name = it
|
||||
def j = getModuleJar(it)
|
||||
into ""
|
||||
from(zipTree(j)){
|
||||
exclude 'mcmod.info'
|
||||
exclude 'META-INF/MANIFEST.MF'
|
||||
exclude 'CREDITS', 'LICENSE*', 'README*'
|
||||
exclude 'META-INF/services/javax.annotation.processing.Processor'
|
||||
into("")
|
||||
}
|
||||
from(zipTree(j)){
|
||||
include 'CREDITS', 'LICENSE*', 'README*'
|
||||
into("META-INF/licenses/$name")
|
||||
}
|
||||
}
|
||||
|
||||
from tasks.createMergedMcmodInfo.getOutputs().getFiles().getSingleFile()
|
||||
from(tasks.createEmbeddedCorePluginsFile.getOutputs().getFiles().getSingleFile()) {
|
||||
into 'META-INF'
|
||||
}
|
||||
from(tasks.createMergedAnnotationProcessorConfig.getOutputs().getFiles().getSingleFile()) {
|
||||
into 'META-INF/services'
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes (
|
||||
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
'FMLCorePluginContainsFMLMod': true,
|
||||
'ForceLoadAsMod': true,
|
||||
'FMLCorePlugin': 'io.github.legacymoddingmc.unimixins.all.AllCore',
|
||||
'MixinConfigs': 'mixins.gtnhmixins.json,mixins.gasstation.json,mixins.gtnhmixins.json,mixingasm.mixin.json',
|
||||
'Premain-Class': 'org.spongepowered.tools.agent.MixinAgent',
|
||||
'Agent-Class': 'org.spongepowered.tools.agent.MixinAgent',
|
||||
'Can-Redefine-Classes': true,
|
||||
'Can-Retransform-Classes': true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
doFirst {
|
||||
manifest.attributes (
|
||||
'Implementation-Version': getManifest(getModuleJar("module-mixin")).getValue("Implementation-Version")
|
||||
)
|
||||
task devJar(type: ShadowJar) {
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
tasks.withType(ShadowJar) {
|
||||
if(name == "shadowJar" || name == "devJar") {
|
||||
dependsOn tasks.createMergedMcmodInfo
|
||||
dependsOn tasks.createEmbeddedCorePluginsFile
|
||||
dependsOn tasks.createMergedAnnotationProcessorConfig
|
||||
|
||||
from sourceSets.main.output
|
||||
configurations = [project.configurations.shadow]
|
||||
relocate 'io.github.legacymoddingmc.unimixins.common', 'io.github.legacymoddingmc.unimixins.all.repackage.common'
|
||||
|
||||
(["module-common"] + moduleNames).each {
|
||||
def name = it
|
||||
def j = getModuleJar(it, classifier)
|
||||
into ""
|
||||
from(zipTree(j)){
|
||||
exclude 'mcmod.info'
|
||||
exclude 'META-INF/MANIFEST.MF'
|
||||
exclude 'CREDITS', 'LICENSE*', 'README*'
|
||||
exclude 'META-INF/services/javax.annotation.processing.Processor'
|
||||
into("")
|
||||
}
|
||||
from(zipTree(j)){
|
||||
include 'CREDITS', 'LICENSE*', 'README*'
|
||||
into("META-INF/licenses/$name")
|
||||
}
|
||||
}
|
||||
|
||||
from tasks.createMergedMcmodInfo.getOutputs().getFiles().getSingleFile()
|
||||
from(tasks.createEmbeddedCorePluginsFile.getOutputs().getFiles().getSingleFile()) {
|
||||
into 'META-INF'
|
||||
}
|
||||
from(tasks.createMergedAnnotationProcessorConfig.getOutputs().getFiles().getSingleFile()) {
|
||||
into 'META-INF/services'
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes (
|
||||
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
'FMLCorePluginContainsFMLMod': true,
|
||||
'ForceLoadAsMod': true,
|
||||
'FMLCorePlugin': 'io.github.legacymoddingmc.unimixins.all.AllCore',
|
||||
'MixinConfigs': 'mixins.gtnhmixins.json,mixins.gasstation.json,mixins.gtnhmixins.json,mixingasm.mixin.json',
|
||||
'Premain-Class': 'org.spongepowered.tools.agent.MixinAgent',
|
||||
'Agent-Class': 'org.spongepowered.tools.agent.MixinAgent',
|
||||
'Can-Redefine-Classes': true,
|
||||
'Can-Retransform-Classes': true,
|
||||
)
|
||||
}
|
||||
|
||||
doFirst {
|
||||
manifest.attributes (
|
||||
'Implementation-Version': getManifest(getModuleJar("module-mixin")).getValue("Implementation-Version")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
dependsOn shadowJar
|
||||
dependsOn shadowJar, devJar
|
||||
}
|
||||
|
||||
task sourcesJar(type: ShadowJar) {
|
||||
dependsOn shadowJar
|
||||
dependsOn devJar
|
||||
|
||||
classifier = 'sources'
|
||||
|
||||
moduleNames.each {
|
||||
def j = getModuleJar(it, true)
|
||||
def j = getModuleJar(it, 'sources')
|
||||
from(zipTree(j)){
|
||||
exclude 'mcmod.info'
|
||||
exclude 'META-INF/MANIFEST.MF'
|
||||
@@ -167,7 +183,7 @@ task sourcesJar(type: ShadowJar) {
|
||||
}
|
||||
}
|
||||
|
||||
from(zipTree(tasks.shadowJar.getOutputs().getFiles().getSingleFile())) {
|
||||
from(zipTree(tasks.devJar.getOutputs().getFiles().getSingleFile())) {
|
||||
include "CREDITS"
|
||||
include "META-INF/licenses/**"
|
||||
}
|
||||
@@ -176,3 +192,5 @@ task sourcesJar(type: ShadowJar) {
|
||||
clean {
|
||||
moduleNames.each { dependsOn tasks.getByPath(":$it:clean") }
|
||||
}
|
||||
|
||||
reobf.enabled = false
|
||||
@@ -4,6 +4,7 @@ import java.util.*;
|
||||
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -70,7 +71,36 @@ public class AllCore implements IFMLLoadingPlugin {
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
return "io.github.legacymoddingmc.unimixins.all.AllCore$CombinedAccessTransformer";
|
||||
}
|
||||
|
||||
public static class CombinedAccessTransformer implements IClassTransformer {
|
||||
private final List<IClassTransformer> delegates = new ArrayList<>();
|
||||
public CombinedAccessTransformer() {
|
||||
for(IFMLLoadingPlugin plugin : embeddedCorePluginInstances) {
|
||||
String atClass = plugin.getAccessTransformerClass();
|
||||
if(atClass != null) {
|
||||
try {
|
||||
delegates.add((IClassTransformer) Class.forName(atClass).newInstance());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
for(IClassTransformer delegate : delegates) {
|
||||
basicClass = delegate.transform(name, transformedName, basicClass);
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegates.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import cpw.mods.fml.common.Mod;
|
||||
/**
|
||||
* This is only here so unimixins shows up in the mod list GUI as a single mod.
|
||||
*/
|
||||
@Mod(modid = "unimixins", version = "@VERSION@")
|
||||
@Mod(modid = "unimixins", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "unimixins", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class AllModule {
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-common-1.7.10")
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-common-1.7.10" )
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package io.github.legacymoddingmc.unimixins.common.abstraction;
|
||||
|
||||
public class ComparableVersion {
|
||||
private final IComparableVersionImpl impl;
|
||||
|
||||
public ComparableVersion(String version) {
|
||||
if(ComparableVersion.class.getResource("/cpw/mods/fml/common/versioning/ComparableVersion.class") != null) {
|
||||
impl = new ComparableVersionOld(version);
|
||||
} else {
|
||||
impl = new ComparableVersionNew(version);
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(ComparableVersion other) {
|
||||
return impl.compareTo(other.impl);
|
||||
}
|
||||
|
||||
public interface IComparableVersionImpl {
|
||||
int compareTo(IComparableVersionImpl other);
|
||||
}
|
||||
|
||||
public static class ComparableVersionOld implements IComparableVersionImpl {
|
||||
private final cpw.mods.fml.common.versioning.ComparableVersion internal;
|
||||
|
||||
public ComparableVersionOld(String version) {
|
||||
this.internal = new cpw.mods.fml.common.versioning.ComparableVersion(version);
|
||||
}
|
||||
|
||||
public int compareTo(IComparableVersionImpl other) {
|
||||
if(other instanceof ComparableVersionOld) {
|
||||
return internal.compareTo(((ComparableVersionOld) other).internal);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ComparableVersionNew implements IComparableVersionImpl {
|
||||
private final net.minecraftforge.fml.common.versioning.ComparableVersion internal;
|
||||
|
||||
public ComparableVersionNew(String version) {
|
||||
this.internal = new net.minecraftforge.fml.common.versioning.ComparableVersion(version);
|
||||
}
|
||||
|
||||
public int compareTo(IComparableVersionImpl other) {
|
||||
if(other instanceof ComparableVersionNew) {
|
||||
return internal.compareTo(((ComparableVersionNew) other).internal);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ archivesBaseName = archivesBaseName.replace("-1.7.10", "-compat-1.7.10")
|
||||
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
|
||||
|
||||
shadowJar {
|
||||
configurations = [project.configurations.shadow]
|
||||
classifier = ''
|
||||
|
||||
+2
@@ -7,4 +7,6 @@ public class CompatConfig {
|
||||
public static boolean enableRemapper;
|
||||
@AnnotatedProperties.ConfigString(def = "true", com = "Include mixin errors and list of applied mixins in crash reports.", cat = "compat")
|
||||
public static boolean enhanceCrashReports;
|
||||
@AnnotatedProperties.ConfigString(def = "true", com = "Make Mixin's INIT phase listener more reliable. Fixes INIT phase mixins not working with certain launchers with the LiteLoader mod.", cat = "compat")
|
||||
public static boolean improveInitPhaseDetection;
|
||||
}
|
||||
+53
-5
@@ -2,11 +2,14 @@ package io.github.legacymoddingmc.unimixins.compat;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import io.github.legacymoddingmc.unimixins.common.config.ConfigUtil;
|
||||
import io.github.legacymoddingmc.unimixins.compat.asm.ModDiscovererTransformer;
|
||||
import io.github.legacymoddingmc.unimixins.compat.asm.IgnoreDuplicateJarsTransformer;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
@@ -31,10 +34,13 @@ public class CompatCore implements IFMLLoadingPlugin {
|
||||
public String[] getASMTransformerClass() {
|
||||
List<String> classes = new ArrayList<>();
|
||||
if(CompatConfig.enhanceCrashReports) {
|
||||
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.FMLCommonHandlerTransformer");
|
||||
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.EnhanceCrashReportsTransformer");
|
||||
}
|
||||
if(ModDiscovererTransformer.wantsToRun()) {
|
||||
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.ModDiscovererTransformer");
|
||||
if(IgnoreDuplicateJarsTransformer.wantsToRun()) {
|
||||
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.IgnoreDuplicateJarsTransformer");
|
||||
}
|
||||
if(Boolean.parseBoolean(System.getProperty("unimixins.compat.hackClasspathModDiscovery", "false"))) {
|
||||
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.HackClasspathModDiscoveryTransformer");
|
||||
}
|
||||
return classes.toArray(new String[0]);
|
||||
}
|
||||
@@ -69,9 +75,51 @@ public class CompatCore implements IFMLLoadingPlugin {
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
return "io.github.legacymoddingmc.unimixins.compat.CompatCore$DummyTransformer";
|
||||
}
|
||||
|
||||
/** Coremod Access Transformers are initialized at the beginning of {@link cpw.mods.fml.common.launcher.FMLDeobfTweaker#injectIntoClassLoader}.
|
||||
* We use this as an injection point, this transformer doesn't actually transform anything. */
|
||||
@SuppressWarnings("unused")
|
||||
public static class DummyTransformer implements IClassTransformer {
|
||||
public DummyTransformer() {
|
||||
if (CompatConfig.improveInitPhaseDetection) {
|
||||
setFmlLoggerToVerbose();
|
||||
}
|
||||
}
|
||||
|
||||
/** Mixin detects the start of the INIT phase by listening for the "Validating minecraft" FML log message.
|
||||
* (See <tt>MixinAppender</tt> in {@link org.spongepowered.asm.launch.platform.MixinPlatformAgentFMLLegacy}.)
|
||||
*
|
||||
* <p>It sets the verbosity to ALL in an attempt to ensure the message gets logged, but this is not always the
|
||||
* case. We add an extra check here, in a method that gets called right before that log message.</p>
|
||||
*/
|
||||
private static void setFmlLoggerToVerbose() {
|
||||
Logger fmlLog;
|
||||
try {
|
||||
fmlLog = FMLRelaunchLog.log.getLogger();
|
||||
if (!(fmlLog instanceof org.apache.logging.log4j.core.Logger)) {
|
||||
return;
|
||||
}
|
||||
} catch (NoClassDefFoundError e) {
|
||||
return;
|
||||
}
|
||||
|
||||
org.apache.logging.log4j.core.Logger fmlCoreLog = (org.apache.logging.log4j.core.Logger)fmlLog;
|
||||
|
||||
if(fmlCoreLog.getLevel() != Level.ALL) {
|
||||
LOGGER.info("Correcting FML log level from " + fmlCoreLog.getLevel() + " to ALL");
|
||||
} else {
|
||||
LOGGER.debug("FML log level was already ALL, doing nothing");
|
||||
}
|
||||
|
||||
fmlCoreLog.setLevel(Level.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
return basicClass;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -5,6 +5,7 @@ import cpw.mods.fml.common.Mod;
|
||||
/**
|
||||
* This is only here to help Forge detect the mod.
|
||||
*/
|
||||
@Mod(modid = "unimixins-compat", version = "@VERSION@")
|
||||
@Mod(modid = "unimixins-compat", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "unimixins-compat", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class CompatModule {
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package io.github.legacymoddingmc.unimixins.compat.api;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** <p>Decorate your class with this annotation to make UniMixins remap references to <code>org.objectweb.asm</code> to
|
||||
* the ASM package name used by the current Mixin environment.</p>
|
||||
* <p>This is needed if you have a mixin config plugin compiled against this package name, and you want to pass the
|
||||
* ClassNode reference to a different class, since otherwise UniMixins only remaps references inside the mixin
|
||||
* config plugin class.</p> */
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface RemapASMForMixin {
|
||||
}
|
||||
+67
-39
@@ -10,45 +10,45 @@ import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.objectweb.asm.commons.RemappingClassAdapter;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>Some classes use Mixin internals, so we need to make sure they use the correct type names, and remap them if they don't.</p>
|
||||
* <p>We do this for every class for maximum compatibility.</p>
|
||||
* <p>The ASM package name used by Mixin differs between mixin loaders. This transformer remaps references to ASM to use the
|
||||
* correct package name for the current runtime environment, allowing mods to work regardless of what mixin loader they
|
||||
* were compiled against.</p>
|
||||
* <p>The following packages are remapped:</p>
|
||||
* <li><code>org.spongepowered.libraries.org.objectweb.asm</code> (MixinBooterLegacy, GTNHMixins) in all classes</li>
|
||||
* <li><code>org.spongepowered.asm.lib</code> (Mixin 0.7, GasStation, UniMixins) in all classes</li>
|
||||
* <li><code>org.objectweb.asm</code> (Mixin 0.8) in classes implementing {@link org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin} or annotated with {@link io.github.legacymoddingmc.unimixins.compat.api.RemapASMForMixin}</li>
|
||||
*/
|
||||
|
||||
// TODO Measure the performance impact of this and switch to doing it selectively if it would improve things.
|
||||
public class ASMRemapperTransformer implements IClassTransformer {
|
||||
|
||||
/** A class will be remapped if it implements one of these interfaces. */
|
||||
private static Set<String> interfaceWhitelist = new HashSet<>();
|
||||
|
||||
/** A class will be remapped if its name starts with one of these strings. */
|
||||
private static Set<String> packageWhitelist = new HashSet<>();
|
||||
|
||||
private static final boolean remapSelectively = Boolean.parseBoolean(System.getProperty("unimixins.compat.remapSelectively", "false"));
|
||||
private static final String ASM_PACKAGE_UNSHADED = "org/objectweb/asm/";
|
||||
private static final String ASM_PACKAGE_LEGACY = "org/spongepowered/asm/lib/";
|
||||
private static final String ASM_PACKAGE_MBL = "org/spongepowered/libraries/org/objectweb/asm/";
|
||||
|
||||
private static final List<String> ASM_PACKAGE_PREFIXES = Arrays.asList(
|
||||
"org/spongepowered/libraries/org/objectweb/asm/",
|
||||
"org/spongepowered/asm/lib/"
|
||||
ASM_PACKAGE_UNSHADED,
|
||||
ASM_PACKAGE_LEGACY,
|
||||
ASM_PACKAGE_MBL
|
||||
);
|
||||
|
||||
private static final List<byte[]> SHADED_ASM_PACKAGE_PREFIXES_RAW = Arrays.asList(
|
||||
ASM_PACKAGE_LEGACY.getBytes(StandardCharsets.UTF_8),
|
||||
ASM_PACKAGE_MBL.getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
|
||||
private static String realASMPackagePrefix;
|
||||
|
||||
public static void registerInterface(String itf) {
|
||||
interfaceWhitelist.add(itf.replace('.', '/'));
|
||||
}
|
||||
|
||||
public static void registerPackage(String pkg) {
|
||||
packageWhitelist.add(pkg + ".");
|
||||
}
|
||||
|
||||
public ASMRemapperTransformer() {
|
||||
registerInterface("org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin");
|
||||
}
|
||||
private static List<byte[]> wrongASMPackagePrefixesRaw;
|
||||
private static List<String> wrongASMPackagePrefixes;
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
@@ -61,35 +61,41 @@ public class ASMRemapperTransformer implements IClassTransformer {
|
||||
|| transformedName.startsWith("org.objectweb.asm.")
|
||||
) return basicClass;
|
||||
|
||||
ClassReader classReader = new ClassReader(basicClass);
|
||||
boolean foundWrongAsm = containsAnyPattern(basicClass, getWrongASMPackagePrefixesRaw());
|
||||
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReaderForNode = new ClassReader(basicClass);
|
||||
classReaderForNode.accept(classNode, 0);
|
||||
if(!foundWrongAsm) return basicClass;
|
||||
|
||||
boolean doRemap = false;
|
||||
boolean foundShadedAsm = containsAnyPattern(basicClass, SHADED_ASM_PACKAGE_PREFIXES_RAW);
|
||||
|
||||
if(remapSelectively) {
|
||||
if(!doRemap) {
|
||||
boolean doRemap = foundShadedAsm;
|
||||
|
||||
if(!doRemap) {
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReaderForNode = new ClassReader(basicClass);
|
||||
classReaderForNode.accept(classNode, 0);
|
||||
|
||||
if(classNode.interfaces != null) {
|
||||
for (String itf : classNode.interfaces) {
|
||||
if (interfaceWhitelist.contains(itf)) {
|
||||
if (itf.equals("org/spongepowered/asm/mixin/extensibility/IMixinConfigPlugin")) {
|
||||
doRemap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!doRemap) {
|
||||
for (String pkg : packageWhitelist) {
|
||||
if(transformedName.startsWith(pkg)) {
|
||||
doRemap = true;
|
||||
if(classNode.visibleAnnotations != null) {
|
||||
for (AnnotationNode ann : classNode.visibleAnnotations) {
|
||||
if (ann.desc.equals("Lio/github/legacymoddingmc/unimixins/compat/api/RemapASMForMixin;")) {
|
||||
doRemap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doRemap = Bytes.indexOf(basicClass, getFakeASMPackagePrefix().getBytes()) != -1;
|
||||
}
|
||||
|
||||
if(doRemap) {
|
||||
ClassReader classReader = new ClassReader(basicClass);
|
||||
LOGGER.info("Transforming class " + transformedName + " to fit current mixin environment.");
|
||||
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
RemappingClassAdapter remapAdapter = new SpongepoweredASMRemappingAdapter(classWriter);
|
||||
@@ -99,6 +105,18 @@ public class ASMRemapperTransformer implements IClassTransformer {
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
private static boolean containsAnyPattern(byte[] array, List<byte[]> patterns) {
|
||||
if(array == null) {
|
||||
return false;
|
||||
}
|
||||
for(byte[] pattern : patterns) {
|
||||
if(Bytes.indexOf(array, pattern) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getRealASMPackagePrefix() {
|
||||
if(realASMPackagePrefix == null) {
|
||||
try {
|
||||
@@ -129,10 +147,20 @@ public class ASMRemapperTransformer implements IClassTransformer {
|
||||
return realASMPackagePrefix;
|
||||
}
|
||||
|
||||
private static String getFakeASMPackagePrefix() {
|
||||
return ASM_PACKAGE_PREFIXES.get(ASM_PACKAGE_PREFIXES.get(0).equals(getRealASMPackagePrefix()) ? 1 : 0);
|
||||
private static List<String> getWrongASMPackagePrefixes() {
|
||||
if(wrongASMPackagePrefixes == null) {
|
||||
wrongASMPackagePrefixes = ASM_PACKAGE_PREFIXES.stream().filter(x -> !x.equals(getRealASMPackagePrefix())).collect(Collectors.toList());
|
||||
}
|
||||
return wrongASMPackagePrefixes;
|
||||
}
|
||||
|
||||
private static List<byte[]> getWrongASMPackagePrefixesRaw() {
|
||||
if(wrongASMPackagePrefixesRaw == null) {
|
||||
wrongASMPackagePrefixesRaw = getWrongASMPackagePrefixes().stream().map(x -> x.getBytes(StandardCharsets.UTF_8)).collect(Collectors.toList());
|
||||
}
|
||||
return wrongASMPackagePrefixesRaw;
|
||||
}
|
||||
|
||||
private static class SpongepoweredASMRemappingAdapter extends RemappingClassAdapter {
|
||||
public SpongepoweredASMRemappingAdapter(ClassWriter classWriter) {
|
||||
super(classWriter, SpongepoweredASMRemapper.INSTANCE);
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ import static io.github.legacymoddingmc.unimixins.compat.CompatCore.LOGGER;
|
||||
* <p>Inserts a hook at the end of FMLCommonHandler#enhanceCrashReport.
|
||||
* <p>We use a transformer instead of a mixin because FML is a minefield for mixin errors.
|
||||
*/
|
||||
public class FMLCommonHandlerTransformer implements IClassTransformer {
|
||||
public class EnhanceCrashReportsTransformer implements IClassTransformer {
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if(basicClass == null) return null;
|
||||
@@ -34,7 +34,7 @@ public class FMLCommonHandlerTransformer implements IClassTransformer {
|
||||
* {
|
||||
* category.addCrashSectionCallable(call.getLabel(), call);
|
||||
* }
|
||||
* + FMLCommonHandlerTransformer.Hooks.postEnhanceCrashReport();
|
||||
* + EnhanceCrashReportsTransformer.Hooks.postEnhanceCrashReport();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@@ -65,7 +65,7 @@ public class FMLCommonHandlerTransformer implements IClassTransformer {
|
||||
//ALOAD category
|
||||
inject.add(new VarInsnNode(ALOAD, 2));
|
||||
//INVOKESTATIC foo/bar.postEnhanceCrashReport(Lnet/minecraft/crash/CrashReport;Lnet/minecraft/crash/CrashReportCategory;)V
|
||||
inject.add(new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/compat/asm/FMLCommonHandlerTransformer$Hooks", "postEnhanceCrashReport", "(Lnet/minecraft/crash/CrashReport;Lnet/minecraft/crash/CrashReportCategory;)V", false));
|
||||
inject.add(new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/compat/asm/EnhanceCrashReportsTransformer$Hooks", "postEnhanceCrashReport", "(Lnet/minecraft/crash/CrashReport;Lnet/minecraft/crash/CrashReportCategory;)V", false));
|
||||
m.instructions.insertBefore(injectionTarget, inject);
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -1,8 +1,7 @@
|
||||
package io.github.legacymoddingmc.unimixins.devcompat.asm;
|
||||
package io.github.legacymoddingmc.unimixins.compat.asm;
|
||||
|
||||
import static io.github.legacymoddingmc.unimixins.devcompat.DevCompatCore.LOGGER;
|
||||
import static io.github.legacymoddingmc.unimixins.compat.CompatCore.LOGGER;
|
||||
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
@@ -18,7 +17,7 @@ import java.util.*;
|
||||
* <p>Fixes classpath mods not getting loaded in dev env when running via the runClient Gradle task.</p>
|
||||
*/
|
||||
|
||||
public class ModDiscovererTransformer implements IClassTransformer {
|
||||
public class HackClasspathModDiscoveryTransformer implements IClassTransformer {
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
@@ -34,7 +33,7 @@ public class ModDiscovererTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
private byte[] doTransformModDiscoverer(byte[] bytes) {
|
||||
LOGGER.info("ModDiscovererTransformer: Transforming ModDiscoverer#findClasspathMods to ignore reparseable coremods.");
|
||||
LOGGER.info("HackClasspathModDiscoveryTransformer: Transforming ModDiscoverer#findClasspathMods to ignore reparseable coremods.");
|
||||
|
||||
try {
|
||||
ClassNode classNode = new ClassNode();
|
||||
@@ -49,7 +48,7 @@ public class ModDiscovererTransformer implements IClassTransformer {
|
||||
if(i.getOpcode() == INVOKESTATIC) {
|
||||
MethodInsnNode mi = (MethodInsnNode)i;
|
||||
if(mi.owner.equals("cpw/mods/fml/relauncher/CoreModManager") && mi.name.equals("getReparseableCoremods") && mi.desc.equals("()Ljava/util/List;")) {
|
||||
m.instructions.insertBefore(mi, new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/devcompat/asm/ModDiscovererTransformer$Hooks", "redirectGetReparseableCoremods", mi.desc));
|
||||
m.instructions.insertBefore(mi, new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/compat/asm/HackClasspathModDiscoveryTransformer$Hooks", "redirectGetReparseableCoremods", mi.desc));
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
+3
-9
@@ -1,9 +1,5 @@
|
||||
package io.github.legacymoddingmc.unimixins.compat.asm;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import cpw.mods.fml.common.discovery.ModCandidate;
|
||||
import cpw.mods.fml.common.discovery.ModDiscoverer;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
@@ -13,10 +9,8 @@ import org.objectweb.asm.tree.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.github.legacymoddingmc.unimixins.compat.CompatCore.LOGGER;
|
||||
import static org.objectweb.asm.Opcodes.ALOAD;
|
||||
@@ -26,7 +20,7 @@ import static org.objectweb.asm.Opcodes.INVOKESTATIC;
|
||||
* Makes the mod discoverer ignore duplicate UniMixins jars that come from java agents. This allows UniMixins to be
|
||||
* safely used as a Java agent instead of having to hunt down the UniMix jar and add that as one.
|
||||
*/
|
||||
public class ModDiscovererTransformer implements IClassTransformer {
|
||||
public class IgnoreDuplicateJarsTransformer implements IClassTransformer {
|
||||
|
||||
private static Set<File> uniMixinsJavaAgentJars;
|
||||
|
||||
@@ -70,7 +64,7 @@ public class ModDiscovererTransformer implements IClassTransformer {
|
||||
}
|
||||
|
||||
private byte[] doTransformModDiscoverer(byte[] bytes) {
|
||||
LOGGER.info("ModDiscovererTransformer: Transforming ModDiscoverer#identifyMods to ignore duplicate UniMixins jars coming from Java agents.");
|
||||
LOGGER.info("IgnoreDuplicateJarsTransformer: Transforming ModDiscoverer#identifyMods to ignore duplicate UniMixins jars coming from Java agents.");
|
||||
|
||||
try {
|
||||
ClassNode classNode = new ClassNode();
|
||||
@@ -80,7 +74,7 @@ public class ModDiscovererTransformer implements IClassTransformer {
|
||||
if(m.name.equals("identifyMods")) {
|
||||
InsnList patch = new InsnList();
|
||||
patch.add(new VarInsnNode(ALOAD, 0));
|
||||
patch.add(new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/compat/asm/ModDiscovererTransformer$Hooks", "preIdentifyMods", "(Lcpw/mods/fml/common/discovery/ModDiscoverer;)V"));
|
||||
patch.add(new MethodInsnNode(INVOKESTATIC, "io/github/legacymoddingmc/unimixins/compat/asm/IgnoreDuplicateJarsTransformer$Hooks", "preIdentifyMods", "(Lcpw/mods/fml/common/discovery/ModDiscoverer;)V"));
|
||||
m.instructions.insert(patch);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,21 @@
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-compatfuture-1.7.10")
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier = ""
|
||||
configurations = []
|
||||
relocate 'io.github.legacymoddingmc.unimixins.compat.stub.cpw', 'cpw'
|
||||
|
||||
manifest {
|
||||
attributes (
|
||||
'FMLCorePluginContainsFMLMod': true,
|
||||
'ForceLoadAsMod': true,
|
||||
'FMLCorePlugin': 'io.github.legacymoddingmc.unimixins.compatfuture.CompatFutureCore'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
jar.dependsOn shadowJar
|
||||
jar.enabled = false
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.github.legacymoddingmc.unimixins.compatfuture;
|
||||
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is only here so Forge puts the mod on the classpath during coremod loading.
|
||||
*/
|
||||
public class CompatFutureCore implements IFMLLoadingPlugin {
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.github.legacymoddingmc.unimixins.compatfuture;
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* This is only here to help Forge detect the mod.
|
||||
*/
|
||||
@Mod(modid = "unimixins-compatfuture", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "unimixins-compatfuture", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class CompatFutureModule {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package io.github.legacymoddingmc.unimixins.compat.stub.cpw.mods.fml.relauncher;
|
||||
|
||||
/** Stub for 1.8+ compat. (This gets relocated to the <code>cpw.mods.fml.relauncher</code> package.) */
|
||||
public interface IFMLLoadingPlugin extends net.minecraftforge.fml.relauncher.IFMLLoadingPlugin {
|
||||
}
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"modid": "unimixins-devcompat",
|
||||
"name": "UniMixins: Dev Compatibility",
|
||||
"description": "UniMixins module that applies compatibility tweaks for dev environments.",
|
||||
"modid": "unimixins-compatfuture",
|
||||
"name": "UniMixins: Future Compatibility",
|
||||
"description": "UniMixins module that makes the mod usable on 1.8.9 ~ 1.12.2.",
|
||||
"version": "${version}",
|
||||
"mcversion": "${minecraft_version}",
|
||||
"url": "${project_url}",
|
||||
@@ -1,16 +0,0 @@
|
||||
dependencies {
|
||||
compileOnly('org.spongepowered:mixin:0.8.5')
|
||||
}
|
||||
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-devcompat-1.7.10")
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes (
|
||||
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
'FMLCorePluginContainsFMLMod': true,
|
||||
'ForceLoadAsMod': true,
|
||||
'FMLCorePlugin': 'io.github.legacymoddingmc.unimixins.devcompat.DevCompatCore'
|
||||
)
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package io.github.legacymoddingmc.unimixins.devcompat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@MCVersion("1.7.10")
|
||||
public class DevCompatCore implements IFMLLoadingPlugin {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger("unimixins");
|
||||
|
||||
public DevCompatCore() {
|
||||
LOGGER.info("Instantiating DevCompatCore");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[] {relativeClassName("asm.ModDiscovererTransformer")};
|
||||
}
|
||||
|
||||
private static String relativeClassName(String relName) {
|
||||
String name = DevCompatCore.class.getName();
|
||||
name = name.substring(0, name.lastIndexOf('.') + 1);
|
||||
name += relName;
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package io.github.legacymoddingmc.unimixins.devcompat;
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* This is only here to help Forge detect the mod.
|
||||
*/
|
||||
@Mod(modid = "unimixins-devcompat", version = "@VERSION@")
|
||||
public class DevCompatModule {
|
||||
}
|
||||
@@ -9,5 +9,6 @@ Modifications:
|
||||
- Removed Mixin and MixinExtras bootstrap from GasStationCore.
|
||||
- Disabled dev mixin plugin because UniMixins's Compat module does the same thing.
|
||||
- Added call to "unimixins.mixinModidDecorator.refresh" after loading early mixins in GasStationCore and late mixins in LoadControllerMixin
|
||||
- Added 1.8+ @Mod and @IFMLPlugin annotations
|
||||
|
||||
License: LGPL3+SNEED (see LICENSE, COPYING and COPYING.LESSER)
|
||||
@@ -1,5 +1,5 @@
|
||||
dependencies {
|
||||
compileOnly('org.spongepowered:mixin:0.8.5-gasstation_7')
|
||||
compileOnly("org.spongepowered:mixin:$gasMixVersion")
|
||||
compileOnly project(':module-mixinbooterlegacy')
|
||||
shadow(project(":module-common")) {
|
||||
transitive = false
|
||||
@@ -29,8 +29,10 @@ jar {
|
||||
dependsOn shadowJar
|
||||
}
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.extraVersion = "0.5.1"
|
||||
ext.mcversion = "1.7.10"
|
||||
version += "+" + ext.extraVersion
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
extraVersion=0.5.1
|
||||
gasMixVersion=0.8.5-gasstation_7
|
||||
@@ -6,5 +6,9 @@ import cpw.mods.fml.common.Mod;
|
||||
version = Tags.VERSION,
|
||||
name = Tags.MODNAME,
|
||||
acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = Tags.MODID,
|
||||
version = Tags.VERSION,
|
||||
name = Tags.MODNAME,
|
||||
acceptableRemoteVersions = "*")
|
||||
public class GasStation {
|
||||
}
|
||||
@@ -19,6 +19,9 @@ import java.util.Map;
|
||||
@IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@IFMLLoadingPlugin.Name(GasStationCore.PLUGIN_NAME)
|
||||
@IFMLLoadingPlugin.TransformerExclusions("com.falsepattern.gasstation.core")
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name(GasStationCore.PLUGIN_NAME)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("com.falsepattern.gasstation.core")
|
||||
public class GasStationCore implements IFMLLoadingPlugin {
|
||||
public static final String PLUGIN_NAME = Tags.MODNAME + " Core Plugin";
|
||||
public static final Logger LOGGER = LogManager.getLogger(PLUGIN_NAME);
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import java.util.List;
|
||||
|
||||
public class GasStationModule {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("unimixin-gasstation");
|
||||
private static final Logger LOGGER = LogManager.getLogger("unimixins-gasstation");
|
||||
|
||||
public static void init() {
|
||||
if(SanityCheckHelper.isEnabled()) {
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
# Classes listed in this file will be considered "untrusted" by Mixingasm and
|
||||
# added to the mixin environment's transformer exclusion list.
|
||||
# See transformer_inclusion_list_default.txt for more info.
|
||||
|
||||
|
||||
# --- Untrusted transformers ---
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
# Classes listed in this file will be considered "trusted" by Mixingasm and
|
||||
# may be spared from the mixin environment's transformer exclusion list.
|
||||
# See transformer_inclusion_list_default.txt for more info.
|
||||
|
||||
|
||||
# --- Additional trusted transformers ---
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
:replaceableFile # This file will get OVERWRITTEN at launch, nullifying any changes made to it, unless you delete this line. It is recommended to edit transformer_inclusion_list.txt and transformer_exclusion_list.txt instead, though.
|
||||
|
||||
# Mixingasm adds all transformers it doesn't "trust" to be Mixin-safe to the
|
||||
# mixin environment's transformer exclusion list, avoiding running them an
|
||||
# additional time when processing mixins at startup.
|
||||
|
||||
# This fixes issues that can arise from non-Mixin-aware transformers being run
|
||||
# in that way. For example, some transformers break when run more than once.
|
||||
|
||||
# A transformer is considered "trusted" if one of these are true...
|
||||
# * It's matched by a pattern in this file
|
||||
# * It's matched by a pattern in transformer_inclusion_list.txt
|
||||
# * It was added to Mixingasm's dynamic inclusion list by a mod using the API at startup
|
||||
# * The transformer implements IMixinSafeTransformer
|
||||
# AND the transformer is not matched by a pattern in transformer_exclusion_list.txt
|
||||
|
||||
# '*' can be used as a wildcard character.
|
||||
|
||||
|
||||
# --- Trusted transformers ---
|
||||
|
||||
cpw.mods.fml.common.asm.*
|
||||
net.minecraftforge.*
|
||||
codechicken.core.asm.*
|
||||
codechicken.lib.asm.*
|
||||
org.spongepowered.asm.*
|
||||
@@ -1,14 +1,16 @@
|
||||
Source: https://github.com/GTNewHorizons/GTNHMixins/tree/2.1.12
|
||||
Source: https://github.com/GTNewHorizons/GTNHMixins/tree/2.1.13
|
||||
|
||||
Classes used:
|
||||
|
||||
com.gtnewhorizon.gtnhmixins.*
|
||||
|
||||
Modifications:
|
||||
- removed Mixin environment initialization in GTNHMixinsCore
|
||||
- added Mixin 0.7 support
|
||||
- made MixinExtras initialization get suppressed if Mixin version is below 0.8.5
|
||||
- made reflection support Mixin 0.7.11
|
||||
- added call to "unimixins.mixinModidDecorator.refresh" after loading early mixins in GTNHMixinsCore and late mixins in LateMixinOrchestrationMixin
|
||||
- Removed Mixin environment initialization in GTNHMixinsCore
|
||||
- Added Mixin 0.7 support
|
||||
- Made reflection support Mixin 0.7.11
|
||||
- Added call to "unimixins.mixinModidDecorator.refresh" after loading early mixins in GTNHMixinsCore and late mixins in LateMixinOrchestrationMixin
|
||||
- Made delegated transformer list get set to null before loading late mixins
|
||||
- Added 1.8+ @Mod and @IFMLPlugin annotations
|
||||
- Removed MixinExtras
|
||||
|
||||
License: LGPL3 (see LICENSE)
|
||||
@@ -1,24 +1,47 @@
|
||||
def mixinExtrasVersion = "0.1.1"
|
||||
|
||||
configurations.create("shadowMixinExtras")
|
||||
|
||||
dependencies {
|
||||
compileOnly('org.spongepowered:mixin:0.8.5')
|
||||
compileOnly('com.github.LlamaLad7:MixinExtras:0.1.1')
|
||||
shadow('com.github.LlamaLad7:MixinExtras:0.1.1')
|
||||
compileOnly('org.spongepowered:mixin:0.8.7')
|
||||
shadow(project(":module-common")) {
|
||||
transitive = false
|
||||
}
|
||||
compileOnly(project(":module-mixingasm")) {
|
||||
transitive = false
|
||||
}
|
||||
compileOnly("com.github.LlamaLad7:MixinExtras:$mixinExtrasVersion")
|
||||
shadowMixinExtras("com.github.LlamaLad7:MixinExtras:$mixinExtrasVersion")
|
||||
}
|
||||
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-gtnhmixins-1.7.10")
|
||||
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
task mixinExtrasJar(type: ShadowJar) {
|
||||
destinationDirectory = file("build/tmp")
|
||||
archiveClassifier.set("mixinExtras")
|
||||
archiveVersion = mixinExtrasVersion
|
||||
configurations = [project.configurations.shadowMixinExtras]
|
||||
relocate 'com.llamalad7.mixinextras', 'com.gtnewhorizon.mixinextras'
|
||||
relocate 'org.objectweb.asm', 'org.spongepowered.asm.lib'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
classifier = ''
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
relocate 'com.llamalad7.mixinextras', 'com.gtnewhorizon.mixinextras'
|
||||
relocate 'org.objectweb.asm', 'org.spongepowered.asm.lib'
|
||||
relocate 'io.github.legacymoddingmc.unimixins.common', 'io.github.legacymoddingmc.unimixins.gtnhmixins.repackage.common'
|
||||
|
||||
from(zipTree(tasks.mixinExtrasJar.archiveFile)) {
|
||||
eachFile({
|
||||
setPath("data/legacy_gtnh_mixinextras/" + getPath().replaceAll("\\.class", ".klass"))
|
||||
})
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes (
|
||||
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
@@ -35,8 +58,12 @@ jar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
shadowJar.dependsOn mixinExtrasJar
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.extraVersion = "2.1.9"
|
||||
ext.extraModid = "gtnhmixins"
|
||||
ext.mcversion = "1.7.10"
|
||||
version += "+" + ext.extraVersion
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
extraVersion=2.2.0
|
||||
@@ -5,9 +5,10 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@Mod(modid = GTNHMixins.MODID, version = GTNHMixins.VERSION, name = GTNHMixins.NAME, acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = GTNHMixins.MODID, version = GTNHMixins.VERSION, name = GTNHMixins.NAME, acceptableRemoteVersions = "*")
|
||||
public class GTNHMixins {
|
||||
public static final String NAME = "GTNHMixins";
|
||||
public static final String MODID = "gtnhmixins";
|
||||
public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
public static final Logger LOGGER = LogManager.getLogger(NAME);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,27 @@
|
||||
package com.gtnewhorizon.gtnhmixins;
|
||||
|
||||
import io.github.legacymoddingmc.unimixins.common.abstraction.ComparableVersion;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.transformer.Config;
|
||||
import org.spongepowered.asm.mixin.transformer.ext.Extensions;
|
||||
import org.spongepowered.asm.service.MixinService;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Reflection {
|
||||
/* Reflection Fun */
|
||||
public static final Class<?> pluginWrapperClass, mixinsClass, configClass, mixinConfigClass, mixinTransformerClass, mixinProcessorClass;
|
||||
public static final Field coreModInstanceField, configField, mixinClassesField, processorField, extensionsField;
|
||||
public static final Class<?> pluginWrapperClass, mixinsClass, configClass, mixinConfigClass, mixinTransformerClass, mixinProcessorClass, mixinServiceLaunchWrapperClass, mixinEnvironmentClass;
|
||||
public static final Field coreModInstanceField, configField, mixinClassesField, processorField, extensionsField, delegatedTransformersField;
|
||||
public static final Method registerConfigurationMethod, selectConfigsMethod, prepareConfigsMethod;
|
||||
|
||||
private static final boolean mixin_0_7;
|
||||
|
||||
static {
|
||||
try {
|
||||
mixin_0_7 = new ComparableVersion((String)Launch.blackboard.get("mixin.initialised")).compareTo(new ComparableVersion("0.8")) < 0;
|
||||
|
||||
/* We're referencing classes here in FML or SpongePowered Mixins, these _should_ be safe to call early */
|
||||
|
||||
/* PluginWrapper */
|
||||
@@ -30,15 +37,17 @@ public class Reflection {
|
||||
|
||||
/* MixinTransformer */
|
||||
mixinTransformerClass = Class.forName("org.spongepowered.asm.mixin.transformer.MixinTransformer");
|
||||
Field processor = null;
|
||||
try {
|
||||
processor = mixinTransformerClass.getDeclaredField("processor");
|
||||
processor.setAccessible(true);
|
||||
} catch(NoSuchFieldException e){}
|
||||
processorField = processor;
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
processorField = mixinTransformerClass.getDeclaredField("processor");
|
||||
processorField.setAccessible(true);
|
||||
} else {
|
||||
// 0.7.11
|
||||
processorField = null;
|
||||
}
|
||||
|
||||
/* MixinProcessor */
|
||||
if(processorField != null) {
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
mixinProcessorClass = Class.forName("org.spongepowered.asm.mixin.transformer.MixinProcessor");
|
||||
selectConfigsMethod = mixinProcessorClass.getDeclaredMethod("selectConfigs", MixinEnvironment.class);
|
||||
@@ -63,6 +72,20 @@ public class Reflection {
|
||||
extensionsField.setAccessible(true);
|
||||
}
|
||||
|
||||
/* MixinEnvironment / MixinServiceLaunchWrapper */
|
||||
mixinServiceLaunchWrapperClass = Class.forName("org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper");
|
||||
mixinEnvironmentClass = Class.forName("org.spongepowered.asm.mixin.MixinEnvironment");
|
||||
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
delegatedTransformersField = mixinServiceLaunchWrapperClass.getDeclaredField("delegatedTransformers");
|
||||
delegatedTransformersField.setAccessible(true);
|
||||
} else {
|
||||
// 0.7.11
|
||||
delegatedTransformersField = mixinEnvironmentClass.getDeclaredField("transformers");
|
||||
delegatedTransformersField.setAccessible(true);
|
||||
}
|
||||
|
||||
/* Config */
|
||||
configClass = Class.forName("org.spongepowered.asm.mixin.transformer.Config");
|
||||
configField = configClass.getDeclaredField("config");
|
||||
@@ -80,7 +103,7 @@ public class Reflection {
|
||||
|
||||
public static void invokeSelectConfigs(Object transformer, MixinEnvironment env) {
|
||||
try {
|
||||
if(processorField != null) {
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
Object processor = Reflection.processorField.get(transformer);
|
||||
|
||||
@@ -97,7 +120,7 @@ public class Reflection {
|
||||
|
||||
public static void invokePrepareConfigs(Object transformer, MixinEnvironment env) {
|
||||
try {
|
||||
if(processorField != null) {
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
Object processor = Reflection.processorField.get(transformer);
|
||||
|
||||
@@ -111,4 +134,18 @@ public class Reflection {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDelegatedTransformersField(Object newValue) {
|
||||
try {
|
||||
if(!mixin_0_7) {
|
||||
// 0.8.5
|
||||
delegatedTransformersField.set(MixinService.getService(), newValue);
|
||||
} else {
|
||||
// 0.7.11
|
||||
delegatedTransformersField.set(MixinEnvironment.getCurrentEnvironment(), newValue);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.util.concurrent.Runnables;
|
||||
import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.Reflection;
|
||||
import com.llamalad7.mixinextras.MixinExtrasBootstrap;
|
||||
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
@@ -24,6 +23,9 @@ import java.util.Set;
|
||||
@IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@IFMLLoadingPlugin.Name(GTNHMixinsCore.PLUGIN_NAME)
|
||||
@IFMLLoadingPlugin.TransformerExclusions("com.gtnewhorizon.gtnhmixins.core")
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name(GTNHMixinsCore.PLUGIN_NAME)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions("com.gtnewhorizon.gtnhmixins.core")
|
||||
public class GTNHMixinsCore implements IFMLLoadingPlugin {
|
||||
public static final String PLUGIN_NAME = "GTNHMixins Core Plugin";
|
||||
public static final Logger LOGGER = LogManager.getLogger(PLUGIN_NAME);
|
||||
@@ -42,9 +44,6 @@ public class GTNHMixinsCore implements IFMLLoadingPlugin {
|
||||
LOGGER.info("Initializing GTNHMixins Core");
|
||||
|
||||
GTNHMixinsModule.init();
|
||||
if(GTNHMixinsModule.isMixinExtrasEnabled()) {
|
||||
MixinExtrasBootstrap.init();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,13 +93,13 @@ public class GTNHMixinsCore implements IFMLLoadingPlugin {
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
LOGGER.info("Examining core mod list");
|
||||
LOGGER.debug("Examining core mod list");
|
||||
final Object coremodList = data.get("coremodList");
|
||||
|
||||
|
||||
if (coremodList instanceof List) {
|
||||
final Set<String> loadedCoremods = getLoadedCoremods((List<?>) coremodList);
|
||||
|
||||
LOGGER.info("LoadedCoreMods {}", loadedCoremods.toString());
|
||||
LOGGER.debug("LoadedCoreMods {}", loadedCoremods.toString());
|
||||
for (Object coremod : (List<?>)coremodList) {
|
||||
// Identify any coremods that are `IEarlyMixinLoader`, and inject any relevant mixins
|
||||
try {
|
||||
@@ -108,10 +107,10 @@ public class GTNHMixinsCore implements IFMLLoadingPlugin {
|
||||
if (theMod instanceof IEarlyMixinLoader) {
|
||||
final IEarlyMixinLoader loader = (IEarlyMixinLoader)theMod;
|
||||
final String mixinConfig = loader.getMixinConfig();
|
||||
final Config config = Config.create(mixinConfig);
|
||||
final Config config = Config.create(mixinConfig, null);
|
||||
final List<String> mixins = loader.getMixins(loadedCoremods);
|
||||
for(String mixin : mixins) {
|
||||
LOGGER.info("Loading [{}] {}", mixinConfig, mixin);
|
||||
LOGGER.debug("Loading [{}] {}", mixinConfig, mixin);
|
||||
}
|
||||
Reflection.mixinClassesField.set(Reflection.configField.get(config), mixins);
|
||||
Reflection.registerConfigurationMethod.invoke(null, config);
|
||||
|
||||
+50
-16
@@ -5,13 +5,16 @@ import com.gtnewhorizon.gtnhmixins.GTNHMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.ILateMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.LateMixin;
|
||||
import com.gtnewhorizon.gtnhmixins.Reflection;
|
||||
import com.gtnewhorizon.gtnhmixins.core.GTNHMixinsCore;
|
||||
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderState;
|
||||
import cpw.mods.fml.common.ModClassLoader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -21,22 +24,23 @@ import org.spongepowered.asm.mixin.transformer.Config;
|
||||
import org.spongepowered.asm.mixin.transformer.Proxy;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@Mixin(value = FMLConstructionEvent.class, remap = false)
|
||||
@Mixin(value = LoadController.class, remap = false)
|
||||
public class LateMixinOrchestrationMixin {
|
||||
private static boolean finished=false;
|
||||
|
||||
@Inject(method = "<init>", at = @At(value = "RETURN"))
|
||||
private void beforeConstructing(Object[] eventData, CallbackInfo ci) throws Throwable {
|
||||
// We would normally target something in LoadController, but FastCraft causes that class to be loaded too early to mixin,
|
||||
// so we instead hijack the very first FMLConstructionEvent that's constructed and run the logic there.
|
||||
if (finished)
|
||||
@Inject(method = "distributeStateMessage(Lcpw/mods/fml/common/LoaderState;[Ljava/lang/Object;)V", at = @At(value = "HEAD"))
|
||||
private void beforeConstructing(LoaderState state, Object[] eventData, CallbackInfo ci) throws Throwable {
|
||||
// This state is where Forge adds mod files to ModClassLoader
|
||||
if (state != LoaderState.CONSTRUCTING) {
|
||||
return;
|
||||
|
||||
finished = true;
|
||||
}
|
||||
|
||||
GTNHMixins.LOGGER.info("Instantiating all @LateMixin annotated and ILateMixinLoader implemented classes...");
|
||||
|
||||
@@ -45,8 +49,11 @@ public class LateMixinOrchestrationMixin {
|
||||
ASMDataTable asmDataTable = (ASMDataTable)eventData[1];
|
||||
final Loader loader = Loader.instance();
|
||||
|
||||
final Set<String> loadedMods = loader.getIndexedModList().keySet();
|
||||
GTNHMixinsCore.LOGGER.info("LoadedMods {}", loadedMods.toString());
|
||||
final Set<String> loadedModsTemp = new HashSet<>();
|
||||
loadedModsTemp.addAll(loader.getIndexedModList().keySet());
|
||||
loadedModsTemp.addAll(getLiteLoaderMods());
|
||||
final Set<String> loadedMods = Collections.unmodifiableSet(loadedModsTemp);
|
||||
GTNHMixins.LOGGER.info("LoadedMods {}", loadedMods.toString());
|
||||
|
||||
for (ASMDataTable.ASMData asmData : asmDataTable.getAll(LateMixin.class.getName())) {
|
||||
modClassLoader.addFile(asmData.getCandidate().getModContainer()); // Add to path before `newInstance`
|
||||
@@ -61,7 +68,7 @@ public class LateMixinOrchestrationMixin {
|
||||
final String mixinConfig = lateLoader.getMixinConfig();
|
||||
GTNHMixins.LOGGER.info("Adding {} mixin configuration.", mixinConfig);
|
||||
|
||||
final Config config = Config.create(mixinConfig);
|
||||
final Config config = Config.create(mixinConfig, null);
|
||||
final List<String> mixins = lateLoader.getMixins(loadedMods);
|
||||
for(String mixin : mixins) {
|
||||
GTNHMixins.LOGGER.info("Loading [{}] {}", mixinConfig, mixin);
|
||||
@@ -78,6 +85,9 @@ public class LateMixinOrchestrationMixin {
|
||||
modClassLoader.addFile(container.getSource());
|
||||
}
|
||||
|
||||
// Force rebuild of the transformer list
|
||||
Reflection.setDelegatedTransformersField(null);
|
||||
|
||||
Field transformerField = Proxy.class.getDeclaredField("transformer");
|
||||
transformerField.setAccessible(true);
|
||||
|
||||
@@ -88,4 +98,28 @@ public class LateMixinOrchestrationMixin {
|
||||
Reflection.invokeSelectConfigs(transformer, env);
|
||||
Reflection.invokePrepareConfigs(transformer, env);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> getLiteLoaderMods() {
|
||||
Set<String> mods = new HashSet<>();
|
||||
try {
|
||||
Class<?> LiteLoaderTweaker = Class.forName("com.mumfrey.liteloader.launch.LiteLoaderTweaker");
|
||||
Method hasValidMetaData = Class.forName("com.mumfrey.liteloader.interfaces.LoadableMod").getMethod("hasValidMetaData");
|
||||
Object instance = FieldUtils.readDeclaredStaticField(LiteLoaderTweaker, "instance", true);
|
||||
Object bootstrap = FieldUtils.readDeclaredField(instance, "bootstrap", true);
|
||||
Object enumerator = FieldUtils.readDeclaredField(bootstrap, "enumerator", true);
|
||||
Map<String, ?> enabledContainers = (Map<String, ?>) FieldUtils.readDeclaredField(enumerator, "enabledContainers", true);
|
||||
GTNHMixins.LOGGER.info("LiteLoader present, adding its mods to the list.");
|
||||
for(Entry<String, ?> e : enabledContainers.entrySet()) {
|
||||
if((boolean) hasValidMetaData.invoke(e.getValue())) {
|
||||
mods.add(e.getKey());
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
GTNHMixins.LOGGER.info("LiteLoader not present.");
|
||||
} catch (Exception e) {
|
||||
GTNHMixins.LOGGER.error("Failed to get LiteLoader mods.", e);
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins;
|
||||
|
||||
import io.github.legacymoddingmc.unimixins.common.config.AnnotatedProperties;
|
||||
|
||||
public class GTNHMixinsConfig {
|
||||
@AnnotatedProperties.ConfigString(def = "true", com = "Provide the deprecated `com.gtnewhorizons.mixinextras` relocation of MixinExtras 0.1.1. May be required by some older mods.", cat = "gtnhmixins")
|
||||
public static boolean enableLegacyGTNHMixinExtrasPackage;
|
||||
}
|
||||
+19
-13
@@ -4,7 +4,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ComparableVersion;
|
||||
import io.github.legacymoddingmc.unimixins.common.abstraction.ComparableVersion;
|
||||
import io.github.legacymoddingmc.unimixins.common.config.ConfigUtil;
|
||||
import io.github.legacymoddingmc.unimixins.common.sanitycheck.SanityCheckHelper;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -12,17 +13,30 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class GTNHMixinsModule {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("unimixin-gtnhmixins");
|
||||
public static final Logger LOGGER = LogManager.getLogger("unimixins-gtnhmixins");
|
||||
|
||||
public static void init() {
|
||||
if(SanityCheckHelper.isEnabled()) {
|
||||
SanityCheckHelper.warnIfJarPrefixesExist(Arrays.asList("gasstation-", "mixinbooterlegacy-", "spongemixins-"));
|
||||
checkComponentIntegrity();
|
||||
}
|
||||
registerASMRemapPackage("com.gtnewhorizon.mixinextras");
|
||||
|
||||
ConfigUtil.load(GTNHMixinsConfig.class);
|
||||
|
||||
if(isLegacyGTNHMixinExtrasEnabled()) {
|
||||
Launch.classLoader.registerTransformer("io.github.legacymoddingmc.unimixins.gtnhmixins.asm.LegacyGTNHMixinExtrasGenerator");
|
||||
try {
|
||||
Class.forName("com.gtnewhorizon.mixinextras.MixinExtrasBootstrap").getMethod("init").invoke(null);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to initialize MixinExtrasBootstrap");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMixinExtrasEnabled() {
|
||||
|
||||
public static boolean isLegacyGTNHMixinExtrasEnabled() {
|
||||
if(!GTNHMixinsConfig.enableLegacyGTNHMixinExtrasPackage) return false;
|
||||
|
||||
String requiredVersion = "0.8.5";
|
||||
String mixinVersion = (String)Launch.blackboard.get("mixin.initialised");
|
||||
if(mixinVersion != null && new ComparableVersion(mixinVersion).compareTo(new ComparableVersion(requiredVersion)) >= 0) {
|
||||
@@ -36,14 +50,6 @@ public class GTNHMixinsModule {
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerASMRemapPackage(String pkg) {
|
||||
try {
|
||||
Class.forName("io.github.legacymoddingmc.unimixins.compat.asm.ASMRemapperTransformer").getMethod("registerPackage", String.class).invoke(null, pkg);
|
||||
} catch(Exception e) {
|
||||
LOGGER.warn("Failed to register package " + pkg + " for ASM remapping, probably because the compat module is missing. " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkComponentIntegrity() {
|
||||
List<String> missingComponents = new ArrayList<>();
|
||||
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins.asm;
|
||||
|
||||
import static io.github.legacymoddingmc.unimixins.gtnhmixins.GTNHMixinsModule.LOGGER;
|
||||
|
||||
import io.github.legacymoddingmc.unimixins.gtnhmixins.util.LaunchClassLoaderUtils;
|
||||
import makamys.mixingasm.api.MixinSafeTransformer;
|
||||
import makamys.mixingasm.api.TransformerInclusions;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@MixinSafeTransformer
|
||||
public class LegacyGTNHMixinExtrasGenerator implements IClassTransformer {
|
||||
static {
|
||||
if(LegacyGTNHMixinExtrasGenerator.class.getResource("/makamys/mixingasm/api/TransformerInclusions.class") != null
|
||||
&& LegacyGTNHMixinExtrasGenerator.class.getResource("/makamys/mixingasm/api/MixinSafeTransformer.class") == null) {
|
||||
// Mixingasm < 0.3 compat
|
||||
TransformerInclusions.getTransformerInclusionList().add("io.github.legacymoddingmc.unimixins.compat.asm.LegacyGTNHMixinExtrasGenerator");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if(basicClass == null && name.startsWith("com.gtnewhorizon.mixinextras") && !name.startsWith("org.apache.commons.io.")) {
|
||||
try {
|
||||
LOGGER.trace("Generating class " + name);
|
||||
byte[] bytes = getClassBytes(name);
|
||||
|
||||
if(bytes != null) {
|
||||
// If NEI is on the class path before CCL (which would cause the game to crash immediately in
|
||||
// production, but is possible in a dev env), ClassHeirachyTransformer will try to call getClassBytes,
|
||||
// and if it fails, it will call Class.forName for the class being loaded, causing a
|
||||
// ClassCircularityError.
|
||||
// So we need to populate the cache to avoid that from happening.
|
||||
LaunchClassLoaderUtils.putInResourceCache(name, bytes);
|
||||
return bytes;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to generate class " + name);
|
||||
}
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
private byte[] getClassBytes(String name) throws IOException {
|
||||
final String resourcePath = "/data/legacy_gtnh_mixinextras/" + name.replace('.', '/').concat(".klass");
|
||||
return IOUtils.toByteArray(LegacyGTNHMixinExtrasGenerator.class.getResourceAsStream(resourcePath));
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins.util;
|
||||
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LaunchClassLoaderUtils {
|
||||
private static Map<String,byte[]> resourceCache;
|
||||
private static Set<String> negativeResourceCache;
|
||||
|
||||
static {
|
||||
try {
|
||||
Field resourceCacheField = LaunchClassLoader.class.getDeclaredField("resourceCache");
|
||||
resourceCacheField.setAccessible(true);
|
||||
resourceCache = (Map<String, byte[]>) resourceCacheField.get(Launch.classLoader);
|
||||
|
||||
Field negativeResourceCacheField = LaunchClassLoader.class.getDeclaredField("negativeResourceCache");
|
||||
negativeResourceCacheField.setAccessible(true);
|
||||
negativeResourceCache = (Set<String>) negativeResourceCacheField.get(Launch.classLoader);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Use with care, ArchaicFix weakens the resource cache once it receives the LoadComplete event, making
|
||||
* this method cease to function! But it's fine for our purposes since all mixins load before that.
|
||||
* It's either this or reflecting every time. */
|
||||
public static void putInResourceCache(String key, byte[] value) {
|
||||
resourceCache.put(key, value);
|
||||
negativeResourceCache.remove(key);
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
com.gtnewhorizon.mixinextras.MixinExtrasAP
|
||||
@@ -2,7 +2,7 @@
|
||||
"required": true,
|
||||
"minVersion": "0.8.3-GTNH",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"target": "@env(DEFAULT)",
|
||||
"target": "@env(PREINIT)",
|
||||
"package": "com.gtnewhorizon.gtnhmixins.mixins",
|
||||
"refmap": "mixins.gtnhmixins.refmap.json",
|
||||
"injectors": {
|
||||
@@ -11,4 +11,4 @@
|
||||
"mixins": [
|
||||
"LateMixinOrchestrationMixin"
|
||||
]
|
||||
}
|
||||
}
|
||||
+20
-20
@@ -15,7 +15,7 @@ archivesBaseName = archivesBaseName.replace("-1.7.10", "-mixin-1.7.10")
|
||||
configurations.archives.artifacts.clear()
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.spongepowered:mixin:0.8.5")
|
||||
compileOnly("org.spongepowered:mixin:$spongepoweredMixinVersion")
|
||||
compileOnly(project(":module-common")) {
|
||||
transitive = false
|
||||
}
|
||||
@@ -23,7 +23,7 @@ dependencies {
|
||||
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
|
||||
def flavors = (project.hasProperty("noAltMixin") ? [] : ["spongepowered", "fabric", "gasmix", "gtnh"]) + ["unimix"]
|
||||
def flavors = (!project.hasProperty("enableAltMixin") ? [] : ["spongepowered", "fabric", "gasmix", "gtnh"]) + ["unimix"]
|
||||
|
||||
flavors.each {
|
||||
def mixinFlavor = it
|
||||
@@ -45,13 +45,11 @@ flavors.each {
|
||||
if (mixinFlavor == "fabric" || mixinFlavor == "spongepowered" || mixinFlavor == "unimix" || mixinFlavor == "gtnh") {
|
||||
// Fabric / SpongePowered / UniMix / GTNH
|
||||
|
||||
def asmVersion = "9.5"
|
||||
|
||||
if (mixinFlavor == "fabric" || mixinFlavor == "unimix") {
|
||||
def uniLocal = mixinFlavor == "unimix" && project.hasProperty("local")
|
||||
def uniJitpack = mixinFlavor == "unimix" && !uniLocal
|
||||
|
||||
mixinVersion = mixinFlavor == "fabric" ? "0.12.5+mixin.0.8.5" : "0.12.2+mixin.0.8.5"
|
||||
mixinVersion = mixinFlavor == "fabric" ? fabricMixinVersion : unimixMixinVersion
|
||||
if (uniLocal) {
|
||||
mixinVersion += "-local"
|
||||
}
|
||||
@@ -85,7 +83,7 @@ flavors.each {
|
||||
})
|
||||
}
|
||||
} else if(mixinFlavor == "spongepowered") {
|
||||
mixinVersion = "0.8.5"
|
||||
mixinVersion = spongepoweredMixinVersion
|
||||
|
||||
mixinFlavorClassifier = "spongepowered.$mixinVersion"
|
||||
|
||||
@@ -105,7 +103,7 @@ flavors.each {
|
||||
} else if(mixinFlavor == "gtnh") {
|
||||
// Adapted from GTNHMixins's build script
|
||||
|
||||
mixinVersion = "0.8.5-GTNH-2"
|
||||
mixinVersion = gtnhMixinVersion
|
||||
mixinFlavorClassifier = "gtnh.$mixinVersion"
|
||||
|
||||
dependencies {
|
||||
@@ -114,8 +112,8 @@ flavors.each {
|
||||
add("shadow$_flavor", "org.ow2.asm:asm-commons:$asmVersion")
|
||||
add("shadow$_flavor", "org.ow2.asm:asm-util:$asmVersion")
|
||||
add("shadow$_flavor", "com.google.guava:guava:21.0")
|
||||
add("shadowBridge$_flavor", 'org.spongepowered:mixin:0.8.5')
|
||||
add("shadowSources$_flavor", 'org.spongepowered:mixin:0.8.5:sources')
|
||||
add("shadowBridge$_flavor", "org.spongepowered:mixin:$spongepoweredMixinVersion")
|
||||
add("shadowSources$_flavor", "org.spongepowered:mixin:$spongepoweredMixinVersion:sources")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -204,7 +202,7 @@ flavors.each {
|
||||
} else if (mixinFlavor == "gasmix") {
|
||||
// GasMix
|
||||
|
||||
mixinVersion = "0.8.5-gasstation_7"
|
||||
mixinVersion = gasmixMixinVersion
|
||||
|
||||
mixinFlavorClassifier = "gasmix.$mixinVersion"
|
||||
|
||||
@@ -235,7 +233,7 @@ flavors.each {
|
||||
from 'src/main/resources/mcmod.info'
|
||||
into "build/tmp/mcmod.${mixinFlavor}.info"
|
||||
filter {
|
||||
line -> line.replaceAll('@MIXIN_CLASSIFIER@', mixinFlavorClassifier).replaceAll('@MIXIN_SOURCE_CAPITALIZED@', mixinFlavorCapitalized).replaceAll('@VERSION@', "$versionBase+$mixinFlavorClassifier")
|
||||
line -> line.replaceAll('@MIXIN_CLASSIFIER@', mixinFlavorClassifier).replaceAll('@MIXIN_SOURCE_CAPITALIZED@', mixinFlavorCapitalized).replaceAll('@VERSION@', "$versionBase+$mixinFlavorClassifier").replaceAll('@PROJECT_URL@', project.project_url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,21 +265,23 @@ flavors.each {
|
||||
}
|
||||
|
||||
jar.dependsOn("shadowSourcesJar$_flavor")
|
||||
|
||||
if(publishModuleToMaven){
|
||||
publishing {
|
||||
publications {
|
||||
create("maven$_flavor", MavenPublication) {
|
||||
artifact tasks."shadowJar$_flavor"
|
||||
artifact tasks."shadowSourcesJar$_flavor"
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create("maven$_flavor", MavenPublication) {
|
||||
artifact tasks."shadowJar$_flavor"
|
||||
artifact tasks."shadowSourcesJar$_flavor"
|
||||
|
||||
artifactId = archivesBaseName
|
||||
version = tasks."shadowJar$_flavor".version
|
||||
artifactId = archivesBaseName.substring(1).replace("-1.7.10", mavenIdSuffix) + (mixinFlavor == "unimix" ? "" : "-" + mixinFlavor)
|
||||
groupId = mavenGroupId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Obfuscation is useless because we're not compiling code referencing Minecraft classes
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
jar.enabled = false
|
||||
@@ -0,0 +1,7 @@
|
||||
fabricMixinVersion=0.15.3+mixin.0.8.7
|
||||
unimixMixinVersion=0.15.4+mixin.0.8.7
|
||||
spongepoweredMixinVersion=0.8.7
|
||||
gtnhMixinVersion=0.8.7-GTNH-2
|
||||
gasmixMixinVersion=0.8.7-gasstation_7
|
||||
|
||||
asmVersion=9.8
|
||||
+2
-1
@@ -6,5 +6,6 @@ import cpw.mods.fml.common.Mod;
|
||||
* An empty mod class provided to make it impossible to load multiple editions
|
||||
* of the module at the same time.
|
||||
*/
|
||||
@Mod(modid = "unimixins-mixin", version = "@VERSION@")
|
||||
@Mod(modid = "unimixins-mixin", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "unimixins-mixin", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class MixinModule {}
|
||||
+1
-1
@@ -28,7 +28,7 @@ public class MixinSanityCheck {
|
||||
boolean isSuspectedToBeDueToNaming =
|
||||
mixinCoreJarName != null && mixinTweakerJarName != null
|
||||
&& mixinCoreJarName.compareToIgnoreCase(mixinTweakerJarName) > 0;
|
||||
return Arrays.asList("A different version of Mixin (the one inside " + stringOr(mixinTweakerJarName, "unknown") + ") is getting loaded instead of UniMixins's one (inside " + stringOr(mixinCoreJarName, "unknown") + ")!" + (isSuspectedToBeDueToNaming ? " This is probably because because UniMixins's jar name comes later alphabetically. Try renaming it to come first (for example, by adding a '!' character at the beginning of the file name.)" : ""));
|
||||
return Arrays.asList("A different version of Mixin (the one inside " + stringOr(mixinTweakerJarName, "unknown") + ") is getting loaded instead of UniMixins's one (inside " + stringOr(mixinCoreJarName, "unknown") + ")!" + (isSuspectedToBeDueToNaming ? " This is probably because because UniMixins's jar name comes later alphabetically. Try renaming it to come first (for example, by adding a '!' character at the beginning of the file name)." : ""));
|
||||
}
|
||||
return Arrays.asList();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": "UniMixins module that provides the @MIXIN_SOURCE_CAPITALIZED@ fork of Mixin (version: @MIXIN_CLASSIFIER@).",
|
||||
"version": "@VERSION@",
|
||||
"mcversion": "1.7.10",
|
||||
"url": "${project_url}",
|
||||
"url": "@PROJECT_URL@",
|
||||
"updateUrl": "",
|
||||
"authorList": ["makamys"],
|
||||
"credits": "",
|
||||
|
||||
@@ -9,5 +9,7 @@ Modifications:
|
||||
- Changed shaded ASM package name to legacy one
|
||||
- Changed mixin config to use PREINIT phase
|
||||
- Added call to "unimixins.mixinModidDecorator.refresh" after loading early mixins in MixinBooterLegacyPlugin and late mixins in LoadControllerMixin
|
||||
- Added 1.8+ @Mod and @IFMLPlugin annotations
|
||||
- Set acceptableRemoteVersions = "*" in @Mod annotation
|
||||
|
||||
License: LGPL 2.1 (see LICENSE)
|
||||
@@ -20,6 +20,9 @@ archivesBaseName = archivesBaseName.replace("-1.7.10", "-mixinbooterlegacy-1.7.1
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
|
||||
shadowJar {
|
||||
classifier = ''
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
relocate 'io.github.legacymoddingmc.unimixins.common', 'io.github.legacymoddingmc.unimixins.mixinbooterlegacy.repackage.common'
|
||||
|
||||
manifest {
|
||||
@@ -32,8 +35,15 @@ shadowJar {
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
dependsOn shadowJar
|
||||
enabled = false
|
||||
}
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.extraVersion = "1.2.1"
|
||||
ext.mcversion = "1.7.10"
|
||||
version += "+" + extraVersion
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
extraVersion=1.2.1
|
||||
+4
-1
@@ -20,6 +20,8 @@ import java.util.Map;
|
||||
@Name("MixinBooterLegacy")
|
||||
@MCVersion("1.7.10")
|
||||
@SortingIndex(Integer.MIN_VALUE + 1)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name("MixinBooterLegacy")
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 1)
|
||||
public final class MixinBooterLegacyPlugin implements IFMLLoadingPlugin {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger("MixinBooter");
|
||||
@@ -81,7 +83,8 @@ public final class MixinBooterLegacyPlugin implements IFMLLoadingPlugin {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Mod(modid = "mixinbooterlegacy", name = "MixinBooterLegacy", version = "@VERSION@")
|
||||
@Mod(modid = "mixinbooterlegacy", name = "MixinBooterLegacy", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "mixinbooterlegacy", name = "MixinBooterLegacy", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public static class Container {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
configurations {
|
||||
shadowBridge
|
||||
shadowSources
|
||||
}
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.extraVersion = "0.2.0-beta.8"
|
||||
ext.extraVersion = mixinExtrasVersion
|
||||
|
||||
dependencies {
|
||||
shadow("com.github.llamalad7.mixinextras:mixinextras-common:$extraVersion")
|
||||
shadow("io.github.llamalad7:mixinextras-common:$extraVersion")
|
||||
shadowSources("io.github.llamalad7:mixinextras-common:$extraVersion:sources")
|
||||
}
|
||||
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-mixinextras-1.7.10")
|
||||
@@ -30,7 +33,22 @@ shadowJar {
|
||||
}
|
||||
}
|
||||
|
||||
task("shadowSources", type: ShadowJar) {
|
||||
from sourceSets.main.allSource
|
||||
classifier = "sources"
|
||||
configurations = [project.configurations."shadowSources"]
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
enabled = false
|
||||
dependsOn shadowSources
|
||||
}
|
||||
|
||||
jar {
|
||||
enabled = false
|
||||
dependsOn shadowJar
|
||||
}
|
||||
|
||||
// ForgeGradle's reobfuscator breaks classes containing CONSTANT_InterfaceMethodRefs, which MixinExtras happens to contain
|
||||
// Also obfuscation is unnecessary anyway since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
@@ -0,0 +1 @@
|
||||
mixinExtrasVersion=0.4.1
|
||||
+2
-1
@@ -5,7 +5,8 @@ import cpw.mods.fml.common.Mod;
|
||||
/**
|
||||
* This is only here to help Forge detect the mod.
|
||||
*/
|
||||
@Mod(modid = "mixinextras", version = "@VERSION@")
|
||||
@Mod(modid = "mixinextras", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "mixinextras", version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class MixinExtrasModule {
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 LlamaLad7
|
||||
|
||||
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.
|
||||
@@ -5,6 +5,8 @@ Classes used:
|
||||
*
|
||||
|
||||
Modifications:
|
||||
- removed update check in MixingasmMod
|
||||
- Removed update check in MixingasmMod
|
||||
- Made new addTransformerExclusion method get called in Mixin 0.8.5+
|
||||
- Added 1.8+ @Mod and @IFMLPlugin annotations
|
||||
|
||||
License: Unlicense (see LICENSE)
|
||||
@@ -11,6 +11,9 @@ archivesBaseName = archivesBaseName.replace("-1.7.10", "-mixingasm-1.7.10")
|
||||
apply plugin: "com.github.johnrengelman.shadow"
|
||||
|
||||
shadowJar {
|
||||
classifier = ''
|
||||
configurations = [project.configurations.shadow]
|
||||
|
||||
relocate 'io.github.legacymoddingmc.unimixins.common', 'io.github.legacymoddingmc.unimixins.mixingasm.repackage.common'
|
||||
|
||||
manifest {
|
||||
@@ -24,8 +27,15 @@ shadowJar {
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
dependsOn shadowJar
|
||||
enabled = false
|
||||
}
|
||||
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.extraVersion = "0.2.2"
|
||||
version += "+" + ext.extraVersion
|
||||
|
||||
minecraft {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
extraVersion=0.3
|
||||
@@ -9,8 +9,9 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ComparableVersion;
|
||||
import io.github.legacymoddingmc.unimixins.common.abstraction.ComparableVersion;
|
||||
import io.github.legacymoddingmc.unimixins.mixingasm.MixingasmModule;
|
||||
import makamys.mixingasm.api.MixinSafeTransformer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -75,7 +76,9 @@ public class Mixingasm {
|
||||
for(IClassTransformer trans : Launch.classLoader.getTransformers()) {
|
||||
String name = trans.getClass().getCanonicalName();
|
||||
boolean included = false;
|
||||
if((included = (transformerInclusionPatterns.stream().anyMatch(p -> patternMatches(name, p)) || trans instanceof IMixinSafeTransformer))
|
||||
if((included = (transformerInclusionPatterns.stream().anyMatch(p -> patternMatches(name, p))
|
||||
|| trans instanceof IMixinSafeTransformer
|
||||
|| trans.getClass().isAnnotationPresent(MixinSafeTransformer.class)))
|
||||
&& transformerExclusionPatterns.stream().noneMatch(p -> patternMatches(name, p))) {
|
||||
LOGGER.debug(" Trusting transformer " + name);
|
||||
} else {
|
||||
@@ -85,7 +88,7 @@ public class Mixingasm {
|
||||
}
|
||||
return badTransformers;
|
||||
}
|
||||
|
||||
|
||||
private static boolean patternMatches(String str, String patternStr) {
|
||||
Pattern pattern = Pattern.compile(patternStr.replace(".", "\\.").replace("*", ".*"));
|
||||
return pattern.matcher(str).matches();
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package makamys.mixingasm.api;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** Decorate your class with this annotation to signal that your transformer is "Mixin-safe", i.e. it does not cause issues when run by Mixin's preprocessor. This will be used as a hint that it shouldn't get excluded from the mixin preprocessor's transformer list by Mixingasm. */
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface MixinSafeTransformer {
|
||||
}
|
||||
@@ -3,7 +3,8 @@ package makamys.mixingasm.forge;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import makamys.mixingasm.Mixingasm;
|
||||
|
||||
@Mod(modid = Mixingasm.MODID, version = "@VERSION@")
|
||||
@Mod(modid = Mixingasm.MODID, version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = Mixingasm.MODID, version = "@VERSION@", acceptableRemoteVersions = "*")
|
||||
public class MixingasmMod {
|
||||
|
||||
}
|
||||
+2
@@ -12,6 +12,7 @@
|
||||
# * It's matched by a pattern in transformer_inclusion_list.txt
|
||||
# * It was added to Mixingasm's dynamic inclusion list by a mod using the API at startup
|
||||
# * The transformer implements IMixinSafeTransformer
|
||||
# * The transformer is decorated with @MixinSafeTransformer
|
||||
# AND the transformer is not matched by a pattern in transformer_exclusion_list.txt
|
||||
|
||||
# '*' can be used as a wildcard character.
|
||||
@@ -24,3 +25,4 @@ net.minecraftforge.*
|
||||
codechicken.core.asm.*
|
||||
codechicken.lib.asm.*
|
||||
org.spongepowered.asm.*
|
||||
ofdev.*
|
||||
@@ -1,4 +1,4 @@
|
||||
Source: https://github.com/GTNewHorizons/GTNHMixins/tree/73e389805d2343e7a000f40879dbe232e53c08f1
|
||||
Source: https://github.com/GTNewHorizons/GTNHMixins/tree/2.1.13
|
||||
|
||||
Classes used:
|
||||
|
||||
@@ -8,10 +8,10 @@ com.gtnewhorizon.gtnhmixins.GTNHMixins (modified to not have @Mod annotation)
|
||||
License: LGPL3 (see LICENSE.LGPLv3)
|
||||
|
||||
|
||||
Source: https://github.com/GTNewHorizons/SpongeMixins/tree/c372c9010f9854dc80415a8fd1ff414fd0822f00
|
||||
Source: https://github.com/GTNewHorizons/SpongeMixins/tree/1.5.0
|
||||
|
||||
Classes used:
|
||||
|
||||
ru.timeconqueror.spongemixins.core.SpongeMixinsCore (removed Mixin bootstrap)
|
||||
ru.timeconqueror.spongemixins.core.SpongeMixinsCore (removed Mixin bootstrap, added 1.8+ @Mod and @IFMLPlugin annotations)
|
||||
|
||||
License: MIT (see LICENSE.SpongeMixins)
|
||||
@@ -4,7 +4,10 @@ dependencies {
|
||||
|
||||
archivesBaseName = archivesBaseName.replace("-1.7.10", "-spongemixins-1.7.10")
|
||||
|
||||
jar {
|
||||
shadowJar {
|
||||
archiveClassifier = ''
|
||||
configurations = []
|
||||
relocate 'com.gtnewhorizon', 'ru.timeconqueror.spongemixins.repackage.com.gtnewhorizon'
|
||||
manifest {
|
||||
attributes (
|
||||
'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
|
||||
@@ -14,11 +17,12 @@ jar {
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
srgExtra "PK: com/gtnewhorizon ru/timeconqueror/spongemixins/repackage/com/gtnewhorizon"
|
||||
}
|
||||
// Obfuscation is unnecessary since this module does not reference Minecraft classes
|
||||
reobf.enabled = false
|
||||
|
||||
ext.uniVersion = version
|
||||
ext.mcversion = "1.7.10"
|
||||
ext.extraVersion = "2.0.1"
|
||||
version += "+gtnh." + ext.extraVersion
|
||||
|
||||
jar.dependsOn shadowJar
|
||||
jar.enabled = false
|
||||
@@ -0,0 +1 @@
|
||||
extraVersion=2.0.1
|
||||
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.Logger;
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
@Mod(modid = SpongeMixins.MODID, version = "2.0.1", name = SpongeMixins.NAME, acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = SpongeMixins.MODID, version = "2.0.1", name = SpongeMixins.NAME, acceptableRemoteVersions = "*")
|
||||
public class SpongeMixins {
|
||||
|
||||
/**
|
||||
|
||||
+2
@@ -8,6 +8,8 @@ import java.util.Map;
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@IFMLLoadingPlugin.Name(SpongeMixinsCore.PLUGIN_NAME)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.SortingIndex(Integer.MIN_VALUE + 5)
|
||||
@net.minecraftforge.fml.relauncher.IFMLLoadingPlugin.Name(SpongeMixinsCore.PLUGIN_NAME)
|
||||
public class SpongeMixinsCore implements IFMLLoadingPlugin {
|
||||
public static final String PLUGIN_NAME = "SpongeMixin Core Plugin";
|
||||
public static final Logger LOGGER = LogManager.getLogger(PLUGIN_NAME);
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# Checks upstream repositories and warns if UniMixins is out of sync with them.
|
||||
#
|
||||
# A GitHub API token can be provided either in the GITHUB_TOKEN environmental
|
||||
# variable, or the ~/.tokens/github file.
|
||||
# Using one is not necessary, but doing so will greatly increase rate limits.
|
||||
|
||||
import requests
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
cachedGithubToken = None
|
||||
foundUpdates = 0
|
||||
|
||||
if not Path("module-mixin").is_dir():
|
||||
sys.exit('''
|
||||
This script needs to be run from the root of the repository, e.g.:
|
||||
python3 scripts/check_upstream.py
|
||||
''')
|
||||
|
||||
def compareVersions(rootName, comparisons):
|
||||
for comparison in comparisons:
|
||||
name, a, b = comparison
|
||||
compareVersion(f"{rootName} ({name})", a, b)
|
||||
|
||||
def compareVersion(name, a, b):
|
||||
global foundUpdates
|
||||
|
||||
upToDate = a == b
|
||||
judgement = "Up to date" if upToDate else "Out of sync!"
|
||||
details = f"({a} << {b})"
|
||||
if not upToDate:
|
||||
print(f"{name}: {judgement} {details}")
|
||||
foundUpdates += 1
|
||||
|
||||
def property(text, propName):
|
||||
props = dict([line.split("=") for line in text.splitlines() if line])
|
||||
return props[propName]
|
||||
|
||||
def localFile(path):
|
||||
return open(path, "r", encoding="utf8").read()
|
||||
|
||||
def githubFile(ownerAndRepo, branch, path):
|
||||
return requests.get(f"https://raw.githubusercontent.com/{ownerAndRepo}/{branch}/{path}").text
|
||||
|
||||
def stripBuildIdentifiers(ver):
|
||||
return ver.split("+")[0]
|
||||
|
||||
def lastReleaseTag(ownerAndRepo):
|
||||
return githubApi(f"/repos/{ownerAndRepo}/releases/latest")["tag_name"]
|
||||
|
||||
def lastVersionTag(ownerAndRepo):
|
||||
# some repos are missing releases, so we have to check tags. we'll have to guess which tags are versions.
|
||||
tags = [tag["ref"][len("refs/tags/"):] for tag in githubApi(f"/repos/{ownerAndRepo}/git/refs/tags")]
|
||||
return [tag for tag in tags if isProbablyAVersion(tag)][-1]
|
||||
|
||||
def isProbablyAVersion(tag):
|
||||
return bool(re.match("(v|V)?\d.*", tag))
|
||||
|
||||
def creditsSources(moduleName):
|
||||
sources = [line.split(": ")[-1] for line in localFile(moduleName + "/CREDITS").splitlines() if line.startswith("Source: ")]
|
||||
out = []
|
||||
|
||||
for source in sources:
|
||||
pattern = re.compile("https://github.com/(.+?)/(.+?)/tree/(.+)")
|
||||
match = pattern.match(source)
|
||||
if match:
|
||||
owner, repo, commitish = match.groups()
|
||||
ownerAndRepo = f"{owner}/{repo}"
|
||||
out.append([ownerAndRepo, commitish, lastVersionTag(ownerAndRepo)])
|
||||
else:
|
||||
raise Exception("Unknown source: " + source)
|
||||
|
||||
return out
|
||||
|
||||
def githubMainBranch(ownerAndRepo):
|
||||
return githubApi(f"/repos/{ownerAndRepo}")["default_branch"]
|
||||
|
||||
def githubHash(ownerAndRepo, commitish):
|
||||
return githubApi(f"/repos/{ownerAndRepo}/commits/{commitish}")["commit"]["tree"]["sha"]
|
||||
|
||||
def githubApi(path):
|
||||
headers = {}
|
||||
if githubToken():
|
||||
headers["Authorization"] = "Bearer " + githubToken()
|
||||
return requests.get(f"https://api.github.com{path}", headers=headers).json()
|
||||
|
||||
def githubToken():
|
||||
global cachedGithubToken
|
||||
if not cachedGithubToken:
|
||||
tokenFile = Path.home() / ".tokens" / "github"
|
||||
if tokenFile.is_file():
|
||||
cachedGithubToken = open(tokenFile, "r", encoding="utf8").read().strip()
|
||||
else:
|
||||
cachedGithubToken = os.environ.get("GITHUB_TOKEN") or ""
|
||||
return cachedGithubToken
|
||||
|
||||
compareVersion("Mixin (SpongePowered)",
|
||||
property(localFile("module-mixin/gradle.properties"), "spongepoweredMixinVersion"),
|
||||
property(githubFile("SpongePowered/Mixin", "master", "gradle.properties"), "buildVersion"))
|
||||
|
||||
compareVersion("Mixin (Fabric)",
|
||||
stripBuildIdentifiers(property(localFile("module-mixin/gradle.properties"), "fabricMixinVersion")),
|
||||
property(githubFile("FabricMC/Mixin", "main", "gradle.properties"), "buildVersion"))
|
||||
|
||||
compareVersion("Mixin (UniMix)",
|
||||
stripBuildIdentifiers(property(localFile("module-mixin/gradle.properties"), "unimixMixinVersion")),
|
||||
property(githubFile("LegacyModdingMC", "UniMix/main", "gradle.properties"), "buildVersion"))
|
||||
|
||||
compareVersion("Mixin (GTNH)",
|
||||
stripBuildIdentifiers(property(localFile("module-mixin/gradle.properties"), "gtnhMixinVersion")),
|
||||
lastVersionTag("GTNewHorizons/SpongePoweredMixin")) # GTNH doesn't have a master branch
|
||||
|
||||
compareVersion("Mixin (GasMix)",
|
||||
stripBuildIdentifiers(property(localFile("module-mixin/gradle.properties"), "gasmixMixinVersion")),
|
||||
property(githubFile("FalsePattern/GasMix", "master", "gradle.properties"), "buildVersion"))
|
||||
|
||||
compareVersions("GasStation",
|
||||
creditsSources("module-gasstation"))
|
||||
|
||||
compareVersions("GTNHMixins",
|
||||
creditsSources("module-gtnhmixins"))
|
||||
|
||||
compareVersions("MixinBooterLegacy",
|
||||
creditsSources("module-mixinbooterlegacy"))
|
||||
|
||||
compareVersion("MixinExtras",
|
||||
property(localFile("module-mixinextras/gradle.properties"), "mixinExtrasVersion"),
|
||||
lastVersionTag("LlamaLad7/MixinExtras"))
|
||||
|
||||
compareVersions("Mixingasm",
|
||||
creditsSources("module-mixingasm"))
|
||||
|
||||
compareVersions("SpongeMixins",
|
||||
creditsSources("module-spongemixins"))
|
||||
|
||||
if not foundUpdates:
|
||||
print("All modules up to date.")
|
||||
else:
|
||||
print()
|
||||
print(foundUpdates, f"repositor{'y is' if foundUpdates == 1 else 'ies are'} out of sync.")
|
||||
sys.exit(1)
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
include 'module-mixin'
|
||||
include 'module-compat'
|
||||
include 'module-devcompat'
|
||||
include 'module-compatfuture'
|
||||
include 'module-mixingasm'
|
||||
include 'module-spongemixins'
|
||||
include 'module-mixinbooterlegacy'
|
||||
|
||||
Reference in new issue
Block a user