Compare commits

...
169 Commits
Author SHA1 Message Date
ah-OOG-ah 1d834475de forgor 2025-06-26 12:44:54 -04:00
ah-OOG-ah 6901315e2e Remove redundant extra configuration
The task already only includes exactly what it needs.
2025-06-26 12:34:21 -04:00
ah-OOG-ah 50b5b3711b Use existing configuration for shading 2025-06-26 12:31:46 -04:00
ah-OOG-ah c1031c9048 Remove useless include 2025-06-26 12:31:26 -04:00
ah-OOG-ah 8537f8e212 Update build.gradle.kts 2025-06-26 11:45:50 -04:00
ah-OOG-ah 110090350c Make shadowImplSources take project deps 2025-06-26 10:46:47 -04:00
ah-OOG-ah 0aa57099f1 Fix source shading 2025-06-25 17:30:14 -04:00
ah-OOG-ah 441b41e8b9 Update MixinExtras for the shadow setup 2025-06-20 16:37:38 -04:00
ah-OOG-ah 9c7fb856a3 Properly set up shadow config extension 2025-06-20 16:37:01 -04:00
ah-OOG-ah dd04399acd Lazily add deps, so it actually works 2025-06-20 16:34:18 -04:00
ah-OOG-ah da4e4d05ab Update UniMixinsPlugin.kt 2025-06-20 16:29:38 -04:00
ah-OOG-ah b9f1dba519 Add configs for shading sources 2025-06-20 16:16:22 -04:00
ah-OOG-ah 36389a489a Fix typo - use fmlCorePlugin, not uniMixVersion 2025-06-20 15:12:59 -04:00
ah-OOG-ah ec57ec1909 Add sources jar 2025-06-20 15:04:42 -04:00
ah-OOG-ah 051e7b5079 Add -dev and normal jars to assemble task 2025-06-20 15:04:18 -04:00
ah-OOG-ah 0815f55f52 Update UniMixinsPlugin.kt 2025-06-20 14:54:13 -04:00
ah-OOG-ah 1c48884055 Shadow submodules 2025-06-20 14:34:14 -04:00
ah-OOG-ah de34b41af0 Switch back to standard artifacts
Hooray! Fixed this awful hack
2025-06-20 11:46:49 -04:00
ah-OOG-ah 5198ed747f Remove manual newlines from mcmod.info 2025-06-20 11:46:49 -04:00
ah-OOG-ah 439defbca4 Use unimixins ext for setting the core plugin 2025-06-20 11:46:49 -04:00
ah-OOG-ah 1f15b3ed3c Rely on extender to create extension 2025-06-20 11:46:49 -04:00
ah-OOG-ah 830d6815fa Add separate plugin to apply extension 2025-06-20 11:46:48 -04:00
ah-OOG-ah d8d80a3fc1 Apply shadowJar and jar configuration by plugin 2025-06-20 11:46:48 -04:00
ah-OOG-ah b25075e52e remove project. where reasonable 2025-06-20 11:46:48 -04:00
ah-OOG-ah 2cc3379211 Use metadata for Unimixins version 2025-06-20 11:46:48 -04:00
ah-OOG-ah 23057cba91 Fix common processResources task 2025-06-20 11:46:48 -04:00
ah-OOG-ah caa1053569 Use standard git-version 2025-06-20 11:46:48 -04:00
ah-OOG-ah 60969ff650 Exclude non-class files from GTNH-MixinExtras 2025-06-20 11:46:48 -04:00
ah-OOG-ah 0086944037 Merge service files 2025-06-20 11:46:48 -04:00
ah-OOG-ah 90dc8f9786 Remove errant README 2025-06-20 11:46:48 -04:00
ah-OOG-ah 697e8a127b Copy Mixin license files to modularized location 2025-06-20 11:46:48 -04:00
ah-OOG-ah f9740e6a59 Fix service merging 2025-06-20 11:46:48 -04:00
ah-OOG-ah a87d3c621c Use shadowJar for common as well
Because I can't be bothered to reconfigure jar *and* shadowJar. Now, if only Gradle had a better way to do this...
2025-06-20 11:46:48 -04:00
ah-OOG-ah d58378153f Update .gitignore 2025-06-20 11:46:48 -04:00
ah-OOG-ah f447a961d0 Use proper includes to grab more licenses 2025-06-20 11:46:48 -04:00
ah-OOG-ah eedb41e273 Fix incorrect license copy 2025-06-20 11:46:48 -04:00
ah-OOG-ah e89272708d Fix incorrect string coercion 2025-06-20 11:46:48 -04:00
ah-OOG-ah fb264715c5 Add implementation version to all jar 2025-06-20 11:46:48 -04:00
ah-OOG-ah 66c33efa07 Remove different local identifier 2025-06-20 11:46:48 -04:00
ah-OOG-ah 7815282efc Move uniMixVersion to DSL block 2025-06-20 11:46:48 -04:00
ah-OOG-ah aada5bff2e Add extension for global values 2025-06-20 11:46:48 -04:00
ah-OOG-ah 47bf297756 Bump to Gradle 8.14.2 2025-06-20 11:46:48 -04:00
ah-OOG-ah 579256e0d2 Add commit ID to manifests 2025-06-20 11:46:48 -04:00
ah-OOG-ah 3aa9962eab Fix wrong MANIFEST.MF being included 2025-06-20 11:46:48 -04:00
ah-OOG-ah 1060c1d50d Apply manifest attributes from old buildscript 2025-06-20 11:46:48 -04:00
ah-OOG-ah 7a1496c88f Delete build.gradle.disabled 2025-06-20 11:46:48 -04:00
ah-OOG-ah 763020eec6 Rename buildSrc
Apparently, IntelliJ just *dies* when the plugin is in buildSrc, as opposed to a manually included build
2025-06-20 11:46:48 -04:00
ah-OOG-ah 22dc439dfd Change "true" to true 2025-06-20 11:46:48 -04:00
ah-OOG-ah 752c66d068 Add all core plugin 2025-06-20 11:46:48 -04:00
ah-OOG-ah 124f1b550f Update AllCore.java 2025-06-20 11:46:48 -04:00
ah-OOG-ah b9951f7fc6 Load merged plugin file 2025-06-20 11:46:48 -04:00
ah-OOG-ah b51a23affb Move convention plugin to class plugin 2025-06-20 11:46:48 -04:00
ah-OOG-ah 2c4830327a Move FMLCorePlugin definition to gradle.properties 2025-06-20 11:46:48 -04:00
ah-OOG-ah 5c92143878 Move subprojects block into buildSrc 2025-06-20 11:46:48 -04:00
ah-OOG-ah d0b94d165a Pull McmodInfoMerger into buildSrc 2025-06-20 11:46:48 -04:00
ah-OOG-ah 775b6a6a2e Add a file for each coremod 2025-06-20 11:46:48 -04:00
ah-OOG-ah 868a305717 Move core mod setting to main BS
Doesn't work, I need to move this to a buildSrc plugin.
2025-06-20 11:46:48 -04:00
ah-OOG-ah c75fdf59f9 Move shadow application to main BS 2025-06-20 11:46:48 -04:00
ah-OOG-ah 7f2abaf16c Update build.gradle.kts 2025-06-20 11:46:48 -04:00
ah-OOG-ah bba6fe800e Update AllCore.java 2025-06-20 11:46:48 -04:00
ah-OOG-ah 01853f27f1 Merge mcmod.info files properly 2025-06-20 11:46:48 -04:00
ah-OOG-ah 454a4736d0 oops 2025-06-20 11:46:48 -04:00
ah-OOG-ah 74b9393a09 Add mcmod.info to all module 2025-06-20 11:46:48 -04:00
ah-OOG-ah d5b9033c4d Shade everything in the -all module 2025-06-20 11:46:48 -04:00
ah-OOG-ah 1263d1bb5b Fix jar naming for the all module 2025-06-20 11:46:48 -04:00
ah-OOG-ah 8f55434547 Add shadowJar artifacts 2025-06-20 11:46:48 -04:00
ah-OOG-ah 589940109b Enable all module 2025-06-20 11:46:48 -04:00
ah-OOG-ah 07ca8dbe0f Add MixinExtras 2025-06-20 11:46:48 -04:00
ah-OOG-ah 091b30b28e Enable GTNHMixins 2025-06-20 11:46:48 -04:00
ah-OOG-ah 1c623d7b12 Publish shadow artifact for Mixingasm
Tried using the default configuration, it didn't work
2025-06-20 11:46:48 -04:00
ah-OOG-ah e7923da598 Enable Gasstation 2025-06-20 11:46:48 -04:00
ah-OOG-ah 90f3dcc6f1 Add shadowed artifact 2025-06-20 11:46:48 -04:00
ah-OOG-ah 54424d7e97 Give up, just use metadata 2025-06-20 11:46:48 -04:00
ah-OOG-ah f36c45e15f Attempt to fix MBL version 2025-06-20 11:46:48 -04:00
ah-OOG-ah 21735c096e Enable MixinBooterLegacy 2025-06-20 11:46:48 -04:00
ah-OOG-ah 9627890f23 Add Spongemixins 2025-06-20 11:46:48 -04:00
ah-OOG-ah 301a0704cf Fix Mixingasm 2025-06-20 11:46:48 -04:00
ah-OOG-ah 63e3953dc7 how 2025-06-20 11:46:48 -04:00
ah-OOG-ah 1eb68f7864 Fix versioning AGAIN 2025-06-20 11:46:48 -04:00
ah-OOG-ah 6b67057695 Enable MixingASM 2025-06-20 11:46:48 -04:00
ah-OOG-ah 5fc8e5b76f Enable and patch compatfuture 2025-06-20 11:46:48 -04:00
ah-OOG-ah f09aed0390 Fix compat module BS
Also consolidate some property expansion
2025-06-20 11:46:48 -04:00
ah-OOG-ah c0b368cd49 Enable compat module 2025-06-20 11:46:48 -04:00
ah-OOG-ah 5fbb40602c Remove old buildscripts 2025-06-20 11:46:48 -04:00
ah-OOG-ah dff5a9df3f Update build.gradle.kts 2025-06-20 11:46:48 -04:00
ah-OOG-ah 0a10e2c099 Actually fix the mcmod.info 2025-06-20 11:46:48 -04:00
ah-OOG-ah 7ba0d6f6d3 Attempt to fix version replacement 2025-06-20 11:46:48 -04:00
ah-OOG-ah 3fe1269c8b Remove errant classifier 2025-06-20 11:46:48 -04:00
ah-OOG-ah 6701a1b0d8 Rearrange mixin project build 2025-06-20 11:46:48 -04:00
ah-OOG-ah 33277033d1 Fix versioning 2025-06-20 11:46:48 -04:00
ah-OOG-ah 815367896f Hack out non-UniMix flavors 2025-06-20 11:46:48 -04:00
ah-OOG-ah fb4ac22a98 Initial port of mixin module BS 2025-06-20 11:46:48 -04:00
ah-OOG-ah ebf46d905d Add mixin module 2025-06-20 11:46:48 -04:00
ah-OOG-ah e7e38e27ef Reenable common module 2025-06-20 11:46:48 -04:00
ah-OOG-ah bd9dca59e2 Update build.gradle.kts 2025-06-20 11:46:48 -04:00
ah-OOG-ah 752c185fe9 Rename and enable common 2025-06-20 11:46:48 -04:00
ah-OOG-ah 0066b48b26 Move properties to buildscript variables 2025-06-20 11:46:48 -04:00
ah-OOG-ah 7d82258dbf nope go back 2025-06-20 11:46:48 -04:00
ah-OOG-ah 689f92eea5 Obliterate mixin module and add it to project 2025-06-20 11:46:48 -04:00
ah-OOG-ah 3c2198317f Add Unimined 2025-06-20 11:46:48 -04:00
ah-OOG-ah 43042cd98d Update gradlew 2025-06-20 11:46:48 -04:00
ah-OOG-ah 59f4175685 Add mavens for plugins 2025-06-20 11:46:48 -04:00
ah-OOG-ah cda6dfc35b Obliteration 2025-06-20 11:46:48 -04:00
ah-OOG-ah ea3cc3efa9 Update GasStation's license
It was relicensed to standard LGPL at some point
2025-06-20 11:46:48 -04:00
ah-OOG-ah f544ebf226 Consolidate build
Don't alter the group or artifact ID of the main module when publishing locally. Also update the NH maven so it builds.
2025-06-20 11:46:48 -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
201 changed files with 3274 additions and 2052 deletions

No files matched your search

+16 -11
View File
@@ -8,25 +8,30 @@ 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: 'zulu'
java-version: |
8
17
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 -Dorg.gradle.jvmargs=-Xmx2048M
run: ./gradlew setupCIWorkspace
- name: Build with Gradle
run: ./gradlew build -Dorg.gradle.jvmargs=-Xmx2048M
run: ./gradlew build
- name: Copy artifacts to a single directory
run: |
mkdir build/tmp/ci -p
@@ -39,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
+20 -6
View File
@@ -16,19 +16,26 @@ 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
@@ -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)"
+203
View File
@@ -0,0 +1,203 @@
Part of the buildscript is adapted from https://github.com/LogicFan/shadow-json-transformer under the Apache v2 license.
The license text is below:
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+15 -10
View File
@@ -2,25 +2,30 @@ 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
Part of the buildscript is adapted from https://github.com/LogicFan/shadow-json-transformer under the Apache v2 license.
Requisite notices are in CREDITS in the repository root. Another part is adapted from
https://github.com/GTNewHorizons/GTNHGradle under the LGPLv3. Again, requisite notices are in CREDITS.
Directory: module-spongemixins
## SpongeMixins
Directory: spongemixins
LICENSE: LGPLv3
## MixinBooterLegacy
Directory: module-mixinbooterlegacy
Directory: mixinbooterlegacy
LICENSE: LGPLv2.1
## GasStation
Directory: module-gasstation
LICENSE: LGPLv3+SNEED
Directory: gasstation
LICENSE: LGPLv3
## GTNHMixins
Directory: module-gtnhmixins
Directory: gtnhmixins
LICENSE: LGPLv3
## UniMixinsPlugin
Directory: UniMixinsPlugin
LICENSE: LGPLv3
Not technically a module proper, it just hosts shared build logic for the others.
+21 -15
View File
@@ -1,8 +1,8 @@
[![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
@@ -12,7 +12,7 @@ UniMixins is a Mixin loader for Minecraft 1.7.10 (with partial 1.8.9~1.12.2 supp
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
@@ -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
@@ -70,13 +70,11 @@ All modules depend on the Mixin module. Note that the dependents don't necessari
* **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>
* Provides the deprecated `com.gtnewhorizons.mixinextras` relocation of MixinExtras 0.1.1.
* Adds a stub that allows loading 1.7.10 FML plugins on 1.8+. **Needed to run the mod on 1.8+.**
* **Mixingasm**: Improves Mixin's compatibility with ASM transformers.
### Optional
* **DevCompat** <sup>[1.7.10 only]</sup>: 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
@@ -91,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?
@@ -99,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.
@@ -114,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
@@ -122,6 +127,7 @@ When editing the source code of modules, please document your changes in the mod
* `-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.
* `-PenableAltMixin`: build alternate flavors of the Mixin module, not just UniMix.
* `-PpublishAll`: publish all modules, not just the combined one.
### Roadmap
+2
View File
@@ -0,0 +1,2 @@
.gradle
.kotlin
+45
View File
@@ -0,0 +1,45 @@
plugins {
kotlin("jvm") version "2.1.21"
`java-gradle-plugin`
}
repositories {
mavenCentral()
gradlePluginPortal()
maven {
url = uri("https://maven.wagyourtail.xyz/releases")
}
}
dependencies {
implementation("xyz.wagyourtail.unimined:xyz.wagyourtail.unimined.gradle.plugin:1.3.14")
implementation("com.palantir.git-version:com.palantir.git-version.gradle.plugin:3.3.0")
implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:8.3.6")
implementation("com.google.code.gson:gson:2.13.1")
implementation("org.apache.ant:ant:1.10.15")
}
gradlePlugin {
plugins {
create("unimixinsConfig") {
id = "unimixinsConfig"
implementationClass = "UniMixinsExtender"
}
create("unimixins") {
id = "unimixins"
implementationClass = "UniMixinsPlugin"
}
}
}
kotlin {
jvmToolchain(21)
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
+1
View File
@@ -0,0 +1 @@
rootProject.name = "UniMixinsPlugin"
@@ -0,0 +1,128 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.google.gson.JsonPrimitive
import org.gradle.api.file.FileTreeElement
import java.io.InputStreamReader
import org.apache.tools.zip.ZipOutputStream
import org.apache.tools.zip.ZipEntry
import org.gradle.api.logging.Logging
/**
* Adapted from https://github.com/LogicFan/shadow-json-transformer.
* @author Logic Fan
* @author ah-OOG-ah
*/
class McmodInfoMerger(private val parentModid: String) : Transformer {
private val GSON = GsonBuilder().setPrettyPrinting().create()
private val LOGGER = Logging.getLogger(McmodInfoMerger::class.java)
private var json: JsonElement? = null
private val targetFile = "mcmod.info"
// GSON adds the extra quotes when parsing, so we add them to the comparison string
private val comparisonModid = "\"$parentModid\""
override fun canTransformResource(element: FileTreeElement?): Boolean {
return targetFile == element?.relativePath.toString()
}
override fun transform(context: TransformerContext?) {
val j: JsonElement?
try {
val inputStream = context?.`is`
j = if (inputStream == null)
null
else
JsonParser.parseReader(InputStreamReader(inputStream, "UTF-8"))
} catch (e: Exception) {
throw RuntimeException("error on processing json", e)
}
val modObj = if (j is JsonArray && !j.isEmpty) j.get(0) as JsonObject
else throw RuntimeException("Mod objects should be in an array!")
if (modObj.get("modid").toString() != comparisonModid) {
modObj.add("parent", JsonPrimitive(parentModid))
}
json = if (json == null) j else mergeJson(json, j)
}
override fun hasTransformedResource(): Boolean {
return json != null
}
override fun modifyOutputStream(os: ZipOutputStream?, preserveFileTimestamps: Boolean) {
val entry = ZipEntry(targetFile)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os!!.putNextEntry(entry)
os.write(GSON.toJson(json).toByteArray())
json = null
}
override fun getName(): String {
return "McmodInfoMerger"
}
/**
* @param lhs a JsonElement
* @param rhs a JsonElement
* @param id used for logging purpose only
* @return the merged JsonElement
*/
fun mergeJson(lhs: JsonElement?, rhs: JsonElement?, id: String = ""): JsonElement? {
if (rhs == null || rhs is JsonNull) {
return lhs
} else if (lhs == null || lhs is JsonNull) {
return rhs
} else if (lhs is JsonArray && rhs is JsonArray) {
return mergeJsonArray(lhs, rhs)
} else if (lhs is JsonObject && rhs is JsonObject) {
return mergeJsonObject(lhs, rhs, id)
} else if (lhs is JsonPrimitive && rhs is JsonPrimitive) {
return mergeJsonPrimitive(lhs, rhs, id)
} else {
LOGGER.warn("conflicts for property {} detected, {} & {}",
id, lhs.toString(), rhs.toString())
return lhs
}
}
fun mergeJsonArray(lhs: JsonArray, rhs: JsonArray): JsonArray {
val array = JsonArray()
array.addAll(lhs)
array.addAll(rhs)
return array
}
fun mergeJsonObject(lhs: JsonObject, rhs: JsonObject, id: String): JsonObject {
val obj = JsonObject()
val properties = HashSet<String>()
properties.addAll(lhs.keySet())
properties.addAll(rhs.keySet())
for (property in properties) {
obj.add(
property,
mergeJson(lhs.get(property),
rhs.get(property),
"$id:$property"))
}
return obj
}
fun mergeJsonPrimitive(lhs: JsonPrimitive, rhs: JsonPrimitive, id: String): JsonPrimitive {
if (lhs != rhs) {
LOGGER.warn("[McmodInfoMerger] conflicts for property {} detected, {} & {}", id, lhs.toString(), rhs.toString())
}
return lhs
}
}
//*/
@@ -0,0 +1,9 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
@Suppress("unused")
class UniMixinsExtender : Plugin<Project> {
override fun apply(project: Project) {
project.extensions.create("unimixins", UniMixinsExtension::class.java)
}
}
@@ -0,0 +1,6 @@
import org.gradle.api.provider.Property
interface UniMixinsExtension {
val uniMixVersion: Property<String>
val fmlCorePlugin: Property<String?>
}
@@ -0,0 +1,204 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.palantir.gradle.gitversion.GitVersionCacheService
import org.apache.tools.ant.filters.ReplaceTokens
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.ConfigurationVariantDetails
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.plugins.BasePluginExtension
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.jvm.tasks.Jar
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.language.jvm.tasks.ProcessResources
import xyz.wagyourtail.unimined.api.UniminedExtension
import java.io.File
@Suppress("unused")
class UniMixinsPlugin : Plugin<Project> {
override fun apply(project: Project) {
val plugins = project.plugins
plugins.apply("java")
plugins.apply("xyz.wagyourtail.unimined")
plugins.apply("com.palantir.git-version")
plugins.apply("com.gradleup.shadow")
val minecraftVersion = "1.7.10"
val forgeVersion = "10.13.4.1614-1.7.10"
val extensions = project.extensions
extensions.getByType(JavaPluginExtension::class.java).withSourcesJar()
val unimixins = extensions.getByType(UniMixinsExtension::class.java)
extensions.configure<JavaPluginExtension>("java") {
it.sourceCompatibility = JavaVersion.VERSION_1_8
it.targetCompatibility = JavaVersion.VERSION_1_8
it.toolchain {
it.languageVersion.set(JavaLanguageVersion.of(8))
}
}
project.dependencies.add("compileOnly", "net.minecraftforge:forge:1.12.2-14.23.5.2860:universal")
val gitVersion = GitVersionCacheService
.getSharedGitVersionCacheService(project)
.get()
val versionDetails = gitVersion
.getVersionDetails(project.projectDir, null)
project.version = getUniMixinsVersion(gitVersion, project)
project.group = "io.github.legacymoddingmc"
val nameSuffix = if (project.name == "all") "" else "-${project.name}"
extensions.configure<BasePluginExtension>("base") {
it.archivesName.set("+unimixins$nameSuffix-1.7.10")
}
val sourceSets = extensions.getByName("sourceSets") as SourceSetContainer
val generated = sourceSets.create("generated")
val genDir = project.layout.buildDirectory.file("genResources")
generated.resources.srcDir(genDir)
val tasks = project.tasks
val generateEmbeddedCorePluginFile = tasks.register("generateEmbeddedCorePluginFile") {
it.doLast {
val fmlCorePlugin = unimixins.fmlCorePlugin.orNull
if (fmlCorePlugin != null) {
val dir = File(genDir.get().asFile, "META-INF")
dir.mkdirs()
val embeddedFile = File(dir, "EmbeddedFMLCorePlugins.txt")
embeddedFile.writeText(fmlCorePlugin)
}
}
}
tasks.named("processResources", ProcessResources::class.java) { task ->
task.dependsOn(generateEmbeddedCorePluginFile)
task.filesMatching("mcmod.info") { copy ->
copy.filter(mapOf("tokens" to mapOf(
"minecraftVersion" to minecraftVersion,
"uniMixinsVersion" to project.version.toString(),
"projectUrl" to "https://github.com/LegacyModdingMC/UniMixins")),
ReplaceTokens::class.java)
}
}
val cfgs = project.configurations
val shadowImplementation = cfgs.maybeCreate("shadowImplementation")
val shadowImplSources = cfgs.maybeCreate("shadowImplSources")
val shadowSources = cfgs.maybeCreate("shadowSources")
for (cfg in listOf(shadowImplementation, shadowImplSources)) {
cfg.isCanBeConsumed = false
cfg.isCanBeResolved = true
}
shadowImplementation.extendsFrom(shadowImplSources)
for (config in listOf("compileClasspath", "runtimeClasspath", "testCompileClasspath", "testRuntimeClasspath")) {
cfgs.getByName(config).extendsFrom(shadowImplementation)
}
// Add the sources from the dual set...
shadowSources.dependencies.addAllLater(project.provider {
shadowImplSources.dependencies.map {
if (it is ProjectDependency) {
project.dependencies.project(mapOf(
"path" to it.path,
"configuration" to "sourcesElements"))
} else {
project.dependencies.create("${it.group}:${it.name}:${it.version}:sources")
}
}
})
// ...and copy the files into the source jar
val sourcesJar = tasks.named("sourcesJar", Jar::class.java)
sourcesJar.configure {
it.duplicatesStrategy = DuplicatesStrategy.EXCLUDE
it.dependsOn(shadowSources)
it.from(shadowSources.map { source ->
project.zipTree(source)
})
}
val shadowJar = tasks.named("shadowJar", ShadowJar::class.java)
shadowJar.configure { sJar ->
sJar.from(generated.resources)
sJar.configurations = listOf(shadowImplementation)
sJar.archiveClassifier.set("dev")
sJar.manifest { manifest ->
manifest.attributes(mapOf(
"Commit-ID" to versionDetails.gitHash,
"FMLCorePlugin" to unimixins.fmlCorePlugin.orNull
).filterValues { it != null })
}
// Copy licenses to a folder in META-INF, for the merged jar.
val licenses = listOf("CREDITS", "LICENSE*", "README*")
sJar.from(project.projectDir) {
it.include(licenses); it.into("META-INF/licenses/${project.name}")
}
// And ensure they end up in the root, too.
sJar.from(project.projectDir) { it.include(licenses); it.into("") }
}
for (outgoingConfig in listOf("runtimeElements", "apiElements")) {
val outgoing = cfgs.getByName(outgoingConfig)
outgoing.outgoing.artifacts.clear()
outgoing.outgoing.artifact(shadowJar)
}
tasks.named("jar", Jar::class.java).configure { jar ->
jar.archiveClassifier.set("dev-preshadow")
}
val shadowRuntimeElements = cfgs.getByName("shadowRuntimeElements")
val javaComponent = project.components.named("java").get() as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(shadowRuntimeElements, ConfigurationVariantDetails::skip)
extensions.configure<UniminedExtension>("unimined") { unimined ->
unimined.minecraft(sourceSets.getByName("main"), true) {
version = minecraftVersion
defaultRemapJar = false
defaultRemapSourcesJar = false
mappings {
searge()
mcp("stable", "12-1.7.10")
}
minecraftForge {
loader(forgeVersion)
}
val remapJar = remap(tasks.getByName("shadowJar")) {
prodNamespace("searge")
}
tasks.named("assemble").configure { assemble ->
assemble.dependsOn(remapJar)
}
}
}
}
private fun getUniMixinsVersion(versionCacheService: GitVersionCacheService, project: Project): String {
val override = System.getenv("VERSION")
if (override != null) {
println("VERSION set! Overriding version to $override")
return override
}
return versionCacheService.getGitVersion(project.projectDir, null)
}
}
+75
View File
@@ -0,0 +1,75 @@
import org.apache.tools.ant.filters.ReplaceTokens
plugins {
id("unimixins")
}
dependencies {
// TODO: make this work
shadowImplementation(project(":mixin"))
shadowImplSources(project(":compat"))
shadowImplSources(project(":mixingasm"))
shadowImplSources(project(":spongemixins"))
shadowImplSources(project(":mixinbooterlegacy"))
shadowImplSources(project(":gasstation"))
shadowImplSources(project(":gtnhmixins"))
shadowImplSources(project(":mixinextras"))
}
val moduleList =
"\\nMixin," +
"Compat," +
"Mixingasm," +
"SpongeMixins," +
"MixinBooterLegacy," +
"GasStation," +
"GTNHMixins, and" +
"MixinExtras."
tasks.processResources {
files("mcmod.info") {
filter<ReplaceTokens>("tokens" to mapOf(
"moduleList" to moduleList
))
}
}
tasks.shadowJar {
// Exclude errant license files
exclude("LICENSE*")
exclude("README.original.md")
// Merge mcmod.info files
transform(McmodInfoMerger("unimixins"))
// Merge list of coremods
append("META-INF/EmbeddedFMLCorePlugins.txt")
// Merge service files
mergeServiceFiles()
// Only keep the manifest from this jar
files("META-INF/MANIFEST.MF") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
manifest {
attributes(
"TweakClass" to "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
// Manually set this, because it doesn't need to be embedded
"FMLCorePlugin" to "io.github.legacymoddingmc.unimixins.all.AllCore",
"MixinConfigs" to "mixins.gtnhmixins.json,mixins.gasstation.json,mixins.gtnhmixins.json,mixingasm.mixin.json",
"Premain-Class" to "org.spongepowered.tools.agent.MixinAgent",
"Agent-Class" to "org.spongepowered.tools.agent.MixinAgent",
"Can-Redefine-Classes" to true,
"Can-Retransform-Classes" to true,
"Implementation-Version" to unimixins.uniMixVersion.get()
)
}
}
unimined.minecraft {
}
@@ -0,0 +1,110 @@
package io.github.legacymoddingmc.unimixins.all;
import java.net.URL;
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;
@MCVersion("1.7.10")
public class AllCore implements IFMLLoadingPlugin {
public static final Logger LOGGER = LogManager.getLogger("unimixins");
private static final List<Class<?>> embeddedCorePluginClasses = new ArrayList<>();
private static final List<IFMLLoadingPlugin> embeddedCorePluginInstances = new ArrayList<>();
private static final URL embeddedCorePluginsFile = AllCore.class.getResource("/META-INF/EmbeddedFMLCorePlugins.txt");
static {
try {
// The file contains a duplicate, and I can't be bothered to remove it at build time.
final HashSet<String> embeddedPlugins = (embeddedCorePluginsFile == null)
? new HashSet<>()
: new HashSet<>(Arrays.asList(IOUtils.toString(embeddedCorePluginsFile).split("\n")));
for (String s : embeddedPlugins) {
Class<?> cls = Class.forName(s);
embeddedCorePluginClasses.add(cls);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public AllCore() {
LOGGER.info("Instantiating AllCore");
for (Class<?> cls : embeddedCorePluginClasses) {
try {
embeddedCorePluginInstances.add((IFMLLoadingPlugin) cls.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Override
public String[] getASMTransformerClass() {
List<String> classes = new ArrayList<>();
for (IFMLLoadingPlugin p : embeddedCorePluginInstances) {
Collections.addAll(classes, p.getASMTransformerClass());
}
return classes.toArray(new String[0]);
}
@Override
public String getModContainerClass() {
return null;
}
@Override
public String getSetupClass() {
return null;
}
@Override
public void injectData(Map<String, Object> data) {
for (IFMLLoadingPlugin p : embeddedCorePluginInstances) {
p.injectData(data);
}
}
@Override
public String getAccessTransformerClass() {
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,7 +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 = Tags.VERSION, acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = "unimixins", version = Tags.VERSION, acceptableRemoteVersions = "*")
@Mod(modid = "unimixins", useMetadata = true, acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = "unimixins", useMetadata = true, acceptableRemoteVersions = "*")
public class AllModule {
}
File renamed without changes.
+11
View File
@@ -0,0 +1,11 @@
[
{
"modid": "unimixins",
"name": "UniMixins",
"description": "UniMixins composite jar consisting of the following modules:@moduleList@",
"version": "@uniMixinsVersion@",
"mcversion": "1.7.10",
"url": "@projectUrl@",
"authorList": ["makamys"]
}
]
-94
View File
@@ -1,94 +0,0 @@
/** The root of the build. Exposed for flexibility, but you shouldn't edit it
unless you have to. Edit project.gradle instead. */
buildscript {
repositories {
mavenCentral()
maven {
name = "forge"
url = "https://maven.minecraftforge.net/"
}
maven {
url = "https://jitpack.io"
}
}
}
plugins {
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id("java-library")
id("maven-publish")
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7"
id("eclipse")
id("com.gtnewhorizons.retrofuturagradle") version "1.3.19"
}
allprojects {
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'maven-publish'
// For some reason this is needed when using Gradle 6.9 (but not if using 4.4.1)
repositories {
mavenLocal()
maven {
name = "forge"
url = "https://maven.minecraftforge.net/"
}
maven {
name = 'sponge'
url = 'https://repo.spongepowered.org/maven/'
}
maven {
url = "https://mvn.falsepattern.com/releases"
}
maven {
name = "GTNH Maven"
url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/"
allowInsecureProtocol = true
}
maven {
url 'https://jitpack.io'
}
}
apply from: "${project.rootDir}/buildscript/forge-1.7.gradle"
dependencies {
// TODO only include IFMLLoadingPlugin, Mod and ComparableVersion
compileOnly "net.minecraftforge:forge:1.12.2-14.23.5.2860:universal"
}
minecraft.injectedTags.put("VERSION", project.version)
if(project.name.startsWith("module-") && project.name != "module-mixin" && project.name != "module-common") {
afterEvaluate {
artifacts {
archives tasks."sourcesJar"
archives jar.enabled ? jar : shadowJar
}
publishing {
publications {
create("maven", MavenPublication) {
artifact reobfJar
artifact source: tasks."sourcesJar", classifier: 'sources'
artifact source: jar.enabled ? jar : shadowJar, classifier: 'dev'
artifactId = archivesBaseName.substring(1)
version = jar.archiveVersion.get()
}
}
}
}
}
// Put license, credits and readme in jar
delete "$projectDir/build/tmp/license"
copy {
from "$projectDir"
into "$projectDir/build/tmp/license"
include "CREDITS", "LICENSE*", "README*"
}
sourceSets.main.resources.srcDir("build/tmp/license")
}
+14
View File
@@ -0,0 +1,14 @@
// The previous buildscript was spaghetti
// Time will tell if I do better.
plugins {
id("unimixins") apply false
}
// See buildSrc/src/main/kotlin/UniMixinsPlugin for shared config logic.
subprojects {
apply(plugin = "unimixinsConfig")
configure<UniMixinsExtension> {
uniMixVersion = "0.15.3+mixin.0.8.7"
}
}
-98
View File
@@ -1,98 +0,0 @@
/** Common code for Forge 1.7.10 builds */
apply plugin: "com.gtnewhorizons.retrofuturagradle"
ext.publishDir = project.multiproject_structure.toBoolean() ? "${projectDir}/../publish" : "${rootDir}/publish"
def runCommand(cmd) {
def commitHashProc = cmd.execute(null, file("${projectDir}"))
commitHashProc.waitFor()
if(commitHashProc.exitValue() == 0){
def commitHash = commitHashProc.text.trim()
return commitHash
} else {
println commitHashProc.err.text
println(cmd + " exited with non-zero return value")
return null
}
}
def getCommitVersion() {
def ver = null
def versionPath = publishDir + "/version.txt"
if(file(versionPath).isFile()) {
ver = file(versionPath).text
} else {
try {
ver = runCommand("git describe --tags --dirty") ?: "UNKNOWN-" + runCommand("git describe --always --dirty") ?: "UNKNOWN"
} catch(Exception e){
println "Failed to run " + cmd + ": " + e.getMessage()
ver = "UNKNOWN"
}
}
ver = ver.trim()
if(ver.charAt(0) == 'v') {
ver = ver.substring(1)
}
return ver
}
project.version = getCommitVersion()
group = project.group
archivesBaseName = "${project.archives_base}-${project.minecraft_version}"
minecraft {
mcVersion.set("1.7.10")
}
processResources {
// This will ensure that this task is redone when the versions or any
// user-defined properties change.
inputs.property "version", version
inputs.property "mcversion", project.minecraft.version
inputs.properties project.ext.getProperties()
filesMatching('*.info') {
expand project.properties
}
}
// Ensures that the encoding of source files is set to UTF-8, see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
// Add git commit hash to MANIFEST.MF
def getCommitHash(){
try {
def commitHashProc = "git describe --always --dirty".execute()
commitHashProc.waitFor()
if(commitHashProc.exitValue() == 0){
def commitHash = commitHashProc.text.trim()
return commitHash
} else {
println commitHashProc.err.text
throw new Exception("git describe exited with non-zero return value")
}
} catch(Exception e){
println "Failed to get commit version: " + e.getMessage()
}
return "UNKNOWN" // fallback
}
jar {
manifest {
attributes (
'Commit-ID': getCommitHash(),
)
}
}
File renamed without changes.
+7
View File
@@ -0,0 +1,7 @@
plugins {
id("unimixins")
}
unimined.minecraft {
}
File renamed without changes.
+30
View File
@@ -0,0 +1,30 @@
unimixins {
fmlCorePlugin = "io.github.legacymoddingmc.unimixins.compat.CompatCore"
}
plugins {
id("unimixins")
}
dependencies {
compileOnly("org.spongepowered:mixin:0.8.5")
shadowImplementation(project(":common")) {
isTransitive = false
}
}
tasks.shadowJar {
relocate("io.github.legacymoddingmc.unimixins.common", "io.github.legacymoddingmc.unimixins.compat.repackage.common")
manifest {
attributes (
"TweakClass" to "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
)
}
}
unimined.minecraft {
}
@@ -7,6 +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 = "Provide the deprecated `com.gtnewhorizons.mixinextras` relocation of MixinExtras 0.1.1. May be required by some older mods.", cat = "compat")
public static boolean enableLegacyGTNHMixinExtrasPackage;
@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;
}
@@ -0,0 +1,125 @@
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.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;
@MCVersion("1.7.10")
public class CompatCore implements IFMLLoadingPlugin {
public static final Logger LOGGER = LogManager.getLogger("unimixins");
public CompatCore() {
LOGGER.info("Instantiating CompatCore");
ConfigUtil.load(CompatConfig.class);
if(CompatConfig.enableRemapper) {
// We register the transformer this way to register it as early as possible.
Launch.classLoader.registerTransformer(relativeClassName("asm.ASMRemapperTransformer"));
}
}
@Override
public String[] getASMTransformerClass() {
List<String> classes = new ArrayList<>();
if(CompatConfig.enhanceCrashReports) {
classes.add("io.github.legacymoddingmc.unimixins.compat.asm.EnhanceCrashReportsTransformer");
}
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]);
}
private static String relativeClassName(String relName) {
String name = CompatCore.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;
}
/**
* <p>This is the earliest point after the Mixin environment's initialization where we can inject code.
* <p>We register our error handler here.
*/
@Override
public void injectData(Map<String, Object> data) {
if(CompatConfig.enhanceCrashReports) {
Mixins.registerErrorHandlerClass("io.github.legacymoddingmc.unimixins.compat.MixinErrorHandler");
}
}
@Override
public String getAccessTransformerClass() {
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;
}
}
}
@@ -0,0 +1,11 @@
package io.github.legacymoddingmc.unimixins.compat;
import cpw.mods.fml.common.Mod;
/**
* This is only here to help Forge detect the mod.
*/
@Mod(modid = "unimixins-compat", useMetadata = true, acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = "unimixins-compat", useMetadata = true, 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 {
}
@@ -0,0 +1,187 @@
package io.github.legacymoddingmc.unimixins.compat.asm;
import static io.github.legacymoddingmc.unimixins.compat.CompatCore.LOGGER;
import com.google.common.primitives.Bytes;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import org.apache.commons.lang3.StringUtils;
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>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 {
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(
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;
private static List<byte[]> wrongASMPackagePrefixesRaw;
private static List<String> wrongASMPackagePrefixes;
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (basicClass == null) {
return null;
}
if (transformedName.startsWith("io.github.legacymoddingmc.unimixins.compat.asm.")
|| transformedName.startsWith("com.google.")
|| transformedName.startsWith("org.apache.")
|| transformedName.startsWith("org.objectweb.asm.")
) return basicClass;
boolean foundWrongAsm = containsAnyPattern(basicClass, getWrongASMPackagePrefixesRaw());
if (!foundWrongAsm) return basicClass;
// Remap if we've found shaded ASM
boolean doRemap = containsAnyPattern(basicClass, SHADED_ASM_PACKAGE_PREFIXES_RAW);
if (!doRemap) {
ClassNode classNode = new ClassNode();
ClassReader classReaderForNode = new ClassReader(basicClass);
classReaderForNode.accept(classNode, 0);
if (classNode.interfaces != null) {
for (Object itf : classNode.interfaces) {
if (itf.equals("org/spongepowered/asm/mixin/extensibility/IMixinConfigPlugin")) {
doRemap = true;
break;
}
}
}
if (!doRemap) {
if (classNode.visibleAnnotations != null) {
for (Object o : classNode.visibleAnnotations) {
final AnnotationNode ann = (AnnotationNode) o;
if (ann.desc.equals("Lio/github/legacymoddingmc/unimixins/compat/api/RemapASMForMixin;")) {
doRemap = true;
break;
}
}
}
}
}
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);
classReader.accept(remapAdapter, ClassReader.EXPAND_FRAMES);
basicClass = classWriter.toByteArray();
}
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 {
ClassReader cr = new ClassReader(Launch.classLoader.getClassBytes("org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin"));
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
for (Object o : cn.methods) {
final MethodNode m = (MethodNode) o;
if (m.name.equals("preApply")) {
int classNodeDescStart = StringUtils.ordinalIndexOf(m.desc, "L", 2);
int classNodeDescEnd = StringUtils.ordinalIndexOf(m.desc, "L", 3);
String classNodeName = m.desc.substring(classNodeDescStart + 1, classNodeDescEnd - 1);
realASMPackagePrefix = classNodeName.substring(0, classNodeName.indexOf("tree/ClassNode"));
break;
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Failed to determine real package name Mixin's shaded ASM.");
} finally {
if (realASMPackagePrefix == null) {
realASMPackagePrefix = "UNKNOWN";
}
LOGGER.debug("Resolved real package prefix to: " + realASMPackagePrefix);
}
}
return realASMPackagePrefix;
}
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);
}
}
private static class SpongepoweredASMRemapper extends Remapper {
public static final Remapper INSTANCE = new SpongepoweredASMRemapper();
@Override
public String map(String typeName) {
for (String s : ASM_PACKAGE_PREFIXES) {
if (typeName.startsWith(s)) {
return ASMRemapperTransformer.getRealASMPackagePrefix() + typeName.substring(s.length());
}
}
return super.map(typeName);
}
}
}
@@ -15,12 +15,12 @@ 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;
if (basicClass == null) return null;
if(name.equals("cpw.mods.fml.common.FMLCommonHandler")) {
if (name.equals("cpw.mods.fml.common.FMLCommonHandler")) {
return transformFMLCommonHandler(basicClass);
}
return basicClass;
@@ -34,7 +34,7 @@ public class FMLCommonHandlerTransformer implements IClassTransformer {
* {
* category.addCrashSectionCallable(call.getLabel(), call);
* }
* + FMLCommonHandlerTransformer.Hooks.postEnhanceCrashReport();
* + EnhanceCrashReportsTransformer.Hooks.postEnhanceCrashReport();
* }
* </pre>
*/
@@ -44,28 +44,30 @@ public class FMLCommonHandlerTransformer implements IClassTransformer {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
for(MethodNode m : classNode.methods) {
for (Object o : classNode.methods) {
final MethodNode m = (MethodNode) o;
if (m.name.equals("enhanceCrashReport")) {
AbstractInsnNode injectionTarget = null;
for(int i = 0; i < m.instructions.size(); i++) {
for (int i = 0; i < m.instructions.size(); i++) {
AbstractInsnNode ain = m.instructions.get(i);
if(ain instanceof InsnNode) {
if (ain instanceof InsnNode) {
InsnNode in = (InsnNode)ain;
if(in.getOpcode() == RETURN) {
if (in.getOpcode() == RETURN) {
injectionTarget = in;
break;
}
}
}
if(injectionTarget != null) {
if (injectionTarget != null) {
InsnList inject = new InsnList();
//ALOAD crashReport
inject.add(new VarInsnNode(ALOAD, 1));
//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,38 +17,40 @@ 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) {
if(basicClass == null) {
if (basicClass == null) {
return null;
}
if(transformedName.startsWith("org.objectweb.asm.")) return basicClass;
if (transformedName.startsWith("org.objectweb.asm.")) return basicClass;
if(transformedName.equals("cpw.mods.fml.common.discovery.ModDiscoverer")) {
if (transformedName.equals("cpw.mods.fml.common.discovery.ModDiscoverer")) {
basicClass = doTransformModDiscoverer(basicClass);
}
return basicClass;
}
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();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
for(MethodNode m : classNode.methods) {
if(m.name.equals("findClasspathMods")) {
Iterator<AbstractInsnNode> it = m.instructions.iterator();
for (Object o : classNode.methods) {
final MethodNode m = (MethodNode) o;
while(it.hasNext()) {
if (m.name.equals("findClasspathMods")) {
@SuppressWarnings("unchecked") Iterator<AbstractInsnNode> it = m.instructions.iterator();
while (it.hasNext()) {
AbstractInsnNode i = it.next();
if(i.getOpcode() == INVOKESTATIC) {
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));
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/compat/asm/HackClasspathModDiscoveryTransformer$Hooks", "redirectGetReparseableCoremods", mi.desc));
it.remove();
break;
}
@@ -57,10 +58,11 @@ public class ModDiscovererTransformer implements IClassTransformer {
}
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
} catch(Exception e) {
} catch (Exception e) {
e.printStackTrace();
}
@@ -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;
@@ -35,7 +29,7 @@ public class ModDiscovererTransformer implements IClassTransformer {
}
private static Set<File> getUniMixinsJavaAgentJars() {
if(uniMixinsJavaAgentJars == null) {
if (uniMixinsJavaAgentJars == null) {
uniMixinsJavaAgentJars = new HashSet<>();
try {
for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
@@ -59,28 +53,30 @@ public class ModDiscovererTransformer implements IClassTransformer {
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if(basicClass == null) {
if (basicClass == null) {
return null;
}
if(transformedName.equals("cpw.mods.fml.common.discovery.ModDiscoverer")) {
if (transformedName.equals("cpw.mods.fml.common.discovery.ModDiscoverer")) {
basicClass = doTransformModDiscoverer(basicClass);
}
return basicClass;
}
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();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
for(MethodNode m : classNode.methods) {
if(m.name.equals("identifyMods")) {
for (Object o : classNode.methods) {
final MethodNode m = (MethodNode) o;
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);
}
}
@@ -101,14 +97,14 @@ public class ModDiscovererTransformer implements IClassTransformer {
List<ModCandidate> candidates = getModCandidates(dis);
Map<File, List<ModCandidate>> modCandidatesByFile = new HashMap<>();
for(ModCandidate mc : candidates) {
for (ModCandidate mc : candidates) {
modCandidatesByFile.computeIfAbsent(getModContainer(mc), x -> new ArrayList<>()).add(mc);
}
for(Map.Entry<File, List<ModCandidate>> e : modCandidatesByFile.entrySet()) {
for (Map.Entry<File, List<ModCandidate>> e : modCandidatesByFile.entrySet()) {
File file = e.getKey();
List<ModCandidate> mcs = e.getValue();
if(getUniMixinsJavaAgentJars().contains(file)) {
if (getUniMixinsJavaAgentJars().contains(file)) {
Iterator<ModCandidate> it = mcs.iterator();
while(mcs.size() > 1 && it.hasNext()) {
ModCandidate mc = it.next();
@@ -131,7 +127,8 @@ public class ModDiscovererTransformer implements IClassTransformer {
private static List<ModCandidate> getModCandidates(ModDiscoverer dis) throws Exception {
Field f = dis.getClass().getDeclaredField("candidates");
f.setAccessible(true);
return (List<ModCandidate>)f.get(dis);
//noinspection unchecked
return (List<ModCandidate>) f.get(dis);
}
private static File getModContainer(ModCandidate mc) throws Exception {
@@ -3,13 +3,11 @@
"modid": "unimixins-compat",
"name": "UniMixins: Compatibility",
"description": "UniMixins module that improves compatibility and helps debug crashes.",
"version": "${version}",
"mcversion": "${minecraft_version}",
"url": "${project_url}",
"version": "@uniMixinsVersion@",
"mcversion": "@minecraftVersion@",
"url": "@projectUrl@",
"updateUrl": "",
"authorList": [
"makamys"
],
"authorList": ["makamys"],
"credits": "",
"logoFile": "",
"screenshots": []
File renamed without changes.
+24
View File
@@ -0,0 +1,24 @@
unimixins {
fmlCorePlugin = "io.github.legacymoddingmc.unimixins.compatfuture.CompatFutureCore"
}
plugins {
id("unimixins")
}
tasks.shadowJar {
configurations = listOf()
relocate("io.github.legacymoddingmc.unimixins.compat.stub.cpw", "cpw")
manifest {
attributes (
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
)
}
}
unimined.minecraft {
}
@@ -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", useMetadata = true, acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = "unimixins-compatfuture", useMetadata = true, acceptableRemoteVersions = "*")
public class CompatFutureModule {
}
@@ -0,0 +1,15 @@
[
{
"modid": "unimixins-compatfuture",
"name": "UniMixins: Future Compatibility",
"description": "UniMixins module that makes the mod usable on 1.8.9 ~ 1.12.2.",
"version": "@uniMixinsVersion@",
"mcversion": "@minecraftVersion@",
"url": "@projectUrl@",
"updateUrl": "",
"authorList": ["makamys"],
"credits": "",
"logoFile": "",
"screenshots": []
}
]
+30 -56
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-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

+1 -1
View File
@@ -57,7 +57,7 @@ All test cases assume default configs for mods.
* [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.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+53
View File
@@ -0,0 +1,53 @@
import org.apache.tools.ant.filters.ReplaceTokens
unimixins {
fmlCorePlugin = "com.falsepattern.gasstation.core.GasStationCore"
}
plugins {
id("unimixins")
}
val gasstationVersion = "0.5.1"
val gasMixVersion = "0.8.5-gasstation_7"
version = "$version+$gasstationVersion"
repositories {
maven {
url = uri("https://mvn.falsepattern.com/releases")
}
}
dependencies {
compileOnly("org.spongepowered:mixin:$gasMixVersion")
compileOnly(project(":mixinbooterlegacy"))
shadow(project(":common")) {
isTransitive = false
}
}
tasks.shadowJar {
configurations = listOf(project.configurations.shadow.get())
relocate("io.github.legacymoddingmc.unimixins.common", "io.github.legacymoddingmc.unimixins.gasstation.repackage.common")
manifest {
attributes (
"TweakClass" to "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
"MixinConfigs" to "mixins.gasstation.json",
)
}
}
tasks.processResources {
files("mcmod.info") {
filter<ReplaceTokens>("tokens" to mapOf(
"gasstationVersion" to gasstationVersion
))
}
}
unimined.minecraft {
}
@@ -3,12 +3,12 @@ package com.falsepattern.gasstation;
import cpw.mods.fml.common.Mod;
@Mod(modid = Tags.MODID,
version = Tags.VERSION,
name = Tags.MODNAME,
useMetadata = true,
acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = Tags.MODID,
version = Tags.VERSION,
name = Tags.MODNAME,
useMetadata = true,
acceptableRemoteVersions = "*")
public class GasStation {
}
@@ -0,0 +1,12 @@
package com.falsepattern.gasstation;
// Use this class for Strings only. Do not import any classes here. It will lead to issues with Mixins if in use!
public class Tags {
// GRADLETOKEN_* will be replaced by your configuration values at build time
public static final String MODID = "gasstation";
public static final String MODNAME = "GasStation";
public static final String VERSION = "GRADLETOKEN_VERSION";
public static final String GROUPNAME = "com.falsepattern.gasstation";
}
@@ -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()) {
@@ -3,13 +3,11 @@
"modid": "gasstation",
"name": "UniMixins: GasStation",
"description": "UniMixins module that provides GasStation extras.\nDepends on: SpongeMixins, MixinBooterLegacy, MixinExtras",
"version": "${extraVersion}+uni.${uniVersion}",
"mcversion": "${mcversion}",
"url": "${project_url}",
"version": "@gasstationVersion@",
"mcversion": "@minecraftVersion@",
"url": "@projectUrl@",
"updateUrl": "",
"authorList": [
"FalsePattern"
],
"authorList": ["FalsePattern"],
"credits": "",
"logoFile": "",
"screenshots": [],
+1 -14
View File
@@ -1,14 +1 @@
# Mod properties
modid=unimixins
archives_base=+unimixins
# http://maven.apache.org/guides/mini/guide-naming-conventions.html
group=io.github.legacymoddingmc.unimixins
# Forge properties
minecraft_version=1.7.10
forge_version=10.13.4.1614-1.7.10
enable_mixin=false
multiproject_structure=false
project_url=https://github.com/LegacyModdingMC/UniMixins
org.gradle.jvmargs = -Xmx2G
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+173 -114
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,105 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
exec "$JAVACMD" "$@"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+10 -7
View File
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,15 +76,17 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:omega
@@ -9,6 +9,7 @@ Modifications:
- 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
File renamed without changes.
File renamed without changes.
+86
View File
@@ -0,0 +1,86 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.apache.tools.ant.filters.ReplaceTokens
unimixins {
fmlCorePlugin = "com.gtnewhorizon.gtnhmixins.core.GTNHMixinsCore"
}
plugins {
id("unimixins")
}
val gtnhMixinsVersion = "2.2.0"
val mixinExtrasVersion = "0.1.1"
val shadowMixinExtras by configurations.creating
repositories {
maven {
name = "GTNH Third-Party Maven"
url = uri("https://nexus.gtnewhorizons.com/repository/thirdparty/")
}
}
dependencies {
compileOnly("org.spongepowered:mixin:0.8.7")
shadow(project(":common")) {
isTransitive = false
}
compileOnly(project(":mixingasm")) {
isTransitive = false
}
compileOnly("com.github.LlamaLad7:MixinExtras:$mixinExtrasVersion")
shadowMixinExtras("com.github.LlamaLad7:MixinExtras:$mixinExtrasVersion")
}
// Create the mixinExtrasJar ShadowJar task
val mixinExtrasJar by tasks.registering(ShadowJar::class) {
destinationDirectory = file("build/tmp")
archiveClassifier = "mixinExtras"
archiveVersion = mixinExtrasVersion
configurations = listOf(shadowMixinExtras)
relocate("com.llamalad7.mixinextras", "com.gtnewhorizon.mixinextras")
relocate("org.objectweb.asm", "org.spongepowered.asm.lib")
}
// Configure the main shadowJar
tasks.shadowJar {
configurations = listOf(project.configurations.shadow.get())
relocate("org.objectweb.asm", "org.spongepowered.asm.lib")
relocate("io.github.legacymoddingmc.unimixins.common", "io.github.legacymoddingmc.unimixins.gtnhmixins.repackage.common")
from(zipTree(mixinExtrasJar.get().archiveFile)) {
eachFile {
if (!path.endsWith(".class")) exclude()
path = "data/legacy_gtnh_mixinextras/" + path.replace(".class", ".klass")
}
}
manifest {
attributes(
mapOf(
"TweakClass" to "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
"MixinConfigs" to "mixins.gtnhmixins.json",
)
)
}
dependsOn(mixinExtrasJar)
}
tasks.processResources {
files("mcmod.info") {
filter<ReplaceTokens>("tokens" to mapOf(
"gtnhMixinsVersion" to gtnhMixinsVersion,
))
}
}
unimined.minecraft {
//replaceIn("GTNHMixins.java")
//replace("GRADLETOKEN_VERSION", extraVersion)
}
@@ -0,0 +1,19 @@
package com.gtnewhorizon.gtnhmixins;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@Mod(modid = GTNHMixins.MODID, name = GTNHMixins.NAME, useMetadata = true, acceptableRemoteVersions = "*")
@net.minecraftforge.fml.common.Mod(modid = GTNHMixins.MODID, name = GTNHMixins.NAME, useMetadata = true, acceptableRemoteVersions = "*")
public class GTNHMixins {
public static final String NAME = "GTNHMixins";
public static final String MODID = "gtnhmixins";
/**
* @deprecated This may not actually reflect the version, use FML methods to detect the version if needed.
*/
@Deprecated
public static final String VERSION = "2.2.0";
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);
}
}
}
@@ -93,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 {
@@ -107,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;
}
@@ -0,0 +1,77 @@
package io.github.legacymoddingmc.unimixins.gtnhmixins;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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;
import org.apache.logging.log4j.Logger;
public class GTNHMixinsModule {
public static final Logger LOGGER = LogManager.getLogger("unimixins-gtnhmixins");
public static void init() {
if(SanityCheckHelper.isEnabled()) {
SanityCheckHelper.warnIfJarPrefixesExist(Arrays.asList("gasstation-", "mixinbooterlegacy-", "spongemixins-"));
checkComponentIntegrity();
}
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 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) {
LOGGER.debug("Initializing MixinExtras");
return true;
} else if(!SanityCheckHelper.isEnabled()){
LOGGER.warn("Skipping MixinExtras because Mixin version (" + mixinVersion + ") is lower than the required (" + requiredVersion + ")");
return false;
} else {
throw new RuntimeException("Cannot load MixinExtras because Mixin version (" + mixinVersion + ") is lower than the required (" + requiredVersion + ")");
}
}
private static void checkComponentIntegrity() {
List<String> missingComponents = new ArrayList<>();
// This is actually redundant; without Mixin, the mod can't even load since its tweaker class is missing
if(!classExists("org.spongepowered.asm.launch.MixinBootstrap")) {
missingComponents.add("Mixin");
}
if(!classExists("ru.timeconqueror.spongemixins.SpongeMixins")) {
missingComponents.add("SpongeMixins");
}
if(!missingComponents.isEmpty()) {
LOGGER.error("The following missing components were detected: " + missingComponents);
LOGGER.error("Please obtain mods which provide them.");
throw new RuntimeException("Missing components detected");
}
}
public static boolean classExists(String string) {
return GTNHMixinsModule.class.getResource("/" + string.replaceAll("\\.", "/") + ".class") != null;
}
}
@@ -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,15 +1,13 @@
[
{
"modid": "${extraModid}",
"modid": "gtnhmixins",
"name": "UniMixins: GTNHMixins",
"description": "UniMixins module that provides GTNHMixins extras and MixinExtras with the GTNH package name.\nDepends on: SpongeMixins",
"version": "${extraVersion}+uni.${uniVersion}",
"mcversion": "${mcversion}",
"url": "${project_url}",
"version": "@gtnhMixinsVersion@",
"mcversion": "@minecraftVersion@",
"url": "@projectUrl@",
"updateUrl": "",
"authorList": [
"mitchej123"
],
"authorList": ["mitchej123"],
"credits": "",
"logoFile": "",
"screenshots": [],
@@ -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"
]
}
}
+193
View File
@@ -0,0 +1,193 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.apache.tools.ant.filters.ReplaceTokens
unimixins {
fmlCorePlugin = "io.github.legacymoddingmc.unimixins.mixin.MixinCore"
}
plugins {
id("unimixins")
}
val versionBase = version.toString()
val spongepoweredMixinVersion = "0.8.7"
val asmVersion = "9.7.1"
repositories {
maven {
name = "GTNH Third-Party Maven"
url = uri("https://nexus.gtnewhorizons.com/repository/thirdparty/")
}
}
val shadowSourcesUniMix: Configuration by configurations.creating
val mixinVersion = unimixins.uniMixVersion.get()
val mixinDep = "io.github.legacymoddingmc:sponge-mixin:$mixinVersion"
val mixinFlavorClassifier = "unimix.${mixinVersion.replace('+', '-')}"
dependencies {
compileOnly("org.spongepowered:mixin:$spongepoweredMixinVersion")
compileOnly(project(":common")) {
isTransitive = false
}
shadowImplementation(project(":common")) {
isTransitive = false
}
shadowImplementation(mixinDep) {
exclude(group = "org.ow2.asm")
}
shadowImplementation("org.ow2.asm:asm-tree:$asmVersion")
shadowImplementation("org.ow2.asm:asm-commons:$asmVersion")
shadowImplementation("org.ow2.asm:asm-util:$asmVersion")
shadowSourcesUniMix("$mixinDep:sources") {
isTransitive = false
}
}
tasks.processResources {
files("mcmod.info") {
filter<ReplaceTokens>("tokens" to mapOf(
"mixinClassifier" to mixinFlavorClassifier,
"version" to "$versionBase+$mixinFlavorClassifier"
))
}
}
// We want to *not* relocate ASM in the bridge classes. So we use a multi-step
// build procedure:
// 1. Create relocated Mixin jar, without the bridge classes
val mixinJarTask = tasks.register<ShadowJar>("mixinJarUniMix", ShadowJar::class) {
destinationDirectory = file("build/tmp")
archiveClassifier = "tmpUnimix"
configurations = listOf(project.configurations.shadowImplementation.get())
relocate("org.objectweb.asm", "org.spongepowered.asm.lib")
relocate("com.google", "org.spongepowered.libraries.com.google")
exclude("org/spongepowered/asm/bridge/RemapperAdapter.class")
exclude("org/spongepowered/asm/bridge/RemapperAdapterFML.class")
// Exclude stuff that's compiled for Java 16
exclude("org/spongepowered/asm/service/modlauncher/*")
exclude("org/spongepowered/asm/launch/MixinTransformationServiceLegacy*")
exclude("org/spongepowered/asm/launch/MixinLaunchPlugin*")
exclude("org/spongepowered/asm/launch/MixinTransformationService*")
exclude("org/spongepowered/asm/launch/platform/container/ContainerHandleModLauncherEx*")
exclude("META-INF/services/cpw.mods.modlauncher.api.ITransformationService")
exclude("META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService")
exclude("**/module-info.class")
// Exclude jar-specific stuff
exclude("META-INF/MANIFEST.MF", "META-INF/maven/**", "META-INF/*.RSA", "META-INF/*.SF")
}
// 2. Create Mixin jar without relocation, with *only* the bridge classes
val bridgeJarTask = tasks.register<ShadowJar>("bridgeJarUniMix", ShadowJar::class) {
destinationDirectory = file("build/tmp")
archiveClassifier = "tmpBridgeUniMix"
configurations = listOf(project.configurations.shadowImplementation.get())
include("org/spongepowered/asm/bridge/*")
}
// 3. Combine the two jars
tasks.shadowJar {
// Clear defaults for the shadow jar
configurations = listOf()
version = "$versionBase+$mixinFlavorClassifier"
from(sourceSets["main"].output)
relocate(
"io.github.legacymoddingmc.unimixins.common",
"io.github.legacymoddingmc.unimixins.mixin.repackage.common"
)
dependsOn(mixinJarTask)
dependsOn(bridgeJarTask)
from(zipTree(mixinJarTask.get().archiveFile).matching {
exclude("module-info.class")
eachFile {
if (path.startsWith("META-INF/services/")) {
@Suppress("NULL_FOR_NONNULL_TYPE")
filter { l ->
if (l.startsWith("org.spongepowered.asm.service.modlauncher."))
return@filter null
else
return@filter l
}
}
}
})
// Copy licenses to modularized path too
from(zipTree(mixinJarTask.get().archiveFile).matching {
include("LICENSE*")
}) {
into("META-INF/licenses/mixin")
}
from(zipTree(bridgeJarTask.get().archiveFile).matching {
include("org/spongepowered/asm/bridge/*")
})
manifest {
attributes(
"TweakClass" to "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePluginContainsFMLMod" to true,
"ForceLoadAsMod" to true,
"Premain-Class" to "org.spongepowered.tools.agent.MixinAgent",
"Agent-Class" to "org.spongepowered.tools.agent.MixinAgent",
"Can-Redefine-Classes" to true,
"Can-Retransform-Classes" to true,
"Implementation-Version" to mixinVersion
)
}
doLast {
delete(mixinJarTask.get().archiveFile)
delete(bridgeJarTask.get().archiveFile)
}
}
val shadowSourcesJarTask = tasks.register<ShadowJar>("shadowSourcesJar", ShadowJar::class) {
from(sourceSets["main"].allSource)
version = "$versionBase+$mixinFlavorClassifier"
archiveClassifier = "sources"
configurations = listOf(shadowSourcesUniMix)
}
tasks.jar {
dependsOn(shadowSourcesJarTask)
dependsOn(tasks.shadowJar)
}
/*if (publishModuleToMaven){
publishing {
publications {
create("maven$_flavor", MavenPublication) {
artifact tasks."shadowJar$_flavor"
artifact tasks."shadowSourcesJar"
artifactId = archivesBaseName.substring(1) + (mixinFlavor == "unimix" ? "" : "-" + mixinFlavor)
groupId = mavenGroupId
}
}
}
}*/
unimined.minecraft {
}
Loaded 100 of 201 files, more files were not shown because too many files have changed in this diff. Show more