Skip to content

Commit aa31256

Browse files
committed
Merge remote-tracking branch 'origin/1.20' into 1.21.1
2 parents 7dcaa6b + 5048e74 commit aa31256

File tree

4 files changed

+90
-4
lines changed

4 files changed

+90
-4
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.embeddedt.modernfix.neoforge.load;
2+
3+
public class MinecraftServerReloadTracker {
4+
public static int ACTIVE_RELOADS = 0;
5+
6+
public static boolean isReloadActive() {
7+
return ACTIVE_RELOADS > 0;
8+
}
9+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.embeddedt.modernfix.neoforge.mixin.core;
2+
3+
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
4+
import net.minecraft.server.MinecraftServer;
5+
import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.Inject;
9+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
10+
11+
import java.util.Collection;
12+
import java.util.concurrent.CompletableFuture;
13+
import java.util.concurrent.Executor;
14+
15+
@Mixin(MinecraftServer.class)
16+
public class MinecraftServerMixin {
17+
@Inject(method = "reloadResources", at = @At("HEAD"))
18+
private void startReloadTrack(Collection<String> selectedIds, CallbackInfoReturnable<CompletableFuture<Void>> cir) {
19+
MinecraftServerReloadTracker.ACTIVE_RELOADS++;
20+
}
21+
22+
@ModifyExpressionValue(method = "reloadResources", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;thenAcceptAsync(Ljava/util/function/Consumer;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0))
23+
private CompletableFuture<Void> mfix$endReloadTrack(CompletableFuture<Void> original) {
24+
return original.thenAcceptAsync(val -> {
25+
MinecraftServerReloadTracker.ACTIVE_RELOADS--;
26+
}, (Executor)this);
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.embeddedt.modernfix.neoforge.mixin.core;
2+
3+
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
4+
import com.llamalad7.mixinextras.sugar.Local;
5+
import net.minecraft.server.WorldLoader;
6+
import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
11+
12+
import java.util.concurrent.CompletableFuture;
13+
import java.util.concurrent.Executor;
14+
15+
@Mixin(WorldLoader.class)
16+
public class WorldLoaderMixin {
17+
@Inject(method = "load", at = @At("HEAD"))
18+
private static void trackStartReload(CallbackInfoReturnable<CompletableFuture<?>> cir) {
19+
MinecraftServerReloadTracker.ACTIVE_RELOADS++;
20+
}
21+
22+
@ModifyReturnValue(method = "load", at = @At("RETURN"))
23+
private static <V> CompletableFuture<V> trackEndReload(CompletableFuture<V> original, @Local(ordinal = 1, argsOnly = true) Executor syncExecutor) {
24+
return original.thenApplyAsync(val -> {
25+
MinecraftServerReloadTracker.ACTIVE_RELOADS--;
26+
return val;
27+
}, syncExecutor);
28+
}
29+
}

neoforge/src/main/java/org/embeddedt/modernfix/neoforge/mixin/perf/faster_ingredients/IngredientMixin.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import net.minecraft.world.item.ItemStackLinkedSet;
99
import net.minecraft.world.item.crafting.Ingredient;
1010
import net.neoforged.neoforge.common.crafting.ICustomIngredient;
11+
import org.embeddedt.modernfix.neoforge.load.MinecraftServerReloadTracker;
1112
import org.embeddedt.modernfix.neoforge.recipe.ExtendedIngredient;
1213
import org.embeddedt.modernfix.neoforge.recipe.IngredientItemStacksSoftReference;
1314
import org.jetbrains.annotations.Nullable;
@@ -43,13 +44,32 @@ private boolean isVanilla() {
4344

4445
private volatile IngredientItemStacksSoftReference mfix$cachedItemStacks;
4546

47+
/**
48+
* Minecraft's server resource loading process has a design flaw in that tags are loaded, recipes are loaded,
49+
* then tags are bound to the server registries. This results in recipe modification mods like KubeJS/CraftTweaker
50+
* not being able to use Ingredient.test reliably as the TagValue will not find any contents for the given tag.
51+
* To work around this issue these mods track tag context themselves and then patch TagValue.getItems to use it
52+
* during the resource reload process. We often bypass Value.getItems, so we must disable that bypass
53+
* whenever a server reload is in progress.
54+
* <p>
55+
* An alternative fix would be to bind tags ourselves when the recipe manager reload begins, before control is
56+
* handed to these mods. However, it's unclear if there would be any negative side effects from binding tags early
57+
* like this. Moreover, this fix would only work if the mod-provided patches to getItems read exactly what the
58+
* registry would normally contain, rather than a modified version.
59+
* <p>
60+
* Note: this is a separate problem from the issue where clients may receive recipes before tags in 1.21.
61+
*/
62+
private boolean mfix$areTagsAvailable() {
63+
return !MinecraftServerReloadTracker.isReloadActive();
64+
}
65+
4666
/**
4767
* @author embeddedt
4868
* @reason tag ingredients can be tested without iterating over all items
4969
*/
5070
@Inject(method = "test(Lnet/minecraft/world/item/ItemStack;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true)
5171
private void modernfix$fasterTagIngredientTest(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
52-
if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue) {
72+
if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
5373
cir.setReturnValue(stack.getItemHolder().is(tagValue.tag()));
5474
}
5575
}
@@ -75,7 +95,7 @@ private boolean containsItems() {
7595
for (Ingredient.Value value : this.values) {
7696
if (value instanceof Ingredient.ItemValue) {
7797
return true;
78-
} else if (value instanceof Ingredient.TagValue tagValue) {
98+
} else if (value instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
7999
var holderSetOpt = BuiltInRegistries.ITEM.getTag(tagValue.tag());
80100
if (holderSetOpt.isPresent() && holderSetOpt.get().size() > 0) {
81101
return true;
@@ -99,7 +119,7 @@ private boolean containsItems() {
99119
*/
100120
@Inject(method = "getStackingIds", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/crafting/Ingredient;getItems()[Lnet/minecraft/world/item/ItemStack;"), cancellable = true)
101121
private void modernfix$fasterTagIngredientStacking(CallbackInfoReturnable<IntList> cir) {
102-
if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue) {
122+
if (this.isVanilla() && this.values.length == 1 && this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
103123
var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag());
104124
if (!tag.isPresent() || tag.get().size() == 0) {
105125
return;
@@ -144,7 +164,7 @@ private ItemStack[] computeItemsArray() {
144164
if (this.values.length == 1) {
145165
if (this.values[0] instanceof Ingredient.ItemValue itemValue) {
146166
return new ItemStack[] { itemValue.item() };
147-
} else if (this.values[0] instanceof Ingredient.TagValue tagValue) {
167+
} else if (this.values[0] instanceof Ingredient.TagValue tagValue && mfix$areTagsAvailable()) {
148168
var tag = BuiltInRegistries.ITEM.getTag(tagValue.tag());
149169
if (tag.isPresent() && tag.get().size() > 0) {
150170
var holderSet = tag.get();

0 commit comments

Comments
 (0)