Compare commits

..

360 Commits

Author SHA1 Message Date
embeddedt
37cb92a64f
Add PreparableModelLoadingPlugin support
Related: #522
2025-02-08 11:40:00 -05:00
embeddedt
95ffcb3194
Merge remote-tracking branch 'origin/1.21.1' into 1.21.4 2025-01-24 22:02:57 -05:00
embeddedt
960c394073
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2025-01-24 22:01:55 -05:00
embeddedt
e8320a3d8f
Fix remapping issue on Neo 2025-01-24 11:33:37 -05:00
embeddedt
74a339bc2c
Add more locking in various vanilla model loading paths 2025-01-24 09:32:06 -05:00
embeddedt
717d2f6b88
Merge remote-tracking branch 'origin/1.21.1' into 1.21.4 2025-01-19 19:54:58 -05:00
embeddedt
6706656623
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2025-01-19 19:53:17 -05:00
embeddedt
db5363a429
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2025-01-01 11:06:39 -05:00
embeddedt
7e9865411e
Update to Neo 21.4.47-beta 2024-12-29 19:57:00 -05:00
embeddedt
28664ddc3a
Fix faster_item_rendering on Neo 2024-12-27 18:14:35 -05:00
embeddedt
5493c736ee
Update Neo & Parchment 2024-12-27 18:14:29 -05:00
embeddedt
3d30de6398
Merge branch '1.21.4' of github.com:embeddedt/ModernFix into 1.21.4 2024-12-26 15:25:32 -05:00
embeddedt
06b1e8f5c3
Merge 1.21.1 into 1.21.4 2024-12-26 15:24:42 -05:00
embeddedt
fc96643a89
Merge 1.20 into 1.21.1 2024-12-26 15:24:41 -05:00
embeddedt
c66dd2382c
Remove LDLib integration as it will likely need changes for 1.21.4 2024-12-26 15:24:09 -05:00
embeddedt
2d263436f6
Merge remote-tracking branch 'origin/1.21.1' into 1.21.4 2024-12-26 15:23:35 -05:00
embeddedt
eeb842332b
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2024-12-26 15:00:06 -05:00
embeddedt
e0f941cfe5
Port faster item rendering to 1.21.4 2024-12-25 20:01:05 -05:00
embeddedt
a5af6e5c1f
Guarantee deterministic behavior of values() iteration 2024-12-25 19:45:27 -05:00
embeddedt
80070aa201
Merge remote-tracking branch 'origin/1.21.1' into 1.21.4 2024-12-25 19:29:33 -05:00
embeddedt
6531b69fb9
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2024-12-25 16:23:07 -05:00
embeddedt
2f977822df
Support the new Fabric model events 2024-12-24 15:38:33 -05:00
embeddedt
9ed71dcdb4
Provide emulated registries permanently 2024-12-24 15:14:41 -05:00
embeddedt
46913ac8b2
Spotless 2024-12-12 22:51:31 -05:00
embeddedt
a0cc8bfbd2
Add Fabric Model Loading API support 2024-12-12 22:49:12 -05:00
embeddedt
e7e065f809
Clean up some log messages 2024-12-12 21:43:21 -05:00
embeddedt
19d2d8cfc0
Get dynamic model loading working with ModifyBakingResult 2024-12-12 21:31:21 -05:00
embeddedt
0f16e159f9
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2024-12-12 19:53:36 -05:00
embeddedt
1d4ddc302a
Merge commit '14a89f94a63d68e855ec38da039363d0147c8147' into 1.21.1 2024-12-12 19:53:23 -05:00
embeddedt
de5b79fe7c
Fix model parents not always being resolved
This would cause models to sometimes not appear at all (CC turtles were one reproduction case)
2024-12-07 21:44:41 -05:00
embeddedt
e82f316216
Remove old AW entry 2024-12-07 17:22:35 -05:00
embeddedt
2901b53424
Spotless 2024-12-07 17:19:39 -05:00
embeddedt
b822f5ce87
Dynamic model loading on Fabric 2024-12-07 17:13:30 -05:00
embeddedt
145896cc99
Initial port to 1.21.4 2024-12-07 15:52:34 -05:00
embeddedt
359d1e81d6
Merge 1.21.3 into 1.21.4 2024-11-29 16:43:01 -05:00
embeddedt
1bb730b2b0
Merge 1.21.1 into 1.21.3 2024-11-29 16:42:59 -05:00
embeddedt
86f06b2f36
Merge 1.20 into 1.21.1 2024-11-29 16:42:45 -05:00
pietro-lopes
520de2c12b
updated spark (#484) 2024-11-28 08:46:29 -05:00
embeddedt
a29bdb2f82
Fix standalone model variant not being loaded
Related: #475
2024-11-12 08:17:12 -05:00
embeddedt
c8ca6a5d53
24w45a
Dynamic resources and faster item rendering are gone for now
2024-11-06 14:59:26 -05:00
embeddedt
103dea589f
fix AW 2024-11-04 16:58:57 -05:00
embeddedt
7645af1bab
Merge 1.21.1 into 1.21.3 2024-11-04 16:55:12 -05:00
embeddedt
cdfe53589e
Merge 1.20 into 1.21.1 2024-11-04 16:55:10 -05:00
embeddedt
1e0d4d9d07
Remove useless test 2024-10-28 11:40:31 -04:00
embeddedt
5450a16aad
Rewrite dynamic resources once again 2024-10-28 11:37:03 -04:00
embeddedt
d8b86708e5
Fix another outdated mixin 2024-10-28 11:36:40 -04:00
Rhys
6012626112
Port cause_lag_by_disabling_threads to 1.21.3 2024-10-28 10:21:51 -04:00
embeddedt
3d785cedb4
Remove obsolete mixin 2024-10-27 21:48:59 -04:00
Rhys
b1f5f6ebbe
Fix faster item rendering mixin 2024-10-27 21:46:58 -04:00
embeddedt
91ffdb1acf
Spotless 2024-10-26 18:44:36 -04:00
embeddedt
f374bcbb3a
Update to 1.21.3, fix tests 2024-10-24 10:46:53 -04:00
embeddedt
e0d24d4cdb
Update to 1.21.2-rc1 2024-10-17 11:08:57 -04:00
embeddedt
545fb386a0
Start rewriting dynamic resources 2024-10-12 11:50:43 -04:00
embeddedt
09ea5e1dc9
Runs, dynamic resources still broken 2024-10-10 14:01:39 -04:00
embeddedt
a841d20f8a
Compiles on 1.21.2-pre2, does not yet run 2024-10-10 12:06:24 -04:00
embeddedt
5463ccc3e6
Merge 1.20 into 1.21.1 2024-09-22 13:49:32 -04:00
embeddedt
dee2627df9
Trim LRU maps after dropping entries 2024-09-21 14:21:18 -04:00
embeddedt
d8e937720f
Always tick model manager even if not in world 2024-09-21 14:18:34 -04:00
embeddedt
9df79d8c8c
Skip filtering states when not in a world 2024-09-21 14:17:03 -04:00
embeddedt
1572bd705d
Merge remote-tracking branch 'origin/1.20' into 1.21.1 2024-08-24 16:34:59 -04:00
embeddedt
2abc4fa56b
Add type checking to dynamic maps to avoid ClassCastException from badly behaved mods 2024-08-19 18:26:58 -04:00
embeddedt
489136d048
Update to 1.21.1 2024-08-19 17:23:30 -04:00
embeddedt
820169667a
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-08-10 19:19:06 -04:00
embeddedt
512a7e237c
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-08-10 19:17:42 -04:00
embeddedt
7db5d6a1da
Make CTM work on 1.21 2024-07-27 14:39:30 -04:00
embeddedt
631ad0528b
Fix registry progress bar on 1.21 2024-07-27 13:33:08 -04:00
embeddedt
1daea1f5e3
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-07-26 20:04:05 -04:00
embeddedt
b2eb14b766
Bump Neo version to fix config screen crash 2024-07-19 20:24:44 -04:00
embeddedt
70fba2e0af
Improve dynamic model loading efficiency during model bake event 2024-07-19 19:44:13 -04:00
embeddedt
30e91f2056
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-07-19 19:21:23 -04:00
embeddedt
beccbef151
Bump Neo requirement 2024-07-12 18:45:27 -04:00
embeddedt
c3b17b2927
Update NF, remove config hacks as config system is rewritten 2024-07-11 08:00:59 -04:00
embeddedt
783627f4c5
Always convert identity unbaked missing model to identity baked missing model
Related: #433
2024-07-08 19:21:30 -04:00
embeddedt
d7bfeedc62
Merge 1.20 into 1.21 2024-07-07 09:14:46 -04:00
embeddedt
212f139bf1
Remove nonexistent JEI plugin from fabric mod file
Related: #428
2024-07-03 17:11:25 -04:00
embeddedt
85740f83af
Remove blast_search_trees 2024-06-28 20:20:06 -04:00
embeddedt
d46d24542f
Update NeoForge, adjust dynamic resources for NF API 2024-06-18 21:49:23 -04:00
embeddedt
700ccc25b7
Freeze model bakery later to allow for mutation in event 2024-06-14 19:19:52 -04:00
embeddedt
1b6075562c
Fix wrong location type being passed to model registry 2024-06-14 19:15:16 -04:00
embeddedt
2697a8f358
Fix lambda shadow remapping issue 2024-06-14 19:08:54 -04:00
embeddedt
f056fe4d0c
Fix item frames not having models with dynamic resources on
Related: #422
2024-06-14 18:58:00 -04:00
embeddedt
ef07197345
Fix deduplicate_location 2024-06-14 18:57:54 -04:00
embeddedt
180606eea1
Remove upgraded structure caching
Performance improvement is minimal with rewritten DFU and it
breaks structure generation on 1.21 for some reason
2024-06-13 21:37:34 -04:00
embeddedt
a6e0785252
Merge 1.20 into 1.21 2024-06-13 18:24:45 -04:00
embeddedt
4673293039
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-06-13 17:27:31 -04:00
embeddedt
f2379dc9e3
Update to 1.21 full release 2024-06-13 17:27:20 -04:00
embeddedt
d4cc7664f6
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-06-10 21:59:04 -04:00
embeddedt
1dce8d4ccf
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-06-10 21:45:23 -04:00
embeddedt
6fd3dde1a2
Fix compile error 2024-06-10 21:45:20 -04:00
embeddedt
f586522dfe
Do not drop models during initial load 2024-06-10 20:23:37 -04:00
embeddedt
168ab8effa
Merge remote-tracking branch 'origin/1.20' into 1.21 2024-06-10 20:20:14 -04:00
embeddedt
6e9dfaf0c6
Enable NeoForge project 2024-06-08 21:01:23 -04:00
embeddedt
9d584d13d2
Make blockstate model loader more resilient 2024-06-08 16:41:45 -04:00
embeddedt
a0f391e258
Update FAPI 2024-06-08 16:39:44 -04:00
embeddedt
8c51ccc022
1.21-pre3 2024-06-05 20:28:43 -04:00
embeddedt
390404d1d5
Merge remote-tracking branch 'origin/1.20.6' into 1.21 2024-06-05 20:23:31 -04:00
embeddedt
57af3c6491
Merge remote-tracking branch 'origin/1.20' into 1.20.6 2024-06-05 20:23:17 -04:00
embeddedt
99da801c3f
Merge 1.20.6 into 1.21 2024-06-04 19:41:27 -04:00
embeddedt
c292f0ddce
Merge 1.20 into 1.20.6 2024-06-04 19:41:09 -04:00
embeddedt
aa2a3817ba
Update NeoForge, work around buggy hasErrors method 2024-06-03 18:52:12 -04:00
embeddedt
4473a4ffb4
Merge 1.20.6 into 1.21 2024-06-01 13:38:18 -04:00
embeddedt
b4398565a6
Merge 1.20 into 1.20.6 2024-06-01 13:38:17 -04:00
embeddedt
9cfccb58fa
Merge 1.20.6 into 1.21 2024-05-30 19:06:42 -04:00
embeddedt
a9f4ce72f1
Merge 1.20 into 1.20.6 2024-05-30 19:06:41 -04:00
embeddedt
bc3af0450e
Fix access widener 2024-05-29 20:52:22 -04:00
embeddedt
d0598055c0
Do not load models for all of a block's blockstates at once 2024-05-29 20:47:59 -04:00
embeddedt
ab8810b7fe
1.21-pre1 - rewrite dynamic resources 2024-05-29 20:37:45 -04:00
embeddedt
2ef7d5fc85
24w21a 2024-05-29 20:37:45 -04:00
embeddedt
d8b207ff10
Merge 1.20.6 into 1.21 2024-05-29 16:04:39 -04:00
embeddedt
4e8427545f
Merge 1.20 into 1.20.6 2024-05-29 16:04:38 -04:00
embeddedt
f85d31d24d
Remove redundant patch 2024-05-19 19:36:39 -04:00
embeddedt
6a7b6abb23
Fix faster_item_rendering mixin 2024-05-17 12:40:07 -04:00
embeddedt
a443972d28
24w20a 2024-05-16 19:53:11 -04:00
embeddedt
b6865eff6c
Merge 1.20.6 into 1.21 2024-05-12 16:59:14 -04:00
embeddedt
cc653249e4
Merge 1.20 into 1.20.6 2024-05-12 16:59:13 -04:00
embeddedt
e75810db5b
Merge 1.20.6 into 1.21 2024-05-12 15:21:27 -04:00
embeddedt
a4359e1ad5
Remove structure location optimization as Mojang fixed it in 1.20.5 2024-05-12 15:21:02 -04:00
embeddedt
95a5a1b7b1
Merge 1.20.6 into 1.21 2024-05-11 22:15:26 -04:00
embeddedt
d846a077ac
Merge 1.20 into 1.20.6 2024-05-11 22:15:25 -04:00
embeddedt
2f98fadc9e
Spotless 2024-05-10 11:58:01 -04:00
embeddedt
de70fbafad
Use chunk status method that more accurately matches 1.20 2024-05-10 11:54:45 -04:00
embeddedt
a66a1dab9d
Fix overwrite lowering method access level 2024-05-10 11:49:49 -04:00
embeddedt
4d251e61ca
Fix tests 2024-05-10 11:47:22 -04:00
embeddedt
57d5f08b1d
24w19a 2024-05-10 11:39:58 -04:00
embeddedt
f13910a6ed
Update NeoForge 2024-05-07 10:39:52 -04:00
embeddedt
bebf3ccec2
Update for NeoForge changes 2024-04-29 15:12:45 -04:00
embeddedt
a5b1cbdc13
1.20.6 2024-04-29 14:52:10 -04:00
embeddedt
89592a2c42
Fix dynamic resources mixin on NeoForge 2024-04-25 19:39:27 -04:00
embeddedt
3f688148d0
Merge 1.20.4 into 1.20.5 2024-04-24 12:14:40 -04:00
embeddedt
c8f9b1cd84
Merge 1.20 into 1.20.4 2024-04-24 12:14:39 -04:00
embeddedt
7ee968f719
Spotless 2024-04-24 09:26:10 -04:00
embeddedt
2cce200e4d
Update to 1.20.5 2024-04-24 09:17:55 -04:00
embeddedt
2e9a6f27e0
1.20.5-rc2 2024-04-21 20:10:26 -04:00
embeddedt
730932b018
Merge 1.20.4 into 1.20.5 2024-04-15 21:22:26 -04:00
embeddedt
c6338f9736
Merge 1.20 into 1.20.4 2024-04-15 21:22:25 -04:00
embeddedt
0277d80ce7
Merge 1.20.4 into 1.20.5 2024-04-13 13:11:22 -04:00
embeddedt
b1c0b0f813
Merge 1.20 into 1.20.4 2024-04-13 13:11:22 -04:00
embeddedt
0476cdc35a
Fix option info screen rendering description behind blur 2024-04-12 09:44:02 -04:00
embeddedt
23bbf7b092
24w14a 2024-04-09 20:00:35 -04:00
embeddedt
0061e1de8e
Remove irrelevant mixin 2024-04-09 19:25:41 -04:00
embeddedt
159f27a8bf
Merge 1.20.4 into 1.20.5 2024-04-09 19:23:04 -04:00
embeddedt
c5dd43f2a1
Merge 1.20 into 1.20.4 2024-04-09 19:23:03 -04:00
embeddedt
da065350d0
Merge 1.20.4 into 1.20.5 2024-03-31 16:06:05 -04:00
embeddedt
9bf4faa4a5
Merge 1.20 into 1.20.4 2024-03-31 16:06:04 -04:00
embeddedt
7bd88b4f04
Merge 1.20.4 into 1.20.5 2024-03-31 09:27:12 -04:00
embeddedt
3bedde4ebe
Merge 1.20 into 1.20.4 2024-03-31 09:27:11 -04:00
embeddedt
2e1bed7cfb
Merge 1.20.4 into 1.20.5 2024-03-30 18:12:30 -04:00
embeddedt
73f706164f
Merge 1.20 into 1.20.4 2024-03-30 18:12:30 -04:00
embeddedt
5b5cbf9380
Merge 1.20.4 into 1.20.5 2024-03-30 17:46:26 -04:00
embeddedt
50556ab005
Update recipe book search tree for 1.20.2 changes 2024-03-30 17:45:49 -04:00
embeddedt
c3d78c3d09
Merge 1.20.4 into 1.20.5 2024-03-30 17:42:56 -04:00
embeddedt
ad07fb3f0c
Merge 1.20 into 1.20.4 2024-03-30 17:42:55 -04:00
embeddedt
a9efc62867
Merge 1.20.4 into 1.20.5 2024-03-30 15:22:47 -04:00
embeddedt
4b741da54d
Merge 1.20 into 1.20.4 2024-03-30 15:22:46 -04:00
embeddedt
60c2b02e37
Merge 1.20.4 into 1.20.5 2024-03-29 10:49:44 -04:00
embeddedt
042a7caa9e
Merge 1.20 into 1.20.4 2024-03-29 10:49:43 -04:00
embeddedt
02e4cb6cf1
24w13a 2024-03-28 10:42:44 -04:00
embeddedt
b2e3ae82eb
Remove optimization that is obsolete in snapshots 2024-03-28 10:39:03 -04:00
embeddedt
180f4eaf8d
Merge 1.20.4 into 1.20.5 2024-03-27 12:15:15 -04:00
embeddedt
95cd576c68
Merge 1.20 into 1.20.4 2024-03-27 12:15:14 -04:00
embeddedt
0ea4284846
Merge 1.20.4 into 1.20.5 2024-03-22 14:11:06 -04:00
embeddedt
8fc9c0b3c1
Merge 1.20 into 1.20.4 2024-03-22 14:11:05 -04:00
embeddedt
60fa5d4afe
Merge 1.20.4 into 1.20.5 2024-03-22 14:08:00 -04:00
embeddedt
95a8e4fe21
Merge 1.20 into 1.20.4 2024-03-22 14:07:59 -04:00
embeddedt
add7dd4609
Deholderize item mesher mixin 2024-03-21 14:14:35 -04:00
embeddedt
827550e8af
Update CTM integration for 1.20.4
Requires https://github.com/Chisel-Team/ConnectedTexturesMod/pull/229 to be built from source
2024-03-21 14:10:56 -04:00
embeddedt
9d7ef772a0
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2024-03-21 13:53:42 -04:00
embeddedt
a47a61a923
24w12a 2024-03-21 11:02:37 -04:00
embeddedt
5e20e25c4d
Loom 1.5 2024-03-20 10:00:02 -04:00
embeddedt
e6b28de740
Merge 1.20.4 into 1.20.5 2024-03-17 16:09:55 -04:00
embeddedt
61c2116946
Merge 1.20 into 1.20.4 2024-03-17 16:09:54 -04:00
embeddedt
72845d8952
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2024-03-17 16:09:32 -04:00
embeddedt
70eaabe756
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2024-03-17 15:53:53 -04:00
embeddedt
e22f5caec7
Fix registry progress bar going off end of screen in NeoForge 2024-03-17 15:25:58 -04:00
embeddedt
8a872fed27
Merge 1.20.4 into 1.20.5 2024-03-17 15:08:26 -04:00
embeddedt
0a2299ee33
Merge 1.20 into 1.20.4 2024-03-17 15:08:25 -04:00
embeddedt
826e5a4c20
Merge 1.20.4 into 1.20.5 2024-03-14 22:13:59 -04:00
embeddedt
a62c0635a5
Merge 1.20 into 1.20.4 2024-03-14 22:13:58 -04:00
embeddedt
4584457a79
Remove blur disabling patch
Mojang fixed this issue in 24w11a, the blur shader is not run for
pointless radii
2024-03-14 20:11:56 -04:00
embeddedt
8f663a0b07
24w11a 2024-03-14 20:10:21 -04:00
embeddedt
b65a63896b
Merge remote-tracking branch 'origin/1.20.4' into 1.20.5 2024-03-14 20:01:31 -04:00
embeddedt
fdc98b2600
Merge 1.20 into 1.20.4 2024-03-10 21:59:06 -04:00
embeddedt
8806dffaea
Merge 1.20 into 1.20.4 2024-03-08 17:51:07 -05:00
embeddedt
761703b4ab
Cast to correct event type 2024-03-02 21:35:50 -05:00
embeddedt
967d39997f
Remove buffer builder leak fix since you can now close them properly 2024-03-02 13:50:35 -05:00
embeddedt
48b492b906
Bump NeoForge 2024-03-02 13:17:19 -05:00
embeddedt
96db279d58
Merge Forge mixins that didn't automerge 2024-03-02 13:14:41 -05:00
embeddedt
8d2d3d8e15
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2024-03-02 13:06:52 -05:00
embeddedt
b82942fe75
Merge 1.20 into 1.20.4 2024-03-01 11:33:04 -05:00
embeddedt
e6ca5f633c
Merge 1.20 into 1.20.4 2024-02-28 20:10:53 -05:00
embeddedt
611dc4a266
Make it possible to properly disable blur 2024-02-28 19:45:16 -05:00
embeddedt
eacab89181
24w09a 2024-02-28 14:05:14 -05:00
embeddedt
139b967ce6
Merge 1.20.4 into 1.20.5 2024-02-26 16:40:49 -05:00
embeddedt
d52725012a
Merge 1.20 into 1.20.4 2024-02-26 16:40:48 -05:00
embeddedt
23e6091747
Merge 1.20.4 into 1.20.5 2024-02-26 16:32:52 -05:00
embeddedt
3f7af1c2e0
Merge 1.20 into 1.20.4 2024-02-26 16:32:51 -05:00
embeddedt
f38a06ecc1
Merge 1.20.4 into 1.20.5 2024-02-23 16:45:24 -05:00
embeddedt
c8485eaef8
Merge 1.20 into 1.20.4 2024-02-23 16:45:23 -05:00
embeddedt
fc86d0eee0 24w07a 2024-02-14 11:40:34 -05:00
embeddedt
6143d8a783 spotless 2024-02-07 15:54:09 -05:00
embeddedt
90cf39e9d8 24w06a 2024-02-07 15:49:00 -05:00
embeddedt
739b1663cd Merge remote-tracking branch 'origin/1.20.4' into 1.20.5 2024-02-07 15:37:37 -05:00
embeddedt
4dfba0cab4 Fix EntityIDSyncPacket being broken in multiplayer 2024-02-05 15:37:44 -05:00
embeddedt
46fc1e8539
Merge 1.20.4 into 1.20.5 2024-02-02 20:38:33 -05:00
embeddedt
2699fe448e
Merge 1.20 into 1.20.4 2024-02-02 20:38:32 -05:00
embeddedt
5c72a527ad 24w05a 2024-01-31 12:29:35 -05:00
embeddedt
25f13a9701 Merge 1.20.4 into 1.20.5 2024-01-30 15:48:16 -05:00
embeddedt
16ef9253e6 Merge 1.20 into 1.20.4 2024-01-30 15:47:48 -05:00
embeddedt
f25ecf337d Update NeoForge version 2024-01-30 15:34:19 -05:00
embeddedt
675ce1cd43 Merge 1.20.4 into 1.20.5 2024-01-29 15:31:11 -05:00
embeddedt
c4855e0b70 Merge 1.20 into 1.20.4 2024-01-29 15:31:10 -05:00
embeddedt
6c206c47e9
Merge 1.20.4 into 1.20.5 2024-01-27 20:23:31 -05:00
embeddedt
daa84565a6
Merge 1.20 into 1.20.4 2024-01-27 20:23:30 -05:00
embeddedt
8658784906
24w04a 2024-01-24 20:39:42 -05:00
embeddedt
d3758eb4f6 Fix mixin target 2024-01-17 14:41:12 -05:00
embeddedt
e9bfd965cd 24w03a 2024-01-17 13:16:17 -05:00
embeddedt
c2a2fd876b Merge 1.20.4 into 1.20.5 2024-01-12 15:49:17 -05:00
embeddedt
649c25d0d2 Merge 1.20 into 1.20.4 2024-01-12 15:49:15 -05:00
embeddedt
ad4bfc79ab Merge 1.20.4 into 1.20.5 2024-01-12 11:36:22 -05:00
embeddedt
a4bb17d2af Merge 1.20 into 1.20.4 2024-01-12 11:36:20 -05:00
embeddedt
b55ed00748
Merge 1.20.4 into 1.20.5 2024-01-11 08:02:54 -05:00
embeddedt
806fb7dcfe
Merge 1.20 into 1.20.4 2024-01-11 08:02:10 -05:00
embeddedt
b5becf6ba3
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2024-01-04 20:33:31 -05:00
embeddedt
c65fdbccc0
Spotless 2023-12-31 21:14:39 -05:00
embeddedt
dcee8b4169
Update to NeoForge 20.4.70-beta 2023-12-31 21:07:32 -05:00
embeddedt
d6fc939f41
Workaround AP throwing exception if there is a compile error in the file 2023-12-31 20:30:04 -05:00
embeddedt
a012b60ae3
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2023-12-31 20:22:33 -05:00
embeddedt
97a2c0e0f5
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2023-12-28 14:50:51 -05:00
Fury_Phoenix
34bc295b3c
Mark some more mixins as ClientOnlyMixin 2023-12-28 09:42:07 -05:00
embeddedt
e08531c228
Merge 1.20.4 into 1.20.5 2023-12-27 15:20:18 -05:00
embeddedt
456bca47b6
Merge 1.20 into 1.20.4 2023-12-27 15:20:17 -05:00
embeddedt
b25bb14d3d
Merge 1.20.4 into 1.20.5 2023-12-23 21:28:43 -05:00
embeddedt
d4fcc80db0
Merge 1.20 into 1.20.4 2023-12-23 21:28:43 -05:00
embeddedt
64ea7eab19
Merge 1.20.4 into 1.20.5 2023-12-23 19:07:06 -05:00
embeddedt
432b137edb
Merge 1.20 into 1.20.4 2023-12-23 19:07:05 -05:00
embeddedt
991ec339b2
Merge 1.20.4 into 1.20.5 2023-12-23 17:15:39 -05:00
embeddedt
1bf98ced86
Merge 1.20 into 1.20.4 2023-12-23 17:15:38 -05:00
embeddedt
7646bfa153
Merge 1.20.4 into 1.20.5 2023-12-23 15:57:42 -05:00
embeddedt
7be97e61e8
Merge 1.20 into 1.20.4 2023-12-23 15:57:41 -05:00
embeddedt
b23502c32b
Fix incorrect merge 2023-12-23 15:56:28 -05:00
embeddedt
d03571cb05
Merge 1.20 into 1.20.4 2023-12-23 15:55:42 -05:00
embeddedt
e1c91f13ac
Merge 1.20.4 into 1.20.5 2023-12-21 16:51:13 -05:00
embeddedt
324fb3af97
Merge 1.20 into 1.20.4 2023-12-21 16:51:12 -05:00
embeddedt
585fdb9e99
Merge 1.20.4 into 1.20.5 2023-12-21 13:41:57 -05:00
embeddedt
fa9d39bd31
Merge 1.20 into 1.20.4 2023-12-21 13:41:56 -05:00
embeddedt
501db5b84a
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2023-12-21 13:33:49 -05:00
embeddedt
8c46b4629d
23w51a 2023-12-18 10:25:10 -05:00
embeddedt
9dcc87b227
Merge 1.20.2 into 1.20.4 2023-12-14 21:12:00 -05:00
embeddedt
0eb70468a1
Merge 1.20 into 1.20.2 2023-12-14 21:11:59 -05:00
embeddedt
ba2b740075
Merge remote-tracking branch 'origin/1.20' into 1.20.4 2023-12-14 20:46:02 -05:00
embeddedt
063289faac
Update NeoForge version target 2023-12-13 09:33:31 -05:00
embeddedt
d3ed56a1c1
Merge 1.20.3 into 1.20.4 2023-12-11 11:01:53 -05:00
embeddedt
45a7f1a63e
Merge 1.20.2 into 1.20.3 2023-12-11 11:01:52 -05:00
embeddedt
04aac43db0
Merge 1.20 into 1.20.2 2023-12-11 11:01:51 -05:00
embeddedt
0ea5139315
Merge remote-tracking branch 'origin/1.20.2' into 1.20.4 2023-12-11 10:16:48 -05:00
embeddedt
06bb9f9545
Update Minecraft & Fabric Loader; stop including Mixin Extras 2023-12-11 10:13:23 -05:00
embeddedt
adf169c3fa
Merge 1.20.2 into 1.20.3 2023-12-11 09:56:50 -05:00
embeddedt
8d5e66218e
Merge 1.20 into 1.20.2 2023-12-11 09:56:49 -05:00
embeddedt
45b734dead
Merge remote-tracking branch 'origin/1.20.2' into 1.20.3 2023-12-09 13:51:28 -05:00
embeddedt
2ec1000ae8
Merge remote-tracking branch 'origin/1.20' into 1.20.2 2023-12-09 13:51:22 -05:00
embeddedt
1f66c7becd
Merge 1.20.2 into 1.20.3 2023-12-06 20:44:42 -05:00
embeddedt
ccc21d76d8
Merge 1.20 into 1.20.2 2023-12-06 20:44:41 -05:00
embeddedt
4fec9f53c3 Fix publishing to CF 2023-12-05 18:12:48 -05:00
embeddedt
b8cd5adbb1 Update Fabric Loader to fix tests 2023-12-05 18:09:10 -05:00
embeddedt
bf69e58169 Merge remote-tracking branch 'origin/neoforge/1.20.2' into 1.20.3 2023-12-05 18:01:12 -05:00
embeddedt
6592ac5cac Update to 1.20.3 2023-12-05 18:00:07 -05:00
embeddedt
1f447b689f
Add back Forge item model shaper mixin 2023-12-03 20:41:07 -05:00
embeddedt
8df6fab0e7
Fix AT not being added to production jar 2023-12-03 20:37:53 -05:00
embeddedt
328507cea3
Fix blockstate ID reassignment being broken 2023-12-03 20:35:26 -05:00
embeddedt
c6b38f340a
Second rename pass, reaches main menu 2023-12-03 20:33:08 -05:00
embeddedt
69a9aa76da
Compiles, not yet running 2023-12-03 20:20:33 -05:00
embeddedt
87ee1017ae
Fix mistake in build script 2023-12-03 19:44:49 -05:00
embeddedt
fcf21283d8
Switch build target to NeoForge 2023-12-03 19:44:05 -05:00
embeddedt
bfdd1f913d
Merge 1.20 into 1.20.2 2023-12-03 19:28:56 -05:00
embeddedt
3187c80d48
Merge 1.20.2 into 1.20.3 2023-12-03 19:28:56 -05:00
embeddedt
f594ec6c5b Update test mod 2023-11-30 13:51:28 -05:00
embeddedt
efa46c3842 Merge 1.20.2 into 1.20.3 2023-11-30 13:42:36 -05:00
embeddedt
473597a915 Fix config screen background 2023-11-30 13:42:22 -05:00
embeddedt
84061b197f 1.20.3-rc1 2023-11-30 13:38:30 -05:00
embeddedt
dc86d3e137 23w45a 2023-11-30 13:18:08 -05:00
embeddedt
4d111cb381
Merge 1.20.2 into 1.20.3 2023-11-27 07:43:53 -05:00
embeddedt
29d1f88539
Merge 1.20 into 1.20.2 2023-11-27 07:43:52 -05:00
embeddedt
0ff032bd1a
Merge 1.20.2 into 1.20.3 2023-11-27 07:43:20 -05:00
embeddedt
e34e9fcf8b
Merge branch 'propagations/1.20' into propagations/1.20.2 2023-11-27 07:43:15 -05:00
embeddedt
9861926f1d Merge 1.20.2 into 1.20.3 2023-11-23 10:12:21 -05:00
embeddedt
acb6809459 Merge 1.20 into 1.20.2 2023-11-23 10:12:20 -05:00
embeddedt
fd975388ca Merge 1.20.2 into 1.20.3 2023-11-23 09:51:42 -05:00
embeddedt
13ee6b3523 Merge 1.20 into 1.20.2 2023-11-23 09:51:14 -05:00
embeddedt
af8e23f41a Fix mixin target 2023-11-21 12:38:02 -05:00
embeddedt
19ba30280c Update Loom 2023-11-21 12:37:30 -05:00
embeddedt
33609d234c Completely remove BitSet trimming 2023-11-21 12:27:02 -05:00
TonimatasDEV
6e3134161a
Forge 1.20.2 (#301) 2023-11-21 12:17:11 -05:00
embeddedt
27142d2c42
Merge 1.20.2 into 1.20.3 2023-11-11 17:26:28 -05:00
embeddedt
c672948d8c
Merge 1.20 into 1.20.2 2023-11-11 17:26:27 -05:00
embeddedt
0a418bc55d Merge 1.20.2 into 1.20.3 2023-11-07 17:27:30 -05:00
embeddedt
d8263c55f8 Merge 1.20 into 1.20.2 2023-11-07 17:27:28 -05:00
embeddedt
a212a3fc7e
Merge 1.20.2 into 1.20.3 2023-11-05 21:59:34 -05:00
embeddedt
7af609b56f
Merge 1.20 into 1.20.2 2023-11-05 21:59:33 -05:00
embeddedt
45c11ea7e0
Merge 1.20.2 into 1.20.3 2023-11-05 21:37:18 -05:00
embeddedt
894173cf1d
Remove unused import 2023-11-05 21:35:15 -05:00
embeddedt
fc52570951
Update cache_profile_texture_url for 1.20.2 2023-11-05 21:32:27 -05:00
embeddedt
207521f778
Merge 1.20.2 into 1.20.3 2023-11-05 21:25:23 -05:00
embeddedt
9efe912090
Merge 1.20 into 1.20.2 2023-11-05 21:25:22 -05:00
embeddedt
15d16ffa9a
Merge 1.20.2 into 1.20.3 2023-11-04 09:02:17 -04:00
embeddedt
95f2dc95d3
Merge 1.20 into 1.20.2 2023-11-04 09:02:16 -04:00
embeddedt
86c6e90436 Support closed flag on BufferBuilders
Thanks to Moulberry for noting this vanilla change
2023-11-02 13:35:25 -04:00
embeddedt
915de8187e 23w44a 2023-11-02 13:34:15 -04:00
embeddedt
181be3cf80 Merge 1.20.2 into 1.20.3 2023-10-30 14:54:27 -04:00
embeddedt
79751dac21 Merge 1.20 into 1.20.2 2023-10-30 14:54:21 -04:00
embeddedt
184dec0739
Merge 1.20.2 into 1.20.3 2023-10-29 21:17:26 -04:00
embeddedt
1339fc7af6
Merge 1.20 into 1.20.2 2023-10-29 21:17:26 -04:00
embeddedt
624a4483eb
Merge 1.20.2 into 1.20.3 2023-10-29 11:44:32 -04:00
embeddedt
3b7d2f1e2e
Merge 1.20 into 1.20.2 2023-10-29 11:44:31 -04:00
embeddedt
91a084f860
Merge 1.20.2 into 1.20.3 2023-10-29 11:41:44 -04:00
embeddedt
546a362d9c
Merge 1.20 into 1.20.2 2023-10-29 11:41:44 -04:00
embeddedt
87b984bfe9
Merge 1.20.2 into 1.20.3 2023-10-29 11:37:50 -04:00
embeddedt
7a2b71381c
Merge 1.20 into 1.20.2 2023-10-29 11:37:50 -04:00
embeddedt
850fdcbf1b
Merge 1.20.2 into 1.20.3 2023-10-28 20:06:04 -04:00
embeddedt
3add97202e
Merge 1.20 into 1.20.2 2023-10-28 20:06:03 -04:00
embeddedt
5d481334a8
Merge 1.20.2 into 1.20.3 2023-10-28 09:54:26 -04:00
embeddedt
6d096e8ae0
Merge 1.20 into 1.20.2 2023-10-28 09:54:26 -04:00
embeddedt
c09b530a8c Merge 1.20.2 into 1.20.3 2023-10-25 17:18:47 -04:00
embeddedt
fbacc85f86 Merge 1.20 into 1.20.2 2023-10-25 17:18:46 -04:00
embeddedt
0e9142e68f Merge 1.20.2 into 1.20.3 2023-10-25 15:00:21 -04:00
embeddedt
f6f7badde8 Merge 1.20 into 1.20.2 2023-10-25 15:00:20 -04:00
embeddedt
2c5b664c68 Merge 1.20.2 into 1.20.3 2023-10-25 14:24:19 -04:00
embeddedt
2a099d8537 Merge 1.20 into 1.20.2 2023-10-25 14:24:18 -04:00
embeddedt
472ed42f22 23w43a 2023-10-25 14:11:52 -04:00
embeddedt
9830d4d6f7 Merge 1.20.2 into 1.20.3 2023-10-25 14:04:07 -04:00
embeddedt
348a2bcf3d Merge 1.20 into 1.20.2 2023-10-25 14:04:06 -04:00
embeddedt
43da9ffcdc Merge 1.20.2 into 1.20.3 2023-10-24 12:45:44 -04:00
embeddedt
7f80f38862 Merge 1.20 into 1.20.2 2023-10-24 12:45:41 -04:00
embeddedt
231c3f41e5 23w42a 2023-10-18 14:45:34 -04:00
embeddedt
cc54b6d67d
Merge 1.20 into 1.20.2 2023-10-13 10:47:53 -04:00
embeddedt
e8fa483917
Merge 1.20 into 1.20.2 2023-10-10 17:40:31 -04:00
embeddedt
dc3cb998b0
Merge 1.20 into 1.20.2 2023-10-09 08:37:43 -04:00
embeddedt
972121fa50 Merge 1.20 into 1.20.2 2023-10-07 18:47:12 -04:00
embeddedt
93554d1854 Merge 1.20 into 1.20.2 2023-10-07 17:48:39 -04:00
embeddedt
a00efe62c7 Merge 1.20 into 1.20.2 2023-10-07 17:46:25 -04:00
embeddedt
1267a25db1 Merge 1.20 into 1.20.2 2023-10-06 17:07:49 -04:00
embeddedt
0149a113a8 Merge 1.20 into 1.20.2 2023-10-05 14:12:36 -04:00
embeddedt
97d4f6bbc2 Merge 1.20 into 1.20.2 2023-10-03 13:45:38 -04:00
embeddedt
dfb0c52fa3 Merge 1.20 into 1.20.2 2023-09-27 17:58:53 -04:00
embeddedt
02fa2be42b
Merge 1.20 into 1.20.2 2023-09-24 12:50:16 -04:00
embeddedt
45c29216a8
Spotless 2023-09-24 12:36:16 -04:00
embeddedt
5e8e7649e5
Merge 1.20 into 1.20.2 2023-09-24 12:34:00 -04:00
embeddedt
0a2cda0814
Disable recursive fluidstate test on 1.20.2 for now 2023-09-24 12:28:58 -04:00
embeddedt
5952fa2178
Merge 1.20 into 1.20.2 2023-09-24 12:19:14 -04:00
embeddedt
9bf0017aeb
1.20.2 2023-09-24 12:15:55 -04:00
embeddedt
cb286c0bca
1.20.2-pre3 2023-09-13 22:01:13 -04:00
embeddedt
b56a65c192
Merge remote-tracking branch 'origin/1.20' into dev/1.20.2 2023-09-05 11:21:20 -04:00
embeddedt
8d1058cc3f
23w33a 2023-08-17 11:55:44 -04:00
embeddedt
eb15718023
Merge remote-tracking branch 'origin/1.20' into dev/1.20.2 2023-08-17 11:30:19 -04:00
embeddedt
861474d635
23w32a 2023-08-09 12:07:35 -04:00
embeddedt
f3bda91ebf
Update Fabric API, fixes tests 2023-08-09 11:46:39 -04:00
embeddedt
84c72f8da8
Merge branch '1.20' into dev/1.20.2 2023-08-09 11:35:59 -04:00
embeddedt
3716912a53
Merge remote-tracking branch 'origin/1.20' into dev/1.20.2 2023-08-03 12:21:14 -04:00
embeddedt
42688757a7
Merge remote-tracking branch 'origin/1.20' into dev/1.20.2 2023-08-03 12:07:48 -04:00
embeddedt
23b473f85d
Move tags update mixin to ClientCommonPacketListenerImpl 2023-08-02 20:08:30 -04:00
embeddedt
7fcaf716d8
23w31a 2023-08-02 20:01:34 -04:00
470 changed files with 6170 additions and 14187 deletions

View File

@ -4,75 +4,51 @@ body:
- type: markdown
attributes:
value: >-
**Need help?** Ask on [Discord](https://discord.gg/rN9Y7caguP) instead of opening an issue.
**Note: This issue tracker is not intended for support requests!** If you need help with crashes or other issues, then
you should [ask on our Discord server](https://discord.gg/rN9Y7caguP) instead. Unless you are certain that you
have found a defect, and you are able to point to where the problem is, you should not open an issue.
<br><br>
Additionally, please make sure you have done the following:
**Issues that do not meet the requirements below (or are otherwise impossible to address with the given info) will be closed without investigation.**
- type: checkboxes
id: confirmations
attributes:
label: Checklist
options:
- label: I am reporting a defect, not asking for help
required: true
- label: I have searched existing issues and this has not been reported
required: true
- label: I have reduced my mod list to the minimum required to reproduce this issue (see below)
required: true
- **Have you ensured that all of your mods (including ModernFix) are up-to-date?** The latest version of ModernFix
can always be found [on Modrinth](https://modrinth.com/mod/modernfix).
- **Have you used the [search tool](https://github.com/embeddedt/ModernFix/issues) to check whether your issue
has already been reported?** If it has been, then consider adding more information to the existing issue instead.
- **Have you determined the minimum set of instructions to reproduce the issue?** If your problem only occurs
with other mods installed, then you should narrow down exactly which mods are causing the issue. Please do not
provide your entire list of mods to us and expect that we will be able to figure out the problem.
- type: textarea
id: description
attributes:
label: Bug Description
description: >-
Describe the issue in detail. Be sure to include what you expected to happen and what actually happened.
validations:
required: true
- type: textarea
id: minimal-mods
attributes:
label: Minimal Mod List
description: >-
List ONLY the mods required to reproduce this issue. Maintainers have debugging tools that help them
locate problems quickly, but these generally don't work well in modpacks or large mod sets.
A minimal list should typically contain fewer than 10 mods.
Use this section to describe the issue you are experiencing in as much depth as possible. The description should
explain what behavior you were expecting, and why you believe the issue to be a bug. If the issue you are reporting
only occurs with specific mods installed, then provide the name and version of each mod.
Reports with large mod lists will likely be closed without investigation, unless the problem is very clear.
If you don't know which mods are causing your problem, use binary search:
1. Remove half your mods
2. Test if the issue still occurs
3. If yes, remove half again. If no, restore the last removed half and repeat from step 1.
4. Repeat until only the necessary mods remain
placeholder: "- ModernFix 5.x.x\n- SomeMod 1.2.3"
validations:
required: true
**Hint:** If you have any screenshots, videos, or other information that you feel is necessary to
explain the issue, you can attach them here.
- type: textarea
id: description-reproduction-steps
attributes:
label: Reproduction Steps
description: >-
Provide clear steps to reproduce the bug. Each step should be a single concrete action.
Maintainers are busy and need to be able to quickly replicate your problem. Your reproduction steps should be
clear enough for someone who is unfamiliar with your mods to follow in 5 minutes or less (not counting time
to launch the game).
Providing vague steps is likely to result in the issue being closed.
placeholder: "1. \n2. \n3. "
Provide as much information as possible on how to reproduce this bug. Make sure your instructions are as clear and
concise as possible, because other people will need to be able to follow your guide in order to re-create the issue.
**Hint:** A common way to fill this section out is to write a step-by-step guide.
validations:
required: true
- type: textarea
id: diagnostic-info
id: log-file
attributes:
label: Diagnostic Info
label: Log File
description: >-
Drag and drop `latest.log` from `.minecraft/logs/` for the session where the issue occurred.
Do not paste log text inline. Issues without a valid `latest.log` will be closed.
If a crash occurred, also attach the relevant file from `.minecraft/crash-reports/`.
**Hint:** You can usually find the log files within the folder `.minecraft/logs`. Most often, you will want the `latest.log`
file, since that file belongs to the last played session of the game.
placeholder: >-
Drag-and-drop the log file here.
validations:
required: true

View File

@ -11,11 +11,6 @@ on:
jobs:
build:
runs-on: ubuntu-22.04
permissions:
issues: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout Repository
uses: actions/checkout@v4
@ -27,108 +22,20 @@ jobs:
distribution: 'temurin'
java-version: 21
check-latest: true
- name: Check if release branch
id: check_branch
if: github.event_name == 'push'
run: |
if [[ "${{ github.ref }}" =~ ^refs/heads/[0-9]+\. ]]; then
echo "is_release=true" >> $GITHUB_OUTPUT
else
echo "is_release=false" >> $GITHUB_OUTPUT
fi
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ steps.check_branch.outputs.is_release != 'true' }}
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/1.') }}
gradle-home-cache-cleanup: true
- name: Remove tags for release on other versions
if: steps.check_branch.outputs.is_release == 'true'
run: ./scripts/tagcleaner.sh
- name: Setup project Loom cache
uses: actions/cache@v4
with:
path: |
.gradle/loom-cache
key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle.properties', '**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Build ModernFix using Gradle
run: ./gradlew build
- name: Run mixin audit
run: timeout 60 xvfb-run ./gradlew runAuditClient
- name: Publish mod to CurseForge & Modrinth
if: steps.check_branch.outputs.is_release == 'true'
run: ./gradlew publishMods copyJarToBin
env:
CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
- name: Capture mod version
if: steps.check_branch.outputs.is_release == 'true'
run: |
echo "MOD_VERSION=$(./gradlew properties -q | grep '^version:' | awk '{print $2}')" >> $GITHUB_ENV
echo "MC_VERSION=$(grep '^minecraft_version=' gradle.properties | cut -d= -f2)" >> $GITHUB_ENV
- name: Comment on fixed issues
if: steps.check_branch.outputs.is_release == 'true'
uses: actions/github-script@v7
with:
script: |
const { execSync } = require('child_process');
const branch = context.ref.replace('refs/heads/', '');
const { data: runs } = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'gradle.yml',
branch,
status: 'success',
per_page: 1
});
const logArgs = runs.workflow_runs.length > 0
? `${runs.workflow_runs[0].head_sha}..${context.sha}`
: `-1 ${context.sha}`;
const log = execSync(`git log ${logArgs} --format=%s%n%b`, { encoding: 'utf8' });
const issueNumbers = new Set();
const pattern = /(?:fix(?:es|ed)?|close[sd]?|resolve[sd]?)\s+#(\d+)/gi;
let match;
while ((match = pattern.exec(log)) !== null) {
issueNumbers.add(parseInt(match[1]));
}
if (issueNumbers.size === 0) {
console.log('No fixed issues found in commits');
return;
}
const MARKER = '<!-- modernfix-fix-tracker -->';
const modVersion = process.env.MOD_VERSION;
const mcVersion = process.env.MC_VERSION;
const newLine = `- ${modVersion} for Minecraft ${mcVersion}`;
for (const issueNumber of issueNumbers) {
try {
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
per_page: 100
});
const existing = comments.find(c => c.body.includes(MARKER));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body: existing.body + `\n${newLine}`
});
console.log(`Updated comment on issue #${issueNumber}`);
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `${MARKER}\nThe fix for this issue has been released in the following versions of ModernFix:\n${newLine}`
});
console.log(`Created comment on issue #${issueNumber}`);
}
} catch (e) {
console.log(`Could not comment on #${issueNumber}: ${e.message}`);
}
}
- name: Upload Artifacts to GitHub
uses: actions/upload-artifact@v4
with:

41
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Release ModernFix Artifacts
on:
release:
types:
- published
jobs:
release:
if: github.repository_owner == 'embeddedt'
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 21
check-latest: true
- name: Remove tags for release on other versions
run: ./scripts/tagcleaner.sh
- name: Build and publish mod to CurseForge & Modrinth
run: ./gradlew publishToModSites copyJarToBin
env:
CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
- name: Upload assets to GitHub
uses: AButler/upload-release-assets@v3.0
with:
files: 'bin/*'
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add changelog to release
uses: irongut/EditRelease@v1.2.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
id: ${{ github.event.release.id }}
replacebody: true
files: "CHANGELOG.md"

View File

@ -1,6 +1,7 @@
plugins {
id 'com.gradleup.shadow' version '8.3.9'
id 'com.github.johnrengelman.shadow'
id 'java-library'
id 'com.diffplug.spotless'
}
repositories {
@ -30,7 +31,7 @@ dependencies {
}
tasks.withType(JavaCompile) {
options.release = 17
options.release = 21
}
shadowJar {
@ -51,4 +52,9 @@ shadowJar {
include {it.getName() == 'EnvType.class'}
}
spotless {
java {
removeUnusedImports()
}
}
version = '1.1.4'

View File

@ -90,19 +90,24 @@ public class ClientMixinValidator {
}
private boolean targetsClient(Object classTarget) {
if (classTarget instanceof TypeElement te) {
return isClientMarked(te);
} else if (classTarget instanceof TypeMirror tm) {
var el = types.asElement(tm);
return el != null ? targetsClient(el) : warn("TypeMirror of " + tm);
} else if (classTarget instanceof String s) {
var te = elemUtils.getTypeElement(toSourceString(s.split("\\$")[0]));
return te != null ? targetsClient(te) : warn(s);
} else {
throw new IllegalArgumentException("Unhandled type: "
return switch (classTarget) {
case TypeElement te ->
isClientMarked(te);
case TypeMirror tm -> {
var el = types.asElement(tm);
yield el != null ? targetsClient(el) : warn("TypeMirror of " + tm);
}
// If you're using a dollar sign in class names you are insane
case String s -> {
var te =
elemUtils.getTypeElement(toSourceString(s.split("\\$")[0]));
yield te != null ? targetsClient(te) : warn(s);
}
default ->
throw new IllegalArgumentException("Unhandled type: "
+ classTarget.getClass() + "\n" + "Stringified contents: "
+ classTarget.toString());
}
};
}
private boolean isClientMarked(TypeElement te) {
@ -161,6 +166,7 @@ public class ClientMixinValidator {
clzsses = wrappedClzss.stream()
.map(AnnotationValue::getValue)
.filter(o -> o instanceof TypeMirror)
.map(TypeMirror.class::cast)
.collect(Collectors.toSet());

View File

@ -25,7 +25,7 @@ public record MixinConfig(
InjectorOptions injectors, OverwriteOptions overwrites
) {
public MixinConfig(String packageName, List<String> commonMixins, List<String> clientMixins) {
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_17",
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_21",
commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT);
}
public record InjectorOptions(int defaultRequire) {

6
annotations/build.gradle Normal file
View File

@ -0,0 +1,6 @@
plugins {
id 'modernfix.common-conventions'
id 'java-library'
}
version = '1.1.0'

View File

@ -1,10 +0,0 @@
plugins {
id("java")
}
version = "1.1.0"
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@ -1,9 +0,0 @@
package org.embeddedt.modernfix.annotation;
public enum FeatureLevel {
GA, BETA;
public boolean isAtLeast(FeatureLevel required) {
return this.ordinal() >= required.ordinal();
}
}

View File

@ -1,12 +0,0 @@
package org.embeddedt.modernfix.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.PACKAGE})
public @interface RequiresFeatureLevel {
FeatureLevel value() default FeatureLevel.GA;
}

View File

@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.PACKAGE})
@Target(ElementType.TYPE)
public @interface RequiresMod {
String value() default "";
}

67
build.gradle Normal file
View File

@ -0,0 +1,67 @@
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.9-SNAPSHOT" apply false
id "maven-publish"
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
id 'com.palantir.git-version' version '1.0.0'
id 'org.ajoberstar.grgit' version '5.2.0'
id 'se.bjurr.gitchangelog.git-changelog-gradle-plugin' version '1.79.0'
id "com.modrinth.minotaur" version "2.+" apply false
id("com.diffplug.spotless") version "6.25.0" apply false
id 'modernfix.common-conventions' apply false
}
architectury {
minecraft = rootProject.minecraft_version
}
ext.archives_base_name = 'modernfix'
apply plugin: 'modernfix.common-conventions'
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
options.encoding = "UTF-8"
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
/*
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
}
*/
}
tasks.register('generateChangelog', se.bjurr.gitchangelog.plugin.gradle.GitChangelogTask) {
def details = versionDetails();
def theVersionRef
if (details.commitDistance > 0) {
theVersionRef = details.lastTag;
} else {
def secondLastTagCmd = "git describe --abbrev=0 " + details.lastTag + "^"
def secondLastTag = secondLastTagCmd.execute().text.trim()
theVersionRef = secondLastTag;
}
fromRef = theVersionRef
file = new File("${rootDir}/CHANGELOG.md");
templateContent = new File("${rootDir}/gradle/changelog.mustache").getText('UTF-8').replace("[[modernFixVersionRef]]", theVersionRef);
toCommit = "HEAD";
}
tasks.register('checkCleanTag') {
doLast {
def details = versionDetails()
if (!details.isCleanTag || versionDetails().commitDistance != 0) {
throw new GradleException('Not a clean tree.')
}
}
}
println "ModernFix: " + version

View File

@ -1,210 +0,0 @@
plugins {
id("net.neoforged.moddev.legacyforge") version("2.0.134")
id("me.modmuss50.mod-publish-plugin") version("1.1.0")
}
val minecraft_version = rootProject.properties["minecraft_version"].toString()
group = "org.embeddedt"
val gitVersion = providers.of(GitVersionSource::class) {
parameters {
minecraftVersion.set(minecraft_version)
projectDir.set(rootProject.layout.projectDirectory)
}
}
version = gitVersion.get()
base.archivesName = "modernfix-forge"
legacyForge {
enable {
forgeVersion = rootProject.properties["forge_version"].toString()
isDisableRecompilation = System.getenv("CI") == "true"
}
rootProject.properties["parchment_version"]?.let { parchmentVer ->
parchment {
minecraftVersion = minecraft_version
mappingsVersion = parchmentVer.toString()
}
}
runs {
create("client") {
client()
}
create("server") {
server()
}
create("auditClient") {
client()
jvmArguments.addAll("-Dmodernfix.auditAndExit=true", "-Djava.awt.headless=true")
}
}
mods {
create("modernfix") {
sourceSet(sourceSets.main.get())
}
}
}
mixin {
add(sourceSets.main.get(), "modernfix.refmap.json")
config("modernfix-modernfix.mixins.json")
}
tasks.named<Jar>("jar") {
manifest.attributes(mapOf(
"MixinConfigs" to "modernfix-modernfix.mixins.json",
"Specification-Version" to "1",
"Implementation-Title" to project.name,
"Implementation-Version" to version
))
}
java {
val curSourceCompatLevel = JavaVersion.VERSION_17
sourceCompatibility = curSourceCompatLevel
targetCompatibility = curSourceCompatLevel
}
repositories {
exclusiveContent {
forRepository {
maven {
// location of the maven that hosts JEI files
name = "Progwml6 maven"
url = uri("https://dvs1.progwml6.com/files/maven/")
}
}
forRepository {
maven {
name = "ModMaven"
url = uri("https://modmaven.dev")
}
}
filter {
includeGroup("mezz.jei")
}
}
exclusiveContent {
forRepository {
maven("https://cursemaven.com")
}
filter {
includeGroup("curse.maven")
}
}
}
val embed by configurations.creating {
isCanBeConsumed = false
isCanBeResolved = true
isTransitive = true
}
dependencies {
implementation(project(":annotations"))
embed(project(":annotations"))
"additionalRuntimeClasspath"(project(":annotations"))
annotationProcessor(project(path = ":annotation-processor", configuration = "shadow"))
val mixinextrasVersion = rootProject.properties["mixinextras_version"].toString()
implementation("io.github.llamalad7:mixinextras-common:${mixinextrasVersion}")
annotationProcessor("net.fabricmc:sponge-mixin:0.12.5+mixin.0.8.5")
annotationProcessor("io.github.llamalad7:mixinextras-common:${mixinextrasVersion}")
implementation("io.github.llamalad7:mixinextras-forge:${mixinextrasVersion}")
"jarJar"("io.github.llamalad7:mixinextras-forge:${mixinextrasVersion}")
val jei_version = rootProject.properties["jei_version"].toString()
modCompileOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}")
modCompileOnly("curse.maven:spark-361579:${rootProject.properties["spark_version"].toString()}")
modCompileOnly("curse.maven:ctm-267602:${rootProject.properties["ctm_version"].toString()}")
modCompileOnly("curse.maven:ldlib-626676:${rootProject.properties["ldlib_version"].toString()}")
modCompileOnly("curse.maven:supermartijncore-454372:4455391")
modCompileOnly("curse.maven:patchouli-306770:6164575")
modCompileOnly("curse.maven:cofhcore-69162:5374122")
modCompileOnly("curse.maven:resourcefullib-570073:5659871")
modCompileOnly("curse.maven:kubejs-238086:5853326")
modCompileOnly("curse.maven:terrablender-563928:6290448")
}
tasks.named<Jar>("jar") {
from(embed.map { if (it.isDirectory) it else zipTree(it) })
}
// For the AP
tasks.withType<JavaCompile>().configureEach {
if (!name.lowercase().contains("test")) {
options.compilerArgs.addAll(
listOf(
"-ArootProject.name=${rootProject.name}",
"-Aproject.name=${project.name}"
)
)
}
}
sourceSets {
main {
resources.srcDir(
layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main/resources")
)
}
}
tasks.named<ProcessResources>("processResources") {
dependsOn(tasks.named("compileJava"))
inputs.property("version", project.version)
filesMatching("META-INF/mods.toml") {
expand("version" to project.version)
}
}
val finalJarTask = "reobfJar"
tasks.register<Copy>("copyJarNameConsistent") {
from(tasks.named<Jar>(finalJarTask).get().outputs.files)
into(project.file("build/libs"))
rename { _ -> "modernfix-" + project.name + "-latest.jar" }
}
tasks.register<Copy>("copyJarToBin") {
from(tasks.named<Jar>(finalJarTask).get().outputs.files)
into(rootProject.file("bin"))
mustRunAfter(tasks.named("copyJarNameConsistent"))
}
tasks.named("build") {
dependsOn("copyJarToBin", "copyJarNameConsistent")
}
publishMods {
file.set(tasks.named<Jar>(finalJarTask).flatMap { it.archiveFile })
displayName.set(tasks.named<Jar>(finalJarTask).flatMap { it.archiveFileName })
changelog = "Please check the [GitHub wiki](https://github.com/embeddedt/ModernFix/wiki/Changelog) for major changes."
type = STABLE
modLoaders.add("forge")
curseforge {
projectId = "790626"
projectSlug = "modernfix"
accessToken = providers.environmentVariable("CURSEFORGE_TOKEN")
minecraftVersions.add(minecraft_version)
}
modrinth {
projectId = "nmDcB62a"
accessToken = providers.environmentVariable("MODRINTH_TOKEN")
minecraftVersions.add(minecraft_version)
}
}
tasks.named("publishMods") {
dependsOn(finalJarTask)
}

3
buildSrc/build.gradle Normal file
View File

@ -0,0 +1,3 @@
plugins {
id 'groovy-gradle-plugin'
}

View File

@ -1,7 +0,0 @@
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}

0
buildSrc/settings.gradle Normal file
View File

View File

@ -0,0 +1,137 @@
plugins {
id 'java'
id 'architectury-plugin'
id 'maven-publish'
id 'com.diffplug.spotless'
}
spotless {
java {
removeUnusedImports()
}
}
architectury {
compileOnly()
}
group = 'org.embeddedt'
// extract base version from tag, generate other metadata ourselves
def details = versionDetails()
def plusIndex = details.lastTag.indexOf("+")
if(plusIndex == -1) {
plusIndex = details.lastTag.length()
}
def baseVersion = details.lastTag.substring(0, plusIndex)
def dirtyMarker = grgit.status().clean ? "" : ".dirty"
def commitHashMarker = details.commitDistance > 0 ? ("." + details.gitHash.substring(0, Math.min(4, details.gitHash.length()))) : ""
def preMarker = (details.commitDistance > 0 || !details.isCleanTag) ? ("-beta." + details.commitDistance) : ""
if(preMarker.length() > 0) {
// bump to next patch release
def versionParts = baseVersion.tokenize(".")
baseVersion = "${versionParts[0]}.${versionParts[1]}.${versionParts[2].toInteger() + 1}"
}
def versionString = "${baseVersion}${preMarker}+mc${minecraft_version}${commitHashMarker}${dirtyMarker}"
version = versionString
archivesBaseName = rootProject.archives_base_name + '-' + project.name
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21
repositories {
exclusiveContent {
forRepository {
maven {
url "https://modmaven.dev"
}
}
filter {
includeGroup "appeng"
includeGroup "vazkii.patchouli"
includeGroup "mezz.jei"
}
}
exclusiveContent {
forRepository {
maven {
url "https://cursemaven.com"
}
}
filter {
includeGroup "curse.maven"
}
}
exclusiveContent {
forRepository {
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org'
}
}
filter {
includeGroup "org.parchmentmc.data"
}
}
exclusiveContent {
forRepository {
maven {
url = 'https://maven.architectury.dev'
}
}
filter {
includeGroup "me.shedaniel"
}
}
exclusiveContent {
forRepository {
maven {
url = 'https://maven.saps.dev/minecraft'
}
}
filter {
includeGroup "dev.latvian.mods"
}
}
exclusiveContent {
forRepository {
maven {
name = "Fuzs Mod Resources"
url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/"
}
}
filter {
includeGroup "fuzs"
}
}
exclusiveContent {
forRepository {
maven {
name = "Fabric maven"
url = "https://maven.fabricmc.net/"
}
}
filter {
includeGroup "net.fabricmc"
}
}
exclusiveContent {
forRepository {
maven {
name = "Mod Menu"
url = "https://maven.terraformersmc.com/releases/"
}
}
filter {
includeGroup "com.terraformersmc"
}
}
exclusiveContent {
forRepository {
maven {
url "https://maven.tterrag.com"
}
}
filter {
includeGroup "team.chisel.ctm"
}
}
}

View File

@ -0,0 +1,42 @@
plugins {
id 'modernfix.common-conventions'
id 'dev.architectury.loom'
}
loom {
silentMojangMappingsLicense()
accessWidenerPath = file("${rootDir}/common/src/main/resources/modernfix.accesswidener")
mixin {
useLegacyMixinAp = true
}
}
dependencies {
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
if(rootProject.hasProperty("parchment_version")) {
parchment("org.parchmentmc.data:parchment-${parchment_mc_version}:${parchment_version}@zip")
}
}
implementation project(":annotations")
annotationProcessor project(path: ":annotation-processor", configuration: 'shadow')
}
project.sourceSets {
main.resources.srcDirs += [layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main/resources")]
}
// hack to shut up gradle about the hack to include generated resources
tasks {
processResources {
dependsOn compileJava
}
}
tasks.withType(JavaCompile) {
configure(options) {
if (!name.toLowerCase().contains('test')) {
options.compilerArgs << "-ArootProject.name=${rootProject.name}" << "-Aproject.name=${project.name}"
}
}
}

View File

@ -0,0 +1,69 @@
plugins {
id 'com.matthewprenger.cursegradle'
id 'com.modrinth.minotaur'
}
loom {
mods {
main { // to match the default mod generated for Forge
sourceSet project.sourceSets.main
sourceSet project(':common').sourceSets.main
}
}
runs {
client {
vmArgs "-Xmx1G"
vmArgs "-Xms1G"
property("mixin.debug.export", "true")
}
}
}
def copyJarNameConsistent = tasks.register('copyJarNameConsistent', Copy) {
from remapJar // shortcut for createJar.outputs.files
into project.file("build/libs")
rename { name -> "modernfix-" + project.name + "-latest.jar" }
}
def copyJarToBin = tasks.register('copyJarToBin', Copy) {
from remapJar // shortcut for createJar.outputs.files
into rootProject.file("bin")
mustRunAfter "copyJarNameConsistent"
}
tasks.build.dependsOn(copyJarToBin, copyJarNameConsistent)
def isBeta = project.version.toString().contains("beta")
curseforge {
if (System.getenv("CURSEFORGE_TOKEN") != null) {
apiKey = System.getenv("CURSEFORGE_TOKEN")
project {
id = "790626"
changelog = file("${rootDir}/CHANGELOG.md")
changelogType = "markdown"
releaseType = isBeta ? "beta" : "release"
addGameVersion (project.name.equals("neoforge") ? "NeoForge" : project.name.capitalize())
gameVersionStrings.addAll(supported_minecraft_versions.tokenize(","))
mainArtifact remapJar
}
}
}
modrinth {
token = System.getenv("MODRINTH_TOKEN")
projectId = "modernfix" // This can be the project ID or the slug. Either will work!
versionType = isBeta ? "beta" : "release" // This is the default -- can also be `beta` or `alpha`
uploadFile = remapJar
gameVersions = supported_minecraft_versions.tokenize(",")
loaders = [project.name]
changelog.set(provider { file("${rootDir}/CHANGELOG.md").getText('UTF-8') })
}
tasks.curseforge.dependsOn(rootProject.generateChangelog)
tasks.modrinth.dependsOn(rootProject.generateChangelog)
tasks.register('publishToModSites') {
publishToModSites.dependsOn(tasks.modrinth)
publishToModSites.dependsOn(tasks.curseforge)
}

View File

@ -1,61 +0,0 @@
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.ValueSource
import org.gradle.api.provider.ValueSourceParameters
import org.gradle.process.ExecOperations
import java.io.ByteArrayOutputStream
import java.io.File
import javax.inject.Inject
abstract class GitVersionSource : ValueSource<String, GitVersionSource.Parameters> {
interface Parameters : ValueSourceParameters {
val minecraftVersion: Property<String>
val projectDir: DirectoryProperty
}
@get:Inject
abstract val execOperations: ExecOperations
override fun obtain(): String {
val minecraftVersion = parameters.minecraftVersion.get()
val workDir = parameters.projectDir.get().asFile
val releaseLine = workDir.resolve("release_line.txt").readText().trim()
val patch = try {
// Find the most recent first-parent commit that touched release_line.txt
val lineStartCommit = git(workDir,
"log", "--first-parent",
"-n", "1",
"--format=%H",
"--",
"release_line.txt"
).trim()
if (lineStartCommit.isEmpty()) {
// count all first-parent commits as a safe fallback
git(workDir, "rev-list", "--count", "--first-parent", "HEAD")
.trim().toIntOrNull() ?: 0
} else {
git(workDir, "rev-list", "--count", "--first-parent", "$lineStartCommit..HEAD")
.trim().toIntOrNull() ?: 0
}
} catch (_: Exception) {
// Git is unavailable or this is not a git repository
999
}
return "$releaseLine.$patch+mc$minecraftVersion"
}
private fun git(workDir: File, vararg args: String): String {
val output = ByteArrayOutputStream()
execOperations.exec {
commandLine("git", *args)
standardOutput = output
workingDir(workDir)
}
return output.toString(Charsets.UTF_8)
}
}

44
common/build.gradle Normal file
View File

@ -0,0 +1,44 @@
plugins {
id "modernfix.mod-common-conventions"
}
architectury {
common(rootProject.enabled_platforms.split(","))
}
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}"))
modCompileOnly("dev.latvian.mods:kubejs:${kubejs_version}") {
transitive = false
}
modApi("dev.latvian.mods:rhino:${rhino_version}") {
transitive = false
}
modCompileOnly "curse.maven:spark-361579:${rootProject.spark_version}"
modCompileOnly fabricApi.module("fabric-model-loading-api-v1", rootProject.fabric_api_version)
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury:${rootProject.architectury_version}"
}
// don't need remapped common jar
tasks.named('remapJar') { enabled = false }
publishing {
publications {
mavenCommon(MavenPublication) {
artifactId = rootProject.archives_base_name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

@ -0,0 +1,21 @@
package org.embeddedt.modernfix;
import com.google.common.cache.CacheLoader;
import org.apache.commons.lang3.tuple.Pair;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileWalker extends CacheLoader<Pair<Path, Integer>, List<Path>> {
public static final FileWalker INSTANCE = new FileWalker();
@Override
public List<Path> load(Pair<Path, Integer> key) throws Exception {
try(Stream<Path> stream = Files.walk(key.getLeft(), key.getRight())) {
return stream.collect(Collectors.toList());
}
}
}

View File

@ -1,8 +1,8 @@
package org.embeddedt.modernfix;
import net.minecraft.SharedConstants;
import net.minecraft.TracingExecutor;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
@ -13,10 +13,8 @@ import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.resources.ReloadExecutor;
import org.embeddedt.modernfix.util.ClassInfoManager;
import org.spongepowered.asm.mixin.MixinEnvironment;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ExecutorService;
// The value here should match an entry in the META-INF/mods.toml file
public class ModernFix {
@ -33,7 +31,7 @@ public class ModernFix {
// Used to skip computing the blockstate caches twice
public static boolean runningFirstInjection = false;
private static ExecutorService resourceReloadService = null;
private static TracingExecutor resourceReloadService = null;
static {
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dedicated_reload_executor.ReloadExecutor")) {
@ -43,21 +41,10 @@ public class ModernFix {
}
}
public static ExecutorService resourceReloadExecutor() {
public static TracingExecutor resourceReloadExecutor() {
return resourceReloadService;
}
public static void runAuditIfRequested() {
boolean auditAndExit = Boolean.getBoolean("modernfix.auditAndExit");
if (auditAndExit || Boolean.getBoolean("modernfix.auditMixinsAtStart")) {
MixinEnvironment.getCurrentEnvironment().audit();
if (auditAndExit) {
// Prevents Crash Assistant from treating mixin audit as a crash
Minecraft.getInstance().stop();
System.exit(0);
}
}
}
public ModernFix() {
INSTANCE = this;

View File

@ -1,20 +1,19 @@
package org.embeddedt.modernfix;
import net.minecraft.client.Minecraft;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.MemoryReserve;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.api.constants.IntegrationConstants;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree;
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry;
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
import org.embeddedt.modernfix.util.ClassInfoManager;
import org.embeddedt.modernfix.world.IntegratedWatchdog;
import java.lang.management.ManagementFactory;
import java.util.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ModernFixClient {
@ -40,7 +39,6 @@ public class ModernFixClient {
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) {
brandingString = ModernFix.NAME + " " + ModernFixPlatformHooks.INSTANCE.getVersionString();
}
SearchTreeProviderRegistry.register(JEIBackedSearchTree.PROVIDER);
for(String className : ModernFixPlatformHooks.INSTANCE.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) {
try {
CLIENT_INTEGRATIONS.add((ModernFixClientIntegration)Class.forName(className).getDeclaredConstructor().newInstance());
@ -92,13 +90,29 @@ public class ModernFixClient {
ModernFix.LOGGER.warn("Time from main menu to in-game was " + timeSpentLoading + " seconds");
ModernFix.LOGGER.warn("Total time to load game and open world was " + (timeSpentLoading + gameStartTimeSeconds) + " seconds");
}
if (ModernFixPlatformHooks.INSTANCE.modPresent("spark") && ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_world_join.WorldJoin")) {
SparkLaunchProfiler.stop("world_join");
}
resetWorldLoadStateMachine();
}
}
/**
* Check if the IDs match and remap them if not.
* @return true if ID remap was needed
*/
private static boolean compareAndSwitchIds(Class<? extends Entity> eClass, String fieldName, EntityDataAccessor<?> accessor, int newId) {
if(accessor.id != newId) {
ModernFix.LOGGER.warn("Corrected ID mismatch on {} field {}. Client had {} but server wants {}.",
eClass,
fieldName,
accessor.id,
newId);
accessor.id = newId;
return true;
} else {
ModernFix.LOGGER.debug("{} {} ID fine: {}", eClass, fieldName, newId);
return false;
}
}
public void onServerStarted(MinecraftServer server) {
if(!ModernFixMixinPlugin.instance.isOptionEnabled("feature.integrated_server_watchdog.IntegratedWatchdog"))
return;

View File

@ -0,0 +1,37 @@
package org.embeddedt.modernfix.api.entrypoint;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.client.resources.model.UnbakedModel;
/**
* Implement this interface in a mod class and add it to "modernfix:integration_v1" in your mod metadata file
* to integrate with ModernFix's features.
*/
public interface ModernFixClientIntegration {
/**
* Called when the dynamic resources status has changed during a model reload so mods know whether to run their
* normal codepath or the dynamic version.
*
* @param enabled whether dynamic resources is enabled
*/
default void onDynamicResourcesStatusChange(boolean enabled) {
}
/**
* Called to allow mods to observe the loading of a baked model and either make changes to it or wrap it with their
* own instance.
*
* @param location the ResourceLocation of the model (this may be a ModelResourceLocation)
* @param originalModel the original model
* @param bakery the model bakery - do not touch internal fields as they probably don't behave the way you expect
* with dynamic resources on
* @param textureGetter function to retrieve textures for this model
* @return the model which should actually be loaded for this resource location
*/
default BakedModel onBakedModelLoad(ModelResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery, ModelBakery.TextureGetter textureGetter) {
return originalModel;
}
}

View File

@ -1,23 +1,18 @@
package org.embeddedt.modernfix.api.helpers;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import org.embeddedt.modernfix.duck.IExtendedModelBakery;
import org.embeddedt.modernfix.dynamicresources.ModelBakeryHelpers;
import org.embeddedt.modernfix.util.DynamicMap;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
@SuppressWarnings("unused")
public final class ModelHelpers {
@ -28,7 +23,7 @@ public final class ModelHelpers {
* @return a list of all blockstates related to the model
*/
public static ImmutableList<BlockState> getBlockStateForLocation(ModelResourceLocation location) {
Optional<Block> blockOpt = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(location.getNamespace(), location.getPath()));
Optional<Block> blockOpt = BuiltInRegistries.BLOCK.getOptional(location.id());
if(blockOpt.isPresent())
return ModelBakeryHelpers.getBlockStatesForMRL(blockOpt.get().getStateDefinition(), location);
else
@ -52,7 +47,7 @@ public final class ModelHelpers {
* @return a fake map of the top-level models
*/
public static Map<ResourceLocation, BakedModel> createFakeTopLevelMap(BiFunction<ResourceLocation, ModelState, BakedModel> modelGetter) {
return new DynamicMap<>(location -> modelGetter.apply(location, BlockModelRotation.X0_Y0));
return new DynamicMap<>(ResourceLocation.class, location -> modelGetter.apply(location, BlockModelRotation.X0_Y0));
}
/**
@ -61,6 +56,8 @@ public final class ModelHelpers {
* @return an appropriate ModelBaker
*/
public static ModelBaker adaptBakery(ModelBakery bakery) {
throw new UnsupportedOperationException("TODO");
/*
return new ModelBaker() {
@Override
public UnbakedModel getModel(ResourceLocation resourceLocation) {
@ -72,16 +69,8 @@ public final class ModelHelpers {
public BakedModel bake(ResourceLocation resourceLocation, ModelState modelState) {
return ((IExtendedModelBakery)bakery).bakeDefault(resourceLocation, modelState);
}
@Override
public @Nullable BakedModel bake(ResourceLocation location, ModelState state, Function<Material, TextureAtlasSprite> sprites) {
throw new UnsupportedOperationException();
}
@Override
public Function<Material, TextureAtlasSprite> getModelTextureGetter() {
return Material::sprite;
}
};
*/
}
}

View File

@ -6,7 +6,7 @@ import net.minecraft.world.level.block.state.BlockState;
import org.embeddedt.modernfix.duck.IBlockState;
public class BlockStateCacheHandler {
public static void invalidateCache() {
public static void rebuildParallel(boolean force) {
synchronized (BlockBehaviour.BlockStateBase.class) {
for (BlockState blockState : Block.BLOCK_STATE_REGISTRY) {
((IBlockState)blockState).clearCache();

View File

@ -0,0 +1,62 @@
package org.embeddedt.modernfix.blockstate;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
public class FerriteCorePostProcess {
private static final boolean willPostProcess;
private static final MethodHandle theTable, toKeyIndex;
static {
boolean success = true;
MethodHandle table = null, keyIndex = null;
try {
Class<?> fastMap = Class.forName("malte0811.ferritecore.fastmap.FastMap");
Field field = fastMap.getDeclaredField("toKeyIndex");
field.setAccessible(true);
keyIndex = MethodHandles.publicLookup().unreflectSetter(field);
field = StateHolder.class.getDeclaredField("ferritecore_globalTable");
field.setAccessible(true);
table = MethodHandles.publicLookup().unreflectGetter(field);
} catch(ReflectiveOperationException | RuntimeException e) {
e.printStackTrace();
success = false;
}
willPostProcess = success;
theTable = table;
toKeyIndex = keyIndex;
}
private static final Object2IntMap<?> EMPTY_MAP;
static {
Object2IntArrayMap<?> map = new Object2IntArrayMap<>();
map.defaultReturnValue(-1);
EMPTY_MAP = Object2IntMaps.unmodifiable(map);
}
public static <O, S extends StateHolder<O, S>> void postProcess(StateDefinition<O, S> state) {
if(!willPostProcess)
return;
try {
if(state.getProperties().size() == 0) {
for(S holder : state.getPossibleStates()) {
// deduplicate Object2IntMap objects from FerriteCore
// will probably be fixed upstream at some point, but likely not for older versions
Object table = theTable.invoke(holder);
toKeyIndex.invoke(table, EMPTY_MAP);
}
}
} catch(Throwable e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,73 @@
package org.embeddedt.modernfix.chunk;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.Nullable;
public class SafeBlockGetter implements BlockGetter {
private final ServerLevel wrapped;
private final Thread mainThread;
public SafeBlockGetter(ServerLevel wrapped) {
this.wrapped = wrapped;
this.mainThread = Thread.currentThread();
}
public boolean shouldUse() {
return Thread.currentThread() != this.mainThread;
}
@Nullable
private BlockGetter getChunkSafe(BlockPos pos) {
// can safely call getChunkForLighting off-thread
BlockGetter access = this.wrapped.getChunkSource().getChunkForLighting(pos.getX() >> 4, pos.getZ() >> 4);
if(!(access instanceof ChunkAccess))
return null;
ChunkAccess chunk = (ChunkAccess)access;
if(!chunk.getPersistedStatus().isOrAfter(ChunkStatus.FULL))
return null;
return chunk;
}
@Override
public int getMaxY() {
return this.wrapped.getMaxY();
}
@Override
public int getMinY() {
return this.wrapped.getMinY();
}
@Override
public int getHeight() {
return this.wrapped.getHeight();
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
BlockGetter g = getChunkSafe(pos);
return g == null ? null : g.getBlockEntity(pos);
}
@Override
public BlockState getBlockState(BlockPos pos) {
BlockGetter g = getChunkSafe(pos);
return g == null ? Blocks.AIR.defaultBlockState() : g.getBlockState(pos);
}
@Override
public FluidState getFluidState(BlockPos pos) {
BlockGetter g = getChunkSafe(pos);
return g == null ? Fluids.EMPTY.defaultFluidState() : g.getFluidState(pos);
}
}

View File

@ -0,0 +1,10 @@
package org.embeddedt.modernfix.command;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
public class ModernFixCommands {
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
}
}

View File

@ -1,6 +1,7 @@
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.gameevent.GameEvent;
@ -17,8 +18,8 @@ public class EntityMixin {
* tries to raytrace blocks. To fix this, we skip firing the sculk event if the chunk the entity is within is not
* loaded.
*/
@WrapWithCondition(method = "addPassenger", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;gameEvent(Lnet/minecraft/world/level/gameevent/GameEvent;Lnet/minecraft/world/entity/Entity;)V"))
private boolean onlyAddIfSelfChunkLoaded(Entity instance, GameEvent event, Entity entity) {
@WrapWithCondition(method = "addPassenger", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;gameEvent(Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;)V"))
private boolean onlyAddIfSelfChunkLoaded(Entity instance, Holder<GameEvent> gameEvent, Entity entity) {
var chunkPos = instance.chunkPosition();
if (instance.level() instanceof ServerLevel serverLevel && serverLevel.getChunkSource().getChunkNow(chunkPos.x, chunkPos.z) == null) {
ModernFix.LOGGER.warn("Skipped emitting ENTITY_MOUNT game event for entity {} as it would cause deadlock", instance.toString());

View File

@ -0,0 +1,18 @@
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
import net.minecraft.server.level.ServerLevel;
import org.embeddedt.modernfix.chunk.SafeBlockGetter;
import org.embeddedt.modernfix.duck.ISafeBlockGetter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(ServerLevel.class)
public class ServerLevelMixin implements ISafeBlockGetter {
@Unique
private final SafeBlockGetter mfix$safeBlockGetter = new SafeBlockGetter((ServerLevel)(Object)this);
@Override
public SafeBlockGetter mfix$getSafeBlockGetter() {
return mfix$safeBlockGetter;
}
}

View File

@ -0,0 +1,36 @@
package org.embeddedt.modernfix.common.mixin.bugfix.concurrency;
import net.minecraft.client.Minecraft;
import net.minecraft.util.thread.BlockableEventLoop;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import java.util.function.BooleanSupplier;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public abstract class MinecraftMixin<R extends Runnable> extends BlockableEventLoop<R> {
protected MinecraftMixin(String p_i50403_1_) {
super(p_i50403_1_);
}
@Override
public void managedBlock(BooleanSupplier pIsDone) {
if(!this.isSameThread()) {
ModernFix.LOGGER.warn("A mod is calling Minecraft.managedBlock from the wrong thread. This is most likely related to one of our parallelizations.");
ModernFix.LOGGER.warn("ModernFix will work around this, however ideally the issue should be patched in the other mod.");
ModernFix.LOGGER.warn("Stacktrace", new IllegalThreadStateException());
while(!pIsDone.getAsBoolean()) {
try {
Thread.sleep(100);
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} else {
super.managedBlock(pIsDone);
}
}
}

View File

@ -86,9 +86,11 @@ public abstract class LevelChunkMixin extends ChunkAccess {
}
BlockEntity blockEntity = this.getBlockEntity(pos.immutable(), LevelChunk.EntityCreationType.IMMEDIATE);
if (blockEntity != null && ModernFix.LOGGER.isDebugEnabled()) {
String blockName = state.getBlock().toString();
ModernFix.LOGGER.debug("Created missing block entity for {} at {}", blockName, pos.toShortString());
String blockName = state.getBlock().toString();
if (blockEntity != null) {
ModernFix.LOGGER.warn("Created missing block entity for {} at {}", blockName, pos.toShortString());
} else {
ModernFix.LOGGER.error("Block entity is missing for {} at {}, but could not be created", blockName, pos.toShortString());
}
}
}

View File

@ -24,7 +24,7 @@ public class MinecraftMixin {
/**
* To mitigate the effect of leaked client worlds, clear most of the data structures that waste memory.
*/
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Minecraft;level:Lnet/minecraft/client/multiplayer/ClientLevel;"))
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;Z)V", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Minecraft;level:Lnet/minecraft/client/multiplayer/ClientLevel;"))
private void clearLevelDataForLeaks(CallbackInfo ci) {
if(this.level != null) {
try {

View File

@ -0,0 +1,18 @@
package org.embeddedt.modernfix.common.mixin.core;
import net.minecraft.client.multiplayer.ClientPacketListener;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = ClientPacketListener.class, priority = 1500)
@ClientOnlyMixin
public class ClientPlayNetHandlerMixin {
@Inject(method = "handleUpdateRecipes", at = @At("RETURN"))
private void signalRecipes(CallbackInfo ci) {
ModernFixClient.INSTANCE.onRecipesUpdated();
}
}

View File

@ -0,0 +1,24 @@
package org.embeddedt.modernfix.common.mixin.core;
import net.minecraft.Util;
import net.minecraft.server.MinecraftServer;
import org.embeddedt.modernfix.duck.ITimeTrackingServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin implements ITimeTrackingServer {
private long mfix$lastTickStartTime = -1L;
@Override
public long mfix$getLastTickStartTime() {
return mfix$lastTickStartTime;
}
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;tickServer(Ljava/util/function/BooleanSupplier;)V"))
private void trackTickTime(CallbackInfo ci) {
mfix$lastTickStartTime = Util.getMillis();
}
}

View File

@ -0,0 +1,17 @@
package org.embeddedt.modernfix.common.mixin.devenv;
import com.mojang.text2speech.Narrator;
import net.minecraft.client.GameNarrator;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(GameNarrator.class)
@ClientOnlyMixin
public class NarratorMixin {
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/text2speech/Narrator;getNarrator()Lcom/mojang/text2speech/Narrator;", remap = false))
private Narrator useDummyNarrator() {
return Narrator.EMPTY;
}
}

View File

@ -1,27 +1,27 @@
package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.TracingExecutor;
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Mixin(ChunkRenderDispatcher.class)
@Mixin(SectionRenderDispatcher.class)
@ClientOnlyMixin
public class ChunkRenderDispatcherMixin {
private static final Executor MFIX_CHUNK_BUILD_EXECUTOR = new ThreadPoolExecutor(1, computeNumThreads(), 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
private static final TracingExecutor MFIX_CHUNK_BUILD_EXECUTOR = new TracingExecutor(new ThreadPoolExecutor(1,computeNumThreads(), 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()));
private static int computeNumThreads() {
return Math.max(Math.min(Runtime.getRuntime().availableProcessors() / 4, 10), 1);
}
@ModifyVariable(method = "<init>*", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private static Executor replaceExecutor(Executor old) {
private static TracingExecutor replaceExecutor(TracingExecutor old) {
return MFIX_CHUNK_BUILD_EXECUTOR;
}
}

View File

@ -1,16 +1,15 @@
package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads;
import net.minecraft.TracingExecutor;
import net.minecraft.Util;
import org.embeddedt.modernfix.util.SingleThreadedWorkerService;
import org.embeddedt.modernfix.util.DirectExecutorService;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.ExecutorService;
@Mixin(Util.class)
public class UtilMixin {
@Shadow @Final @Mutable
private static final ExecutorService BACKGROUND_EXECUTOR = new SingleThreadedWorkerService();
private static final TracingExecutor BACKGROUND_EXECUTOR = new TracingExecutor(new DirectExecutorService());
}

View File

@ -0,0 +1,22 @@
package org.embeddedt.modernfix.common.mixin.feature.direct_stack_trace;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(CrashReport.class)
public class CrashReportMixin {
@Shadow @Final private Throwable exception;
@Inject(method = "addCategory(Ljava/lang/String;I)Lnet/minecraft/CrashReportCategory;", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
private void dumpStacktrace(String s, int i, CallbackInfoReturnable<CrashReportCategory> cir) {
new Exception("ModernFix crash stacktrace").printStackTrace();
if(this.exception != null)
this.exception.printStackTrace();
}
}

View File

@ -0,0 +1,37 @@
package org.embeddedt.modernfix.common.mixin.feature.disable_unihex_font;
import com.mojang.blaze3d.font.GlyphProvider;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.gui.font.CodepointMap;
import net.minecraft.client.gui.font.providers.GlyphProviderDefinition;
import net.minecraft.client.gui.font.providers.UnihexProvider;
import net.minecraft.server.packs.resources.ResourceManager;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.IOException;
import java.lang.reflect.Constructor;
@Mixin(UnihexProvider.Definition.class)
@ClientOnlyMixin
public class UnihexProviderDefinitionMixin {
@Inject(method = "unpack", at = @At("HEAD"), cancellable = true)
private void disableProvider(CallbackInfoReturnable<Either<GlyphProviderDefinition.Loader, GlyphProviderDefinition.Reference>> cir) {
cir.setReturnValue(Either.left(this::mfix$loadEmpty));
}
private GlyphProvider mfix$loadEmpty(ResourceManager resourceManager) throws IOException {
try {
ModernFix.LOGGER.warn("Unihex provider is disabled, a number of Unicode characters will likely not render");
Constructor<UnihexProvider> constructor = UnihexProvider.class.getDeclaredConstructor(CodepointMap.class);
constructor.setAccessible(true);
return constructor.newInstance(new CodepointMap<>(Object[]::new, Object[][]::new));
} catch(ReflectiveOperationException e) {
throw new IOException("Failed to create empty loader", e);
}
}
}

View File

@ -0,0 +1,23 @@
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ProfiledReloadInstance;
import org.embeddedt.modernfix.util.NamedPreparableResourceListener;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.ArrayList;
import java.util.List;
@Mixin(ProfiledReloadInstance.class)
public class ProfiledReloadInstanceMixin {
@ModifyVariable(method = "<init>", at = @At("HEAD"), argsOnly = true, ordinal = 0)
private static List<PreparableReloadListener> getWrappedListeners(List<PreparableReloadListener> listeners) {
List<PreparableReloadListener> newList = new ArrayList<>(listeners.size());
for(PreparableReloadListener listener : listeners) {
newList.add(new NamedPreparableResourceListener(listener));
}
return newList;
}
}

View File

@ -0,0 +1,70 @@
package org.embeddedt.modernfix.common.mixin.feature.stalled_chunk_load_detection;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ChunkResult;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.EmptyLevelChunk;
import org.embeddedt.modernfix.ModernFix;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.*;
@Mixin(value = ServerChunkCache.class, priority = 1100)
public abstract class ServerChunkCacheMixin {
@Shadow @Final private Thread mainThread;
@Shadow @Final public ServerLevel level;
@Shadow protected abstract CompletableFuture<ChunkResult<ChunkAccess>> getChunkFutureMainThread(int k, int l, ChunkStatus arg, boolean bl);
@Shadow @Final private ServerChunkCache.MainThreadExecutor mainThreadProcessor;
private final boolean debugDeadServerAccess = Boolean.getBoolean("modernfix.debugBadChunkloading");
@Inject(method = "getChunk", at = @At("HEAD"), cancellable = true)
private void bailIfServerDead(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load, CallbackInfoReturnable<ChunkAccess> cir) {
if(!this.level.getServer().isRunning() && !this.mainThread.isAlive()) {
ModernFix.LOGGER.fatal("A mod is accessing chunks from a stopped server (this will also cause memory leaks)");
if(debugDeadServerAccess) {
new Exception().printStackTrace();
}
Holder<Biome> plains = this.level.registryAccess().lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS);
cir.setReturnValue(new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ), plains));
} else if(Thread.currentThread() != this.mainThread) {
CompletableFuture<ChunkResult<ChunkAccess>> future = CompletableFuture.supplyAsync(() -> this.getChunkFutureMainThread(chunkX, chunkZ, requiredStatus, false), this.mainThreadProcessor).join();
if(!future.isDone()) {
// Wait at least 500 milliseconds before printing anything
ChunkResult<ChunkAccess> resultingChunk = null;
try {
resultingChunk = future.get(500, TimeUnit.MILLISECONDS);
} catch(InterruptedException | ExecutionException | TimeoutException ignored) {
}
if(resultingChunk != null && resultingChunk.isSuccess()) {
cir.setReturnValue(resultingChunk.orElse(null));
return;
}
if(debugDeadServerAccess)
ModernFix.LOGGER.warn("Async loading of a chunk was requested, this might not be desirable", new Exception());
try {
resultingChunk = future.get(10, TimeUnit.SECONDS);
if(resultingChunk.isSuccess()) {
cir.setReturnValue(resultingChunk.orElse(null));
return;
}
} catch(InterruptedException | ExecutionException | TimeoutException e) {
ModernFix.LOGGER.error("Async chunk load took way too long, this needs to be reported to the appropriate mod.", e);
}
//cir.setReturnValue(new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ)));
}
}
}
}

View File

@ -3,7 +3,6 @@ package org.embeddedt.modernfix.common.mixin.perf.cache_profile_texture_url;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import net.minecraft.client.resources.SkinManager;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@ -13,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@Mixin(SkinManager.class)
@Mixin(targets = {"net/minecraft/client/resources/SkinManager$TextureCache" })
@ClientOnlyMixin
public class SkinManagerMixin {
@Unique
@ -22,7 +21,7 @@ public class SkinManagerMixin {
.concurrencyLevel(1)
.build();
@Redirect(method = "registerTexture(Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;Lcom/mojang/authlib/minecraft/MinecraftProfileTexture$Type;Lnet/minecraft/client/resources/SkinManager$SkinTextureCallback;)Lnet/minecraft/resources/ResourceLocation;",
@Redirect(method = { "getOrLoad", "registerTexture" },
at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/minecraft/MinecraftProfileTexture;getHash()Ljava/lang/String;", remap = false))
private String useCachedHash(MinecraftProfileTexture texture) {
// avoid lambda allocation for common case

View File

@ -0,0 +1,68 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Mixin(ChunkGeneratorStructureState.class)
public class ChunkGeneratorMixin implements IChunkGenerator {
private WeakReference<ServerLevel> mfix$serverLevel;
@Override
public void mfix$setAssociatedServerLevel(ServerLevel level) {
mfix$serverLevel = new WeakReference<>(level);
}
@Inject(method = "generateRingPositions", at = @At("HEAD"), cancellable = true)
private void useCachedDataIfAvailable(Holder<StructureSet> structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
if(placement.count() == 0)
return;
ServerLevel level = searchLevel();
if(level == null)
return;
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
List<ChunkPos> positions = cache.getChunkPosList();
if(positions.isEmpty())
return;
ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size());
cir.setReturnValue(CompletableFuture.completedFuture(positions));
}
private ServerLevel searchLevel() {
if(mfix$serverLevel != null)
return mfix$serverLevel.get();
else
return null;
}
@Inject(method = "generateRingPositions", at = @At("RETURN"), cancellable = true)
private void saveCachedData(Holder<StructureSet> structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
cir.setReturnValue(cir.getReturnValue().thenApplyAsync(list -> {
if(list.size() == 0)
return list;
ServerLevel level = searchLevel();
if(level != null) {
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
cache.setChunkPosList(list);
ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location());
}
return list;
}, Util.backgroundExecutor()));
}
}

View File

@ -0,0 +1,59 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.WritableLevelData;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerLevel.class)
public abstract class ServerLevelMixin extends Level implements IServerLevel {
protected ServerLevelMixin(WritableLevelData writableLevelData, ResourceKey<Level> resourceKey, RegistryAccess registryAccess, Holder<DimensionType> holder, boolean bl, boolean bl2, long l, int i) {
super(writableLevelData, resourceKey, registryAccess, holder, bl, bl2, l, i);
}
@Shadow public abstract DimensionDataStorage getDataStorage();
@Shadow @Final private ServerChunkCache chunkSource;
private StrongholdLocationCache mfix$strongholdCache;
/**
* Initialize the stronghold cache but don't force any structure generation yet.
*/
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkGeneratorStructureState;ensureStructuresGenerated()V"))
private void hookStrongholdCache(ChunkGeneratorStructureState generator) {
((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this);
}
/**
* Now start the stronghold generation process.
*/
@Inject(method = "<init>", at = @At("TAIL"))
private void ensureGeneration(CallbackInfo ci) {
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(
StrongholdLocationCache.factory((ServerLevel)(Object)this),
StrongholdLocationCache.getFileId(this.dimensionTypeRegistration()));
this.chunkSource.getGeneratorState().ensureStructuresGenerated();
}
@Override
public StrongholdLocationCache mfix$getStrongholdCache() {
return mfix$strongholdCache;
}
}

View File

@ -1,9 +1,7 @@
package org.embeddedt.modernfix.common.mixin.perf.chunk_meshing;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.renderer.chunk.RenderChunkRegion;
import net.minecraft.client.renderer.chunk.SectionCompiler;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.util.blockpos.SectionBlockPosIterator;
@ -11,7 +9,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(targets = { "net/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk$RebuildTask"}, priority = 2000)
@Mixin(value = SectionCompiler.class, priority = 2000)
@ClientOnlyMixin
@RequiresMod("!fluidlogged")
public class RebuildTaskMixin {
@ -23,13 +21,4 @@ public class RebuildTaskMixin {
private Iterable<BlockPos> fastBetweenClosed(BlockPos firstPos, BlockPos secondPos) {
return () -> new SectionBlockPosIterator(firstPos);
}
/**
* @author embeddedt
* @reason RenderChunkRegion.getBlockState is expensive, avoid calling it multiple times for the same position
*/
@Redirect(method = "compile", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/RenderChunkRegion;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;", ordinal = 1), require = 0)
private BlockState useExistingBlockState(RenderChunkRegion instance, BlockPos pos, @Local(ordinal = 0) BlockState state) {
return state;
}
}

View File

@ -1,7 +1,8 @@
package org.embeddedt.modernfix.common.mixin.perf.compact_mojang_registries;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.resources.ResourceKey;
import org.embeddedt.modernfix.annotation.IgnoreOutsideDev;
import org.embeddedt.modernfix.registry.LifecycleMap;
import org.spongepowered.asm.mixin.Final;
@ -20,10 +21,10 @@ public abstract class MappedRegistryMixin<T> {
@Shadow
@Final
@Mutable
private Map<T, Lifecycle> lifecycles;
private Map<ResourceKey<T>, RegistrationInfo> registrationInfos;
@Inject(method = "<init>", at = @At("RETURN"))
private void replaceStorage(CallbackInfo ci) {
this.lifecycles = new LifecycleMap<>();
this.registrationInfos = new LifecycleMap<>();
}
}

View File

@ -17,7 +17,7 @@ public class CreateWorldScreenMixin {
return ModernFix.resourceReloadExecutor();
}
@ModifyArg(method = "openFresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3)
@ModifyArg(method = "openCreateWorldScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 3)
private static Executor getCreationExecutorService(Executor e) {
return ModernFix.resourceReloadExecutor();
}

View File

@ -1,5 +1,6 @@
package org.embeddedt.modernfix.common.mixin.perf.dedicated_reload_executor;
import net.minecraft.TracingExecutor;
import net.minecraft.client.Minecraft;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
@ -7,13 +8,11 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.concurrent.ExecutorService;
@Mixin(Minecraft.class)
@ClientOnlyMixin
public class MinecraftMixin {
@Redirect(method = { "<init>", "reloadResourcePacks(Z)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;backgroundExecutor()Ljava/util/concurrent/ExecutorService;", ordinal = 0))
private ExecutorService getResourceReloadExecutor() {
@Redirect(method = { "<init>", "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;backgroundExecutor()Lnet/minecraft/TracingExecutor;", ordinal = 0))
private TracingExecutor getResourceReloadExecutor() {
return ModernFix.resourceReloadExecutor();
}
}

View File

@ -10,7 +10,7 @@ import java.util.concurrent.Executor;
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin {
@ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/RegistryAccess$Frozen;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 5)
@ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Ljava/util/List;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 6)
private Executor getReloadExecutor(Executor asyncExecutor) {
return ModernFix.resourceReloadExecutor();
}

View File

@ -0,0 +1,15 @@
package org.embeddedt.modernfix.common.mixin.perf.deduplicate_climate_parameters;
import net.minecraft.world.level.biome.Climate;
import org.embeddedt.modernfix.dedup.ClimateCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin({ Climate.Parameter.class, Climate.ParameterPoint.class })
public class ParameterMixin {
@Redirect(method = "*", at = @At(value = "NEW", target = "net/minecraft/world/level/biome/Climate$Parameter"), require = 0)
private static Climate.Parameter internParameterStatic(long min, long max) {
return ClimateCache.MFIX_INTERNER.intern(new Climate.Parameter(min, max));
}
}

View File

@ -0,0 +1,30 @@
package org.embeddedt.modernfix.common.mixin.perf.deduplicate_location;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.dedup.IdentifierCaches;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ResourceLocation.class)
public class MixinResourceLocation {
@Mutable
@Shadow
@Final
private String namespace;
@Mutable
@Shadow
@Final
private String path;
@Inject(method = "<init>", at = @At("RETURN"))
private void reinit(String string, String string2, CallbackInfo ci) {
this.namespace = IdentifierCaches.NAMESPACES.deduplicate(this.namespace);
this.path = IdentifierCaches.PATH.deduplicate(this.path);
}
}

View File

@ -25,7 +25,7 @@ import java.util.Map;
*/
@Mixin(WallBlock.class)
public abstract class WallBlockMixin extends Block {
private static Map<ImmutableList<Float>, Pair<Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>>> CACHE_BY_SHAPE_VALS = new HashMap<>();
private static Map<ImmutableList<Float>, Pair<Map<Map<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>>> CACHE_BY_SHAPE_VALS = new HashMap<>();
public WallBlockMixin(Properties properties) {
super(properties);
@ -34,7 +34,7 @@ public abstract class WallBlockMixin extends Block {
@Inject(method = "makeShapes", at = @At("HEAD"), cancellable = true)
private synchronized void useCachedShapeMap(float f1, float f2, float f3, float f4, float f5, float f6, CallbackInfoReturnable<Map<BlockState, VoxelShape>> cir) {
ImmutableList<Float> key = ImmutableList.of(f1, f2, f3, f4, f5, f6);
Pair<Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>> cache = CACHE_BY_SHAPE_VALS.get(key);
Pair<Map<Map<Property<?>, Comparable<?>>, VoxelShape>, StateDefinition<Block, BlockState>> cache = CACHE_BY_SHAPE_VALS.get(key);
// require the properties to be identical
if(cache == null || !cache.getSecond().getProperties().equals(this.stateDefinition.getProperties()))
return;
@ -55,7 +55,7 @@ public abstract class WallBlockMixin extends Block {
return;
ImmutableList<Float> key = ImmutableList.of(f1, f2, f3, f4, f5, f6);
if(!CACHE_BY_SHAPE_VALS.containsKey(key)) {
Map<ImmutableMap<Property<?>, Comparable<?>>, VoxelShape> cacheByProperties = new HashMap<>();
Map<Map<Property<?>, Comparable<?>>, VoxelShape> cacheByProperties = new HashMap<>();
Map<BlockState, VoxelShape> shapeMap = cir.getReturnValue();
for(Map.Entry<BlockState, VoxelShape> entry : shapeMap.entrySet()) {
cacheByProperties.put(entry.getKey().getValues(), entry.getValue());

View File

@ -0,0 +1,38 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_entity_renderers;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.entity.EntityRendererMap;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(EntityRenderDispatcher.class)
@ClientOnlyMixin
public class EntityRenderDispatcherMixin {
@Shadow private Map<EntityType<?>, EntityRenderer<?, ?>> renderers;
private EntityRendererMap mfix$dynamicRenderers;
@Inject(method = "getRenderer", at = @At("RETURN"), cancellable = true)
private <T extends Entity> void checkNullness(T entity, CallbackInfoReturnable<EntityRenderer<? super T, ?>> cir) {
// apparently some mods yeet the renderers map and cause issues
if(cir.getReturnValue() == null)
cir.setReturnValue((EntityRenderer<? super T, ?>)mfix$dynamicRenderers.get(entity.getType()));
}
@Redirect(method = "onResourceManagerReload", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderers:Ljava/util/Map;"))
private void setRendererField(EntityRenderDispatcher instance, Map<EntityType<?>, EntityRenderer<?, ?>> incomingMap) {
this.renderers = incomingMap;
this.mfix$dynamicRenderers = (EntityRendererMap)incomingMap;
}
}

View File

@ -0,0 +1,29 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_entity_renderers;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.world.entity.EntityType;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.entity.EntityRendererMap;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(EntityRenderers.class)
@ClientOnlyMixin
public class EntityRenderersMixin {
@Shadow @Final private static Map<EntityType<?>, EntityRendererProvider<?>> PROVIDERS;
@Inject(method = "createEntityRenderers", at = @At("HEAD"), cancellable = true)
private static void createDynamicRendererLoader(EntityRendererProvider.Context context, CallbackInfoReturnable<Map<EntityType<?>, EntityRenderer<?, ?>>> cir) {
cir.setReturnValue(new EntityRendererMap(PROVIDERS, context));
ModernFix.LOGGER.info("Dynamic entity renderer hook setup");
}
}

View File

@ -29,7 +29,7 @@ public class BlockModelShaperMixin {
@Inject(method = { "<init>", "replaceCache" }, at = @At("RETURN"))
private void replaceModelMap(CallbackInfo ci) {
// replace the backing map for mods which will access it
this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state)));
this.modelByStateCache = new DynamicOverridableMap<>(BlockState.class, state -> modelManager.getModel(ModelLocationCache.get(state)));
// Clear the cached models on blockstate objects
for(Block block : BuiltInRegistries.BLOCK) {
for(BlockState state : block.getStateDefinition().getPossibleStates()) {
@ -72,3 +72,4 @@ public class BlockModelShaperMixin {
}
}
}

View File

@ -24,3 +24,4 @@ public class BlockStateBaseMixin implements IModelHoldingBlockState {
mfix$model = model != null ? new SoftReference<>(model) : null;
}
}

View File

@ -0,0 +1,22 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import net.minecraft.client.resources.model.ModelDiscovery;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ModelDiscovery.class)
@ClientOnlyMixin
public class ModelDiscoveryMixin {
/**
* @author embeddedt
* @reason We will show the warning ourselves later when loading the model dynamically, this is just spam since
* the models don't exist during early loading
*/
@Redirect(method = "loadBlockModel", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V"))
private void disableMissingModelWarning(Logger instance, String s, Object o) {
}
}

View File

@ -0,0 +1,98 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.google.common.collect.Maps;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.item.ClientItem;
import net.minecraft.client.renderer.item.ItemModel;
import net.minecraft.client.resources.model.AtlasSet;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.BlockStateModelLoader;
import net.minecraft.client.resources.model.ClientItemInfoLoader;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.level.block.state.BlockState;
import org.apache.commons.lang3.ArrayUtils;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.DynamicModelProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@Mixin(ModelManager.class)
@ClientOnlyMixin
public class ModelManagerMixin implements DynamicModelProvider.ModelManagerExtension {
@Shadow private Map<ModelResourceLocation, BakedModel> bakedBlockStateModels;
@Shadow private Map<ResourceLocation, ItemModel> bakedItemStackModels;
@Shadow private Map<ResourceLocation, ClientItem.Properties> itemProperties;
@Unique
private DynamicModelProvider mfix$modelProvider;
@Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ModelManager;loadBlockModels(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
private CompletableFuture<Map<ResourceLocation, BlockModel>> deferBlockModelLoad(ResourceManager manager, Executor executor) {
return CompletableFuture.completedFuture(Map.of());
}
@Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/BlockStateModelLoader;loadBlockStates(Lnet/minecraft/client/resources/model/UnbakedModel;Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
private CompletableFuture<BlockStateModelLoader.LoadedModels> deferBlockStateLoad(UnbakedModel unbakedModel, ResourceManager resourceManager, Executor executor) {
return CompletableFuture.completedFuture(new BlockStateModelLoader.LoadedModels(Map.of()));
}
/**
* @author embeddedt
* @reason disable map creation
*/
@Overwrite
private static Map<BlockState, BakedModel> createBlockStateToModelDispatch(Map<ModelResourceLocation, BakedModel> map, BakedModel bakedModel) {
return Map.of();
}
@Redirect(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/resources/model/ClientItemInfoLoader;scheduleLoad(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"))
private CompletableFuture<ClientItemInfoLoader.LoadedClientInfos> disableClientItemEarlyLoad(ResourceManager resourceManager, Executor executor) {
return CompletableFuture.completedFuture(new ClientItemInfoLoader.LoadedClientInfos(Map.of()));
}
@ModifyArg(method = "reload", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;allOf([Ljava/util/concurrent/CompletableFuture;)Ljava/util/concurrent/CompletableFuture;", ordinal = 1))
private CompletableFuture<?>[] createModelProvider(CompletableFuture<?>[] cfs, @Local(ordinal = 0) CompletableFuture<EntityModelSet> entityModelFuture, @Local(ordinal = 0, argsOnly = true) Executor executor, @Local(ordinal = 0) Map<ResourceLocation, CompletableFuture<AtlasSet.StitchResult>> atlasPreparations) {
CompletableFuture<Void> makeModelProviderFuture = CompletableFuture.supplyAsync(() -> {
return Map.copyOf(Maps.transformValues(atlasPreparations, CompletableFuture::join));
}, executor).thenAcceptBoth(entityModelFuture, (stitchResults, entityModelSet) -> {
this.mfix$modelProvider = new DynamicModelProvider(
Minecraft.getInstance().getResourceManager(),
entityModelSet,
stitchResults
);
DynamicModelProvider.currentReloadingModelProvider = new WeakReference<>(this.mfix$modelProvider);
});
return ArrayUtils.add(cfs, makeModelProviderFuture);
}
@Inject(method = "apply", at = @At("RETURN"))
private void setModelRegistries(CallbackInfo ci) {
this.bakedBlockStateModels = this.mfix$modelProvider.getTopLevelEmulatedRegistry();
this.bakedItemStackModels = this.mfix$modelProvider.getItemModelEmulatedRegistry();
this.itemProperties = this.mfix$modelProvider.getItemPropertiesEmulatedRegistry();
}
@Override
public DynamicModelProvider mfix$getModelProvider() {
return this.mfix$modelProvider;
}
}

View File

@ -0,0 +1,47 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_sounds;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalNotification;
import com.mojang.blaze3d.audio.SoundBuffer;
import net.minecraft.client.sounds.SoundBufferLibrary;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.DynamicSoundHelpers;
import org.embeddedt.modernfix.ModernFix;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.Map;
@Mixin(SoundBufferLibrary.class)
@ClientOnlyMixin
public abstract class SoundBufferLibraryMixin {
private static final boolean debugDynamicSoundLoading = Boolean.getBoolean("modernfix.debugDynamicSoundLoading");
@Shadow @Final @Mutable
private Map<ResourceLocation, CompletableFuture<SoundBuffer>> cache = CacheBuilder.newBuilder()
.expireAfterAccess(DynamicSoundHelpers.MAX_SOUND_LIFETIME_SECS, TimeUnit.SECONDS)
.concurrencyLevel(1)
// Excessive use of type hinting due to it assuming Object as the broadest correct type
.<ResourceLocation, CompletableFuture<SoundBuffer>>removalListener(this::onSoundRemoval)
.build()
.asMap();
private <K extends ResourceLocation, V extends CompletableFuture<SoundBuffer>> void onSoundRemoval(RemovalNotification<K, V> notification) {
if(notification.getCause() == RemovalCause.REPLACED && notification.getValue() == cache.get(notification.getKey()))
return;
notification.getValue().thenAccept(SoundBuffer::discardAlBuffer);
if(!debugDynamicSoundLoading)
return;
K k = notification.getKey();
if(k == null)
return;
ModernFix.LOGGER.warn("Evicted sound {}", k);
}
}

View File

@ -11,12 +11,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GameRenderer.class)
@ClientOnlyMixin
public class GameRendererMixin {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V", shift = At.Shift.BEFORE))
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V", shift = At.Shift.BEFORE))
private void markRenderingLevel(CallbackInfo ci) {
RenderState.IS_RENDERING_LEVEL = true;
}
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(FJLcom/mojang/blaze3d/vertex/PoseStack;)V", shift = At.Shift.AFTER))
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;renderLevel(Lnet/minecraft/client/DeltaTracker;)V", shift = At.Shift.AFTER))
private void markNotRenderingLevel(CallbackInfo ci) {
RenderState.IS_RENDERING_LEVEL = false;
}

View File

@ -0,0 +1,14 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.world.item.ItemDisplayContext;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ItemStackRenderState.class)
@ClientOnlyMixin
public interface ItemStackRenderStateAccessor {
@Accessor
ItemDisplayContext getDisplayContext();
}

View File

@ -1,36 +1,30 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_item_rendering;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.SimpleBakedModel;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.render.FastItemRenderType;
import org.embeddedt.modernfix.render.RenderState;
import org.embeddedt.modernfix.render.SimpleItemModelView;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = ItemRenderer.class, priority = 600)
@Mixin(value = ItemStackRenderState.LayerRenderState.class, priority = 600)
@ClientOnlyMixin
public abstract class ItemRendererMixin {
private ItemDisplayContext transformType;
private final SimpleItemModelView modelView = new SimpleItemModelView();
public abstract class LayerRenderStateMixin {
@Shadow(aliases = {"this$0"}) @Final private ItemStackRenderState field_55345;
@Inject(method = "render", at = @At("HEAD"))
private void markRenderingType(ItemStack itemStack, ItemDisplayContext transformType, boolean leftHand, PoseStack matrixStack, MultiBufferSource buffer, int combinedLight, int combinedOverlay, BakedModel model, CallbackInfo ci) {
this.transformType = transformType;
}
@Shadow abstract ItemTransform transform();
@Unique
private final SimpleItemModelView modelView = new SimpleItemModelView();
/**
* If a model
@ -40,20 +34,24 @@ public abstract class ItemRendererMixin {
* we do not need to go through the process of rendering every quad. Just render the south ones (the ones facing the
* camera).
*/
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;renderModelLists(Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/item/ItemStack;IILcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;)V"), index = 0)
private BakedModel useSimpleWrappedItemModel(BakedModel model, ItemStack stack, int combinedLight, int combinedOverlay, PoseStack matrixStack, VertexConsumer buffer, @Local(ordinal = 0) BakedModel originalModel) {
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;renderItem(Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;II[ILnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/client/renderer/RenderType;Lnet/minecraft/client/renderer/item/ItemStackRenderState$FoilType;)V"), index = 6)
private BakedModel useSimpleWrappedItemModel(BakedModel model) {
var transformType = ((ItemStackRenderStateAccessor)this.field_55345).getDisplayContext();
// Forge composite models split themselves into a smaller simple model, we need to detect that the parent
// was not simple
// TODO 1.21.4 - I don't think that is needed anymore with the changes to item rendering
/*
if(originalModel != null && originalModel.getClass() != SimpleBakedModel.class) {
return model;
}
*/
if(!RenderState.IS_RENDERING_LEVEL && !stack.isEmpty() && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) {
if(!RenderState.IS_RENDERING_LEVEL && model.getClass() == SimpleBakedModel.class && transformType == ItemDisplayContext.GUI) {
FastItemRenderType type;
ItemTransform transform = model.getTransforms().gui;
ItemTransform transform = this.transform();
if(transform == ItemTransform.NO_TRANSFORM)
type = FastItemRenderType.SIMPLE_ITEM;
else if(stack.getItem() instanceof BlockItem && isBlockTransforms(transform))
else if(model.isGui3d() && isBlockTransforms(transform))
type = FastItemRenderType.SIMPLE_BLOCK;
else
return model;

View File

@ -0,0 +1,23 @@
package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting;
import net.minecraft.util.thread.BlockableEventLoop;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
// This should fix https://bugs.mojang.com/browse/MC-183518
@Mixin(value = BlockableEventLoop.class, priority = 500)
public class BlockableEventLoopMixin {
private static final long MFIX$TICK_WAIT_TIME = TimeUnit.MILLISECONDS.toNanos(2);
/**
* @author embeddedt
* @reason yielding the thread is pretty pointless if we're about to park anyway
*/
@Overwrite
public void waitForTasks() {
LockSupport.parkNanos("waiting for tasks", MFIX$TICK_WAIT_TIME);
}
}

View File

@ -1,22 +1,25 @@
package org.embeddedt.modernfix.common.mixin.perf.model_optimizations;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.dedup.IdentifierCaches;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Property.class)
public class PropertyMixin {
@Shadow @Final private String name;
@Shadow @Mutable
@Final private String name;
@Shadow private Integer hashCode;
@Shadow @Final private Class clazz;
@ModifyVariable(method = "<init>", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private static String internName(String name) {
return name.intern();
@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/state/properties/Property;name:Ljava/lang/String;"))
private void internName(Property instance, String name) {
this.name = IdentifierCaches.PROPERTY.deduplicate(name);
}
/**
* @author embeddedt
* @reason compare hashcodes if generated, use reference equality for speed
@ -29,8 +32,7 @@ public class PropertyMixin {
return false;
} else {
Property<?> property = (Property)p_equals_1_;
/* reference equality is safe here because of interning above */
//noinspection StringEquality
/* reference equality is safe here because of deduplication */
return this.clazz == property.getValueClass() && this.name == property.getName();
}
}

View File

@ -0,0 +1,28 @@
package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(ResourceKey.class)
public class ResourceKeyMixin<T> {
private static final Map<ResourceLocation, Map<ResourceLocation, ResourceKey<?>>> INTERNING_MAP = new Object2ObjectOpenHashMap<>();
@Inject(method = "create(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/resources/ResourceKey;", at = @At("HEAD"), cancellable = true)
private static <T> void createEfficient(ResourceLocation parent, ResourceLocation location, CallbackInfoReturnable<ResourceKey<T>> cir) {
synchronized (ResourceKey.class) {
Map<ResourceLocation, ResourceKey<?>> keys = INTERNING_MAP.computeIfAbsent(parent, k -> new Object2ObjectOpenHashMap<>());
ResourceKey<?> key = keys.get(location);
if(key == null) {
key = new ResourceKey<>(parent, location);
keys.put(location, key);
}
cir.setReturnValue((ResourceKey<T>)key);
}
}
}

View File

@ -1,9 +1,6 @@
package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size;
import com.google.common.collect.ArrayTable;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Table;
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.annotation.RequiresMod;
@ -13,6 +10,8 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
/**
* Minor mixin to avoid duplicate empty neighbor tables, used when FerriteCore is not present. Won't be enabled in 99% of
* modded environments but is useful for testing in dev without dragging in Fabric API.
@ -20,12 +19,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(StateHolder.class)
@RequiresMod("!ferritecore")
public class StateHolderMixin {
@Shadow private Table<Property<?>, Comparable<?>, ?> neighbours;
private static final Reference2ObjectArrayMap<Property<?>, ?> EMPTY_NEIGHBOURS = new Reference2ObjectArrayMap<>();
@Shadow private Map<Property<?>, ?> neighbours;
/* optimize the case where block has no properties */
@Inject(method = "populateNeighbours", at = @At("RETURN"), require = 0)
private void replaceEmptyTable(CallbackInfo ci) {
if((this.neighbours instanceof ArrayTable || this.neighbours instanceof HashBasedTable) && this.neighbours.isEmpty())
this.neighbours = ImmutableTable.of();
if (this.neighbours.isEmpty()) {
this.neighbours = EMPTY_NEIGHBOURS;
}
}
}

View File

@ -0,0 +1,20 @@
package org.embeddedt.modernfix.common.mixin.perf.nbt_memory_usage;
import net.minecraft.nbt.Tag;
import org.embeddedt.modernfix.util.CanonizingStringMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.Map;
@Mixin(targets = "net/minecraft/nbt/CompoundTag$1")
public class CompoundTag1Mixin {
@ModifyVariable(method = "loadCompound", at = @At(value = "INVOKE_ASSIGN", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;", remap = false))
private static Map<String, Tag> modifyMap(Map<String, Tag> map) {
CanonizingStringMap<Tag> newMap = new CanonizingStringMap<>();
if(map != null)
newMap.putAll(map);
return newMap;
}
}

View File

@ -0,0 +1,40 @@
package org.embeddedt.modernfix.common.mixin.perf.nbt_memory_usage;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import org.embeddedt.modernfix.util.CanonizingStringMap;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(CompoundTag.class)
public class CompoundTagMixin {
@Shadow @Final
private Map<String, Tag> tags;
/**
* Ensure that the default backing map is a CanonizingStringMap.
*/
@ModifyArg(method = "<init>()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/CompoundTag;<init>(Ljava/util/Map;)V"), index = 0)
private static Map<String, Tag> useCanonizingStringMap(Map<String, Tag> incoming) {
CanonizingStringMap<Tag> newMap = new CanonizingStringMap<>();
if(incoming != null)
newMap.putAll(incoming);
return newMap;
}
/**
* @author embeddedt
* @reason use more efficient method when copying canonizing string map
*/
@Inject(method = "copy()Lnet/minecraft/nbt/CompoundTag;", at = @At("HEAD"), cancellable = true)
public void copyEfficient(CallbackInfoReturnable<Tag> cir) {
if(this.tags instanceof CanonizingStringMap) {
cir.setReturnValue(new CompoundTag(CanonizingStringMap.deepCopy((CanonizingStringMap<Tag>)this.tags, Tag::copy)));
}
}
}

View File

@ -9,7 +9,7 @@ import org.spongepowered.asm.mixin.Shadow;
/* Idea from Lithium for 1.19.3 */
@Mixin(Biome.class)
public abstract class BiomeMixin {
@Shadow protected abstract float getHeightAdjustedTemperature(BlockPos pos);
@Shadow protected abstract float getHeightAdjustedTemperature(BlockPos pos, int i);
/**
* @author 2No2Name
@ -18,7 +18,7 @@ public abstract class BiomeMixin {
* @return
*/
@Overwrite
private float getTemperature(BlockPos pos) {
return this.getHeightAdjustedTemperature(pos);
private float getTemperature(BlockPos pos, int i) {
return this.getHeightAdjustedTemperature(pos, i);
}
}

View File

@ -0,0 +1,18 @@
package org.embeddedt.modernfix.common.mixin.perf.resourcepacks;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.resources.PackResourcesCacheEngine;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ReloadableResourceManager.class)
public class ReloadableResourceManagerMixin {
@Inject(method = "createReload", at = @At("HEAD"))
private void invalidateResourceCaches(CallbackInfoReturnable<?> cir) {
ModernFix.LOGGER.info("Invalidating pack caches");
PackResourcesCacheEngine.invalidate();
}
}

Some files were not shown because too many files have changed in this diff Show More