mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-28 10:36:43 -05:00
Test fixes
This commit is contained in:
parent
4c89a6c135
commit
b01b9d36a7
8 changed files with 53 additions and 66 deletions
|
@ -20,10 +20,7 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.ComposterBlock;
|
import net.minecraft.block.ComposterBlock;
|
||||||
import net.minecraft.block.HopperBlock;
|
|
||||||
import net.minecraft.block.entity.AbstractFurnaceBlockEntity;
|
|
||||||
import net.minecraft.block.entity.BrewingStandBlockEntity;
|
import net.minecraft.block.entity.BrewingStandBlockEntity;
|
||||||
import net.minecraft.block.entity.HopperBlockEntity;
|
|
||||||
import net.minecraft.component.DataComponentTypes;
|
import net.minecraft.component.DataComponentTypes;
|
||||||
import net.minecraft.component.type.PotionContentsComponent;
|
import net.minecraft.component.type.PotionContentsComponent;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -34,7 +31,6 @@ import net.minecraft.test.GameTest;
|
||||||
import net.minecraft.test.TestContext;
|
import net.minecraft.test.TestContext;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
|
||||||
import net.minecraft.world.GameMode;
|
import net.minecraft.world.GameMode;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
||||||
|
@ -67,35 +63,6 @@ public class ContentRegistryGameTest {
|
||||||
context.complete();
|
context.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE, tickLimit = 110)
|
|
||||||
public void testFuelRegistry(TestContext context) {
|
|
||||||
BlockPos pos = new BlockPos(0, 1, 0);
|
|
||||||
// Use blast furnace to make it cook faster (100 ticks / 200 ticks)
|
|
||||||
context.setBlockState(pos, Blocks.BLAST_FURNACE);
|
|
||||||
|
|
||||||
if (!(context.getBlockEntity(pos) instanceof AbstractFurnaceBlockEntity furnace)) {
|
|
||||||
throw new AssertionError("Furnace was not placed");
|
|
||||||
}
|
|
||||||
|
|
||||||
furnace.setStack(0, new ItemStack(Items.RAW_IRON, 1));
|
|
||||||
// Ensure hopper inserts fuel to the furnace
|
|
||||||
context.setBlockState(pos.east(), Blocks.HOPPER.getDefaultState().with(HopperBlock.FACING, Direction.WEST));
|
|
||||||
|
|
||||||
if (!(context.getBlockEntity(pos.east()) instanceof HopperBlockEntity hopper)) {
|
|
||||||
throw new AssertionError("Hopper was not placed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 100 ticks/1 smelted item worth of fuel.
|
|
||||||
hopper.setStack(0, new ItemStack(Items.OBSIDIAN, 2));
|
|
||||||
hopper.setStack(1, new ItemStack(Items.DIRT));
|
|
||||||
|
|
||||||
context.waitAndRun(105, () -> {
|
|
||||||
context.assertTrue(hopper.isEmpty(), "fuel hopper should have been emptied");
|
|
||||||
context.assertTrue(ItemStack.areEqual(furnace.getStack(2), new ItemStack(Items.IRON_INGOT, 1)), "one iron ingot should have been smelted");
|
|
||||||
context.complete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
|
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
|
||||||
public void testStrippableBlockRegistry(TestContext context) {
|
public void testStrippableBlockRegistry(TestContext context) {
|
||||||
BlockPos pos = new BlockPos(0, 1, 0);
|
BlockPos pos = new BlockPos(0, 1, 0);
|
||||||
|
|
|
@ -16,27 +16,21 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.mixin.event.lifecycle.client;
|
package net.fabricmc.fabric.mixin.event.lifecycle.client;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Final;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.network.ClientConfigurationNetworkHandler;
|
||||||
import net.minecraft.network.packet.s2c.common.SynchronizeTagsS2CPacket;
|
|
||||||
import net.minecraft.registry.DynamicRegistryManager;
|
import net.minecraft.registry.DynamicRegistryManager;
|
||||||
|
import net.minecraft.resource.ResourceFactory;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents;
|
||||||
|
|
||||||
@Mixin(ClientPlayNetworkHandler.class)
|
@Mixin(ClientConfigurationNetworkHandler.class)
|
||||||
public class ClientTagLoaderMixin {
|
public class ClientConfigurationNetworkHandlerMixin {
|
||||||
@Shadow
|
@Inject(method = "method_57043", at = @At(value = "RETURN"))
|
||||||
@Final
|
private void invokeTagsLoaded(ResourceFactory factory, CallbackInfoReturnable<DynamicRegistryManager.Immutable> cir) {
|
||||||
private DynamicRegistryManager.Immutable combinedDynamicRegistries;
|
CommonLifecycleEvents.TAGS_LOADED.invoker().onTagsLoaded(cir.getReturnValue(), true);
|
||||||
|
|
||||||
@Inject(method = "onSynchronizeTags", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/FuelRegistry;createDefault(Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;Lnet/minecraft/resource/featuretoggle/FeatureSet;)Lnet/minecraft/item/FuelRegistry;"))
|
|
||||||
private void invokeTagsLoaded(SynchronizeTagsS2CPacket packet, CallbackInfo ci) {
|
|
||||||
CommonLifecycleEvents.TAGS_LOADED.invoker().onTagsLoaded(combinedDynamicRegistries, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.mixin.event.lifecycle.client;
|
package net.fabricmc.fabric.mixin.event.lifecycle.client;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
@ -26,12 +27,15 @@ import net.minecraft.block.entity.BlockEntity;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.network.packet.s2c.common.SynchronizeTagsS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
|
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
|
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
|
||||||
|
import net.minecraft.registry.DynamicRegistryManager;
|
||||||
import net.minecraft.world.chunk.WorldChunk;
|
import net.minecraft.world.chunk.WorldChunk;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents;
|
||||||
import net.fabricmc.fabric.impl.event.lifecycle.LoadedChunksCache;
|
import net.fabricmc.fabric.impl.event.lifecycle.LoadedChunksCache;
|
||||||
|
|
||||||
@Mixin(ClientPlayNetworkHandler.class)
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
|
@ -39,6 +43,10 @@ abstract class ClientPlayNetworkHandlerMixin {
|
||||||
@Shadow
|
@Shadow
|
||||||
private ClientWorld world;
|
private ClientWorld world;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private DynamicRegistryManager.Immutable combinedDynamicRegistries;
|
||||||
|
|
||||||
@Inject(method = "onPlayerRespawn", at = @At(value = "NEW", target = "net/minecraft/client/world/ClientWorld"))
|
@Inject(method = "onPlayerRespawn", at = @At(value = "NEW", target = "net/minecraft/client/world/ClientWorld"))
|
||||||
private void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) {
|
private void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) {
|
||||||
// If a world already exists, we need to unload all (block)entities in the world.
|
// If a world already exists, we need to unload all (block)entities in the world.
|
||||||
|
@ -93,4 +101,9 @@ abstract class ClientPlayNetworkHandlerMixin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onSynchronizeTags", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/FuelRegistry;createDefault(Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;Lnet/minecraft/resource/featuretoggle/FeatureSet;)Lnet/minecraft/item/FuelRegistry;"))
|
||||||
|
private void invokeTagsLoaded(SynchronizeTagsS2CPacket packet, CallbackInfo ci) {
|
||||||
|
CommonLifecycleEvents.TAGS_LOADED.invoker().onTagsLoaded(combinedDynamicRegistries, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"client": [
|
"client": [
|
||||||
"ClientChunkManagerMixin",
|
"ClientChunkManagerMixin",
|
||||||
"ClientPlayNetworkHandlerMixin",
|
"ClientPlayNetworkHandlerMixin",
|
||||||
"ClientTagLoaderMixin",
|
"ClientConfigurationNetworkHandlerMixin",
|
||||||
"ClientWorldClientEntityHandlerMixin",
|
"ClientWorldClientEntityHandlerMixin",
|
||||||
"ClientWorldMixin",
|
"ClientWorldMixin",
|
||||||
"MinecraftClientMixin",
|
"MinecraftClientMixin",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
|
@ -54,10 +55,15 @@ public class AllIngredient extends CombinedIngredient {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RegistryEntry<Item>> getMatchingStacks() {
|
public List<RegistryEntry<Item>> getMatchingStacks() {
|
||||||
return ingredients.stream()
|
// There's always at least one sub ingredient, so accessing ingredients[0] is safe.
|
||||||
.flatMap(ingredient -> ingredient.getMatchingStacks().stream())
|
List<RegistryEntry<Item>> previewStacks = new ArrayList<>(ingredients.getFirst().getMatchingStacks());
|
||||||
.distinct()
|
|
||||||
.toList();
|
for (int i = 1; i < ingredients.size(); ++i) {
|
||||||
|
Ingredient ing = ingredients.get(i);
|
||||||
|
previewStacks.removeIf(entry -> !ing.test(entry.value().getDefaultStack()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return previewStacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
|
@ -54,10 +55,13 @@ public class AnyIngredient extends CombinedIngredient {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RegistryEntry<Item>> getMatchingStacks() {
|
public List<RegistryEntry<Item>> getMatchingStacks() {
|
||||||
return ingredients.stream()
|
List<RegistryEntry<Item>> previewStacks = new ArrayList<>();
|
||||||
.flatMap(ingredient -> ingredient.getMatchingStacks().stream())
|
|
||||||
.distinct()
|
for (Ingredient ingredient : ingredients) {
|
||||||
.toList();
|
previewStacks.addAll(ingredient.getMatchingStacks());
|
||||||
|
}
|
||||||
|
|
||||||
|
return previewStacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class IngredientMatchTests {
|
||||||
Ingredient allIngredient = DefaultCustomIngredients.all(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
Ingredient allIngredient = DefaultCustomIngredients.all(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
||||||
|
|
||||||
assertEquals(1, allIngredient.getMatchingStacks().size());
|
assertEquals(1, allIngredient.getMatchingStacks().size());
|
||||||
assertEquals(Items.CARROT, allIngredient.getMatchingStacks().getFirst());
|
assertEquals(Items.CARROT, allIngredient.getMatchingStacks().getFirst().value());
|
||||||
assertEquals(false, allIngredient.getMatchingStacks().isEmpty());
|
assertEquals(false, allIngredient.getMatchingStacks().isEmpty());
|
||||||
|
|
||||||
assertEquals(false, allIngredient.test(new ItemStack(Items.APPLE)));
|
assertEquals(false, allIngredient.test(new ItemStack(Items.APPLE)));
|
||||||
|
@ -66,10 +66,10 @@ public class IngredientMatchTests {
|
||||||
Ingredient anyIngredient = DefaultCustomIngredients.any(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
Ingredient anyIngredient = DefaultCustomIngredients.any(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
||||||
|
|
||||||
assertEquals(4, anyIngredient.getMatchingStacks().size());
|
assertEquals(4, anyIngredient.getMatchingStacks().size());
|
||||||
assertEquals(Items.APPLE, anyIngredient.getMatchingStacks().getFirst());
|
assertEquals(Items.APPLE, anyIngredient.getMatchingStacks().getFirst().value());
|
||||||
assertEquals(Items.CARROT, anyIngredient.getMatchingStacks().get(1));
|
assertEquals(Items.CARROT, anyIngredient.getMatchingStacks().get(1).value());
|
||||||
assertEquals(Items.STICK, anyIngredient.getMatchingStacks().get(2));
|
assertEquals(Items.STICK, anyIngredient.getMatchingStacks().get(2).value());
|
||||||
assertEquals(Items.CARROT, anyIngredient.getMatchingStacks().get(3));
|
assertEquals(Items.CARROT, anyIngredient.getMatchingStacks().get(3).value());
|
||||||
assertEquals(false, anyIngredient.getMatchingStacks().isEmpty());
|
assertEquals(false, anyIngredient.getMatchingStacks().isEmpty());
|
||||||
|
|
||||||
assertEquals(true, anyIngredient.test(new ItemStack(Items.APPLE)));
|
assertEquals(true, anyIngredient.test(new ItemStack(Items.APPLE)));
|
||||||
|
@ -84,7 +84,7 @@ public class IngredientMatchTests {
|
||||||
Ingredient differenceIngredient = DefaultCustomIngredients.difference(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
Ingredient differenceIngredient = DefaultCustomIngredients.difference(Ingredient.ofItems(Items.APPLE, Items.CARROT), Ingredient.ofItems(Items.STICK, Items.CARROT));
|
||||||
|
|
||||||
assertEquals(1, differenceIngredient.getMatchingStacks().size());
|
assertEquals(1, differenceIngredient.getMatchingStacks().size());
|
||||||
assertEquals(Items.APPLE, differenceIngredient.getMatchingStacks().getFirst());
|
assertEquals(Items.APPLE, differenceIngredient.getMatchingStacks().getFirst().value());
|
||||||
assertEquals(false, differenceIngredient.getMatchingStacks().isEmpty());
|
assertEquals(false, differenceIngredient.getMatchingStacks().isEmpty());
|
||||||
|
|
||||||
assertEquals(true, differenceIngredient.test(new ItemStack(Items.APPLE)));
|
assertEquals(true, differenceIngredient.test(new ItemStack(Items.APPLE)));
|
||||||
|
@ -195,7 +195,8 @@ public class IngredientMatchTests {
|
||||||
List<RegistryEntry<Item>> matchingStacks = customDataIngredient.getMatchingStacks();
|
List<RegistryEntry<Item>> matchingStacks = customDataIngredient.getMatchingStacks();
|
||||||
assertEquals(1, matchingStacks.size());
|
assertEquals(1, matchingStacks.size());
|
||||||
assertEquals(Items.STICK, matchingStacks.getFirst().value());
|
assertEquals(Items.STICK, matchingStacks.getFirst().value());
|
||||||
assertEquals(NbtComponent.of(requiredNbt), matchingStacks.getFirst().value().getDefaultStack().get(DataComponentTypes.CUSTOM_DATA));
|
// Test disabled as the vanilla API no longer exposes the stack with data.
|
||||||
|
// assertEquals(NbtComponent.of(requiredNbt), matchingStacks.getFirst().value().getDefaultStack().get(DataComponentTypes.CUSTOM_DATA));
|
||||||
|
|
||||||
context.complete();
|
context.complete();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.mojang.serialization.JsonOps;
|
||||||
|
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.recipe.Ingredient;
|
import net.minecraft.recipe.Ingredient;
|
||||||
|
import net.minecraft.registry.RegistryOps;
|
||||||
import net.minecraft.test.GameTest;
|
import net.minecraft.test.GameTest;
|
||||||
import net.minecraft.test.GameTestException;
|
import net.minecraft.test.GameTestException;
|
||||||
import net.minecraft.test.TestContext;
|
import net.minecraft.test.TestContext;
|
||||||
|
@ -71,17 +72,18 @@ public class SerializationTests {
|
||||||
public void testCustomIngredientSerialization(TestContext context) {
|
public void testCustomIngredientSerialization(TestContext context) {
|
||||||
for (boolean allowEmpty : List.of(false, true)) {
|
for (boolean allowEmpty : List.of(false, true)) {
|
||||||
String ingredientJson = """
|
String ingredientJson = """
|
||||||
{"ingredients":[{"item":"minecraft:stone"}],"fabric:type":"fabric:all"}
|
{"ingredients":["minecraft:stone"],"fabric:type":"fabric:all"}
|
||||||
""".trim();
|
""".trim();
|
||||||
|
|
||||||
|
RegistryOps<JsonElement> registryOps = context.getWorld().getRegistryManager().getOps(JsonOps.INSTANCE);
|
||||||
Ingredient ingredient = DefaultCustomIngredients.all(
|
Ingredient ingredient = DefaultCustomIngredients.all(
|
||||||
Ingredient.ofItems(Items.STONE)
|
Ingredient.ofItems(Items.STONE)
|
||||||
);
|
);
|
||||||
Codec<Ingredient> ingredientCodec = Ingredient.CODEC;
|
Codec<Ingredient> ingredientCodec = Ingredient.CODEC;
|
||||||
JsonObject json = ingredientCodec.encodeStart(JsonOps.INSTANCE, ingredient).getOrThrow(IllegalStateException::new).getAsJsonObject();
|
JsonObject json = ingredientCodec.encodeStart(registryOps, ingredient).getOrThrow(IllegalStateException::new).getAsJsonObject();
|
||||||
context.assertTrue(json.toString().equals(ingredientJson), "Unexpected json: " + json);
|
context.assertTrue(json.toString().equals(ingredientJson), "Unexpected json: " + json);
|
||||||
// Make sure that we can deserialize it
|
// Make sure that we can deserialize it
|
||||||
Ingredient deserialized = ingredientCodec.parse(JsonOps.INSTANCE, json).getOrThrow(JsonParseException::new);
|
Ingredient deserialized = ingredientCodec.parse(registryOps, json).getOrThrow(JsonParseException::new);
|
||||||
context.assertTrue(deserialized.getCustomIngredient() != null, "Custom ingredient was not deserialized");
|
context.assertTrue(deserialized.getCustomIngredient() != null, "Custom ingredient was not deserialized");
|
||||||
context.assertTrue(deserialized.getCustomIngredient().getSerializer() == ingredient.getCustomIngredient().getSerializer(), "Serializer did not match");
|
context.assertTrue(deserialized.getCustomIngredient().getSerializer() == ingredient.getCustomIngredient().getSerializer(), "Serializer did not match");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue