Compare commits

...
123 Commits
Author SHA1 Message Date
ah-OOG-ah 3cc4912c55 Bump ASM 2025-06-28 16:18:10 -04:00
Ven 05878bfde1 Added support for OptiFineDevTweaker (#44) 2025-06-17 22:05:56 -04:00
amy 43ac78f2dc Use debug level for printing enabled GTNH mixins (#41) 2025-06-17 21:37:00 -04:00
ah-OOG-ahandRaven Szewczyk 1cbd6a0ecd Bump mixin to UniMix 0.15.4 (#39)
* Bump mixin

* Update github actions

---------

Co-authored-by: Raven Szewczyk <git@eigenraven.me>
2025-03-02 13:41:48 +00:00
ah-OOG-ah a97b3ce85c Update actions/upload-artifact (#40) 2025-02-19 08:41:45 -05:00
Jason Mitchell 56a008ce92 Update release.yml
V3 is being deprecated
2024-11-05 16:43:35 -08:00
Jason Mitchell 02a9a1a10d Move GTNH LateMixins to pre-init and fix compat with some mods that are triggering FMLConstructionEvent to load too early 2024-10-29 16:37:16 -07:00
Jason Mitchell 5fbb67e26f New mixins 0.8.7, mixinextras 0.4.1, and ASM 9.7.1 (#30)
* UniMix -> 0.15.0+mixin.0.8.7
MixinExtras -> 0.4.0

* maybe fix 1.8+

* GTNHMixins fix

* specify jdk

* rm

* mixin 0.15.3+mixin.0.8.7 and asm 9.7.1

* mixin extras 0.4.1
2024-10-14 18:17:32 -07:00
makamys 918a80ae53 [skip ci] README: Tweak badge styling 2024-03-21 19:32:43 +01:00
makamys 5788d7ec1e Bump ASM to 9.6
Mirroring change in Fabric Mixin
2024-03-19 02:51:57 +01:00
makamys e29c36c603 Bump UniMix and Fabric Mixin versions 2024-03-19 02:08:54 +01:00
makamys aed49ce829 Fix INIT mixins not loading with the LiteLoader mod in non-MultiMC 2024-03-19 02:08:51 +01:00
makamys 39a31c66da Remove trailing spaces 2024-02-14 20:24:25 +01:00
makamys d2c55ed6e3 Add maven publish CI workflow 2024-02-14 20:19:21 +01:00
makamys 614e8b9569 Adapt to GTNH maven 2024-02-14 20:19:18 +01:00
makamys 45d16b96ab Set up maven publishing 2024-02-14 19:30:18 +01:00
makamys 3563c869b5 [skip ci] Be more specific about GT6 version used in testing.md
Had this stashed and forgot to commit it
2024-02-14 19:29:59 +01:00
makamys 64a4084138 [skip ci] Use legacy curseforge in readme 2024-02-14 09:55:11 +01:00
drori200 acdd68819f Update mixinextras minor version 2024-02-09 03:38:37 +01:00
makamys 0fff377da8 docs: Make alternate mixin flavors less prominent
Since nobody uses them, and they aren't even published on Jitpack (because I don't want to increase build times unnecessarily)
2023-12-21 21:19:27 +01:00
makamys 1b130b1314 Use same version for all maven publications
For consistency with Jitpack, which uses the git tag for all publications.
2023-12-21 20:48:53 +01:00
makamys 608639acf3 Remap un-shadowed ASM package in mixin plugins
Needed for Zume
2023-12-21 17:11:18 +01:00
makamys 44f89624b0 Remove half-implemented selective remapping functionality
It's in the way
2023-12-20 11:03:03 +01:00
makamys 4f5d454d03 Update MixinExtras to 0.3.2 2023-12-19 08:01:44 +01:00
glowredman bbed619396 Use LoadableMod.hasValidMetaData() to filter out libs 2023-12-18 18:04:01 +01:00
glowredman d66394b2ea Add LiteLoader compat 2023-12-18 18:04:01 +01:00
makamys 220d040ebd [skip ci] Fix typo in license 2023-12-15 08:23:35 +01:00
makamys b42622470f [skip ci] README: Add image illustrating modularity, update info 2023-12-15 08:23:34 +01:00
makamys 3bc74ae73d [skip ci] Update the reference in the readme too 2023-12-12 07:59:13 +01:00
makamys 839425440e [skip ci] Link example mod in developer-usage.md 2023-12-12 07:56:13 +01:00
drori200 c2e86f3aae Update gradle.properties 2023-11-22 03:38:44 +01:00
drori200 48d55f2b44 Update build.gradle 2023-11-22 03:38:44 +01:00
drori200 de08ce459e Use MavenCentral 2023-11-22 03:38:44 +01:00
drori200 43a764c055 Pull mixinextras from MavenCentral 2023-11-22 03:38:44 +01:00
drori200 dad688c742 latest mixinextras rc 2023-11-22 03:38:44 +01:00
makamys f524e7de7f Fix typo in logger name of GTNHMixins and GasStation modules 2023-10-29 02:05:52 +01:00
makamys 181924abd1 Fix all obf jar not being included in maven publication 2023-10-29 02:42:33 +02:00
makamys 8bc2051af9 Give legacy GTNH MixinExtras directory a more descriptive name 2023-10-29 02:06:18 +02:00
makamys 87e71b1ba3 Fix legacy GTNHMixins still being indexed by IDEs 2023-10-29 02:04:23 +02:00
makamys ae12182d30 Fix wrong punctuation of sentences containing parentheses 2023-10-29 00:51:55 +02:00
makamys 189bf0b5e9 README: expand on documentation of extras 2023-10-29 00:51:52 +02:00
makamys 6b528532a2 Rebuild delegated transformer list at the beginning of late phase
Fixes mixin processor not running transformers added after DEFAULT phase
2023-10-29 00:15:48 +02:00
makamys 062eab7754 Fix project_url not getting substituted in mixin module's mcmod.info 2023-10-29 00:07:06 +02:00
makamys c053f33017 README: Remove outdated info about 1.8+ compat stub 2023-10-22 09:24:02 +02:00
makamys 016cf16396 README: Document Future Compat 2023-10-21 14:05:41 +02:00
makamys 9cff9105af Remove leftover GTNHMixins MixinExtras things 2023-10-21 14:01:58 +02:00
makamys 41aecb728a Make ASMRemapperTransformer skip uninteresting classes
Reduces ASMRemapperTransformer time from 2337ms to 220ms in gtnh.
2023-10-21 13:58:52 +02:00
makamys 8a8444d7f8 Remove duplicate MixinExtras license file 2023-10-21 12:58:28 +02:00
makamys cd232ec4a0 Shadow MixinExtras source 2023-10-21 12:58:03 +02:00
makamys 14e8ce7cb2 Document LaunchClassLoaderUtils some more 2023-10-21 12:32:51 +02:00
makamys 6c55d33c18 Move GTNH MixinExtras generator to GTNHMixins module
It shouldn't be around if you're not using the GTNHMixins module
2023-10-21 11:50:22 +02:00
makamys fcd416e31b Only generate class if it's not present 2023-10-21 11:50:22 +02:00
makamys fe11aee64c Fix GTNH MixinExtras generator crashing in dev env with NEI 2023-10-21 11:50:21 +02:00
makamys d5c96de372 Rename fix to hack because that's what it is 2023-10-21 11:50:21 +02:00
makamys 798b3fb1c9 Update developer usage 2023-10-21 11:50:21 +02:00
makamys ee81c389fa Oops, FML's deobf property isn't set yet. Just use a jvm arg then. 2023-10-21 11:50:21 +02:00
makamys 1237e86768 Don't allow empty changelog in publish script 2023-10-21 11:50:21 +02:00
makamys d268a991ad README: Add hint about compilation 2023-10-21 11:50:21 +02:00
makamys f1a63f392d Move 1.8+ compat stub into separate module (fixes #19) 2023-10-21 11:50:21 +02:00
makamys 7ee32c62d3 Merge devcompat module into compat
It was kept separate to make it easy to apply the dev compat tweaks in dev
environments without having to mess with config files, but this is unnecessary
now that you can set config values via JVM flags.
2023-10-21 11:50:16 +02:00
makamys ddd608a8f8 Give transformers more unique and descriptive names 2023-10-21 03:04:02 +02:00
makamys a4bddd8dbf Allow setting properties using JVM flags 2023-10-21 02:34:43 +02:00
makamys a892f6d119 Disable reobf in modules that don't need it 2023-10-21 02:34:40 +02:00
makamys 58bb4137f0 Fix the LWJGL3ify compat ForgeGradle style
Reobfuscating the MixinExtras module is what breaks it. So don't do that, and
don't run the reobf task for the all jar either, just collect the contents
of all the obf jars.
2023-10-21 01:39:36 +02:00
makamys 28b93dd4f7 Reject RFG, return to FG
RFG's performance is unsuitable for this project, see
https://github.com/GTNewHorizons/RetroFuturaGradle/issues/49

Reverts the following commits:

ba1f02d Begin RFG move. Common module compiles
b589106 Mixin module works now I think
46a5c6d Use VERSION tag in Mixin module
2409b24 Mixingasm seems to work now
f0b355c Sources jar get
23e833f Remove redundant calls
2e78938 Update gradle in hopes that it will magically fix all my problems
80e0723 Port all the modules
28e98d5 Port All module (not the same thing)
3a09260 Fix common module build failing
1088934 Get rid of bloat from buildscript template
bff36c3 Porting is done now maybe
27e3058 Fix what I broke
bbc0b48 zulu?
9b4bde7 I guess I need Java 17 too
c3af516 RFG needs alot of ram apparently

But keeps these:

9152c1a Don't build alternate flavors by default
24f6c06 Move compat module's MixinExtras temp jar to temp dir
2023-10-21 00:32:29 +02:00
makamys c3af5167df RFG needs alot of ram apparently 2023-10-19 11:49:56 +02:00
makamys 9b4bde7e95 I guess I need Java 17 too 2023-10-19 11:33:48 +02:00
makamys bbc0b48175 zulu? 2023-10-19 11:31:05 +02:00
makamys 27e3058a53 Fix what I broke 2023-10-19 11:13:56 +02:00
makamys 24f6c06631 Move compat module's MixinExtras temp jar to temp dir 2023-10-19 10:44:51 +02:00
makamys bff36c3067 Porting is done now maybe 2023-10-19 10:22:24 +02:00
makamys 108893429f Get rid of bloat from buildscript template 2023-10-19 10:04:04 +02:00
makamys 3a09260a99 Fix common module build failing 2023-10-19 10:02:22 +02:00
makamys 9152c1a5ca Don't build alternate flavors by default
Because I'm tired of having to append -PnoAltMixin to the command
every time
2023-10-19 09:51:42 +02:00
makamys 28e98d501f Port All module (not the same thing) 2023-10-19 09:49:47 +02:00
makamys 80e07234f5 Port all the modules 2023-10-19 09:27:49 +02:00
makamys 2e7893816f Update gradle in hopes that it will magically fix all my problems 2023-10-19 08:37:12 +02:00
makamys 23e833fd1e Remove redundant calls 2023-10-19 07:14:32 +02:00
makamys f0b355c782 Sources jar get 2023-10-19 06:46:30 +02:00
makamys 2409b246b3 Mixingasm seems to work now 2023-10-19 06:34:39 +02:00
makamys 46a5c6d167 Use VERSION tag in Mixin module 2023-10-19 06:27:59 +02:00
makamys b5891061e0 Mixin module works now I think 2023-10-19 06:02:15 +02:00
makamys ba1f02d541 Begin RFG move. Common module compiles 2023-10-19 01:49:42 +02:00
makamys 9aa07d509c Update Mixingasm config to mention @MixinSafeTransformer 2023-10-18 19:31:19 +02:00
makamys 8e17e96c3e Remove duplicated Mixingasm assets in GasStation module 2023-10-18 19:31:18 +02:00
makamys 8e3e7e49e5 Make compat module use new Mixingasm API
(But keep using the old one as a fallback.)
2023-10-17 05:47:10 +02:00
makamys 0e54b7bf08 Add better Mixingasm API that doesn't create a runtime dependency 2023-10-17 05:47:10 +02:00
makamys 1db6d9b000 Fix generator crashing in GTNH 2023-10-17 05:47:10 +02:00
makamys 9354ebd81a Update readme 2023-10-17 05:47:10 +02:00
makamys df12ab3ef3 Generate GTNH-relocated MixinExtras at runtime
This preserves backwards compatibility while making new mods fail to compile if
they try to reference the old package.
2023-10-17 05:47:09 +02:00
makamys 2ae66ed7a6 Document changes 2023-10-17 05:47:09 +02:00
makamys 46d1e77770 Remove leftover GTNH-MixinExtras references 2023-10-17 05:47:09 +02:00
drori200 e3c8d83108 Remove MixinExtras from GTNHMixin (#18)
* Remove MixinExtras from GTNHMixin

* Bump GTNHMixin version

* Version bump

branch was out of date
2023-10-17 05:45:07 +02:00
Jason Mitchell cec3048ed4 Merge pull request #15 from drori200/patch-1
Update MixinExtras to latest
2023-10-13 17:34:30 -07:00
drori200 f5800a69c2 Update to MixinExtras stable 0.2.0 2023-10-14 03:24:05 +03:00
drori200 b143241008 Revert "Update build.gradle"
This reverts commit 0daba06b88.
2023-10-14 03:17:08 +03:00
drori200 0daba06b88 Update build.gradle 2023-09-29 19:45:59 +03:00
drori200 ba453f04c5 Update build.gradle 2023-09-29 19:42:05 +03:00
drori200 8e2d6beb3f Correct gtnh's mixinextra AP path 2023-09-29 02:11:25 +03:00
drori200 c0f712fb9d Update GTNHMixin's MixinExtra version 2023-09-29 02:05:54 +03:00
drori200 2376d1ce50 Correct the MixinExtras ap path 2023-09-29 01:35:48 +03:00
drori200 37edc3537a Update MixinExtras to latest rc 2023-09-26 06:57:35 +03:00
makamys 618bd0de47 testing.md: Update FPLib and RPGS, fix some inaccuracies 2023-06-21 08:58:27 +02:00
makamys d4213cf71a Add forge-network-fix to testing.md 2023-06-21 07:44:39 +02:00
Egor 92db4df839 Fix mixin-booter-legacy module not having a manifest. 2023-06-21 07:42:53 +02:00
makamys 278edd177d Change remaining - to + in README 2023-06-11 06:08:27 +02:00
makamys 1ed02bc811 Change jar name prefix to +
Because - is annoying to work with in the command line
2023-06-11 05:44:01 +02:00
makamys 2a331ee00f Remove build-zip.sh since it's not used anymore 2023-06-11 05:30:32 +02:00
makamys 5d5aff4efe Remove - prefix from maven artifact id 2023-06-11 05:30:11 +02:00
makamys e54253eb95 Make update checker pluralize nouns properly 2023-06-10 22:26:23 +02:00
makamys adfa0b9061 Move more versions to gradle.properties for consistency 2023-06-10 22:22:47 +02:00
makamys 12ea25c3f2 Make update checker print a summary and use return codes 2023-06-10 21:59:25 +02:00
makamys 96fcda3db2 Bump GTNHMixins version
(There were no new changes to merge, this is just a metadata change.)
2023-06-10 21:56:17 +02:00
makamys 524ee60d9a Add update check script 2023-06-10 21:51:21 +02:00
makamys 4144ea5913 Move dependency versions to gradle.properties
This will make checking for updates easier
2023-06-10 21:46:46 +02:00
makamys b8953cc38c Use tags everywhere in source urls in credits
This will make checking for updates easier
2023-06-10 21:19:47 +02:00
makamys f20c78c96b Set acceptableRemoteVersions = "*" in all modules 2023-06-01 19:07:04 +02:00
makamys f595016981 README: Hint at the existence of 1.8+ support 2023-05-24 08:03:22 +02:00
makamys 4355a4a481 Add Forge maven 2023-05-24 07:31:03 +02:00
makamys a68db4a990 Document changes 2023-05-24 07:14:33 +02:00
makamys b8830d9375 Add ComparableVersion abstraction layer 2023-05-24 07:14:33 +02:00
makamys 23386a3ea8 Add 1.8+ Mod and IFMLPlugin annotations and stub IFMLPlugin interface 2023-05-24 07:14:21 +02:00
makamys 4b1b1423fd Fix Mixingasm standalone jar being broken 2023-05-24 05:36:13 +02:00
83 changed files with 1827 additions and 521 deletions

No files matched your search

+12 -5
View File
@@ -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
+21 -7
View File
@@ -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)"
+1 -1
View File
@@ -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
+31 -22
View File
@@ -1,18 +1,18 @@
[![downloads](https://img.shields.io/badge/-⬇%20releases-brightgreen)](https://github.com/LegacyModdingMC/UniMixins/releases)
[![builds](https://img.shields.io/badge/-🛈%20builds-blue)](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
[![CurseForge](https://shields.io/badge/CurseForge-555555?logo=curseforge)](https://www.curseforge.com/minecraft/mc-mods/unimixins)
[![modrinth](https://shields.io/badge/modrinth-555555?logo=data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBhcmlhLWxhYmVsPSJtb2RyaW50aCIgY2xhc3M9InNtYWxsLWxvZ28iIHZlcnNpb249IjEuMSIgaWQ9InN2ZzkwMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNTEyIDUxNCI+PHN0eWxlPnBhdGh7ZmlsbDojZmZmO2ZpbGwtb3BhY2l0eToxfTwvc3R5bGU+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01MDMgMzI0QTI1NiAyNTYgMCAxMDEgMjMxaDQzYTIxMiAyMTIgMCAwMTQwOS01MGwtNDIgMTJjLTE5LTQ3LTU4LTgyLTEwNS05NmwtNyA0NGExMjQgMTI0IDAgMDExMCAyMjhsMTEgNDNjNzAtMjkgMTEyLTEwMiAxMDItMTc3bDQyLTExYzUgMjkgMyA1Ny0zIDg0bDQyIDE2eiIgaWQ9InBhdGg4OTgiLz48cGF0aCBjbGFzcz0ibm9ybWFsIiBkPSJNMzIyIDUwNEEyNTYgMjU2IDAgMDEwIDI3NWg0M2EyMTMgMjEzIDAgMDAyMCA3MmwzOC0yMy04LTI0QTE2OCAxNjggMCAwMTI2MyA4OWwtOCA0NGExMjUgMTI1IDAgMDAtMTE5IDE1Nmw0IDEyIDQ5LTMwLTE1LTM5IDQ3LTQ4IDU5LTEzIDE3IDIxLTI4IDI4LTIzIDctMTcgMTggOCAyMyAxNyAxOCAyNC03IDE3LTE4IDM2LTEyIDExIDI1LTM4IDQ2LTYzIDIxLTI5LTMyLTUwIDMwYzI2IDI5IDY0IDQ1IDEwNCA0MmwxMiA0M2MtNjAgNy0xMTgtMTctMTU0LTYybC0zOCAyM2EyMTIgMjEyIDAgMDAzNTktMzZsNDMgMTZjLTMxIDY2LTkwIDExOS0xNjYgMTM5eiIgaWQ9InBhdGg5MDAiLz48c3R5bGUvPjwvc3ZnPg==)](https://modrinth.com/mod/unimixins)
[![Discord](https://shields.io/badge/Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/AJxEFs6YBN)
[![downloads](https://img.shields.io/badge/-⬇%20releases-brightgreen?style=flat-square)](https://github.com/LegacyModdingMC/UniMixins/releases)
[![builds](https://img.shields.io/badge/-🛈%20builds-blue?style=flat-square)](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
[![CurseForge](https://shields.io/badge/CurseForge-555555?logo=curseforge&logoColor=white&style=flat-square)](https://legacy.curseforge.com/minecraft/mc-mods/unimixins)
[![modrinth](https://shields.io/badge/modrinth-555555?logo=modrinth&logoColor=white&style=flat-square)](https://modrinth.com/mod/unimixins)
[![Discord](https://shields.io/badge/Discord-5865F2?logo=discord&logoColor=white&style=flat-square)](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
-15
View File
@@ -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
View File
@@ -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
View File
@@ -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

+712
View File
@@ -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 &quot;BOX&quot;, 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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
}
+4 -1
View File
@@ -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
@@ -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();
}
}
}
}
-1
View File
@@ -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 = ''
@@ -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;
}
@@ -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;
}
}
}
@@ -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 {
}
@@ -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 {
}
@@ -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);
@@ -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);
}
}
@@ -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;
}
@@ -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.
+21
View File
@@ -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
@@ -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;
}
}
@@ -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 {
}
@@ -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 {
}
@@ -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}",
-16
View File
@@ -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'
)
}
}
@@ -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;
}
}
@@ -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 {
}
+1
View File
@@ -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)
+4 -2
View File
@@ -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
+2
View File
@@ -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);
@@ -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()) {
@@ -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 ---
@@ -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 ---
@@ -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.*
+8 -6
View File
@@ -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)
+32 -5
View File
@@ -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
+1
View File
@@ -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);
}
}
}
@@ -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);
@@ -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;
}
}
@@ -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;
}
@@ -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<>();
@@ -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));
}
}
@@ -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 +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
View File
@@ -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
+7
View File
@@ -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
@@ -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 {}
@@ -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();
}
+1 -1
View File
@@ -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": "",
+2
View File
@@ -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)
+11 -1
View File
@@ -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
@@ -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 {
}
+21 -3
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
mixinExtrasVersion=0.4.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.
+3 -1
View File
@@ -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 -1
View File
@@ -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 {
+1
View File
@@ -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 {
}
@@ -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.*
+3 -3
View File
@@ -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)
+9 -5
View File
@@ -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
+1
View File
@@ -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 {
/**
@@ -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);
+143
View File
@@ -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
View File
@@ -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'