Compare commits

...

912 Commits

Author SHA1 Message Date
thirtyninerealms-cloud
667ac6c6ee
Fix thread leak and graceful shutdown issue in NightConfigWatchThrottler
Fix thread leak and graceful shutdown issue in NightConfigWatchThrottler
2026-06-14 17:30:06 +08:00
thirtyninerealms-cloud
2d760eecbb
Fix thread leak and graceful shutdown issue in NightConfigWatchThrottler
Problem:
- FileSystemWatchService threads accumulate over time (observed 17+ threads)
- Threads cannot be interrupted during container shutdown due to unhandled parkNanos()
- Container fails to stop gracefully, requiring force kill

Root cause:
- LockSupport.parkNanos() called without interruption handling
- No shutdown detection mechanism
- Threads continue polling file system even when JVM is terminating

Changes:
1. Add AtomicBoolean shutdown flag to prevent new watch iterations during shutdown
2. Add proper thread interruption handling with graceful fallback to empty iterator
3. Register shutdown hook to set flag on JVM exit

Testing:
- Verified threads no longer accumulate after multiple config reloads
- Container now responds to SIGTERM and stops within 5 seconds
- CPU usage returns to normal after shutdown sequence
2026-06-14 17:24:20 +08:00
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
dfb9378297
Merge 1.18 into 1.19.2 2024-06-01 13:38:16 -04:00
embeddedt
94c848b0de
Merge 1.16 into 1.18 2024-06-01 13:38:15 -04:00
embeddedt
5d7813bf3e
Fix watchdog crash on server start 2024-06-01 13:37:50 -04:00
embeddedt
3a190a56b4
Add optional fix for modern ender dragon having broken movement compared to 1.13 2024-06-01 13:33:21 -04:00
embeddedt
b088fee0e8
Merge 1.19.2 into 1.20 2024-05-30 19:06:40 -04:00
embeddedt
e9ffa69412
Merge 1.18 into 1.19.2 2024-05-30 19:06:39 -04:00
embeddedt
5a7ba9ffea
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-05-30 19:06:33 -04:00
embeddedt
6bfe079175
Attempt to track server tick times more accurately 2024-05-29 18:53:52 -04:00
embeddedt
def4c05dbc
Merge 1.19.2 into 1.20 2024-05-29 16:04:37 -04:00
embeddedt
309870517e
Merge 1.18 into 1.19.2 2024-05-29 16:04:36 -04:00
embeddedt
0d462268e9
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-05-29 16:04:27 -04:00
embeddedt
1728de0f16
Fix CME in BiomeDictionary.Type
Thanks @Asek3 for noticing this
2024-05-26 15:58:37 -04:00
embeddedt
06878c69e4
Disable biome container compression when WorldEdit is installed 2024-05-19 15:16:49 -04:00
embeddedt
831db874e4
Merge 1.19.2 into 1.20 2024-05-12 16:59:13 -04:00
embeddedt
fdac36df9f
Merge 1.18 into 1.19.2 2024-05-12 16:59:12 -04:00
embeddedt
ad9ce1265e
Add a force option to enable blast_search_trees even if no search mod is installed 2024-05-12 16:59:06 -04:00
embeddedt
16f637329f
Merge 1.19.2 into 1.20 2024-05-11 22:15:25 -04:00
embeddedt
d9a44ee061
Merge 1.18 into 1.19.2 2024-05-11 22:15:24 -04:00
embeddedt
1ce76470c2
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-05-11 22:14:45 -04:00
embeddedt
4e3897636d
Disable buffer builder leak fix if Wither Storm Mod is installed
Related: #405
2024-05-11 22:14:26 -04:00
embeddedt
965d105542
Trigger chunk load when remove_spawn_chunks is enabled and end portal teleportation occurs
Related: #404
2024-05-11 22:09:18 -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
2e8c003572
Improve speed of searching for structures 2024-04-30 17:12:14 -04:00
Santiago Hernandez
60707e43b9
Add es_mx.json translation (#391) 2024-04-29 15:02:24 -04:00
embeddedt
641649c1aa
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-04-22 21:25:51 -04:00
embeddedt
8b2fa7e554
Merge 1.16 into 1.18 2024-04-21 21:26:39 -04:00
embeddedt
67e3a863cc
Merge 1.18 into 1.19.2 2024-04-21 21:26:39 -04:00
embeddedt
2915a88465
Use vanilla stitcher for simple atlases
Fixes some minor mod compatibility issues
2024-04-21 21:26:13 -04:00
embeddedt
f8424a9fac
Merge 1.19.2 into 1.20 2024-04-15 21:22:18 -04:00
embeddedt
237239d466
Merge 1.18 into 1.19.2 2024-04-15 21:22:17 -04:00
embeddedt
2f4836b045
Support new REI version 2024-04-15 21:22:06 -04:00
embeddedt
c15b95e2be
Fix mixin.perf.resourcepacks overwriting Fusion patches
Related: #392
2024-04-13 22:26:43 -04:00
embeddedt
97e2a318f3
Update Loom & Gradle 2024-04-13 15:06:53 -04:00
embeddedt
d7f2e90984
Merge 1.19.2 into 1.20 2024-04-13 13:11:21 -04:00
embeddedt
dcc0ed27d8
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2024-04-10 23:14:22 -04:00
embeddedt
debfbdc017
Fix OptiFine resources not being loaded with mixin.perf.resourcepacks
This will impact launch performance, but that is unavoidable if we
want the OF patch to apply. Using a Sodium port is recommended instead.

Related: #41, #45
2024-04-10 23:14:01 -04:00
embeddedt
dd45519d21
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-04-09 19:20:30 -04:00
embeddedt
d36ac86b2a
Merge 1.18 into 1.19.2 2024-04-09 19:19:24 -04:00
embeddedt
ecf3417b45
Merge 1.16 into 1.18 2024-04-09 19:19:23 -04:00
embeddedt
32b0216b19
Work around Carpet crash when remove_spawn_chunks is enabled
Related: #390
2024-04-09 19:13:35 -04:00
ZZZank
9f521ed308
Update zh_cn localizations for mixin options (#387) 2024-04-03 10:41:16 -04:00
embeddedt
ab1da68da2
Document all new mixin options 2024-03-31 16:43:12 -04:00
embeddedt
ec189b55a2
Fix concurrency bugs in Mantle models
Backports eb111d2083
Related: https://github.com/embeddedt/embeddium/issues/251
2024-03-31 16:34:46 -04:00
embeddedt
8873a055bc
Fix https://github.com/thebrightspark/AsyncLocator/issues/12 for 1.16 2024-03-31 16:08:39 -04:00
embeddedt
53e5eb6748
Merge 1.19.2 into 1.20 2024-03-31 16:06:03 -04:00
embeddedt
851febf61d
Merge 1.18 into 1.19.2 2024-03-31 16:06:02 -04:00
embeddedt
dac091cea4
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-03-31 16:03:42 -04:00
embeddedt
e1059e15e7
Convert repository declarations to exclusive content 2024-03-31 15:58:34 -04:00
embeddedt
efc764020a
Merge 1.19.2 into 1.20 2024-03-31 09:27:10 -04:00
embeddedt
9c7b482a20
Merge 1.18 into 1.19.2 2024-03-31 09:27:10 -04:00
embeddedt
8f6c76e93a
Merge 1.16 into 1.18 2024-03-31 09:27:09 -04:00
embeddedt
eddb7fa166
Use low-priority overwrite so other mixins can also apply 2024-03-31 09:26:38 -04:00
embeddedt
0e48559109
Merge 1.19.2 into 1.20 2024-03-30 18:12:29 -04:00
embeddedt
34b9f8d755
Merge 1.18 into 1.19.2 2024-03-30 18:12:28 -04:00
embeddedt
8cca316fb5
Optimize ChunkAccess.getAllReferences directly 2024-03-30 18:10:20 -04:00
embeddedt
4ddac48f1e
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-30 17:42:09 -04:00
embeddedt
e9c266cd16
Properly port recipe book tree to 1.19.2 2024-03-30 17:39:36 -04:00
embeddedt
b0ed60c2f0
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-30 17:37:23 -04:00
embeddedt
099c62672b
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2024-03-30 17:36:18 -04:00
embeddedt
6c82d448f7
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-03-30 17:35:57 -04:00
embeddedt
469b4b7093
Use separate backing search tree for recipe book 2024-03-30 17:35:06 -04:00
embeddedt
033cfd34e5
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2024-03-30 17:34:32 -04:00
embeddedt
c3eeb1e90f
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-03-30 17:31:55 -04:00
embeddedt
db105905f7
Implement a fallback search tree for the recipe book 2024-03-30 17:27:37 -04:00
embeddedt
85aa352215
Merge 1.19.2 into 1.20 2024-03-30 15:22:45 -04:00
embeddedt
aa6b7fad1f
Merge 1.18 into 1.19.2 2024-03-30 15:22:44 -04:00
embeddedt
43dbba1152
Merge 1.16 into 1.18 2024-03-30 15:22:43 -04:00
embeddedt
9e3e732b43
Fix MC-183518 2024-03-30 15:14:44 -04:00
embeddedt
8dac16bfc4
Merge 1.19.2 into 1.20 2024-03-29 10:49:42 -04:00
embeddedt
72ba7d37e0
Merge 1.18 into 1.19.2 2024-03-29 10:49:42 -04:00
embeddedt
183429867a
Merge 1.16 into 1.18 2024-03-29 10:49:41 -04:00
embeddedt
226e4a373b
Reduce chances of CME when iterating class info cache 2024-03-29 10:49:36 -04:00
embeddedt
ddffe93f1a
Stop clearing fields/methods on mixin classes
This seems to break generating the needed bridge access$xxx methods
for inner classes in mixins.

Example mixin that breaks: d5b3c910ac/common/src/main/java/com/railwayteam/railways/mixin/client/MixinStationScreen.java
2024-03-29 10:49:36 -04:00
embeddedt
8a247bd8aa
Merge 1.19.2 into 1.20 2024-03-27 12:15:12 -04:00
embeddedt
a198bfaecd
Merge 1.18 into 1.19.2 2024-03-27 12:15:11 -04:00
embeddedt
c413a70c56
Merge 1.16 into 1.18 2024-03-27 12:15:09 -04:00
embeddedt
66abdcd9a7
Null-check config keybind 2024-03-27 12:14:58 -04:00
Marlester
1b52387cfa
Create de_de.json (#385) 2024-03-27 10:20:35 -04:00
embeddedt
e5e8e6d9b5
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-26 10:04:59 -04:00
embeddedt
f7b4c786d7
Merge 1.18 into 1.19.2 2024-03-26 10:02:09 -04:00
embeddedt
3bf8255581
Merge 1.16 into 1.18 2024-03-26 10:02:08 -04:00
embeddedt
7e9ace3fc6
Fix optimized stitcher ignoring maximum atlas size 2024-03-26 10:02:04 -04:00
embeddedt
fe3de55409
Merge 1.19.2 into 1.20 2024-03-22 14:11:03 -04:00
embeddedt
deb81ec6cd
Merge 1.18 into 1.19.2 2024-03-22 14:10:50 -04:00
embeddedt
b85f1341c1
Merge 1.16 into 1.18 2024-03-22 14:10:49 -04:00
embeddedt
d2680cf29d
Mark mixin as client-only 2024-03-22 14:10:42 -04:00
embeddedt
ab077bc48f
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-22 14:06:24 -04:00
embeddedt
884bdb0fe2
Merge 1.18 into 1.19.2 2024-03-22 14:05:15 -04:00
embeddedt
f63d82ce9b
Merge 1.16 into 1.18 2024-03-22 14:05:13 -04:00
embeddedt
4af1e27a89
Work around NPEs from early queries to ModelManager 2024-03-22 14:05:10 -04:00
embeddedt
3ad7a8ce9d
Merge 1.19.2 into 1.20 2024-03-20 21:38:15 -04:00
embeddedt
b916ef5ae9
Update mixin for 1.19 renames 2024-03-20 16:52:34 -04:00
embeddedt
9c2fbfcae6
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2024-03-20 16:45:55 -04:00
embeddedt
1814bd3e1f
Reduce overhead of the PotentialSpawns event 2024-03-20 16:39:24 -04:00
embeddedt
070b7b6d12
Add some simple patches to cut down allocation rate when ticking chunks 2024-03-20 15:44:28 -04:00
embeddedt
a0fdb3e6d7
Update for FML changes 2024-03-20 15:18:22 -04:00
embeddedt
94d37544b2
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-03-20 14:53:06 -04:00
embeddedt
bf74ab5a80
Mitigate excessive resource usage from Night Config 2024-03-20 14:40:56 -04:00
embeddedt
e1ff64785e
Fix "Illegal prefix" error in log when custom class/resource locators are in use 2024-03-20 14:00:23 -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
e39cc1ca15
Update for Forge registry changes 2024-03-17 16:00:08 -04:00
embeddedt
ebb4f26777
Merge 1.19.2 into 1.20 2024-03-17 15:55:35 -04:00
embeddedt
571d6c6865
Merge 1.18 into 1.19.2 2024-03-17 15:55:34 -04:00
embeddedt
5cc62f7e90
Merge 1.16 into 1.18 2024-03-17 15:55:33 -04:00
embeddedt
31cc0a0da0
Retrieve block name once per state 2024-03-17 15:55:07 -04:00
embeddedt
280d14a595
Merge 1.19.2 into 1.20 2024-03-17 15:52:55 -04:00
embeddedt
3b0e7ce18f
Merge 1.18 into 1.19.2 2024-03-17 15:52:54 -04:00
embeddedt
09e2e0e145
Merge 1.16 into 1.18 2024-03-17 15:52:54 -04:00
embeddedt
06726296fe
Speed up ModelBakeEventHelper constructor 2024-03-17 15:52:41 -04:00
embeddedt
d128ca12c9
Merge 1.19.2 into 1.20 2024-03-17 15:08:24 -04:00
embeddedt
fc2bcc3fb6
Merge 1.18 into 1.19.2 2024-03-17 15:08:23 -04:00
embeddedt
89badd662b
Merge 1.16 into 1.18 2024-03-17 15:08:22 -04:00
embeddedt
d854fcffff
Move stalled async chunk load detection to its own config
This seems to sometimes be a hotspot in profiling, and the log
message is not commonly reported nowadays, indicating most mods
have probably fixed their code.
2024-03-17 15:06:58 -04:00
embeddedt
7b2a0e39be
Merge 1.19.2 into 1.20 2024-03-14 22:13:57 -04:00
embeddedt
3c17a5b4a2
Merge 1.18 into 1.19.2 2024-03-14 22:13:57 -04:00
embeddedt
89b07422e7
Merge 1.16 into 1.18 2024-03-14 22:13:56 -04:00
embeddedt
e6bb67cb05
Disable the testmod by default 2024-03-14 22:13:45 -04:00
embeddedt
095ba1905d
Merge 1.19.2 into 1.20 2024-03-10 21:58:39 -04:00
embeddedt
36f2564d6a
Store delegates on registry objects to avoid map lookup 2024-03-10 21:54:27 -04:00
embeddedt
f1fc20d5a1
Merge 1.19.2 into 1.20 2024-03-08 17:51:05 -05:00
embeddedt
1747cb0b46
Merge 1.18 into 1.19.2 2024-03-08 17:51:04 -05:00
embeddedt
6531e605c2
Merge 1.16 into 1.18 2024-03-08 17:51:02 -05:00
embeddedt
40b9ac6002
Disable pose stack bugfix when OptiFine is installed
Related: #376
2024-03-08 17:49:46 -05:00
embeddedt
263ed51369
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-03-04 16:39:07 -05:00
embeddedt
a197120f57
Merge 1.18 into 1.19.2 2024-03-04 16:38:22 -05:00
embeddedt
49364f6f6d
Merge 1.16 into 1.18 2024-03-04 16:38:20 -05:00
embeddedt
a45783647f
Make the block model cache thread-local instead of using a lock 2024-03-04 16:37:50 -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
124112259e
Reduce load factor of ForgeRegistry delegate map 2024-03-01 11:32:24 -05:00
embeddedt
01a68a2453
Merge 1.19.2 into 1.20 2024-02-28 20:10:52 -05:00
embeddedt
a1ece7da38
Merge 1.18 into 1.19.2 2024-02-28 20:10:06 -05:00
embeddedt
c1f409f9ad
Merge 1.16 into 1.18 2024-02-28 20:09:50 -05:00
embeddedt
ad1e12a3bb
Remove unfinished/obsolete registry & block optimizations
These patches were unfinished, are known to be buggy, and won't make
sense in modern versions of Minecraft, where many of the underlying
issues have been addressed in other ways
2024-02-28 20:07:56 -05:00
embeddedt
e1fcac1761
Merge 1.19.2 into 1.20 2024-02-26 16:40:47 -05:00
embeddedt
3e3b9128c3
Disable primitive chat signing removal if NCR is installed 2024-02-26 16:40:29 -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
51c31bf0b8
Spotless 2024-02-26 16:27:24 -05:00
embeddedt
feaf363fd8
Add oversimplified version of No Chat Reports
This has no player-friendly UI whatsoever, doesn't work on
enforce-secure-profile servers, and has had very limited testing.

In exchange, it costs virtually nothing to maintain.
2024-02-26 16:21:41 -05:00
embeddedt
edda3b4e02
Merge 1.19.2 into 1.20 2024-02-23 16:45:22 -05:00
embeddedt
5fe5a484a3
Use fastutil maps for holder lookups in Forge registry 2024-02-23 16:45:01 -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
2d2bc94747
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2024-02-04 20:22:46 -05:00
embeddedt
2120774df5
Update patch for 1.18 2024-02-04 20:21:53 -05:00
embeddedt
e9c0f6df3b
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-02-04 20:20:45 -05:00
embeddedt
12d69bec45
Fix https://github.com/MinecraftForge/MinecraftForge/issues/9118 2024-02-04 20:05:05 -05:00
embeddedt
e1d203ba10
Merge 1.19.2 into 1.20 2024-02-02 20:38:31 -05:00
embeddedt
e3a41d7416
Merge 1.18 into 1.19.2 2024-02-02 20:38:30 -05:00
embeddedt
8b0080256c
Merge 1.16 into 1.18 2024-02-02 20:38:30 -05:00
embeddedt
f12d7723c0
Call onDynamicResourcesStatusChange if dynamic resources is enabled 2024-02-02 20:38:25 -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
f4c7832964 Merge 1.18 into 1.19.2 2024-01-30 15:47:46 -05:00
embeddedt
a36ad8a4b4 Merge 1.16 into 1.18 2024-01-30 15:47:45 -05:00
embeddedt
2c963888b5 Don't run mappings clearer on FL 0.15+, it's not needed
Related: #329
2024-01-30 15:47:16 -05:00
embeddedt
6207162a17 Merge 1.19.2 into 1.20 2024-01-29 15:30:53 -05:00
embeddedt
efdb1d475d Merge 1.18 into 1.19.2 2024-01-29 15:30:52 -05:00
embeddedt
ca3c02677e Merge 1.16 into 1.18 2024-01-29 15:30:51 -05:00
Kichura
20c0f3dd6a
Update GitHub workflows (#358) 2024-01-28 13:15:27 -05:00
embeddedt
c32fad10e0
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2024-01-27 20:22:16 -05:00
embeddedt
0d4126df41
Merge 1.18 into 1.19.2 2024-01-27 20:19:15 -05:00
embeddedt
41596444a3
Merge remote-tracking branch 'origin/1.16' into 1.18 2024-01-27 20:18:49 -05:00
Fury_Phoenix
c749fc1aeb
Tidy up version detection (#352) 2024-01-25 15:19:37 -05:00
embeddedt
55cb94f1d1 Add textureGetter parameter to onBakedModelLoad 2024-01-24 10:38:57 -05:00
embeddedt
94ca6ccdd6 Add bug report template, heavily derived from Sodium 2024-01-18 16:14:37 -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
27d831ef6a
Merge 1.18 into 1.19.2 2024-01-13 11:17:16 -05:00
embeddedt
0a8a88047c
Merge 1.16 into 1.18 2024-01-13 11:16:03 -05:00
embeddedt
d7146a0667
Restrict resource pack cache to assets/ and data/ folders 2024-01-13 11:15:19 -05:00
embeddedt
c6e01f8a59 Merge 1.19.2 into 1.20 2024-01-12 15:49:13 -05:00
embeddedt
1f7db94281 Merge 1.18 into 1.19.2 2024-01-12 15:49:02 -05:00
embeddedt
5d6abe46f5 Merge 1.16 into 1.18 2024-01-12 15:49:00 -05:00
embeddedt
03e7df5308 Make dynamic maps return empty immutable collections instead of throwing 2024-01-12 15:28:34 -05:00
embeddedt
6fa3e64210 Lower priority of datapack reload exception mixins 2024-01-12 15:18:11 -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
2e88482344
Update for 1.19 model data manager changes 2024-01-04 20:32:30 -05:00
embeddedt
91602ae7d6
Merge 1.19.2 into 1.20 2024-01-04 20:31:06 -05:00
embeddedt
ac4ebd871c
Merge 1.18 into 1.19.2 2024-01-04 20:31:05 -05:00
embeddedt
1d67197df1
Merge 1.16 into 1.18 2024-01-04 20:31:04 -05:00
embeddedt
c678ebbb91
Avoid refresh loop if no model data needs refreshing 2024-01-04 20:30:13 -05:00
embeddedt
7174ae1454
Do not actually load all models in replaceAll, use clever trick instead
Otherwise, it takes 20 seconds to run this with just Mekanism+Additions+Pneumaticcraft
2024-01-02 12:17:53 -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
3214311bb6
Slightly optimize entity capability retrieval 2024-01-01 19:03:52 -05:00
embeddedt
d0fd498682
Suppress mixin forceload logging when clear_mixin_info is on 2024-01-01 12:25:16 -05:00
embeddedt
a186c956f7
Merge 1.19.2 into 1.20 2023-12-30 19:06:11 -05:00
embeddedt
5e983ea936
Merge 1.18 into 1.19.2 2023-12-30 19:05:49 -05:00
embeddedt
8320c31f85
Merge 1.16 into 1.18 2023-12-30 19:05:38 -05:00
embeddedt
1da264e5a7
Bump Fabric Loader 2023-12-30 19:05:20 -05:00
embeddedt
6d7b50bdd8
Merge 1.19.2 into 1.20 2023-12-30 19:02:49 -05:00
embeddedt
300ff4d5f8
Merge 1.18 into 1.19.2 2023-12-30 19:02:48 -05:00
embeddedt
3fa0c3923a
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-30 19:02:42 -05:00
embeddedt
db5a3234d2
Update MixinExtras 2023-12-30 18:59:44 -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
cc1be852bb
More ClientOnlyMixin 2023-12-28 14:42:01 -05:00
embeddedt
35c82b81c8
Mark WorldSelectionList mixin as client-only 2023-12-28 14:33:39 -05:00
embeddedt
357d421f5a
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-28 14:26:35 -05:00
embeddedt
5772661dfb
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-28 14:26:26 -05:00
embeddedt
f6c7b3109b
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-28 14:25:15 -05:00
embeddedt
e301d7d480
Shadow annotations project so they are in the production jar 2023-12-28 14:08:32 -05:00
embeddedt
8d6a344ded
Use correct comment style 2023-12-28 14:08:25 -05:00
embeddedt
4512bc6fbd
Generate config options from both 'mixins' and 'client' keys 2023-12-28 12:31:29 -05:00
embeddedt
4f49ba3f9b
Apply excludedTaskNames in the testmod subproject rather than globally 2023-12-28 12:31:00 -05:00
Fury_Phoenix
7e53a8bc73
Eliminate extraneous casts (#327) 2023-12-28 09:38:54 -05:00
Fury_Phoenix
06bfd71d07
Generate mixin configs automatically using custom AP (#305) 2023-12-28 09:36:49 -05:00
embeddedt
ae8cfbaa3d
Disable dynamic DFU when Litematica is installed 2023-12-27 19:12:11 -05:00
embeddedt
0ea384f3e6
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-27 19:08:21 -05:00
embeddedt
837a66befc
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-27 19:07:33 -05:00
embeddedt
6f0d6e473f
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-27 19:06:49 -05:00
embeddedt
a79ea9766a
Prevent mod mixins from applying if there is a Forge loading error 2023-12-27 18:42:39 -05:00
embeddedt
675c58a437
Only call put on the model map if the replacement model is different 2023-12-27 16:13:45 -05:00
embeddedt
d1863cc66e
Make replaceAll implementation more robust, add warning 2023-12-27 16:06:22 -05:00
embeddedt
11508fbe07
Track duration of model bake events when dynamic resources is enabled 2023-12-27 16:03:54 -05:00
embeddedt
aee0b2a47d
Add Mekanism to model bake event helper 2023-12-27 15:59:51 -05:00
embeddedt
d76fd84b76
Support replaceAll on the wrapping model registry 2023-12-27 15:56:52 -05:00
embeddedt
6578040e77
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-27 15:27:03 -05:00
embeddedt
ecef37ac60
Make handlers not static 2023-12-27 15:26:58 -05:00
embeddedt
c96f7ecf11
Merge 1.19.2 into 1.20 2023-12-27 15:20:17 -05:00
embeddedt
d90a56ff40
Merge 1.18 into 1.19.2 2023-12-27 15:20:16 -05:00
embeddedt
bcd2e80821
Merge 1.16 into 1.18 2023-12-27 15:20:15 -05:00
embeddedt
152cdc4469
Disable ModelDataManager fixes if Rubidium is installed
Since legacy Rubidium versions only retrieve model data on a worker
thread, the data will probably never be refreshed, causing rendering
issues.
2023-12-27 15:19:13 -05:00
embeddedt
2406c1a338
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-26 20:53:09 -05:00
embeddedt
4646b525f3
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-26 20:52:51 -05:00
embeddedt
ae561db9e3
Update mixin for 1.19 model data changes 2023-12-26 20:52:23 -05:00
embeddedt
ebf1d93422
Suppress mixin remap error 2023-12-26 20:51:26 -05:00
embeddedt
b5ef37a713
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-26 20:48:37 -05:00
embeddedt
85928b5b9c
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-26 20:47:23 -05:00
embeddedt
12b0d352cd
Fix some concurrency issues in Forge's ModelDataManager
Model data is now refreshed in a 3x3 radius if retrieved on
the main thread, but not refreshed at all if retrieved on a
worker. This should emulate the old behavior well enough
for most (if not all) mods, while preventing weird CMEs
from accessing block entities off-thread
2023-12-26 20:44:59 -05:00
Fury_Phoenix
8aa04e13a6
Remove testmod genSources task (#333) 2023-12-26 10:13:46 -05:00
embeddedt
6ef5654bb6
Merge 1.19.2 into 1.20 2023-12-23 21:28:42 -05:00
embeddedt
0abffa26ee
Merge 1.18 into 1.19.2 2023-12-23 21:28:41 -05:00
embeddedt
7e57ad8279
Merge 1.16 into 1.18 2023-12-23 21:28:02 -05:00
embeddedt
97ba361867
Retrieve quads on incorrect cullface lists if direction matches 2023-12-23 21:27:39 -05:00
embeddedt
a87399a10f
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-23 19:06:59 -05:00
embeddedt
9034688502
Merge 1.18 into 1.19.2 2023-12-23 19:05:37 -05:00
embeddedt
cef8abe247
Merge 1.16 into 1.18 2023-12-23 19:05:37 -05:00
embeddedt
60b372870b
Fix nixie tubes being invisible with faster_item_rendering 2023-12-23 19:05:16 -05:00
embeddedt
95496fc27c
Merge 1.19.2 into 1.20 2023-12-23 17:15:32 -05:00
embeddedt
d8da6c08a0
Merge 1.18 into 1.19.2 2023-12-23 17:15:26 -05:00
embeddedt
7547a9227c
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-23 17:15:10 -05:00
embeddedt
8058d4caa9
Remove dynamic item overrides
This system conflicts with other optimization mods (e.g. Noxesium)
and is annoying to maintain. Please stop using item overrides and
use real items/mods instead
2023-12-23 17:12:50 -05:00
embeddedt
f35d920801
Merge 1.19.2 into 1.20 2023-12-23 15:57:41 -05:00
embeddedt
7efe10a8a9
Merge 1.18 into 1.19.2 2023-12-23 15:57:40 -05:00
embeddedt
94fbefd901
Update mixin 2023-12-23 15:57:12 -05:00
embeddedt
88a276eed9
Update mixin target 2023-12-23 15:55:32 -05:00
embeddedt
8bcd85d079
Merge 1.18 into 1.19.2 2023-12-23 15:54:20 -05:00
embeddedt
8729e50f1b
Merge 1.19.2 into 1.20 2023-12-23 15:54:20 -05:00
embeddedt
ee8093fc50
Merge 1.16 into 1.18 2023-12-23 15:54:19 -05:00
embeddedt
a7c2424b14
Handle missing models in item overrides 2023-12-23 15:53:40 -05:00
embeddedt
5ff2951b5a
Work around Flywheel leaving freed buffers in BufferBuilder 2023-12-23 14:12:16 -05:00
embeddedt
4d0444ba2a
Merge 1.19.2 into 1.20 2023-12-21 16:51:11 -05:00
embeddedt
f59aa5b19c
Merge 1.18 into 1.19.2 2023-12-21 16:51:10 -05:00
embeddedt
00fa8227c3
Merge 1.16 into 1.18 2023-12-21 16:50:40 -05:00
embeddedt
bc2e84bacc
Cache item override model instance 2023-12-21 16:50:08 -05:00
embeddedt
ed74748994
Merge 1.19.2 into 1.20 2023-12-21 13:41:55 -05:00
embeddedt
0111102d25
Remove obsolete mixin 2023-12-21 13:41:30 -05:00
embeddedt
c5afe3c769
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-21 13:32:19 -05:00
embeddedt
1cfe0216ac
Remove CTM layer hacks entirely on 1.19+, code is unused 2023-12-21 13:31:23 -05:00
embeddedt
ba6103bbc7
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-21 13:28:46 -05:00
embeddedt
1f16ce835a
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-21 13:21:29 -05:00
embeddedt
7e2f3f3fb9
Rewrite CTM predicate handling again, fix more bugs 2023-12-21 13:16:25 -05:00
embeddedt
09939a551f
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-18 22:11:14 -05:00
embeddedt
af13e30f95
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-18 22:06:24 -05:00
embeddedt
9c00f7297d
Reset block predicate when model is loaded
Should help invalidate Embeddium's cache
2023-12-18 22:03:18 -05:00
embeddedt
aa53a7610b
Only wrap top-level CTM models if dynamic resources is on 2023-12-18 22:02:21 -05:00
embeddedt
5fa94bf5e4
Add Elevator Mod to dynamic resources iteration list 2023-12-18 21:39:18 -05:00
embeddedt
b5c4b79eb8
Merge 1.19.2 into 1.20 2023-12-14 21:11:58 -05:00
embeddedt
5e8a111fed
Merge 1.18 into 1.19.2 2023-12-14 21:11:57 -05:00
embeddedt
fe65ffa4d1
Merge 1.16 into 1.18 2023-12-14 21:11:56 -05:00
embeddedt
240fa4b510
Implement dynamic model cache on vanilla ItemModelShaper 2023-12-14 21:11:10 -05:00
embeddedt
8677532629
Merge remote-tracking branch 'origin/1.19.2' into 1.20 2023-12-14 20:44:44 -05:00
embeddedt
559bdb612c
Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-12-14 20:41:47 -05:00
embeddedt
5579743b6c
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-14 20:39:20 -05:00
embeddedt
81836a838d
Implement caching on the blockstate and item to model maps 2023-12-14 20:10:54 -05:00
embeddedt
0056a57f30
Optimize RegistryDelegate#hashCode() 2023-12-13 14:44:25 -05:00
embeddedt
e47bdbf6d0
Merge 1.19.2 into 1.20 2023-12-11 11:01:50 -05:00
embeddedt
845671ce07
Merge 1.18 into 1.19.2 2023-12-11 11:01:49 -05:00
embeddedt
07159b5eb7
Merge 1.16 into 1.18 2023-12-11 11:01:48 -05:00
embeddedt
a76c7f2505
Prevent mixin error if Sophisticated Backpacks isn't installed 2023-12-11 11:01:23 -05:00
embeddedt
cba08057cf
Merge remote-tracking branch 'origin/1.16' into 1.18 2023-12-11 10:58:54 -05:00
embeddedt
b351febc82
Patch CME in Sophisticatd Backpacks 2023-12-11 10:58:10 -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
ccfc282cfc
Remove hot allocations in ForgeRegistry#getDelegateOrThrow 2023-12-07 22:14:30 -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
bf43ba7bf4 Merge 1.18 into 1.19.2 2023-11-23 10:12:18 -05:00
embeddedt
c0f162716b Merge 1.16 into 1.18 2023-11-23 10:12:17 -05:00
embeddedt
2946b3a7b5 Handle path arrays with empty components correctly
Related: #304
2023-11-23 10:11:45 -05:00
embeddedt
61ce2e7117 Mark buffer builder fix as client only 2023-11-23 09:58:20 -05:00
embeddedt
8ce41242ed Update generic 2023-11-23 09:58:03 -05:00
embeddedt
c7a60f5112 Update RegistryObject for 1.19.2 changes 2023-11-23 09:56:35 -05:00
embeddedt
9fb1464176 Merge remote-tracking branch 'origin/1.18' into 1.19.2 2023-11-23 09:56:22 -05:00
embeddedt
488be0c748 Update RegistryObject package name 2023-11-23 09:56:11 -05:00
embeddedt
1002baa6b1 Merge 1.19.2 into 1.20 2023-11-23 09:51:13 -05:00
embeddedt
0b9b49c360 Merge 1.18 into 1.19.2 2023-11-23 09:51:05 -05:00
embeddedt
0aea884052 Merge 1.16 into 1.18 2023-11-23 09:51:03 -05:00
embeddedt
a1f3300a8a More ClientOnlyMixin
Related: #297
2023-11-23 09:50:47 -05:00
Bogdan
ef6c14a61e
Create ru_ru.json (#303) 2023-11-22 09:47:11 -05:00
notlin4
27167ea42c
Update zh_tw.json (#302) 2023-11-21 12:05:45 -05:00
embeddedt
a531df53cb
Fix RegistryObject#get allocating on every call
Credit to jaskarth for discovering this problem
2023-11-19 19:49:08 -05:00
embeddedt
3fb3bb3c11
Merge 1.19.2 into 1.20 2023-11-11 17:26:27 -05:00
embeddedt
8bc92e051e
Merge 1.18 into 1.19.2 2023-11-11 17:26:26 -05:00
embeddedt
adc3dbaf57
Merge 1.16 into 1.18 2023-11-11 17:26:25 -05:00
embeddedt
7c0f8b8bef
Stop logging for suspicious async chunkloads if they complete quickly enough 2023-11-11 17:26:21 -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
embeddedt
3e52c75d0f Merge 1.18 into 1.19.2 2023-11-07 17:27:24 -05:00
embeddedt
552eea488d Merge 1.16 into 1.18 2023-11-07 17:27:22 -05:00
embeddedt
215b797e7b Fix replaceAll being broken on the model registry
Thanks Guava.
2023-11-07 17:26:01 -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
8bb70222ce
Merge 1.18 into 1.19.2 2023-11-05 21:59:08 -05:00
embeddedt
2f3df11220
Merge 1.16 into 1.18 2023-11-05 21:59:07 -05:00
embeddedt
134dc0ef20
Fix path replacements being too aggressive 2023-11-05 21:58:42 -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
53b7d34649
Merge 1.18 into 1.19.2 2023-11-04 09:02:15 -04:00
embeddedt
2ecd0c654b
Merge 1.16 into 1.18 2023-11-04 09:02:14 -04:00
embeddedt
4de9022e3c
Warn if keySet is used by a mod when dynamic resources is on 2023-11-04 09:00:57 -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
819cb13d43 Merge 1.18 into 1.19.2 2023-10-30 14:53:53 -04:00
embeddedt
32ad8f6df1 Update RS integration for 1.18+ 2023-10-30 14:53:34 -04:00
embeddedt
58f79e25e9
Update Diagonal Fences mixin on 1.19 2023-10-30 09:41:48 -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
6b01f0450b
Merge 1.16 into 1.18 2023-10-29 21:15:43 -04:00
embeddedt
6a8d63a2cd
Merge 1.18 into 1.19.2 2023-10-29 21:15:43 -04:00
embeddedt
ced7f866d8
Revert "Use copy-on-write map for permanent overrides"
This solution is also not good enough. It causes catastrophic
time complexity with mods that call get and put in rapid
succession (i.e. every Forge mod using ModelBakeEvent)
2023-10-29 21:14:51 -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
d4f09f6ff9
Merge 1.18 into 1.19.2 2023-10-29 11:36:16 -04:00
embeddedt
fccbae33db
Merge 1.16 into 1.18 2023-10-29 11:36:15 -04:00
embeddedt
621ecf6b3e
Use copy-on-write map for permanent overrides 2023-10-29 11:35:46 -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
0b5145f290
Merge 1.18 into 1.19.2 2023-10-28 20:06:01 -04:00
embeddedt
0a72abb519
Merge 1.16 into 1.18 2023-10-28 20:06:00 -04:00
embeddedt
5d984f653e
Don't log error if NO_GROUP field is missing
Fixes error message in log with Connector
2023-10-28 20:05:55 -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
b9d81f44e6
Merge 1.18 into 1.19.2 2023-10-28 09:54:24 -04:00
embeddedt
93fbbfe2d1
Force UnsafeBufferHelper to be classloaded at startup 2023-10-28 09:50:25 -04:00
Moulberry
e36ba04921
Avoid mods causing double free when BufferBuilder leak fix is enabled 2023-10-28 09:44:12 -04:00
embeddedt
7054c16f6c Merge 1.19.2 into 1.20 2023-10-25 17:18:45 -04:00
embeddedt
b7b510f807 Merge 1.18 into 1.19.2 2023-10-25 17:18:43 -04:00
embeddedt
4054bd8a23 Merge 1.16 into 1.18 2023-10-25 17:18:42 -04:00
embeddedt
89dab59980 Revert "Change permanentOverrides to ConcurrentHashMap"
This reverts commit a5b5733965.

We require the ability to store null values in the map for now
2023-10-25 17:17:52 -04:00
embeddedt
f4ce7072a6 Enable dynamic sounds now that Guava issue is worked around 2023-10-25 15:03:16 -04:00
embeddedt
daea9dd83a Merge 1.19.2 into 1.20 2023-10-25 15:00:19 -04:00
embeddedt
b10e9de54c Merge 1.18 into 1.19.2 2023-10-25 14:58:33 -04:00
embeddedt
14abfef522 Merge 1.16 into 1.18 2023-10-25 14:58:01 -04:00
embeddedt
77760d7dd2 Remember previous scroll position on config screen 2023-10-25 14:56:37 -04:00
embeddedt
f391e97a62 Handle Knot behaving differently from FML with getResource 2023-10-25 14:34:45 -04:00
embeddedt
fd68efec0c Remove async_jei option from 1.18 listing 2023-10-25 14:30:10 -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
04a72f4d90 Merge 1.18 into 1.19.2 2023-10-25 14:24:16 -04:00
embeddedt
8b37a1dbfc Disable buffer builder fix when isometric-renders is installed
Related: #273
2023-10-25 14:23:27 -04:00
embeddedt
b943dc1449 Fix deobfuscation check not working on Forge 1.18+ 2023-10-25 14:22:20 -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
54c7dbd16e Merge 1.18 into 1.19.2 2023-10-24 12:45:37 -04:00
embeddedt
c5a5b01bfb Merge 1.16 into 1.18 2023-10-24 12:45:35 -04:00
embeddedt
6740857274 Fix unsanitized input being passed to TinyFD 2023-10-24 12:45:13 -04:00
Phoenix-Starlight
9f040b2c43
Dynamic sounds code cleanup (#264) 2023-10-14 22:17:00 -04:00
embeddedt
a5b5733965
Change permanentOverrides to ConcurrentHashMap
Should help address thread contention noted while profiling
2023-10-14 13:24:26 -04:00
embeddedt
b567658318
Disable async_jei by default, to match newer versions
There have been a couple isolated reports of weird JEI behavior,
and this might be why
2023-10-14 13:20:26 -04:00
embeddedt
7cbea84706
Merge 1.19.2 into 1.20 2023-10-13 10:47:52 -04:00
embeddedt
5fbbacbe11
Merge 1.18 into 1.19.2 2023-10-13 10:47:51 -04:00
embeddedt
4b8ec822fe
Merge 1.16 into 1.18 2023-10-13 10:47:50 -04:00
embeddedt
8059fc4672
Make clear_fabric_mapping_tables work on Fabric Loader 0.14.23 2023-10-13 10:47:44 -04:00
embeddedt
49c1bc71ba
Patch modded shape caches to be thread-safe
Related: #260
2023-10-13 10:47:44 -04:00
Phoenix-Starlight
e7277b89d5
Fix dynamic_sounds breaking on 1.16 (#259)
An issue in Guava (https://github.com/google/guava/issues/3081) causes the removal listener to fire even when entries haven't actually been removed. We filter them to get around this.
2023-10-12 22:19:46 -04:00
embeddedt
cbfe1636ff
Merge 1.19.2 into 1.20 2023-10-10 17:40:30 -04:00
embeddedt
cebe1c308a
Merge 1.18 into 1.19.2 2023-10-10 17:40:29 -04:00
embeddedt
39fa555209
Merge 1.16 into 1.18 2023-10-10 17:40:29 -04:00
embeddedt
538d332310
Disable dynamic sounds by default until it can be tested more 2023-10-10 17:39:54 -04:00
embeddedt
ed1f2c5837
Merge 1.19.2 into 1.20 2023-10-09 08:37:42 -04:00
embeddedt
1d68dd797c
Merge 1.18 into 1.19.2 2023-10-09 08:37:04 -04:00
embeddedt
da71fc1a2c
Merge 1.16 into 1.18 2023-10-09 08:37:03 -04:00
embeddedt
40b04cbded
Fix cache_upgraded_structures leaking open input streams 2023-10-09 08:36:35 -04:00
羊羽ちゃん
504397bc23
Update ja_jp.json (#255) 2023-10-08 21:09:29 -04:00
embeddedt
e537cbe29a Merge 1.19.2 into 1.20 2023-10-07 18:47:10 -04:00
embeddedt
b1e91686da Merge 1.18 into 1.19.2 2023-10-07 18:47:09 -04:00
embeddedt
5007c5e286 Merge 1.16 into 1.18 2023-10-07 18:47:08 -04:00
embeddedt
bf6979e45b Cleanup dynamic sounds patch, bump eviction time to 5 minutes 2023-10-07 18:44:33 -04:00
Phoenix-Starlight
803aaba204
Dynamic sound unloading (#234) 2023-10-07 18:41:52 -04:00
embeddedt
637c14fb6d Merge 1.19.2 into 1.20 2023-10-07 17:48:38 -04:00
embeddedt
ea918a44c4 Merge 1.18 into 1.19.2 2023-10-07 17:48:36 -04:00
embeddedt
5c73ddeaf8 Port vehicle mixin to 1.18 2023-10-07 17:48:30 -04:00
embeddedt
b56fbc853d Merge 1.19.2 into 1.20 2023-10-07 17:46:24 -04:00
embeddedt
1a358582a5 Merge 1.18 into 1.19.2 2023-10-07 17:46:23 -04:00
embeddedt
2d14bc3b1b Merge 1.16 into 1.18 2023-10-07 17:46:21 -04:00
embeddedt
6593b6a5cf Preserve rotation 2023-10-07 17:42:04 -04:00
embeddedt
204c8b78c4 Fix lag caused by Forge vehicle resync patch
This patch previously set the player to the entity's position,
which is not always correct for entities that position the player
at an offset (e.g. boats with two entities). Move the player using
positionRider() instead

Original PR: https://github.com/MinecraftForge/MinecraftForge/pull/5160
2023-10-07 17:27:23 -04:00
embeddedt
b1a0d0b94a Merge 1.19.2 into 1.20 2023-10-06 17:07:47 -04:00
embeddedt
d7d75e88d5 Merge 1.18 into 1.19.2 2023-10-06 17:07:46 -04:00
embeddedt
6c7a5c70f5 Merge 1.16 into 1.18 2023-10-06 17:07:23 -04:00
embeddedt
d877ab46f0 Remove reference to Component in NightConfigFixer 2023-10-06 17:06:10 -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
c87dee4f3f Merge 1.18 into 1.19.2 2023-10-05 14:30:23 -04:00
embeddedt
fb720782b9 Merge 1.16 into 1.18 2023-10-05 14:30:21 -04:00
embeddedt
36673f275e Tweak dynamic resources injection point on Forge
Related: #252
2023-10-05 14:29:28 -04:00
embeddedt
385523c826 Merge 1.19.2 into 1.20 2023-10-05 14:12:35 -04:00
embeddedt
c387e91f0d Merge 1.18 into 1.19.2 2023-10-05 14:12:33 -04:00
embeddedt
9c02b2c393 Update mixin for 1.18 2023-10-05 14:12:26 -04:00
embeddedt
9306743001 Update package for 1.18 2023-10-05 14:09:25 -04:00
embeddedt
a1f867c26d Merge remote-tracking branch 'origin/1.16' into 1.18 2023-10-05 14:09:04 -04:00
embeddedt
2710a02b2a Detect vanilla connection using custom logic 2023-10-05 14:08:44 -04:00
embeddedt
4090a91272 Merge 1.18 into 1.19.2 2023-10-05 13:37:48 -04:00
embeddedt
00144af296 Merge 1.16 into 1.18 2023-10-05 13:37:46 -04:00
embeddedt
96d01e5a1e Don't read modded recipe book settings on vanilla connection
Related: https://github.com/neoforged/NeoForge/issues/150
2023-10-05 13:37:31 -04:00
embeddedt
225366ee02 Merge 1.19.2 into 1.20 2023-10-03 13:45:37 -04:00
embeddedt
cedcd94417 Merge 1.18 into 1.19.2 2023-10-03 13:45:36 -04:00
embeddedt
43ca13cdf2 Attempt to free leaked BufferBuilders 2023-10-03 13:45:18 -04:00
embeddedt
8fd8efb2e3 Merge 1.19.2 into 1.20 2023-09-27 17:58:52 -04:00
embeddedt
f9856ec591 Merge 1.18 into 1.19.2 2023-09-27 17:58:51 -04:00
embeddedt
0dc068eabf Merge 1.16 into 1.18 2023-09-27 17:58:50 -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
羊羽ちゃん
aa25e3f05e
Update ja_jp.json (#248) 2023-09-25 11:08:24 -04:00
I_am_Vietnam
b57eeb38de
Add vi_vn.json (#247) 2023-09-25 10:06:12 -04:00
embeddedt
3011e40972
Merge 1.19.2 into 1.20 2023-09-24 12:50:15 -04:00
embeddedt
47ced6ee40
Merge 1.18 into 1.19.2 2023-09-24 12:50:14 -04:00
embeddedt
db49f73bf5
Merge 1.16 into 1.18 2023-09-24 12:50:13 -04:00
embeddedt
cf362047a6
Fix Modrinth changelog 2023-09-24 12:47:56 -04:00
embeddedt
b1a1d785de
Merge 1.19.2 into 1.20 2023-09-24 12:33:59 -04:00
embeddedt
4529bf36d1
Merge 1.18 into 1.19.2 2023-09-24 12:33:58 -04:00
embeddedt
3150863b2c
Merge 1.16 into 1.18 2023-09-24 12:33:57 -04:00
embeddedt
f59e003df1
Prepare for release 2023-09-24 12:33:48 -04:00
embeddedt
f1ef1a6c41
Merge 1.19.4 into 1.20 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
88d56c451e Merge 1.19.4 into 1.20 2023-09-20 17:58:55 -04:00
embeddedt
eff07204ea
Merge 1.19.4 into 1.20 2023-09-17 12:33:57 -04:00
embeddedt
e9f6f3d953 Merge 1.19.4 into 1.20 2023-09-15 09:40:55 -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
6198f0c9d3
Merge 1.19.4 into 1.20 2023-08-31 07:57:26 -04:00
embeddedt
4b560c7d3d
Merge 1.19.4 into 1.20 2023-08-29 15:17:06 -04:00
embeddedt
501d24ddfd
Merge 1.19.4 into 1.20 2023-08-29 14:39:57 -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
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
26bdb57972
Merge 1.19.4 into 1.20 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
501e498175
Merge 1.19.4 into 1.20 2023-08-19 19:19:59 -04:00
embeddedt
b171d4bf19
Merge 1.19.4 into 1.20 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
e946cc896a
Merge 1.19.4 into 1.20 2023-08-18 15:16:55 -04:00
embeddedt
bc7fb1e6d4
Merge 1.19.4 into 1.20 2023-08-18 14:39:26 -04:00
embeddedt
9964693050
Merge 1.19.4 into 1.20 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
74c9f684e6
Merge 1.19.4 into 1.20 2023-08-15 22:03:47 -04:00
embeddedt
6e00010e9a
Merge 1.19.4 into 1.20 2023-08-15 21:21:18 -04:00
embeddedt
00481145b6
Merge 1.19.4 into 1.20 2023-08-15 21:19:16 -04:00
embeddedt
ef341932a3
Merge 1.19.4 into 1.20 2023-08-15 13:08:56 -04:00
embeddedt
5203985a25
Merge 1.19.4 into 1.20 2023-08-13 16:38:04 -04:00
embeddedt
05cc25c761
Merge 1.19.4 into 1.20 2023-08-12 12:13:46 -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
507cc7eb14
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-11 19:55:28 -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
712409b4e1
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-09 17:20:45 -04:00
embeddedt
32e246885b Merge 1.19.4 into 1.20 2023-08-08 18:17:36 -04:00
embeddedt
180ac925f7
Merge 1.19.4 into 1.20 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
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
fa17a5f745
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-07 10:47:02 -04:00
embeddedt
823fa259e9
Merge 1.19.4 into 1.20 2023-08-05 19:43:20 -04:00
embeddedt
8a0ff999bd
Merge 1.19.4 into 1.20 2023-08-05 12:52:06 -04:00
embeddedt
5165cf20c8
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-05 12:18:45 -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
c2695b1180
Merge 1.19.4 into 1.20 2023-08-03 20:04:49 -04:00
embeddedt
331ad00758
Merge 1.19.4 into 1.20 2023-08-03 17:01:14 -04:00
embeddedt
d5a9f68575
Merge 1.19.4 into 1.20 2023-08-03 13:14:38 -04:00
embeddedt
df854f333c
Merge 1.19.4 into 1.20 2023-08-03 12:21:04 -04:00
embeddedt
13aaab4798
Merge 1.19.4 into 1.20 2023-08-03 11:54:01 -04:00
embeddedt
19593b5574
Merge 1.19.4 into 1.20 2023-08-03 11:27:54 -04:00
embeddedt
bf5ca2f3cd
Merge 1.19.4 into 1.20 2023-08-02 22:18:19 -04:00
embeddedt
fa6b93fad2
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 19:51:25 -04:00
embeddedt
5bd5c8289c
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 16:41:39 -04:00
embeddedt
02fd57f9a4
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 16:31:51 -04:00
embeddedt
a1a441d397
Merge 1.19.4 into 1.20 2023-08-02 15:45:57 -04:00
embeddedt
11fd512c5e
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-08-02 11:56:36 -04:00
embeddedt
156f0a10cb
Merge 1.19.4 into 1.20 2023-07-31 15:35:57 -04:00
embeddedt
858325e40d
Merge 1.19.4 into 1.20 2023-07-31 15:34:04 -04:00
embeddedt
84bd756cdf
Merge 1.19.4 into 1.20 2023-07-30 13:11:12 -04:00
embeddedt
3e3448adb1
Merge 1.19.4 into 1.20 2023-07-28 22:11:28 -04:00
embeddedt
3a4b8738fc
Merge 1.19.4 into 1.20 2023-07-28 22:00:23 -04:00
embeddedt
4697704763
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-28 21:45:25 -04:00
embeddedt
1884996e53
Merge 1.19.4 into 1.20 2023-07-28 16:40:02 -04:00
embeddedt
51bf5890d3
Merge 1.19.4 into 1.20 2023-07-28 16:09:27 -04:00
embeddedt
e1fdca5f41
Merge 1.19.4 into 1.20 2023-07-28 16:07:14 -04:00
embeddedt
4e3dc99479
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-07-27 16:49:05 -04:00
embeddedt
ae8c062631
Merge 1.19.4 into 1.20 2023-07-27 16:04:08 -04:00
embeddedt
36ae73316a
Merge 1.19.4 into 1.20 2023-07-27 12:41:43 -04:00
embeddedt
7a648f0c5e
Merge 1.19.4 into 1.20 2023-07-26 22:03:11 -04:00
embeddedt
055892cd62
Merge 1.19.4 into 1.20 2023-07-26 09:37:05 -04:00
embeddedt
76d1c8e8bd
Merge 1.19.4 into 1.20 2023-07-24 17:19:03 -04:00
embeddedt
c41728b97c
Merge 1.19.4 into 1.20 2023-07-24 16:05:01 -04:00
embeddedt
437eb9f793
Merge 1.19.4 into 1.20 2023-07-23 19:29:31 -04:00
embeddedt
1889ef2d8c
Merge 1.19.4 into 1.20 2023-07-23 19:23:27 -04:00
embeddedt
90f6f6d68d
Merge 1.19.4 into 1.20 2023-07-23 18:33:34 -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
821f87b880
Merge 1.19.4 into 1.20 2023-07-22 11:22:05 -04:00
embeddedt
4031b65099
Merge 1.19.4 into 1.20 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
c6eb703648
Merge 1.19.4 into 1.20 2023-07-20 21:35:15 -04:00
embeddedt
a5fb8575a6
Merge 1.19.4 into 1.20 2023-07-20 20:18:46 -04:00
embeddedt
374aac7ff5
Merge 1.19.4 into 1.20 2023-07-20 10:57:47 -04:00
embeddedt
5ed2faebc4
Merge 1.19.4 into 1.20 2023-07-20 10:43:40 -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
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
d69f5ac18d
Merge 1.19.4 into 1.20 2023-07-19 17:01:44 -04:00
embeddedt
3162a531b7
Merge 1.19.4 into 1.20 2023-07-19 16:46:15 -04:00
embeddedt
7d7e2f029d
Merge 1.19.4 into 1.20 2023-07-19 12:39:52 -04:00
embeddedt
9eed139cc9
Merge 1.19.4 into 1.20 2023-07-19 12:32:40 -04:00
embeddedt
30f483245c
Merge 1.19.4 into 1.20 2023-07-19 12:20:52 -04:00
embeddedt
5b716dcdf2
Merge 1.19.4 into 1.20 2023-07-18 13:57:31 -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
c51b0585a2
Merge 1.19.4 into 1.20 2023-07-16 20:00:08 -04:00
embeddedt
e86787c663
Merge 1.19.4 into 1.20 2023-07-16 16:58:47 -04:00
embeddedt
9a5edb9431
Merge 1.19.4 into 1.20 2023-07-15 20:37:19 -04:00
embeddedt
d9f93ec67e
Merge 1.19.4 into 1.20 2023-07-15 15:07:38 -04:00
embeddedt
ff292cfabc
Merge 1.19.4 into 1.20 2023-07-14 13:57:40 -04:00
embeddedt
faccdb0ed7
Merge 1.19.4 into 1.20 2023-07-13 21:43:49 -04:00
embeddedt
dc0ea4d828
Merge 1.19.4 into 1.20 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
a799afc19c
Merge 1.19.4 into 1.20 2023-07-13 17:08:59 -04:00
embeddedt
eecf9f0726
Merge 1.19.4 into 1.20 2023-07-13 14:58:37 -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
e4cce437d4
Merge 1.19.4 into 1.20 2023-07-12 19:35:53 -04:00
embeddedt
e5152439ef
Merge 1.19.4 into 1.20 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
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
2bf51c2034
Merge 1.19.4 into 1.20 2023-07-11 22:13:41 -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
a5ae6e0631
Merge 1.19.4 into 1.20 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
9a966cfad9
Merge 1.19.4 into 1.20 2023-07-10 20:28:31 -04:00
embeddedt
489d3abe65
Merge 1.19.4 into 1.20 2023-07-10 09:02:45 -04:00
embeddedt
b3f00a0681
Merge 1.19.4 into 1.20 2023-07-09 20:41:08 -04:00
embeddedt
827d09289d
Merge 1.19.4 into 1.20 2023-07-09 20:37:25 -04:00
embeddedt
7e25e31d33
Merge 1.19.4 into 1.20 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
05e66b2492
Merge 1.19.4 into 1.20 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
1a7909aaa4
Merge 1.19.4 into 1.20 2023-07-07 21:06:48 -04:00
embeddedt
e56898fff4
Merge 1.19.4 into 1.20 2023-07-07 20:23:42 -04:00
embeddedt
60d06c92f6
Merge 1.19.4 into 1.20 2023-07-07 19:22:08 -04:00
embeddedt
e65727937c
Merge 1.19.4 into 1.20 2023-07-06 22:10:26 -04:00
embeddedt
5e7421ab24
Merge 1.19.4 into 1.20 2023-07-06 21:29:26 -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
ba7bda0b04
Remove LazyDFU change for 1.20 2023-07-05 15:08:31 -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
2a16229056
Merge 1.19.4 into 1.20 2023-07-05 14:50:28 -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
c33fe2e928
Merge 1.19.4 into 1.20 2023-07-03 15:10:48 -04:00
embeddedt
3237de7e33
Merge 1.19.4 into 1.20 2023-07-03 14:59:21 -04:00
embeddedt
3be36f826c
Merge 1.19.4 into 1.20 2023-06-29 19:28:08 -04:00
embeddedt
7464cf7420
Merge 1.19.4 into 1.20 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
840cad23b8
Merge 1.19.4 into 1.20 2023-06-27 15:29:27 -04:00
embeddedt
463bd4ef51
Merge 1.19.4 into 1.20 2023-06-27 11:27:38 -04:00
embeddedt
ca60a13bb4
Merge 1.19.4 into 1.20 2023-06-27 11:04:06 -04:00
embeddedt
54f55ee257
Merge 1.19.4 into 1.20 2023-06-26 21:26:28 -04:00
embeddedt
7a2d38f2f1
Merge 1.19.4 into 1.20 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
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
2bad1c0226
Merge 1.19.4 into 1.20 2023-06-26 13:04:44 -04:00
embeddedt
b755d745c5
Merge 1.19.4 into 1.20 2023-06-26 12:59:35 -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
63bcdb1019
Merge 1.19.4 into 1.20 2023-06-22 13:42:57 -04:00
embeddedt
1f589901d6
Merge 1.19.4 into 1.20 2023-06-21 21:44:00 -04:00
embeddedt
9bc6b7b0f7
Merge 1.19.4 into 1.20 2023-06-20 14:43:13 -04:00
embeddedt
c1c0010126
Merge 1.19.4 into 1.20 2023-06-20 14:34:54 -04:00
embeddedt
6006026deb
Merge 1.19.4 into 1.20 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
42d41eb0f7
Merge 1.19.4 into 1.20 2023-06-14 22:14:23 -04:00
embeddedt
75bd0a5ff7
Merge 1.19.4 into 1.20 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
761417833e
Merge 1.19.4 into 1.20 2023-06-12 21:58:58 -04:00
embeddedt
173d71b04f
Merge 1.19.4 into 1.20 2023-06-12 10:56:16 -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
a7e5147104
Merge 1.19.4 into 1.20 2023-06-11 21:32:24 -04:00
embeddedt
cc6191cef2
Merge 1.19.4 into 1.20 2023-06-11 21:03:06 -04:00
embeddedt
002ff639a0
Merge 1.19.4 into 1.20 2023-06-11 20:48:20 -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
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
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
30bf3afc1d
Merge remote-tracking branch 'origin/1.19.4' into 1.20 2023-05-16 11:18:10 -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
510 changed files with 13340 additions and 8042 deletions

78
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,78 @@
name: Bug Report
description: "For reporting bugs and other defects"
body:
- type: markdown
attributes:
value: >-
**Need help?** Ask on [Discord](https://discord.gg/rN9Y7caguP) instead of opening an issue.
**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: >-
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.
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 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: diagnostic-info
attributes:
label: Diagnostic Info
description: >-
Drag and drop `latest.log` from `.minecraft/logs/` for the session where the issue occurred.
Do not paste log text inline. Issues without a valid `latest.log` will be closed.
If a crash occurred, also attach the relevant file from `.minecraft/crash-reports/`.
validations:
required: true

6
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,6 @@
blank_issues_enabled: true
contact_links:
- name: For help with other issues, join our Discord community
url: https://discord.gg/rN9Y7caguP
about: This is the best option for getting help with mod installation, performance issues, and any other support inquiries
# Copied from https://github.com/CaffeineMC/sodium-fabric#community

View File

@ -10,35 +10,127 @@ on:
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
issues: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v3
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
with:
cache-read-only: ${{ !startsWith(github.ref, 'refs/heads/1.') }}
gradle-home-cache-cleanup: true
- name: Setup project Loom cache
uses: actions/cache@v3
with:
path: |
.gradle/loom-cache
key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle.properties', '**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Build ModernFix
java-version: 21
check-latest: true
- name: Check if release branch
id: check_branch
if: github.event_name == 'push'
run: |
chmod +x gradlew
./gradlew build
if [[ "${{ github.ref }}" =~ ^refs/heads/[0-9]+\. ]]; then
echo "is_release=true" >> $GITHUB_OUTPUT
else
echo "is_release=false" >> $GITHUB_OUTPUT
fi
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ steps.check_branch.outputs.is_release != 'true' }}
gradle-home-cache-cleanup: true
- name: Remove tags for release on other versions
if: steps.check_branch.outputs.is_release == 'true'
run: ./scripts/tagcleaner.sh
- name: 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@v3
uses: actions/upload-artifact@v4
with:
name: Package
path: bin

View File

@ -1,42 +0,0 @@
name: Release ModernFix Artifacts
on:
release:
types:
- published
jobs:
release:
if: github.repository_owner == 'embeddedt'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 17
- name: Remove tags for release on other versions
run: ./scripts/tagcleaner.sh
- name: Build and publish mod to CurseForge & Modrinth
run: |
chmod +x gradlew
./gradlew forge:publishToModSites fabric:publishToModSites forge:copyJarToBin fabric:copyJarToBin
env:
CURSEFORGE_TOKEN: ${{ secrets.CURSEFORGE_TOKEN }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
- name: Upload assets to GitHub
uses: AButler/upload-release-assets@v2.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

@ -8,10 +8,10 @@ on:
jobs:
wikigen:
if: github.repository_owner == 'embeddedt'
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate Markdown Patch-List
@ -24,4 +24,4 @@ jobs:
with:
path: "doc/generated"
env:
GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.WIKI_TOKEN }}
GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.WIKI_TOKEN }}

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

@ -6,11 +6,11 @@ Some fixes are based on prior work in various Forge PRs (check commit history an
is directly derived from Sodium and used under the terms of the LGPL-3.0 license.
## Development builds (generally stable, but may occasionally have bugs)
- 1.16.5, both modloaders: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.16/Package.zip
- 1.18.2, both modloaders: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.18/Package.zip
- 1.19.2, both modloaders: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.19.2/Package.zip
- 1.19.4, both modloaders: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.19.4/Package.zip
- 1.20.1, both modloaders: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.20/Package.zip
- 1.16.5: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.16/Package.zip
- 1.18.2: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.18/Package.zip
- 1.19.2: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.19.2/Package.zip
- 1.20.1: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.20/Package.zip
- 1.20.2: https://nightly.link/embeddedt/ModernFix/workflows/gradle/1.20.2/Package.zip
------------

View File

@ -0,0 +1,54 @@
plugins {
id 'com.gradleup.shadow' version '8.3.9'
id 'java-library'
}
repositories {
mavenCentral()
maven { url uri("https://maven.fabricmc.net") }
maven { url "https://maven.neoforged.net/releases" }
}
dependencies {
annotationProcessor 'com.google.auto.service:auto-service:1.1.1'
compileOnly 'com.google.auto.service:auto-service:1.1.1'
implementation 'com.google.code.gson:gson:2.10.1'
shadow 'com.google.code.gson:gson:2.10.1'
implementation 'com.google.auto:auto-common:1.2.1'
shadow 'com.google.auto:auto-common:1.2.1'
implementation 'com.google.guava:guava:21.0'
shadow 'com.google.guava:guava:21.0'
implementation project(":annotations")
shadow project(":annotations")
// Shadow annotations
implementation 'net.fabricmc:sponge-mixin:0.12.5+'
implementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation 'net.minecraftforge:mergetool:1.1.7'
implementation 'net.neoforged:mergetool:2.0.2'
}
tasks.withType(JavaCompile) {
options.release = 17
}
shadowJar {
dependencies {
include(dependency('net.fabricmc:sponge-mixin:'))
include(dependency('net.fabricmc:fabric-loader:'))
include(dependency(':mergetool:'))
}
// 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'}
include {it.getName() == 'Dist.class'}
include {it.getName() == 'Environment.class'}
include {it.getName() == 'EnvType.class'}
}
version = '1.1.4'

View File

@ -0,0 +1,184 @@
package org.fury_phoenix.mixinAp.annotation;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import net.fabricmc.api.Environment;
import org.embeddedt.modernfix.annotation.ClientOnlyMixin;
import org.embeddedt.modernfix.annotation.IgnoreMixin;
import org.fury_phoenix.mixinAp.util.TypedAccessorMap;
import org.spongepowered.asm.mixin.Mixin;
import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
import static java.util.AbstractMap.SimpleImmutableEntry;
public class ClientMixinValidator {
private final Messager messager;
private final Elements elemUtils;
private final Types types;
private final boolean debug;
private static final TypedAccessorMap<Annotation> markers = new TypedAccessorMap<>();
private static final Map.Entry<Class<Environment>, Function<? super Environment, ?>>
FabricAccessor = new SimpleImmutableEntry<>(Environment.class, Environment::value);
private static final Map.Entry<
Class<net.minecraftforge.api.distmarker.OnlyIn>,
Function<? super net.minecraftforge.api.distmarker.OnlyIn, ?>>
ForgeAccessor = new SimpleImmutableEntry<>(
net.minecraftforge.api.distmarker.OnlyIn.class,
net.minecraftforge.api.distmarker.OnlyIn::value
);
private static final Map.Entry<
Class<net.neoforged.api.distmarker.OnlyIn>,
Function<? super net.neoforged.api.distmarker.OnlyIn, ?>>
NeoForgeAccessor = new SimpleImmutableEntry<>(
net.neoforged.api.distmarker.OnlyIn.class,
net.neoforged.api.distmarker.OnlyIn::value
);
static {
markers.put(FabricAccessor);
markers.put(ForgeAccessor);
markers.put(NeoForgeAccessor);
}
private static final Collection<String> unannotatedClasses = new HashSet<>();
public ClientMixinValidator(ProcessingEnvironment env) {
debug = Boolean.valueOf(env.getOptions().get("org.fury_phoenix.mixinAp.validator.debug"));
messager = env.getMessager();
elemUtils = env.getElementUtils();
types = env.getTypeUtils();
}
public boolean validateMixin(TypeElement annotatedMixinClass) {
return targetsClient(annotatedMixinClass) &&
(annotatedMixinClass.getAnnotation(ClientOnlyMixin.class) == null);
}
public boolean targetsClient(TypeElement annotatedMixinClass) {
return targetsClient(getTargets(annotatedMixinClass)) &&
!isIgnored(annotatedMixinClass);
}
private boolean targetsClient(Collection<?> classTargets) {
return classTargets.stream().anyMatch(this::targetsClient);
}
private boolean targetsClient(Object classTarget) {
if (classTarget instanceof TypeElement te) {
return isClientMarked(te);
} else if (classTarget instanceof TypeMirror tm) {
var el = types.asElement(tm);
return el != null ? targetsClient(el) : warn("TypeMirror of " + tm);
} else if (classTarget instanceof String s) {
var te = elemUtils.getTypeElement(toSourceString(s.split("\\$")[0]));
return te != null ? targetsClient(te) : warn(s);
} else {
throw new IllegalArgumentException("Unhandled type: "
+ classTarget.getClass() + "\n" + "Stringified contents: "
+ classTarget.toString());
}
}
private boolean isClientMarked(TypeElement te) {
for (var entry : markers.entrySet()) {
var marker = te.getAnnotation(entry.getKey());
if(marker == null) continue;
return entry.getValue().apply(marker).toString().equals("CLIENT");
}
if(debug && unannotatedClasses.add(te.toString())) {
messager.printMessage(Diagnostic.Kind.WARNING,
"No marker annotations present on " + te + "!");
}
return false;
}
private boolean isIgnored(TypeElement te) {
if(te.getAnnotation(IgnoreMixin.class) != null) {
messager.printMessage(Diagnostic.Kind.WARNING,
toSourceString(te.toString()) + " is ignored!");
return true;
}
return false;
}
private boolean warn(Object o) {
messager.printMessage(Diagnostic.Kind.WARNING,
toSourceString(o.toString()) + " can't be loaded, so it is skipped!");
return false;
}
public Map.Entry<? extends CharSequence, ? extends CharSequence>
getClientMixinEntry(TypeElement annotatedMixinClass) {
return new SimpleImmutableEntry<>(
annotatedMixinClass.getQualifiedName(),
getTargets(annotatedMixinClass)
.stream()
.filter(this::targetsClient)
.map(Object::toString)
.map(ClientMixinValidator::toSourceString)
.collect(Collectors.joining(", "))
);
}
private Collection<Object> getTargets(TypeElement annotatedMixinClass) {
Collection<? extends TypeMirror> clzsses = Set.of();
Collection<? extends String> imaginaries = Set.of();
TypeMirror MixinElement = elemUtils.getTypeElement(Mixin.class.getName()).asType();
for (var mirror : annotatedMixinClass.getAnnotationMirrors()) {
if(!types.isSameType(mirror.getAnnotationType(), MixinElement))
continue;
@SuppressWarnings("unchecked")
var wrappedClzss = (List<? extends AnnotationValue>)
getAnnotationValue(mirror, "value").getValue();
clzsses = wrappedClzss.stream()
.map(AnnotationValue::getValue)
.map(TypeMirror.class::cast)
.collect(Collectors.toSet());
@SuppressWarnings("unchecked")
var wrappedStrings = (List<? extends AnnotationValue>)
getAnnotationValue(mirror, "targets").getValue();
imaginaries = wrappedStrings.stream()
.map(AnnotationValue::getValue)
.map(String.class::cast)
.collect(Collectors.toSet());
}
return Stream.of(clzsses, imaginaries)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
public static String toSourceString(String bytecodeName) {
return bytecodeName.replaceAll("\\/", ".");
}
}

View File

@ -0,0 +1,118 @@
package org.fury_phoenix.mixinAp.annotation;
import com.google.auto.service.AutoService;
import com.google.common.base.Throwables;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
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"})
@AutoService(Processor.class)
public class MixinProcessor extends AbstractProcessor {
// Remember to call toString when using aliases
private static final Map<String, String> aliases = Map.of(
"Mixin", "mixins",
"ClientOnlyMixin", "client"
);
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 {
if(roundEnv.processingOver()){
filterMixinSets();
// create record for serialization, compute package name
String packageName = Optional.ofNullable(mixinConfigList.get("mixins"))
.orElse(mixinConfigList.get("client"))
.get(0).split("(?<=mixin)")[0];
finalizeMixinConfig();
new MixinConfig(packageName,
mixinConfigList.get("mixins"),
mixinConfigList.get("client")
).generateMixinConfig(processingEnv);
} else {
processMixins(annotations, roundEnv);
}
} catch (Exception e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Fatal error:" +
Throwables.getStackTraceAsString(e));
throw new RuntimeException(e);
// Halt the AP to prevent nonsense errors
}
return false;
}
private void processMixins(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
Set<? extends Element> annotatedMixins = roundEnv.getElementsAnnotatedWith(annotation);
Stream<TypeElement> mixinStream =
annotatedMixins.stream()
.map(TypeElement.class::cast);
validateCommonMixins(annotation, mixinStream);
List<String> mixins =
annotatedMixins.stream()
.map(TypeElement.class::cast)
.map(e -> processingEnv.getElementUtils().getBinaryName(e).toString())
.collect(Collectors.toList());
mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins);
}
}
private void filterMixinSets() {
List<String> commonSet = mixinConfigList.get("mixins");
if(commonSet == null) return;
commonSet.removeAll(mixinConfigList.get("client"));
}
private void validateCommonMixins(TypeElement annotation, Stream<TypeElement> mixins) {
if(!annotation.getSimpleName().toString().equals("Mixin"))
return;
ClientMixinValidator validator = new ClientMixinValidator(processingEnv);
// The implementation may throw a CME
mixins.sequential()
.filter(validator::validateMixin)
.map(validator::getClientMixinEntry)
.forEach(this::logClientClassTarget);
}
private void logClientClassTarget(Map.Entry<? extends CharSequence, ? extends CharSequence> mixin) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
"Mixin " + mixin.getKey() + " targets client-side classes: " + mixin.getValue());
}
private void finalizeMixinConfig() {
// relativize class names
for(var list : mixinConfigList.values()) {
list.replaceAll(className -> className.split("(?<=mixin.)")[1]);
}
}
}

View File

@ -0,0 +1,65 @@
package org.fury_phoenix.mixinAp.config;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.Optional;
import javax.annotation.processing.ProcessingEnvironment;
import javax.tools.StandardLocation;
public record MixinConfig(
boolean required,
String minVersion,
@SerializedName("package")
String packageName,
String plugin,
String compatibilityLevel,
@SerializedName("mixins")
List<String> commonMixins,
@SerializedName("client")
List<String> clientMixins,
InjectorOptions injectors, OverwriteOptions overwrites
) {
public MixinConfig(String packageName, List<String> commonMixins, List<String> clientMixins) {
this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_17",
commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT);
}
public record InjectorOptions(int defaultRequire) {
public static final InjectorOptions DEFAULT = new InjectorOptions(1);
}
public record OverwriteOptions(boolean conformVisibility) {
public static final OverwriteOptions DEFAULT = new OverwriteOptions(true);
}
public void generateMixinConfig(ProcessingEnvironment env) throws IOException {
try (
Writer mixinConfigWriter = env.getFiler()
.createResource(StandardLocation.SOURCE_OUTPUT, "",
MixinConfig.computeMixinConfigPath(
Optional.of(env.getOptions().get("rootProject.name")),
Optional.ofNullable(env.getOptions().get("project.name"))
)
).openWriter()
) {
String mixinConfig = new GsonBuilder()
.setPrettyPrinting()
.create()
.toJson(this);
mixinConfigWriter.write(mixinConfig);
mixinConfigWriter.write("\n");
} catch (IOException e) { throw e; }
}
private static String computeMixinConfigPath(Optional<String> rootProjectName, Optional<String> projectName) {
return "resources/" +
rootProjectName.get() +
(projectName.isPresent() ? "-" : "") +
projectName.orElse("") +
".mixins.json";
}
}

View File

@ -0,0 +1,37 @@
package org.fury_phoenix.mixinAp.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import static java.util.Map.Entry;
/**
* Type-safe heterogenous map of accessors
* @author Fury_Phoenix
* @reason Type-safety since K, V of Map are non-identical
* @param <SuperType> The supertype of desired types.
* This is useful in cases such as <A extends Annotation>.
*/
public class TypedAccessorMap<SuperType> {
private final Map<Class<? extends SuperType>, Function<Object, ?>> typedAccessors = new HashMap<>();
public <T extends SuperType> void put(Class<T> key, Function<? super T, ?> func) {
Objects.requireNonNull(func);
typedAccessors.put(Objects.requireNonNull(key), o -> func.apply(key.cast(o)));
}
public <T extends SuperType> void put(Entry<Class<T>, Function<? super T, ?>> entry) {
put(entry.getKey(), entry.getValue());
}
public <T extends SuperType> Function<Object, ?> get(Class<T> key) {
return typedAccessors.get(key);
}
public Set<Entry<Class<? extends SuperType>, Function<Object, ?>>> entrySet() {
return typedAccessors.entrySet();
}
}

View File

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

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,11 @@
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.SOURCE)
@Target(ElementType.TYPE)
public @interface IgnoreMixin {
}

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.3-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,81 +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 {
maven { url 'https://modmaven.dev/' }
maven {
url "https://cursemaven.com"
content {
includeGroup "curse.maven"
}
}
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org'
}
maven {
// Shedaniel's maven (Architectury API)
url = "https://maven.architectury.dev"
content {
includeGroup "me.shedaniel"
}
}
maven {
// saps.dev Maven (KubeJS and Rhino)
url = "https://maven.saps.dev/minecraft"
content {
includeGroup "dev.latvian.mods"
}
}
maven { // CTM
url "https://maven.tterrag.com/"
}
maven { url 'https://maven.blamejared.com' }
repositories {
maven {
name = "Fuzs Mod Resources"
url = "https://raw.githubusercontent.com/Fuzss/modresources/main/maven/"
}
}
maven {
url 'https://maven.terraformersmc.com/releases'
}
maven { url = "https://jitpack.io" }
}

View File

@ -1,52 +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")
}
}
}
tasks {
processResources {
def mixinFileList = []
def mixinDirectory = file("src/main/java/org/embeddedt/modernfix/" + project.name + "/mixin")
fileTree(mixinDirectory).visit { FileVisitDetails details ->
if(details.file.isFile()) {
def fileName = mixinDirectory.relativePath(details.file).toString().replaceFirst(/\.java$/, "").replace('/', '.')
mixinFileList << fileName
}
}
def mixinClassesStringB = new StringBuilder()
for(int i = 0; i < mixinFileList.size(); i++) {
mixinClassesStringB.append(" \"")
mixinClassesStringB.append(mixinFileList.get(i))
mixinClassesStringB.append('"')
if(i < (mixinFileList.size() - 1))
mixinClassesStringB.append(',')
mixinClassesStringB.append('\n')
}
def replacements = [
mixin_classes: mixinClassesStringB.toString()
]
inputs.properties replacements
def filePattern = "modernfix-" + project.name + ".mixins.json"
filesMatching(filePattern) {
expand replacements
}
}
}

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("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,54 +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("com.github.llamalad7.mixinextras: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("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,205 +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);
}
}
}
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,73 +0,0 @@
package org.embeddedt.modernfix.common.mixin.bugfix.chunk_deadlock;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.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(Registries.BIOME).getHolderOrThrow(Biomes.PLAINS);
cir.setReturnValue(new EmptyLevelChunk(this.level, new ChunkPos(chunkX, chunkZ), plains));
} else if(Thread.currentThread() != this.mainThread) {
CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> future = CompletableFuture.supplyAsync(() -> this.getChunkFutureMainThread(chunkX, chunkZ, requiredStatus, false), this.mainThreadProcessor).join();
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());
else
ModernFix.LOGGER.warn("Suspicious async chunkload, pass -Dmodernfix.debugBadChunkloading=true for more details");
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,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,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,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,68 +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.ChunkGeneratorStructureState;
import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.duck.IChunkGenerator;
import org.embeddedt.modernfix.duck.IServerLevel;
import org.embeddedt.modernfix.world.StrongholdLocationCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Mixin(ChunkGeneratorStructureState.class)
public class ChunkGeneratorMixin implements IChunkGenerator {
private WeakReference<ServerLevel> mfix$serverLevel;
@Override
public void mfix$setAssociatedServerLevel(ServerLevel level) {
mfix$serverLevel = new WeakReference<>(level);
}
@Inject(method = "generateRingPositions", at = @At("HEAD"), cancellable = true)
private void useCachedDataIfAvailable(Holder<StructureSet> structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
if(placement.count() == 0)
return;
ServerLevel level = searchLevel();
if(level == null)
return;
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
List<ChunkPos> positions = cache.getChunkPosList();
if(positions.isEmpty())
return;
ModernFix.LOGGER.debug("Loaded stronghold cache for dimension {} with {} positions", level.dimension().location(), positions.size());
cir.setReturnValue(CompletableFuture.completedFuture(positions));
}
private ServerLevel searchLevel() {
if(mfix$serverLevel != null)
return mfix$serverLevel.get();
else
return null;
}
@Inject(method = "generateRingPositions", at = @At("RETURN"), cancellable = true)
private void saveCachedData(Holder<StructureSet> structureSet, ConcentricRingsStructurePlacement placement, CallbackInfoReturnable<CompletableFuture<List<ChunkPos>>> cir) {
cir.setReturnValue(cir.getReturnValue().thenApplyAsync(list -> {
if(list.size() == 0)
return list;
ServerLevel level = searchLevel();
if(level != null) {
StrongholdLocationCache cache = ((IServerLevel)level).mfix$getStrongholdCache();
cache.setChunkPosList(list);
ModernFix.LOGGER.debug("Saved stronghold cache for dimension {}", level.dimension().location());
}
return list;
}, Util.backgroundExecutor()));
}
}

View File

@ -1,69 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.cache_strongholds;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.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.ChunkGeneratorStructureState;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
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, RegistryAccess arg3, Holder<DimensionType> arg4, Supplier<ProfilerFiller> supplier, boolean bl, boolean bl2, long l, int i) {
super(arg, arg2, arg3, arg4, 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/ChunkGeneratorStructureState;ensureStructuresGenerated()V"))
private void hookStrongholdCache(ChunkGeneratorStructureState generator) {
((IChunkGenerator)generator).mfix$setAssociatedServerLevel((ServerLevel)(Object)this);
}
/**
* Now start the stronghold generation process.
*/
@Inject(method = "<init>", at = @At("TAIL"))
private void ensureGeneration(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.getGeneratorState().ensureStructuresGenerated();
}
@Override
public StrongholdLocationCache mfix$getStrongholdCache() {
return mfix$strongholdCache;
}
}

View File

@ -1,24 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.compact_mojang_registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import org.embeddedt.modernfix.annotation.IgnoreOutsideDev;
import org.embeddedt.modernfix.registry.DirectStorageRegistryObject;
import org.spongepowered.asm.mixin.Mixin;
@Mixin({ Block.class, Item.class })
@IgnoreOutsideDev
public class DirectObjectMixin implements DirectStorageRegistryObject {
private ResourceLocation mfix$resourceKey;
@Override
public ResourceLocation mfix$getResourceKey() {
return mfix$resourceKey;
}
@Override
public void mfix$setResourceKey(ResourceLocation key) {
mfix$resourceKey = key;
}
}

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,26 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_block_codecs;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
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.ModifyVariable;
import java.util.Map;
import java.util.function.Function;
@Mixin(StateDefinition.class)
public class StateDefinitionMixin<O, S extends StateHolder<O, S>> {
@Shadow @Final private O owner;
@ModifyVariable(method = "<init>", at = @At("HEAD"), ordinal = 0, argsOnly = true)
private static <O, S extends StateHolder<O, S>> StateDefinition.Factory<O, S> replaceMapCodec(StateDefinition.Factory<O, S> factory, Function<O, S> function, O object, StateDefinition.Factory<O, S> factory2, Map<String, Property<?>> map) {
if(object instanceof Block)
return (o, m, c) -> factory.create(o, m, null);
return factory;
}
}

View File

@ -1,58 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_block_codecs;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Decoder;
import com.mojang.serialization.Encoder;
import com.mojang.serialization.MapCodec;
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.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.function.Supplier;
@Mixin(StateHolder.class)
public class StateHolderMixin {
private static final LoadingCache<Block, MapCodec<BlockState>> MODERNFIX_CODEC_CACHE = CacheBuilder.newBuilder()
.maximumSize(100000)
.build(new CacheLoader<Block, MapCodec<BlockState>>() {
@Override
public MapCodec<BlockState> load(Block block) throws Exception {
Supplier<BlockState> stateSupplier = block::defaultBlockState;
MapCodec<BlockState> mapCodec = MapCodec.of(Encoder.empty(), Decoder.unit(stateSupplier));
for(Property<?> property : block.getStateDefinition().getProperties()) {
mapCodec = StateDefinition.appendPropertyCodec(mapCodec, stateSupplier, property.getName(), property);
}
return mapCodec;
}
});
@Redirect(method = "codec", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;dispatch(Ljava/lang/String;Ljava/util/function/Function;Ljava/util/function/Function;)Lcom/mojang/serialization/Codec;", remap = false))
private static <O, S extends StateHolder<O, S>> Codec<S> obtainCodec(Codec<O> codec, String typeKey, Function<S, O> type, Function<O, ? extends Codec<S>> codecFn, Codec<O> codecMethodArg, Function<O, S> stateSupplier) {
return codec.dispatch(typeKey, type, block -> {
if(block instanceof Block) {
S state = stateSupplier.apply(block);
if(state.getValues().isEmpty())
return Codec.unit(state);
MapCodec<S> mapCodec;
try {
mapCodec = (MapCodec<S>)MODERNFIX_CODEC_CACHE.get((Block)block);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
return mapCodec.fieldOf("Properties").codec();
} else {
return codecFn.apply(block);
}
});
}
}

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,21 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.dynamic_resources;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.resources.model.BakedModel;
import org.embeddedt.modernfix.dynamicresources.ItemOverrideBakedModel;
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(ItemOverrides.class)
public class ItemOverridesMixin {
@Inject(method = "resolve", at = @At("RETURN"), cancellable = true)
private void getRealModel(CallbackInfoReturnable<BakedModel> cir) {
BakedModel original = cir.getReturnValue();
if(original instanceof ItemOverrideBakedModel) {
ItemOverrideBakedModel override = (ItemOverrideBakedModel)original;
cir.setReturnValue(override.getRealModel());
}
}
}

View File

@ -1,56 +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()) {
try {
appendDiagonalSelectors(((ModelBakeryAccessor)bakery)::diagonalfences$callCacheAndQueueDependencies, multipart, block instanceof IronBarsBlock);
} catch(RuntimeException e) {
e.printStackTrace();
}
}
}
return originalModel;
}
});
}
}

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,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,76 +0,0 @@
package org.embeddedt.modernfix.dynamicresources;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Delegate model that stores the location of an actual baked model, for use in ItemOverrides.
*/
public class ItemOverrideBakedModel implements BakedModel {
private static final Map<ResourceLocation, ItemOverrideBakedModel> OVERRIDE_MODELS = new ConcurrentHashMap<>();
public final ResourceLocation realLocation;
private ItemOverrideBakedModel(ResourceLocation realLocation) {
this.realLocation = realLocation;
}
public static ItemOverrideBakedModel of(ResourceLocation realLocation) {
return OVERRIDE_MODELS.computeIfAbsent(realLocation, ItemOverrideBakedModel::new);
}
public BakedModel getRealModel() {
return DynamicBakedModelProvider.currentInstance.get(realLocation);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction direction, RandomSource random) {
return getRealModel().getQuads(state, direction, random);
}
@Override
public boolean useAmbientOcclusion() {
return getRealModel().useAmbientOcclusion();
}
@Override
public boolean isGui3d() {
return getRealModel().isGui3d();
}
@Override
public boolean usesBlockLight() {
return getRealModel().usesBlockLight();
}
@Override
public boolean isCustomRenderer() {
return getRealModel().isCustomRenderer();
}
@Override
public TextureAtlasSprite getParticleIcon() {
return getRealModel().getParticleIcon();
}
@Override
public ItemTransforms getTransforms() {
return getRealModel().getTransforms();
}
@Override
public ItemOverrides getOverrides() {
return getRealModel().getOverrides();
}
}

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.registries.BuiltInRegistries;
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 {}", BuiltInRegistries.ENTITY_TYPE.getKey(key));
} catch(RuntimeException e) {
ModernFix.LOGGER.error("Failed to create entity model for " + BuiltInRegistries.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,184 +0,0 @@
package org.embeddedt.modernfix.registry;
import com.google.common.collect.BiMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@SuppressWarnings("unchecked")
public class DirectStorageBiMap<K, V> implements BiMap<K, V> {
private final Function<V, K> keyGetter;
private final BiConsumer<V, K> keySetter;
private final Map<K, V> forwardMap;
public DirectStorageBiMap(Function<V, K> keyGetter, BiConsumer<V, K> keySetter) {
Objects.requireNonNull(keyGetter);
Objects.requireNonNull(keySetter);
this.keyGetter = keyGetter;
this.keySetter = keySetter;
this.forwardMap = new Object2ObjectOpenHashMap<>();
}
@Override
public int size() {
return this.forwardMap.size();
}
@Override
public boolean isEmpty() {
return this.forwardMap.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return this.forwardMap.containsKey(o);
}
@Override
public boolean containsValue(Object o) {
return o != null && keyGetter.apply((V)o) != null;
}
@Override
public V get(Object o) {
return this.forwardMap.get(o);
}
@Override
public V put(K key, V value) {
if(this.forwardMap.containsKey(key) || (value != null && keyGetter.apply(value) != null))
throw new IllegalArgumentException("Already have mapping for " + key);
return forcePut(key, value);
}
@Override
public V remove(Object o) {
return put((K)o, null);
}
@Override
public V forcePut(K key, V value) {
V previousValue = this.forwardMap.put(key, value);
if(previousValue != null)
keySetter.accept(previousValue, null);
if(value != null)
keySetter.accept(value, key);
return previousValue;
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
map.forEach(this::put);
}
@Override
public void clear() {
for(V value : this.forwardMap.values()) {
if(value != null)
keySetter.accept(value, null);
}
this.forwardMap.clear();
}
@NotNull
@Override
public Set<K> keySet() {
return this.forwardMap.keySet();
}
@Override
public Set<V> values() {
return new HashSet<>(this.forwardMap.values());
}
@NotNull
@Override
public Set<Entry<K, V>> entrySet() {
return this.forwardMap.entrySet();
}
@Override
public BiMap<V, K> inverse() {
return new Reverse();
}
class Reverse implements BiMap<V, K> {
@Override
public int size() {
return DirectStorageBiMap.this.size();
}
@Override
public boolean isEmpty() {
return DirectStorageBiMap.this.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return DirectStorageBiMap.this.containsValue(o);
}
@Override
public boolean containsValue(Object o) {
return DirectStorageBiMap.this.containsKey(o);
}
@Override
public K get(Object o) {
return o == null ? null : keyGetter.apply((V)o);
}
@Override
public K put(V key, K value) {
throw new UnsupportedOperationException();
}
@Override
public K remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public K forcePut(V key, K value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends V, ? extends K> map) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Set<V> keySet() {
return DirectStorageBiMap.this.values();
}
@Override
public Set<K> values() {
return DirectStorageBiMap.this.keySet();
}
@NotNull
@Override
public Set<Entry<V, K>> entrySet() {
return DirectStorageBiMap.this.entrySet().stream()
.map(entry -> new AbstractMap.SimpleImmutableEntry<>(entry.getValue(), entry.getKey()))
.collect(Collectors.toSet());
}
@Override
public BiMap<K, V> inverse() {
return DirectStorageBiMap.this;
}
}
}

View File

@ -1,8 +0,0 @@
package org.embeddedt.modernfix.registry;
import net.minecraft.resources.ResourceLocation;
public interface DirectStorageRegistryObject {
ResourceLocation mfix$getResourceKey();
void mfix$setResourceKey(ResourceLocation key);
}

View File

@ -1,34 +0,0 @@
package org.embeddedt.modernfix.registry;
import com.google.common.collect.BiMap;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
import java.util.function.Function;
public class RegistryStorage {
public static BiMap<ResourceLocation, DirectStorageRegistryObject> createStorage() {
return new DirectStorageBiMap<>(DirectStorageRegistryObject::mfix$getResourceKey, DirectStorageRegistryObject::mfix$setResourceKey);
}
public static <T> BiMap<ResourceKey<T>, DirectStorageRegistryObject> createKeyStorage(ResourceKey<? extends Registry<T>> registryKey, BiMap<ResourceLocation, DirectStorageRegistryObject> storage) {
if(storage instanceof DirectStorageBiMap) {
DirectStorageBiMap<ResourceLocation, DirectStorageRegistryObject> directStorageBiMap = (DirectStorageBiMap<ResourceLocation, DirectStorageRegistryObject>)storage;
// silently ignore put/putAll calls on this map
return new TransformingBiMap<ResourceLocation, DirectStorageRegistryObject, ResourceKey<T>, DirectStorageRegistryObject>(directStorageBiMap, loc -> ResourceKey.create(registryKey, loc), ResourceKey::location, Function.identity(), Function.identity()) {
@Override
public DirectStorageRegistryObject put(ResourceKey<T> key, DirectStorageRegistryObject value) {
return null;
}
@Override
public void putAll(Map<? extends ResourceKey<T>, ? extends DirectStorageRegistryObject> map) {
}
};
} else
throw new UnsupportedOperationException();
}
}

View File

@ -1,224 +0,0 @@
package org.embeddedt.modernfix.registry;
import com.google.common.collect.BiMap;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterators;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Function;
public class TransformingBiMap<KFrom, VFrom, KTo, VTo> implements BiMap<KTo, VTo> {
private final BiMap<KFrom, VFrom> delegate;
private final Function<KFrom, KTo> keyFwd;
private final Function<KTo, KFrom> keyBack;
private final Function<VFrom, VTo> valueFwd;
private final Function<VTo, VFrom> valueBack;
public TransformingBiMap(BiMap<KFrom, VFrom> map, Function<KFrom, KTo> keyFwd, Function<KTo, KFrom> keyBack, Function<VFrom, VTo> valueFwd, Function<VTo, VFrom> valueBack) {
this.delegate = map;
this.keyFwd = keyFwd;
this.keyBack = keyBack;
this.valueFwd = valueFwd;
this.valueBack = valueBack;
}
private KFrom keyBack(KTo key) {
return key == null ? null : this.keyBack.apply(key);
}
private KTo keyFwd(KFrom key) {
return key == null ? null : this.keyFwd.apply(key);
}
private VFrom valueBack(VTo value) {
return value == null ? null : this.valueBack.apply(value);
}
private VTo valueFwd(VFrom value) {
return value == null ? null : this.valueFwd.apply(value);
}
@Override
public int size() {
return this.delegate.size();
}
@Override
public boolean isEmpty() {
return this.delegate.isEmpty();
}
@Override
public boolean containsKey(Object o) {
return this.delegate.containsKey(keyBack((KTo)o));
}
@Override
public boolean containsValue(Object o) {
return false;
}
@Override
public VTo get(Object o) {
return valueFwd(this.delegate.get(keyBack((KTo)o)));
}
@Override
public VTo put(KTo key, VTo value) {
return valueFwd(this.delegate.put(keyBack(key), valueBack(value)));
}
@Override
public VTo remove(Object o) {
return valueFwd(this.delegate.remove(keyBack((KTo)o)));
}
@Override
public VTo forcePut(KTo key, VTo value) {
return valueFwd(this.delegate.forcePut(keyBack(key), valueBack(value)));
}
@Override
public void putAll(Map<? extends KTo, ? extends VTo> map) {
map.forEach((key, value) -> {
this.delegate.put(keyBack(key), valueBack(value));
});
}
@Override
public void clear() {
this.delegate.clear();
}
@NotNull
@Override
public Set<KTo> keySet() {
return new TransformingSet<>(this.delegate.keySet(), this.keyFwd, this.keyBack);
}
@Override
public Set<VTo> values() {
return new TransformingSet<>(this.delegate.values(), this.valueFwd, this.valueBack);
}
@NotNull
@Override
public Set<Entry<KTo, VTo>> entrySet() {
return new TransformingSet<>(this.delegate.entrySet(), entry -> {
return new AbstractMap.SimpleImmutableEntry<>(keyFwd(entry.getKey()), valueFwd(entry.getValue()));
}, entry -> {
return new AbstractMap.SimpleImmutableEntry<>(keyBack(entry.getKey()), valueBack(entry.getValue()));
});
}
@Override
public BiMap<VTo, KTo> inverse() {
return new TransformingBiMap<>(this.delegate.inverse(), this.valueFwd, this.valueBack, this.keyFwd, this.keyBack);
}
static class TransformingSet<TypeFrom, TypeTo> implements Set<TypeTo> {
private final Set<TypeFrom> delegate;
private final Function<TypeFrom, TypeTo> forward;
private final Function<TypeTo, TypeFrom> reverse;
public TransformingSet(Set<TypeFrom> set, Function<TypeFrom, TypeTo> forward, Function<TypeTo, TypeFrom> reverse) {
this.delegate = set;
this.forward = forward;
this.reverse = reverse;
}
private TypeTo forward(TypeFrom t) {
return t == null ? null : this.forward.apply(t);
}
private TypeFrom reverse(TypeTo t) {
return t == null ? null : this.reverse.apply(t);
}
@Override
public int size() {
return this.delegate.size();
}
@Override
public boolean isEmpty() {
return this.delegate.isEmpty();
}
@Override
public boolean contains(Object o) {
return this.delegate.contains(reverse((TypeTo)o));
}
@NotNull
@Override
public Iterator<TypeTo> iterator() {
return Iterators.transform(this.delegate.iterator(), this::forward);
}
@NotNull
@Override
public Object[] toArray() {
Object[] array = this.delegate.toArray();
for(int i = 0; i < array.length; i++) {
array[i] = this.forward((TypeFrom)array[i]);
}
return array;
}
@NotNull
@Override
public <T> T[] toArray(@NotNull T[] ts) {
if(ts.length >= this.delegate.size()) {
Object[] setContents = toArray();
System.arraycopy(setContents, 0, ts, 0, Math.min(setContents.length, ts.length));
if(ts.length > setContents.length)
ts[setContents.length] = null;
return ts;
} else {
T[] realArray = Arrays.copyOf(ts, this.delegate.size());
Iterator<TypeTo> iterator = this.iterator();
int i = 0;
while(iterator.hasNext())
realArray[i++] = (T)iterator.next();
return realArray;
}
}
@Override
public boolean add(TypeTo typeFrom) {
return this.delegate.add(reverse(typeFrom));
}
@Override
public boolean remove(Object o) {
return this.delegate.remove(reverse((TypeTo)o));
}
@Override
public boolean containsAll(@NotNull Collection<?> collection) {
return this.delegate.containsAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj)));
}
@Override
public boolean addAll(@NotNull Collection<? extends TypeTo> collection) {
return this.delegate.addAll(Collections2.transform(collection, this::reverse));
}
@Override
public boolean retainAll(@NotNull Collection<?> collection) {
return this.delegate.retainAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj)));
}
@Override
public boolean removeAll(@NotNull Collection<?> collection) {
return this.delegate.removeAll(Collections2.transform(collection, obj -> reverse((TypeTo)obj)));
}
@Override
public void clear() {
this.delegate.clear();
}
}
}

View File

@ -1,101 +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) {
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,17 +0,0 @@
package org.embeddedt.modernfix.resources;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.resources.IoSupplier;
import java.io.InputStream;
import java.util.Collection;
import java.util.function.Function;
public class NewResourcePackAdapter {
public static void sendToOutput(Function<ResourceLocation, IoSupplier<InputStream>> streamCreator, PackResources.ResourceOutput output, Collection<ResourceLocation> locations) {
for(ResourceLocation rl : locations) {
output.accept(rl, streamCreator.apply(rl));
}
}
}

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,134 +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.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
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);
}
};
return new AsyncSearchManager(stackListSupplier, () -> {
return Predicates.alwaysTrue();
}, normalizeOperator);
} 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,155 +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.*;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.Difficulty;
import net.minecraft.world.level.levelgen.WorldOptions;
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 WorldDataConfiguration getDataConfiguration() {
return null;
}
@Override
public void setDataConfiguration(WorldDataConfiguration arg) {
}
@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 WorldOptions worldGenOptions() {
return null;
}
@Override
public boolean isFlatWorld() {
return false;
}
@Override
public boolean isDebugWorld() {
return false;
}
@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,13 +0,0 @@
{
"key.modernfix": "ModernFix",
"key.modernfix.config": "開啟設定介面",
"modernfix.jei_load": "正在載入 JEI這可能需要一點時間",
"modernfix.no_lazydfu": "沒有安裝 LazyDFU。如果 Minecraft 需要從舊版本更新遊戲資料,可能會出現明顯的延遲。",
"modernfix.config": "ModernFix 注入設定",
"modernfix.config.done_restart": "完成(需要重新啟動遊戲)",
"modernfix.option.on": "開啟",
"modernfix.option.off": "關閉",
"modernfix.config.not_default": "(已修改)",
"asynclocator.map.locating": "地圖(定位中...",
"asynclocator.map.none": "地圖(未找到附近的特徵)"
}

View File

@ -1,16 +0,0 @@
{
"required": true,
"minVersion": "0.8",
"package": "org.embeddedt.modernfix.common.mixin",
"plugin": "org.embeddedt.modernfix.core.ModernFixMixinPlugin",
"compatibilityLevel": "JAVA_17",
"mixins": [
${mixin_classes}
],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"conformVisibility": true
}
}

View File

@ -1,51 +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 field net/minecraft/client/renderer/block/model/BlockModel GSON Lcom/google/gson/Gson;
accessible class net/minecraft/server/level/ChunkMap$DistanceManager
accessible class net/minecraft/client/resources/model/ModelBakery$BakedCacheKey
accessible field net/minecraft/client/resources/model/ModelBakery bakedCache Ljava/util/Map;
accessible field net/minecraft/client/resources/model/ModelBakery ITEM_MODEL_GENERATOR Lnet/minecraft/client/renderer/block/model/ItemModelGenerator;
accessible method net/minecraft/client/resources/model/ModelBakery loadTopLevel (Lnet/minecraft/client/resources/model/ModelResourceLocation;)V
accessible field net/minecraft/client/resources/model/ModelBakery topLevelModels Ljava/util/Map;
accessible class net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl
accessible method net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl <init> (Lnet/minecraft/client/resources/model/ModelBakery;Ljava/util/function/BiFunction;Lnet/minecraft/resources/ResourceLocation;)V
accessible method net/minecraft/client/resources/model/ModelBakery$BakedCacheKey <init> (Lnet/minecraft/resources/ResourceLocation;Lcom/mojang/math/Transformation;Z)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/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;

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