Compare commits

..

821 Commits

Author SHA1 Message Date
embeddedt
292a6aeab3
Fix optimize_surface_rules breaking mods that provide custom BiomeManagers 2026-06-11 20:01:31 -04:00
embeddedt
7fbfcf1a92
Remove error when missing_block_entities sees null BE
Blocks may legitimately not have a block entity for some states
2026-06-07 21:50:44 -04:00
embeddedt
1bcb28a1ad
Allow feature level requirement to be set at package level 2026-06-07 19:43:28 -04:00
embeddedt
d51b0f60a2
Fix an instance of vanilla leaking a BufferBuilder 2026-06-07 19:19:25 -04:00
embeddedt
ab9880159e
Add experimental KubeJS memory usage optimization 2026-06-06 21:17:34 -04:00
embeddedt
0f94634361
Remove the item stack reference thread 2026-06-06 21:04:09 -04:00
embeddedt
f1492cc829
Allow ZipPackIndex to work with any byte channel 2026-06-04 20:57:13 -04:00
embeddedt
0ecee529d7
Fix Forge calling getResource on every loot table unnecessarily 2026-06-03 18:05:56 -04:00
embeddedt
e9bfd96dd9
Fix Forge pack finder being injected multiple times into pack repository 2026-05-28 22:33:03 -04:00
embeddedt
fb9dcf77c6
Improve ZipPackIndex 2026-05-28 22:20:28 -04:00
embeddedt
33851c1cb6
Fix ImposterProtoChunk leaking live block entities to worldgen 2026-05-24 23:09:52 -04:00
embeddedt
494203ef5a
Fix potential crash during worldgen with release_protochunks enabled
The crash can occur if a protochunk next to a FULL chunk is dropped,
and then later re-requested. If it was not persisted to disk for any
reason, it starts regeneration from scratch. At FEATURES stage, it may
try to place blocks into the adjacent LevelChunk already in the world.

The fix is to prevent this situation from even happening by pinning
protochunks directly next to FULL chunks, and preventing them from
unloading.
2026-05-24 19:45:24 -04:00
embeddedt
74f76f7305
Improvements to ZipPackIndex
- Allow it to work on channels that don't support mapping
- Skip indexing folders that are not part of a pack type
2026-05-23 21:44:14 -04:00
embeddedt
62dbbea083
Optimize ZIP resource packs significantly 2026-05-23 21:28:19 -04:00
embeddedt
538c52bc2a
Run stronghold gen on dedicated thread pool 2026-05-23 17:00:08 -04:00
embeddedt
b62eb1845b
Avoid blocking chunk generation on concentric rings calculation where possible 2026-05-23 16:43:56 -04:00
embeddedt
7c45564979
Fix potential stronghold cache corruption if player exits world too quickly 2026-05-23 16:32:56 -04:00
embeddedt
f8d2425242
Improve accuracy of possible biomes check 2026-05-23 12:50:48 -04:00
embeddedt
50cedfc699
Fix stability level being impossible to override 2026-05-23 12:50:33 -04:00
embeddedt
f4f596ca0c
Fix mixin failing at runtime due to missing AT 2026-05-23 12:50:21 -04:00
embeddedt
85aab426c5
Fix mixin AP complaints 2026-05-23 12:01:33 -04:00
embeddedt
29ff5f152e
Log the state of each mixin at DEBUG level 2026-05-23 11:58:36 -04:00
embeddedt
8213a720a3
Optimize TerraBlender using extended surface biome context
Supersedes TerraBlenderFix
2026-05-23 11:56:45 -04:00
embeddedt
afe3e09a27
Add feature level system for mixins 2026-05-23 11:51:11 -04:00
embeddedt
ae20fa17c9
Fix random CMEs from NightConfigWatchThrottler 2026-05-18 10:05:23 -04:00
embeddedt
a6c03e9928
Rewrite biome condition optimizer inspired by 26.2 changes
Thanks to https://codeberg.org/ZenXArch for making me aware of the
simpler vanilla approach to achieve the same thing
2026-05-16 13:59:01 -04:00
embeddedt
864c751aea
Remove stream in hot path of capability provider construction 2026-05-15 21:14:26 -04:00
embeddedt
f931d5c442
Fix isOptionEnabled being invoked in hot path during capability provider creation
Fixes #664
2026-05-15 21:04:40 -04:00
embeddedt
55cec86e5f
Disable mixin.perf.faster_ingredients with Prefab installed
Prefab relies on the nullity of `Ingredient.itemStacks` matching
vanilla, which is not true with this option enabled

aa5386c78b/Shared/src/com/prefab/recipe/ConditionedShapedRecipe.java (L166)

Fixes #660
2026-05-07 21:48:04 -04:00
embeddedt
4ec8ef753a
Fix scripts not detecting 26.1 branch 2026-05-06 18:19:17 -04:00
embeddedt
3f22e23565
Further optimize OptimizedBiomeLookupSequenceRule 2026-05-06 18:18:14 -04:00
embeddedt
a73dd5ef6a
Update bug report template 2026-05-05 20:27:55 -04:00
embeddedt
653a477060
Fix crash when mods use null attributes
Fixes #658
2026-05-05 20:23:06 -04:00
embeddedt
44113d2536
Improve efficiency of surface rule optimizer when rules are complex 2026-05-05 19:41:28 -04:00
embeddedt
1165d3bdd1
Fix Crash Assistant treating a mixin audit as a crash 2026-04-29 18:47:02 -04:00
embeddedt
c73cdc49a4
Replace CapabilityProvider mixin with ASM transformer
Works around this Mixin bug: https://github.com/FabricMC/Mixin/issues/146

Since CapabilityProvider is the parent of many commonly targeted classes
like Level, ItemStack, etc., this breaks mods

Fixes #650
2026-04-28 18:59:09 -04:00
embeddedt
4e3ecf9b6d
Disable mixin.perf.release_protochunks when Moonrise is present
Fixes #652
2026-04-27 19:52:08 -04:00
embeddedt
a40363c1fb
Improve issue comment workflow [skip ci] 2026-04-22 19:42:45 -04:00
embeddedt
46dd5ecddd
Comment on issues when fix is released
Fixes #649
2026-04-22 19:36:59 -04:00
embeddedt
b765bcb51f
Improve compatibility with mods that inject into ModelBaker.bake
Fixes #646
2026-04-22 19:27:07 -04:00
Mustafa
26bd7116a1
Change log level from warn to debug for successfully created missing block entities
Closes #648
2026-04-22 19:05:18 -04:00
Mustafa
4d2f0da1fc
Reduce log level of mixin.perf.spam_thread_dump to info
Closes #647
2026-04-22 18:48:47 -04:00
embeddedt
c2f585da95
Fix rare crash from HandshakeHandler in 5.27.0+
The existing Forge logic can concurrently modify sentMessages from two threads,
since handleIndexedMessage runs on the Netty thread, while tickServer is on the
server thread. Ticking the handler faster made the race condition significantly
more likely to manifest.
2026-04-14 22:22:06 -04:00
Evoloxi
327c3cd9ff
Fall back to interfaces when resolving capability fields (#643) 2026-04-13 20:32:01 -04:00
embeddedt
c64ca2e54b
Fix potential crash with mods that inject custom surface building logic
Fixes #638
2026-04-12 16:36:44 -04:00
embeddedt
85955ebf75
Ensure integrated server is ticked at least once before player connects
Fixes #639
2026-04-12 16:02:54 -04:00
embeddedt
d749205427
Adjust dynamic_languages for better mod compatibility 2026-04-11 14:39:36 -04:00
embeddedt
438ceb1984
Move auditing to happen later in launch 2026-04-11 14:19:22 -04:00
embeddedt
5acb5115b9
Add mixin audit to CI 2026-04-11 14:14:53 -04:00
embeddedt
37dc9e60eb
Do not intern AttributeSuppliers after launch 2026-04-11 14:04:37 -04:00
embeddedt
c2191df359
Release 5.27.0 & enable continuous deployment 2026-04-10 21:07:34 -04:00
embeddedt
d08da1b3c8
Disable release_protochunks when C2ME is installed 2026-03-29 19:46:04 -04:00
embeddedt
36f425b8cd
Fix excessive recursion from mailbox 2026-03-28 22:07:59 -04:00
embeddedt
dc3c379049
Fix ChunkBiomeLookup leaking a worldgen region 2026-03-28 21:45:59 -04:00
embeddedt
4ff7d4c554
Allow a single low-priority worker thread when cause_lag_by_disabling_threads is enabled
On a system with few cores, we should still benefit from using one low-priority
background thread for worldgen, because it avoids the server thread stopping
to handle it itself. The thread will be blocked
from progressing while higher-priority work (e.g. rendering or server ticking)
is in progress.
2026-03-28 21:45:14 -04:00
embeddedt
db13f39b30
Implement dynamic language loading 2026-03-28 20:55:27 -04:00
embeddedt
5a9c49f8d4
Add option to reduce memory usage of entity models 2026-03-28 20:02:30 -04:00
embeddedt
8ee85f2c16
Remove duplicate list held by DebugLevelSource 2026-03-28 19:31:24 -04:00
embeddedt
2081b63b56
Fix looking up private static final Capability fields 2026-03-27 22:38:18 -04:00
embeddedt
94f1fbf4db
Rewrite AttachCapabilitiesEvent hoisting to not rely on phases 2026-03-27 21:18:38 -04:00
embeddedt
ab8a8068e0
Avoid synchronizing layer list in LivingEntityRenderer 2026-03-26 22:58:18 -04:00
embeddedt
79d2b28d5b
Fix Forge handshake taking extremely long time with many payloads 2026-03-19 21:25:37 -04:00
embeddedt
18dc488ab9
Avoid spinning in Minecraft.doWorldLoad 2026-03-19 20:36:07 -04:00
embeddedt
a9340b2642
Rewrite and improve mixin.perf.cache_strongholds 2026-03-19 20:11:11 -04:00
embeddedt
670e06816b
Reduce work done while waiting for singleplayer client to initiate connection 2026-03-16 22:15:44 -04:00
embeddedt
53349cbd1a
Remove skip_redundant_saves 2026-03-16 22:14:35 -04:00
embeddedt
1794c81b61
Optimize sequence rules that check many biome conditions in a row 2026-03-15 15:24:54 -04:00
embeddedt
dbe9acb3d8
Heavily optimize the BlockColumn impl used during surface rule evaluation 2026-03-14 22:05:36 -04:00
embeddedt
22915a91a1
Implement a significantly more optimized biome lookup for surface rules 2026-03-14 19:44:42 -04:00
embeddedt
1289897004
Add worldgen benchmarking harness 2026-03-14 18:46:32 -04:00
embeddedt
9692da12b4
Add idle timer to prevent chunks from suspending too quickly 2026-03-14 15:59:52 -04:00
embeddedt
e34a99b38c
Simplify chunk unload logic & fix events not being fired when INACCESSIBLE chunks are unloaded 2026-03-14 14:59:45 -04:00
embeddedt
f79eae8b83
Make integrated server treat game as paused while singleplayer client is still loading 2026-03-14 10:44:04 -04:00
embeddedt
38288d5e6a
Automatically free contents of ChunkHolders only used for worldgen when generation finishes 2026-03-13 22:26:51 -04:00
embeddedt
2050516bf1
Do not cache supported glyphs in lazy provider 2026-03-13 19:53:33 -04:00
embeddedt
02f486ebf4
Avoid loading multiple copies of a lazy glyph provider 2026-03-13 19:36:15 -04:00
embeddedt
9edce9ad91
Dynamically load/unload Unihex font data 2026-03-06 20:52:26 -05:00
embeddedt
ac8d93d5b9
Ensure exceptions thrown in chunk load events are not dropped 2026-03-06 09:00:28 -05:00
embeddedt
bee4536c1a
Tweak full chunk promotion to reduce opportunities for deadlocks 2026-03-05 21:09:33 -05:00
embeddedt
da2206168b
Port AP to Java 17 2026-03-04 19:18:01 -05:00
embeddedt
17f930ea6f
WIP chunk saving optimization 2026-03-04 18:41:28 -05:00
embeddedt
f23348c6cb
Clear unneeded ObjectHolderRefs 2026-03-01 19:28:52 -05:00
embeddedt
21cbcb0e04
Strip signatures from jar manifests at startup to save memory 2026-03-01 17:52:13 -05:00
embeddedt
925c7526ee
Reduce memory usage of ImposterProtoChunks 2026-03-01 15:46:52 -05:00
embeddedt
30e3deb8e2
Avoid unnecessary chunkloads when remove_spawn_chunks is enabled 2026-03-01 15:18:13 -05:00
embeddedt
ee34dcf96e
Drastically simplify and document chunk system memory usage patch 2026-02-28 16:42:42 -05:00
embeddedt
49d800ff27
Avoid calling LazyOptional.isPresent() if possible 2026-02-27 22:19:04 -05:00
embeddedt
15f30b532c
Reduce generated class size slightly 2026-02-27 21:30:35 -05:00
embeddedt
df06010846
Fix superclass capability types being ignored sometimes 2026-02-27 20:53:40 -05:00
embeddedt
696b344ef5
Fix missed detection of certain cap equality checks 2026-02-27 20:35:58 -05:00
embeddedt
e63d99763e
Avoid initializing lazy capability providers for compatibility checks where possible 2026-02-27 19:29:16 -05:00
embeddedt
60850610f9
Group capability providers of known types together when possible 2026-02-27 19:11:24 -05:00
embeddedt
e16179b797
Emit more debug info to the generated dispatcher classes 2026-02-27 19:08:06 -05:00
embeddedt
784b914a43
Optimize runs of ICapabilityProvider calls into hash lookups 2026-02-26 22:26:57 -05:00
embeddedt
b9933b1158
Add bytecode analysis to filter ICapabilityProvider impls where possible
Currently disabled by default till more testing is completed
2026-02-26 21:45:31 -05:00
embeddedt
878b3798f3
Detect mods causing CMEs with the client resource reload listener list
Related: #512
2026-02-05 21:10:39 -05:00
embeddedt
bc0e9a09fc
Prevent model locations added in RegisterAdditional from being early baked 2026-02-02 21:29:14 -05:00
embeddedt
8c34c0de50
Dump stats on permanently loaded baked models to debug log 2026-02-02 20:50:21 -05:00
embeddedt
5a93bc6109
Use identityHashCode for attribute 2026-01-25 21:31:06 -05:00
embeddedt
8125da7882
Avoid propagating unbaked model load errors to higher-level code
Related: #625
2026-01-25 21:28:23 -05:00
embeddedt
d699187006
Fix AttachCapabilitiesEvent dispatch being very slow
EventBus strikes again...
2026-01-25 20:38:18 -05:00
embeddedt
cff29149db
Intern map keys in BlockStateData 2026-01-25 19:41:29 -05:00
embeddedt
3926f27d33
Optimize memory usage of entity attribute templates 2026-01-25 19:27:27 -05:00
embeddedt
9bc5f06a19
Ensure correct order of properties in generated ModelResourceLocation variant strings
Related: https://github.com/malte0811/FerriteCore/issues/219
2026-01-24 10:41:23 -05:00
embeddedt
a70f76a34d
Document the reason for lack of optimization 2026-01-23 20:20:48 -05:00
embeddedt
4dcdf09a01
Do not convert ModFileScanData annotation values to immutable lists
Related: #627
2026-01-23 20:19:28 -05:00
embeddedt
f26d35070e
Remove changelog step from release workflow [skip ci] 2026-01-22 20:01:26 -05:00
embeddedt
a04266df54
Fix bugs in release process 2026-01-22 19:47:26 -05:00
embeddedt
2ec6a6afbc
Fix error running publishMods 2026-01-22 19:39:49 -05:00
embeddedt
49f5b527db
Add JVM argument to help prevent mass Spark profile uploads 2026-01-22 19:03:01 -05:00
embeddedt
00287612de
Reimplement publish task 2026-01-17 21:20:21 -05:00
embeddedt
4b18cc2cc6
Fix crash when user home/config folders are inaccessible 2026-01-09 21:05:49 -05:00
embeddedt
b2ed5b9341
Adjust mixin for CIT Reforged compatibility
Related: https://github.com/embeddedt/ModernFix/issues/624
2026-01-09 21:05:06 -05:00
embeddedt
a30dd08cd1
Optimize memory usage of ModFileScanData 2026-01-06 21:58:21 -05:00
embeddedt
7420a7c7ab
Dispatch getCapability calls using specialized ASM loop per provider types
Idea suggested by @eigenraven
2026-01-01 13:09:17 -05:00
embeddedt
3f9148fa62
Update to Gradle 9.2.1 2025-12-27 18:27:09 -05:00
embeddedt
8cc41fa222
Delete old Gradle files and resolve deprecation warning 2025-12-27 18:26:15 -05:00
embeddedt
f06fb8c32e
Fix several issues running production jar 2025-12-26 18:29:35 -05:00
embeddedt
6ee15122f9
Add jar copying tasks 2025-12-26 18:20:35 -05:00
embeddedt
c9843e08bd
Remove Loom cache [skip ci] 2025-12-26 18:16:41 -05:00
embeddedt
7b47c39e6b
Update scripts to use root folder 2025-12-26 18:15:21 -05:00
embeddedt
b26ab375b5
Merge common & forge projects, replace Arch Loom with MDG 2025-12-26 18:13:42 -05:00
embeddedt
9c4da7fa68
Remove Fabric subproject 2025-12-26 16:26:58 -05:00
embeddedt
d64a1c760b
Fix compile errors 2025-12-26 16:16:15 -05:00
embeddedt
555213714f
Delete more old code 2025-12-26 16:10:07 -05:00
embeddedt
7f27141a16
Remove more old code 2025-12-26 15:53:26 -05:00
embeddedt
a8227a964d
Remove deduplicate_climate_parameters, not worth the overhead
Also remove some other misc classes
2025-12-26 15:49:44 -05:00
embeddedt
a7a9aac23a
Begin cleaning up a large volume of code 2025-12-26 15:37:32 -05:00
embeddedt
1176cc98e3
Compact NBT used for Flattening world upgrades 2025-12-26 14:02:42 -05:00
embeddedt
a7622f58ae
Run formatter 2025-12-07 20:36:07 -05:00
embeddedt
67814db6ad
Mitigate dynres cache thrashing for blocks with more than 10,000 states
The previous implementation kept trying to load the models for all
states at once in this scenario, which would cause thrashing as
most of the loads would be thrown out. The new implementation
limits how many models it will load at a time, but still tries
to batch as much as possible
2025-12-07 20:26:42 -05:00
embeddedt
8959c2ff91
Remove dynamic_sounds
This option is unlikely to offer substantial memory savings,
especially when considering that sounds are located off-heap
(meaning the OS should be able to effectively swap out the
unreferenced sound pages to disk). It does not seem worth
the effort to hack this into a game not designed for sounds
to unload at runtime.
2025-11-08 11:49:58 -05:00
embeddedt
a6eb99d23c
Spotless 2025-11-01 20:22:53 -04:00
embeddedt
fd46baae21
Backport model compat fix from 1.21
ff6b687d5a

Related: #606
2025-11-01 20:18:17 -04:00
embeddedt
273bab7856
Rewrite dynamic_sounds to consider sound duration when caching
Related: #594
2025-11-01 19:52:56 -04:00
embeddedt
8133198cc2
Enable worldgen_allocation by default 2025-08-22 20:25:27 -04:00
embeddedt
25976f3b87
Disable LazyYCondition logic in situations where it has no effect
This saves roughly 10% of time in surface rule evaluation in some
tests.

Closes #585

Co-authored-by: Voidsong Dragonfly <voidsongdragonfly@pm.me>
2025-08-22 20:25:12 -04:00
embeddedt
f71277eb64
Memoize VanillaRegistres.createLookup 2025-08-09 20:44:08 -04:00
embeddedt
b30b319214
Deduplicate ResourcefulLib Highlight objects 2025-08-09 20:43:49 -04:00
embeddedt
e411f11c0c
Implement Forge ingredient invalidation correctly 2025-08-02 15:29:41 -04:00
embeddedt
e30a7fccf2
Add global properties file
Not populated by default. User must create
`global/modernfix-global-mixins.properties` in the standard global
.minecraft folder for their OS
2025-08-01 18:59:13 -04:00
embeddedt
12a0414f61
Do not override user-specified max.bg.threads 2025-08-01 18:41:55 -04:00
embeddedt
44322a7d07
Tweak narrator mixin 2025-08-01 18:40:40 -04:00
embeddedt
8d4a7c3374
Mark Spark worker as daemon thread 2025-08-01 18:34:53 -04:00
DerCommander323
29c1a479a4
Add mixin.feature.suppress_narrator_stacktrace to prevent some log spam on Linux (#590) 2025-08-01 18:29:20 -04:00
embeddedt
ee6489fb69
Make mixin.perf.thread_priorities limit background thread count as well 2025-07-27 14:55:34 -04:00
embeddedt
87c977a3e6
Patch concurrency issue in ForgeRegistryTagManager 2025-07-16 21:50:00 -04:00
embeddedt
54e55e7534
Don't specify ordering for JEI dependency 2025-07-13 19:15:21 -04:00
embeddedt
65ab37b819
Fix reobfuscation issue 2025-07-13 14:31:58 -04:00
embeddedt
873e3bd676
Fix race condition when mods create tags on different threads 2025-07-12 22:22:58 -04:00
embeddedt
6b37051980
Fix faster_ingredients bypassing defensive copy of ItemValue
Kudos to @nutant233 for noticing this
2025-07-04 18:42:39 -04:00
embeddedt
cf5c81f7e2
Hotfix: disable ingredient_item_deduplication by default 2025-07-03 08:08:03 -04:00
embeddedt
9d280f51df
Remove tterrag maven 2025-07-01 20:48:02 -04:00
embeddedt
f26ed86973
Disable smart ingredient sync with CraftTweaker installed
Related: #570
2025-06-16 19:49:46 -04:00
embeddedt
38f1370d59
Do not register smart ingredient sync channel if option is off
Related: #570
2025-06-16 19:21:25 -04:00
embeddedt
213e0ceb9a
Fix incorrect kick logic 2025-06-05 22:07:09 -04:00
embeddedt
7688fc2b16
Implement Java 17-compatible DFU cache blaster 2025-06-05 21:35:21 -04:00
embeddedt
20b3d8bffa
Do not apply optimization to subclasses of ItemValue 2025-06-05 18:08:19 -04:00
embeddedt
2e0ec6ae9e
Add ingredient item value ItemStack deduplication
Inspired by AllTheLeaks, but done slightly differently to hopefully
be compatible with more mods
2025-06-04 22:53:28 -04:00
embeddedt
a170f072ff
Invalidate memoization for non-category creative tabs when categories are rebuilt 2025-06-02 19:15:20 -04:00
embeddedt
e7542afd1c
Disable mixin.perf.faster_ingredients with VMP installed
Related: #565
2025-06-01 15:24:29 -04:00
embeddedt
71b444288b
Remove nbt_memory_usage
This will be replaced by more targeted optimizations towards the
most common allocators of duplicate keys. The current implementation
forces every key to be interned which may be redundant in many cases
(e.g. when constants are given to the compound tag)
2025-05-30 22:20:51 -04:00
embeddedt
94271b866b
Add world join profiling 2025-05-30 21:35:52 -04:00
embeddedt
6e591f5ace
Add more sysprops 2025-05-30 21:23:51 -04:00
embeddedt
4802988bbb
Add sysprop to allow using async profiler for launch profiling 2025-05-30 21:18:22 -04:00
embeddedt
292b80cf37
Fix missing bitmask when compressing smaller datums into long 2025-05-19 15:19:46 -04:00
embeddedt
5048e74c79
Do not bypass Ingredient.TagValue#getItems during server resource reload
This breaks KubeJS/CraftTweaker's workarounds for tags not being
available during RecipeManager#apply (even though they become available
right after)

Related: #555
2025-05-19 14:55:50 -04:00
embeddedt
c3086e5249
Remove defensive copy of model location collection in replaceAll
The defensive copy shouldn't be necessary, as the set is effectively
immutable anyways
2025-05-19 12:37:32 -04:00
embeddedt
bb658319cb
Try to use a more optimal Set implementation for filtering 2025-05-19 12:17:50 -04:00
embeddedt
14f1552ad7
Use Guava immutable list to avoid extra internal copying 2025-05-19 11:59:44 -04:00
embeddedt
61c8cfdca6
Slight tweaks to ModelLocationBuilder 2025-05-19 11:30:13 -04:00
embeddedt
af526b9113
Include ModernFix itself in time calculations for dynamic resources 2025-05-19 11:02:07 -04:00
embeddedt
6df33005a7
Fix copy-and-paste mistake in compact unihex logic 2025-05-19 10:24:13 -04:00
embeddedt
e9cb602ab7
Add some universe filters 2025-05-18 22:42:56 -04:00
embeddedt
a13587e139
Fix presizing of model location set & use more efficient string generation logic 2025-05-18 21:55:51 -04:00
embeddedt
6979b56d8c
Merge branch 'unihex' into 1.20 2025-05-18 21:06:09 -04:00
embeddedt
3a2edf7ddd
Attempt to reduce overhead of splitting same path string many times 2025-05-18 21:05:12 -04:00
embeddedt
a643170426
Implement more accurate fix for MC-183518
The game now sleeps precisely till the next tick, rather than still
waking up periodically

Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
2025-05-18 19:10:11 -04:00
embeddedt
4964cccff9
Ensure files in assets/ are not counted as namespaces 2025-05-18 15:36:12 -04:00
embeddedt
82535da861
Replace mixin.feature.disable_unihex_font with mixin.perf.compress_unihex_font
The font still takes up some memory, but less than before
2025-05-15 22:11:58 -04:00
embeddedt
f70fb212f7
Update KubeJS maven to fix build failure 2025-05-15 21:39:43 -04:00
embeddedt
588b56530e
Support clearing model registry in dev for testing purposes 2025-05-15 20:22:29 -04:00
embeddedt
3ad4e2478e
Optimize MultiVariant.resolveParents 2025-05-15 20:21:34 -04:00
embeddedt
c118675369
Fix concurrency issues in vanilla RegistryOps.memoizeLookup 2025-05-15 18:53:47 -04:00
embeddedt
8b0622ff5c
Log when model universe is restricted 2025-05-14 22:19:10 -04:00
embeddedt
900e5786b6
Pre-size the top level model location set to reduce rehashing 2025-05-09 22:17:36 -04:00
embeddedt
2535174e00
Implement advanced caching of ingredient item stacks using soft references
This gives the GC control over when to evict the cache, which combines
the benefits of removing the cache entirely with the speed of keeping it
2025-05-03 14:34:48 -04:00
embeddedt
7398b48345
Patch CoFH Core to not rely on Ingredient.itemStacks 2025-05-02 17:27:56 -04:00
embeddedt
eed320b055
Optimize some methods in Ingredient and remove itemStacks caching 2025-05-01 19:10:18 -04:00
embeddedt
01d2582c44
Sync tag ingredients directly if ModernFix is installed on both sides 2025-05-01 17:14:19 -04:00
embeddedt
536eb03b50
Trigger classloading of Items when deferring blockstate cache rebuild 2025-05-01 15:21:08 -04:00
embeddedt
1b37c9da66
Remove obsolete OBJLoader patch 2025-04-29 18:33:50 -04:00
embeddedt
e253833b68
Use CHM's built-in set instead of newSetFromMap 2025-04-29 18:26:20 -04:00
embeddedt
ae729bcd15
Enable use of FML's unused TracingPrintStream for tracking mod messages on System.out
We implement this ourselves because we need it on 1.20.1 anyway,
it will eventually be implemented upstream in NeoForge, at
which point this feature will be removed:
https://github.com/neoforged/FancyModLoader/issues/277
2025-04-29 11:18:21 -04:00
embeddedt
9be6134073
Remove obsolete resource pack code 2025-04-28 18:55:23 -04:00
embeddedt
59e3b83d74
Default to showing the whole model registry to mods
This should fix many silent incompatibilities that existed with the
original opt-in approach. To my knowledge, there are no remaining
popular mods on 1.20 that forcefully load all models in this event
(by iterating over entrySet and calling getValue unconditionally)
so doing this should be safe. Additional logging is also added
to provide quick insight into what mod(s) have the slowest handling
of this event.
2025-04-28 10:59:49 -04:00
embeddedt
4bdddf1051
Attempt to improve parity/reliability of dynamic_entity_renderers 2025-04-27 20:29:21 -04:00
embeddedt
211e404687
Implement a very primitive datapack function profiler 2025-04-27 19:38:23 -04:00
embeddedt
4cde23f4fe
Rewrite resource pack caching to use a tree 2025-04-27 18:35:28 -04:00
embeddedt
dbb6e4713d
Improve usability of -Dmodernfix.debugReloaders 2025-04-27 18:35:14 -04:00
embeddedt
8c2c33093b
Build creative mode tab search tree on first use
This avoids holding search trees for many creative tabs that will
likely never be searched during gameplay.
2025-04-26 16:15:24 -04:00
embeddedt
63aeef1ba0
Add back datapack reload time tracking during world creation 2025-04-26 12:32:50 -04:00
embeddedt
51c4f3eae8
Use smarter iteration order in model bake event registry
This heavily improves the rate of cache hits when mods are baking
many variants of the same model via iteration over the keys,
as now all the variants will be obtained at once rather than
being retrieved randomly.

Cable Tiers used to take 8 seconds in the event before this change
on a Ryzen 7700X, and is now nearly instant.
2025-04-26 12:06:12 -04:00
embeddedt
455b56749c
Document many mixin options 2025-04-25 21:29:46 -04:00
embeddedt
673851ffbd
Check before casting JEI runtime 2025-04-06 14:21:55 -04:00
embeddedt
20be8d0da3
Fix obfuscation error 2025-04-02 18:58:39 -04:00
embeddedt
967b0c1982
Prevent Forge's crash report analyser from complaining about ModernFix 2025-04-02 18:52:37 -04:00
embeddedt
fcea407708
Memoize creative tab content building per-tab
This should greatly reduce lag spikes experienced when opening
the creative inventory with a mod like EMI installed, as the creative
tabs will not be rebuilt a second time
2025-03-06 19:53:33 -05:00
embeddedt
5168eb63aa
Fix BuildCraft pipes
Related: #516
2025-02-15 15:52:19 -05:00
embeddedt
4a8e0487bc
Prevent crash when server sends invalid palette
Related: #509
2025-01-20 09:35:13 -05:00
embeddedt
e7f86f8687
Modernize toolchain
Now requires Fabric Loader 0.16.10 even on Minecraft 1.20.1
2025-01-19 19:26:55 -05:00
embeddedt
f97766019a
Prevent sculk events in addPassenger from deadlocking the game during worldgen
This seems to be a vanilla bug when spawning entities that ride other entities

Related: #510
2025-01-19 19:08:14 -05:00
embeddedt
6aae0f952c
Add debug feature to catch illegal block entity map mutation 2025-01-01 11:05:05 -05:00
embeddedt
b72959f257
Block telemetry by default
Related: #488
2024-12-26 15:17:54 -05:00
embeddedt
64a427fa62
Add LDLib connected textures integration 2024-12-26 14:51:20 -05:00
embeddedt
32a8800344
Premultiply chunk offset for incredibly small performance gain 2024-12-25 22:27:56 -05:00
embeddedt
1c789111e8
"Fix" Hypixel's disappearing chests problem on modern clients
We really should not need to do this. Hypixel, *please* fix your
protocol translation plugin.
2024-12-25 22:13:52 -05:00
embeddedt
0b8eddbf25
Replace RS integration with generic model registry emulation
Fixes patterns not rendering

Related: #499
2024-12-25 15:45:25 -05:00
embeddedt
631b3eddfb
Detect Redirector and show warnings 2024-12-23 13:56:54 -05:00
embeddedt
98e6af87c1
Protect DynamicBakedModelProvider against null keys
Related: #495
2024-12-16 17:01:46 -05:00
embeddedt
639f0e2c1a
Force-override updateY to be public
Related: #494
2024-12-16 09:56:38 -05:00
embeddedt
ba6d0d20fc
Stop looking for legacy cache file names
Related: #485
2024-12-12 19:29:24 -05:00
embeddedt
14a89f94a6
Backport CTM mixin from 1.21
Related: #487
2024-12-12 19:28:01 -05:00
embeddedt
8307564336
Use SSH for propagators 2024-11-29 16:42:36 -05:00
embeddedt
fffb1031f7
Propagate via SSH 2024-11-29 16:41:58 -05:00
embeddedt
0bda3c9f43
Fix setup-gradle 2024-11-29 16:40:29 -05:00
embeddedt
0f3bfd894e
Fix Furniture Mod hedges rendering in fast mode with dynres on 2024-11-02 13:38:31 -04:00
embeddedt
054d36baa0
WIP ingredient work 2024-11-02 13:38:20 -04:00
embeddedt
8e1270dcdc
Skip filtering blockstates if client is not in world 2024-09-22 13:47:35 -04:00
embeddedt
fec7eb66ea
Avoid error from mods that replace chunk system 2024-09-22 13:46:09 -04:00
embeddedt
7c550a1ce4
Fix fluidlogged incompatibility 2024-08-27 17:48:52 -04:00
embeddedt
333147cfd5
Silence mixin warning with Moonrise 2024-08-23 20:52:21 -04:00
embeddedt
d25781f36c
Implement more methods on FakeStateMap 2024-08-23 20:50:28 -04:00
embeddedt
75ff154eca
Mark the section compile optimization as not required for better compat 2024-08-10 19:18:27 -04:00
embeddedt
49464451dd
Make state_definition_construct degrade gracefully if map is used like a hashmap
Related: #452
2024-08-09 18:02:39 -04:00
embeddedt
c0eaf29cb5
Remove mod file scan data deduplicator
This has no effect on newer FML versions since fields are now records
2024-08-06 20:27:25 -04:00
embeddedt
87d1aad3d1
Backport unbaked model caching from 1.21 2024-08-05 09:48:10 -04:00
embeddedt
6f4212ebc8
Unfreeze block registry ourselves in tests 2024-07-27 12:51:32 -04:00
embeddedt
6a365be734
Disable FAPI in dev 2024-07-27 12:44:02 -04:00
embeddedt
2e52db6e93
Apply some simple optimizations for vanilla section meshing 2024-07-27 12:43:48 -04:00
embeddedt
ece2897c37
Loom 1.7 + Gradle 8.8 2024-07-24 20:33:01 -04:00
embeddedt
4ee8c41abd
Allow debugReloader option to also work with datapack reloads
Related: #397
2024-07-24 20:14:41 -04:00
embeddedt
66ef30449a
Collect JEI ingredients to list first to avoid concurrency issues 2024-07-17 18:45:53 -04:00
embeddedt
edddba6991
Fix searching in latest JEI 2024-07-16 18:58:21 -04:00
embeddedt
bc7aa5539c
Do not spin the watchdog thread while server is booting 2024-07-07 20:52:06 -04:00
embeddedt
7348737878
Emulate entrySet on dynamic resources model registry
Related: #429
2024-07-07 11:26:06 -04:00
embeddedt
fd42c5b129
Disable classload hack as it causes the same issue it tried to solve
Related: #431
2024-07-07 09:13:57 -04:00
embeddedt
3bad8f5934
Avoid "timeout is negative" exception in watchdog 2024-06-29 13:46:03 -04:00
embeddedt
72fc1583be
Disable worldgen optimizations for patch release 2024-06-13 18:24:25 -04:00
embeddedt
aac4334b37
Re-enable mixin AP, static remapping is broken right now 2024-06-13 18:19:04 -04:00
embeddedt
6f4098a2d9
re-enable runtime FAPI 2024-06-13 17:24:58 -04:00
embeddedt
b50a7587da
Spotless 2024-06-10 21:58:59 -04:00
embeddedt
f7f871ffc1
Spotless 2024-06-10 21:43:16 -04:00
embeddedt
2193aa11a4
Add some relatively safe allocation optimizations for worldgen 2024-06-10 20:18:11 -04:00
embeddedt
1ec9aad47f
Spotless 2024-06-09 22:03:00 -04:00
embeddedt
fb51a31dd2
Add option to disable thread pool 2024-06-09 21:57:15 -04:00
embeddedt
ef528a4f3a
Avoid thread-local map by storing model reference on BlockState object directly 2024-06-09 20:40:21 -04:00
embeddedt
792f9790ea
Improve F3+T speed when in world 2024-06-08 22:12:30 -04:00
dirtTW
661c6c9ccf
Update Traditional Chinese translation (#413) 2024-06-07 17:29:07 -04:00
embeddedt
809c622ad4
Spotless 2024-06-05 20:14:25 -04:00
embeddedt
a51e740040
Move to Java 21 for building the mod 2024-06-05 20:11:13 -04:00
embeddedt
c7befd1913
Switch to TR mixin remapping, make our custom AP incremental 2024-06-05 19:43:09 -04:00
embeddedt
03e758a037
Fix launch crash on Forge 47.3.1 2024-06-04 19:39:52 -04:00
embeddedt
10f1365905
Merge 1.19.2 into 1.20 2024-06-01 13:38:17 -04:00
embeddedt
b088fee0e8
Merge 1.19.2 into 1.20 2024-05-30 19:06:40 -04:00
embeddedt
def4c05dbc
Merge 1.19.2 into 1.20 2024-05-29 16:04:37 -04:00
embeddedt
831db874e4
Merge 1.19.2 into 1.20 2024-05-12 16:59:13 -04:00
embeddedt
16f637329f
Merge 1.19.2 into 1.20 2024-05-11 22:15:25 -04:00
embeddedt
90848b8972
Update optimization to 1.20 2024-04-30 18:04:30 -04:00
embeddedt
473c74e63b
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-04-30 17:12:34 -04:00
embeddedt
641649c1aa
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-04-22 21:25:51 -04:00
embeddedt
f8424a9fac
Merge 1.19.2 into 1.20 2024-04-15 21:22:18 -04:00
embeddedt
c15b95e2be
Fix mixin.perf.resourcepacks overwriting Fusion patches
Related: #392
2024-04-13 22:26:43 -04:00
embeddedt
d7f2e90984
Merge 1.19.2 into 1.20 2024-04-13 13:11:21 -04:00
embeddedt
dd45519d21
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-04-09 19:20:30 -04:00
embeddedt
53e5eb6748
Merge 1.19.2 into 1.20 2024-03-31 16:06:03 -04:00
embeddedt
efc764020a
Merge 1.19.2 into 1.20 2024-03-31 09:27:10 -04:00
embeddedt
0e48559109
Merge 1.19.2 into 1.20 2024-03-30 18:12:29 -04:00
embeddedt
4ddac48f1e
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-30 17:42:09 -04:00
embeddedt
b0ed60c2f0
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-30 17:37:23 -04:00
embeddedt
85aa352215
Merge 1.19.2 into 1.20 2024-03-30 15:22:45 -04:00
embeddedt
8dac16bfc4
Merge 1.19.2 into 1.20 2024-03-29 10:49:42 -04:00
embeddedt
8a247bd8aa
Merge 1.19.2 into 1.20 2024-03-27 12:15:12 -04:00
embeddedt
e5e8e6d9b5
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-26 10:04:59 -04:00
embeddedt
fe3de55409
Merge 1.19.2 into 1.20 2024-03-22 14:11:03 -04:00
embeddedt
ab077bc48f
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-22 14:06:24 -04:00
embeddedt
3ad7a8ce9d
Merge 1.19.2 into 1.20 2024-03-20 21:38:15 -04:00
embeddedt
0e9d024c5d
Do not treat invalid ModelResourceLocations as top-level when baking dynamic models
Related: #379
2024-03-20 10:18:45 -04:00
embeddedt
de63462363
Merge 1.19.2 into 1.20 2024-03-17 16:09:42 -04:00
embeddedt
ebb4f26777
Merge 1.19.2 into 1.20 2024-03-17 15:55:35 -04:00
embeddedt
280d14a595
Merge 1.19.2 into 1.20 2024-03-17 15:52:55 -04:00
embeddedt
d128ca12c9
Merge 1.19.2 into 1.20 2024-03-17 15:08:24 -04:00
embeddedt
7b2a0e39be
Merge 1.19.2 into 1.20 2024-03-14 22:13:57 -04:00
embeddedt
095ba1905d
Merge 1.19.2 into 1.20 2024-03-10 21:58:39 -04:00
embeddedt
f1fc20d5a1
Merge 1.19.2 into 1.20 2024-03-08 17:51:05 -05:00
embeddedt
263ed51369
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-04 16:39:07 -05:00
embeddedt
e7632b7f0b
Remove Blueprint memory leak patch 2024-03-02 12:28:04 -05:00
embeddedt
56779b9a5b
Merge 1.19.2 into 1.20 2024-03-01 11:33:03 -05:00
embeddedt
01a68a2453
Merge 1.19.2 into 1.20 2024-02-28 20:10:52 -05:00
embeddedt
e1fcac1761
Merge 1.19.2 into 1.20 2024-02-26 16:40:47 -05:00
embeddedt
73b0f13de0
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-02-26 16:28:20 -05:00
embeddedt
f4f76cada3
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-02-26 16:27:55 -05:00
embeddedt
edda3b4e02
Merge 1.19.2 into 1.20 2024-02-23 16:45:22 -05:00
embeddedt
e91220cdea Retrieve missing model when first required 2024-02-07 15:28:01 -05:00
embeddedt
e0516ebc51
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-02-05 09:14:35 -05:00
embeddedt
e1d203ba10
Merge 1.19.2 into 1.20 2024-02-02 20:38:31 -05:00
embeddedt
81c4980738 Fix resource pack cache engine being unable to list resource stacks for files 2024-02-01 10:06:18 -05:00
embeddedt
df9d280b1c Merge 1.19.2 into 1.20 2024-01-30 15:47:47 -05:00
embeddedt
6207162a17 Merge 1.19.2 into 1.20 2024-01-29 15:30:53 -05:00
embeddedt
c32fad10e0
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-01-27 20:22:16 -05:00
embeddedt
55cb94f1d1 Add textureGetter parameter to onBakedModelLoad 2024-01-24 10:38:57 -05:00
embeddedt
a100622a03
Only apply resource pack speedup on paths starting with assets or data
Related: #354
2024-01-13 11:22:29 -05:00
embeddedt
c6e01f8a59 Merge 1.19.2 into 1.20 2024-01-12 15:49:13 -05:00
embeddedt
b2d80ada34
Use wildcard on ItemOverrides mixin to capture Forge rename 2024-01-11 21:04:48 -05:00
embeddedt
9d95a5363f
Update cap mixin for 1.20 changes 2024-01-04 20:35:41 -05:00
embeddedt
c85f7e49d7
Merge 1.19.2 into 1.20 2024-01-04 20:32:38 -05:00
embeddedt
91602ae7d6
Merge 1.19.2 into 1.20 2024-01-04 20:31:06 -05:00
embeddedt
9375a4233b
Fix Forge errors 2024-01-02 09:55:55 -05:00
embeddedt
17fdccddfe
Allow missing models on item overrides
Please ask your servers to stop shipping the client invalid model
files.

Related: #343
2024-01-02 09:52:55 -05:00
embeddedt
a186c956f7
Merge 1.19.2 into 1.20 2023-12-30 19:06:11 -05:00
embeddedt
6d7b50bdd8
Merge 1.19.2 into 1.20 2023-12-30 19:02:49 -05:00
embeddedt
8b97ebf945
Even More ClientOnlyMixin 2023-12-28 14:45:15 -05:00
embeddedt
6706715fb1
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-28 14:42:25 -05:00
embeddedt
357d421f5a
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-28 14:26:35 -05:00
embeddedt
0ea384f3e6
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-27 19:08:21 -05:00
embeddedt
6578040e77
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-27 15:27:03 -05:00
embeddedt
c96f7ecf11
Merge 1.19.2 into 1.20 2023-12-27 15:20:17 -05:00
embeddedt
2406c1a338
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-26 20:53:09 -05:00
embeddedt
6ef5654bb6
Merge 1.19.2 into 1.20 2023-12-23 21:28:42 -05:00
embeddedt
a87399a10f
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-23 19:06:59 -05:00
embeddedt
95496fc27c
Merge 1.19.2 into 1.20 2023-12-23 17:15:32 -05:00
embeddedt
f35d920801
Merge 1.19.2 into 1.20 2023-12-23 15:57:41 -05:00
embeddedt
88a276eed9
Update mixin target 2023-12-23 15:55:32 -05:00
embeddedt
8729e50f1b
Merge 1.19.2 into 1.20 2023-12-23 15:54:20 -05:00
embeddedt
4d0444ba2a
Merge 1.19.2 into 1.20 2023-12-21 16:51:11 -05:00
embeddedt
ed74748994
Merge 1.19.2 into 1.20 2023-12-21 13:41:55 -05:00
embeddedt
c5afe3c769
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-21 13:32:19 -05:00
embeddedt
b5c4b79eb8
Merge 1.19.2 into 1.20 2023-12-14 21:11:58 -05:00
embeddedt
8677532629
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-14 20:44:44 -05:00
embeddedt
e47bdbf6d0
Merge 1.19.2 into 1.20 2023-12-11 11:01:50 -05:00
embeddedt
9464f07a5a
Replace hacky capturing with MixinExtras 2023-12-09 14:32:52 -05:00
embeddedt
28ac5eaec4
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-09 14:08:31 -05:00
embeddedt
11f313f6e7
Avoid capturedLocation being replaced unexpectedly 2023-12-09 13:50:04 -05:00
embeddedt
46127b50f3
Invalidate blockstate cache in place of initCache 2023-12-06 20:44:31 -05:00
embeddedt
cb09af7e86 Mark registry redirect as non-required
Related: #309
2023-11-30 15:45:27 -05:00
embeddedt
2c577da8fd
Spotless 2023-11-27 07:41:43 -05:00
embeddedt
2e9166c7df
Rewrite missing model emulation functionality for 1.20+ dynres implementation
Fixes #308
2023-11-27 07:38:53 -05:00
embeddedt
7be382a3ce More ClientOnlyMixin 2023-11-23 10:16:01 -05:00
embeddedt
7c57ffd2c6 Merge 1.19.2 into 1.20 2023-11-23 10:12:19 -05:00
embeddedt
1002baa6b1 Merge 1.19.2 into 1.20 2023-11-23 09:51:13 -05:00
embeddedt
3fb3bb3c11
Merge 1.19.2 into 1.20 2023-11-11 17:26:27 -05:00
embeddedt
193b0922cc Remove blockstate lambda fallback on Forge
The conversion of MRL->state->MRL is very costly and slows down
model bake events by a lot. Since Fabric Model Loading API is
now standard, there is no need to pass models through the lambda
anymore
2023-11-10 15:42:37 -05:00
embeddedt
abfaea19a5 Merge 1.19.2 into 1.20 2023-11-07 17:27:26 -05:00
其智乃反不能及
5983ed5bf3
Update zh_cn.json (#288) 2023-11-07 09:15:17 -05:00
embeddedt
ed9dc3719c
Merge 1.19.2 into 1.20 2023-11-05 21:59:32 -05:00
embeddedt
bd55e16d6e
Add description for cache_profile_texture_url 2023-11-05 21:23:58 -05:00
embeddedt
e859ce8eb6
Avoid slow getHash call when retrieving skins
Co-authored-by: Fury_Phoenix <64714532+Phoenix-Starlight@users.noreply.github.com>
2023-11-05 21:22:17 -05:00
embeddedt
d11e9ac190
Mark Embers as requiring namespaced model registry
Related: #284
2023-11-05 21:00:25 -05:00
embeddedt
3551ab645a
Fix compile errors 2023-11-04 10:26:58 -04:00
embeddedt
cc60cba1f2
Refactor Forge dynamic resources implementation to be similar to Fabric 2023-11-04 10:21:38 -04:00
embeddedt
fb84fda4de
Merge 1.19.2 into 1.20 2023-11-04 09:02:16 -04:00
embeddedt
482c0ca503 Allow dimensions to be removed
Fixes https://github.com/neoforged/NeoForge/issues/102
2023-10-31 09:50:01 -04:00
embeddedt
b6a47da3b0 Merge 1.19.2 into 1.20 2023-10-30 14:54:19 -04:00
embeddedt
d358ea37a8
Remove Diagonal Fences mixin on 1.20+, mod now uses dynres-compatible logic
Related: #199
2023-10-30 09:30:52 -04:00
embeddedt
2a6077cb65
Merge branch '1.20' of https://github.com/embeddedt/ModernFix into 1.20 2023-10-29 21:17:49 -04:00
embeddedt
d557725c82
Merge 1.19.2 into 1.20 2023-10-29 21:17:24 -04:00
embeddedt
375276ea1f
Disable mixin.feature.registry_event_progress by default 2023-10-29 21:05:17 -04:00
embeddedt
72a653e532
Merge branch 'experiment/loading-screen' into 1.20 2023-10-29 21:04:35 -04:00
embeddedt
59235e6a21
Fix spotless 2023-10-29 11:44:25 -04:00
embeddedt
09490df85d
Fix compile errors 2023-10-29 11:41:35 -04:00
embeddedt
a677f6d571
Merge 1.19.2 into 1.20 2023-10-29 11:37:49 -04:00
embeddedt
81baeea35b
Support earlyy baking models on Forge as well
Fixes FFAPI model provider hooks not running
2023-10-28 20:12:46 -04:00
embeddedt
f4f3eff242
Merge 1.19.2 into 1.20 2023-10-28 20:06:02 -04:00
embeddedt
7cb660f955
Fix FFAPI Model Loading API v1 causing missing item models 2023-10-28 20:00:48 -04:00
embeddedt
3eff8c787d
Merge 1.19.2 into 1.20 2023-10-28 09:54:25 -04:00
embeddedt
7054c16f6c Merge 1.19.2 into 1.20 2023-10-25 17:18:45 -04:00
embeddedt
daea9dd83a Merge 1.19.2 into 1.20 2023-10-25 15:00:19 -04:00
Fury_Phoenix
c0cdbd122e
Unify ModelMangerMixin (#265) 2023-10-25 14:26:01 -04:00
embeddedt
e397f0ca78 Merge 1.19.2 into 1.20 2023-10-25 14:24:17 -04:00
embeddedt
fd61abb375 Drop TinyFD patch on 1.20+ 2023-10-24 12:45:56 -04:00
embeddedt
735a626cf3 Merge 1.19.2 into 1.20 2023-10-24 12:45:39 -04:00
embeddedt
7cbea84706
Merge 1.19.2 into 1.20 2023-10-13 10:47:52 -04:00
embeddedt
cbfe1636ff
Merge 1.19.2 into 1.20 2023-10-10 17:40:30 -04:00
embeddedt
ed1f2c5837
Merge 1.19.2 into 1.20 2023-10-09 08:37:42 -04:00
embeddedt
e537cbe29a Merge 1.19.2 into 1.20 2023-10-07 18:47:10 -04:00
embeddedt
637c14fb6d Merge 1.19.2 into 1.20 2023-10-07 17:48:38 -04:00
embeddedt
b56fbc853d Merge 1.19.2 into 1.20 2023-10-07 17:46:24 -04:00
embeddedt
b1a0d0b94a Merge 1.19.2 into 1.20 2023-10-06 17:07:47 -04:00
embeddedt
c45f83e896 Suppress latest.log warning about structures on 1.20+ 2023-10-06 09:49:12 -04:00
embeddedt
ce0d054e6e Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-10-05 14:31:16 -04:00
embeddedt
385523c826 Merge 1.19.2 into 1.20 2023-10-05 14:12:35 -04:00
embeddedt
225366ee02 Merge 1.19.2 into 1.20 2023-10-03 13:45:37 -04:00
embeddedt
8fd8efb2e3 Merge 1.19.2 into 1.20 2023-09-27 17:58:52 -04:00
embeddedt
c0815b787e Fix legacy solid property not being set correctly when blockstate cache is invalid
Related: #244
2023-09-27 17:49:36 -04:00
embeddedt
3011e40972
Merge 1.19.2 into 1.20 2023-09-24 12:50:15 -04:00
embeddedt
b1a1d785de
Merge 1.19.2 into 1.20 2023-09-24 12:33:59 -04:00
embeddedt
f1ef1a6c41
Merge 1.19.4 into 1.20 2023-09-24 11:55:27 -04:00
embeddedt
d76e841761
Merge 1.19.2 into 1.19.4 2023-09-24 11:55:27 -04:00
embeddedt
dc4850502d
Merge 1.19.4 into 1.20 2023-09-22 22:05:53 -04:00
embeddedt
8d057a2b55
Merge 1.19.2 into 1.19.4 2023-09-22 22:05:52 -04:00
embeddedt
88d56c451e Merge 1.19.4 into 1.20 2023-09-20 17:58:55 -04:00
embeddedt
ec6de638a2 Merge 1.19.2 into 1.19.4 2023-09-20 17:58:53 -04:00
embeddedt
eff07204ea
Merge 1.19.4 into 1.20 2023-09-17 12:33:57 -04:00
embeddedt
4a90be9bc7
Merge 1.19.2 into 1.19.4 2023-09-17 12:33:56 -04:00
embeddedt
e9f6f3d953 Merge 1.19.4 into 1.20 2023-09-15 09:40:55 -04:00
embeddedt
2a6be9f9e6 Merge 1.19.2 into 1.19.4 2023-09-15 09:40:54 -04:00
embeddedt
a0c5c90c8d Prevent crash with mods calling getFluidState recursively
The returned fluid is meaningless, but vanilla doesn't crash here

Fixes #238
2023-09-15 09:32:30 -04:00
embeddedt
22559131cc
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-31 11:35:57 -04:00
embeddedt
8b0b0759ef
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-31 11:33:23 -04:00
embeddedt
6198f0c9d3
Merge 1.19.4 into 1.20 2023-08-31 07:57:26 -04:00
embeddedt
5f45f612a3
Merge 1.19.2 into 1.19.4 2023-08-31 07:57:25 -04:00
Phoenix-Starlight
5fef7dc66b
Fix dynamic resources ModelManager leak (#231)
The opened BufferedReader was not being closed, and apparently the cleaner/finalize mechanism doesn't exist for it
2023-08-31 07:56:38 -04:00
embeddedt
4b560c7d3d
Merge 1.19.4 into 1.20 2023-08-29 15:17:06 -04:00
embeddedt
ecb3863410
Merge 1.19.2 into 1.19.4 2023-08-29 15:17:05 -04:00
embeddedt
501d24ddfd
Merge 1.19.4 into 1.20 2023-08-29 14:39:57 -04:00
embeddedt
2aab73220c
Merge 1.19.2 into 1.19.4 2023-08-29 14:39:56 -04:00
embeddedt
eadb19d386
Allow Model Loading API to inject and load extra models 2023-08-25 15:00:21 -04:00
embeddedt
ce7b7cbaf2 Merge 1.19.4 into 1.20 2023-08-24 21:47:04 -04:00
embeddedt
fa5b947442 Merge 1.19.2 into 1.19.4 2023-08-24 21:47:03 -04:00
embeddedt
73d2a4405d
Improve performance of async handoff 2023-08-20 20:51:46 -04:00
embeddedt
8d766a8cc8
Avoid calling createCapabilities many times, mark mixin as client-only 2023-08-20 20:35:20 -04:00
embeddedt
fe8d0434c5
Rename feature 2023-08-20 20:27:10 -04:00
embeddedt
ae59c2496e
Show mod names and progress during registry events 2023-08-20 20:26:26 -04:00
embeddedt
a19d519b4b
Temporarily shift splash screen control to background thread during registry events 2023-08-20 20:01:36 -04:00
embeddedt
f7097ec394
Update Forge target to 47.1.3 2023-08-20 19:58:07 -04:00
embeddedt
16e1e37fd9
Merge 1.19.4 into 1.20 2023-08-20 16:50:45 -04:00
embeddedt
48c9d401db
Merge 1.19.2 into 1.19.4 2023-08-20 16:50:44 -04:00
embeddedt
26bdb57972
Merge 1.19.4 into 1.20 2023-08-20 13:15:52 -04:00
embeddedt
c34974a555
Merge 1.19.2 into 1.19.4 2023-08-20 13:15:52 -04:00
embeddedt
29e3d38c55
Merge 1.19.4 into 1.20 2023-08-19 19:32:24 -04:00
embeddedt
0df87a9f83
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-19 19:32:16 -04:00
embeddedt
501e498175
Merge 1.19.4 into 1.20 2023-08-19 19:19:59 -04:00
embeddedt
f8a35c5884
Merge 1.19.2 into 1.19.4 2023-08-19 19:19:58 -04:00
embeddedt
b171d4bf19
Merge 1.19.4 into 1.20 2023-08-19 14:59:19 -04:00
embeddedt
e827fba754
Merge 1.19.2 into 1.19.4 2023-08-19 14:59:19 -04:00
embeddedt
9f5ccf28df
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-18 15:39:58 -04:00
embeddedt
6536c49c3c
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-18 15:39:03 -04:00
embeddedt
e946cc896a
Merge 1.19.4 into 1.20 2023-08-18 15:16:55 -04:00
embeddedt
a1e8838aee
Merge 1.19.2 into 1.19.4 2023-08-18 15:16:54 -04:00
embeddedt
bc7fb1e6d4
Merge 1.19.4 into 1.20 2023-08-18 14:39:26 -04:00
embeddedt
2ee1ef13ec
Merge 1.19.2 into 1.19.4 2023-08-18 14:39:25 -04:00
embeddedt
9964693050
Merge 1.19.4 into 1.20 2023-08-18 14:35:25 -04:00
embeddedt
c51133f2c3
Merge 1.19.2 into 1.19.4 2023-08-18 14:35:25 -04:00
embeddedt
4aebee53ac
Merge 1.19.4 into 1.20 2023-08-18 14:19:48 -04:00
embeddedt
7faa29e84b
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-18 14:17:00 -04:00
embeddedt
74c9f684e6
Merge 1.19.4 into 1.20 2023-08-15 22:03:47 -04:00
embeddedt
18722beebd
Merge 1.19.2 into 1.19.4 2023-08-15 22:03:46 -04:00
embeddedt
6e00010e9a
Merge 1.19.4 into 1.20 2023-08-15 21:21:18 -04:00
embeddedt
9325a8c892
Update mixin target 2023-08-15 21:21:10 -04:00
embeddedt
00481145b6
Merge 1.19.4 into 1.20 2023-08-15 21:19:16 -04:00
embeddedt
a918c09543
Merge 1.19.2 into 1.19.4 2023-08-15 21:19:15 -04:00
embeddedt
ef341932a3
Merge 1.19.4 into 1.20 2023-08-15 13:08:56 -04:00
embeddedt
2e272f9b18
Merge 1.19.2 into 1.19.4 2023-08-15 13:08:55 -04:00
embeddedt
5203985a25
Merge 1.19.4 into 1.20 2023-08-13 16:38:04 -04:00
embeddedt
351e4d3fc6
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-13 16:37:56 -04:00
embeddedt
05cc25c761
Merge 1.19.4 into 1.20 2023-08-12 12:13:46 -04:00
embeddedt
d13cfd5ca8
Merge 1.19.2 into 1.19.4 2023-08-12 12:13:45 -04:00
embeddedt
2f92dbe12c
Update mixin 2023-08-12 12:13:31 -04:00
embeddedt
fab831f143
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-12 12:09:38 -04:00
embeddedt
073b8cb9de
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-12 12:09:21 -04:00
embeddedt
507cc7eb14
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-11 19:55:28 -04:00
embeddedt
fa4d659c5b
Update testmod mixin 2023-08-11 19:52:40 -04:00
embeddedt
74d28ed997
Update mixin 2023-08-11 19:50:33 -04:00
embeddedt
dcad671568
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-11 19:48:12 -04:00
embeddedt
be4a6abc81
Port testmod to 1.20 2023-08-10 11:07:39 -04:00
embeddedt
770969ec5c
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-10 10:54:46 -04:00
embeddedt
24e014f326
Update testmod to 1.19.4 2023-08-10 10:54:27 -04:00
embeddedt
a506f8785e
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-10 10:47:59 -04:00
embeddedt
712409b4e1
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-09 17:20:45 -04:00
embeddedt
571d3bd5e2
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-09 17:14:22 -04:00
embeddedt
32e246885b Merge 1.19.4 into 1.20 2023-08-08 18:17:36 -04:00
embeddedt
824deddb46 Merge 1.19.2 into 1.19.4 2023-08-08 18:17:35 -04:00
embeddedt
180ac925f7
Merge 1.19.4 into 1.20 2023-08-08 10:27:08 -04:00
embeddedt
bb115f1d2f
Merge 1.19.2 into 1.19.4 2023-08-08 10:27:08 -04:00
embeddedt
8f31048619
Merge 1.19.4 into 1.20 2023-08-07 21:53:31 -04:00
embeddedt
52b66db729
Merge 1.19.2 into 1.19.4 2023-08-07 21:53:30 -04:00
embeddedt
858551411b
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-07 11:22:35 -04:00
embeddedt
4ed5e8a434
Update CTM version 2023-08-07 11:22:29 -04:00
embeddedt
e0a170db92
Fix CTM block models not working (only item models worked) 2023-08-07 11:21:47 -04:00
embeddedt
fa17a5f745
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-07 10:47:02 -04:00
embeddedt
dc59c9bf0c
Update CTM integration for 1.19.4+ 2023-08-07 10:46:19 -04:00
embeddedt
823fa259e9
Merge 1.19.4 into 1.20 2023-08-05 19:43:20 -04:00
embeddedt
c81327fdb5
Merge 1.19.2 into 1.19.4 2023-08-05 19:43:19 -04:00
embeddedt
ec5b92dd7a
Don't trigger full blockstate cache rebuilds when requesting fluid
This causes mods to prematurely rebuild the whole cache, which
is not what we want
2023-08-05 19:38:45 -04:00
embeddedt
8a0ff999bd
Merge 1.19.4 into 1.20 2023-08-05 12:52:06 -04:00
embeddedt
7b18bcafd6
Merge 1.19.2 into 1.19.4 2023-08-05 12:52:05 -04:00
embeddedt
5165cf20c8
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-05 12:18:45 -04:00
embeddedt
2cb5acb9f9
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-05 12:17:50 -04:00
embeddedt
3df41090e4
Remove resource_key_equality patch as NeoForge fixes it in 1.20+ 2023-08-04 10:05:55 -04:00
embeddedt
1b73ded110
Merge 1.19.4 into 1.20 2023-08-04 09:44:06 -04:00
embeddedt
6fe2674f5b
Merge 1.19.2 into 1.19.4 2023-08-04 09:44:05 -04:00
embeddedt
c2695b1180
Merge 1.19.4 into 1.20 2023-08-03 20:04:49 -04:00
embeddedt
d3884d764d
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-03 20:02:55 -04:00
embeddedt
331ad00758
Merge 1.19.4 into 1.20 2023-08-03 17:01:14 -04:00
embeddedt
b64fefa73c
Merge 1.19.2 into 1.19.4 2023-08-03 17:01:13 -04:00
embeddedt
d5a9f68575
Merge 1.19.4 into 1.20 2023-08-03 13:14:38 -04:00
embeddedt
3caba87924
Merge 1.19.2 into 1.19.4 2023-08-03 13:14:37 -04:00
embeddedt
df854f333c
Merge 1.19.4 into 1.20 2023-08-03 12:21:04 -04:00
embeddedt
23605b2a80
Merge 1.19.2 into 1.19.4 2023-08-03 12:21:03 -04:00
embeddedt
13aaab4798
Merge 1.19.4 into 1.20 2023-08-03 11:54:01 -04:00
embeddedt
0f08491f50
Merge 1.19.2 into 1.19.4 2023-08-03 11:54:00 -04:00
embeddedt
19593b5574
Merge 1.19.4 into 1.20 2023-08-03 11:27:54 -04:00
embeddedt
89abcdb17c
Merge 1.19.2 into 1.19.4 2023-08-03 11:27:53 -04:00
embeddedt
bf5ca2f3cd
Merge 1.19.4 into 1.20 2023-08-02 22:18:19 -04:00
embeddedt
23ffdabcc4
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-02 22:18:13 -04:00
embeddedt
fa6b93fad2
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 19:51:25 -04:00
embeddedt
942b7cbb43
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-02 19:41:34 -04:00
embeddedt
5bd5c8289c
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 16:41:39 -04:00
embeddedt
26998e912b
Mark fluidState redirect as optional for old Lithium/VMP versions 2023-08-02 16:41:23 -04:00
embeddedt
02fd57f9a4
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 16:31:51 -04:00
embeddedt
f76ca049cc
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-02 16:31:07 -04:00
embeddedt
a1a441d397
Merge 1.19.4 into 1.20 2023-08-02 15:45:57 -04:00
embeddedt
ba9ba01dfe
Merge 1.19.2 into 1.19.4 2023-08-02 15:45:56 -04:00
embeddedt
11fd512c5e
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 11:56:36 -04:00
embeddedt
7d6fa48a74
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-08-02 11:55:34 -04:00
embeddedt
156f0a10cb
Merge 1.19.4 into 1.20 2023-07-31 15:35:57 -04:00
embeddedt
9c0c2416d6
Update mixin target to 1.19.4 2023-07-31 15:35:43 -04:00
embeddedt
858325e40d
Merge 1.19.4 into 1.20 2023-07-31 15:34:04 -04:00
embeddedt
c7604672fc
Merge 1.19.2 into 1.19.4 2023-07-31 15:34:03 -04:00
embeddedt
ec2f6e8490
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-31 11:21:39 -04:00
embeddedt
84bd756cdf
Merge 1.19.4 into 1.20 2023-07-30 13:11:12 -04:00
embeddedt
1a2981e5f1
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-30 13:09:42 -04:00
embeddedt
94f7b9295d
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-30 12:59:23 -04:00
embeddedt
3e3448adb1
Merge 1.19.4 into 1.20 2023-07-28 22:11:28 -04:00
embeddedt
3b3803f57e
Merge 1.19.2 into 1.19.4 2023-07-28 22:11:27 -04:00
embeddedt
3a4b8738fc
Merge 1.19.4 into 1.20 2023-07-28 22:00:23 -04:00
embeddedt
eb1d16740e
Merge 1.19.2 into 1.19.4 2023-07-28 22:00:22 -04:00
embeddedt
4697704763
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-28 21:45:25 -04:00
embeddedt
4a66802b37
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-28 21:41:44 -04:00
embeddedt
1884996e53
Merge 1.19.4 into 1.20 2023-07-28 16:40:02 -04:00
embeddedt
451b26fa93
Use Redirect instead of Inject to avoid allocations 2023-07-28 16:38:44 -04:00
embeddedt
4fe3b93fb0
Fix crash on Forge 2023-07-28 16:17:49 -04:00
embeddedt
51bf5890d3
Merge 1.19.4 into 1.20 2023-07-28 16:09:27 -04:00
embeddedt
23e768d629
Spotless 2023-07-28 16:09:21 -04:00
embeddedt
e1fdca5f41
Merge 1.19.4 into 1.20 2023-07-28 16:07:14 -04:00
embeddedt
d3ff2823dc
Update blockstate caching logic for vanilla 1.19.4 changes 2023-07-28 16:05:21 -04:00
embeddedt
4e3dc99479
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-27 16:49:05 -04:00
embeddedt
e45acac6b6
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-27 16:48:48 -04:00
embeddedt
ae8c062631
Merge 1.19.4 into 1.20 2023-07-27 16:04:08 -04:00
embeddedt
49c847f38a
Merge 1.19.2 into 1.19.4 2023-07-27 16:04:07 -04:00
embeddedt
36ae73316a
Merge 1.19.4 into 1.20 2023-07-27 12:41:43 -04:00
embeddedt
a467d853b0
Rip out wasMissingModel flag, causes more issues than it solves
Logic will be reintroduced later to emulate nullness if Fabric mods
need it
2023-07-27 12:39:26 -04:00
embeddedt
7a648f0c5e
Merge 1.19.4 into 1.20 2023-07-26 22:03:11 -04:00
embeddedt
f1fa3a4c9c
Merge 1.19.2 into 1.19.4 2023-07-26 22:03:10 -04:00
embeddedt
055892cd62
Merge 1.19.4 into 1.20 2023-07-26 09:37:05 -04:00
embeddedt
4da012c871
Merge 1.19.2 into 1.19.4 2023-07-26 09:37:04 -04:00
embeddedt
76d1c8e8bd
Merge 1.19.4 into 1.20 2023-07-24 17:19:03 -04:00
embeddedt
5d33805a6f
Merge 1.19.2 into 1.19.4 2023-07-24 17:19:01 -04:00
embeddedt
c41728b97c
Merge 1.19.4 into 1.20 2023-07-24 16:05:01 -04:00
embeddedt
512ed02db2
Merge 1.19.2 into 1.19.4 2023-07-24 16:05:00 -04:00
embeddedt
437eb9f793
Merge 1.19.4 into 1.20 2023-07-23 19:29:31 -04:00
embeddedt
23f5af93ce
Merge 1.19.2 into 1.19.4 2023-07-23 19:29:30 -04:00
embeddedt
1889ef2d8c
Merge 1.19.4 into 1.20 2023-07-23 19:23:27 -04:00
embeddedt
3a96f63798
Merge 1.19.2 into 1.19.4 2023-07-23 19:23:26 -04:00
embeddedt
90f6f6d68d
Merge 1.19.4 into 1.20 2023-07-23 18:33:34 -04:00
embeddedt
b24f82d257
Merge 1.19.2 into 1.19.4 2023-07-23 18:33:33 -04:00
embeddedt
d3bd8289ec
Support NeoForge on Modrinth 2023-07-22 20:55:48 -04:00
embeddedt
7b670f229e
Merge 1.19.4 into 1.20 2023-07-22 17:07:35 -04:00
embeddedt
b43e7902df
Merge 1.19.2 into 1.19.4 2023-07-22 17:07:34 -04:00
embeddedt
821f87b880
Merge 1.19.4 into 1.20 2023-07-22 11:22:05 -04:00
embeddedt
ecbcc6dcaa
Merge 1.19.2 into 1.19.4 2023-07-22 11:22:04 -04:00
embeddedt
4031b65099
Merge 1.19.4 into 1.20 2023-07-21 11:15:22 -04:00
embeddedt
bc09210ada
Merge 1.19.2 into 1.19.4 2023-07-21 11:15:22 -04:00
embeddedt
19df78dbe2
Merge 1.19.4 into 1.20 2023-07-21 10:47:57 -04:00
embeddedt
4131f3b2fe
Merge 1.19.2 into 1.19.4 2023-07-21 10:47:56 -04:00
embeddedt
c6eb703648
Merge 1.19.4 into 1.20 2023-07-20 21:35:15 -04:00
embeddedt
24598ac463
Merge 1.19.2 into 1.19.4 2023-07-20 21:35:14 -04:00
embeddedt
a5fb8575a6
Merge 1.19.4 into 1.20 2023-07-20 20:18:46 -04:00
embeddedt
f9315a127f
Merge 1.19.2 into 1.19.4 2023-07-20 20:18:45 -04:00
embeddedt
374aac7ff5
Merge 1.19.4 into 1.20 2023-07-20 10:57:47 -04:00
embeddedt
e8aa88b317
Fix Diagonal Fences breaking after resource reload 2023-07-20 10:57:29 -04:00
embeddedt
5ed2faebc4
Merge 1.19.4 into 1.20 2023-07-20 10:43:40 -04:00
embeddedt
0767b6e9cf
Fix incorrect field being used for pre-bake event 2023-07-20 10:43:23 -04:00
embeddedt
174e609526
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-19 22:15:51 -04:00
embeddedt
63111ed938
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-19 22:15:40 -04:00
embeddedt
42298947cc
Backport model loading API change to 1.19.4 2023-07-19 22:15:16 -04:00
embeddedt
427a92f0f3
Stop JiJing fabric-models-v0 2023-07-19 22:10:38 -04:00
embeddedt
4a0219e9da
Revert JiJ of fabric-model-loading-api-v1 2023-07-19 22:07:50 -04:00
embeddedt
b7a1f16a9d
Merge 1.19.4 into 1.20 2023-07-19 17:34:39 -04:00
embeddedt
5994edcf17
Merge 1.19.2 into 1.19.4 2023-07-19 17:34:38 -04:00
embeddedt
d69f5ac18d
Merge 1.19.4 into 1.20 2023-07-19 17:01:44 -04:00
embeddedt
72a45ef014
Synchronize outside of ModelBaker for FAPI compat 2023-07-19 17:01:10 -04:00
embeddedt
3162a531b7
Merge 1.19.4 into 1.20 2023-07-19 16:46:15 -04:00
embeddedt
02f6431109
Merge 1.19.2 into 1.19.4 2023-07-19 16:46:14 -04:00
embeddedt
7d7e2f029d
Merge 1.19.4 into 1.20 2023-07-19 12:39:52 -04:00
embeddedt
3827d8a5ce
Merge 1.19.2 into 1.19.4 2023-07-19 12:39:09 -04:00
embeddedt
9eed139cc9
Merge 1.19.4 into 1.20 2023-07-19 12:32:40 -04:00
embeddedt
ab55dde534
Merge 1.19.2 into 1.19.4 2023-07-19 12:32:39 -04:00
embeddedt
30f483245c
Merge 1.19.4 into 1.20 2023-07-19 12:20:52 -04:00
embeddedt
8527594b3b
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-19 12:17:13 -04:00
embeddedt
5b716dcdf2
Merge 1.19.4 into 1.20 2023-07-18 13:57:31 -04:00
embeddedt
e88d8bb7b7
Merge 1.19.2 into 1.19.4 2023-07-18 13:57:30 -04:00
embeddedt
ed7bd69116
Merge branch 'dev/fabric-model-v1' into 1.20 2023-07-18 11:28:24 -04:00
embeddedt
e34beb5775
Merge 1.19.4 into 1.20 2023-07-17 16:09:27 -04:00
embeddedt
95c3044a40
Merge 1.19.2 into 1.19.4 2023-07-17 16:09:26 -04:00
embeddedt
c51b0585a2
Merge 1.19.4 into 1.20 2023-07-16 20:00:08 -04:00
embeddedt
2f7bd0e083
Merge 1.19.2 into 1.19.4 2023-07-16 20:00:07 -04:00
embeddedt
e86787c663
Merge 1.19.4 into 1.20 2023-07-16 16:58:47 -04:00
embeddedt
24ec6f154a
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-16 16:58:41 -04:00
embeddedt
9a5edb9431
Merge 1.19.4 into 1.20 2023-07-15 20:37:19 -04:00
embeddedt
2a328356cd
Merge 1.19.2 into 1.19.4 2023-07-15 20:37:18 -04:00
embeddedt
d9f93ec67e
Merge 1.19.4 into 1.20 2023-07-15 15:07:38 -04:00
embeddedt
18e354d0ae
Merge 1.19.2 into 1.19.4 2023-07-15 15:07:37 -04:00
embeddedt
ff292cfabc
Merge 1.19.4 into 1.20 2023-07-14 13:57:40 -04:00
embeddedt
76d6ff14c2
Merge 1.19.2 into 1.19.4 2023-07-14 13:57:13 -04:00
embeddedt
faccdb0ed7
Merge 1.19.4 into 1.20 2023-07-13 21:43:49 -04:00
embeddedt
b0815bcae6
Merge 1.19.2 into 1.19.4 2023-07-13 21:43:48 -04:00
embeddedt
dc0ea4d828
Merge 1.19.4 into 1.20 2023-07-13 20:12:46 -04:00
embeddedt
ec1bacd1dd
Merge 1.19.2 into 1.19.4 2023-07-13 20:12:46 -04:00
embeddedt
1531762524
Merge 1.19.4 into 1.20 2023-07-13 19:40:40 -04:00
embeddedt
b79a66ce83
Merge 1.19.2 into 1.19.4 2023-07-13 19:40:39 -04:00
embeddedt
a799afc19c
Merge 1.19.4 into 1.20 2023-07-13 17:08:59 -04:00
embeddedt
24130cde74
Merge 1.19.2 into 1.19.4 2023-07-13 17:08:58 -04:00
embeddedt
eecf9f0726
Merge 1.19.4 into 1.20 2023-07-13 14:58:37 -04:00
embeddedt
9f212fc475
Merge 1.19.2 into 1.19.4 2023-07-13 14:58:36 -04:00
embeddedt
ad1df59c18
Update 2023-07-13 11:52:23 -04:00
embeddedt
804cd04778
Explicitly depend on fabric-model-loading-api-v1 so it gets JiJed 2023-07-12 20:37:53 -04:00
embeddedt
083664d858
Support the new Fabric Model Loading API v1 2023-07-12 20:13:50 -04:00
embeddedt
c98721056d
Merge 1.19.4 into 1.20 2023-07-12 19:37:05 -04:00
embeddedt
d2fe664fe5
Merge 1.19.2 into 1.19.4 2023-07-12 19:37:04 -04:00
embeddedt
e4cce437d4
Merge 1.19.4 into 1.20 2023-07-12 19:35:53 -04:00
embeddedt
3a6b5c91d5
Merge 1.19.2 into 1.19.4 2023-07-12 19:35:52 -04:00
embeddedt
e5152439ef
Merge 1.19.4 into 1.20 2023-07-12 19:30:47 -04:00
embeddedt
1a68035131
Merge 1.19.2 into 1.19.4 2023-07-12 19:30:47 -04:00
embeddedt
73e8631fcd
Merge 1.19.4 into 1.20 2023-07-12 11:49:31 -04:00
embeddedt
29c260f7ce
Merge 1.19.2 into 1.19.4 2023-07-12 11:49:30 -04:00
embeddedt
6548d5da80
Fix parity issue in paper_chunk_patches for 1.20+
Ensure scheduleChunkGeneration is correctly called if chunk status has load dependencies

Thanks to ishland for noticing this
2023-07-12 11:28:19 -04:00
embeddedt
55c9b8e322
Merge 1.19.4 into 1.20 2023-07-11 22:15:11 -04:00
embeddedt
9281344863
Merge 1.19.2 into 1.19.4 2023-07-11 22:15:10 -04:00
embeddedt
2bf51c2034
Merge 1.19.4 into 1.20 2023-07-11 22:13:41 -04:00
embeddedt
cbf63b8c19
Merge 1.19.2 into 1.19.4 2023-07-11 22:13:40 -04:00
embeddedt
944e481f32
Remove item cache flag patch on 1.20 branch 2023-07-11 21:33:27 -04:00
embeddedt
b409db3e29
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-11 21:33:07 -04:00
embeddedt
6ae19f11ea
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-11 21:31:29 -04:00
embeddedt
a5ae6e0631
Merge 1.19.4 into 1.20 2023-07-11 17:00:20 -04:00
embeddedt
0e248f8b83
Merge 1.19.2 into 1.19.4 2023-07-11 17:00:20 -04:00
embeddedt
61288a17ac
Merge 1.19.4 into 1.20 2023-07-11 14:25:35 -04:00
embeddedt
fff28fdcbf
Merge 1.19.2 into 1.19.4 2023-07-11 14:25:34 -04:00
embeddedt
9a966cfad9
Merge 1.19.4 into 1.20 2023-07-10 20:28:31 -04:00
embeddedt
e235e07bb2
Merge 1.19.2 into 1.19.4 2023-07-10 20:28:30 -04:00
embeddedt
489d3abe65
Merge 1.19.4 into 1.20 2023-07-10 09:02:45 -04:00
embeddedt
5dea99f139
Merge 1.19.2 into 1.19.4 2023-07-10 09:02:44 -04:00
embeddedt
61a8000bf1
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-09 21:17:50 -04:00
embeddedt
b3f00a0681
Merge 1.19.4 into 1.20 2023-07-09 20:41:08 -04:00
embeddedt
8cc5785e86
Port dynres change to 1.19.4+ 2023-07-09 20:38:35 -04:00
embeddedt
827d09289d
Merge 1.19.4 into 1.20 2023-07-09 20:37:25 -04:00
embeddedt
0ce00531a6
Merge 1.19.2 into 1.19.4 2023-07-09 20:37:24 -04:00
embeddedt
7e25e31d33
Merge 1.19.4 into 1.20 2023-07-09 20:35:41 -04:00
embeddedt
a1d56e2921
Merge 1.19.2 into 1.19.4 2023-07-09 20:35:41 -04:00
embeddedt
540b19c141
Merge 1.19.4 into 1.20 2023-07-09 14:15:14 -04:00
embeddedt
aa493c41d5
Merge 1.19.2 into 1.19.4 2023-07-09 14:15:13 -04:00
embeddedt
05e66b2492
Merge 1.19.4 into 1.20 2023-07-09 13:32:49 -04:00
embeddedt
ae115c4908
Merge 1.19.2 into 1.19.4 2023-07-09 13:32:49 -04:00
embeddedt
7d8dd5ab09
Merge 1.19.4 into 1.20 2023-07-08 14:52:16 -04:00
embeddedt
adfbc7508e
Merge 1.19.2 into 1.19.4 2023-07-08 14:52:16 -04:00
embeddedt
1a7909aaa4
Merge 1.19.4 into 1.20 2023-07-07 21:06:48 -04:00
embeddedt
0fea79a647
Merge 1.19.2 into 1.19.4 2023-07-07 21:06:47 -04:00
embeddedt
e56898fff4
Merge 1.19.4 into 1.20 2023-07-07 20:23:42 -04:00
embeddedt
7671066548
Merge 1.19.2 into 1.19.4 2023-07-07 20:23:41 -04:00
embeddedt
60d06c92f6
Merge 1.19.4 into 1.20 2023-07-07 19:22:08 -04:00
embeddedt
f1cd8bac20
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-07 19:21:25 -04:00
embeddedt
e65727937c
Merge 1.19.4 into 1.20 2023-07-06 22:10:26 -04:00
embeddedt
a1f3cb9270
Merge 1.19.2 into 1.19.4 2023-07-06 22:10:25 -04:00
embeddedt
29f7badbfb
Update test to reflect Mojang changes [skip ci] 2023-07-06 22:10:16 -04:00
embeddedt
5e7421ab24
Merge 1.19.4 into 1.20 2023-07-06 21:29:26 -04:00
embeddedt
8325a8ba02
Merge 1.19.2 into 1.19.4 2023-07-06 21:29:09 -04:00
embeddedt
92264ed37e
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-06 21:27:43 -04:00
embeddedt
6300dd6737
Add utility for disabling Unihex font
Saves 10MB of RAM
2023-07-06 11:38:36 -04:00
embeddedt
ce8c6e0283
Merge 1.19.4 into 1.20 2023-07-05 20:02:28 -04:00
embeddedt
50e558644a
Merge 1.19.2 into 1.19.4 2023-07-05 20:02:27 -04:00
embeddedt
ba7bda0b04
Remove LazyDFU change for 1.20 2023-07-05 15:08:31 -04:00
embeddedt
c7787d1390
Merge 1.19.2 into 1.19.4 2023-07-05 15:04:49 -04:00
embeddedt
a7d0d4892f
Merge 1.19.4 into 1.20 2023-07-05 15:04:49 -04:00
embeddedt
079c348948
Merge 1.19.4 into 1.20 2023-07-05 14:52:56 -04:00
embeddedt
c50388a358
Merge 1.19.2 into 1.19.4 2023-07-05 14:52:55 -04:00
embeddedt
2a16229056
Merge 1.19.4 into 1.20 2023-07-05 14:50:28 -04:00
embeddedt
7652a1dbc5
Merge 1.19.2 into 1.19.4 2023-07-05 14:50:07 -04:00
embeddedt
5aeea48413
Apply spotless 2023-07-05 12:47:43 -04:00
embeddedt
7632647e1d
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-05 12:45:02 -04:00
embeddedt
41a56fba20
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-07-05 12:35:41 -04:00
embeddedt
c33fe2e928
Merge 1.19.4 into 1.20 2023-07-03 15:10:48 -04:00
embeddedt
cac4ca96d5
Merge 1.19.2 into 1.19.4 2023-07-03 15:10:47 -04:00
embeddedt
3237de7e33
Merge 1.19.4 into 1.20 2023-07-03 14:59:21 -04:00
embeddedt
37d6f477c4
Merge 1.19.2 into 1.19.4 2023-07-03 14:58:45 -04:00
embeddedt
dc8d727bdb
Update Diagonal Fences mixin 2023-07-02 13:30:43 -04:00
embeddedt
3be36f826c
Merge 1.19.4 into 1.20 2023-06-29 19:28:08 -04:00
embeddedt
dc268285b0
Add .mcmeta files to resource list to match 1.19.4+ behavior
Fixes modded texture .mcmeta files not being picked up

Fixes #145
2023-06-29 19:28:01 -04:00
embeddedt
7464cf7420
Merge 1.19.4 into 1.20 2023-06-29 15:26:55 -04:00
embeddedt
30c9956acd
Merge 1.19.2 into 1.19.4 2023-06-29 15:26:55 -04:00
embeddedt
a6cce0c043
Merge 1.19.4 into 1.20 2023-06-27 16:40:33 -04:00
embeddedt
152e795c32
Merge 1.19.2 into 1.19.4 2023-06-27 16:40:32 -04:00
embeddedt
840cad23b8
Merge 1.19.4 into 1.20 2023-06-27 15:29:27 -04:00
embeddedt
93817c5d3a
Merge 1.19.2 into 1.19.4 2023-06-27 15:29:26 -04:00
embeddedt
463bd4ef51
Merge 1.19.4 into 1.20 2023-06-27 11:27:38 -04:00
embeddedt
c8192ef7e3
Merge 1.19.2 into 1.19.4 2023-06-27 11:27:37 -04:00
embeddedt
ca60a13bb4
Merge 1.19.4 into 1.20 2023-06-27 11:04:06 -04:00
embeddedt
96a83533dd
Merge 1.19.2 into 1.19.4 2023-06-27 11:04:05 -04:00
embeddedt
54f55ee257
Merge 1.19.4 into 1.20 2023-06-26 21:26:28 -04:00
embeddedt
84b08ef64a
Merge 1.19.2 into 1.19.4 2023-06-26 21:26:27 -04:00
embeddedt
7a2d38f2f1
Merge 1.19.4 into 1.20 2023-06-26 19:46:09 -04:00
embeddedt
370a0fad11
Merge 1.19.2 into 1.19.4 2023-06-26 19:46:09 -04:00
embeddedt
af486998d2
Merge 1.19.4 into 1.20 2023-06-26 15:57:50 -04:00
embeddedt
5229643761
Add missing ExpectPlatform 2023-06-26 15:57:37 -04:00
embeddedt
4fd4de7d52
Change spark version 2023-06-26 14:33:43 -04:00
embeddedt
8e467e8239
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-06-26 14:33:26 -04:00
embeddedt
04c6ea2e66
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-26 14:33:12 -04:00
embeddedt
2bad1c0226
Merge 1.19.4 into 1.20 2023-06-26 13:04:44 -04:00
embeddedt
65506ba7e1
Merge 1.19.2 into 1.19.4 2023-06-26 13:04:43 -04:00
embeddedt
b755d745c5
Merge 1.19.4 into 1.20 2023-06-26 12:59:35 -04:00
embeddedt
c23a4be440
Merge 1.19.2 into 1.19.4 2023-06-26 12:59:34 -04:00
embeddedt
99acb17d90
Bump Forge 2023-06-22 13:53:17 -04:00
embeddedt
565dfb4b81
Merge 1.19.4 into 1.20 2023-06-22 13:45:27 -04:00
embeddedt
24f31dd92a
Initial version of resource pack caching for 1.19.4+ 2023-06-22 13:45:13 -04:00
embeddedt
63bcdb1019
Merge 1.19.4 into 1.20 2023-06-22 13:42:57 -04:00
embeddedt
5b2e70cda0
Merge 1.19.2 into 1.19.4 2023-06-22 13:42:56 -04:00
embeddedt
1f589901d6
Merge 1.19.4 into 1.20 2023-06-21 21:44:00 -04:00
embeddedt
1afdfccf3b
Merge 1.19.2 into 1.19.4 2023-06-21 21:43:59 -04:00
embeddedt
9bc6b7b0f7
Merge 1.19.4 into 1.20 2023-06-20 14:43:13 -04:00
embeddedt
49bc941dd7
Merge 1.19.2 into 1.19.4 2023-06-20 14:43:12 -04:00
embeddedt
c1c0010126
Merge 1.19.4 into 1.20 2023-06-20 14:34:54 -04:00
embeddedt
9cdeeb4c94
Merge 1.19.2 into 1.19.4 2023-06-20 14:34:53 -04:00
embeddedt
6006026deb
Merge 1.19.4 into 1.20 2023-06-19 20:58:13 -04:00
embeddedt
00b6261a1c
Merge 1.19.2 into 1.19.4 2023-06-19 20:58:13 -04:00
embeddedt
683f9fd13b
1.20.1 2023-06-19 20:38:33 -04:00
embeddedt
18e1cec611
Merge 1.19.4 into 1.20 2023-06-15 22:14:57 -04:00
embeddedt
4d47ca26db
Fix miscopied patch from Fabric to Forge 2023-06-15 22:14:39 -04:00
embeddedt
42d41eb0f7
Merge 1.19.4 into 1.20 2023-06-14 22:14:23 -04:00
embeddedt
fea1d35d08
Merge 1.19.2 into 1.19.4 2023-06-14 22:14:22 -04:00
embeddedt
f7037e3ecb
Change cancellation strategy for bakeModels, fixes Balm issues 2023-06-14 22:14:13 -04:00
embeddedt
75bd0a5ff7
Merge 1.19.4 into 1.20 2023-06-13 17:52:45 -04:00
embeddedt
c3a5964f17
Merge 1.19.2 into 1.19.4 2023-06-13 17:52:45 -04:00
embeddedt
9aa96b4d03
Merge 1.19.4 into 1.20 2023-06-13 17:41:04 -04:00
embeddedt
0765b6770f
Fix creative search tab not having a populator registered on Fabric 2023-06-13 17:40:40 -04:00
embeddedt
761417833e
Merge 1.19.4 into 1.20 2023-06-12 21:58:58 -04:00
embeddedt
e5ab4df3dc
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-12 21:58:51 -04:00
embeddedt
173d71b04f
Merge 1.19.4 into 1.20 2023-06-12 10:56:16 -04:00
embeddedt
6df837f9ba
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-12 10:56:06 -04:00
embeddedt
d352c9e8ca
Mark 1.20.1 as supported 2023-06-12 10:46:56 -04:00
embeddedt
e5cc8ef97c
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-06-12 10:46:44 -04:00
embeddedt
af63a6ca09
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-12 10:46:33 -04:00
embeddedt
a7e5147104
Merge 1.19.4 into 1.20 2023-06-11 21:32:24 -04:00
embeddedt
017d81a8c6
Merge 1.19.2 into 1.19.4 2023-06-11 21:32:23 -04:00
embeddedt
cc6191cef2
Merge 1.19.4 into 1.20 2023-06-11 21:03:06 -04:00
embeddedt
9aa28c3e3f
Merge 1.19.2 into 1.19.4 2023-06-11 21:03:05 -04:00
embeddedt
002ff639a0
Merge 1.19.4 into 1.20 2023-06-11 20:48:20 -04:00
embeddedt
826694793c
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-11 20:46:55 -04:00
embeddedt
48924e3364
Allow DashLoader 5 on 1.19.4+ 2023-06-09 12:46:08 -04:00
embeddedt
79c4b1cb27
Re-add Forge support for 1.20 2023-06-08 09:34:41 -04:00
embeddedt
b1bfcfb190
1.20 2023-06-07 11:56:11 -04:00
embeddedt
7ab2dac645
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-06-07 11:47:24 -04:00
embeddedt
702fe0ba24
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-07 11:47:12 -04:00
embeddedt
7bbc10acc3
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-06-06 12:51:48 -04:00
embeddedt
ca4f2a2aeb
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-06-06 12:50:50 -04:00
embeddedt
aedbc88e3c
Update to 1.20-rc1 2023-06-06 12:28:30 -04:00
embeddedt
f9cbd8fa61
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-06-06 12:01:21 -04:00
embeddedt
a614c050e7
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-06 11:57:49 -04:00
embeddedt
673e6dec8d
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-03 11:40:31 -04:00
embeddedt
a635671276
This will likely be the last ever 1.19.4 release 2023-06-02 20:17:13 -04:00
embeddedt
144bdaa301
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-06-02 20:14:14 -04:00
embeddedt
830eb19420
Hopefully final fix for the 1.19.4 "missing model" bug on Fabric 2023-05-30 11:18:27 -04:00
embeddedt
4a9cd78d1d
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-29 20:39:14 -04:00
embeddedt
bd94b5dd2e
Spotless 2023-05-22 14:40:26 -04:00
embeddedt
31feef398f
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-22 14:24:27 -04:00
embeddedt
4cccd8f6d9
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-17 17:46:31 -04:00
embeddedt
adbf61a06b
1.20-pre2 2023-05-16 11:27:08 -04:00
embeddedt
b44739e33c
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-05-16 11:21:43 -04:00
embeddedt
340b026951
Remove unneeded imports 2023-05-16 11:21:34 -04:00
embeddedt
30bf3afc1d
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-05-16 11:18:10 -04:00
embeddedt
119f9ec6dd
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-16 11:11:00 -04:00
embeddedt
d2d5f81782
Bump required Forge version, drop datapack reload patch
https://github.com/MinecraftForge/MinecraftForge/pull/9454 has been
merged upstream
2023-05-15 19:43:31 -04:00
embeddedt
b1fb365f22
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-15 11:14:20 -04:00
embeddedt
a1f50a0c4f
Fix missing model flag not being cleared at times 2023-05-12 10:52:18 -04:00
embeddedt
57947441ce
Spotless 2023-05-11 11:33:32 -04:00
embeddedt
f1515c5063
1.20-pre1 2023-05-11 11:27:22 -04:00
embeddedt
ec10f36839
Fix compile errors 2023-05-11 11:27:10 -04:00
embeddedt
05b28b8269
Fix spotless error 2023-05-11 11:01:49 -04:00
embeddedt
9c421218b8
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-11 10:51:34 -04:00
embeddedt
163ac96cd7
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-06 16:20:18 -04:00
embeddedt
c229b1c60c
Update item renderer mixin for 1.19.4 2023-05-06 16:18:47 -04:00
embeddedt
422b6d56f7
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-06 16:07:10 -04:00
embeddedt
650bd0bfb9
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-05 13:30:31 -04:00
embeddedt
95ee0c60ca
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-05 10:53:30 -04:00
embeddedt
1f4e45eca6
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-05 10:50:34 -04:00
embeddedt
170da33755
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-04 11:47:58 -04:00
embeddedt
1fbf83c562
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-04 10:22:23 -04:00
embeddedt
65f151bbef
Actually cache item models 2023-05-03 21:40:57 -04:00
embeddedt
545c68f122
Rewrite 1.19.4 Fabric model baker mixin for compatibility purposes 2023-05-03 19:59:48 -04:00
embeddedt
d4bfe17a72
Tweak Fabric model bakery to run more vanilla code 2023-05-03 19:23:43 -04:00
embeddedt
2a7733e61f
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-03 11:16:34 -04:00
embeddedt
ae33070507
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-02 20:24:48 -04:00
embeddedt
969c3fd18e
Update entity renderer mixin 2023-05-02 19:24:42 -04:00
embeddedt
f62aac1c77
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-02 19:23:34 -04:00
embeddedt
09c5cdb6a2
Drop resource pack mixin from 1.19.4 for now 2023-05-02 15:33:32 -04:00
embeddedt
cae1026fee
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-02 15:32:54 -04:00
embeddedt
7ca647b763
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-02 11:20:58 -04:00
embeddedt
5edbe16e18
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-02 10:29:00 -04:00
embeddedt
8a06ef1322
Fix model bakery issues 2023-05-02 10:07:19 -04:00
embeddedt
0de67936c1
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-01 21:30:01 -04:00
embeddedt
ada0bd4012
Fix mixin 2023-05-01 20:50:56 -04:00
embeddedt
a06a46b498
Spotless 2023-05-01 20:47:24 -04:00
embeddedt
b746be4c67
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-01 20:46:16 -04:00
embeddedt
efb9f4ca2d
Fabric 2023-05-01 20:38:47 -04:00
embeddedt
ea25f2e854
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-05-01 20:30:25 -04:00
embeddedt
e989411074
Compilation fixes 2023-04-30 19:39:04 -04:00
embeddedt
0ee41f262e
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-30 19:31:57 -04:00
embeddedt
50dc476ceb
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-29 16:04:43 -04:00
embeddedt
1ae3f9f319
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-29 15:24:02 -04:00
embeddedt
4a3a555326
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-27 15:29:39 -04:00
embeddedt
0d74ad8cbf
Fix compile error 2023-04-27 14:26:09 -04:00
embeddedt
8b84b97cf0
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-27 14:22:31 -04:00
embeddedt
dc236d6ec1
Fix NamespacedWrapper needing remap 2023-04-27 13:58:39 -04:00
embeddedt
90585fbb4f
Fix exception in model removal notification 2023-04-27 13:38:20 -04:00
embeddedt
6c7cd80bb3
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-27 13:37:50 -04:00
embeddedt
42398fcd17
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-24 13:55:44 -04:00
embeddedt
7eaa286a7a
Fix search trees, downgrade Forge so REI works in dev 2023-04-23 21:36:47 -04:00
embeddedt
d534dacf18
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-22 13:15:28 -04:00
embeddedt
23ee5cf982
Merge remote-tracking branch 'origin/1.19.2' into 1.19.4 2023-04-22 11:49:43 -04:00
embeddedt
99ffd3dc95
Fix running outside dev 2023-04-15 15:51:44 -04:00
embeddedt
8dbcac7afc
Speed up world creation screen 2023-04-15 15:08:05 -04:00
embeddedt
f8f0e0ca45
Port dynamic model loading to 1.19.4 2023-04-15 14:56:14 -04:00
embeddedt
c891501579
1.19.4 2023-04-15 14:22:36 -04:00
504 changed files with 11346 additions and 8349 deletions

View File

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

View File

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

View File

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

View File

@ -2,16 +2,15 @@ ModernFix is a standard Minecraft-style Gradle project powered by Architectury L
run the `build` task (e.g. via `./gradlew build`). You can also use `./gradlew forge:build` or `./gradlew fabric:build`
to build for just one loader (e.g. when debugging and wanting to rebuild quickly).
You must use Java 17 to develop ModernFix as the toolchain requires it. Nonetheless, the 1.16 mod JARs will work on
a Minecraft instance with Java 8.
You must use Java 21 to develop ModernFix as the toolchain requires it. Nonetheless, the built 1.20.1 JAR is still
compatible with Java 17.
## Submitting pull requests
Code or documentation contributions are welcome. Please keep the following points in mind:
* This project supports many Minecraft versions. Ideally, contributions should be made to the oldest relevant MC version.
For instance, a PR optimizing new worldgen should be made to 1.18 (not 1.19 or 1.20) while a PR optimizing something
like recipes should be made to 1.16 (the oldest supported version).
* This project supports many Minecraft versions. Ideally, contributions should be made to the oldest relevant MC version (currently 1.20)
and then they will be ported forward.
This somewhat unconventional policy ensures that all supported versions are treated equal when it comes to development,
rather than the onus being on other modders and players to backport changes that are needed. Changes to older versions are

View File

@ -1,7 +1,6 @@
plugins {
id 'com.github.johnrengelman.shadow'
id 'com.gradleup.shadow' version '8.3.9'
id 'java-library'
id 'com.diffplug.spotless'
}
repositories {
@ -31,7 +30,6 @@ dependencies {
}
tasks.withType(JavaCompile) {
options.compilerArgs += '--enable-preview'
options.release = 17
}
@ -44,6 +42,7 @@ shadowJar {
// shadowJar bug
include '*.jar'
include 'META-INF/services/javax.annotation.processing.Processor'
include 'META-INF/gradle/incremental.annotation.processors'
include 'org/spongepowered/asm/mixin/Mixin.class'
include 'org/fury_phoenix/**/*'
include {it.getName() == 'OnlyIn.class'}
@ -52,9 +51,4 @@ shadowJar {
include {it.getName() == 'EnvType.class'}
}
spotless {
java {
removeUnusedImports()
}
}
version = '1.1.4'

View File

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

View File

@ -16,7 +16,6 @@ import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
@ -26,7 +25,6 @@ import org.fury_phoenix.mixinAp.config.MixinConfig;
@SupportedAnnotationTypes({"org.spongepowered.asm.mixin.Mixin", "org.embeddedt.modernfix.annotation.ClientOnlyMixin"})
@SupportedOptions({"rootProject.name", "project.name", "org.fury_phoenix.mixinAp.validator.debug"})
@SupportedSourceVersion(SourceVersion.RELEASE_17)
@AutoService(Processor.class)
public class MixinProcessor extends AbstractProcessor {
@ -38,6 +36,11 @@ public class MixinProcessor extends AbstractProcessor {
private final Map<String, List<String>> mixinConfigList = new HashMap<>();
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
@ -77,7 +80,7 @@ public class MixinProcessor extends AbstractProcessor {
List<String> mixins =
annotatedMixins.stream()
.map(TypeElement.class::cast)
.map(TypeElement::toString)
.map(e -> processingEnv.getElementUtils().getBinaryName(e).toString())
.collect(Collectors.toList());
mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins);

View File

@ -17,7 +17,7 @@ public record MixinConfig(
@SerializedName("package")
String packageName,
String plugin,
String compatabilityLevel,
String compatibilityLevel,
@SerializedName("mixins")
List<String> commonMixins,
@SerializedName("client")
@ -25,7 +25,7 @@ public record MixinConfig(
InjectorOptions injectors, OverwriteOptions overwrites
) {
public MixinConfig(String packageName, List<String> commonMixins, List<String> clientMixins) {
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_8",
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_17",
commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT);
}
public record InjectorOptions(int defaultRequire) {

View File

@ -0,0 +1 @@
org.fury_phoenix.mixinAp.annotation.MixinProcessor,aggregating

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

210
build.gradle.kts Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,55 +0,0 @@
plugins {
id "modernfix.mod-common-conventions"
}
architectury {
common(rootProject.enabled_platforms.split(","))
}
dependencies {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixinextras_version}"))
modCompileOnly("dev.latvian.mods:kubejs:${kubejs_version}") {
transitive = false
}
modApi("dev.latvian.mods:rhino:${rhino_version}") {
transitive = false
}
modApi("me.shedaniel:RoughlyEnoughItems-api:${rei_version}") {
transitive = false
}
modCompileOnly("me.shedaniel:RoughlyEnoughItems-fabric:${rei_version}") {
transitive = false
}
modCompileOnly("appeng:appliedenergistics2-fabric:${appeng_version}") {
transitive = false
}
modCompileOnly("curse.maven:diagonal-fences-458048:${diagonal_fences_version}")
modCompileOnly "curse.maven:spark-361579:${rootProject.spark_version}"
// compile against the JEI API but do not include it at runtime
modCompileOnly("mezz.jei:jei-${minecraft_version}-common:${jei_version}")
modCompileOnly("mezz.jei:jei-${minecraft_version}-gui:${jei_version}")
modCompileOnly("mezz.jei:jei-${minecraft_version}-lib:${jei_version}")
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury:${rootProject.architectury_version}"
}
// don't need remapped common jar
tasks.named('remapJar') { enabled = false }
publishing {
publications {
mavenCommon(MavenPublication) {
artifactId = rootProject.archives_base_name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

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

View File

@ -1,211 +0,0 @@
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;
import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry;
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.concurrent.CopyOnWriteArrayList;
public class ModernFixClient {
public static ModernFixClient INSTANCE;
public static long worldLoadStartTime = -1;
private static int numRenderTicks;
public static float gameStartTimeSeconds = -1;
public static boolean recipesUpdated, tagsUpdated = false;
public String brandingString = null;
/**
* The list of loaded client integrations.
*/
public static List<ModernFixClientIntegration> CLIENT_INTEGRATIONS = new CopyOnWriteArrayList<>();
public ModernFixClient() {
INSTANCE = this;
// clear reserve as it's not needed
MemoryReserve.release();
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) {
brandingString = ModernFix.NAME + " " + ModernFixPlatformHooks.INSTANCE.getVersionString();
}
SearchTreeProviderRegistry.register(JEIBackedSearchTree.PROVIDER);
SearchTreeProviderRegistry.register(REIBackedSearchTree.PROVIDER);
for(String className : ModernFixPlatformHooks.INSTANCE.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) {
try {
CLIENT_INTEGRATIONS.add((ModernFixClientIntegration)Class.forName(className).getDeclaredConstructor().newInstance());
} catch(ReflectiveOperationException | ClassCastException e) {
ModernFix.LOGGER.error("Could not instantiate integration {}", className, e);
}
}
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.FireIntegrationHook")) {
for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) {
integration.onDynamicResourcesStatusChange(true);
}
}
}
public void resetWorldLoadStateMachine() {
numRenderTicks = 0;
worldLoadStartTime = -1;
recipesUpdated = false;
tagsUpdated = false;
}
public void onGameLaunchFinish() {
if(gameStartTimeSeconds >= 0)
return;
gameStartTimeSeconds = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f;
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.measure_time.GameLoad"))
ModernFix.LOGGER.warn("Game took " + gameStartTimeSeconds + " seconds to start");
ModernFixPlatformHooks.INSTANCE.onLaunchComplete();
ClassInfoManager.clear();
}
public void onRecipesUpdated() {
recipesUpdated = true;
}
public void onTagsUpdated() {
tagsUpdated = true;
}
public void onRenderTickEnd() {
if(recipesUpdated
&& tagsUpdated
&& worldLoadStartTime != -1
&& Minecraft.getInstance().player != null
&& numRenderTicks++ >= 10) {
float timeSpentLoading = ((float)(System.nanoTime() - worldLoadStartTime) / 1000000000f);
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.measure_time.WorldLoad")) {
ModernFix.LOGGER.warn("Time from main menu to in-game was " + timeSpentLoading + " seconds");
ModernFix.LOGGER.warn("Total time to load game and open world was " + (timeSpentLoading + gameStartTimeSeconds) + " seconds");
}
resetWorldLoadStateMachine();
}
}
/**
* Check if the IDs match and remap them if not.
* @return true if ID remap was needed
*/
private static boolean compareAndSwitchIds(Class<? extends Entity> eClass, String fieldName, EntityDataAccessor<?> accessor, int newId) {
if(accessor.id != newId) {
ModernFix.LOGGER.warn("Corrected ID mismatch on {} field {}. Client had {} but server wants {}.",
eClass,
fieldName,
accessor.id,
newId);
accessor.id = newId;
return true;
} else {
ModernFix.LOGGER.debug("{} {} ID fine: {}", eClass, fieldName, newId);
return false;
}
}
/**
* 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;
IntegratedWatchdog watchdog = new IntegratedWatchdog(server);
watchdog.start();
}
}

View File

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

View File

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

View File

@ -1,22 +0,0 @@
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.embeddedt.modernfix.chunk.SafeBlockGetter;
import org.embeddedt.modernfix.duck.ISafeBlockGetter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@Mixin(value = BlockBehaviour.BlockStateBase.class, priority = 100)
public class BlockStateBaseMixin {
@ModifyVariable(method = "getOffset", at = @At("HEAD"), argsOnly = true, index = 1)
private BlockGetter useSafeGetter(BlockGetter g) {
if(g instanceof ISafeBlockGetter) {
SafeBlockGetter replacement = ((ISafeBlockGetter) g).mfix$getSafeBlockGetter();
if(replacement.shouldUse())
return replacement;
}
return g;
}
}

View File

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

View File

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

View File

@ -1,49 +0,0 @@
package org.embeddedt.modernfix.common.mixin.bugfix.item_cache_flag;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import org.objectweb.asm.Opcodes;
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.Redirect;
/**
* Remove emptyCacheFlag from ItemStack, as Mojang did in 1.20 due to <a href="https://bugs.mojang.com/browse/MC-258939">MC-258939</a>.
*/
@Mixin(ItemStack.class)
public class ItemStackMixin {
@Shadow @Final @Deprecated private Item item;
/**
* @author embeddedt, Mojang
* @reason avoid getItem()
*/
@Redirect(method = "isEmpty", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getItem()Lnet/minecraft/world/item/Item;"))
private Item getItemDirect(ItemStack stack) {
return this.item;
}
/**
* @author embeddedt, Mojang
* @reason avoid getItem()
*/
@Redirect(method = "isEmpty", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z"))
private boolean checkIsDirect(ItemStack stack, Item item) {
return this.item == item;
}
@Redirect(method = "*", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/world/item/ItemStack;emptyCacheFlag:Z"))
private boolean checkEmptyDirect(ItemStack stack) {
return stack.isEmpty();
}
/**
* @author embeddedt, Mojang
* @reason flag is no longer used
*/
@Overwrite
private void updateEmptyCacheFlag() {}
}

View File

@ -1,75 +0,0 @@
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 org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@Mixin(ChunkMap.class)
public abstract class ChunkMapMixin {
@Shadow @Final private BlockableEventLoop<Runnable> mainThreadExecutor;
@Shadow @Final private ChunkMap.DistanceManager distanceManager;
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> protoChunkToFullChunk(ChunkHolder arg);
@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 @Final private StructureTemplateManager structureTemplateManager;
/* 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)
private Executor useMainThreadExecutor(Executor executor) {
return this.mainThreadExecutor;
}
/**
* @author embeddedt
* @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) {
if(requiredStatus != ChunkStatus.EMPTY) {
ChunkPos chunkpos = holder.getPos();
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = holder.getOrScheduleFuture(requiredStatus.getParent(), (ChunkMap)(Object)this);
cir.setReturnValue(future.thenComposeAsync((either) -> {
Optional<ChunkAccess> optional = either.left();
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());
this.progressListener.onStatusChange(chunkpos, requiredStatus);
return completablefuture;
} else {
return this.scheduleChunkGeneration(holder, requiredStatus);
}
}, this.mainThreadExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainThreadExecutor));
}
}
}

View File

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

View File

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

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

View File

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

View File

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

View File

@ -1,20 +0,0 @@
package org.embeddedt.modernfix.common.mixin.feature.measure_time;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(ReloadableResourceManager.class)
public class SimpleReloadableResourceManagerMixin {
// TODO maybe expose as a mixin config
private static final boolean ENABLE_DEBUG_RELOADER = Boolean.getBoolean("modernfix.debugReloader");
/**
* @author embeddedt
* @reason add ability to use this feature in modpacks
*/
@ModifyArg(method = "createReload", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleReloadInstance;create(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/List;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Z)Lnet/minecraft/server/packs/resources/ReloadInstance;"), index = 5)
private boolean enableDebugReloader(boolean bl) {
return bl || ENABLE_DEBUG_RELOADER;
}
}

View File

@ -1,71 +0,0 @@
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.Registry;
import net.minecraft.server.level.ChunkHolder;
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.EmptyLevelChunk;
import org.embeddedt.modernfix.ModernFix;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.*;
@Mixin(value = ServerChunkCache.class, priority = 1100)
public abstract class ServerChunkCacheMixin {
@Shadow @Final private Thread mainThread;
@Shadow @Final public ServerLevel level;
@Shadow protected abstract CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> getChunkFutureMainThread(int k, int l, ChunkStatus arg, boolean bl);
@Shadow @Final private ServerChunkCache.MainThreadExecutor mainThreadProcessor;
private final boolean debugDeadServerAccess = Boolean.getBoolean("modernfix.debugBadChunkloading");
@Inject(method = "getChunk", at = @At("HEAD"), cancellable = true)
private void bailIfServerDead(int chunkX, int chunkZ, ChunkStatus requiredStatus, boolean load, CallbackInfoReturnable<ChunkAccess> cir) {
if(!this.level.getServer().isRunning() && !this.mainThread.isAlive()) {
ModernFix.LOGGER.fatal("A mod is accessing chunks from a stopped server (this will also cause memory leaks)");
if(debugDeadServerAccess) {
new Exception().printStackTrace();
}
Holder<Biome> plains = this.level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).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();
if(!future.isDone()) {
// Wait at least 500 milliseconds before printing anything
Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure> 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());
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());
return;
}
} catch(InterruptedException | ExecutionException | TimeoutException e) {
ModernFix.LOGGER.error("Async chunk load took way too long, this needs to be reported to the appropriate mod.", e);
}
//cir.setReturnValue(new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ)));
}
}
}
}

View File

@ -1,110 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import com.mojang.datafixers.util.Either;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.Material;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.duck.ICachedMaterialsModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@Mixin(BlockModel.class)
@ClientOnlyMixin
public class BlockModelMixin {
@Shadow @Final @Mutable public Map<String, Either<Material, String>> textureMap;
/**
* @author embeddedt
* @reason detect changes to the texture map, and clear the material cache as needed
*/
@Inject(method = "<init>", at = @At("RETURN"))
private void useTrackingTextureMap(CallbackInfo ci) {
Map<String, Either<Material, String>> backingMap = this.textureMap;
ICachedMaterialsModel cacheHolder = (ICachedMaterialsModel)this;
this.textureMap = new Map<String, Either<Material, String>>() {
@Override
public int size() {
return backingMap.size();
}
@Override
public boolean isEmpty() {
return backingMap.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return backingMap.containsKey(o);
}
@Override
public boolean containsValue(Object o) {
return backingMap.containsValue(o);
}
@Override
public Either<Material, String> get(Object o) {
return backingMap.get(o);
}
@Nullable
@Override
public Either<Material, String> put(String s, Either<Material, String> materialStringEither) {
Either<Material, String> old = backingMap.put(s, materialStringEither);
cacheHolder.clearMaterialsCache();
return old;
}
@Override
public Either<Material, String> remove(Object o) {
Either<Material, String> e = backingMap.remove(o);
cacheHolder.clearMaterialsCache();
return e;
}
@Override
public void putAll(@NotNull Map<? extends String, ? extends Either<Material, String>> map) {
backingMap.putAll(map);
cacheHolder.clearMaterialsCache();
}
@Override
public void clear() {
backingMap.clear();
cacheHolder.clearMaterialsCache();
}
@NotNull
@Override
public Set<String> keySet() {
cacheHolder.clearMaterialsCache();
return backingMap.keySet();
}
@NotNull
@Override
public Collection<Either<Material, String>> values() {
cacheHolder.clearMaterialsCache();
return backingMap.values();
}
@NotNull
@Override
public Set<Entry<String, Either<Material, String>>> entrySet() {
cacheHolder.clearMaterialsCache();
return backingMap.entrySet();
}
};
}
}

View File

@ -1,28 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import net.minecraft.client.renderer.block.model.multipart.MultiPart;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Collection;
@Mixin(MultiPart.class)
@ClientOnlyMixin
public class MultipartMixin {
private Collection<ResourceLocation> dependencyCache = null;
@Inject(method = "getDependencies", at = @At("HEAD"), cancellable = true)
private void useDependencyCache(CallbackInfoReturnable<Collection<ResourceLocation>> cir) {
if(dependencyCache != null)
cir.setReturnValue(dependencyCache);
}
@Inject(method = "getDependencies", at = @At("RETURN"))
private void storeDependencyCache(CallbackInfoReturnable<Collection<ResourceLocation>> cir) {
if(dependencyCache == null)
dependencyCache = cir.getReturnValue();
}
}

View File

@ -1,43 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_model_materials;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.duck.ICachedMaterialsModel;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
/* only cache BlockModel to prevent issues with CTM on Fabric */
@Mixin(value = {BlockModel.class})
@ClientOnlyMixin
public class VanillaModelMixin implements ICachedMaterialsModel {
private Collection<Material> materialsCache = null;
@Inject(method = "getMaterials", at = @At("HEAD"), cancellable = true)
private void useCachedMaterials(Function<ResourceLocation, UnbakedModel> pModelGetter, Set<Pair<String, String>> pMissingTextureErrors, CallbackInfoReturnable<Collection<Material>> cir) {
if(materialsCache != null) {
cir.setReturnValue(materialsCache);
}
}
@Inject(method = "getMaterials", at = @At("RETURN"))
private void storeCachedMaterials(Function<ResourceLocation, UnbakedModel> pModelGetter, Set<Pair<String, String>> pMissingTextureErrors, CallbackInfoReturnable<Collection<Material>> cir) {
if(materialsCache == null)
materialsCache = Collections.unmodifiableCollection(cir.getReturnValue());
}
@Override
public void clearMaterialsCache() {
materialsCache = null;
}
}

View File

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

View File

@ -1,69 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.storage.DimensionDataStorage;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
@Mixin(ServerLevel.class)
public abstract class ServerLevelMixin extends Level implements IServerLevel {
protected ServerLevelMixin(WritableLevelData arg, ResourceKey<Level> arg2, Holder<DimensionType> arg3, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l, int i) {
super(arg, arg2, arg3, supplier, bl, bl2, l, i);
}
@Shadow public abstract DimensionDataStorage getDataStorage();
@Shadow @Final private ServerChunkCache chunkSource;
private StrongholdLocationCache mfix$strongholdCache;
/**
* Initialize the stronghold cache but don't force any structure generation yet.
*/
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkGenerator;ensureStructuresGenerated(Lnet/minecraft/world/level/levelgen/RandomState;)V"))
private void hookStrongholdCache(ChunkGenerator generator, RandomState state) {
((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this);
}
/**
* Now start the stronghold generation process.
*/
@Inject(method = "<init>", at = @At("TAIL"))
private void ensureGeneration(MinecraftServer minecraftServer, Executor executor, LevelStorageSource.LevelStorageAccess arg, ServerLevelData arg2, ResourceKey<Level> arg3, LevelStem arg4, ChunkProgressListener arg5, boolean bl, long l, List<CustomSpawner> list, boolean bl2, CallbackInfo ci) {
mfix$strongholdCache = this.getDataStorage().computeIfAbsent(StrongholdLocationCache::load,
StrongholdLocationCache::new,
StrongholdLocationCache.getFileId(this.dimensionTypeRegistration()));
this.chunkSource.getGenerator().ensureStructuresGenerated(this.chunkSource.randomState());
}
@Override
public StrongholdLocationCache mfix$getStrongholdCache() {
return mfix$strongholdCache;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,23 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import net.minecraft.client.renderer.block.model.BlockElementFace;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.dynamicresources.UVController;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.lang.reflect.Type;
@Mixin(BlockElementFace.Deserializer.class)
@ClientOnlyMixin
public class BlockElementFaceDeserializerMixin {
@Redirect(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/renderer/block/model/BlockElementFace;",
at = @At(value = "INVOKE", target = "Lcom/google/gson/JsonDeserializationContext;deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;)Ljava/lang/Object;", ordinal = 0, remap = false))
private Object skipUvsForInitialLoad(JsonDeserializationContext context, JsonElement element, Type type) {
return UVController.useDummyUv.get() ? UVController.dummyUv : context.deserialize(element, type);
}
}

View File

@ -1,28 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
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.util.HashMap;
import java.util.Map;
@Mixin(ModelManager.class)
@ClientOnlyMixin
public class ModelManagerMixin {
@Shadow private Map<ResourceLocation, BakedModel> bakedRegistry;
@Inject(method = "<init>", at = @At("RETURN"))
private void injectDummyBakedRegistry(CallbackInfo ci) {
if(this.bakedRegistry == null) {
// Create a dummy baked registry. This prevents NPEs when mods query block models too early
this.bakedRegistry = new HashMap<>();
}
}
}

View File

@ -1,46 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.ae2;
import appeng.core.AppEng;
import appeng.init.client.InitAutoRotatingModel;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
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.util.Map;
import java.util.function.Function;
@Mixin(InitAutoRotatingModel.class)
@RequiresMod("ae2")
@ClientOnlyMixin
public class RegistrationMixin {
@Shadow(remap = false) @Final private static Map<String, Function<BakedModel, BakedModel>> CUSTOMIZERS;
@Inject(method = "init", at = @At("TAIL"), remap = false)
private static void doRegisterDynBake(CallbackInfo ci) {
ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
@Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
if(location.getNamespace().equals(AppEng.MOD_ID)) {
BakedModel m = bakery.bake(ModelBakery.MISSING_MODEL_LOCATION, BlockModelRotation.X0_Y0);
if(originalModel == m)
return originalModel;
Function<BakedModel, BakedModel> customizerFn = CUSTOMIZERS.get(location.getPath());
if(customizerFn != null)
originalModel = customizerFn.apply(originalModel);
}
return originalModel;
}
});
}
}

View File

@ -1,52 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources.diagonalfences;
import fuzs.diagonalfences.api.world.level.block.DiagonalBlock;
import fuzs.diagonalfences.client.model.MultipartAppender;
import fuzs.diagonalfences.mixin.client.accessor.ModelBakeryAccessor;
import net.minecraft.client.renderer.block.model.multipart.MultiPart;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.FenceBlock;
import net.minecraft.world.level.block.IronBarsBlock;
import org.apache.logging.log4j.util.BiConsumer;
import org.embeddedt.modernfix.ModernFixClient;
import org.embeddedt.modernfix.annotation.RequiresMod;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
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(MultipartAppender.class)
@RequiresMod("diagonalfences")
public abstract class MultipartAppenderMixin {
@Shadow(remap = false)
public static void appendDiagonalSelectors(BiConsumer<ResourceLocation, UnbakedModel> modelBakery, MultiPart multiPart, boolean rotateCenter) {
throw new AssertionError();
}
private static boolean handlerInjected = false;
@Inject(method = "onPrepareModelBaking", at = @At("HEAD"), cancellable = true)
private static void setupHelper(CallbackInfo ci) {
ci.cancel();
if(handlerInjected)
return;
handlerInjected = true;
ModernFixClient.CLIENT_INTEGRATIONS.add(new ModernFixClientIntegration() {
@Override
public UnbakedModel onUnbakedModelLoad(ResourceLocation location, UnbakedModel originalModel, ModelBakery bakery) {
if(originalModel instanceof MultiPart multipart) {
Block block = multipart.definition.getOwner();
if((block instanceof FenceBlock || block instanceof IronBarsBlock) && block instanceof DiagonalBlock diagonalBlock && diagonalBlock.hasProperties()) {
appendDiagonalSelectors(((ModelBakeryAccessor)bakery)::diagonalfences$callCacheAndQueueDependencies, multipart, block instanceof IronBarsBlock);
}
}
return originalModel;
}
});
}
}

View File

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

View File

@ -1,71 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_font_loading;
import com.mojang.blaze3d.platform.NativeImage;
import net.minecraft.client.gui.font.providers.LegacyUnicodeBitmapsProvider;
import net.minecraft.resources.ResourceLocation;
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.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.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* Objective: avoid recomputing locations many times, as well as loading all the font sheets in the constructor
* only to do it again later.
*/
@Mixin(LegacyUnicodeBitmapsProvider.class)
@ClientOnlyMixin
public abstract class LegacyUnicodeBitmapsProviderMixin {
@Shadow protected abstract ResourceLocation getSheetLocation(int i);
@Shadow @Final private Map<ResourceLocation, NativeImage> textures;
private final ResourceLocation[] glyphLocations = new ResourceLocation[256];
private ResourceLocation currentCharIdx;
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/font/providers/LegacyUnicodeBitmapsProvider;getSheetLocation(I)Lnet/minecraft/resources/ResourceLocation;"))
private ResourceLocation storeCurrentCharIdx(LegacyUnicodeBitmapsProvider provider, int i) {
ResourceLocation location = getSheetLocation(i);
currentCharIdx = location;
return location;
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/NativeImage;read(Lcom/mojang/blaze3d/platform/NativeImage$Format;Ljava/io/InputStream;)Lcom/mojang/blaze3d/platform/NativeImage;"))
private NativeImage storeLoadedFontSheet(NativeImage.Format format, InputStream stream) throws IOException {
NativeImage image = NativeImage.read(format, stream);
textures.put(currentCharIdx, image);
return image;
}
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/NativeImage;close()V"))
private void skipCloseNativeImage(NativeImage image) {
/* we can't close here, as the image has been stored for use later */
}
@Inject(method = "<init>", at = @At("RETURN"))
private void clearLocation(CallbackInfo ci) {
currentCharIdx = null;
}
@Inject(method = "getSheetLocation", at = @At("HEAD"), cancellable = true)
private void useCachedLocation(int idx, CallbackInfoReturnable<ResourceLocation> cir) {
int cachedIdx = idx / 256;
if(cachedIdx >= 0 && cachedIdx < glyphLocations.length && glyphLocations[cachedIdx] != null)
cir.setReturnValue(glyphLocations[cachedIdx]);
}
@Inject(method = "getSheetLocation", at = @At("RETURN"))
private void saveCachedLocation(int idx, CallbackInfoReturnable<ResourceLocation> cir) {
int cachedIdx = idx / 256;
if(cachedIdx >= 0 && cachedIdx < glyphLocations.length)
glyphLocations[cachedIdx] = cir.getReturnValue();
}
}

View File

@ -1,17 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_structure_location;
import net.minecraft.core.Holder;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
@Mixin(ChunkGenerator.class)
public interface ChunkGeneratorAccessor {
@Invoker("getPlacementsForStructure")
List<StructurePlacement> invokeGetPlacementsForStructure(Holder<Structure> structure, RandomState random);
}

View File

@ -1,127 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.faster_texture_loading;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import org.apache.commons.io.IOUtils;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@Mixin(value = TextureAtlas.class, priority = 600)
@ClientOnlyMixin
public abstract class TextureAtlasMixin {
@Shadow protected abstract ResourceLocation getResourceLocation(ResourceLocation location);
@Shadow protected abstract Collection<TextureAtlasSprite.Info> getBasicSpriteInfos(ResourceManager resourceManager, Set<ResourceLocation> spriteLocations);
private Map<ResourceLocation, Pair<Resource, NativeImage>> loadedImages = new ConcurrentHashMap<>();
private boolean usingFasterLoad;
private Collection<TextureAtlasSprite.Info> storedResults;
/**
* @author embeddedt
* @reason simplify texture loading by loading whole image once, avoid slow PngInfo code
*/
@Inject(method = "getBasicSpriteInfos", at = @At("HEAD"))
private void loadImages(ResourceManager manager, Set<ResourceLocation> imageLocations, CallbackInfoReturnable<Collection<TextureAtlasSprite.Info>> cir) {
usingFasterLoad = ModernFixPlatformHooks.INSTANCE.isLoadingNormally();
}
@Redirect(method = "getBasicSpriteInfos", at = @At(value = "INVOKE", target = "Ljava/util/Set;iterator()Ljava/util/Iterator;", ordinal = 0))
private Iterator<?> skipIteration(Set<?> instance, ResourceManager manager, Set<ResourceLocation> imageLocations) {
// bail if Forge is erroring to avoid AT crashes
if(!usingFasterLoad)
return instance.iterator();
List<CompletableFuture<?>> futures = new ArrayList<>();
ConcurrentLinkedQueue<TextureAtlasSprite.Info> results = new ConcurrentLinkedQueue<>();
for(ResourceLocation location : imageLocations) {
if(MissingTextureAtlasSprite.getLocation().equals(location))
continue;
futures.add(CompletableFuture.runAsync(() -> {
InputStream stream = null;
try {
ResourceLocation fileLocation = this.getResourceLocation(location);
Optional<Resource> resourceOpt = manager.getResource(fileLocation);
if(!resourceOpt.isPresent()) {
ModernFix.LOGGER.error("Using missing texture, unable to load {}", location);
return;
}
Resource resource = resourceOpt.get();
stream = resource.open();
NativeImage image = NativeImage.read(stream);
AnimationMetadataSection animData = resource.metadata().getSection(AnimationMetadataSection.SERIALIZER).orElse(AnimationMetadataSection.EMPTY);
Pair<Integer, Integer> dimensions = animData.getFrameSize(image.getWidth(), image.getHeight());
loadedImages.put(location, Pair.of(resource, image));
results.add(new TextureAtlasSprite.Info(location, dimensions.getFirst(), dimensions.getSecond(), animData));
stream.close();
stream = null;
} catch(IOException e) {
ModernFix.LOGGER.error("Using missing texture, unable to load {} : {}", location, e);
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Unable to parse metadata from {} : {}", location, e);
}
if(stream != null)
IOUtils.closeQuietly(stream);
}, ModernFix.resourceReloadExecutor()));
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
storedResults = results;
return Collections.emptyIterator();
}
@Inject(method = "getBasicSpriteInfos", at = @At("RETURN"))
private void injectFastSprites(ResourceManager resourceManager, Set<ResourceLocation> spriteLocations, CallbackInfoReturnable<Collection<TextureAtlasSprite.Info>> cir) {
if(usingFasterLoad)
cir.getReturnValue().addAll(storedResults);
}
@Inject(method = "prepareToStitch", at = @At("HEAD"))
private void initMap(CallbackInfoReturnable<TextureAtlas.Preparations> cir) {
loadedImages = new ConcurrentHashMap<>();
}
@Inject(method = "prepareToStitch", at = @At("RETURN"))
private void clearLoadedImages(CallbackInfoReturnable<TextureAtlas.Preparations> cir) {
loadedImages = Collections.emptyMap();
storedResults = null;
}
@Inject(method = "load(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIII)Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/TextureAtlas;getResourceLocation(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/resources/ResourceLocation;"), cancellable = true)
private void loadFromExisting(ResourceManager resourceManager, TextureAtlasSprite.Info spriteInfo, int storageX, int storageY, int mipLevel, int x, int y, CallbackInfoReturnable<TextureAtlasSprite> cir) {
if(!usingFasterLoad)
return;
Pair<Resource, NativeImage> pair = loadedImages.get(spriteInfo.name());
if(pair == null) {
ModernFix.LOGGER.error("Texture {} was not loaded in early stage", spriteInfo.name());
cir.setReturnValue(null);
} else {
TextureAtlasSprite sprite = null;
try {
sprite = ModernFixPlatformHooks.INSTANCE.loadTextureAtlasSprite((TextureAtlas)(Object)this, resourceManager, spriteInfo, pair.getFirst(), storageX, storageY, x, y, mipLevel, pair.getSecond());
} catch(RuntimeException | IOException e) {
ModernFix.LOGGER.error("Error loading texture {}: {}", spriteInfo.name(), e);
}
cir.setReturnValue(sprite);
}
}
}

View File

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

View File

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

View File

@ -1,20 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.nbt_memory_usage;
import net.minecraft.nbt.Tag;
import org.embeddedt.modernfix.util.CanonizingStringMap;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import java.util.Map;
@Mixin(targets = "net/minecraft/nbt/CompoundTag$1")
public class CompoundTag1Mixin {
@ModifyVariable(method = "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) {
CanonizingStringMap<Tag> newMap = new CanonizingStringMap<>();
if(map != null)
newMap.putAll(map);
return newMap;
}
}

View File

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

View File

@ -1,61 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.embeddedt.modernfix.duck.IBlockState;
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.Redirect;
@Mixin(BlockBehaviour.BlockStateBase.class)
public abstract class BlockStateBaseMixin implements IBlockState {
@Shadow public abstract void initCache();
@Shadow private BlockBehaviour.BlockStateBase.Cache cache;
private volatile boolean cacheInvalid = false;
private static boolean buildingCache = false;
@Override
public void clearCache() {
cacheInvalid = true;
}
@Override
public boolean isCacheInvalid() {
return cacheInvalid;
}
private void mfix$generateCache() {
if(cacheInvalid) {
// Ensure that only one block's cache is built at a time
synchronized (BlockBehaviour.BlockStateBase.class) {
if(cacheInvalid) {
// Ensure that if we end up in here recursively, we just use the original cache
if(!buildingCache) {
buildingCache = true;
try {
this.initCache();
cacheInvalid = false;
} finally {
buildingCache = false;
}
}
}
}
}
}
@Redirect(method = "*", at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;",
ordinal = 0
))
private BlockBehaviour.BlockStateBase.Cache dynamicCacheGen(BlockBehaviour.BlockStateBase base) {
mfix$generateCache();
return this.cache;
}
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuilds;
import net.minecraft.world.level.block.Blocks;
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.ModifyArg;
import java.util.function.Consumer;
@Mixin(value = Blocks.class, priority = 1100)
public class BlocksMixin {
@ModifyArg(method = "rebuildCache", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/IdMapper;forEach(Ljava/util/function/Consumer;)V"), index = 0)
private static Consumer getEmptyConsumer(Consumer original) {
BlockStateCacheHandler.rebuildParallel(true);
return o -> {};
}
}

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

View File

@ -1,28 +0,0 @@
package org.embeddedt.modernfix.common.mixin.safety;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import java.util.List;
@Mixin(LivingEntityRenderer.class)
@ClientOnlyMixin
public class LivingEntityRendererMixin {
@Shadow @Final @Mutable
protected List<RenderLayer<?, ?>> layers;
@Inject(method = "<init>", at = @At("RETURN"))
private void synchronizeLayerList(CallbackInfo ci) {
/* allows buggy mods to call addLayer concurrently, order is not deterministic but can't fix that */
this.layers = Collections.synchronizedList(layers);
}
}

View File

@ -1,9 +0,0 @@
package org.embeddedt.modernfix.dedup;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import net.minecraft.world.level.biome.Climate;
public class ClimateCache {
public static final Interner<Climate.Parameter> MFIX_INTERNER = Interners.newStrongInterner();
}

View File

@ -1,56 +0,0 @@
package org.embeddedt.modernfix.dedup;
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
import java.util.Objects;
public class DeduplicationCache<T> {
private final ObjectOpenCustomHashSet<T> pool;
private int attemptedInsertions = 0;
private int deduplicated = 0;
public DeduplicationCache(Hash.Strategy<T> strategy) {
this.pool = new ObjectOpenCustomHashSet<>(strategy);
}
public DeduplicationCache() {
this.pool = new ObjectOpenCustomHashSet<>(new Hash.Strategy<T>() {
@Override
public int hashCode(T o) {
return Objects.hashCode(o);
}
@Override
public boolean equals(T a, T b) {
return Objects.equals(a, b);
}
});
}
public synchronized T deduplicate(T item) {
this.attemptedInsertions++;
T result = this.pool.addOrGet(item);
if (result != item) {
this.deduplicated++;
}
return result;
}
public synchronized void clearCache() {
this.attemptedInsertions = 0;
this.deduplicated = 0;
this.pool.clear();
}
@Override
public synchronized String toString() {
return String.format("DeduplicationCache ( %d/%d de-duplicated, %d pooled )",
this.deduplicated, this.attemptedInsertions, this.pool.size());
}
}

View File

@ -1,16 +0,0 @@
package org.embeddedt.modernfix.dedup;
import org.embeddedt.modernfix.ModernFix;
public class IdentifierCaches {
public static final DeduplicationCache<String> NAMESPACES = new DeduplicationCache<>();
public static final DeduplicationCache<String> PATH = new DeduplicationCache<>();
public static final DeduplicationCache<String> PROPERTY = new DeduplicationCache<>();
public static void printDebug() {
ModernFix.LOGGER.info("[[[ Identifier de-duplication statistics ]]]");
ModernFix.LOGGER.info("Namespace cache: {}", NAMESPACES);
ModernFix.LOGGER.info("Path cache: {}", PATH);
}
}

View File

@ -1,68 +0,0 @@
package org.embeddedt.modernfix.dfu;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.datafixers.RewriteResult;
import com.mojang.datafixers.TypeRewriteRule;
import com.mojang.datafixers.functions.PointFreeRule;
import com.mojang.datafixers.types.Type;
import com.mojang.datafixers.util.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.embeddedt.modernfix.ModernFix;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.IntFunction;
public class DFUBlaster {
private static final Cache<Pair<IntFunction<RewriteResult<?, ?>>, Integer>, RewriteResult<?, ?>> hmapApplyCache = CacheBuilder.newBuilder()
.expireAfterAccess(3, TimeUnit.MINUTES)
.build();
private static final Cache<Triple<Type<?>, TypeRewriteRule, PointFreeRule>, Optional<? extends RewriteResult<?, ?>>> rewriteCache = CacheBuilder.newBuilder()
.expireAfterAccess(3, TimeUnit.MINUTES)
.build();
public static void blastMaps() {
try {
Class<?> FOLD_CLASS = Class.forName("com.mojang.datafixers.functions.Fold");
Field hmapField = FOLD_CLASS.getDeclaredField("HMAP_APPLY_CACHE");
hmapField.setAccessible(true);
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe)theUnsafe.get(null);
Object base = unsafe.staticFieldBase(hmapField);
long offset = unsafe.staticFieldOffset(hmapField);
unsafe.putObject(base, offset, hmapApplyCache.asMap());
Field rewriteCacheField = Type.class.getDeclaredField("REWRITE_CACHE");
rewriteCacheField.setAccessible(true);
base = unsafe.staticFieldBase(rewriteCacheField);
offset = unsafe.staticFieldOffset(rewriteCacheField);
unsafe.putObject(base, offset, rewriteCache.asMap());
new CleanerThread().start();
} catch(Throwable e) {
ModernFix.LOGGER.error("Could not replace DFU map", e);
}
}
static class CleanerThread extends Thread {
CleanerThread() {
this.setName("DFU cleaning thread");
this.setPriority(1);
this.setDaemon(true);
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(15000);
} catch(InterruptedException e){
return;
}
rewriteCache.cleanUp();
hmapApplyCache.cleanUp();
}
}
}
}

View File

@ -1,5 +0,0 @@
package org.embeddedt.modernfix.duck;
public interface ICachedMaterialsModel {
public void clearMaterialsCache();
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.duck;
import net.minecraft.server.level.ServerLevel;
public interface IChunkGenerator {
void mfix$setAssociatedServerLevel(ServerLevel level);
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.duck;
import net.minecraft.world.level.storage.LevelStorageSource;
public interface ILevelSave {
public void runWorldPersistenceHooks(LevelStorageSource format);
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.duck;
import org.embeddedt.modernfix.chunk.SafeBlockGetter;
public interface ISafeBlockGetter {
SafeBlockGetter mfix$getSafeBlockGetter();
}

View File

@ -1,7 +0,0 @@
package org.embeddedt.modernfix.duck;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
public interface IServerLevel {
StrongholdLocationCache mfix$getStrongholdCache();
}

View File

@ -1,10 +0,0 @@
package org.embeddedt.modernfix.duck.reuse_datapacks;
import net.minecraft.server.ReloadableServerResources;
import java.util.Collection;
public interface ICachingResourceClient {
void setCachedResources(ReloadableServerResources r);
void setCachedDataPackConfig(Collection<String> c);
}

View File

@ -1,8 +0,0 @@
package org.embeddedt.modernfix.dynamicresources;
public class DynamicSoundHelpers {
/**
* The duration until a sound is eligible for eviction if unused.
*/
public static final int MAX_SOUND_LIFETIME_SECS = 300;
}

View File

@ -1,404 +0,0 @@
package org.embeddedt.modernfix.dynamicresources;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceSet;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.FallbackResourceManager;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static net.minecraft.client.resources.model.ModelBakery.BLOCK_ENTITY_MARKER;
import static net.minecraft.client.resources.model.ModelBakery.GENERATION_MARKER;
public class ModelBakeryHelpers {
/**
* The maximum number of baked models kept in memory at once.
*/
public static final int MAX_BAKED_MODEL_COUNT = 10000;
/**
* The maximum number of unbaked models kept in memory at once.
*/
public static final int MAX_UNBAKED_MODEL_COUNT = 10000;
/**
* The time in seconds after which a model becomes eligible for eviction if not used.
*/
public static final int MAX_MODEL_LIFETIME_SECS = 300;
/**
* These folders will have all textures stitched onto the atlas when dynamic resources is enabled.
*/
public static String[] getExtraTextureFolders() {
return new String[] {
"attachment",
"bettergrass",
"block",
"blocks",
"cape",
"entity/bed",
"entity/chest",
"item",
"items",
"model",
"models",
"part",
"pipe",
"ropebridge",
"runes",
"solid_block",
"spell_effect",
"spell_projectile"
};
}
private static JsonElement parseStream(InputStream stream) {
JsonParser parser = new JsonParser();
JsonReader jsonReader = new JsonReader(new InputStreamReader(stream, StandardCharsets.UTF_8));
jsonReader.setLenient(true);
return parser.parse(jsonReader);
}
private static void gatherAdditionalViaManualScan(List<PackResources> untrustedPacks, Set<ResourceLocation> knownLocations,
Collection<ResourceLocation> uncertainLocations, String filePrefix) {
if(untrustedPacks.size() > 0) {
/* Now make a fallback resource manager and use it on the remaining packs to see if they actually contain these files */
FallbackResourceManager frm = new FallbackResourceManager(PackType.CLIENT_RESOURCES, "dummy");
for (int i = untrustedPacks.size() - 1; i >= 0; i--) {
frm.push(untrustedPacks.get(i));
}
for (ResourceLocation blockstate : uncertainLocations) {
if (knownLocations.contains(blockstate))
continue; // don't check ones we know exist
ResourceLocation fileLocation = new ResourceLocation(blockstate.getNamespace(), filePrefix + blockstate.getPath() + ".json");
Optional<Resource> resource = frm.getResource(fileLocation);
if(resource.isPresent())
knownLocations.add(blockstate);
}
}
}
private static final int ERROR_THRESHOLD = 200;
private static void logOrSuppressError(Object2IntOpenHashMap<String> suppressionMap, String type, ResourceLocation location, Throwable e) {
int numErrors;
synchronized (suppressionMap) {
numErrors = suppressionMap.computeInt(location.getNamespace(), (k, oldVal) -> (oldVal == null ? 1 : oldVal + 1));
}
if(numErrors <= ERROR_THRESHOLD)
ModernFix.LOGGER.error("Error reading {} {}: {}", type, location, e);
}
/**
* Some mods (cough, EBE) inject their custom resource pack into the namespaced resource managers, but not into the
* main list contained inside the parent resource manager, so we need to scan each of the namespaced managers as
* well.
*/
private static void checkFallbacks(MultiPackResourceManager manager, List<PackResources> resourcePackList) {
ReferenceSet<PackResources> knownPacks = new ReferenceOpenHashSet<>(resourcePackList);
Map<String, FallbackResourceManager> namespacedMap = manager.namespacedManagers;
namespacedMap.values().stream().flatMap(FallbackResourceManager::listPacks).forEach(pack -> {
if(knownPacks.add(pack)) {
/* the pack was not previously known, add to our list */
ModernFix.LOGGER.debug("Injecting unlisted pack '{}': {}", pack.getName(), pack.getClass().getName());
resourcePackList.add(pack);
}
});
}
public static void gatherModelMaterials(ResourceManager manager, Predicate<PackResources> isTrustedPack,
Set<Material> materialSet, Set<ResourceLocation> blockStateFiles,
Set<ResourceLocation> modelFiles, UnbakedModel missingModel,
Function<JsonElement, BlockModel> modelDeserializer,
Function<ResourceLocation, UnbakedModel> bakeryModelGetter) {
if(!ModernFixPlatformHooks.INSTANCE.isLoadingNormally())
return;
Stopwatch stopwatch = Stopwatch.createStarted();
final Object2IntOpenHashMap<String> blockstateErrors = new Object2IntOpenHashMap<>();
/*
* First, gather all vanilla packs, and use listResources on them. This will allow us to (hopefully) avoid
* scanning most packs a lot.
*/
List<PackResources> allPackResources = new ArrayList<>(manager.listPacks().collect(Collectors.toList()));
if(manager instanceof MultiPackResourceManager) {
checkFallbacks((MultiPackResourceManager)manager, allPackResources);
}
Collections.reverse(allPackResources);
ObjectOpenHashSet<ResourceLocation> allAvailableModels = new ObjectOpenHashSet<>(), allAvailableStates = new ObjectOpenHashSet<>();
/* try to fix CME in some runtime packs by forcing generation */
for(PackResources pack : allPackResources) {
try(InputStream stream = pack.getResource(PackType.CLIENT_RESOURCES, new ResourceLocation("modernfix", "dummy.json"))) {
} catch(Exception ignored) {
}
}
allPackResources.removeIf(pack -> {
for(String namespace : pack.getNamespaces(PackType.CLIENT_RESOURCES)) {
Collection<ResourceLocation> allBlockstates = pack.getResources(PackType.CLIENT_RESOURCES, namespace, "blockstates", p -> p.getPath().endsWith(".json"));
for(ResourceLocation blockstate : allBlockstates) {
allAvailableStates.add(new ResourceLocation(blockstate.getNamespace(), blockstate.getPath().replaceFirst("blockstates/", "").replace(".json", "")));
}
Collection<ResourceLocation> allModels = pack.getResources(PackType.CLIENT_RESOURCES, namespace, "models", p -> p.getPath().endsWith(".json"));
for(ResourceLocation blockstate : allModels) {
allAvailableModels.add(new ResourceLocation(blockstate.getNamespace(), blockstate.getPath().replaceFirst("models/", "").replace(".json", "")));
}
}
if(!isTrustedPack.test(pack)) {
ModernFix.LOGGER.debug("Pack with class {} needs manual scan", pack.getClass().getName());
return false;
}
return true;
});
gatherAdditionalViaManualScan(allPackResources, allAvailableStates, blockStateFiles, "blockstates/");
// We now have a list of all blockstates known to exist. Delete anything that we don't have
blockStateFiles.retainAll(allAvailableStates);
allAvailableStates.clear();
allAvailableStates.trim();
ConcurrentLinkedQueue<Pair<ResourceLocation, JsonElement>> blockStateLoadedFiles = new ConcurrentLinkedQueue<>();
List<CompletableFuture<Void>> blockStateData = new ArrayList<>();
for(ResourceLocation blockstate : blockStateFiles) {
ResourceLocation fileLocation = new ResourceLocation(blockstate.getNamespace(), "blockstates/" + blockstate.getPath() + ".json");
List<Resource> resources = manager.getResourceStack(fileLocation);
if(resources.isEmpty())
continue;
blockStateData.add(CompletableFuture.runAsync(() -> {
try {
for(Resource resource : resources) {
JsonParser parser = new JsonParser();
try(InputStream stream = resource.open()) {
blockStateLoadedFiles.add(Pair.of(blockstate, parseStream(stream)));
} catch(JsonParseException e) {
logOrSuppressError(blockstateErrors, "blockstate", blockstate, e);
}
}
} catch(IOException e) {
logOrSuppressError(blockstateErrors, "blockstate", blockstate, e);
}
}, ModernFix.resourceReloadExecutor()));
}
blockStateFiles = null;
CompletableFuture.allOf(blockStateData.toArray(new CompletableFuture[0])).join();
for(Pair<ResourceLocation, JsonElement> pair : blockStateLoadedFiles) {
if(pair.getSecond() != null) {
try {
JsonObject obj = pair.getSecond().getAsJsonObject();
if(obj.has("variants")) {
JsonObject eachVariant = obj.getAsJsonObject("variants");
for(Map.Entry<String, JsonElement> entry : eachVariant.entrySet()) {
JsonElement variantData = entry.getValue();
List<JsonObject> variantModels;
if(variantData.isJsonArray()) {
variantModels = new ArrayList<>();
for(JsonElement model : variantData.getAsJsonArray()) {
variantModels.add(model.getAsJsonObject());
}
} else
variantModels = Collections.singletonList(variantData.getAsJsonObject());
for(JsonObject variant : variantModels) {
modelFiles.add(new ResourceLocation(variant.get("model").getAsString()));
}
}
} else {
JsonArray multipartData = obj.get("multipart").getAsJsonArray();
for(JsonElement element : multipartData) {
JsonObject self = element.getAsJsonObject();
JsonElement apply = self.get("apply");
List<JsonObject> applyObjects;
if(apply.isJsonArray()) {
applyObjects = new ArrayList<>();
for(JsonElement e : apply.getAsJsonArray()) {
applyObjects.add(e.getAsJsonObject());
}
} else
applyObjects = Collections.singletonList(apply.getAsJsonObject());
for(JsonObject applyEntry : applyObjects) {
modelFiles.add(new ResourceLocation(applyEntry.get("model").getAsString()));
}
}
}
} catch(RuntimeException e) {
logOrSuppressError(blockstateErrors, "blockstate", pair.getFirst(), e);
}
}
}
blockstateErrors.object2IntEntrySet().forEach(entry -> {
if(entry.getIntValue() > ERROR_THRESHOLD) {
ModernFix.LOGGER.error("Suppressed additional {} blockstate errors for domain {}", entry.getIntValue(), entry.getKey());
}
});
blockstateErrors.clear();
blockStateData = null;
blockStateLoadedFiles.clear();
modelFiles.addAll(allAvailableModels);
/* figure out which models we should actually load */
gatherAdditionalViaManualScan(allPackResources, allAvailableModels, modelFiles, "models/");
modelFiles.retainAll(allAvailableModels);
allAvailableModels.clear();
allAvailableModels.trim();
Map<ResourceLocation, BlockModel> basicModels = new HashMap<>();
basicModels.put(ModelBakery.MISSING_MODEL_LOCATION, (BlockModel)missingModel);
basicModels.put(new ResourceLocation("builtin/generated"), GENERATION_MARKER);
basicModels.put(new ResourceLocation("builtin/entity"), BLOCK_ENTITY_MARKER);
Set<Pair<String, String>> errorSet = Sets.newLinkedHashSet();
while(modelFiles.size() > 0) {
List<CompletableFuture<Pair<ResourceLocation, JsonElement>>> modelBytes = new ArrayList<>();
for(ResourceLocation model : modelFiles) {
if(basicModels.containsKey(model))
continue;
ResourceLocation fileLocation = new ResourceLocation(model.getNamespace(), "models/" + model.getPath() + ".json");
modelBytes.add(CompletableFuture.supplyAsync(() -> {
Optional<Resource> resource = manager.getResource(fileLocation);
try(InputStream stream = resource.orElseThrow().open()) {
return Pair.of(model, parseStream(stream));
} catch(IOException | NoSuchElementException | JsonParseException e) {
logOrSuppressError(blockstateErrors, "model", fileLocation, e);
return Pair.of(fileLocation, null);
}
}, ModernFix.resourceReloadExecutor()));
}
modelFiles.clear();
CompletableFuture.allOf(modelBytes.toArray(new CompletableFuture[0])).join();
UVController.useDummyUv.set(Boolean.TRUE);
for(CompletableFuture<Pair<ResourceLocation, JsonElement>> future : modelBytes) {
Pair<ResourceLocation, JsonElement> pair = future.join();
try {
if(pair.getSecond() != null) {
BlockModel model = modelDeserializer.apply(pair.getSecond());
model.name = pair.getFirst().toString();
modelFiles.addAll(model.getDependencies());
basicModels.put(pair.getFirst(), model);
continue;
}
} catch(Throwable e) {
logOrSuppressError(blockstateErrors, "model", pair.getFirst(), e);
}
basicModels.put(pair.getFirst(), (BlockModel)missingModel);
}
UVController.useDummyUv.set(Boolean.FALSE);
}
blockstateErrors.object2IntEntrySet().forEach(entry -> {
if(entry.getIntValue() > ERROR_THRESHOLD) {
ModernFix.LOGGER.error("Suppressed additional {} model errors for domain {}", entry.getIntValue(), entry.getKey());
}
});
blockstateErrors.clear();
modelFiles = null;
Function<ResourceLocation, UnbakedModel> modelGetter = loc -> {
UnbakedModel m = basicModels.get(loc);
/* fallback to vanilla loader if missing */
return m != null ? m : bakeryModelGetter.apply(loc);
};
for(BlockModel model : basicModels.values()) {
try {
materialSet.addAll(model.getMaterials(modelGetter, errorSet));
} catch(Throwable e) {
ModernFix.LOGGER.error("Model {} threw error while getting materials", model.name, e);
}
}
//errorSet.stream().filter(pair -> !pair.getSecond().equals(MISSING_MODEL_LOCATION_STRING)).forEach(pair -> LOGGER.warn("Unable to resolve texture reference: {} in {}", pair.getFirst(), pair.getSecond()));
stopwatch.stop();
ModernFix.LOGGER.info("Resolving model textures took " + stopwatch);
}
private static <T extends Comparable<T>, V extends T> BlockState setPropertyGeneric(BlockState state, Property<T> prop, Object o) {
return state.setValue(prop, (V)o);
}
private static <T extends Comparable<T>> T getValueHelper(Property<T> property, String value) {
return property.getValue(value).orElse(null);
}
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
private static final Splitter EQUAL_SPLITTER = Splitter.on('=').limit(2);
public static ImmutableList<BlockState> getBlockStatesForMRL(StateDefinition<Block, BlockState> stateDefinition, ModelResourceLocation location) {
if(Objects.equals(location.getVariant(), "inventory"))
return ImmutableList.of();
Set<Property<?>> fixedProperties = new HashSet<>();
BlockState fixedState = stateDefinition.any();
for(String s : COMMA_SPLITTER.split(location.getVariant())) {
Iterator<String> iterator = EQUAL_SPLITTER.split(s).iterator();
if (iterator.hasNext()) {
String s1 = iterator.next();
Property<?> property = stateDefinition.getProperty(s1);
if (property != null && iterator.hasNext()) {
String s2 = iterator.next();
Object value = getValueHelper(property, s2);
if (value == null) {
throw new RuntimeException("Unknown value: '" + s2 + "' for blockstate property: '" + s1 + "' " + property.getPossibleValues());
}
fixedState = setPropertyGeneric(fixedState, property, value);
fixedProperties.add(property);
} else if (!s1.isEmpty()) {
throw new RuntimeException("Unknown blockstate property: '" + s1 + "'");
}
}
}
// check if there is only one possible state
if(fixedProperties.size() == stateDefinition.getProperties().size()) {
return ImmutableList.of(fixedState);
}
// generate all possible blockstates from the remaining properties
ArrayList<Property<?>> anyProperties = new ArrayList<>(stateDefinition.getProperties());
anyProperties.removeAll(fixedProperties);
ArrayList<BlockState> finalList = new ArrayList<>();
finalList.add(fixedState);
for(Property<?> property : anyProperties) {
ArrayList<BlockState> newPermutations = new ArrayList<>();
for(BlockState state : finalList) {
for(Comparable<?> value : property.getPossibleValues()) {
newPermutations.add(setPropertyGeneric(state, property, value));
}
}
finalList = newPermutations;
}
return ImmutableList.copyOf(finalList);
}
public static ModernFixClientIntegration bakedModelWrapper(BiFunction<ResourceLocation, Pair<UnbakedModel, BakedModel>, BakedModel> consumer) {
return new ModernFixClientIntegration() {
@Override
public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, BakedModel originalModel, ModelState state, ModelBakery bakery) {
return consumer.apply(location, Pair.of(baseModel, originalModel));
}
};
}
}

View File

@ -1,8 +0,0 @@
package org.embeddedt.modernfix.dynamicresources;
import net.minecraft.client.renderer.block.model.BlockFaceUV;
public class UVController {
public static final ThreadLocal<Boolean> useDummyUv = ThreadLocal.withInitial(() -> Boolean.FALSE);
public static final BlockFaceUV dummyUv = new BlockFaceUV(new float[4], 0);
}

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,127 +0,0 @@
package org.embeddedt.modernfix.entity;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.core.Registry;
import net.minecraft.world.entity.EntityType;
import org.embeddedt.modernfix.ModernFix;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
public class EntityRendererMap implements Map<EntityType<?>, EntityRenderer<?>> {
private final Map<EntityType<?>, EntityRendererProvider<?>> rendererProviders;
private final LoadingCache<EntityType<?>, EntityRenderer<?>> rendererMap;
private final EntityRendererProvider.Context context;
public EntityRendererMap(Map<EntityType<?>, EntityRendererProvider<?>> rendererProviders, EntityRendererProvider.Context context) {
this.rendererProviders = rendererProviders;
this.context = context;
this.rendererMap = CacheBuilder.newBuilder().build(new RenderConstructor());
}
class RenderConstructor extends CacheLoader<EntityType<?>, EntityRenderer<?>> {
@Override
public EntityRenderer<?> load(EntityType<?> key) throws Exception {
EntityRendererProvider<?> provider = rendererProviders.get(key);
synchronized(EntityRenderers.class) {
EntityRenderer<?> renderer;
try {
if(provider == null)
throw new RuntimeException("Provider not registered");
renderer = provider.create(context);
ModernFix.LOGGER.info("Loaded entity {}", Registry.ENTITY_TYPE.getKey(key));
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Failed to create entity model for " + Registry.ENTITY_TYPE.getKey(key) + ":", e);
renderer = new ErroredEntityRenderer<>(context);
}
return renderer;
}
}
}
@Override
public int size() {
return rendererProviders.size();
}
@Override
public boolean isEmpty() {
return rendererProviders.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return rendererProviders.containsKey(o);
}
@Override
public boolean containsValue(Object o) {
return false;
}
@Override
public EntityRenderer<?> get(Object o) {
try {
EntityRenderer<?> renderer = rendererMap.get((EntityType<?>)o);
if(renderer == null)
throw new AssertionError("Returned entity renderer should never be null");
return renderer;
} catch (IllegalStateException e) {
return null; /* emulate value not being present if recursive load occurs */
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
@Nullable
@Override
public EntityRenderer<?> put(EntityType<?> entityType, EntityRenderer<?> entityRenderer) {
EntityRenderer<?> old = rendererMap.getIfPresent(entityType);
rendererMap.put(entityType, entityRenderer);
return old;
}
@Override
public EntityRenderer<?> remove(Object o) {
EntityRenderer<?> r = rendererMap.getIfPresent(o);
rendererMap.invalidate(o);
return r;
}
@Override
public void putAll(@NotNull Map<? extends EntityType<?>, ? extends EntityRenderer<?>> map) {
rendererMap.putAll(map);
}
@Override
public void clear() {
rendererMap.invalidateAll();
}
@NotNull
@Override
public Set<EntityType<?>> keySet() {
return rendererProviders.keySet();
}
@NotNull
@Override
public Collection<EntityRenderer<?>> values() {
return rendererMap.asMap().values();
}
@NotNull
@Override
public Set<Map.Entry<EntityType<?>, EntityRenderer<?>>> entrySet() {
return rendererMap.asMap().entrySet();
}
}

View File

@ -1,30 +0,0 @@
package org.embeddedt.modernfix.entity;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
public class ErroredEntityRenderer<T extends Entity> extends EntityRenderer<T> {
public ErroredEntityRenderer(EntityRendererProvider.Context arg) {
super(arg);
}
@Override
public ResourceLocation getTextureLocation(T entity) {
return TextureAtlas.LOCATION_BLOCKS;
}
@Override
public boolean shouldRender(T livingEntity, Frustum camera, double camX, double camY, double camZ) {
return false;
}
@Override
public void render(T entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight) {
}
}

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

@ -1,108 +0,0 @@
package org.embeddedt.modernfix.resources;
import com.google.common.base.Splitter;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import org.embeddedt.modernfix.util.FileUtil;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
public class CachedResourcePath {
private final String[] pathComponents;
public static final Interner<String> PATH_COMPONENT_INTERNER = Interners.newStrongInterner();
private static final Splitter SLASH_SPLITTER = Splitter.on('/');
public static final String[] NO_PREFIX = new String[0];
public CachedResourcePath(String[] prefix, Path path) {
this(prefix, path, path.getNameCount(), true);
}
public CachedResourcePath(String s) {
// normalize so we can guarantee there are no empty sections
this(NO_PREFIX, SLASH_SPLITTER.splitToList(FileUtil.normalize(s)), false);
}
public <T> CachedResourcePath(String[] prefixElements, Collection<T> collection, boolean intern) {
this(prefixElements, collection, collection.size(), intern);
}
public <T> CachedResourcePath(String[] prefixElements, Iterable<T> path, int count, boolean intern) {
String[] components = new String[prefixElements.length + count];
int i = 0;
while(i < prefixElements.length) {
components[i] = intern ? PATH_COMPONENT_INTERNER.intern(prefixElements[i]) : prefixElements[i];
i++;
}
for(Object component : path) {
String s = component.toString();
if(s.length() == 0)
continue;
components[i] = intern ? PATH_COMPONENT_INTERNER.intern(s) : s;
i++;
}
pathComponents = components;
}
public CachedResourcePath(String[] prefixElements, CachedResourcePath other) {
String[] components = new String[prefixElements.length + other.pathComponents.length];
int i = 0;
while(i < prefixElements.length) {
components[i] = PATH_COMPONENT_INTERNER.intern(prefixElements[i]);
i++;
}
System.arraycopy(other.pathComponents, 0, components, i, other.pathComponents.length);
pathComponents = components;
}
/**
* DOES NOT INTERN!
*/
public CachedResourcePath(String[] pathComponents) {
for(String s : pathComponents) {
if(s.length() == 0) {
// reconstruct the whole array skipping blanks. inefficient, but should not be the common case
pathComponents = Arrays.stream(pathComponents).filter(comp -> comp.length() > 0).toArray(String[]::new);
break;
}
}
this.pathComponents = pathComponents;
}
@Override
public int hashCode() {
return Arrays.hashCode(pathComponents);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CachedResourcePath that = (CachedResourcePath) o;
return Arrays.equals(pathComponents, that.pathComponents);
}
public String getFileName() {
return pathComponents[pathComponents.length - 1];
}
public int getNameCount() {
return pathComponents.length;
}
public String getNameAt(int i) {
return pathComponents[i];
}
public String getFullPath(int startIndex) {
StringBuilder sb = new StringBuilder();
for(int i = startIndex; i < pathComponents.length; i++) {
sb.append(pathComponents[i]);
if(i != (pathComponents.length - 1))
sb.append('/');
}
return sb.toString();
}
}

View File

@ -1,184 +0,0 @@
package org.embeddedt.modernfix.resources;
import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackType;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import org.embeddedt.modernfix.util.PackTypeHelper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* The core of the resource pack cache system.
*
* Using a dedicated set and also separate lists is important; testing without this showed a huge performance
* drop.
*/
public class PackResourcesCacheEngine {
private static final Joiner SLASH_JOINER = Joiner.on('/');
private final Map<PackType, Set<String>> namespacesByType;
private final Set<CachedResourcePath> containedPaths;
private final EnumMap<PackType, Map<String, List<CachedResourcePath>>> resourceListings;
private volatile boolean cacheGenerationFlag = false;
private List<Runnable> cacheGenerationTasks = new ArrayList<>();
private Path debugPath;
public PackResourcesCacheEngine(Function<PackType, Set<String>> namespacesRetriever, BiFunction<PackType, String, Path> basePathRetriever) {
this.namespacesByType = new EnumMap<>(PackType.class);
for(PackType type : PackType.values()) {
if(!PackTypeHelper.isVanillaPackType(type))
continue;
this.namespacesByType.put(type, namespacesRetriever.apply(type));
}
this.containedPaths = new ObjectOpenHashSet<>();
this.resourceListings = new EnumMap<>(PackType.class);
// used for log message
this.debugPath = basePathRetriever.apply(PackType.CLIENT_RESOURCES, "minecraft").toAbsolutePath();
for(PackType type : PackType.values()) {
Collection<String> namespaces = PackTypeHelper.isVanillaPackType(type) ? this.namespacesByType.get(type) : namespacesRetriever.apply(type);
Collection<Pair<String, Path>> namespacedRoots = namespaces.stream().map(s -> Pair.of(s, basePathRetriever.apply(type, s).toAbsolutePath())).collect(Collectors.toList());
cacheGenerationTasks.add(() -> {
ImmutableMap.Builder<String, List<CachedResourcePath>> packTypedMap = ImmutableMap.builder();
for(Pair<String, Path> pair : namespacedRoots) {
try {
ImmutableList.Builder<CachedResourcePath> namespacedList = ImmutableList.builder();
String namespace = pair.getFirst();
Path root = pair.getSecond();
String[] prefix = new String[] { type.getDirectory(), namespace };
try (Stream<Path> stream = Files.walk(root)) {
stream
.map(path -> root.relativize(path.toAbsolutePath()))
.filter(PackResourcesCacheEngine::isValidCachedResourcePath)
.forEach(path -> {
CachedResourcePath cachedPath = new CachedResourcePath(prefix, path);
synchronized (this.containedPaths) {
this.containedPaths.add(cachedPath);
}
if(!cachedPath.getFileName().endsWith(".mcmeta"))
namespacedList.add(cachedPath);
});
}
packTypedMap.put(namespace, namespacedList.build());
} catch(IOException ignored) {
}
}
synchronized (this.resourceListings) {
this.resourceListings.put(type, packTypedMap.build());
}
});
}
cacheGenerationTasks.add(() -> {
((ObjectOpenHashSet<CachedResourcePath>)this.containedPaths).trim();
});
}
private static boolean isValidCachedResourcePath(Path path) {
if(path.getFileName() == null || path.getNameCount() == 0) {
return false;
}
String str = SLASH_JOINER.join(path);
if(str.length() == 0)
return false;
for(int i = 0; i < str.length(); i++) {
if(!ResourceLocation.validPathChar(str.charAt(i))) {
return false;
}
}
return true;
}
public Set<String> getNamespaces(PackType type) {
if(PackTypeHelper.isVanillaPackType(type))
return this.namespacesByType.get(type);
else
return null;
}
private void doGenerateCache() {
Stopwatch watch = Stopwatch.createStarted();
for(Runnable r : this.cacheGenerationTasks) {
r.run();
}
watch.stop();
ModernFix.LOGGER.debug("Generated cache for {} in {}", debugPath, watch);
debugPath = null;
cacheGenerationTasks = ImmutableList.of();
}
private void awaitLoad() {
if(!this.cacheGenerationFlag) {
synchronized (this) {
if(!this.cacheGenerationFlag) {
this.doGenerateCache();
this.cacheGenerationFlag = true;
}
}
}
}
public boolean hasResource(String path) {
awaitLoad();
return this.containedPaths.contains(new CachedResourcePath(path));
}
public boolean hasResource(String[] paths) {
awaitLoad();
return this.containedPaths.contains(new CachedResourcePath(paths));
}
public Collection<ResourceLocation> getResources(PackType type, String resourceNamespace, String pathIn, int maxDepth, Predicate<ResourceLocation> filter) {
if(!PackTypeHelper.isVanillaPackType(type))
throw new IllegalArgumentException("Only vanilla PackTypes are supported");
awaitLoad();
List<CachedResourcePath> paths = resourceListings.get(type).getOrDefault(resourceNamespace, Collections.emptyList());
if(paths.isEmpty())
return Collections.emptyList();
String testPath = pathIn.endsWith("/") ? pathIn : (pathIn + "/");
ArrayList<ResourceLocation> resources = new ArrayList<>();
for(CachedResourcePath cachePath : paths) {
if((cachePath.getNameCount() - 2) > maxDepth)
continue;
String fullPath = cachePath.getFullPath(2);
if(!fullPath.startsWith(testPath))
continue;
ResourceLocation foundResource = new ResourceLocation(resourceNamespace, fullPath);
if(!filter.test(foundResource))
continue;
resources.add(foundResource);
}
return resources;
}
private static final WeakHashMap<ICachingResourcePack, Boolean> cachingPacks = new WeakHashMap<>();
public static void track(ICachingResourcePack pack) {
synchronized (cachingPacks) {
cachingPacks.put(pack, Boolean.TRUE);
}
}
public static void invalidate() {
if(!ModernFixPlatformHooks.INSTANCE.isDevEnv())
return;
synchronized (cachingPacks) {
cachingPacks.keySet().forEach(pack -> {
if(pack != null)
pack.invalidateCache();
});
}
}
}

View File

@ -1,150 +0,0 @@
package org.embeddedt.modernfix.searchtree;
import com.google.common.base.Predicates;
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes;
import me.shedaniel.rei.impl.client.search.AsyncSearchManager;
import me.shedaniel.rei.impl.common.entry.type.EntryRegistryImpl;
import me.shedaniel.rei.impl.common.util.HashedEntryStackWrapper;
import net.minecraft.client.searchtree.RefreshableSearchTree;
import net.minecraft.world.item.ItemStack;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.platform.ModernFixPlatformHooks;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
public class REIBackedSearchTree extends DummySearchTree<ItemStack> {
private final AsyncSearchManager searchManager = createSearchManager();
private final boolean filteringByTag;
private String lastSearchText = "";
private final List<ItemStack> listCache = new ArrayList<>();
public REIBackedSearchTree(boolean filteringByTag) {
this.filteringByTag = filteringByTag;
}
@Override
public List<ItemStack> search(String pSearchText) {
if(true) {
return this.searchREI(pSearchText);
} else {
/* Use the default, dummy implementation */
return super.search(pSearchText);
}
}
private List<ItemStack> searchREI(String pSearchText) {
if(!pSearchText.equals(lastSearchText)) {
listCache.clear();
this.searchManager.updateFilter(pSearchText);
List stacks;
try {
stacks = this.searchManager.getNow();
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Couldn't search for '" + pSearchText + "'", e);
stacks = Collections.emptyList();
}
for(Object o : stacks) {
EntryStack<?> stack;
if(o instanceof EntryStack<?>)
stack = (EntryStack<?>)o;
else if(o instanceof HashedEntryStackWrapper) {
stack = ((HashedEntryStackWrapper)o).unwrap();
} else {
ModernFix.LOGGER.error("Don't know how to handle {}", o.getClass().getName());
continue;
}
if(stack.getType() == VanillaEntryTypes.ITEM) {
listCache.add(stack.cheatsAs().getValue());
}
}
lastSearchText = pSearchText;
}
return listCache;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static AsyncSearchManager createSearchManager() {
Method m, normalizeMethod;
try {
try {
m = EntryRegistryImpl.class.getDeclaredMethod("getPreFilteredComplexList");
m.setAccessible(true);
normalizeMethod = HashedEntryStackWrapper.class.getDeclaredMethod("normalize");
normalizeMethod.setAccessible(true);
} catch(NoSuchMethodException e) {
m = EntryRegistryImpl.class.getDeclaredMethod("getPreFilteredList");
m.setAccessible(true);
normalizeMethod = EntryStack.class.getDeclaredMethod("normalize");
normalizeMethod.setAccessible(true);
}
final MethodHandle getListMethod = MethodHandles.publicLookup().unreflect(m);
final MethodHandle normalize = MethodHandles.publicLookup().unreflect(normalizeMethod);
final EntryRegistryImpl registry = (EntryRegistryImpl)EntryRegistry.getInstance();
Supplier stackListSupplier = () -> {
try {
return (List)getListMethod.invokeExact(registry);
} catch(Throwable e) {
if(e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
};
UnaryOperator normalizeOperator = o -> {
try {
return normalize.invoke(o);
} catch(Throwable e) {
if(e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
};
Supplier<Predicate<Boolean>> shouldShowStack = () -> {
return Predicates.alwaysTrue();
};
try {
try {
// Old constructor taking Supplier as first arg
MethodHandle cn = MethodHandles.publicLookup().findConstructor(AsyncSearchManager.class, MethodType.methodType(void.class, Supplier.class, Supplier.class, UnaryOperator.class));
return (AsyncSearchManager)cn.invoke(stackListSupplier, shouldShowStack, normalizeOperator);
} catch(NoSuchMethodException e) {
// New constructor taking Function as first arg
MethodHandle cn = MethodHandles.publicLookup().findConstructor(AsyncSearchManager.class, MethodType.methodType(void.class, Function.class, Supplier.class, UnaryOperator.class));
return (AsyncSearchManager)cn.invoke((Function<?, ?>)o -> stackListSupplier.get(), shouldShowStack, normalizeOperator);
}
} catch(Throwable mhThrowable) {
throw new ReflectiveOperationException(mhThrowable);
}
} catch(ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
public static final SearchTreeProviderRegistry.Provider PROVIDER = new SearchTreeProviderRegistry.Provider() {
@Override
public RefreshableSearchTree<ItemStack> getSearchTree(boolean tag) {
return new REIBackedSearchTree(tag);
}
@Override
public boolean canUse() {
return ModernFixPlatformHooks.INSTANCE.modPresent("roughlyenoughitems");
}
@Override
public String getName() {
return "REI";
}
};
}

View File

@ -1,47 +0,0 @@
package org.embeddedt.modernfix.tickables;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class LoadableTickableObject<T> implements TickableObject {
private volatile int ticksInactive = 0;
private final int timeout;
private final Supplier<T> loader;
private final Consumer<T> finalizer;
private volatile T theObject = null;
public LoadableTickableObject(int timeout, Supplier<T> loader, Consumer<T> finalizer) {
this(timeout, loader, finalizer, null);
}
public LoadableTickableObject(int timeout, Supplier<T> loader, Consumer<T> finalizer, @Nullable T initialValue) {
this.timeout = timeout;
this.loader = loader;
this.finalizer = finalizer;
this.theObject = initialValue;
}
public T get() {
synchronized (this) {
ticksInactive++;
T obj = theObject;
if(obj == null) {
obj = loader.get();
theObject = obj;
}
return obj;
}
}
public final void tick() {
synchronized (this) {
ticksInactive++;
if(ticksInactive >= this.timeout) {
finalizer.accept(theObject);
theObject = null;
}
}
}
}

View File

@ -1,5 +0,0 @@
package org.embeddedt.modernfix.tickables;
public interface TickableObject {
void tick();
}

View File

@ -1,18 +0,0 @@
package org.embeddedt.modernfix.tickables;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class TickableObjectManager {
private static final List<TickableObject> TICKABLE_OBJECT_LIST = new CopyOnWriteArrayList<>();
public static void register(TickableObject object) {
TICKABLE_OBJECT_LIST.add(object);
}
public static void runTick() {
for(TickableObject o : TICKABLE_OBJECT_LIST) {
o.tick();
}
}
}

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

@ -1,48 +0,0 @@
package org.embeddedt.modernfix.util;
import com.google.common.base.Function;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.google.common.collect.Maps;
import java.util.HashMap;
import java.util.Map;
/**
* Replacement backing map for CompoundTags that interns keys.
*/
public class CanonizingStringMap<T> extends HashMap<String, T> {
private static final Interner<String> KEY_INTERNER = Interners.newWeakInterner();
private static String intern(String key) {
return key != null ? KEY_INTERNER.intern(key) : null;
}
public CanonizingStringMap() {
super();
}
@Override
public T put(String key, T value) {
return super.put(intern(key), value);
}
@Override
public void putAll(Map<? extends String, ? extends T> m) {
if(m.isEmpty())
return;
HashMap<String, T> tmp = new HashMap<>();
m.forEach((k, v) -> tmp.put(intern(k), v));
super.putAll(tmp);
}
private void putAllWithoutInterning(Map<? extends String, ? extends T> m) {
super.putAll(m);
}
public static <T> CanonizingStringMap<T> deepCopy(CanonizingStringMap<T> incomingMap, Function<T, T> deepCopier) {
CanonizingStringMap<T> newMap = new CanonizingStringMap<>();
newMap.putAllWithoutInterning(Maps.transformValues(incomingMap, deepCopier));
return newMap;
}
}

View File

@ -1,148 +0,0 @@
package org.embeddedt.modernfix.util;
import com.google.common.collect.ImmutableSet;
import com.mojang.serialization.Lifecycle;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.DataPackConfig;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.Difficulty;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.LevelSettings;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.storage.WorldData;
import net.minecraft.world.level.storage.ServerLevelData;
import java.util.Set;
public class DummyServerConfiguration implements WorldData {
@Override
public DataPackConfig getDataPackConfig() {
return DataPackConfig.DEFAULT;
}
@Override
public void setDataPackConfig(DataPackConfig codec) {
}
@Override
public boolean wasModded() {
return true;
}
@Override
public Set<String> getKnownServerBrands() {
return ImmutableSet.of("forge");
}
@Override
public void setModdedInfo(String name, boolean isModded) {
}
@Override
public CompoundTag getCustomBossEvents() {
return null;
}
@Override
public void setCustomBossEvents(CompoundTag nbt) {
}
@Override
public ServerLevelData overworldData() {
return null;
}
@Override
public LevelSettings getLevelSettings() {
return null;
}
@Override
public CompoundTag createTag(RegistryAccess registries, CompoundTag hostPlayerNBT) {
return null;
}
@Override
public boolean isHardcore() {
return false;
}
@Override
public int getVersion() {
return 0;
}
@Override
public String getLevelName() {
return null;
}
@Override
public GameType getGameType() {
return null;
}
@Override
public void setGameType(GameType type) {
}
@Override
public boolean getAllowCommands() {
return false;
}
@Override
public Difficulty getDifficulty() {
return null;
}
@Override
public void setDifficulty(Difficulty difficulty) {
}
@Override
public boolean isDifficultyLocked() {
return false;
}
@Override
public void setDifficultyLocked(boolean locked) {
}
@Override
public GameRules getGameRules() {
return null;
}
@Override
public CompoundTag getLoadedPlayerTag() {
return null;
}
@Override
public CompoundTag endDragonFightData() {
return null;
}
@Override
public void setEndDragonFightData(CompoundTag nbt) {
}
@Override
public WorldGenSettings worldGenSettings() {
return null;
}
@Override
public Lifecycle worldGenSettingsLifecycle() {
return Lifecycle.stable();
}
}

View File

@ -1,132 +0,0 @@
package org.embeddedt.modernfix.util;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Simple forwarding map implementation that allows layering multiple maps together.
*/
public class LayeredForwardingMap<K, V> implements Map<K, V> {
private final Map<K, V>[] layers;
public LayeredForwardingMap(Map<K, V>[] layers) {
if(layers.length < 1)
throw new IllegalArgumentException();
for(Map<K, V> layer : layers) {
if(layer == null)
throw new IllegalArgumentException();
}
this.layers = layers;
}
@Override
public int size() {
return 1;
}
@Override
public boolean isEmpty() {
for(Map<K, V> map : layers) {
if(!map.isEmpty())
return false;
}
return true;
}
@Override
public boolean containsKey(Object key) {
for(Map<K, V> map : layers) {
if(map.containsKey(key))
return true;
}
return false;
}
@Override
public boolean containsValue(Object value) {
for(Map<K, V> map : layers) {
if(map.containsValue(value))
return true;
}
return false;
}
@Override
public V get(Object key) {
for(Map<K, V> map : layers) {
V value = map.get(key);
if(value != null)
return value;
}
return null;
}
@Nullable
@Override
public V put(K key, V value) {
if(value == null)
throw new IllegalArgumentException();
V originalValue = null;
for(Map<K, V> map : layers) {
V oldVal = map.remove(key);
if(originalValue == null)
originalValue = oldVal;
map.put(key, value);
}
return originalValue;
}
@Override
public V remove(Object key) {
for(Map<K, V> map : layers) {
map.remove(key);
}
return null;
}
@Override
public void putAll(@NotNull Map<? extends K, ? extends V> m) {
for(V value : m.values()) {
if(value == null)
throw new IllegalArgumentException();
}
for(Map<K, V> map : layers) {
map.putAll(m);
}
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Set<K> keySet() {
Set<K> keys = new ObjectOpenHashSet<>();
for(Map<K, V> map : layers) {
keys.addAll(map.keySet());
}
return Collections.unmodifiableSet(keys);
}
@NotNull
@Override
public Collection<V> values() {
Set<K> keys = keySet();
List<V> vals = new ArrayList<>();
for(K key : keys) {
vals.add(get(key));
}
return vals;
}
@NotNull
@Override
public Set<Entry<K, V>> entrySet() {
throw new UnsupportedOperationException();
}
}

View File

@ -1,54 +0,0 @@
package org.embeddedt.modernfix.world;
import net.minecraft.core.Holder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.saveddata.SavedData;
import java.util.ArrayList;
import java.util.List;
public class StrongholdLocationCache extends SavedData {
private List<ChunkPos> chunkPosList;
public StrongholdLocationCache() {
super();
chunkPosList = new ArrayList<>();
}
public List<ChunkPos> getChunkPosList() {
return new ArrayList<>(chunkPosList);
}
public void setChunkPosList(List<ChunkPos> positions) {
this.chunkPosList = new ArrayList<>(positions);
this.setDirty();
}
public static StrongholdLocationCache load(CompoundTag arg) {
StrongholdLocationCache cache = new StrongholdLocationCache();
if(arg.contains("Positions", Tag.TAG_LONG_ARRAY)) {
long[] positions = arg.getLongArray("Positions");
for(long position : positions) {
cache.chunkPosList.add(new ChunkPos(position));
}
}
return cache;
}
@Override
public CompoundTag save(CompoundTag compoundTag) {
long[] serialized = new long[chunkPosList.size()];
for(int i = 0; i < chunkPosList.size(); i++) {
ChunkPos thePos = chunkPosList.get(i);
serialized[i] = thePos.toLong();
}
compoundTag.putLongArray("Positions", serialized);
return compoundTag;
}
public static String getFileId(Holder<DimensionType> dimensionType) {
return "mfix_strongholds";
}
}

View File

@ -1,46 +0,0 @@
accessWidener v2 named
accessible field net/minecraft/client/multiplayer/ClientChunkCache storage Lnet/minecraft/client/multiplayer/ClientChunkCache$Storage;
accessible field net/minecraft/client/multiplayer/ClientChunkCache lightEngine Lnet/minecraft/world/level/lighting/LevelLightEngine;
mutable field net/minecraft/client/multiplayer/ClientChunkCache lightEngine Lnet/minecraft/world/level/lighting/LevelLightEngine;
accessible class net/minecraft/client/multiplayer/ClientChunkCache$Storage
accessible field net/minecraft/client/multiplayer/ClientChunkCache$Storage chunks Ljava/util/concurrent/atomic/AtomicReferenceArray;
accessible field net/minecraft/world/level/Level blockEntityTickers Ljava/util/List;
accessible class net/minecraft/client/renderer/RenderType$CompositeRenderType
accessible method net/minecraft/nbt/CompoundTag <init> (Ljava/util/Map;)V
accessible class net/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache
accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor
accessible field net/minecraft/world/level/block/state/BlockBehaviour properties Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;
accessible class net/minecraft/client/renderer/block/model/BlockElementFace$Deserializer
accessible class net/minecraft/client/renderer/texture/Stitcher$Holder
accessible field net/minecraft/client/renderer/texture/Stitcher$Holder width I
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;
accessible field net/minecraft/server/level/ChunkMap pendingUnloads Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
accessible method net/minecraft/resources/ResourceKey <init> (Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)V
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite <init> (Lnet/minecraft/client/renderer/texture/TextureAtlas;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$Info;IIIIILcom/mojang/blaze3d/platform/NativeImage;)V
accessible field net/minecraft/client/renderer/block/model/BlockModel GSON Lcom/google/gson/Gson;
accessible class net/minecraft/server/level/ChunkMap$DistanceManager
accessible method net/minecraft/client/gui/screens/worldselection/WorldGenSettingsComponent updateSettings (Lnet/minecraft/client/gui/screens/worldselection/WorldCreationContext;)V
accessible class net/minecraft/world/level/chunk/PalettedContainer$Data
accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources;
accessible class net/minecraft/server/MinecraftServer$ReloadableResources
accessible method net/minecraft/client/gui/screens/Screen addRenderableWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener;
accessible field net/minecraft/client/KeyMapping ALL Ljava/util/Map;
accessible field net/minecraft/client/renderer/block/model/multipart/MultiPart definition Lnet/minecraft/world/level/block/state/StateDefinition;
accessible field net/minecraft/server/packs/resources/MultiPackResourceManager namespacedManagers Ljava/util/Map;
accessible field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel;
mutable field net/minecraft/client/renderer/block/model/ItemOverrides$BakedOverride model Lnet/minecraft/client/resources/model/BakedModel;
accessible field net/minecraft/client/renderer/entity/EnderDragonRenderer$DragonModel entity Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;
accessible method net/minecraft/world/level/block/state/StateDefinition appendPropertyCodec (Lcom/mojang/serialization/MapCodec;Ljava/util/function/Supplier;Ljava/lang/String;Lnet/minecraft/world/level/block/state/properties/Property;)Lcom/mojang/serialization/MapCodec;

View File

@ -1,127 +0,0 @@
plugins {
id "com.github.johnrengelman.shadow"
id 'com.adarshr.test-logger' version '3.2.0'
id "modernfix.mod-common-conventions"
id "modernfix.platform-conventions"
}
architectury {
platformSetupLoomIde()
fabric()
}
configurations {
common
shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
modIncludeImplementation
include.extendsFrom modIncludeImplementation
modImplementation.extendsFrom modIncludeImplementation
testAgent {
canBeConsumed = false
}
}
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' }
modCompileOnly(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-models-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
modCompileOnly(fabricApi.module("fabric-data-generation-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' }
if(project.use_fabric_api_at_runtime.toBoolean()) {
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false }
modImplementation "curse.maven:spark-361579:${rootProject.spark_version}"
modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}") { exclude group: 'net.fabricmc', module: 'fabric-loader' }
} else {
modCompileOnly("com.terraformersmc:modmenu:${rootProject.modmenu_version}") { transitive false }
modCompileOnly "curse.maven:spark-361579:${rootProject.spark_version}"
}
// Remove the next line if you don't want to depend on the API
// modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}"
common(project(path: ":common", configuration: "namedElements")) { transitive false }
testImplementation(shadowCommon(project(path: ":common", configuration: "transformProductionFabric"))) { transitive false }
shadowCommon(project(path: ":annotations"))
testImplementation(platform("org.junit:junit-bom:${project.junit_version}"))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.junit.platform:junit-platform-launcher")
testImplementation("org.assertj:assertj-core:3.19.0")
testImplementation("com.google.guava:guava-testlib:21.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.3.1")
testAgent(project("path": ":test_agent", "configuration": "agentJar"))
}
test {
useJUnitPlatform()
def runDir = file('test_run')
doFirst() {
runDir.mkdir()
}
workingDir = runDir
systemProperty 'modernfix.ignoreConfigForTesting', 'true'
// inject our custom agent to fix #817
FileCollection agentFile = configurations.getByName("testAgent")
jvmArgs "-javaagent:${agentFile.singleFile.absolutePath}"
dependsOn(agentFile)
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
shadowJar {
exclude "architectury.common.json"
configurations = [project.configurations.shadowCommon]
archiveClassifier.set("dev-shadow")
}
remapJar {
injectAccessWidener = true
input.set shadowJar.archiveFile
dependsOn shadowJar
archiveClassifier.set(null)
}
jar {
archiveClassifier.set("dev")
}
components.java {
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
skip()
}
}
publishing {
publications {
mavenFabric(MavenPublication) {
artifactId = rootProject.archives_base_name + "-" + project.name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

@ -1,20 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import org.embeddedt.modernfix.fabric.datagen.RuntimeDatagen;
public class ModernFixClientFabric implements ClientModInitializer {
public static ModernFixClient commonMod;
@Override
public void onInitializeClient() {
commonMod = new ModernFixClient();
org.embeddedt.modernfix.fabric.modfixs.DecorativeBlocksFix.fix();
if(FabricLoader.getInstance().isModLoaded("fabric-data-generation-api-v1")) {
RuntimeDatagen.init();
}
}
}

View File

@ -1,19 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.api.ModInitializer;
import net.minecraft.server.MinecraftServer;
import java.lang.ref.WeakReference;
public class ModernFixFabric implements ModInitializer {
public static ModernFix commonMod;
public static WeakReference<MinecraftServer> theServer = new WeakReference<>(null);
@Override
public void onInitialize() {
commonMod = new ModernFix();
// TODO: implement entity ID desync
}
}

View File

@ -1,39 +0,0 @@
package org.embeddedt.modernfix;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import net.fabricmc.loader.impl.gui.FabricGuiEntry;
import net.fabricmc.loader.impl.gui.FabricStatusTree;
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
import org.embeddedt.modernfix.fabric.mappings.MappingsClearer;
import org.embeddedt.modernfix.spark.SparkLaunchProfiler;
import org.embeddedt.modernfix.util.CommonModUtil;
public class ModernFixPreLaunchFabric implements PreLaunchEntrypoint {
@Override
public void onPreLaunch() {
if(ModernFixMixinPlugin.instance == null) {
System.err.println("Mixin plugin not loaded yet");
return;
}
if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_launch.OnFabric")) {
CommonModUtil.runWithoutCrash(() -> SparkLaunchProfiler.start("launch"), "Failed to start profiler");
}
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.clear_fabric_mapping_tables.MappingsClearer")) {
MappingsClearer.clear();
}
// Prevent launching with Continuity when dynamic resources is on
if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.ContinuityCheck")
&& FabricLoader.getInstance().isModLoaded("continuity")) {
CommonModUtil.runWithoutCrash(() -> {
FabricGuiEntry.displayError("Compatibility warning", null, tree -> {
FabricStatusTree.FabricStatusTab crashTab = tree.addTab("Warning");
crashTab.node.addMessage("Continuity and ModernFix's dynamic resources option are not compatible before Minecraft 1.19.4.", FabricStatusTree.FabricTreeWarningLevel.ERROR);
crashTab.node.addMessage("Remove Continuity or disable dynamic resources in the ModernFix config.", FabricStatusTree.FabricTreeWarningLevel.ERROR);
tree.tabs.removeIf(tab -> tab != crashTab);
}, true);
}, "display Continuity warning");
}
}
}

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