diff --git a/README.md b/README.md
index 16902097..0df351e2 100644
--- a/README.md
+++ b/README.md
@@ -355,8 +355,8 @@ This list may not always be up-to-date. To view an updated list, click [here](ht
License disclaimers
-This work, "PolyPatcher", uses code from CaffeineMC's "lithium-fabric", licensed under the LGPL-3.0 license. The original license is included in the repository.
-https://github.com/CaffeineMC/lithium-fabric/tree/develop
-https://github.com/CaffeineMC/lithium-fabric/blob/develop/LICENSE.txt
+PolyPatcher uses code from [CaffeineMC's lithium mod](https://github.com/CaffeineMC/lithium-fabric/tree/develop), licensed under the [LGPL-3.0 license](https://github.com/CaffeineMC/lithium-fabric/blob/develop/LICENSE.txt).
+
+PolyPatcher uses code from [CaffeineMC's hydrogen mod](https://github.com/CaffeineMC/hydrogen-fabric/tree/develop), licensed under the [LGPL-3.0 license](https://github.com/CaffeineMC/hydrogen-fabric/blob/1.17.x/LICENSE.txt).
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a4413138..9355b415 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/src/main/java/club/sk1er/patcher/mixins/performance/ResourceLocation_Deduplicate.java b/src/main/java/club/sk1er/patcher/mixins/performance/ResourceLocation_Deduplicate.java
new file mode 100644
index 00000000..b3535171
--- /dev/null
+++ b/src/main/java/club/sk1er/patcher/mixins/performance/ResourceLocation_Deduplicate.java
@@ -0,0 +1,33 @@
+package club.sk1er.patcher.mixins.performance;
+
+import me.jellysquid.mods.hydrogen.common.dedup.IdentifierCaches;
+import net.minecraft.util.ResourceLocation;
+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;
+
+/**
+ * From CaffeineMC/hydrogen-fabric under GNU LGPL v3.0
+ */
+@Mixin(ResourceLocation.class)
+public class ResourceLocation_Deduplicate {
+ @Shadow
+ @Final
+ @Mutable
+ protected String resourceDomain;
+
+ @Shadow
+ @Final
+ @Mutable
+ protected String resourcePath;
+
+ @Inject(method = "(I[Ljava/lang/String;)V", at = @At("RETURN"))
+ private void reinit(int what, String[] id, CallbackInfo ci) {
+ this.resourceDomain = IdentifierCaches.NAMESPACES.deduplicate(this.resourceDomain);
+ this.resourcePath = IdentifierCaches.PATH.deduplicate(this.resourcePath);
+ }
+}
diff --git a/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/DeduplicationCache.java b/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/DeduplicationCache.java
new file mode 100644
index 00000000..f1a3883f
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/DeduplicationCache.java
@@ -0,0 +1,56 @@
+package me.jellysquid.mods.hydrogen.common.dedup;
+
+import it.unimi.dsi.fastutil.Hash;
+import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
+
+import java.util.Objects;
+
+public class DeduplicationCache {
+ private final ObjectOpenCustomHashSet pool;
+
+ private int attemptedInsertions = 0;
+ private int deduplicated = 0;
+
+ public DeduplicationCache(Hash.Strategy strategy) {
+ this.pool = new ObjectOpenCustomHashSet<>(strategy);
+ }
+
+ public DeduplicationCache() {
+ this.pool = new ObjectOpenCustomHashSet<>(new Hash.Strategy() {
+ @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());
+ }
+}
diff --git a/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/IdentifierCaches.java b/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/IdentifierCaches.java
new file mode 100644
index 00000000..69246b3e
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/hydrogen/common/dedup/IdentifierCaches.java
@@ -0,0 +1,6 @@
+package me.jellysquid.mods.hydrogen.common.dedup;
+
+public class IdentifierCaches {
+ public static final DeduplicationCache NAMESPACES = new DeduplicationCache<>();
+ public static final DeduplicationCache PATH = new DeduplicationCache<>();
+}
diff --git a/src/main/resources/mixins.patcher.json b/src/main/resources/mixins.patcher.json
index ffe86c3c..90a59493 100644
--- a/src/main/resources/mixins.patcher.json
+++ b/src/main/resources/mixins.patcher.json
@@ -249,6 +249,7 @@
"performance.RenderChunkMixin_OptimizeSpecialTileEntities",
"performance.RenderEntityItemMixin_EntityCulling",
"performance.RenderGlobalMixin_LimitVisGraphScan",
+ "performance.ResourceLocation_Deduplicate",
"performance.ResourcePackRepositoryMixin_FasterSearching",
"performance.SimpleReloadableResourceManager_OnlyRefreshNecessaryListeners",
"performance.TexturedQuadMixin_BatchDraw",