Compare commits

...

246 Commits

Author SHA1 Message Date
embeddedt
57af3c6491
Merge remote-tracking branch 'origin/1.20' into 1.20.6 2024-06-05 20:23:17 -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
b4398565a6
Merge 1.20 into 1.20.6 2024-06-01 13:38:17 -04:00
embeddedt
a9f4ce72f1
Merge 1.20 into 1.20.6 2024-05-30 19:06:41 -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
cc653249e4
Merge 1.20 into 1.20.6 2024-05-12 16:59:13 -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
d846a077ac
Merge 1.20 into 1.20.6 2024-05-11 22:15:25 -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
140 changed files with 578 additions and 2432 deletions

View File

@ -166,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

@ -1,6 +1,6 @@
plugins {
id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false
id "dev.architectury.loom" version "1.6.396" apply false
id "maven-publish"
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
id 'com.palantir.git-version' version '1.0.0'

View File

@ -35,7 +35,7 @@ def versionString = "${baseVersion}${preMarker}+mc${minecraft_version}${commitHa
version = versionString
archivesBaseName = rootProject.archives_base_name + '-' + project.name
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21
repositories {
exclusiveContent {

View File

@ -43,7 +43,7 @@ curseforge {
changelog = file("${rootDir}/CHANGELOG.md")
changelogType = "markdown"
releaseType = isBeta ? "beta" : "release"
addGameVersion project.name.capitalize()
addGameVersion (project.name.equals("neoforge") ? "NeoForge" : project.name.capitalize())
gameVersionStrings.addAll(supported_minecraft_versions.tokenize(","))
mainArtifact remapJar
}
@ -66,4 +66,4 @@ tasks.modrinth.dependsOn(rootProject.generateChangelog)
tasks.register('publishToModSites') {
publishToModSites.dependsOn(tasks.modrinth)
publishToModSites.dependsOn(tasks.curseforge)
}
}

View File

@ -6,7 +6,7 @@ architectury {
common(rootProject.enabled_platforms.split(","))
}
ext.jei_minecraft_version = "1.19.4" /* temporary, till 1.20 releases */
ext.jei_minecraft_version = "1.20.2" /* temporary, till 1.20 releases */
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies

View File

@ -1,17 +1,13 @@
package org.embeddedt.modernfix;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
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.packet.EntityIDSyncPacket;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree;
import org.embeddedt.modernfix.searchtree.REIBackedSearchTree;
@ -20,8 +16,7 @@ import org.embeddedt.modernfix.util.ClassInfoManager;
import org.embeddedt.modernfix.world.IntegratedWatchdog;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ModernFixClient {
@ -123,85 +118,6 @@ public class ModernFixClient {
}
}
/**
* Horrendous hack to allow tracking every synced entity data manager.
*
* This is to ensure we can perform ID fixup on already constructed managers.
*/
public static final Set<SynchedEntityData> allEntityDatas = Collections.newSetFromMap(new WeakHashMap<>());
private static final Field entriesArrayField;
static {
Field field;
try {
field = SynchedEntityData.class.getDeclaredField("entriesArray");
field.setAccessible(true);
} catch(ReflectiveOperationException e) {
field = null;
}
entriesArrayField = field;
}
/**
* Extremely hacky method to detect and correct mismatched entity data parameter IDs on the client and server.
*
* The technique is far from ideal, but it should detect reliably and also not break already constructed entities.
*/
public static void handleEntityIDSync(EntityIDSyncPacket packet) {
Map<Class<? extends Entity>, List<Pair<String, Integer>>> info = packet.getFieldInfo();
boolean fixNeeded = false;
for(Map.Entry<Class<? extends Entity>, List<Pair<String, Integer>>> entry : info.entrySet()) {
Class<? extends Entity> eClass = entry.getKey();
for(Pair<String, Integer> field : entry.getValue()) {
String fieldName = field.getFirst();
int newId = field.getSecond();
try {
Field f = eClass.getDeclaredField(fieldName);
f.setAccessible(true);
EntityDataAccessor<?> accessor = (EntityDataAccessor<?>)f.get(null);
if(compareAndSwitchIds(eClass, fieldName, accessor, newId))
fixNeeded = true;
} catch(NoSuchFieldException e) {
ModernFix.LOGGER.warn("Couldn't find field on {}: {}", eClass, fieldName);
} catch(ReflectiveOperationException e) {
throw new RuntimeException("Unexpected exception", e);
}
}
}
/* Now the ID mappings on synced entity data instances are probably all wrong. Fix that. */
List<SynchedEntityData> dataEntries;
synchronized (allEntityDatas) {
if(fixNeeded) {
dataEntries = new ArrayList<>(allEntityDatas);
for(SynchedEntityData manager : dataEntries) {
Int2ObjectOpenHashMap<SynchedEntityData.DataItem<?>> fixedMap = new Int2ObjectOpenHashMap<>();
List<SynchedEntityData.DataItem<?>> items = new ArrayList<>(manager.itemsById.values());
for(SynchedEntityData.DataItem<?> item : items) {
fixedMap.put(item.getAccessor().id, item);
}
manager.lock.writeLock().lock();
try {
manager.itemsById.replaceAll((id, parameter) -> fixedMap.get((int)id));
if(entriesArrayField != null) {
try {
SynchedEntityData.DataItem<?>[] dataArray = new SynchedEntityData.DataItem[items.size()];
for(int i = 0; i < dataArray.length; i++) {
dataArray[i] = fixedMap.get(i);
}
entriesArrayField.set(manager, dataArray);
} catch(ReflectiveOperationException e) {
ModernFix.LOGGER.error(e);
}
}
} finally {
manager.lock.writeLock().unlock();
}
}
}
allEntityDatas.clear();
}
}
public void onServerStarted(MinecraftServer server) {
if(!ModernFixMixinPlugin.instance.isOptionEnabled("feature.integrated_server_watchdog.IntegratedWatchdog"))
return;

View File

@ -7,7 +7,7 @@ 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.ChunkStatus;
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;

View File

@ -1,56 +0,0 @@
package org.embeddedt.modernfix.common.mixin.bugfix.buffer_builder_leak;
import com.mojang.blaze3d.vertex.BufferBuilder;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.render.UnsafeBufferHelper;
import org.spongepowered.asm.mixin.Dynamic;
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.CallbackInfo;
import java.nio.ByteBuffer;
@Mixin(value = BufferBuilder.class, priority = 1500)
@ClientOnlyMixin
public class BufferBuilderMixin {
@Shadow private ByteBuffer buffer;
private static boolean leakReported = false;
private boolean mfix$shouldFree = true;
@Dynamic
@Inject(method = "flywheel$injectForRender", at = @At("RETURN"), remap = false, require = 0)
private void preventFree(CallbackInfo ci) {
mfix$shouldFree = false;
}
/**
* Ensure UnsafeBufferHelper is classloaded early, to avoid Forge's event transformer showing an error in the log.
*/
@Inject(method = "<clinit>", at = @At(value = "RETURN"))
private static void initUnsafeBufferHelper(CallbackInfo ci) {
UnsafeBufferHelper.init();
}
@Override
protected void finalize() throws Throwable {
try {
ByteBuffer buf = buffer;
// can be null if a mod already tried to free the buffer
if(buf != null && mfix$shouldFree) {
if(!leakReported) {
leakReported = true;
ModernFix.LOGGER.warn("One or more BufferBuilders have been leaked, ModernFix will attempt to correct this.");
}
UnsafeBufferHelper.free(buf);
buffer = null;
}
} finally {
super.finalize();
}
}
}

View File

@ -1,13 +1,12 @@
package org.embeddedt.modernfix.common.mixin.bugfix.paper_chunk_patches;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.level.*;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.thread.BlockableEventLoop;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -16,7 +15,6 @@ 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.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -27,15 +25,13 @@ public abstract class ChunkMapMixin {
@Shadow @Final private ChunkMap.DistanceManager distanceManager;
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> protoChunkToFullChunk(ChunkHolder arg);
@Shadow protected abstract CompletableFuture<ChunkAccess> protoChunkToFullChunk(ChunkHolder arg, ChunkAccess chunkAccess);
@Shadow @Final private ServerLevel level;
@Shadow @Final private ThreadedLevelLightEngine lightEngine;
@Shadow @Final private ChunkProgressListener progressListener;
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus);
@Shadow protected abstract CompletableFuture<ChunkResult<ChunkAccess>> scheduleChunkGeneration(ChunkHolder chunkHolder, ChunkStatus chunkStatus);
@Shadow @Final private StructureTemplateManager structureTemplateManager;
@Shadow private WorldGenContext worldGenContext;
/* https://github.com/PaperMC/Paper/blob/ver/1.17.1/patches/server/0752-Fix-chunks-refusing-to-unload-at-low-TPS.patch */
@ModifyArg(method = "prepareAccessibleChunk", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenApplyAsync(Ljava/util/function/Function;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 1)
@ -48,24 +44,24 @@ public abstract class ChunkMapMixin {
* @reason revert 1.17 chunk system changes, significantly reduces time and RAM needed to load chunks
*/
@Inject(method = "schedule", at = @At("HEAD"), cancellable = true)
private void useLegacySchedulingLogic(ChunkHolder holder, ChunkStatus requiredStatus, CallbackInfoReturnable<CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>>> cir) {
private void useLegacySchedulingLogic(ChunkHolder holder, ChunkStatus requiredStatus, CallbackInfoReturnable<CompletableFuture<ChunkResult<ChunkAccess>>> cir) {
if(requiredStatus != ChunkStatus.EMPTY && !requiredStatus.hasLoadDependencies()) {
ChunkPos chunkpos = holder.getPos();
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = holder.getOrScheduleFuture(requiredStatus.getParent(), (ChunkMap)(Object)this);
CompletableFuture<ChunkResult<ChunkAccess>> future = holder.getOrScheduleFuture(requiredStatus.getParent(), (ChunkMap)(Object)this);
cir.setReturnValue(future.thenComposeAsync((either) -> {
Optional<ChunkAccess> optional = either.left();
ChunkAccess partialChunk = either.orElse(null);
if (requiredStatus == ChunkStatus.LIGHT) {
this.distanceManager.addTicket(TicketType.LIGHT, chunkpos, 33 + ChunkStatus.getDistance(ChunkStatus.LIGHT), chunkpos);
}
// from original method
if (optional.isPresent() && optional.get().getStatus().isOrAfter(requiredStatus)) {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = requiredStatus.load(this.level, this.structureTemplateManager, this.lightEngine, (arg2) -> {
return this.protoChunkToFullChunk(holder);
}, (ChunkAccess)optional.get());
if (partialChunk != null && partialChunk.getStatus().isOrAfter(requiredStatus)) {
CompletableFuture<ChunkAccess> completablefuture = requiredStatus.load(this.worldGenContext, (partialChunkAccess) -> {
return this.protoChunkToFullChunk(holder, partialChunkAccess);
}, partialChunk);
this.progressListener.onStatusChange(chunkpos, requiredStatus);
return completablefuture;
return completablefuture.thenApply(ChunkResult::of);
} else {
return this.scheduleChunkGeneration(holder, requiredStatus);
}

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

@ -1,26 +0,0 @@
package org.embeddedt.modernfix.common.mixin.core;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.Entity;
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(SynchedEntityData.class)
@ClientOnlyMixin
public class SynchedEntityDataMixin {
/**
* Store this in our set of all entity data objects.
*
* Not an ideal solution, but it should guarantee compatibility with mods.
*/
@Inject(method = "<init>", at = @At("RETURN"))
private void storeInSet(Entity arg, CallbackInfo ci) {
synchronized (ModernFixClient.allEntityDatas) {
ModernFixClient.allEntityDatas.add((SynchedEntityData)(Object)this);
}
}
}

View File

@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class CrashReportMixin {
@Shadow @Final private Throwable exception;
@Inject(method = "addCategory(Ljava/lang/String;I)Lnet/minecraft/CrashReportCategory;", at = @At(value = "INVOKE", target = "Ljava/io/PrintStream;println(Ljava/lang/String;)V"))
@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)

View File

@ -1,16 +1,15 @@
package org.embeddedt.modernfix.common.mixin.feature.stalled_chunk_load_detection;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ChunkHolder;
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.ChunkStatus;
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;
@ -26,7 +25,7 @@ public abstract class ServerChunkCacheMixin {
@Shadow @Final private Thread mainThread;
@Shadow @Final public ServerLevel level;
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFutureMainThread(int k, int l, ChunkStatus arg, boolean bl);
@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");
@ -41,24 +40,24 @@ public abstract class ServerChunkCacheMixin {
Holder<Biome> plains = this.level.registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(Biomes.PLAINS);
cir.setReturnValue(new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ), plains));
} else if(Thread.currentThread() != this.mainThread) {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = CompletableFuture.supplyAsync(() -> this.getChunkFutureMainThread(chunkX, chunkZ, requiredStatus, false), this.mainThreadProcessor).join();
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
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> resultingChunk = null;
ChunkResult<ChunkAccess> resultingChunk = null;
try {
resultingChunk = future.get(500, TimeUnit.MILLISECONDS);
} catch(InterruptedException | ExecutionException | TimeoutException ignored) {
}
if(resultingChunk != null && resultingChunk.left().isPresent()) {
cir.setReturnValue(resultingChunk.left().get());
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.left().isPresent()) {
cir.setReturnValue(resultingChunk.left().get());
if(resultingChunk.isSuccess()) {
cir.setReturnValue(resultingChunk.orElse(null));
return;
}
} catch(InterruptedException | ExecutionException | TimeoutException e) {

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

@ -48,8 +48,8 @@ public abstract class ServerLevelMixin extends Level implements IServerLevel {
*/
@Inject(method = "<init>", at = @At("TAIL"))
private void ensureGeneration(CallbackInfo ci) {
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(StrongholdLocationCache::load,
StrongholdLocationCache::new,
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(
StrongholdLocationCache.factory((ServerLevel)(Object)this),
StrongholdLocationCache.getFileId(this.dimensionTypeRegistration()));
this.chunkSource.getGeneratorState().ensureStructuresGenerated();
}

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

@ -12,7 +12,7 @@ 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))
@Redirect(method = { "<init>", "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;" }, at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;backgroundExecutor()Ljava/util/concurrent/ExecutorService;", ordinal = 0))
private ExecutorService 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;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;"), index = 5)
private Executor getReloadExecutor(Executor asyncExecutor) {
return ModernFix.resourceReloadExecutor();
}

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

@ -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(FJ)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(FJ)V", shift = At.Shift.AFTER))
private void markNotRenderingLevel(CallbackInfo ci) {
RenderState.IS_RENDERING_LEVEL = false;
}

View File

@ -1,22 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_structure_location;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.levelgen.structure.StructureCheck;
import org.embeddedt.modernfix.duck.IStructureCheck;
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;
@Mixin(ServerLevel.class)
public class ServerLevelMixin {
@Shadow @Final private ServerChunkCache chunkSource;
@ModifyExpressionValue(method = "<init>", at = @At(value = "NEW", target = "(Lnet/minecraft/world/level/chunk/storage/ChunkScanAccess;Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/chunk/ChunkGenerator;Lnet/minecraft/world/level/levelgen/RandomState;Lnet/minecraft/world/level/LevelHeightAccessor;Lnet/minecraft/world/level/biome/BiomeSource;JLcom/mojang/datafixers/DataFixer;)Lnet/minecraft/world/level/levelgen/structure/StructureCheck;", ordinal = 0))
private StructureCheck attachGeneratorState(StructureCheck check) {
((IStructureCheck)check).mfix$setStructureState(this.chunkSource.getGeneratorState());
return check;
}
}

View File

@ -1,51 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_structure_location;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.core.Registry;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.StructureCheck;
import net.minecraft.world.level.levelgen.structure.StructureCheckResult;
import org.embeddedt.modernfix.duck.IStructureCheck;
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;
@Mixin(StructureCheck.class)
public class StructureCheckMixin implements IStructureCheck {
@Shadow @Final private Registry<Structure> structureConfigs;
private ChunkGeneratorStructureState mfix$structureState;
@Override
public void mfix$setStructureState(ChunkGeneratorStructureState state) {
mfix$structureState = state;
}
/**
* @author embeddedt (inspired by 24w04a and Bytzo's comment on https://bugs.mojang.com/browse/MC-249136)
* @reason Avoid running the canCreateStructure method (which can be expensive) if the structure placement already
* forbids placing the structure in this chunk.
*/
@ModifyExpressionValue(method = "checkStart", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureCheck;tryLoadFromStorage(Lnet/minecraft/world/level/ChunkPos;Lnet/minecraft/world/level/levelgen/structure/Structure;ZJ)Lnet/minecraft/world/level/levelgen/structure/StructureCheckResult;"))
private StructureCheckResult mfix$checkForValidPosition(StructureCheckResult storageResult, ChunkPos chunkPos, Structure structure, boolean skipKnownStructures) {
if (storageResult != null) {
return storageResult;
} else if(mfix$structureState != null) {
// Check if any of the placements allow for this structure to be in this chunk
var structureHolder = this.structureConfigs.wrapAsHolder(structure);
for (var placement : mfix$structureState.getPlacementsForStructure(structureHolder)) {
if (placement.isStructureChunk(mfix$structureState, chunkPos.x, chunkPos.z)) {
// Allowed - return null so regular check runs
return null;
}
}
// Not allowed - early exit by returning a non-null value
return StructureCheckResult.START_NOT_PRESENT;
} else {
return null;
}
}
}

View File

@ -1,36 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import net.minecraft.core.MappedRegistry;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(MappedRegistry.class)
public class MappedRegistryMixin {
/**
* Avoid copying the ID list to a slightly larger one every time an entry is added to the registry.
* The original behavior causes O(n) time complexity for registration.
*/
@Redirect(
method = "registerMapping(ILnet/minecraft/resources/ResourceKey;Ljava/lang/Object;Lcom/mojang/serialization/Lifecycle;)Lnet/minecraft/core/Holder$Reference;",
at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectList;size(I)V", remap = false)
)
private void setSizeSmart(ObjectList<?> list, int size) {
if(list instanceof ObjectArrayList && size > list.size()) {
int requestedSize = size;
/* choose next power of two, or this value if it is a power of two */
int p2Size = Integer.highestOneBit(size);
if(p2Size != size)
size = p2Size << 1;
// grow backing array to power-of-two size, this will return instantly in most cases
((ObjectArrayList<?>)list).ensureCapacity(size);
// write null entries to fill size, to match the behavior of list.size(int)
while(list.size() < requestedSize)
list.add(null);
} else {
list.size(size);
}
}
}

View File

@ -10,8 +10,8 @@ import java.util.Map;
@Mixin(targets = "net/minecraft/nbt/CompoundTag$1")
public class CompoundTag1Mixin {
@ModifyVariable(method = "load(Ljava/io/DataInput;ILnet/minecraft/nbt/NbtAccounter;)Lnet/minecraft/nbt/CompoundTag;", at = @At(value = "INVOKE_ASSIGN", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;", remap = false))
private Map<String, Tag> modifyMap(Map<String, Tag> map) {
@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);

View File

@ -0,0 +1,15 @@
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(BlockBehaviour.class)
public interface BlockBehaviourInvoker {
@Invoker
FluidState invokeGetFluidState(BlockState blockState);
@Invoker
boolean invokeIsRandomlyTicking(BlockState blockState);
}

View File

@ -1,7 +1,7 @@
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.MapCodec;
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
@ -17,9 +17,10 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(BlockBehaviour.BlockStateBase.class)
public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState> implements IBlockState {
protected BlockStateBaseMixin(Block object, ImmutableMap<Property<?>, Comparable<?>> immutableMap, MapCodec<BlockState> mapCodec) {
protected BlockStateBaseMixin(Block object, Reference2ObjectArrayMap<Property<?>, Comparable<?>> immutableMap, MapCodec<BlockState> mapCodec) {
super(object, immutableMap, mapCodec);
}
@ -93,7 +94,7 @@ public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState>
if(!buildingCache) {
buildingCache = true;
try {
this.fluidState = this.owner.getFluidState(this.asState());
this.fluidState = ((BlockBehaviourInvoker)this.owner).invokeGetFluidState(this.asState());
} finally {
buildingCache = false;
}
@ -112,7 +113,7 @@ public abstract class BlockStateBaseMixin extends StateHolder<Block, BlockState>
))
private boolean genCacheBeforeGettingTicking(BlockBehaviour.BlockStateBase base) {
if(this.cacheInvalid)
return this.owner.isRandomlyTicking(this.asState());
return ((BlockBehaviourInvoker)this.owner).invokeIsRandomlyTicking(this.asState());
return this.isRandomlyTicking;
}

View File

@ -1,37 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(Entity.class)
public class EntityMixin {
/**
* @author embeddedt
* @reason If the spawn chunks are not loaded, end portals linking to the overworld will teleport entities into
* the void at the spawn position, which is not ideal. To solve this, we create a PORTAL ticket if the expected
* overworld chunk is missing.
*/
@ModifyExpressionValue(method = "findDimensionEntryPoint", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;getSharedSpawnPos()Lnet/minecraft/core/BlockPos;"), require = 0)
private BlockPos mfix$triggerChunkloadAtSpawnPos(BlockPos spawnPos, ServerLevel destination) {
// Only apply this change if the overworld is the destination
if (destination.dimension() == ServerLevel.OVERWORLD) {
// No ticket is required if the chunk happens to already be loaded
if(!destination.hasChunk(spawnPos.getX() >> 4, spawnPos.getZ() >> 4)) {
// Create a portal ticket. While we could just load the chunk once, it would immediately unload on the
// next tick, causing churn. The ticket will keep it loaded for a few seconds which should give high
// performance for farms pumping things through portals frequently.
BlockPos key = spawnPos.immutable();
destination.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(key), 3, key);
// Wait for the chunk to be loaded, as adding the ticket is asynchronous
destination.getChunk(key);
}
}
return spawnPos;
}
}

View File

@ -1,24 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = MinecraftServer.class, priority = 1100)
public class MinecraftServerMixin {
@Redirect(method = "prepareLevels", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;addRegionTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"))
private void addSpawnChunkTicket(ServerChunkCache cache, TicketType<?> type, ChunkPos pos, int distance, Object o) {
// load first chunk
cache.getChunk(pos.x, pos.z, ChunkStatus.FULL, true);
}
@Redirect(method = "prepareLevels", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;getTickingGenerated()I"), require = 0)
private int getGenerated(ServerChunkCache cache) {
return 441;
}
}

View File

@ -1,12 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.level.DistanceManager;
import net.minecraft.server.level.ServerChunkCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ServerChunkCache.class)
public interface ServerChunkCacheAccessor {
@Accessor("distanceManager")
DistanceManager getDistanceManager();
}

View File

@ -1,20 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ServerLevel.class)
public class ServerLevelMixin {
@Redirect(method = "setDefaultSpawnPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;removeRegionTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"))
private void removeTicket(ServerChunkCache cache, TicketType<?> type, ChunkPos pos, int distance, Object o) {
}
@Redirect(method = "setDefaultSpawnPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;addRegionTicket(Lnet/minecraft/server/level/TicketType;Lnet/minecraft/world/level/ChunkPos;ILjava/lang/Object;)V"))
private void addTicket(ServerChunkCache cache, TicketType<?> type, ChunkPos pos, int distance, Object o) {
}
}

View File

@ -1,25 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.remove_spawn_chunks;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.util.SortedArraySet;
import org.embeddedt.modernfix.ModernFix;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(SortedArraySet.class)
public class SortedArraySetMixin<T> {
/**
* @author embeddedt
* @reason Make add() not crash with a null key, since some mods (Carpet) assume there will always be a spawn ticket,
* and then assume the reference they have is non-null (it can be null with this option enabled).
*/
@WrapOperation(method = "add", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/SortedArraySet;findIndex(Ljava/lang/Object;)I"), require = 0)
private int checkStatus(SortedArraySet<T> instance, T object, Operation<Integer> original) {
if(object == null) {
ModernFix.LOGGER.error("Attempted to insert a null key into SortedArraySet, ignoring");
return 0;
}
return original.call(instance, object);
}
}

View File

@ -1,40 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.ticking_chunk_alloc;
import com.mojang.datafixers.util.Either;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.world.level.chunk.LevelChunk;
import org.embeddedt.modernfix.util.EitherUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.CompletableFuture;
@Mixin(value = ChunkHolder.class, priority = 500)
public abstract class ChunkHolderMixin {
@Shadow public abstract CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> getTickingChunkFuture();
@Shadow public abstract CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> getFullChunkFuture();
/**
* @author embeddedt
* @reason avoid Optional allocation
*/
@Overwrite
public LevelChunk getTickingChunk() {
CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completableFuture = this.getTickingChunkFuture();
Either<LevelChunk, ChunkHolder.ChunkLoadingFailure> either = completableFuture.getNow(null);
return either == null ? null : EitherUtil.leftOrNull(either);
}
/**
* @author embeddedt
* @reason avoid Optional allocation
*/
@Overwrite
public LevelChunk getFullChunk() {
CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completableFuture = this.getFullChunkFuture();
Either<LevelChunk, ChunkHolder.ChunkLoadingFailure> either = completableFuture.getNow(null);
return either == null ? null : EitherUtil.leftOrNull(either);
}
}

View File

@ -63,7 +63,7 @@ public class ModernFixEarlyConfig {
private static final String MIXIN_REQUIRES_MOD_DESC = Type.getDescriptor(RequiresMod.class);
private static final String MIXIN_DEV_ONLY_DESC = Type.getDescriptor(IgnoreOutsideDev.class);
private static final Pattern PLATFORM_PREFIX = Pattern.compile("(forge|fabric|common)\\.");
private static final Pattern PLATFORM_PREFIX = Pattern.compile("(neoforge|fabric|common)\\.");
public static String sanitize(String mixinClassName) {
return PLATFORM_PREFIX.matcher(mixinClassName).replaceFirst("");
@ -79,7 +79,7 @@ public class ModernFixEarlyConfig {
}
private void scanForAndBuildMixinOptions() {
List<String> configFiles = ImmutableList.of("modernfix-common.mixins.json", "modernfix-fabric.mixins.json", "modernfix-forge.mixins.json");
List<String> configFiles = ImmutableList.of("modernfix-common.mixins.json", "modernfix-fabric.mixins.json", "modernfix-neoforge.mixins.json");
List<String> mixinPaths = new ArrayList<>();
for(String configFile : configFiles) {
InputStream stream = ModernFixEarlyConfig.class.getClassLoader().getResourceAsStream(configFile);
@ -180,9 +180,7 @@ public class ModernFixEarlyConfig {
.put("mixin.feature.warn_missing_perf_mods", true)
.put("mixin.feature.spark_profile_launch", false)
.put("mixin.devenv", isDevEnv)
.put("mixin.perf.remove_spawn_chunks", isDevEnv)
.putConditionally(() -> !isFabric, "mixin.bugfix.fix_config_crashes", true)
.putConditionally(() -> !isFabric, "mixin.bugfix.forge_at_inject_error", true)
.putConditionally(() -> !isFabric, "mixin.feature.registry_event_progress", false)
.putConditionally(() -> isFabric, "mixin.perf.clear_fabric_mapping_tables", false)
.build();

View File

@ -1,57 +0,0 @@
package org.embeddedt.modernfix.entity;
import com.mojang.datafixers.util.Pair;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EntityDataIDSyncHandler {
private static Map<Class<? extends Entity>, List<Pair<String, Integer>>> fieldsToSyncMap;
@SuppressWarnings("unchecked")
public static void onDatapackSyncEvent(ServerPlayer targetPlayer) {
if(targetPlayer != null) {
/* Compute the current set of serializer IDs in use and send them */
if(fieldsToSyncMap == null) {
fieldsToSyncMap = new HashMap<>();
Map<Class<? extends Entity>, Integer> entityPoolMap = SynchedEntityData.ENTITY_ID_POOL;
List<Field> fieldsToSync = new ArrayList<>();
for(Class<? extends Entity> eClass : entityPoolMap.keySet()) {
fieldsToSync.clear();
try {
Field[] classFields = eClass.getDeclaredFields();
for(Field field : classFields) {
if(!Modifier.isStatic(field.getModifiers()))
continue;
field.setAccessible(true);
Object o = field.get(null);
if(o != null && EntityDataAccessor.class.isAssignableFrom(o.getClass())) {
fieldsToSync.add(field);
}
}
for(Field field : fieldsToSync) {
int id = ((EntityDataAccessor<?>)field.get(null)).id;
fieldsToSyncMap.computeIfAbsent(eClass, k -> new ArrayList<>()).add(Pair.of(field.getName(), id));
}
} catch(Throwable e) {
ModernFix.LOGGER.error("Skipping entity ID sync for {}: {}", eClass.getName(), e);
}
}
}
EntityIDSyncPacket packet = new EntityIDSyncPacket(fieldsToSyncMap);
ModernFix.LOGGER.debug("Sending ID correction packet to client with " + fieldsToSyncMap.size() + " classes");
ModernFixPlatformHooks.INSTANCE.sendPacket(targetPlayer, packet);
}
}
}

View File

@ -1,78 +0,0 @@
package org.embeddedt.modernfix.packet;
import com.mojang.datafixers.util.Pair;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.Entity;
import org.embeddedt.modernfix.ModernFix;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
public class EntityIDSyncPacket {
private Map<Class<? extends Entity>, List<Pair<String, Integer>>> map;
public EntityIDSyncPacket(Map<Class<? extends Entity>, List<Pair<String, Integer>>> map) {
this.map = map;
}
public Map<Class<? extends Entity>, List<Pair<String, Integer>>> getFieldInfo() {
return this.map;
}
public EntityIDSyncPacket() {
this.map = new HashMap<>();
}
public void serialize(FriendlyByteBuf buf) {
buf.writeVarInt(map.keySet().size());
for(Map.Entry<Class<? extends Entity>, List<Pair<String, Integer>>> entry : map.entrySet()) {
buf.writeUtf(entry.getKey().getName());
buf.writeVarInt(entry.getValue().size());
for(Pair<String, Integer> field : entry.getValue()) {
buf.writeUtf(field.getFirst());
buf.writeVarInt(field.getSecond());
}
}
}
@SuppressWarnings("unchecked")
public static EntityIDSyncPacket deserialize(FriendlyByteBuf buf) {
EntityIDSyncPacket self = new EntityIDSyncPacket();
int numEntityClasses = buf.readVarInt();
for(int i = 0; i < numEntityClasses; i++) {
String clzName = buf.readUtf();
try {
Class<?> clz;
try {
clz = Class.forName(clzName);
} catch(ClassNotFoundException e) {
ModernFix.LOGGER.warn("Entity class not found: {}", clzName);
break;
}
if(!Entity.class.isAssignableFrom(clz)) {
ModernFix.LOGGER.error("Not an entity: " + clzName);
break;
}
int numFields = buf.readVarInt();
for(int j = 0; j < numFields; j++) {
String fieldName = buf.readUtf();
int id = buf.readVarInt();
Field f = clz.getDeclaredField(fieldName);
if(!Modifier.isStatic(f.getModifiers()))
continue;
f.setAccessible(true);
if(!EntityDataAccessor.class.isAssignableFrom(f.get(null).getClass())) {
ModernFix.LOGGER.error("Not a data accessor field: " + clz + "." + fieldName);
continue;
}
self.map.computeIfAbsent((Class<? extends Entity>)clz, k -> new ArrayList<>()).add(Pair.of(fieldName, id));
}
} catch(ReflectiveOperationException e) {
ModernFix.LOGGER.error("Error deserializing packet", e);
}
}
return self;
}
}

View File

@ -4,6 +4,7 @@ import com.google.common.collect.Multimap;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
@ -39,7 +40,7 @@ public interface ModernFixPlatformHooks {
Path getGameDirectory();
void sendPacket(ServerPlayer player, Object packet);
void sendPacket(ServerPlayer player, CustomPacketPayload packet);
Multimap<String, String> getCustomModOptions();

View File

@ -4,7 +4,7 @@ import java.lang.reflect.Constructor;
class PlatformHookLoader {
static ModernFixPlatformHooks findInstance() {
String[] locations = new String[] { "forge", "fabric" };
String[] locations = new String[] { "neoforge", "fabric" };
for(String location : locations) {
try {
Class<?> clz = Class.forName("org.embeddedt.modernfix.platform." + location + ".ModernFixPlatformHooksImpl");

View File

@ -1,15 +1,16 @@
package org.embeddedt.modernfix.registry;
import com.mojang.serialization.Lifecycle;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.resources.ResourceKey;
public class LifecycleMap<T> extends Reference2ReferenceOpenHashMap<T, Lifecycle> {
public class LifecycleMap<T> extends Reference2ReferenceOpenHashMap<ResourceKey<T>, RegistrationInfo> {
public LifecycleMap() {
this.defaultReturnValue(Lifecycle.stable());
this.defaultReturnValue(RegistrationInfo.BUILT_IN);
}
@Override
public Lifecycle put(T t, Lifecycle lifecycle) {
public RegistrationInfo put(ResourceKey<T> t, RegistrationInfo lifecycle) {
if(lifecycle != defRetValue)
return super.put(t, lifecycle);
else {

View File

@ -1,51 +0,0 @@
package org.embeddedt.modernfix.render;
import org.embeddedt.modernfix.ModernFix;
import org.lwjgl.system.MemoryUtil;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
/**
* Helper that frees ByteBuffers allocated by BufferBuilders, and nulls out the address pointer
* to prevent double frees.
*
* @author Moulberry
*/
public class UnsafeBufferHelper {
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
private static sun.misc.Unsafe UNSAFE = null;
private static long ADDRESS = -1;
static {
try {
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe)theUnsafe.get(null);
final Field addressField = MemoryUtil.class.getDeclaredField("ADDRESS");
addressField.setAccessible(true);
ADDRESS = addressField.getLong(null);
} catch(Throwable t) {
ModernFix.LOGGER.error("Could load unsafe/buffer address", t);
}
}
public static void init() {
}
public static void free(ByteBuffer buf) {
if(UNSAFE != null && ADDRESS >= 0) {
// set the address to 0 to prevent double free
long address = UNSAFE.getAndSetLong(buf, ADDRESS, 0);
if(address != 0) {
ALLOCATOR.free(address);
}
} else {
ALLOCATOR.free(MemoryUtil.memAddress0(buf));
}
}
}

View File

@ -42,11 +42,10 @@ public class ModernFixConfigScreen extends Screen {
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(guiGraphics);
super.render(guiGraphics, mouseX, mouseY, partialTicks);
this.optionList.render(guiGraphics, mouseX, mouseY, partialTicks);
guiGraphics.drawCenteredString(this.font, this.title, this.width / 2, 8, 16777215);
this.doneButton.setMessage(madeChanges ? Component.translatable("modernfix.config.done_restart") : CommonComponents.GUI_DONE);
super.render(guiGraphics, mouseX, mouseY, partialTicks);
}
public void setLastScrollAmount(double d) {

View File

@ -41,9 +41,8 @@ public class ModernFixOptionInfoScreen extends Screen {
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(guiGraphics);
super.render(guiGraphics, mouseX, mouseY, partialTicks);
guiGraphics.drawCenteredString(this.font, this.title, this.width / 2, 8, 16777215);
this.drawMultilineString(guiGraphics, this.minecraft.font, description, 10, 50);
super.render(guiGraphics, mouseX, mouseY, partialTicks);
}
}

View File

@ -69,7 +69,7 @@ public class OptionList extends ContainerObjectSelectionList<OptionList.Entry> {
}
public OptionList(ModernFixConfigScreen arg, Minecraft arg2) {
super(arg2,arg.width + 45, arg.height, 43, arg.height - 32, 20);
super(arg2,arg.width + 45, arg.height - 52, 20, 20);
this.mainScreen = arg;

View File

@ -28,7 +28,7 @@ public class RecipeBookSearchTree extends DummySearchTree<RecipeCollection> {
collections = new Object2ObjectOpenHashMap<>();
Map<Item, List<RecipeCollection>> finalCollection = collections;
for(RecipeCollection collection : allCollections) {
collection.getRecipes().stream().map(recipe -> recipe.getResultItem(collection.registryAccess()).getItem()).distinct().forEach(item -> {
collection.getRecipes().stream().map(recipe -> recipe.value().getResultItem(collection.registryAccess()).getItem()).distinct().forEach(item -> {
finalCollection.computeIfAbsent(item, k -> new ArrayList<>()).add(collection);
});
}

View File

@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.SharedConstants;
import net.minecraft.core.HolderGetter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.datafix.DataFixTypes;
@ -58,7 +59,7 @@ public class CachingStructureManager {
public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException {
byte[] structureBytes = toBytes(stream);
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes));
CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes), NbtAccounter.unlimitedHeap());
if (!currentTag.contains("DataVersion", 99)) {
currentTag.putInt("DataVersion", 500);
}
@ -100,8 +101,8 @@ public class CachingStructureManager {
private static synchronized CompoundTag getCachedUpgraded(ResourceLocation location, String hash) {
File theFile = getCachePath(location, hash);
try {
return NbtIo.readCompressed(theFile);
try(FileInputStream stream = new FileInputStream(theFile)) {
return NbtIo.readCompressed(stream, NbtAccounter.unlimitedHeap());
} catch(FileNotFoundException e) {
return null;
} catch(IOException e) {
@ -112,8 +113,8 @@ public class CachingStructureManager {
private static synchronized void saveCachedUpgraded(ResourceLocation location, String hash, CompoundTag tagToSave) {
File theFile = getCachePath(location, truncateHash(hash));
try {
NbtIo.writeCompressed(tagToSave, theFile);
try(FileOutputStream stream = new FileOutputStream(theFile)) {
NbtIo.writeCompressed(tagToSave, stream);
} catch(IOException e) {
e.printStackTrace();
}

View File

@ -1,25 +0,0 @@
package org.embeddedt.modernfix.util;
import org.embeddedt.modernfix.ModernFix;
public enum BakeReason {
FREEZE,
REMOTE_SNAPSHOT_INJECT,
LOCAL_SNAPSHOT_INJECT,
REVERT,
UNKNOWN;
private static BakeReason currentBakeReason = null;
private static boolean bakeReasonWarned = false;
public static BakeReason getCurrentBakeReason() {
if(currentBakeReason == null && !bakeReasonWarned) {
ModernFix.LOGGER.warn("No bake reason found, mixin probably not applied correctly", new IllegalStateException());
bakeReasonWarned = false;
}
return currentBakeReason;
}
public static void setCurrentBakeReason(BakeReason reason) {
currentBakeReason = reason;
}
}

View File

@ -96,7 +96,7 @@ public class DummyServerConfiguration implements WorldData {
}
@Override
public boolean getAllowCommands() {
public boolean isAllowCommands() {
return false;
}

View File

@ -1,8 +1,11 @@
package org.embeddedt.modernfix.world;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.datafix.DataFixTypes;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.saveddata.SavedData;
@ -17,6 +20,11 @@ public class StrongholdLocationCache extends SavedData {
chunkPosList = new ArrayList<>();
}
public static SavedData.Factory<StrongholdLocationCache> factory(ServerLevel serverLevel) {
// FIXME datafixer will probably throw on update
return new SavedData.Factory<>(StrongholdLocationCache::new, StrongholdLocationCache::load, DataFixTypes.SAVED_DATA_FORCED_CHUNKS);
}
public List<ChunkPos> getChunkPosList() {
return new ArrayList<>(chunkPosList);
}
@ -26,7 +34,7 @@ public class StrongholdLocationCache extends SavedData {
this.setDirty();
}
public static StrongholdLocationCache load(CompoundTag arg) {
public static StrongholdLocationCache load(CompoundTag arg, HolderLookup.Provider provider) {
StrongholdLocationCache cache = new StrongholdLocationCache();
if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) {
long[] positions = arg.getLongArray("Positions");
@ -38,7 +46,7 @@ public class StrongholdLocationCache extends SavedData {
}
@Override
public CompoundTag save(CompoundTag compoundTag) {
public CompoundTag save(CompoundTag compoundTag, HolderLookup.Provider provider) {
long[] serialized = new long[chunkPosList.size()];
for(int i = 0; i < chunkPosList.size(); i++) {
ChunkPos thePos = chunkPosList.get(i);

View File

@ -21,9 +21,6 @@ accessible field net/minecraft/client/renderer/texture/Stitcher$Holder height I
accessible field net/minecraft/network/syncher/EntityDataAccessor id I
mutable field net/minecraft/network/syncher/EntityDataAccessor id I
accessible class net/minecraft/client/resources/model/ModelBakery$BlockStateDefinitionException
accessible field net/minecraft/network/syncher/SynchedEntityData itemsById Lit/unimi/dsi/fastutil/ints/Int2ObjectMap;
accessible field net/minecraft/network/syncher/SynchedEntityData ENTITY_ID_POOL Lit/unimi/dsi/fastutil/objects/Object2IntMap;
accessible field net/minecraft/network/syncher/SynchedEntityData lock Ljava/util/concurrent/locks/ReadWriteLock;
accessible method net/minecraft/Util makeExecutor (Ljava/lang/String;)Ljava/util/concurrent/ExecutorService;
accessible field net/minecraft/server/level/ChunkMap updatingChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
accessible field net/minecraft/server/level/ChunkMap visibleChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;

View File

@ -29,7 +29,6 @@ configurations {
dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
testImplementation "net.fabricmc:fabric-loader-junit:${rootProject.fabric_loader_version}"
include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${rootProject.mixinextras_version}")))
modCompileOnly(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }

View File

@ -3,7 +3,6 @@ package org.embeddedt.modernfix.fabric.mappings;
import net.fabricmc.loader.api.*;
import net.fabricmc.loader.impl.launch.FabricLauncherBase;
import net.fabricmc.loader.impl.launch.MappingConfiguration;
import net.fabricmc.mapping.tree.TinyMappingFactory;
import org.embeddedt.modernfix.util.CommonModUtil;
import java.lang.reflect.Constructor;
@ -28,7 +27,9 @@ public class MappingsClearer {
@SuppressWarnings("unchecked")
public static void clear() {
if(FabricLoader.getInstance().isDevelopmentEnvironment())
// TODO: Port this to Fabric Loader 0.15
if(true) //FabricLoader.getInstance().isDevelopmentEnvironment())
return; // never do this in dev
Optional<Version> loaderVersion = FabricLoader.getInstance().getModContainer("fabricloader").map(m -> m.getMetadata().getVersion());
@ -50,7 +51,7 @@ public class MappingsClearer {
MappingConfiguration config = FabricLauncherBase.getLauncher().getMappingConfiguration();
Field mappingsField = MappingConfiguration.class.getDeclaredField("mappings");
mappingsField.setAccessible(true);
mappingsField.set(config, TinyMappingFactory.EMPTY_TREE);
//mappingsField.set(config, TinyMappingFactory.EMPTY_TREE);
// clear useless intermediary->intermediary mappings
MappingResolver resolver = FabricLoader.getInstance().getMappingResolver();

View File

@ -0,0 +1,18 @@
package org.embeddedt.modernfix.fabric.mixin.core;
import net.minecraft.client.multiplayer.ClientConfigurationPacketListenerImpl;
import org.embeddedt.modernfix.ModernFixClientFabric;
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(ClientConfigurationPacketListenerImpl.class)
@ClientOnlyMixin
public class ClientCommonPacketListenerImplMixin {
@Inject(method = "handleUpdateTags", at = @At("RETURN"))
private void signalTags(CallbackInfo ci) {
ModernFixClientFabric.commonMod.onTagsUpdated();
}
}

View File

@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
@ClientOnlyMixin
public class ClientMinecraftServerMixin {
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getMillis()J", ordinal = 0))
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getNanos()J", ordinal = 0))
private void markServerStarted(CallbackInfo ci) {
ModernFixClient.INSTANCE.onServerStarted((MinecraftServer)(Object)this);
}

View File

@ -15,9 +15,4 @@ public class ClientPlayNetHandlerMixin {
private void signalRecipes(CallbackInfo ci) {
ModernFixClientFabric.commonMod.onRecipesUpdated();
}
@Inject(method = "handleUpdateTags", at = @At("RETURN"))
private void signalTags(CallbackInfo ci) {
ModernFixClientFabric.commonMod.onTagsUpdated();
}
}

View File

@ -17,7 +17,7 @@ public class MinecraftServerMixin {
ModernFixFabric.theServer = new WeakReference<>((MinecraftServer)(Object)this);
}
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getMillis()J", ordinal = 0))
@Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;getNanos()J", ordinal = 0))
private void hookServerStarted(CallbackInfo ci) {
ModernFix.INSTANCE.onServerStarted();
}

View File

@ -11,6 +11,7 @@ import net.fabricmc.loader.api.metadata.CustomValue;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.minecraft.client.searchtree.SearchRegistry;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.CreativeModeTabs;
@ -70,7 +71,7 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks {
return FabricLoader.getInstance().getGameDir();
}
public void sendPacket(ServerPlayer player, Object packet) {
public void sendPacket(ServerPlayer player, CustomPacketPayload packet) {
//PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), packet);
}

View File

@ -42,7 +42,8 @@
"modernfix-common.mixins.json"
],
"depends": {
"minecraft": ">=1.16.2"
"minecraft": ">=1.16.2",
"fabricloader": ">=0.15.0"
},
"breaks": {
"dashloader": "<5.0.0-beta.1"

View File

@ -4,7 +4,6 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.FluidState;
import org.embeddedt.modernfix.duck.IBlockState;
import org.embeddedt.modernfix.testing.util.BootstrapMinecraft;
import org.junit.jupiter.api.*;
@ -79,6 +78,7 @@ public class BlockStateCacheTest {
}
}
/*
@Test
@Order(5)
public void checkRecursiveFluidState() {
@ -93,4 +93,5 @@ public class BlockStateCacheTest {
// this should not throw
state.getFluidState();
}
*/
}

View File

@ -25,7 +25,7 @@ dependencies {
modImplementation(fabricApi.module("fabric-models-v0", "0.84.0+1.20.1")) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-registry-sync-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-renderer-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-rendering-data-attachment-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.36+92a0d36777") { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modImplementation(fabricApi.module("fabric-rendering-fluids-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modRuntimeOnly(fabricApi.module("fabric-renderer-indigo", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }

View File

@ -5,7 +5,7 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
public class TestBlock extends Block {
private static final BlockBehaviour.Properties PROPERTIES = BlockBehaviour.Properties.copy(Blocks.STONE);
private static final BlockBehaviour.Properties PROPERTIES = BlockBehaviour.Properties.ofFullCopy(Blocks.STONE);
public TestBlock() {
super(PROPERTIES);

View File

@ -1 +0,0 @@
loom.platform=forge

View File

@ -1,121 +0,0 @@
package org.embeddedt.modernfix.forge.classloading;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.modlauncher.LaunchPluginHandler;
import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.api.NamedPath;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModValidator;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import org.apache.commons.lang3.tuple.Pair;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.util.CommonModUtil;
import org.objectweb.asm.Type;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class ATInjector {
public static void injectModATs() {
CommonModUtil.runWithoutCrash(() -> {
ModValidator validator = ObfuscationReflectionHelper.getPrivateValue(FMLLoader.class, null, "modValidator");
List<ModFile> modFiles = ObfuscationReflectionHelper.getPrivateValue(ModValidator.class, validator, "candidateMods");
List<Pair<ModFile, Path>> list = modFiles.stream()
.filter(file -> file.getAccessTransformer().isPresent())
.map(file -> Pair.of(file, file.getAccessTransformer().get()))
.collect(Collectors.toList());
if(list.size() > 0) {
ModernFixMixinPlugin.instance.logger.warn("Applying ATs from {} mods despite being in errored state, this might cause a crash!", list.size());
for(var pair : list) {
try {
FMLLoader.addAccessTransformer(pair.getRight(), pair.getLeft());
} catch(RuntimeException e) {
ModernFixMixinPlugin.instance.logger.error("Exception occured applying AT from {}", pair.getLeft().getFileName(), e);
}
}
}
// inject into Launcher.INSTANCE.launchPlugins and wrap the mixin plugin, so that mixin transformations
// are not applied
try {
Launcher launcher = Launcher.INSTANCE;
Field launchPlugins = Launcher.class.getDeclaredField("launchPlugins");
launchPlugins.setAccessible(true);
LaunchPluginHandler handler = (LaunchPluginHandler) launchPlugins.get(launcher);
Field plugins = LaunchPluginHandler.class.getDeclaredField("plugins");
plugins.setAccessible(true);
//noinspection unchecked
Map<String, ILaunchPluginService> map = (Map<String, ILaunchPluginService>) plugins.get(handler);
Map<String, ILaunchPluginService> newMap = new HashMap<>(map);
NonTransformingLaunchPluginService.class.getName(); // trigger classloading, just to be safe
newMap.replaceAll((name, plugin) -> {
if(plugin.getClass().getName().startsWith("org.spongepowered.asm.launch.MixinLaunchPlugin")) {
ModernFixMixinPlugin.instance.logger.warn("Disabling plugin '{}': {}", name, plugin.getClass().getName());
return new NonTransformingLaunchPluginService(plugin);
} else {
return plugin;
}
});
plugins.set(handler, newMap);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}, "applying mod ATs in errored state");
}
static class NonTransformingLaunchPluginService implements ILaunchPluginService {
private final ILaunchPluginService delegate;
NonTransformingLaunchPluginService(ILaunchPluginService delegate) {
this.delegate = delegate;
}
@Override
public String name() {
return delegate.name();
}
private static final EnumSet<Phase> NEVER = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
return NEVER;
}
@Override
public void offerResource(Path resource, String name) {
delegate.offerResource(resource, name);
}
@Override
public void addResources(List<SecureJar> resources) {
delegate.addResources(resources);
}
@Override
public void initializeLaunch(ITransformerLoader transformerLoader, NamedPath[] specialPaths) {
delegate.initializeLaunch(transformerLoader, specialPaths);
}
@Override
public <T> T getExtension() {
return delegate.getExtension();
}
@Override
public void customAuditConsumer(String className, Consumer<String[]> auditDataAcceptor) {
delegate.customAuditConsumer(className, auditDataAcceptor);
}
}
}

View File

@ -1,134 +0,0 @@
package org.embeddedt.modernfix.forge.classloading;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraftforge.accesstransformer.AccessTransformer;
import net.minecraftforge.accesstransformer.AccessTransformerEngine;
import net.minecraftforge.accesstransformer.INameHandler;
import net.minecraftforge.accesstransformer.Target;
import net.minecraftforge.accesstransformer.parser.AccessTransformerList;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import org.objectweb.asm.Type;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class FastAccessTransformerList extends AccessTransformerList {
private FastATMap accessTransformerMap;
public static void attemptReplace() {
AccessTransformerList masterList;
FastAccessTransformerList myList = new FastAccessTransformerList();
try {
Field master = AccessTransformerEngine.class.getDeclaredField("masterList");
master.setAccessible(true);
masterList = (AccessTransformerList)master.get(AccessTransformerEngine.INSTANCE);
Field transfomersMap = AccessTransformerList.class.getDeclaredField("accessTransformers");
transfomersMap.setAccessible(true);
Map<Target<?>, AccessTransformer> map = (Map<Target<?>, AccessTransformer>)transfomersMap.get(masterList);
INameHandler nameHandler = ObfuscationReflectionHelper.getPrivateValue(AccessTransformerList.class, masterList, "nameHandler");
myList.setNameHandler(nameHandler);
myList.accessTransformerMap = new FastATMap(map);
ObfuscationReflectionHelper.setPrivateValue(AccessTransformerList.class, myList, myList.accessTransformerMap, "accessTransformers");
master.set(AccessTransformerEngine.INSTANCE, myList);
} catch(ReflectiveOperationException e) {
e.printStackTrace();
}
}
@Override
public boolean containsClassTarget(Type type) {
return this.accessTransformerMap.containsType(type);
}
private static class FastATMap implements Map<Target<?>, AccessTransformer> {
private final Map<Target<?>, AccessTransformer> delegate;
private final Set<Type> allContainedTypes;
public FastATMap(Map<Target<?>, AccessTransformer> delegate) {
this.delegate = new HashMap<>();
this.allContainedTypes = new ObjectOpenHashSet<>();
this.putAll(delegate);
}
@Override
public int size() {
return this.delegate.size();
}
@Override
public boolean isEmpty() {
return this.delegate.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return this.delegate.containsKey(o);
}
@Override
public boolean containsValue(Object o) {
return this.delegate.containsValue(o);
}
@Override
public AccessTransformer get(Object o) {
return this.delegate.get(o);
}
@Nullable
@Override
public AccessTransformer put(Target<?> target, AccessTransformer accessTransformer) {
this.allContainedTypes.add(target.getASMType());
return this.delegate.put(target, accessTransformer);
}
@Override
public AccessTransformer remove(Object o) {
if(o instanceof Target) {
this.allContainedTypes.remove(((Target<?>)o).getASMType());
}
return this.delegate.remove(o);
}
@Override
public void putAll(@NotNull Map<? extends Target<?>, ? extends AccessTransformer> map) {
for(Target<?> key : map.keySet()) {
this.allContainedTypes.add(key.getASMType());
}
this.delegate.putAll(map);
}
@Override
public void clear() {
this.allContainedTypes.clear();
this.delegate.clear();
}
@NotNull
@Override
public Set<Target<?>> keySet() {
return this.delegate.keySet();
}
@NotNull
@Override
public Collection<AccessTransformer> values() {
return this.delegate.values();
}
@NotNull
@Override
public Set<Entry<Target<?>, AccessTransformer>> entrySet() {
return this.delegate.entrySet();
}
public boolean containsType(Type type) {
return this.allContainedTypes.contains(type);
}
}
}

View File

@ -1,122 +0,0 @@
package org.embeddedt.modernfix.forge.init;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.OnDatapackSyncEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.network.NetworkConstants;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
import net.minecraftforge.server.ServerLifecycleHooks;
import org.apache.commons.lang3.tuple.Pair;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.entity.EntityDataIDSyncHandler;
import org.embeddedt.modernfix.forge.ModernFixConfig;
import org.embeddedt.modernfix.forge.classloading.ClassLoadHack;
import org.embeddedt.modernfix.forge.classloading.ModFileScanDataDeduplicator;
import org.embeddedt.modernfix.forge.config.ConfigFixer;
import org.embeddedt.modernfix.forge.config.NightConfigFixer;
import org.embeddedt.modernfix.forge.packet.PacketHandler;
import org.embeddedt.modernfix.forge.registry.ObjectHolderClearer;
import java.util.List;
@Mod(ModernFix.MODID)
public class ModernFixForge {
private static ModernFix commonMod;
public static boolean launchDone = false;
public ModernFixForge() {
commonMod = new ModernFix();
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerItems);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> MinecraftForge.EVENT_BUS.register(new ModernFixClientForge()));
ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> NetworkConstants.IGNORESERVERONLY, (a, b) -> true));
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModernFixConfig.COMMON_CONFIG);
PacketHandler.register();
ModFileScanDataDeduplicator.deduplicate();
ClassLoadHack.loadModClasses();
ConfigFixer.replaceConfigHandlers();
}
@SubscribeEvent
public void onCommandRegister(RegisterCommandsEvent event) {
for(String name : new String[] { "mfsrc"}) {
event.getDispatcher().register(LiteralArgumentBuilder.<CommandSourceStack>literal(name)
.requires(source -> source.hasPermission(3))
.executes(context -> {
NightConfigFixer.runReloads();
return 1;
}));
}
}
@SubscribeEvent
public void onDatapackSync(OnDatapackSyncEvent event) {
if(event.getPlayer() != null) {
if(!ServerLifecycleHooks.getCurrentServer().isDedicatedServer() && event.getPlayerList().getPlayerCount() == 0)
return;
EntityDataIDSyncHandler.onDatapackSyncEvent(event.getPlayer());
}
}
private void registerItems(RegisterEvent event) {
if(Boolean.getBoolean("modernfix.largeRegistryTest")) {
event.register(ForgeRegistries.Keys.ITEMS, helper -> {
Item.Properties props = new Item.Properties();
for(int i = 0; i < 1000000; i++) {
helper.register(new ResourceLocation("modernfix", "item_" + i), new Item(props));
}
});
}
}
private static final List<Pair<List<String>, String>> MOD_WARNINGS = ImmutableList.of(
Pair.of(ImmutableList.of("ferritecore"), "modernfix.no_ferritecore")
);
@SubscribeEvent
public void commonSetup(FMLCommonSetupEvent event) {
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.warn_missing_perf_mods.Warnings")) {
event.enqueueWork(() -> {
boolean atLeastOneWarning = false;
for(Pair<List<String>, String> warning : MOD_WARNINGS) {
boolean isPresent = !FMLLoader.isProduction() || warning.getLeft().stream().anyMatch(name -> ModList.get().isLoaded(name));
if(!isPresent) {
atLeastOneWarning = true;
ModLoader.get().addWarning(new ModLoadingWarning(ModLoadingContext.get().getActiveContainer().getModInfo(), ModLoadingStage.COMMON_SETUP, warning.getRight()));
}
}
if(atLeastOneWarning)
ModLoader.get().addWarning(new ModLoadingWarning(ModLoadingContext.get().getActiveContainer().getModInfo(), ModLoadingStage.COMMON_SETUP, "modernfix.perf_mod_warning"));
});
}
ObjectHolderClearer.clearThrowables();
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onServerDead(ServerStoppedEvent event) {
commonMod.onServerDead(event.getServer());
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onServerStarted(ServerStartedEvent event) {
commonMod.onServerStarted();
}
}

View File

@ -1,58 +0,0 @@
package org.embeddedt.modernfix.forge.load;
import net.minecraftforge.fml.ModWorkManager;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
public class ModWorkManagerQueue extends ConcurrentLinkedDeque<Runnable> {
private static final long PARK_TIME = TimeUnit.MILLISECONDS.toNanos(25);
private static final Runnable DUMMY_TASK = () -> {};
private boolean shouldReturnDummyTask = false;
/**
* Sleep for a bit if there are no tasks.
*/
@Override
public Runnable pollFirst() {
Runnable r = super.pollFirst();
if(r == null) {
LockSupport.parkNanos(PARK_TIME);
boolean isReturning = shouldReturnDummyTask;
shouldReturnDummyTask = !shouldReturnDummyTask;
/*
* We need to kick FML to redraw the loading screen periodically,
* but also allow actually exiting the executor loop, so that
* loading can complete if async work is done.
*
* This is accomplished by alternating between returning a dummy
* task and nothing.
*/
return isReturning ? DUMMY_TASK : null;
} else {
return r;
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static void replace() {
try {
Class<?> syncExecutorClass = Class.forName("net.minecraftforge.fml.ModWorkManager$SyncExecutor");
ConcurrentLinkedDeque<Runnable> taskQueue = (ConcurrentLinkedDeque<Runnable>) ObfuscationReflectionHelper.getPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), "tasks");
ModWorkManagerQueue q = new ModWorkManagerQueue();
Runnable task;
do {
task = taskQueue.pollFirst();
if(task != null)
q.push(task);
} while(task != null);
ObfuscationReflectionHelper.setPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), q, "tasks");
} catch(ReflectiveOperationException e) {
e.printStackTrace();
}
}
}

View File

@ -1,57 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.bugfix.chunk_deadlock;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import org.jetbrains.annotations.Nullable;
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.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
@Mixin(value = ServerChunkCache.class, priority = 1100)
public abstract class ServerChunkCache_CurrentLoadingMixin {
@Shadow @Nullable protected abstract ChunkHolder getVisibleChunkIfPresent(long l);
private static final MethodHandle CURRENTLY_LOADING;
static {
try {
Field currentlyLoadingField = ObfuscationReflectionHelper.findField(ChunkHolder.class, "currentlyLoading");
currentlyLoadingField.setAccessible(true);
CURRENTLY_LOADING = MethodHandles.lookup().unreflectGetter(currentlyLoadingField);
} catch(Exception e) {
throw new RuntimeException("Failed to get currentlyLoading field", e);
}
}
/**
* Check the currentlyLoading field before going to the future chain, as was done in 1.16. In 1.18 upstream seems
* to have only applied this to getChunkNow().
*/
@Inject(method = "getChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerChunkCache;getChunkFutureMainThread(IILnet/minecraft/world/level/chunk/ChunkStatus;Z)Ljava/util/concurrent/CompletableFuture;"), cancellable = true, require = 0)
private void checkCurrentlyLoading(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load, CallbackInfoReturnable<ChunkAccess> cir) {
long i = ChunkPos.asLong(chunkX, chunkZ);
ChunkHolder holder = this.getVisibleChunkIfPresent(i);
if(holder != null) {
LevelChunk c;
try {
c = (LevelChunk)CURRENTLY_LOADING.invokeExact(holder);
} catch(Throwable e) {
e.printStackTrace();
c = null;
}
if(c != null)
cir.setReturnValue(c);
}
}
}

View File

@ -1,36 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.bugfix.forge_vehicle_packets;
import net.minecraft.network.protocol.game.ServerboundMoveVehiclePacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.phys.Vec3;
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.Redirect;
@Mixin(ServerGamePacketListenerImpl.class)
public class ServerGamePacketListenerImplMixin {
@Shadow public ServerPlayer player;
@Redirect(method = "handleMoveVehicle", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;absMoveTo(DDDFF)V"), require = 0)
private void movePlayerUsingPositionRider(ServerPlayer player, double x, double y, double z, float yRot, float xRot, ServerboundMoveVehiclePacket packet) {
if(player == this.player) {
// use positionRider
Vec3 oldPos = this.player.position();
yRot = this.player.getYRot();
xRot = this.player.getXRot();
float yHeadRot = this.player.getYHeadRot();
this.player.getRootVehicle().positionRider(this.player);
// keep old rotation
this.player.setYRot(yRot);
this.player.setXRot(xRot);
this.player.setYHeadRot(yHeadRot);
// save old position
this.player.xo = oldPos.x;
this.player.yo = oldPos.y;
this.player.zo = oldPos.z;
} else
player.absMoveTo(x, y, z, yRot, xRot);
}
}

View File

@ -1,56 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.bugfix.model_data_manager_cme;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraftforge.client.model.data.ModelDataManager;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
/**
* Fix several concurrency issues in the default ModelDataManager.
*/
@Mixin(ModelDataManager.class)
@ClientOnlyMixin
public abstract class ModelDataManagerMixin {
@Shadow protected abstract void refreshAt(ChunkPos chunk);
@Shadow @Final private Map<ChunkPos, Set<BlockPos>> needModelDataRefresh;
/**
* Make the set of positions to refresh a real concurrent hash set rather than relying on synchronizedSet,
* because the returned iterator won't be thread-safe otherwise. See https://github.com/AppliedEnergistics/Applied-Energistics-2/issues/7511
*/
@ModifyArg(method = "requestRefresh", at = @At(value = "INVOKE", target = "Ljava/util/Map;computeIfAbsent(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;", ordinal = 0), index = 1, remap = false)
private Function<ChunkPos, Set<BlockPos>> changeTypeOfSetUsed(Function<ChunkPos, Set<BlockPos>> mappingFunction) {
return pos -> Collections.newSetFromMap(new ConcurrentHashMap<>());
}
@Redirect(method = "getAt(Lnet/minecraft/world/level/ChunkPos;)Ljava/util/Map;", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/model/data/ModelDataManager;refreshAt(Lnet/minecraft/world/level/ChunkPos;)V"), remap = false)
private void onlyRefreshOnMainThread(ModelDataManager instance, ChunkPos pos) {
// Only refresh model data on the main thread. This prevents calling getBlockEntity from worker threads
// which could cause weird CMEs or other behavior.
// Avoid the loop if no model data needs to be refreshed, to prevent unnecessary allocation.
if(Minecraft.getInstance().isSameThread() && !needModelDataRefresh.isEmpty()) {
// Refresh the given chunk, and all its neighbors. This is less efficient than the default code
// but we have no choice since we need to not do refreshing on workers, and blocks might
// try to access model data in neighboring chunks.
for(int x = -1; x <= 1; x++) {
for(int z = -1; z <= 1; z++) {
refreshAt(new ChunkPos(pos.x + x, pos.z + z));
}
}
}
}
}

View File

@ -1,14 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.bugfix.removed_dimensions;
import net.minecraft.world.level.storage.LevelStorageSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(LevelStorageSource.class)
public class LevelStorageSourceMixin {
@ModifyArg(method = "*", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/DataResult;getOrThrow(ZLjava/util/function/Consumer;)Ljava/lang/Object;", ordinal = 0), index = 0)
private static boolean alwaysAllowPartialDimensions(boolean flag) {
return true;
}
}

View File

@ -1,22 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.core;
import net.minecraft.network.Connection;
import net.minecraftforge.network.NetworkHooks;
import org.embeddedt.modernfix.forge.packet.NetworkUtils;
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.CallbackInfo;
@Mixin(NetworkHooks.class)
public abstract class NetworkHooksMixin {
@Shadow public static boolean isVanillaConnection(Connection manager) {
throw new AssertionError();
}
@Inject(method = "handleClientLoginSuccess", at = @At("RETURN"), remap = false)
private static void setVanillaGlobalFlag(Connection manager, CallbackInfo ci) {
NetworkUtils.isCurrentlyVanilla = isVanillaConnection(manager);
}
}

View File

@ -1,16 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.devenv;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(GameData.class)
public class GameDataMixin {
@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/registries/ForgeRegistry;dump(Lnet/minecraft/resources/ResourceLocation;)V", remap = false))
private static void noDump(ForgeRegistry<?> reg, ResourceLocation id) {
}
}

View File

@ -1,52 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.feature.registry_event_progress;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.StartupMessageManager;
import net.minecraftforge.fml.event.IModBusEvent;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegisterEvent;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.forge.util.AsyncLoadingScreen;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = GameData.class, remap = false)
@ClientOnlyMixin
public class GameDataMixin {
private static AsyncLoadingScreen mfix$asyncScreen;
@Inject(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Ljava/util/Set;iterator()Ljava/util/Iterator;", ordinal = 0))
private static void createAsyncScreen(CallbackInfo ci) {
mfix$asyncScreen = new AsyncLoadingScreen();
}
@Inject(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Ljava/lang/RuntimeException;getSuppressed()[Ljava/lang/Throwable;", ordinal = 0))
private static void closeAsyncScreen(CallbackInfo ci) {
mfix$asyncScreen.close();
mfix$asyncScreen = null;
}
@Redirect(method = "postRegisterEvents", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/ModLoader;postEventWrapContainerInModOrder(Lnet/minecraftforge/eventbus/api/Event;)V"))
private static <T extends Event & IModBusEvent> void swapThreadAndPost(ModLoader loader, T event) {
RegisterEvent registryEvent = (RegisterEvent)event;
var pb = StartupMessageManager.addProgressBar(registryEvent.getRegistryKey().location().toString(), ModList.get().size());
try {
loader.postEventWithWrapInModOrder(event, (mc, e) -> {
ModLoadingContext.get().setActiveContainer(mc);
pb.label(pb.name() + " - " + mc.getModInfo().getDisplayName());
pb.increment();
}, (mc, e) -> {
ModLoadingContext.get().setActiveContainer(null);
});
} finally {
pb.complete();
}
}
}

View File

@ -1,43 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.fast_forge_dummies;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
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.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(targets = { "net/minecraftforge/registries/NamespacedWrapper" })
public abstract class NamespacedHolderHelperMixin<T> extends MappedRegistry<T> {
@Shadow(remap = false) private Map<ResourceLocation, Holder.Reference<T>> holdersByName;
public NamespacedHolderHelperMixin(ResourceKey<? extends Registry<T>> arg, Lifecycle lifecycle) {
super(arg, lifecycle);
}
@Inject(method = "freeze", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraftforge/registries/NamespacedWrapper;holdersByName:Ljava/util/Map;", remap = false), cancellable = true)
private void fastDummyCheck(CallbackInfoReturnable<Registry<T>> cir) {
// Quickly iterate without making any streams, etc. to see if everything is fine
// Use the slow path (by returning without cancelling) when there is an error
for(Holder.Reference<T> ref : this.holdersByName.values()) {
if(!ref.isBound())
return;
}
if (this.unregisteredIntrusiveHolders != null) {
for(Holder.Reference<T> ref : this.unregisteredIntrusiveHolders.values()) {
if(ref.getType() == Holder.Reference.Type.INTRUSIVE && !ref.isBound())
return;
}
}
// Skip the creation of streams
cir.setReturnValue(this);
}
}

View File

@ -1,55 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.fast_registry_validation;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.minecraftforge.registries.ForgeRegistry;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.lang.reflect.Method;
import java.util.*;
@Mixin(value = ForgeRegistry.class, remap = false)
public class ForgeRegistryMixin<V> {
private static Method bitSetTrimMethod = null;
private static boolean bitSetTrimMethodRetrieved = false;
/**
* Cache the result of findMethod instead of running it multiple times.
* Null checks are not required as the surrounding code handles it already.
*/
@Redirect(method = "validateContent", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/fml/util/ObfuscationReflectionHelper;findMethod(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"), require = 0)
private Method skipMultipleRemap(Class<?> clz, String methodName, Class<?>[] params) {
if(!bitSetTrimMethodRetrieved) {
bitSetTrimMethodRetrieved = true;
bitSetTrimMethod = ObfuscationReflectionHelper.findMethod(clz, methodName, params);
}
return bitSetTrimMethod;
}
private int expectedNextBit = -1;
/**
* Avoid calling nextClearBit and scanning the whole registry for every block registration.
*/
@Redirect(method = "add(ILnet/minecraft/resources/ResourceLocation;Ljava/lang/Object;Ljava/lang/String;)I", at = @At(value = "INVOKE", target = "Ljava/util/BitSet;nextClearBit(I)I"))
private int useCachedBit(BitSet availabilityMap, int minimum) {
int bit = availabilityMap.nextClearBit(expectedNextBit != -1 ? expectedNextBit : minimum);
expectedNextBit = bit + 1;
return bit;
}
@Inject(method = { "sync", "clear", "block" }, at = @At("HEAD"))
private void clearBitCache(CallbackInfo ci) {
expectedNextBit = -1;
}
@Redirect(method = "add(ILnet/minecraft/resources/ResourceLocation;Ljava/lang/Object;Ljava/lang/String;)I", at = @At(value = "INVOKE", target = "Lorg/apache/logging/log4j/Logger;trace(Lorg/apache/logging/log4j/Marker;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V"))
private void skipTrace(Logger logger, Marker marker, String s, Object o, Object o1, Object o2, Object o3, Object o4) {
}
}

View File

@ -1,24 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.forge_cap_retrieval;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.LivingEntity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import javax.annotation.Nullable;
@Mixin(LivingEntity.class)
public class LivingEntityMixin {
/**
* @author embeddedt (issue noted by XFactHD)
* @reason check capability equality before checking that entity is alive, the latter requires a lot more
* indirection
*/
@Redirect(method = "getCapability", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isAlive()Z"))
private <T> boolean checkAliveAfterCap(LivingEntity entity, Capability<T> capability, @Nullable Direction facing) {
return capability == ForgeCapabilities.ITEM_HANDLER && entity.isAlive();
}
}

View File

@ -1,30 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.forge_registry_alloc;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import org.embeddedt.modernfix.forge.registry.DelegateHolder;
import org.spongepowered.asm.mixin.Mixin;
@Mixin({Block.class, Item.class})
public class DelegateHolderMixin<T> implements DelegateHolder<T> {
private Holder.Reference<T> mfix$delegate;
private ResourceKey<Registry<T>> mfix$key;
@Override
public Holder.Reference<T> mfix$getDelegate(ResourceKey<Registry<T>> registryKey) {
if(mfix$key == registryKey) {
return mfix$delegate;
} else {
return null;
}
}
@Override
public void mfix$setDelegate(ResourceKey<Registry<T>> registryKey, Holder.Reference<T> holder) {
this.mfix$delegate = holder;
this.mfix$key = registryKey;
}
}

View File

@ -1,99 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.forge_registry_alloc;
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
import org.embeddedt.modernfix.forge.registry.DelegateHolder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
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.Locale;
import java.util.Map;
@Mixin(value = ForgeRegistry.class, remap = false)
public abstract class ForgeRegistryMixin<V> {
// Replace the backing maps with fastutil maps for a bit more speed, since value->holder lookups in particular
// are a bottleneck in many areas (e.g. render type lookup)
@Shadow @Final private Map<ResourceLocation, Holder.Reference<V>> delegatesByName = new Object2ObjectOpenHashMap<>();
@Shadow @Final private Map<V, Holder.Reference<V>> delegatesByValue = new Object2ObjectOpenHashMap<>(Hash.DEFAULT_INITIAL_SIZE, 0.5F);
@Shadow public abstract ResourceKey<Registry<V>> getRegistryKey();
@Shadow @Final private RegistryManager stage;
/**
* @author embeddedt
* @reason stop allocating so many unneeded objects. stop.
*/
@Overwrite
public Holder.Reference<V> getDelegateOrThrow(ResourceLocation location) {
Holder.Reference<V> holder = delegatesByName.get(location);
if (holder == null) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for location %s", location));
}
return holder;
}
/**
* @author embeddedt
* @reason see above
*/
@Overwrite
public Holder.Reference<V> getDelegateOrThrow(ResourceKey<V> rkey) {
Holder.Reference<V> holder = delegatesByName.get(rkey.location());
if (holder == null) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for key %s", rkey));
}
return holder;
}
/**
* @author embeddedt
* @reason store delegates that are accessed extremely regularly on the registry entry itself, rather than
* going through a map lookup
*/
@Inject(method = "bindDelegate", at = @At("RETURN"))
private void attachDelegate(ResourceKey<V> rkey, V value, CallbackInfoReturnable<Holder.Reference<V>> cir) {
// Only attach delegates for the ACTIVE registry. The Forge registry system is weird and seems to keep multiple
// copies of itself at once.
if(this.stage == RegistryManager.ACTIVE && value instanceof DelegateHolder<?>) {
((DelegateHolder<V>)value).mfix$setDelegate(this.getRegistryKey(), cir.getReturnValue());
}
}
/**
* @author embeddedt
* @reason skip map lookup for hot delegates, avoid allocations otherwise
*/
@Overwrite
public Holder.Reference<V> getDelegateOrThrow(V value) {
Holder.Reference<V> holder = null;
if (this.stage == RegistryManager.ACTIVE && value instanceof DelegateHolder<?>) {
holder = ((DelegateHolder<V>)value).mfix$getDelegate(this.getRegistryKey());
}
if (holder == null) {
holder = delegatesByValue.get(value);
if (holder == null) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No delegate exists for value %s", value));
}
}
return holder;
}
}

View File

@ -1,29 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.forge_registry_lambda;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.registries.RegistryObject;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(value = RegistryObject.class, remap = false)
public class RegistryObjectMixin<T> {
@Shadow private @Nullable T value;
@Shadow @Final private ResourceLocation name;
/**
* @author embeddedt
* @reason avoid lambda allocation on every call
*/
@Overwrite
public T get() {
T ret = this.value;
if(ret == null) {
throw new NullPointerException("Registry Object not present: " + this.name);
}
return ret;
}
}

View File

@ -1,25 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.potential_spawns_alloc;
import net.minecraft.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraftforge.event.ForgeEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.List;
@Mixin(ForgeEventFactory.class)
public class ForgeEventFactoryMixin {
@Redirect(method = "getPotentialSpawns", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/random/WeightedRandomList;create(Ljava/util/List;)Lnet/minecraft/util/random/WeightedRandomList;"))
private static WeightedRandomList<MobSpawnSettings.SpawnerData> reuseOldList(List<MobSpawnSettings.SpawnerData> items, LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList) {
// Our patched version of PotentialSpawns will return the same list as unwrap() if no one mutated the list
if(items == oldList.unwrap()) {
return oldList;
}
return WeightedRandomList.create(items);
}
}

View File

@ -1,68 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.potential_spawns_alloc;
import net.minecraft.core.BlockPos;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraftforge.event.level.LevelEvent;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Mixin(LevelEvent.PotentialSpawns.class)
public class PotentialSpawnsMixin {
@Shadow(remap = false) @Final @Mutable private List<MobSpawnSettings.SpawnerData> view;
@Shadow(remap = false) @Final @Mutable private List<MobSpawnSettings.SpawnerData> list;
private static final ArrayList<MobSpawnSettings.SpawnerData> SENTINEL = new ArrayList<>();
@Redirect(method = "<init>", at = @At(value = "NEW", target = "java/util/ArrayList", ordinal = 1))
private ArrayList<?> avoidListAlloc1() {
return SENTINEL;
}
@Redirect(method = "<init>", at = @At(value = "NEW", target = "java/util/ArrayList", ordinal = 0))
private ArrayList<?> avoidListAlloc2(Collection c) {
return SENTINEL;
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Collections;unmodifiableList(Ljava/util/List;)Ljava/util/List;"))
private List<?> avoidListAlloc3(List<?> l) {
return null;
}
@Inject(method = "<init>", at = @At("RETURN"))
private void initializeSmartLists(LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList, CallbackInfo ci) {
this.view = oldList.unwrap();
this.list = null;
}
private void mfix$populateList() {
if(this.list == null) {
this.list = new ArrayList<>(this.view);
this.view = Collections.unmodifiableList(this.list);
}
}
@Inject(method = {"addSpawnerData" }, at = @At("HEAD"), remap = false)
private void populateList(MobSpawnSettings.SpawnerData data, CallbackInfo ci) {
mfix$populateList();
}
@Inject(method = {"removeSpawnerData" }, at = @At("HEAD"), remap = false)
private void populateList(MobSpawnSettings.SpawnerData data, CallbackInfoReturnable<Boolean> cir) {
mfix$populateList();
}
}

View File

@ -1,25 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.registries.IForgeRegistryInternal;
import net.minecraftforge.registries.RegistryManager;
import org.embeddedt.modernfix.blockstate.BlockStateCacheHandler;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = { "net/minecraftforge/registries/GameData$BlockCallbacks" })
public class BlockCallbacksMixin {
@Redirect(method = "onBake", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;initCache()V"))
private void skipCache(BlockState instance) {
}
@Inject(method = "onBake", at = @At(value = "TAIL"), remap = false)
private void computeCaches(IForgeRegistryInternal<Block> owner, RegistryManager stage, CallbackInfo ci) {
BlockStateCacheHandler.rebuildParallel(false);
}
}

View File

@ -1,47 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.reduce_blockstate_cache_rebuilds;
import com.google.common.collect.Multimap;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import org.embeddedt.modernfix.util.BakeReason;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Map;
@Mixin(GameData.class)
public class GameDataMixin {
@Inject(method = "freezeData", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1), remap = false)
private static void markFreezeBakeReason(CallbackInfo ci) {
BakeReason.setCurrentBakeReason(BakeReason.FREEZE);
}
@Inject(method = "freezeData", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/registries/GameData;fireRemapEvent(Ljava/util/Map;Z)V"), remap = false)
private static void markEmptyBakeReason1(CallbackInfo ci) {
BakeReason.setCurrentBakeReason(null);
}
@Inject(method = "revertTo", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1), remap = false)
private static void markRevertBakeReason(CallbackInfo ci) {
BakeReason.setCurrentBakeReason(BakeReason.REVERT);
}
@Inject(method = "revertTo", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;forEach(Ljava/util/function/BiConsumer;)V", ordinal = 1, shift = At.Shift.AFTER), remap = false)
private static void markEmptyBakeReason2(CallbackInfo ci) {
BakeReason.setCurrentBakeReason(null);
}
@Inject(method = "injectSnapshot", at = @At("HEAD"), remap = false)
private static void markSnapshotInjectBakeReason(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld, CallbackInfoReturnable<Multimap<ResourceLocation, ResourceLocation>> cir) {
BakeReason.setCurrentBakeReason(isLocalWorld ? BakeReason.LOCAL_SNAPSHOT_INJECT : BakeReason.REMOTE_SNAPSHOT_INJECT);
}
@Inject(method = "injectSnapshot", at = @At("RETURN"), remap = false)
private static void markEmptyBakeReason2(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld, CallbackInfoReturnable<Multimap<ResourceLocation, ResourceLocation>> cir) {
BakeReason.setCurrentBakeReason(null);
}
}

View File

@ -1,114 +0,0 @@
package org.embeddedt.modernfix.forge.mixin.perf.resourcepacks;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraftforge.forgespi.locating.IModFile;
import net.minecraftforge.resource.PathPackResources;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.forge.load.ModResourcePackPathFixer;
import org.embeddedt.modernfix.resources.ICachingResourcePack;
import org.embeddedt.modernfix.resources.NewResourcePackAdapter;
import org.embeddedt.modernfix.resources.PackResourcesCacheEngine;
import org.embeddedt.modernfix.util.PackTypeHelper;
import org.jetbrains.annotations.NotNull;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
@Mixin(value = PathPackResources.class, priority = 1100)
public abstract class ForgePathPackResourcesMixin implements ICachingResourcePack {
@Shadow(remap = false) protected abstract Path resolve(String... paths);
@Shadow(remap = false) @NotNull
protected abstract Set<String> getNamespacesFromDisk(PackType type);
@Shadow(remap = false) private static String[] getPathFromLocation(PackType type, ResourceLocation location) {
throw new AssertionError();
}
private PackResourcesCacheEngine cacheEngine;
private IModFile mfix$resolveFileOverride;
@Inject(method = "<init>", at = @At("TAIL"))
private void cacheResources(String packId, boolean isBuiltin, final Path source, CallbackInfo ci) {
// handle buggy mods instantiating at the root path, but only if they didn't override at all
// (otherwise they may have handled resolve() already)
if(((Object)this).getClass() == PathPackResources.class)
this.mfix$resolveFileOverride = ModResourcePackPathFixer.getModFileByRootPath(source);
if(this.mfix$resolveFileOverride != null)
ModernFix.LOGGER.warn("PathResourcePack base class instantiated with root path of mod file {}. This probably means a mod should be calling ResourcePackLoader.createPackForMod instead. Applying workaround.", mfix$resolveFileOverride.getFileName());
invalidateCache();
PackResourcesCacheEngine.track(this);
}
@Inject(method = "resolve", at = @At("HEAD"), cancellable = true, remap = false)
private void resolveViaModFile(String[] paths, CallbackInfoReturnable<Path> cir) {
if(this.mfix$resolveFileOverride != null)
cir.setReturnValue(this.mfix$resolveFileOverride.findResource(paths));
}
private PackResourcesCacheEngine generateResourceCache() {
synchronized (this) {
PackResourcesCacheEngine engine = this.cacheEngine;
if(engine != null)
return engine;
this.cacheEngine = engine = new PackResourcesCacheEngine(this::getNamespacesFromDisk, (type, namespace) -> this.resolve(type.getDirectory(), namespace));
return engine;
}
}
@Override
public void invalidateCache() {
this.cacheEngine = null;
}
@Redirect(method = "getNamespaces", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/resource/PathPackResources;getNamespacesFromDisk(Lnet/minecraft/server/packs/PackType;)Ljava/util/Set;"))
private Set<String> useCacheForNamespaces(PathPackResources instance, PackType type) {
PackResourcesCacheEngine engine = cacheEngine;
if(engine != null) {
Set<String> namespaces = engine.getNamespaces(type);
if(namespaces != null)
return namespaces;
}
return this.getNamespacesFromDisk(type);
}
@Redirect(method = "getRootResource", at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;exists(Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z"))
private boolean useCacheForExistence(Path path, LinkOption[] options, String[] originalPaths) {
// the cache only stores things with a namespace and pack type
if(originalPaths.length < 3 || (!Objects.equals(originalPaths[0], "assets") && !Objects.equals(originalPaths[0], "data")))
return Files.exists(path, options);
else
return this.generateResourceCache().hasResource(originalPaths);
}
/**
* @author embeddedt
* @reason Use cached listing of mod resources
*/
@Inject(method = "listResources", at = @At("HEAD"), cancellable = true)
private void fastGetResources(PackType type, String namespace, String path, PackResources.ResourceOutput resourceOutput, CallbackInfo ci)
{
if(!PackTypeHelper.isVanillaPackType(type))
return;
ci.cancel();
Collection<ResourceLocation> allPossibleResources = this.generateResourceCache().getResources(type, namespace, path, Integer.MAX_VALUE, p -> true);
NewResourcePackAdapter.sendToOutput(location -> {
Path target = resolve(getPathFromLocation(location.getPath().startsWith("lang/") ? PackType.CLIENT_RESOURCES : type, location));
return () -> Files.newInputStream(target);
}, resourceOutput, allPossibleResources);
}
}

View File

@ -1,5 +0,0 @@
package org.embeddedt.modernfix.forge.packet;
public class NetworkUtils {
public static boolean isCurrentlyVanilla;
}

View File

@ -1,35 +0,0 @@
package org.embeddedt.modernfix.forge.packet;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
import java.util.function.Supplier;
public class PacketHandler {
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(ModernFix.MODID, "main"),
() -> PROTOCOL_VERSION,
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION),
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION)
);
public static void register() {
int id = 1;
INSTANCE.registerMessage(id++, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, PacketHandler::handleSyncPacket);
}
private static void handleSyncPacket(EntityIDSyncPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
contextSupplier.get().enqueueWork(() -> ModernFixClient.handleEntityIDSync(packet));
contextSupplier.get().setPacketHandled(true);
});
}
}

View File

@ -1,10 +0,0 @@
package org.embeddedt.modernfix.forge.registry;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
public interface DelegateHolder<T> {
Holder.Reference<T> mfix$getDelegate(ResourceKey<Registry<T>> registryKey);
void mfix$setDelegate(ResourceKey<Registry<T>> registryKey, Holder.Reference<T> holder);
}

View File

@ -1,46 +0,0 @@
package org.embeddedt.modernfix.forge.registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.minecraftforge.registries.ObjectHolderRegistry;
import org.embeddedt.modernfix.ModernFix;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class ObjectHolderClearer {
/**
* Many of the built-in Forge holders needlessly hold on to an exception.
*/
public static void clearThrowables() {
Set<Consumer<Predicate<ResourceLocation>>> holders = ObfuscationReflectionHelper.getPrivateValue(ObjectHolderRegistry.class, null, "objectHolders");
if(holders != null) {
int numCleared = 0;
HashMap<Class<?>, Field> throwableField = new HashMap<>();
Throwable singletonThrowable = new Throwable("[This stacktrace was cleared to save memory]");
try {
for(Consumer<Predicate<ResourceLocation>> holder : holders) {
Field target = throwableField.computeIfAbsent(holder.getClass(), clz -> {
Field[] clzFields = clz.getDeclaredFields();
for(Field f : clzFields) {
if(Throwable.class.isAssignableFrom(f.getType())) {
f.setAccessible(true);
return f;
}
}
return null;
});
if(target != null) {
target.set(holder, singletonThrowable);
numCleared++;
}
}
} catch(RuntimeException | ReflectiveOperationException | NoClassDefFoundError ignored) {
}
ModernFix.LOGGER.debug("Cleared " + numCleared + " object holder stacktrace references");
}
}
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.forge.rs;
import net.minecraftforge.fluids.capability.IFluidHandler;
public interface IFluidExternalStorageCache {
boolean initCache(IFluidHandler handler);
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.forge.rs;
import net.minecraftforge.items.IItemHandler;
public interface IItemExternalStorageCache {
boolean initCache(IItemHandler handler);
}

View File

@ -1,66 +0,0 @@
package org.embeddedt.modernfix.forge.util;
import net.minecraftforge.eventbus.EventBus;
import net.minecraftforge.eventbus.api.EventListenerHelper;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import org.embeddedt.modernfix.ModernFix;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.function.Supplier;
public class ModUtil {
private static final Set<Class<?>> erroredContexts = new HashSet<>();
private static boolean busListensToEvent(EventBus bus, Class<?> eventClazz) {
try {
int busID = ObfuscationReflectionHelper.getPrivateValue(EventBus.class, bus, "busID");
return EventListenerHelper.getListenerList(eventClazz).getListeners(busID).length > 0;
} catch(Exception e) {
ModernFix.LOGGER.error(e);
return false;
}
}
public static Collection<String> findAllModsListeningToEvent(Class<?> eventClazz) {
Set<String> modsListening = new HashSet<>();
ModList.get().forEachModContainer((modId, container) -> {
Supplier<?> languageExtensionSupplier = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, container, "contextExtension");
Object context = languageExtensionSupplier.get();
if(context == null)
return;
if(context instanceof FMLJavaModLoadingContext) {
if(busListensToEvent((EventBus)((FMLJavaModLoadingContext) context).getModEventBus(), eventClazz)) {
modsListening.add(modId);
}
} else {
synchronized(erroredContexts) {
if(!erroredContexts.contains(context.getClass())) {
ModernFix.LOGGER.warn("Unknown modloading context: " + context.getClass().getName());
erroredContexts.add(context.getClass());
}
}
}
});
return modsListening;
}
private static final ClassLoader targetClassLoader = Thread.currentThread().getContextClassLoader();
private static class ModernFixForkJoinWorkerThread extends ForkJoinWorkerThread {
ModernFixForkJoinWorkerThread(ForkJoinPool pool) {
super(pool);
/* Ensure that the context class loader is set correctly */
this.setContextClassLoader(targetClassLoader);
}
}
public static ForkJoinPool commonPool = new ForkJoinPool(
ForkJoinPool.getCommonPoolParallelism(),
ModernFixForkJoinWorkerThread::new,
null,
false
);
}

View File

@ -5,29 +5,29 @@ junit_version=5.10.0-M1
mixinextras_version=0.3.2
mod_id=modernfix
minecraft_version=1.20.1
enabled_platforms=fabric,forge
forge_version=1.20.1-47.1.3
parchment_version=2023.07.09
minecraft_version=1.20.6
enabled_platforms=fabric,neoforge
forge_version=20.6.100-beta
# parchment_version=2023.07.09
refined_storage_version=4392788
jei_version=13.1.0.2
rei_version=11.0.597
jei_version=16.0.0.28
rei_version=13.0.678
ctm_version=1.20.1-1.1.8+4
kubejs_version=1902.6.0-build.142
rhino_version=1902.2.2-build.268
supported_minecraft_versions=1.20.1
supported_minecraft_versions=1.20.6
fabric_loader_version=0.14.25
fabric_api_version=0.86.0+1.20.1
fabric_loader_version=0.15.9
fabric_api_version=0.97.8+1.20.6
continuity_version=3.0.0-beta.2+1.19.3
continuity_version=3.0.0-beta.4+1.20.2
modmenu_version=7.0.0-beta.2
diagonal_fences_version=4558828
spark_version=4587310
use_fabric_api_at_runtime=true
use_fabric_api_at_runtime=false
# Look up maven coordinates when changing shadow_version
shadow_version=7.1.2

View File

@ -6,17 +6,7 @@ plugins {
architectury {
platformSetupLoomIde()
forge()
}
loom {
forge {
convertAccessWideners = true
extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
mixinConfig "modernfix-common.mixins.json"
mixinConfig "modernfix-forge.mixins.json"
}
neoForge()
}
configurations {
@ -40,12 +30,12 @@ repositories {
includeGroup "extra-mods"
}
}
maven { url "https://maven.neoforged.net" }
}
dependencies {
forge "net.minecraftforge:forge:${rootProject.forge_version}"
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}"))
implementation(include("io.github.llamalad7:mixinextras-forge:${rootProject.mixinextras_version}"))
neoForge "net.neoforged:neoforge:${rootProject.forge_version}"
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury-forge:${rootProject.architectury_version}"
@ -55,7 +45,7 @@ dependencies {
modCompileOnly("me.shedaniel:RoughlyEnoughItems-forge:${rei_version}") { transitive false }
modCompileOnly("dev.latvian.mods:kubejs-forge:${kubejs_version}")
//modRuntimeOnly("curse.maven:ferritecore-429235:4441949")
modCompileOnly("team.chisel.ctm:CTM:${ctm_version}")
modCompileOnly files("deps/ctm.jar")
modCompileOnly("curse.maven:supermartijncore-454372:4455391")
modCompileOnly("vazkii.patchouli:Patchouli:1.19.2-77")
@ -71,7 +61,7 @@ dependencies {
}
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
shadowCommon(project(path: ":common", configuration: "transformProductionNeoForge")) { transitive = false }
shadowCommon(project(path: ":annotations"))
forgeRuntimeLibrary(project(path: ":annotations"))
}
@ -79,7 +69,7 @@ dependencies {
processResources {
inputs.property "version", project.version
filesMatching("META-INF/mods.toml") {
filesMatching("META-INF/neoforge.mods.toml") {
expand "version": project.version
}
}
@ -96,6 +86,7 @@ remapJar {
input.set shadowJar.archiveFile
dependsOn shadowJar
archiveClassifier.set(null)
atAccessWideners.add "modernfix.accesswidener"
}
jar {

BIN
neoforge/deps/ctm.jar Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
loom.platform=neoforge

View File

@ -1,8 +1,8 @@
package org.embeddedt.modernfix.forge;
package org.embeddedt.modernfix.neoforge;
import com.google.common.collect.ImmutableList;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.ForgeConfigSpec;
import net.neoforged.neoforge.common.ModConfigSpec;
import java.util.List;
import java.util.Set;
@ -10,10 +10,10 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
public class ModernFixConfig {
private static final ForgeConfigSpec.Builder COMMON_BUILDER = new ForgeConfigSpec.Builder();
public static ForgeConfigSpec COMMON_CONFIG;
private static final ModConfigSpec.Builder COMMON_BUILDER = new ModConfigSpec.Builder();
public static ModConfigSpec COMMON_CONFIG;
public static ForgeConfigSpec.ConfigValue<List<? extends String>> BLACKLIST_ASYNC_JEI_PLUGINS;
public static ModConfigSpec.ConfigValue<List<? extends String>> BLACKLIST_ASYNC_JEI_PLUGINS;
private static Set<ResourceLocation> jeiPluginBlacklist;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.forge.classloading;
package org.embeddedt.modernfix.neoforge.classloading;
/**
* Sometimes mods have classes that circularly reference each other. If each of these classes ends up being loaded

View File

@ -1,10 +1,10 @@
package org.embeddedt.modernfix.forge.classloading;
package org.embeddedt.modernfix.neoforge.classloading;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.forgespi.language.ModFileScanData;
import net.minecraftforge.forgespi.locating.IModFile;
import net.neoforged.fml.ModList;
import net.neoforged.neoforgespi.language.ModFileScanData;
import net.neoforged.neoforgespi.locating.IModFile;
import org.objectweb.asm.Type;
import java.lang.reflect.Field;

View File

@ -1,9 +1,9 @@
package org.embeddedt.modernfix.forge.config;
package org.embeddedt.modernfix.neoforge.config;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.config.IConfigEvent;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;

View File

@ -1,9 +1,9 @@
package org.embeddedt.modernfix.forge.config;
package org.embeddedt.modernfix.neoforge.config;
import com.electronwill.nightconfig.core.file.FileWatcher;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import cpw.mods.modlauncher.api.LambdaExceptionUtils;
import net.neoforged.fml.loading.FMLLoader;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.util.CommonModUtil;
@ -51,7 +51,7 @@ public class NightConfigFixer {
}
static class MonitoringMap extends ConcurrentHashMap<Path, Object> {
private static final Class<?> WATCHED_FILE = LamdbaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile"));
private static final Class<?> WATCHED_FILE = LambdaExceptionUtils.uncheck(() -> Class.forName("com.electronwill.nightconfig.core.file.FileWatcher$WatchedFile"));
private static final Field CHANGE_HANDLER = ObfuscationReflectionHelper.findField(WATCHED_FILE, "changeHandler");
public MonitoringMap(ConcurrentHashMap<Path, ?> oldMap) {

View File

@ -1,9 +1,9 @@
package org.embeddedt.modernfix.forge.config;
package org.embeddedt.modernfix.neoforge.config;
import com.electronwill.nightconfig.core.file.FileWatcher;
import com.google.common.collect.ForwardingCollection;
import com.google.common.collect.ForwardingMap;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import java.util.Collection;
import java.util.Iterator;

View File

@ -1,4 +1,4 @@
package org.embeddedt.modernfix.forge.datagen;
package org.embeddedt.modernfix.neoforge.datagen;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
@ -10,15 +10,15 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.data.loading.DatagenModLoader;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModLoader;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.util.ObfuscationReflectionHelper;
import net.neoforged.neoforge.client.event.ScreenEvent;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.data.event.GatherDataEvent;
import net.neoforged.neoforge.data.loading.DatagenModLoader;
import org.embeddedt.modernfix.ModernFix;
import java.nio.file.Path;
@ -27,7 +27,7 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Mod.EventBusSubscriber(value = Dist.CLIENT)
@EventBusSubscriber(value = Dist.CLIENT)
public class RuntimeDatagen {
private static final String RESOURCES_OUT_DIR = getPropertyOrBlank("modernfix.datagen.output");
private static final String RESOURCES_IN_DIR = getPropertyOrBlank("modernfix.datagen.existing");
@ -67,7 +67,7 @@ public class RuntimeDatagen {
List<PackResources> oldPacks = new ArrayList<>(manager.listPacks().collect(Collectors.toList()));
oldPacks.add(Minecraft.getInstance().getVanillaPackResources());
ObfuscationReflectionHelper.setPrivateValue(ExistingFileHelper.class, existingFileHelper, new MultiPackResourceManager(PackType.CLIENT_RESOURCES, oldPacks), "clientResources");
ModLoader.get().runEventGenerator(mc->new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
ModLoader.runEventGenerator(mc->new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
dataGeneratorConfig.runAll();
ObfuscationReflectionHelper.setPrivateValue(DatagenModLoader.class, null, false, "runningDataGen");
ModernFix.LOGGER.info("Finished runtime datagen.");

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