mirror of
https://github.com/LegacyModdingMC/UniMixins.git
synced 2026-10-27 06:53:48 +00:00
Compare commits
169
Commits
rfg
...
devastation
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d834475de | ||
|
|
6901315e2e | ||
|
|
50b5b3711b | ||
|
|
c1031c9048 | ||
|
|
8537f8e212 | ||
|
|
110090350c | ||
|
|
0aa57099f1 | ||
|
|
441b41e8b9 | ||
|
|
9c7fb856a3 | ||
|
|
dd04399acd | ||
|
|
da4e4d05ab | ||
|
|
b9f1dba519 | ||
|
|
36389a489a | ||
|
|
ec57ec1909 | ||
|
|
051e7b5079 | ||
|
|
0815f55f52 | ||
|
|
1c48884055 | ||
|
|
de34b41af0 | ||
|
|
5198ed747f | ||
|
|
439defbca4 | ||
|
|
1f15b3ed3c | ||
|
|
830d6815fa | ||
|
|
d8d80a3fc1 | ||
|
|
b25075e52e | ||
|
|
2cc3379211 | ||
|
|
23057cba91 | ||
|
|
caa1053569 | ||
|
|
60969ff650 | ||
|
|
0086944037 | ||
|
|
90dc8f9786 | ||
|
|
697e8a127b | ||
|
|
f9740e6a59 | ||
|
|
a87d3c621c | ||
|
|
d58378153f | ||
|
|
f447a961d0 | ||
|
|
eedb41e273 | ||
|
|
e89272708d | ||
|
|
fb264715c5 | ||
|
|
66c33efa07 | ||
|
|
7815282efc | ||
|
|
aada5bff2e | ||
|
|
47bf297756 | ||
|
|
579256e0d2 | ||
|
|
3aa9962eab | ||
|
|
1060c1d50d | ||
|
|
7a1496c88f | ||
|
|
763020eec6 | ||
|
|
22dc439dfd | ||
|
|
752c66d068 | ||
|
|
124f1b550f | ||
|
|
b9951f7fc6 | ||
|
|
b51a23affb | ||
|
|
2c4830327a | ||
|
|
5c92143878 | ||
|
|
d0b94d165a | ||
|
|
775b6a6a2e | ||
|
|
868a305717 | ||
|
|
c75fdf59f9 | ||
|
|
7f2abaf16c | ||
|
|
bba6fe800e | ||
|
|
01853f27f1 | ||
|
|
454a4736d0 | ||
|
|
74b9393a09 | ||
|
|
d5b9033c4d | ||
|
|
1263d1bb5b | ||
|
|
8f55434547 | ||
|
|
589940109b | ||
|
|
07ca8dbe0f | ||
|
|
091b30b28e | ||
|
|
1c623d7b12 | ||
|
|
e7923da598 | ||
|
|
90f3dcc6f1 | ||
|
|
54424d7e97 | ||
|
|
f36c45e15f | ||
|
|
21735c096e | ||
|
|
9627890f23 | ||
|
|
301a0704cf | ||
|
|
63e3953dc7 | ||
|
|
1eb68f7864 | ||
|
|
6b67057695 | ||
|
|
5fc8e5b76f | ||
|
|
f09aed0390 | ||
|
|
c0b368cd49 | ||
|
|
5fbb40602c | ||
|
|
dff5a9df3f | ||
|
|
0a10e2c099 | ||
|
|
7ba0d6f6d3 | ||
|
|
3fe1269c8b | ||
|
|
6701a1b0d8 | ||
|
|
33277033d1 | ||
|
|
815367896f | ||
|
|
fb4ac22a98 | ||
|
|
ebf46d905d | ||
|
|
e7e38e27ef | ||
|
|
bd9dca59e2 | ||
|
|
752c185fe9 | ||
|
|
0066b48b26 | ||
|
|
7d82258dbf | ||
|
|
689f92eea5 | ||
|
|
3c2198317f | ||
|
|
43042cd98d | ||
|
|
59f4175685 | ||
|
|
cda6dfc35b | ||
|
|
ea3cc3efa9 | ||
|
|
f544ebf226 | ||
|
|
05878bfde1 | ||
|
|
43ac78f2dc | ||
|
|
1cbd6a0ecd | ||
|
|
a97b3ce85c | ||
|
|
56a008ce92 | ||
|
|
02a9a1a10d | ||
|
|
5fbb67e26f | ||
|
|
918a80ae53 | ||
|
|
5788d7ec1e | ||
|
|
e29c36c603 | ||
|
|
aed49ce829 | ||
|
|
39a31c66da | ||
|
|
d2c55ed6e3 | ||
|
|
614e8b9569 | ||
|
|
45d16b96ab | ||
|
|
3563c869b5 | ||
|
|
64a4084138 | ||
|
|
acdd68819f | ||
|
|
0fff377da8 | ||
|
|
1b130b1314 | ||
|
|
608639acf3 | ||
|
|
44f89624b0 | ||
|
|
4f5d454d03 | ||
|
|
bbed619396 | ||
|
|
d66394b2ea | ||
|
|
220d040ebd | ||
|
|
b42622470f | ||
|
|
3bc74ae73d | ||
|
|
839425440e | ||
|
|
c2e86f3aae | ||
|
|
48d55f2b44 | ||
|
|
de08ce459e | ||
|
|
43a764c055 | ||
|
|
dad688c742 | ||
|
|
f524e7de7f | ||
|
|
181924abd1 | ||
|
|
8bc2051af9 | ||
|
|
87e71b1ba3 | ||
|
|
ae12182d30 | ||
|
|
189bf0b5e9 | ||
|
|
6b528532a2 | ||
|
|
062eab7754 | ||
|
|
c053f33017 | ||
|
|
016cf16396 | ||
|
|
9cff9105af | ||
|
|
41aecb728a | ||
|
|
8a8444d7f8 | ||
|
|
cd232ec4a0 | ||
|
|
14e8ce7cb2 | ||
|
|
6c55d33c18 | ||
|
|
fcd416e31b | ||
|
|
fe11aee64c | ||
|
|
d5c96de372 | ||
|
|
798b3fb1c9 | ||
|
|
ee81c389fa | ||
|
|
1237e86768 | ||
|
|
d268a991ad | ||
|
|
f1a63f392d | ||
|
|
7ee32c62d3 | ||
|
|
ddd608a8f8 | ||
|
|
a4bddd8dbf | ||
|
|
a892f6d119 | ||
|
|
58bb4137f0 | ||
|
|
28b93dd4f7 |
No files matched your search
@@ -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
|
||||
@@ -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)"
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -1,8 +1,8 @@
|
||||
[](https://github.com/LegacyModdingMC/UniMixins/releases)
|
||||
[](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
|
||||
[](https://www.curseforge.com/minecraft/mc-mods/unimixins)
|
||||
[](https://modrinth.com/mod/unimixins)
|
||||
[](https://discord.gg/AJxEFs6YBN)
|
||||
[](https://github.com/LegacyModdingMC/UniMixins/releases)
|
||||
[](https://makamys.github.io/docs/CI-Downloads/CI-Downloads.html)
|
||||
[](https://legacy.curseforge.com/minecraft/mc-mods/unimixins)
|
||||
[](https://modrinth.com/mod/unimixins)
|
||||
[](https://discord.gg/AJxEFs6YBN)
|
||||
|
||||
# UniMixins
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.gradle
|
||||
.kotlin
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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.
@@ -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"]
|
||||
}
|
||||
]
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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.
@@ -0,0 +1,7 @@
|
||||
plugins {
|
||||
id("unimixins")
|
||||
}
|
||||
|
||||
unimined.minecraft {
|
||||
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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 {
|
||||
|
||||
}
|
||||
+2
-2
@@ -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 {
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
+16
@@ -0,0 +1,16 @@
|
||||
package io.github.legacymoddingmc.unimixins.compat.api;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** <p>Decorate your class with this annotation to make UniMixins remap references to <code>org.objectweb.asm</code> to
|
||||
* the ASM package name used by the current Mixin environment.</p>
|
||||
* <p>This is needed if you have a mixin config plugin compiled against this package name, and you want to pass the
|
||||
* ClassNode reference to a different class, since otherwise UniMixins only remaps references inside the mixin
|
||||
* config plugin class.</p> */
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface RemapASMForMixin {
|
||||
}
|
||||
+187
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-10
@@ -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);
|
||||
}
|
||||
}
|
||||
+18
-16
@@ -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();
|
||||
}
|
||||
|
||||
+15
-18
@@ -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.
@@ -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 {
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.github.legacymoddingmc.unimixins.compatfuture;
|
||||
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is only here so Forge puts the mod on the classpath during coremod loading.
|
||||
*/
|
||||
public class CompatFutureCore implements IFMLLoadingPlugin {
|
||||
@Override
|
||||
public String[] getASMTransformerClass() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModContainerClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSetupClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package io.github.legacymoddingmc.unimixins.compatfuture;
|
||||
|
||||
import cpw.mods.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* This is only here to help Forge detect the mod.
|
||||
*/
|
||||
@Mod(modid = "unimixins-compatfuture", useMetadata = true, acceptableRemoteVersions = "*")
|
||||
@net.minecraftforge.fml.common.Mod(modid = "unimixins-compatfuture", useMetadata = true, acceptableRemoteVersions = "*")
|
||||
public class CompatFutureModule {
|
||||
}
|
||||
File renamed without changes.
@@ -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
@@ -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 |
@@ -0,0 +1,712 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="272mm"
|
||||
height="98.300003mm"
|
||||
viewBox="0 0 272 98.300003"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="modularity.svg"
|
||||
inkscape:export-filename="modularity.png"
|
||||
inkscape:export-xdpi="300"
|
||||
inkscape:export-ydpi="300"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
height="9.83cm"
|
||||
inkscape:zoom="1.8116734"
|
||||
inkscape:cx="707.08107"
|
||||
inkscape:cy="100.45961"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="false" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<pattern
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Strips1_4"
|
||||
id="pattern73765"
|
||||
patternTransform="matrix(-0.41147911,-0.41147911,2.1055851,-2.1055851,28.02852,-37.612396)" />
|
||||
<pattern
|
||||
inkscape:collect="always"
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="5"
|
||||
height="1"
|
||||
patternTransform="translate(0,0) scale(10,10)"
|
||||
id="Strips1_4"
|
||||
inkscape:stockid="Stripes 1:4"
|
||||
inkscape:isstock="true">
|
||||
<rect
|
||||
style="fill:black;stroke:none"
|
||||
x="0"
|
||||
y="-0.5"
|
||||
width="1"
|
||||
height="2"
|
||||
id="rect2974" />
|
||||
</pattern>
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="217.25429"
|
||||
height="52.39732"
|
||||
id="rect6184" />
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Duochrome"
|
||||
id="filter75351"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1">
|
||||
<feColorMatrix
|
||||
type="luminanceToAlpha"
|
||||
result="colormatrix1"
|
||||
id="feColorMatrix75331" />
|
||||
<feFlood
|
||||
flood-opacity="0.501961"
|
||||
flood-color="rgb(229,229,229)"
|
||||
result="flood1"
|
||||
id="feFlood75333" />
|
||||
<feComposite
|
||||
in2="colormatrix1"
|
||||
operator="out"
|
||||
result="composite1"
|
||||
id="feComposite75335" />
|
||||
<feFlood
|
||||
flood-opacity="1"
|
||||
flood-color="rgb(255,255,0)"
|
||||
result="flood2"
|
||||
id="feFlood75337" />
|
||||
<feComposite
|
||||
in2="colormatrix1"
|
||||
result="composite2"
|
||||
operator="in"
|
||||
id="feComposite75339" />
|
||||
<feComposite
|
||||
in="composite2"
|
||||
in2="composite1"
|
||||
k2="1"
|
||||
k3="1"
|
||||
operator="arithmetic"
|
||||
result="composite3"
|
||||
id="feComposite75341"
|
||||
k1="0"
|
||||
k4="0" />
|
||||
<feColorMatrix
|
||||
in="composite3"
|
||||
type="matrix"
|
||||
values="2 -1 0 0 0 0 2 -1 0 0 -1 0 2 0 0 0 0 0 1 0 "
|
||||
result="colormatrix2"
|
||||
id="feColorMatrix75343" />
|
||||
<feComposite
|
||||
in="colormatrix2"
|
||||
in2="composite3"
|
||||
operator="arithmetic"
|
||||
k2="0"
|
||||
result="composite4"
|
||||
id="feComposite75345"
|
||||
k1="0"
|
||||
k3="0"
|
||||
k4="0" />
|
||||
<feBlend
|
||||
in="composite4"
|
||||
in2="composite3"
|
||||
mode="normal"
|
||||
result="blend"
|
||||
id="feBlend75347" />
|
||||
<feComposite
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
id="feComposite75349" />
|
||||
</filter>
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="191.31142"
|
||||
height="45.221634"
|
||||
id="rect6184-8" />
|
||||
<rect
|
||||
x="67.893028"
|
||||
y="19.871132"
|
||||
width="322.4542"
|
||||
height="53.027752"
|
||||
id="rect6184-8-4" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7"
|
||||
width="63.608315"
|
||||
height="8.1022758"
|
||||
x="13.800014"
|
||||
y="46.707821" />
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="36.178707"
|
||||
y="59.424469" />
|
||||
<rect
|
||||
style="display:inline;fill:url(#pattern73765);fill-opacity:1;stroke:none;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter75351);stop-color:#000000"
|
||||
id="rect1104-0-0"
|
||||
width="21.420921"
|
||||
height="8.0959282"
|
||||
x="34.857468"
|
||||
y="46.708447"
|
||||
ry="0" />
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-5"
|
||||
width="21.420921"
|
||||
height="8.0959272"
|
||||
x="34.857468"
|
||||
y="46.708447" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,0.12802956,1.2560112)"
|
||||
id="text6182"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.5px;white-space:pre;shape-inside:url(#rect6184);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="73.532947"
|
||||
y="35.357673"
|
||||
id="tspan326524">EXISTING MIXIN LOADERS
|
||||
</tspan><tspan
|
||||
x="106.52431"
|
||||
y="57.757637"
|
||||
id="tspan326526">ARE MONOLITHIC.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,90.941647,2.4661355)"
|
||||
id="text6182-6"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:21.3333px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.5px;white-space:pre;shape-inside:url(#rect6184-8);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="70.094129"
|
||||
y="37.491004"
|
||||
id="tspan326528">UNIMIXINS IS MODULAR.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,166.16598,1.3341978)"
|
||||
id="text6182-6-7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.3333px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script Bold';text-align:center;letter-spacing:-0.6px;white-space:pre;shape-inside:url(#rect6184-8-4);display:inline;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="80.298035"
|
||||
y="0"><tspan
|
||||
x="90.91602"
|
||||
y="35.357673"
|
||||
id="tspan326532"><tspan
|
||||
style="font-weight:normal;-inkscape-font-specification:'xkcd Script'"
|
||||
id="tspan326530">UNIMIXINS MODULES CAN EVEN BE </tspan></tspan><tspan
|
||||
x="72.625018"
|
||||
y="57.757637"
|
||||
id="tspan326536"><tspan
|
||||
style="font-weight:normal;-inkscape-font-specification:'xkcd Script'"
|
||||
id="tspan326534">ADDED ON TOP OF ANOTHER LOADER.</tspan></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.185208px;text-anchor:middle;white-space:pre;inline-size:82.321;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="44.71722"
|
||||
y="24.065899"
|
||||
id="text32884"
|
||||
transform="translate(0.52916667,1.5875)"><tspan
|
||||
x="44.71722"
|
||||
y="24.065899"
|
||||
id="tspan326538">THEY CANNOT BE LOADED AT THE SAME TIME DUE TO<tspan
|
||||
y="24.065899"
|
||||
id="tspan326540"> </tspan></tspan><tspan
|
||||
x="44.71722"
|
||||
y="27.770067"
|
||||
id="tspan326542">FEATURE OVERLAP, EVEN THOUGH THEIR INDIVIDUAL FEATURES<tspan
|
||||
y="27.770067"
|
||||
id="tspan326544"> </tspan></tspan><tspan
|
||||
x="44.71722"
|
||||
y="31.474235"
|
||||
id="tspan326546">WOULD BE ABLE TO CO-EXIST.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52778px;line-height:1.05;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.132292px;text-anchor:middle;white-space:pre;inline-size:89.1681;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="134.89743"
|
||||
y="23.701571"
|
||||
id="text32884-1"
|
||||
transform="translate(0,1.0583333)"><tspan
|
||||
x="134.89743"
|
||||
y="23.701571"
|
||||
id="tspan326548">EACH FEATURE IS IN ITS OWN "BOX", ALLOWING THEM TO BE<tspan
|
||||
y="23.701571"
|
||||
id="tspan326550"> </tspan></tspan><tspan
|
||||
x="134.89743"
|
||||
y="27.405738"
|
||||
id="tspan326552">COMBINED FREELY WITHOUT ANY ARBITRARY RESTRICTIONS.</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.89278px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;letter-spacing:-0.132292px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="225.63924"
|
||||
y="24.60577"
|
||||
id="text32884-1-9"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.89278px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';text-align:center;text-anchor:middle;stroke-width:0.264583"
|
||||
x="225.57309"
|
||||
y="24.60577"
|
||||
id="tspan116154-7">(THIS KIND OF SUPPORT IS NOT FULLY IMPLEMENTED THOUGH.)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#3f48cc;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="23.71513"
|
||||
y="42.778732"
|
||||
id="text63580"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#3f48cc;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.71513"
|
||||
y="42.778732">GTNHMIXINS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="27.273415"
|
||||
y="50.070621"
|
||||
id="text63580-6"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="27.273415"
|
||||
y="50.070621"
|
||||
id="tspan76477">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="27.233727"
|
||||
y="53.160957"
|
||||
id="tspan189479">0.8-GTNH</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="45.815434"
|
||||
y="62.721596"
|
||||
id="text63580-6-89"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="45.815434"
|
||||
y="62.721596"
|
||||
id="tspan104620">SPONGEMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="45.775745"
|
||||
y="65.811935"
|
||||
id="tspan199017">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="13.745136"
|
||||
y="72.354515" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="23.381863"
|
||||
y="75.724663"
|
||||
id="text63580-6-89-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.381863"
|
||||
y="75.724663"
|
||||
id="tspan105830">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="23.342175"
|
||||
y="78.815002"
|
||||
id="tspan195563">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="58.160408"
|
||||
y="72.281502" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="67.79715"
|
||||
y="75.72467"
|
||||
id="text63580-6-89-5-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="67.79715"
|
||||
y="75.72467"
|
||||
id="tspan106818">GASSTATION</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="67.757462"
|
||||
y="78.81501"
|
||||
id="tspan197827">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="display:inline;fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16634"
|
||||
y="38.274223" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="41.717392"
|
||||
id="text63580-6-89-5-1-2"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="41.717392"
|
||||
id="tspan116603">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="44.807728"
|
||||
id="tspan206609">0.8-UNIMIX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="63.996986"
|
||||
y="50.144955"
|
||||
id="text63580-6-8"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="63.996986"
|
||||
y="50.144955"
|
||||
id="tspan76477-8">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="63.957298"
|
||||
y="53.235291"
|
||||
id="tspan192367">0.8-GASMIX</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="50.883247"
|
||||
y="42.739273"
|
||||
id="text63580-0"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ed1c24;fill-opacity:1;stroke-width:0.264583"
|
||||
x="50.883247"
|
||||
y="42.739273">GASSTATION</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="43.174267"
|
||||
id="text63580-0-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="43.174267">MIXIN MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16634"
|
||||
y="51.642021" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80305"
|
||||
y="55.08519"
|
||||
id="text63580-6-89-5-1-2-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80305"
|
||||
y="55.08519"
|
||||
id="tspan132092">SPONGEMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76336"
|
||||
y="58.175526"
|
||||
id="tspan207303">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59996"
|
||||
y="56.542065"
|
||||
id="text63580-0-3-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59996"
|
||||
y="56.542065">SPONGEMIXINS MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16635"
|
||||
y="64.523148" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="67.966316"
|
||||
id="text63580-6-89-5-1-2-1-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="67.966316"
|
||||
id="tspan126306">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="71.056656"
|
||||
id="tspan207993">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="69.423195"
|
||||
id="text63580-0-3-3-4"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="69.423195">GTNHMIXINS MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3-8"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="118.16635"
|
||||
y="77.124695" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="80.567863"
|
||||
id="text63580-6-89-5-1-2-1-5-7"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.80308"
|
||||
y="80.567863"
|
||||
id="tspan128146">GASSTATION</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="127.76339"
|
||||
y="83.658203"
|
||||
id="tspan208641">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="82.024742"
|
||||
id="text63580-0-3-3-4-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2-5"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="141.59998"
|
||||
y="82.024742">GASSTATION MODULE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-0"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60686"
|
||||
y="41.695419" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="45.138588"
|
||||
id="text63580-6-89-5-1-2-5"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="45.138588"
|
||||
id="tspan116603-60">MIXIN</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.2039"
|
||||
y="48.228924"
|
||||
id="tspan213995">0.7</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="211.10968"
|
||||
y="38.747059"
|
||||
id="text63580-0-3-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-2"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#a349a4;fill-opacity:1;stroke-width:0.264583"
|
||||
x="211.10968"
|
||||
y="38.747059">GRIMOIRE</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-5"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60686"
|
||||
y="55.063217" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24358"
|
||||
y="58.506386"
|
||||
id="text63580-6-89-5-1-2-1-2"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24358"
|
||||
y="58.506386"
|
||||
id="tspan138056">GRIMOIRE</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.20389"
|
||||
y="61.596722"
|
||||
id="tspan214617">EXTRAS</tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000046;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0-7-8-3-4-9-9-3-1"
|
||||
width="19.243679"
|
||||
height="8.0107975"
|
||||
x="207.60687"
|
||||
y="67.944344" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;line-height:1.2;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;letter-spacing:-0.079375px;text-anchor:middle;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="71.387512"
|
||||
id="text63580-6-89-5-1-2-1-5-1"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.24359"
|
||||
y="71.387512"
|
||||
id="tspan126306-5">GTNHMIXINS</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.57528px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="217.2039"
|
||||
y="74.477852"
|
||||
id="tspan215145">EXTRAS</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;line-height:1.25;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:-0.079375px;display:inline;fill:#ed1c24;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="231.0405"
|
||||
y="72.844391"
|
||||
id="text63580-0-3-3-4-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan63578-4-0-1-2-7"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.175px;font-family:'xkcd Script';-inkscape-font-specification:'xkcd Script';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#22b14c;fill-opacity:1;stroke-width:0.264583"
|
||||
x="231.0405"
|
||||
y="72.844391">GTNHMIXINS MODULE</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:1.25;font-family:sans-serif;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="134.45549"
|
||||
y="11.566064"
|
||||
id="text109002"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan109000"
|
||||
style="stroke-width:0.264583"
|
||||
x="134.45549"
|
||||
y="11.566064"></tspan></text>
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="1.5918018"
|
||||
y="1.5918018" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836-0"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="92.015823"
|
||||
y="1.5918018" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect261836-0-8"
|
||||
width="87.778175"
|
||||
height="94.800415"
|
||||
x="182.40633"
|
||||
y="1.6533977" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Layer 2"
|
||||
sodipodi:insensitive="true">
|
||||
<rect
|
||||
style="display:inline;fill:#3f48cc;fill-opacity:0.17;stroke:#3f48cc;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-0"
|
||||
width="45.063374"
|
||||
height="37.911438"
|
||||
x="11.578111"
|
||||
y="44.065044" />
|
||||
<rect
|
||||
style="display:inline;fill:#ed1c24;fill-opacity:0.17;stroke:#ed1c24;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104"
|
||||
width="45.040031"
|
||||
height="37.936855"
|
||||
x="34.465179"
|
||||
y="44.840611" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="36.860748" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="50.228546" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="63.109657" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9-0"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="116.1311"
|
||||
y="75.71122" />
|
||||
<rect
|
||||
style="display:inline;fill:#a349a4;fill-opacity:0.17;stroke:#a349a4;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-7"
|
||||
width="23.043869"
|
||||
height="24.047258"
|
||||
x="205.57162"
|
||||
y="40.281944" />
|
||||
<rect
|
||||
style="display:inline;fill:#2fa755;fill-opacity:0.17;stroke:#22b14c;stroke-width:0.4;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stop-color:#000000"
|
||||
id="rect1104-3-0-9-4"
|
||||
width="23.043865"
|
||||
height="11.087069"
|
||||
x="205.57162"
|
||||
y="66.530869" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 44 KiB |
+1
-1
@@ -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.
@@ -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 {
|
||||
|
||||
}
|
||||
+2
-2
@@ -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 {
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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";
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -10,7 +10,7 @@ import java.util.List;
|
||||
|
||||
public class GasStationModule {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("unimixin-gasstation");
|
||||
private static final Logger LOGGER = LogManager.getLogger("unimixins-gasstation");
|
||||
|
||||
public static void init() {
|
||||
if(SanityCheckHelper.isEnabled()) {
|
||||
+4
-6
@@ -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": [],
|
||||
File renamed without changes.
File renamed without changes.
+1
-14
@@ -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
@@ -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
|
||||
@@ -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
@@ -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.
@@ -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);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+48
-11
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -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);
|
||||
+50
-16
@@ -5,13 +5,16 @@ import com.gtnewhorizon.gtnhmixins.GTNHMixins;
|
||||
import com.gtnewhorizon.gtnhmixins.ILateMixinLoader;
|
||||
import com.gtnewhorizon.gtnhmixins.LateMixin;
|
||||
import com.gtnewhorizon.gtnhmixins.Reflection;
|
||||
import com.gtnewhorizon.gtnhmixins.core.GTNHMixinsCore;
|
||||
|
||||
import cpw.mods.fml.common.LoadController;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderState;
|
||||
import cpw.mods.fml.common.ModClassLoader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -21,22 +24,23 @@ import org.spongepowered.asm.mixin.transformer.Config;
|
||||
import org.spongepowered.asm.mixin.transformer.Proxy;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@Mixin(value = FMLConstructionEvent.class, remap = false)
|
||||
@Mixin(value = LoadController.class, remap = false)
|
||||
public class LateMixinOrchestrationMixin {
|
||||
private static boolean finished=false;
|
||||
|
||||
@Inject(method = "<init>", at = @At(value = "RETURN"))
|
||||
private void beforeConstructing(Object[] eventData, CallbackInfo ci) throws Throwable {
|
||||
// We would normally target something in LoadController, but FastCraft causes that class to be loaded too early to mixin,
|
||||
// so we instead hijack the very first FMLConstructionEvent that's constructed and run the logic there.
|
||||
if (finished)
|
||||
@Inject(method = "distributeStateMessage(Lcpw/mods/fml/common/LoaderState;[Ljava/lang/Object;)V", at = @At(value = "HEAD"))
|
||||
private void beforeConstructing(LoaderState state, Object[] eventData, CallbackInfo ci) throws Throwable {
|
||||
// This state is where Forge adds mod files to ModClassLoader
|
||||
if (state != LoaderState.CONSTRUCTING) {
|
||||
return;
|
||||
|
||||
finished = true;
|
||||
}
|
||||
|
||||
GTNHMixins.LOGGER.info("Instantiating all @LateMixin annotated and ILateMixinLoader implemented classes...");
|
||||
|
||||
@@ -45,8 +49,11 @@ public class LateMixinOrchestrationMixin {
|
||||
ASMDataTable asmDataTable = (ASMDataTable)eventData[1];
|
||||
final Loader loader = Loader.instance();
|
||||
|
||||
final Set<String> loadedMods = loader.getIndexedModList().keySet();
|
||||
GTNHMixinsCore.LOGGER.info("LoadedMods {}", loadedMods.toString());
|
||||
final Set<String> loadedModsTemp = new HashSet<>();
|
||||
loadedModsTemp.addAll(loader.getIndexedModList().keySet());
|
||||
loadedModsTemp.addAll(getLiteLoaderMods());
|
||||
final Set<String> loadedMods = Collections.unmodifiableSet(loadedModsTemp);
|
||||
GTNHMixins.LOGGER.info("LoadedMods {}", loadedMods.toString());
|
||||
|
||||
for (ASMDataTable.ASMData asmData : asmDataTable.getAll(LateMixin.class.getName())) {
|
||||
modClassLoader.addFile(asmData.getCandidate().getModContainer()); // Add to path before `newInstance`
|
||||
@@ -61,7 +68,7 @@ public class LateMixinOrchestrationMixin {
|
||||
final String mixinConfig = lateLoader.getMixinConfig();
|
||||
GTNHMixins.LOGGER.info("Adding {} mixin configuration.", mixinConfig);
|
||||
|
||||
final Config config = Config.create(mixinConfig);
|
||||
final Config config = Config.create(mixinConfig, null);
|
||||
final List<String> mixins = lateLoader.getMixins(loadedMods);
|
||||
for(String mixin : mixins) {
|
||||
GTNHMixins.LOGGER.info("Loading [{}] {}", mixinConfig, mixin);
|
||||
@@ -78,6 +85,9 @@ public class LateMixinOrchestrationMixin {
|
||||
modClassLoader.addFile(container.getSource());
|
||||
}
|
||||
|
||||
// Force rebuild of the transformer list
|
||||
Reflection.setDelegatedTransformersField(null);
|
||||
|
||||
Field transformerField = Proxy.class.getDeclaredField("transformer");
|
||||
transformerField.setAccessible(true);
|
||||
|
||||
@@ -88,4 +98,28 @@ public class LateMixinOrchestrationMixin {
|
||||
Reflection.invokeSelectConfigs(transformer, env);
|
||||
Reflection.invokePrepareConfigs(transformer, env);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> getLiteLoaderMods() {
|
||||
Set<String> mods = new HashSet<>();
|
||||
try {
|
||||
Class<?> LiteLoaderTweaker = Class.forName("com.mumfrey.liteloader.launch.LiteLoaderTweaker");
|
||||
Method hasValidMetaData = Class.forName("com.mumfrey.liteloader.interfaces.LoadableMod").getMethod("hasValidMetaData");
|
||||
Object instance = FieldUtils.readDeclaredStaticField(LiteLoaderTweaker, "instance", true);
|
||||
Object bootstrap = FieldUtils.readDeclaredField(instance, "bootstrap", true);
|
||||
Object enumerator = FieldUtils.readDeclaredField(bootstrap, "enumerator", true);
|
||||
Map<String, ?> enabledContainers = (Map<String, ?>) FieldUtils.readDeclaredField(enumerator, "enabledContainers", true);
|
||||
GTNHMixins.LOGGER.info("LiteLoader present, adding its mods to the list.");
|
||||
for(Entry<String, ?> e : enabledContainers.entrySet()) {
|
||||
if((boolean) hasValidMetaData.invoke(e.getValue())) {
|
||||
mods.add(e.getKey());
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
GTNHMixins.LOGGER.info("LiteLoader not present.");
|
||||
} catch (Exception e) {
|
||||
GTNHMixins.LOGGER.error("Failed to get LiteLoader mods.", e);
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins;
|
||||
|
||||
import io.github.legacymoddingmc.unimixins.common.config.AnnotatedProperties;
|
||||
|
||||
public class GTNHMixinsConfig {
|
||||
@AnnotatedProperties.ConfigString(def = "true", com = "Provide the deprecated `com.gtnewhorizons.mixinextras` relocation of MixinExtras 0.1.1. May be required by some older mods.", cat = "gtnhmixins")
|
||||
public static boolean enableLegacyGTNHMixinExtrasPackage;
|
||||
}
|
||||
+77
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins.asm;
|
||||
|
||||
import static io.github.legacymoddingmc.unimixins.gtnhmixins.GTNHMixinsModule.LOGGER;
|
||||
|
||||
import io.github.legacymoddingmc.unimixins.gtnhmixins.util.LaunchClassLoaderUtils;
|
||||
import makamys.mixingasm.api.MixinSafeTransformer;
|
||||
import makamys.mixingasm.api.TransformerInclusions;
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@MixinSafeTransformer
|
||||
public class LegacyGTNHMixinExtrasGenerator implements IClassTransformer {
|
||||
static {
|
||||
if(LegacyGTNHMixinExtrasGenerator.class.getResource("/makamys/mixingasm/api/TransformerInclusions.class") != null
|
||||
&& LegacyGTNHMixinExtrasGenerator.class.getResource("/makamys/mixingasm/api/MixinSafeTransformer.class") == null) {
|
||||
// Mixingasm < 0.3 compat
|
||||
TransformerInclusions.getTransformerInclusionList().add("io.github.legacymoddingmc.unimixins.compat.asm.LegacyGTNHMixinExtrasGenerator");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass) {
|
||||
if(basicClass == null && name.startsWith("com.gtnewhorizon.mixinextras") && !name.startsWith("org.apache.commons.io.")) {
|
||||
try {
|
||||
LOGGER.trace("Generating class " + name);
|
||||
byte[] bytes = getClassBytes(name);
|
||||
|
||||
if(bytes != null) {
|
||||
// If NEI is on the class path before CCL (which would cause the game to crash immediately in
|
||||
// production, but is possible in a dev env), ClassHeirachyTransformer will try to call getClassBytes,
|
||||
// and if it fails, it will call Class.forName for the class being loaded, causing a
|
||||
// ClassCircularityError.
|
||||
// So we need to populate the cache to avoid that from happening.
|
||||
LaunchClassLoaderUtils.putInResourceCache(name, bytes);
|
||||
return bytes;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to generate class " + name);
|
||||
}
|
||||
}
|
||||
return basicClass;
|
||||
}
|
||||
|
||||
private byte[] getClassBytes(String name) throws IOException {
|
||||
final String resourcePath = "/data/legacy_gtnh_mixinextras/" + name.replace('.', '/').concat(".klass");
|
||||
return IOUtils.toByteArray(LegacyGTNHMixinExtrasGenerator.class.getResourceAsStream(resourcePath));
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package io.github.legacymoddingmc.unimixins.gtnhmixins.util;
|
||||
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class LaunchClassLoaderUtils {
|
||||
private static Map<String,byte[]> resourceCache;
|
||||
private static Set<String> negativeResourceCache;
|
||||
|
||||
static {
|
||||
try {
|
||||
Field resourceCacheField = LaunchClassLoader.class.getDeclaredField("resourceCache");
|
||||
resourceCacheField.setAccessible(true);
|
||||
resourceCache = (Map<String, byte[]>) resourceCacheField.get(Launch.classLoader);
|
||||
|
||||
Field negativeResourceCacheField = LaunchClassLoader.class.getDeclaredField("negativeResourceCache");
|
||||
negativeResourceCacheField.setAccessible(true);
|
||||
negativeResourceCache = (Set<String>) negativeResourceCacheField.get(Launch.classLoader);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Use with care, ArchaicFix weakens the resource cache once it receives the LoadComplete event, making
|
||||
* this method cease to function! But it's fine for our purposes since all mixins load before that.
|
||||
* It's either this or reflecting every time. */
|
||||
public static void putInResourceCache(String key, byte[] value) {
|
||||
resourceCache.put(key, value);
|
||||
negativeResourceCache.remove(key);
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -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
-2
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -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 {
|
||||
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
Loaded 100 of 201 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user