mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-14 19:25:23 -05:00
24w09a (#3623)
* In game * More fixes * Small fixes + changes * Rename * Fix test
This commit is contained in:
parent
c81ced1dbb
commit
1172e89799
53 changed files with 441 additions and 709 deletions
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.test.lookup.item;
|
|||
|
||||
import static net.fabricmc.fabric.test.lookup.FabricApiLookupTest.ensureException;
|
||||
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.item.ToolItem;
|
||||
|
@ -41,7 +42,7 @@ public class FabricItemApiLookupTest {
|
|||
|
||||
// Diamonds and diamond blocks can be inspected and will also print their name.
|
||||
INSPECTABLE.registerForItems((stack, ignored) -> () -> {
|
||||
if (stack.hasCustomName()) {
|
||||
if (stack.contains(DataComponentTypes.CUSTOM_NAME)) {
|
||||
return stack.getName();
|
||||
} else {
|
||||
return Text.literal("Unnamed gem.");
|
||||
|
|
|
@ -44,16 +44,4 @@ public class LandPathNodeMakerMixin {
|
|||
cir.setReturnValue(nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the node type for the specified position, if the position is found as neighbor block in a path.
|
||||
*/
|
||||
@Inject(method = "getNodeTypeFromNeighbors", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/entity/ai/pathing/LandPathNodeMaker;getCommonNodeType(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/entity/ai/pathing/PathNodeType;"), cancellable = true)
|
||||
private static void getNodeTypeFromNeighbors(BlockView world, BlockPos.Mutable pos, PathNodeType nodeType, CallbackInfoReturnable<PathNodeType> cir) {
|
||||
PathNodeType neighborNodeType = LandPathNodeTypesRegistry.getPathNodeType(world.getBlockState(pos), world, pos, true);
|
||||
|
||||
if (neighborNodeType != null) {
|
||||
cir.setReturnValue(neighborNodeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.content.registry;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
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 net.minecraft.block.BlockState;
|
||||
import net.minecraft.class_9316;
|
||||
import net.minecraft.entity.ai.pathing.PathNodeType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.CollisionView;
|
||||
|
||||
import net.fabricmc.fabric.api.registry.LandPathNodeTypesRegistry;
|
||||
|
||||
@Mixin(class_9316.class)
|
||||
public abstract class class_9316Mixin {
|
||||
@Shadow
|
||||
public abstract BlockState method_57623(BlockPos blockPos);
|
||||
|
||||
@Shadow
|
||||
public abstract CollisionView method_57621();
|
||||
|
||||
/**
|
||||
* Overrides the node type for the specified position, if the position is found as neighbor block in a path.
|
||||
*/
|
||||
@Inject(method = "method_57622", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/math/BlockPos$Mutable;set(III)Lnet/minecraft/util/math/BlockPos$Mutable;"), cancellable = true)
|
||||
private void method_57622(int x, int y, int z, CallbackInfoReturnable<PathNodeType> cir, @Local BlockPos pos) {
|
||||
final PathNodeType neighborNodeType = LandPathNodeTypesRegistry.getPathNodeType(method_57623(pos), method_57621(), pos, true);
|
||||
|
||||
if (neighborNodeType != null) {
|
||||
cir.setReturnValue(neighborNodeType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"AxeItemAccessor",
|
||||
"class_9316Mixin",
|
||||
"FarmerWorkTaskAccessor",
|
||||
"GiveGiftsToHeroTaskAccessor",
|
||||
"HoeItemAccessor",
|
||||
|
|
|
@ -50,7 +50,7 @@ public class AttachmentSerializingImpl {
|
|||
Codec<Object> codec = (Codec<Object>) type.persistenceCodec();
|
||||
|
||||
if (codec != null) {
|
||||
RegistryOps<NbtElement> registryOps = wrapperLookup.method_57093(NbtOps.INSTANCE);
|
||||
RegistryOps<NbtElement> registryOps = wrapperLookup.getOps(NbtOps.INSTANCE);
|
||||
codec.encodeStart(registryOps, entry.getValue())
|
||||
.get()
|
||||
.ifRight(partial -> {
|
||||
|
@ -81,7 +81,7 @@ public class AttachmentSerializingImpl {
|
|||
Codec<?> codec = type.persistenceCodec();
|
||||
|
||||
if (codec != null) {
|
||||
RegistryOps<NbtElement> registryOps = wrapperLookup.method_57093(NbtOps.INSTANCE);
|
||||
RegistryOps<NbtElement> registryOps = wrapperLookup.getOps(NbtOps.INSTANCE);
|
||||
codec.parse(registryOps, compound.get(key))
|
||||
.get()
|
||||
.ifRight(partial -> {
|
||||
|
|
|
@ -253,7 +253,7 @@ public class CommonAttachmentTests {
|
|||
|
||||
private static DynamicRegistryManager mockDRM() {
|
||||
DynamicRegistryManager drm = mock(DynamicRegistryManager.class);
|
||||
when(drm.method_57093(any())).thenReturn((RegistryOps<Object>) (Object) RegistryOps.of(NbtOps.INSTANCE, drm));
|
||||
when(drm.getOps(any())).thenReturn((RegistryOps<Object>) (Object) RegistryOps.of(NbtOps.INSTANCE, drm));
|
||||
return drm;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public abstract class FabricAdvancementProvider implements DataProvider {
|
|||
*
|
||||
* <p>Use {@link Advancement.Builder#build(Consumer, String)} to help build advancements.
|
||||
*/
|
||||
public abstract void generateAdvancement(Consumer<AdvancementEntry> consumer);
|
||||
public abstract void generateAdvancement(RegistryWrapper.WrapperLookup registryLookup, Consumer<AdvancementEntry> consumer);
|
||||
|
||||
/**
|
||||
* Return a new exporter that applies the specified conditions to any advancement it receives.
|
||||
|
@ -80,13 +80,13 @@ public abstract class FabricAdvancementProvider implements DataProvider {
|
|||
|
||||
@Override
|
||||
public CompletableFuture<?> run(DataWriter writer) {
|
||||
final Set<Identifier> identifiers = Sets.newHashSet();
|
||||
final Set<AdvancementEntry> advancements = Sets.newHashSet();
|
||||
|
||||
generateAdvancement(advancements::add);
|
||||
|
||||
return this.registryLookup.thenCompose(lookup -> {
|
||||
RegistryOps<JsonElement> ops = lookup.method_57093(JsonOps.INSTANCE);
|
||||
final Set<Identifier> identifiers = Sets.newHashSet();
|
||||
final Set<AdvancementEntry> advancements = Sets.newHashSet();
|
||||
|
||||
generateAdvancement(lookup, advancements::add);
|
||||
|
||||
RegistryOps<JsonElement> ops = lookup.getOps(JsonOps.INSTANCE);
|
||||
final List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
|
||||
for (AdvancementEntry advancement : advancements) {
|
||||
|
|
|
@ -72,7 +72,7 @@ public abstract class FabricBlockLootTableProvider extends BlockLootTableGenerat
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(BiConsumer<Identifier, LootTable.Builder> biConsumer) {
|
||||
public void accept(RegistryWrapper.WrapperLookup registryLookup, BiConsumer<Identifier, LootTable.Builder> biConsumer) {
|
||||
generate();
|
||||
|
||||
for (Map.Entry<Identifier, LootTable.Builder> entry : lootTables.entrySet()) {
|
||||
|
|
|
@ -59,7 +59,7 @@ public abstract class FabricCodecDataProvider<T> implements DataProvider {
|
|||
public CompletableFuture<?> run(DataWriter writer) {
|
||||
return this.registriesFuture.thenCompose(lookup -> {
|
||||
Map<Identifier, JsonElement> entries = new HashMap<>();
|
||||
RegistryOps<JsonElement> ops = lookup.method_57093(JsonOps.INSTANCE);
|
||||
RegistryOps<JsonElement> ops = lookup.getOps(JsonOps.INSTANCE);
|
||||
|
||||
BiConsumer<Identifier, T> provider = (id, value) -> {
|
||||
JsonElement json = this.convert(id, value, ops);
|
||||
|
|
|
@ -208,7 +208,7 @@ public abstract class FabricDynamicRegistryProvider implements DataProvider {
|
|||
return entries;
|
||||
})
|
||||
.thenCompose(entries -> {
|
||||
final RegistryOps<JsonElement> dynamicOps = registries.method_57093(JsonOps.INSTANCE);
|
||||
final RegistryOps<JsonElement> dynamicOps = registries.getOps(JsonOps.INSTANCE);
|
||||
ArrayList<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
|
||||
for (RegistryEntries<?> registryEntries : entries.queuedEntries.values()) {
|
||||
|
|
|
@ -41,6 +41,7 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryWrapper;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.stat.StatType;
|
||||
import net.minecraft.text.TextContent;
|
||||
|
@ -52,21 +53,23 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
|
|||
|
||||
/**
|
||||
* Extend this class and implement {@link FabricLanguageProvider#generateTranslations(TranslationBuilder)}.
|
||||
* Make sure to use {@link FabricLanguageProvider#FabricLanguageProvider(FabricDataOutput, String)} FabricLanguageProvider} to declare what language code is being generated if it isn't {@code en_us}.
|
||||
* Make sure to use {@link FabricLanguageProvider#FabricLanguageProvider(FabricDataOutput, String, CompletableFuture)} FabricLanguageProvider} to declare what language code is being generated if it isn't {@code en_us}.
|
||||
*
|
||||
* <p>Register an instance of the class with {@link FabricDataGenerator.Pack#addProvider} in a {@link net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint}.
|
||||
*/
|
||||
public abstract class FabricLanguageProvider implements DataProvider {
|
||||
protected final FabricDataOutput dataOutput;
|
||||
private final String languageCode;
|
||||
private final CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup;
|
||||
|
||||
protected FabricLanguageProvider(FabricDataOutput dataOutput) {
|
||||
this(dataOutput, "en_us");
|
||||
protected FabricLanguageProvider(FabricDataOutput dataOutput, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
|
||||
this(dataOutput, "en_us", registryLookup);
|
||||
}
|
||||
|
||||
protected FabricLanguageProvider(FabricDataOutput dataOutput, String languageCode) {
|
||||
protected FabricLanguageProvider(FabricDataOutput dataOutput, String languageCode, CompletableFuture<RegistryWrapper.WrapperLookup> registryLookup) {
|
||||
this.dataOutput = dataOutput;
|
||||
this.languageCode = languageCode;
|
||||
this.registryLookup = registryLookup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,30 +77,32 @@ public abstract class FabricLanguageProvider implements DataProvider {
|
|||
*
|
||||
* <p>Call {@link TranslationBuilder#add(String, String)} to add a translation.
|
||||
*/
|
||||
public abstract void generateTranslations(TranslationBuilder translationBuilder);
|
||||
public abstract void generateTranslations(RegistryWrapper.WrapperLookup registryLookup, TranslationBuilder translationBuilder);
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> run(DataWriter writer) {
|
||||
TreeMap<String, String> translationEntries = new TreeMap<>();
|
||||
|
||||
generateTranslations((String key, String value) -> {
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(value);
|
||||
return this.registryLookup.thenCompose(lookup -> {
|
||||
generateTranslations(lookup, (String key, String value) -> {
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(value);
|
||||
|
||||
if (translationEntries.containsKey(key)) {
|
||||
throw new RuntimeException("Existing translation key found - " + key + " - Duplicate will be ignored.");
|
||||
if (translationEntries.containsKey(key)) {
|
||||
throw new RuntimeException("Existing translation key found - " + key + " - Duplicate will be ignored.");
|
||||
}
|
||||
|
||||
translationEntries.put(key, value);
|
||||
});
|
||||
|
||||
JsonObject langEntryJson = new JsonObject();
|
||||
|
||||
for (Map.Entry<String, String> entry : translationEntries.entrySet()) {
|
||||
langEntryJson.addProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
translationEntries.put(key, value);
|
||||
return DataProvider.writeToPath(writer, langEntryJson, getLangFilePath(this.languageCode));
|
||||
});
|
||||
|
||||
JsonObject langEntryJson = new JsonObject();
|
||||
|
||||
for (Map.Entry<String, String> entry : translationEntries.entrySet()) {
|
||||
langEntryJson.addProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return DataProvider.writeToPath(writer, langEntryJson, getLangFilePath(this.languageCode));
|
||||
}
|
||||
|
||||
private Path getLangFilePath(String code) {
|
||||
|
|
|
@ -99,7 +99,7 @@ public abstract class FabricRecipeProvider extends RecipeProvider {
|
|||
throw new IllegalStateException("Duplicate recipe " + identifier);
|
||||
}
|
||||
|
||||
RegistryOps<JsonElement> registryOps = wrapperLookup.method_57093(JsonOps.INSTANCE);
|
||||
RegistryOps<JsonElement> registryOps = wrapperLookup.getOps(JsonOps.INSTANCE);
|
||||
JsonObject recipeJson = Util.getResult(Recipe.CODEC.encodeStart(registryOps, recipe), IllegalStateException::new).getAsJsonObject();
|
||||
ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(recipe);
|
||||
ConditionJsonProvider.write(recipeJson, conditions);
|
||||
|
|
|
@ -84,7 +84,7 @@ public abstract class FabricTagProvider<T> extends TagProvider<T> {
|
|||
/**
|
||||
* Implement this method and then use {@link FabricTagProvider#getOrCreateTagBuilder} to get and register new tag builders.
|
||||
*/
|
||||
protected abstract void configure(RegistryWrapper.WrapperLookup arg);
|
||||
protected abstract void configure(RegistryWrapper.WrapperLookup wrapperLookup);
|
||||
|
||||
/**
|
||||
* Override to enable adding objects to the tag builder directly.
|
||||
|
|
|
@ -58,17 +58,17 @@ public final class FabricLootTableProviderImpl {
|
|||
HashMap<Identifier, LootTable> builders = Maps.newHashMap();
|
||||
HashMap<Identifier, ConditionJsonProvider[]> conditionMap = new HashMap<>();
|
||||
|
||||
provider.accept((identifier, builder) -> {
|
||||
ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(builder);
|
||||
conditionMap.put(identifier, conditions);
|
||||
return registryLookup.thenApply(lookup -> {
|
||||
provider.accept(lookup, (identifier, builder) -> {
|
||||
ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(builder);
|
||||
conditionMap.put(identifier, conditions);
|
||||
|
||||
if (builders.put(identifier, builder.type(lootContextType).build()) != null) {
|
||||
throw new IllegalStateException("Duplicate loot table " + identifier);
|
||||
}
|
||||
});
|
||||
if (builders.put(identifier, builder.type(lootContextType).build()) != null) {
|
||||
throw new IllegalStateException("Duplicate loot table " + identifier);
|
||||
}
|
||||
});
|
||||
|
||||
return registryLookup.thenCompose(lookup -> {
|
||||
RegistryOps<JsonElement> ops = lookup.method_57093(JsonOps.INSTANCE);
|
||||
RegistryOps<JsonElement> ops = lookup.getOps(JsonOps.INSTANCE);
|
||||
final List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<Identifier, LootTable> entry : builders.entrySet()) {
|
||||
|
|
|
@ -308,6 +308,7 @@ transitive-accessible method net/minecraft/data/server/loottable/BlockLootTableG
|
|||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator register (Lnet/minecraft/item/Item;Lnet/minecraft/data/client/Model;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator register (Lnet/minecraft/item/Item;Ljava/lang/String;Lnet/minecraft/data/client/Model;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator register (Lnet/minecraft/item/Item;Lnet/minecraft/item/Item;Lnet/minecraft/data/client/Model;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator registerWolfArmor (Lnet/minecraft/item/Item;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator registerCompass (Lnet/minecraft/item/Item;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator registerClock (Lnet/minecraft/item/Item;)V
|
||||
transitive-accessible method net/minecraft/data/client/ItemModelGenerator uploadArmor (Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)V
|
||||
|
@ -322,6 +323,7 @@ transitive-extendable method net/minecraft/data/dev/NbtProvider getName ()Ljava/
|
|||
transitive-extendable method net/minecraft/data/report/BlockListProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/report/CommandSyntaxProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/report/DynamicRegistriesProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/report/ItemListProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/report/RegistryDumpProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/server/BiomeParametersProvider getName ()Ljava/lang/String;
|
||||
transitive-extendable method net/minecraft/data/server/advancement/AdvancementProvider getName ()Ljava/lang/String;
|
||||
|
|
|
@ -44,6 +44,8 @@ import net.minecraft.advancement.criterion.OnKilledCriterion;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockKeys;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.component.ComponentChanges;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.data.DataOutput;
|
||||
import net.minecraft.data.client.BlockStateModelGenerator;
|
||||
import net.minecraft.data.client.ItemModelGenerator;
|
||||
|
@ -193,7 +195,13 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
.input(DefaultCustomIngredients.nbt(new ItemStack(Items.DIAMOND_PICKAXE), false))
|
||||
.input(DefaultCustomIngredients.components(
|
||||
Ingredient.ofItems(Items.DIAMOND_PICKAXE),
|
||||
ComponentChanges.builder()
|
||||
.add(DataComponentTypes.DAMAGE, 0)
|
||||
.build()
|
||||
)
|
||||
)
|
||||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
.input(Ingredient.ofItems(Items.DIAMOND_PICKAXE))
|
||||
|
@ -205,10 +213,10 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
// To test: try renaming an apple to "Golden Apple" in creative with an anvil.
|
||||
// That should match the recipe and give a golden apple. Any other NBT should not match.
|
||||
ItemStack appleWithGoldenName = new ItemStack(Items.APPLE);
|
||||
appleWithGoldenName.setCustomName(Text.literal("Golden Apple"));
|
||||
appleWithGoldenName.setRepairCost(0);
|
||||
appleWithGoldenName.set(DataComponentTypes.CUSTOM_NAME, Text.literal("Golden Apple"));
|
||||
appleWithGoldenName.set(DataComponentTypes.REPAIR_COST, 0);
|
||||
ShapelessRecipeJsonBuilder.create(RecipeCategory.MISC, Items.GOLDEN_APPLE)
|
||||
.input(DefaultCustomIngredients.nbt(appleWithGoldenName, true))
|
||||
.input(DefaultCustomIngredients.components(appleWithGoldenName))
|
||||
.criterion("has_apple", conditionsFromItem(Items.APPLE))
|
||||
.offerTo(exporter);
|
||||
|
||||
|
@ -242,12 +250,12 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
}
|
||||
|
||||
private static class ExistingEnglishLangProvider extends FabricLanguageProvider {
|
||||
private ExistingEnglishLangProvider(FabricDataOutput output) {
|
||||
super(output);
|
||||
private ExistingEnglishLangProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
|
||||
super(output, registriesFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateTranslations(TranslationBuilder translationBuilder) {
|
||||
public void generateTranslations(RegistryWrapper.WrapperLookup registryLookup, TranslationBuilder translationBuilder) {
|
||||
translationBuilder.add(SIMPLE_BLOCK, "Simple Block");
|
||||
translationBuilder.add(new Identifier(MOD_ID, "identifier_test"), "Identifier Test");
|
||||
translationBuilder.add(EntityType.ALLAY, "Allay");
|
||||
|
@ -274,12 +282,12 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
}
|
||||
|
||||
private static class JapaneseLangProvider extends FabricLanguageProvider {
|
||||
private JapaneseLangProvider(FabricDataOutput output) {
|
||||
super(output, "ja_jp");
|
||||
private JapaneseLangProvider(FabricDataOutput output, CompletableFuture<RegistryWrapper.WrapperLookup> registriesFuture) {
|
||||
super(output, "ja_jp", registriesFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateTranslations(TranslationBuilder translationBuilder) {
|
||||
public void generateTranslations(RegistryWrapper.WrapperLookup registryLookup, TranslationBuilder translationBuilder) {
|
||||
translationBuilder.add(SIMPLE_BLOCK, "シンプルブロック");
|
||||
translationBuilder.add(SIMPLE_ITEM_GROUP, "データ生成項目");
|
||||
translationBuilder.add("this.is.a.test", "こんにちは");
|
||||
|
@ -361,7 +369,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void generateAdvancement(Consumer<AdvancementEntry> consumer) {
|
||||
public void generateAdvancement(RegistryWrapper.WrapperLookup registryLookup, Consumer<AdvancementEntry> consumer) {
|
||||
AdvancementEntry root = Advancement.Builder.create()
|
||||
.display(
|
||||
SIMPLE_BLOCK,
|
||||
|
@ -406,7 +414,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void accept(BiConsumer<Identifier, LootTable.Builder> consumer) {
|
||||
public void accept(RegistryWrapper.WrapperLookup registryLookup, BiConsumer<Identifier, LootTable.Builder> consumer) {
|
||||
withConditions(consumer, ALWAYS_LOADED).accept(
|
||||
LootTables.PIGLIN_BARTERING_GAMEPLAY,
|
||||
LootTable.builder().pool(
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
|||
import net.minecraft.block.AbstractBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.entity.damage.DamageTypes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
|
@ -225,7 +226,7 @@ public final class EntityEventTests implements ModInitializer {
|
|||
|
||||
private static ItemStack createNamedItem(Item item, String name) {
|
||||
ItemStack stack = new ItemStack(item);
|
||||
stack.setCustomName(Text.literal(name));
|
||||
stack.set(DataComponentTypes.CUSTOM_NAME, Text.literal(name));
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,10 @@ public abstract class TestFunctionsMixin {
|
|||
gameTest.tickLimit(),
|
||||
gameTest.duration(),
|
||||
gameTest.required(),
|
||||
gameTest.requiredSuccesses(),
|
||||
gameTest.manualOnly(),
|
||||
gameTest.maxAttempts(),
|
||||
gameTest.method_57098(),
|
||||
gameTest.requiredSuccesses(),
|
||||
gameTest.skyAccess(),
|
||||
FabricGameTestHelper.getTestMethodInvoker(method)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.item.v1;
|
||||
|
||||
import net.minecraft.item.FoodComponent;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.resource.featuretoggle.FeatureFlag;
|
||||
import net.minecraft.util.Rarity;
|
||||
|
||||
import net.fabricmc.fabric.impl.item.FabricItemInternals;
|
||||
|
||||
/**
|
||||
* @deprecated replace with {@link Item.Settings}
|
||||
*/
|
||||
@Deprecated
|
||||
public class FabricItemSettings extends Item.Settings {
|
||||
/**
|
||||
* Sets the equipment slot provider of the item.
|
||||
*
|
||||
* @param equipmentSlotProvider the equipment slot provider
|
||||
* @return this builder
|
||||
* @deprecated replace with {@link FabricItem.Settings#equipmentSlot(EquipmentSlotProvider)}
|
||||
*/
|
||||
@Deprecated
|
||||
public FabricItemSettings equipmentSlot(EquipmentSlotProvider equipmentSlotProvider) {
|
||||
FabricItemInternals.computeExtraData(this).equipmentSlot(equipmentSlotProvider);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom damage handler of the item.
|
||||
* Note that this is only called on an ItemStack if {@link ItemStack#isDamageable()} returns true.
|
||||
*
|
||||
* @deprecated replace with {@link FabricItem.Settings#customDamage(CustomDamageHandler)}
|
||||
* @see CustomDamageHandler
|
||||
*/
|
||||
@Deprecated
|
||||
public FabricItemSettings customDamage(CustomDamageHandler handler) {
|
||||
FabricItemInternals.computeExtraData(this).customDamage(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Overrides of vanilla methods
|
||||
|
||||
@Override
|
||||
public FabricItemSettings food(FoodComponent foodComponent) {
|
||||
super.food(foodComponent);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxCount(int maxCount) {
|
||||
super.maxCount(maxCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxDamageIfAbsent(int maxDamage) {
|
||||
super.maxDamageIfAbsent(maxDamage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings maxDamage(int maxDamage) {
|
||||
super.maxDamage(maxDamage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings recipeRemainder(Item recipeRemainder) {
|
||||
super.recipeRemainder(recipeRemainder);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings rarity(Rarity rarity) {
|
||||
super.rarity(rarity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings fireproof() {
|
||||
super.fireproof();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricItemSettings requires(FeatureFlag... features) {
|
||||
super.requires(features);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.item.v1;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
|
||||
/**
|
||||
* Stack-aware attribute modifier callback for foreign items.
|
||||
* Instead of using Mixin to change attribute modifiers in items not in your mod,
|
||||
* you can use this event instead, either checking the Item itself or using a tag.
|
||||
* This event provides you with a guaranteed mutable map you can put attribute modifiers in.
|
||||
* Do not use for your own Item classes; see {@link FabricItem#getAttributeModifiers} instead.
|
||||
* For example, the following code modifies a Diamond Helmet to give you five extra hearts when wearing.
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* ModifyItemAttributeModifiersCallback.EVENT.register((stack, slot, attributeModifiers) -> {
|
||||
* if (stack.isOf(Items.DIAMOND_HELMET) && slot.getEntitySlotId() == HEAD_SLOT_ID) {
|
||||
* attributeModifiers.put(EntityAttributes.GENERIC_MAX_HEALTH, MODIFIER);
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ModifyItemAttributeModifiersCallback {
|
||||
void modifyAttributeModifiers(ItemStack stack, EquipmentSlot slot, Multimap<RegistryEntry<EntityAttribute>, EntityAttributeModifier> attributeModifiers);
|
||||
|
||||
Event<ModifyItemAttributeModifiersCallback> EVENT = EventFactory.createArrayBacked(
|
||||
ModifyItemAttributeModifiersCallback.class,
|
||||
callbacks -> (stack, slot, attributeModifiers) -> {
|
||||
for (ModifyItemAttributeModifiersCallback callback : callbacks) {
|
||||
callback.modifyAttributeModifiers(stack, slot, attributeModifiers);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.item;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
|
@ -31,17 +29,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.attribute.EntityAttribute;
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
|
||||
import net.fabricmc.fabric.api.item.v1.CustomDamageHandler;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemStack;
|
||||
import net.fabricmc.fabric.api.item.v1.ModifyItemAttributeModifiersCallback;
|
||||
import net.fabricmc.fabric.impl.item.ItemExtensions;
|
||||
|
||||
@Mixin(ItemStack.class)
|
||||
|
@ -67,21 +61,6 @@ public abstract class ItemStackMixin implements FabricItemStack {
|
|||
original.call(instance, amount, random, serverPlayerEntity, runnable);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "getAttributeModifiers",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/item/Item;getAttributeModifiers(Lnet/minecraft/entity/EquipmentSlot;)Lcom/google/common/collect/Multimap;"
|
||||
)
|
||||
)
|
||||
public Multimap<RegistryEntry<EntityAttribute>, EntityAttributeModifier> hookGetAttributeModifiers(Item item, EquipmentSlot slot) {
|
||||
ItemStack stack = (ItemStack) (Object) this;
|
||||
//we need to ensure it is modifiable for the callback, use linked map to preserve ordering
|
||||
Multimap<RegistryEntry<EntityAttribute>, EntityAttributeModifier> attributeModifiers = LinkedHashMultimap.create(item.getAttributeModifiers(stack, slot));
|
||||
ModifyItemAttributeModifiersCallback.EVENT.invoker().modifyAttributeModifiers(stack, slot, attributeModifiers);
|
||||
return attributeModifiers;
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "isSuitableFor",
|
||||
at = @At(
|
||||
|
|
|
@ -16,17 +16,19 @@
|
|||
|
||||
package net.fabricmc.fabric.test.item;
|
||||
|
||||
import net.minecraft.component.DataComponentType;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.PickaxeItem;
|
||||
import net.minecraft.item.ToolMaterials;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.potion.Potions;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.item.v1.CustomDamageHandler;
|
||||
|
@ -35,6 +37,8 @@ import net.fabricmc.fabric.api.registry.FuelRegistry;
|
|||
|
||||
public class CustomDamageTest implements ModInitializer {
|
||||
public static final Item WEIRD_PICK = new WeirdPick();
|
||||
public static final DataComponentType<Integer> WEIRD = Registry.register(Registries.DATA_COMPONENT_TYPE, new Identifier("fabric-item-api-v1-testmod", "weird"),
|
||||
DataComponentType.<Integer>builder().codec(Codecs.NONNEGATIVE_INT).packetCodec(PacketCodecs.VAR_INT).build());
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
|
@ -48,20 +52,19 @@ public class CustomDamageTest implements ModInitializer {
|
|||
if (entity.isSneaking()) {
|
||||
return amount;
|
||||
} else {
|
||||
NbtCompound tag = stack.getOrCreateNbt();
|
||||
tag.putInt("weird", tag.getInt("weird") + 1);
|
||||
stack.set(WEIRD, stack.getOrDefault(WEIRD, 0) + 1);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
public static class WeirdPick extends PickaxeItem {
|
||||
protected WeirdPick() {
|
||||
super(ToolMaterials.GOLD, 1, -2.8F, new Item.Settings().customDamage(WEIRD_DAMAGE_HANDLER));
|
||||
super(ToolMaterials.GOLD, new Item.Settings().customDamage(WEIRD_DAMAGE_HANDLER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName(ItemStack stack) {
|
||||
int v = stack.getOrCreateNbt().getInt("weird");
|
||||
int v = stack.getOrDefault(WEIRD, 0);
|
||||
return super.getName(stack).copy().append(" (Weird Value: " + v + ")");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.test.item;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||
|
||||
public class FabricItemSettingsTests implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// Registers an item with a custom equipment slot.
|
||||
Item testItem = new Item(new Item.Settings().equipmentSlot(stack -> EquipmentSlot.CHEST));
|
||||
Registry.register(Registries.ITEM, new Identifier("fabric-item-api-v1-testmod", "test_item"), testItem);
|
||||
|
||||
final List<String> missingMethods = new ArrayList<>();
|
||||
|
||||
for (Method method : FabricItemSettings.class.getMethods()) {
|
||||
if ((method.getModifiers() & Opcodes.ACC_SYNTHETIC) != 0) {
|
||||
// Ignore synthetic bridge methods
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((method.getModifiers() & Opcodes.ACC_STATIC) != 0) {
|
||||
// Ignore static methods
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method.getReturnType() == Item.Settings.class) {
|
||||
missingMethods.add(method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (missingMethods.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Missing method overrides in FabricItemSettings: " + String.join(", ", missingMethods));
|
||||
}
|
||||
}
|
|
@ -16,13 +16,19 @@
|
|||
|
||||
package net.fabricmc.fabric.test.item;
|
||||
|
||||
import net.minecraft.component.DataComponentType;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
public class ItemUpdateAnimationTest implements ModInitializer {
|
||||
public static final DataComponentType<Integer> TICKS = Registry.register(Registries.DATA_COMPONENT_TYPE, new Identifier("fabric-item-api-v1-testmod", "ticks"),
|
||||
DataComponentType.<Integer>builder().codec(Codecs.NONNEGATIVE_INT).packetCodec(PacketCodecs.VAR_INT).build());
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
Registry.register(Registries.ITEM, new Identifier("fabric-item-api-v1-testmod", "updating_allowed"), new UpdatingItem(true));
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.test.item;
|
||||
|
||||
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.item.Items;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.item.v1.ModifyItemAttributeModifiersCallback;
|
||||
|
||||
public class ModifyItemAttributeModifiersCallbackTest implements ModInitializer {
|
||||
public static final int HEAD_SLOT_ID = 3;
|
||||
public static final EntityAttributeModifier MODIFIER = new EntityAttributeModifier("generic_max_health_modifier", 5.0, EntityAttributeModifier.Operation.ADDITION);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
ModifyItemAttributeModifiersCallback.EVENT.register((stack, slot, attributeModifiers) -> {
|
||||
if (stack.isOf(Items.DIAMOND_HELMET) && slot.getEntitySlotId() == HEAD_SLOT_ID) {
|
||||
attributeModifiers.put(EntityAttributes.GENERIC_MAX_HEALTH, MODIFIER);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ import net.minecraft.entity.attribute.EntityAttributes;
|
|||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -47,8 +46,7 @@ public class UpdatingItem extends Item {
|
|||
@Override
|
||||
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
|
||||
if (!world.isClient) {
|
||||
NbtCompound tag = stack.getOrCreateNbt();
|
||||
tag.putLong("ticks", tag.getLong("ticks") + 1);
|
||||
stack.set(ItemUpdateAnimationTest.TICKS, stack.getOrDefault(ItemUpdateAnimationTest.TICKS, 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +62,7 @@ public class UpdatingItem extends Item {
|
|||
|
||||
// True for 15 seconds every 30 seconds
|
||||
private boolean isEnabled(ItemStack stack) {
|
||||
return !stack.hasNbt() || stack.getNbt().getLong("ticks") % 600 < 300;
|
||||
return !stack.contains(ItemUpdateAnimationTest.TICKS) || stack.getOrDefault(ItemUpdateAnimationTest.TICKS, 0) % 600 < 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,10 +20,13 @@ import java.util.Objects;
|
|||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.BrewingStandBlockEntity;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.PotionContentsComponent;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.potion.PotionUtil;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.Potions;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.test.GameTest;
|
||||
import net.minecraft.test.TestContext;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -43,13 +46,13 @@ public class BrewingStandGameTest implements FabricGameTest {
|
|||
loadFuel(blockEntity, context);
|
||||
|
||||
prepareForBrewing(blockEntity, new ItemStack(Items.NETHER_WART, 8),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
|
||||
brew(blockEntity, context);
|
||||
assertInventory(blockEntity, "Testing vanilla brewing.",
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
new ItemStack(Items.NETHER_WART, 7),
|
||||
ItemStack.EMPTY);
|
||||
|
||||
|
@ -64,13 +67,13 @@ public class BrewingStandGameTest implements FabricGameTest {
|
|||
loadFuel(blockEntity, context);
|
||||
|
||||
prepareForBrewing(blockEntity, new ItemStack(Items.DRAGON_BREATH),
|
||||
PotionUtil.setPotion(new ItemStack(Items.SPLASH_POTION), Potions.AWKWARD));
|
||||
setPotion(new ItemStack(Items.SPLASH_POTION), Potions.AWKWARD));
|
||||
|
||||
brew(blockEntity, context);
|
||||
assertInventory(blockEntity, "Testing vanilla brewing recipe remainder.",
|
||||
PotionUtil.setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.LINGERING_POTION), Potions.AWKWARD),
|
||||
ItemStack.EMPTY,
|
||||
ItemStack.EMPTY);
|
||||
|
||||
|
@ -86,35 +89,35 @@ public class BrewingStandGameTest implements FabricGameTest {
|
|||
loadFuel(blockEntity, context);
|
||||
|
||||
prepareForBrewing(blockEntity, new ItemStack(CustomDamageTest.WEIRD_PICK),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
|
||||
brew(blockEntity, context);
|
||||
assertInventory(blockEntity, "Testing fabric brewing recipe remainder.",
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
RecipeGameTest.withDamage(new ItemStack(CustomDamageTest.WEIRD_PICK), 1),
|
||||
ItemStack.EMPTY);
|
||||
|
||||
prepareForBrewing(blockEntity, RecipeGameTest.withDamage(new ItemStack(CustomDamageTest.WEIRD_PICK), 10),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
|
||||
brew(blockEntity, context);
|
||||
assertInventory(blockEntity, "Testing fabric brewing recipe remainder.",
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
RecipeGameTest.withDamage(new ItemStack(CustomDamageTest.WEIRD_PICK), 11),
|
||||
ItemStack.EMPTY);
|
||||
|
||||
prepareForBrewing(blockEntity, RecipeGameTest.withDamage(new ItemStack(CustomDamageTest.WEIRD_PICK), 31),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
setPotion(new ItemStack(Items.POTION), Potions.WATER));
|
||||
|
||||
brew(blockEntity, context);
|
||||
assertInventory(blockEntity, "Testing fabric brewing recipe remainder.",
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
PotionUtil.setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
setPotion(new ItemStack(Items.POTION), Potions.AWKWARD),
|
||||
ItemStack.EMPTY,
|
||||
ItemStack.EMPTY);
|
||||
|
||||
|
@ -147,4 +150,9 @@ public class BrewingStandGameTest implements FabricGameTest {
|
|||
BrewingStandBlockEntity.tick(context.getWorld(), POS, context.getBlockState(POS), blockEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private static ItemStack setPotion(ItemStack itemStack, RegistryEntry<Potion> potion) {
|
||||
itemStack.set(DataComponentTypes.POTION_CONTENTS, new PotionContentsComponent(potion));
|
||||
return itemStack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.test.item.gametest;
|
|||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.passive.WolfEntity;
|
||||
import net.minecraft.entity.player.HungerManager;
|
||||
|
@ -66,7 +67,7 @@ public final class FoodGameTest implements FabricGameTest {
|
|||
hungerManager.setFoodLevel(0);
|
||||
hungerManager.setSaturationLevel(0);
|
||||
ItemStack foodStack = FoodGameInitializer.NAME.getDefaultStack();
|
||||
foodStack.setCustomName(Text.literal("enchanted_golden_apple"));
|
||||
foodStack.set(DataComponentTypes.CUSTOM_NAME, Text.literal("enchanted_golden_apple"));
|
||||
player.eatFood(player.getWorld(), foodStack.copy());
|
||||
FoodComponent fc = FoodComponents.ENCHANTED_GOLDEN_APPLE;
|
||||
int foodActual = hungerManager.getFoodLevel();
|
||||
|
@ -86,7 +87,7 @@ public final class FoodGameTest implements FabricGameTest {
|
|||
wolf.setOwner(player);
|
||||
wolf.setHealth(1f);
|
||||
ItemStack meat = FoodGameInitializer.NAME.getDefaultStack();
|
||||
meat.setCustomName(Text.of("mutton"));
|
||||
meat.set(DataComponentTypes.CUSTOM_NAME, Text.literal("mutton"));
|
||||
player.setStackInHand(Hand.MAIN_HAND, meat);
|
||||
player.interact(wolf, Hand.MAIN_HAND);
|
||||
float wolfHealth = wolf.getHealth();
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package net.fabricmc.fabric.test.item.gametest;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.inventory.SimpleInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
|
@ -129,8 +127,8 @@ public class RecipeGameTest implements FabricGameTest {
|
|||
throw new GameTestException("Size doesnt match. " + extraErrorInfo);
|
||||
}
|
||||
|
||||
if (!Objects.equals(currentStack.getNbt(), expectedStack.getNbt())) {
|
||||
throw new GameTestException("Nbt doesnt match. " + extraErrorInfo);
|
||||
if (!ItemStack.areItemsAndNbtEqual(currentStack, expectedStack)) {
|
||||
throw new GameTestException("Stack doesnt match. " + extraErrorInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond",
|
||||
"id": "minecraft:diamond",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.item.CustomDamageTest",
|
||||
"net.fabricmc.fabric.test.item.FabricItemSettingsTests",
|
||||
"net.fabricmc.fabric.test.item.ItemUpdateAnimationTest",
|
||||
"net.fabricmc.fabric.test.item.ModifyItemAttributeModifiersCallbackTest",
|
||||
"net.fabricmc.fabric.test.item.ArmorKnockbackResistanceTest",
|
||||
"net.fabricmc.fabric.test.item.FoodGameInitializer"
|
||||
],
|
||||
|
|
|
@ -128,11 +128,11 @@ public final class NetworkingPlayPacketTest implements ModInitializer {
|
|||
public static final PacketCodec<RegistryByteBuf, OverlayPacket> CODEC = CustomPayload.codecOf(OverlayPacket::write, OverlayPacket::new);
|
||||
|
||||
public OverlayPacket(RegistryByteBuf buf) {
|
||||
this(TextCodecs.PACKET_CODEC.decode(buf));
|
||||
this(TextCodecs.REGISTRY_PACKET_CODEC.decode(buf));
|
||||
}
|
||||
|
||||
public void write(RegistryByteBuf buf) {
|
||||
TextCodecs.PACKET_CODEC.encode(buf, this.message);
|
||||
TextCodecs.REGISTRY_PACKET_CODEC.encode(buf, this.message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ final class ChannelScreen extends Screen {
|
|||
|
||||
@Override
|
||||
public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackgroundTexture(drawContext);
|
||||
this.renderBackground(drawContext, mouseX, mouseY, delta);
|
||||
this.channelList.render(drawContext, mouseX, mouseY, delta);
|
||||
super.render(drawContext, mouseX, mouseY, delta);
|
||||
|
||||
|
|
|
@ -18,20 +18,19 @@ package net.fabricmc.fabric.mixin.object.builder;
|
|||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import net.minecraft.class_9306;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.registry.DefaultedRegistry;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.village.TradeOffer;
|
||||
import net.minecraft.village.TradeOffers;
|
||||
import net.minecraft.village.VillagerDataContainer;
|
||||
import net.minecraft.village.VillagerType;
|
||||
|
||||
@Mixin(TradeOffers.TypeAwareBuyForOneEmeraldFactory.class)
|
||||
|
@ -50,9 +49,9 @@ public abstract class TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin {
|
|||
/**
|
||||
* To prevent "item" -> "air" trades, if the result of a type aware trade is air, make sure no offer is created.
|
||||
*/
|
||||
@Inject(method = "create", at = @At(value = "NEW", target = "net/minecraft/village/TradeOffer"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
|
||||
private void failOnNullItem(Entity entity, Random random, CallbackInfoReturnable<TradeOffer> cir, VillagerDataContainer villagerDataContainer, ItemStack buyingItem) {
|
||||
if (buyingItem.isEmpty()) { // Will return true for an "empty" item stack that had null passed in the ctor
|
||||
@Inject(method = "create", at = @At(value = "NEW", target = "net/minecraft/village/TradeOffer"), cancellable = true)
|
||||
private void failOnNullItem(Entity entity, Random random, CallbackInfoReturnable<TradeOffer> cir, @Local() class_9306 buyingItem) {
|
||||
if (buyingItem.itemStack().isEmpty()) { // Will return true for an "empty" item stack that had null passed in the ctor
|
||||
cir.setReturnValue(null); // Return null to prevent creation of empty trades
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@ import static net.minecraft.command.argument.EntityArgumentType.getEntity;
|
|||
import static net.minecraft.server.command.CommandManager.argument;
|
||||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
|
||||
import net.minecraft.class_9306;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.passive.WanderingTraderEntity;
|
||||
import net.minecraft.item.Item;
|
||||
|
@ -48,16 +51,16 @@ public class VillagerTypeTest1 implements ModInitializer {
|
|||
public void onInitialize() {
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, (factories, rebalanced) -> {
|
||||
Item scrap = rebalanced ? Items.NETHER_BRICK : Items.NETHERITE_SCRAP;
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.GOLD_INGOT, 3), new ItemStack(scrap, 4), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.GOLD_INGOT, 3), Optional.of(new class_9306(scrap, 4)), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.15F)));
|
||||
});
|
||||
// Toolsmith is not rebalanced yet
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.TOOLSMITH, 1, (factories, rebalanced) -> {
|
||||
Item scrap = rebalanced ? Items.NETHER_BRICK : Items.NETHERITE_SCRAP;
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.GOLD_INGOT, 3), new ItemStack(scrap, 4), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.GOLD_INGOT, 3), Optional.of(new class_9306(scrap, 4)), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.15F)));
|
||||
});
|
||||
|
||||
TradeOfferHelper.registerWanderingTraderOffers(1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.GOLD_INGOT, 3), new ItemStack(Items.NETHERITE_SCRAP, 4), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.35F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.GOLD_INGOT, 3), Optional.of(new class_9306(Items.NETHERITE_SCRAP, 4)), new ItemStack(Items.NETHERITE_INGOT), 2, 6, 0.35F)));
|
||||
});
|
||||
|
||||
TradeOfferHelper.registerRebalancedWanderingTraderOffers(builder -> {
|
||||
|
@ -65,28 +68,28 @@ public class VillagerTypeTest1 implements ModInitializer {
|
|||
FOOD_POOL_ID,
|
||||
5,
|
||||
Registries.ITEM.stream().filter(item -> item.getFoodComponent() != null).map(
|
||||
item -> new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(item), 3, 4, 0.15F))
|
||||
item -> new SimpleTradeFactory(new TradeOffer(new class_9306(Items.NETHERITE_INGOT), new ItemStack(item), 3, 4, 0.15F))
|
||||
).toList()
|
||||
);
|
||||
builder.addAll(
|
||||
THING_POOL_ID,
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(Items.MOJANG_BANNER_PATTERN), 1, 4, 0.15F))
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.NETHERITE_INGOT), new ItemStack(Items.MOJANG_BANNER_PATTERN), 1, 4, 0.15F))
|
||||
);
|
||||
builder.addOffersToPool(
|
||||
TradeOfferHelper.WanderingTraderOffersBuilder.BUY_ITEMS_POOL,
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.BLAZE_POWDER, 1), new ItemStack(Items.EMERALD, 4), 3, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHER_WART, 5), new ItemStack(Items.EMERALD, 1), 3, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.GOLDEN_CARROT, 4), new ItemStack(Items.EMERALD, 1), 3, 4, 0.15F))
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.BLAZE_POWDER, 1), new ItemStack(Items.EMERALD, 4), 3, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.NETHER_WART, 5), new ItemStack(Items.EMERALD, 1), 3, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.GOLDEN_CARROT, 4), new ItemStack(Items.EMERALD, 1), 3, 4, 0.15F))
|
||||
);
|
||||
builder.addOffersToPool(
|
||||
TradeOfferHelper.WanderingTraderOffersBuilder.SELL_SPECIAL_ITEMS_POOL,
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.EMERALD, 6), new ItemStack(Items.BRUSH, 1), 1, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 16), new ItemStack(Items.ELYTRA, 1), 1, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.EMERALD, 3), new ItemStack(Items.LEAD, 2), 3, 4, 0.15F))
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.EMERALD, 6), new ItemStack(Items.BRUSH, 1), 1, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 16), new ItemStack(Items.ELYTRA, 1), 1, 4, 0.15F)),
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.EMERALD, 3), new ItemStack(Items.LEAD, 2), 3, 4, 0.15F))
|
||||
);
|
||||
builder.addOffersToPool(
|
||||
FOOD_POOL_ID,
|
||||
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(Items.EGG), 3, 4, 0.15F))
|
||||
new SimpleTradeFactory(new TradeOffer(new class_9306(Items.NETHERITE_INGOT), new ItemStack(Items.EGG), 3, 4, 0.15F))
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package net.fabricmc.fabric.test.object.builder;
|
||||
|
||||
import net.minecraft.class_9306;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.village.TradeOffer;
|
||||
|
@ -31,22 +32,22 @@ public class VillagerTypeTest2 implements ModInitializer {
|
|||
@Override
|
||||
public void onInitialize() {
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.WEAPONSMITH, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 5), new ItemStack(Items.NETHERITE_INGOT), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 5), new ItemStack(Items.NETHERITE_INGOT), 3, 4, 0.15F)));
|
||||
});
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 6), new ItemStack(Items.ELYTRA), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 6), new ItemStack(Items.ELYTRA), 3, 4, 0.15F)));
|
||||
});
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 7), new ItemStack(Items.CHAINMAIL_BOOTS), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 7), new ItemStack(Items.CHAINMAIL_BOOTS), 3, 4, 0.15F)));
|
||||
});
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 8), new ItemStack(Items.CHAINMAIL_CHESTPLATE), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 8), new ItemStack(Items.CHAINMAIL_CHESTPLATE), 3, 4, 0.15F)));
|
||||
});
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 9), new ItemStack(Items.CHAINMAIL_HELMET), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 9), new ItemStack(Items.CHAINMAIL_HELMET), 3, 4, 0.15F)));
|
||||
});
|
||||
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, factories -> {
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 10), new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 4, 0.15F)));
|
||||
factories.add(new SimpleTradeFactory(new TradeOffer(new class_9306(Items.DIAMOND, 10), new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 4, 0.15F)));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,16 @@ package net.fabricmc.fabric.api.recipe.v1.ingredient;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.component.ComponentChanges;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.AllIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.AnyIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.ComponentsIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.DifferenceIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.NbtIngredient;
|
||||
|
||||
/**
|
||||
* Factory methods for the custom ingredients directly provided by Fabric API.
|
||||
|
@ -101,42 +99,38 @@ public final class DefaultCustomIngredients {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an ingredient that wraps another ingredient to also check for stack NBT.
|
||||
* This check can either be strict (the exact NBT must match) or non-strict aka. partial (the ingredient NBT must be a subset of the stack NBT).
|
||||
* Creates an ingredient that wraps another ingredient to also check for matching components.
|
||||
*
|
||||
* <p>In strict mode, passing a {@code null} {@code nbt} is allowed, and will only match stacks with {@code null} NBT.
|
||||
* In partial mode, passing a {@code null} {@code nbt} is <strong>not</strong> allowed, as it would always match.
|
||||
* <p>Use {@link ComponentChanges#builder()} to add or remove components.
|
||||
* Added components are checked to match on the target stack.
|
||||
* Removed components are checked to not exist in the target stack
|
||||
*
|
||||
* <p>See {@link NbtHelper#matches} for the non-strict matching.
|
||||
*
|
||||
* <p>The JSON format is as follows:
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "fabric:type": "fabric:nbt",
|
||||
* "base": // base ingredient,
|
||||
* "nbt": // NBT tag to match, either in JSON directly or a string representation (default: null),
|
||||
* "strict": // whether to use strict matching (default: false)
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code strict} is {@code false} and the NBT is {@code null}
|
||||
* @throws IllegalArgumentException if {@link ComponentChanges#isEmpty} is true
|
||||
*/
|
||||
public static Ingredient nbt(Ingredient base, @Nullable NbtCompound nbt, boolean strict) {
|
||||
public static Ingredient components(Ingredient base, ComponentChanges components) {
|
||||
Objects.requireNonNull(base, "Base ingredient cannot be null");
|
||||
Objects.requireNonNull(components, "Component changes cannot be null");
|
||||
|
||||
return new NbtIngredient(base, nbt, strict).toVanilla();
|
||||
return new ComponentsIngredient(base, components).toVanilla();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ingredient that matches the passed template stack, including NBT.
|
||||
* @see #components(Ingredient, ComponentChanges)
|
||||
*/
|
||||
public static Ingredient components(Ingredient base, UnaryOperator<ComponentChanges.Builder> operator) {
|
||||
return components(base, operator.apply(ComponentChanges.builder()).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ingredient that matches the passed template stack, including {@link ItemStack#getComponentChanges()}.
|
||||
* Note that the count of the stack is ignored.
|
||||
*
|
||||
* @see #nbt(Ingredient, NbtCompound, boolean)
|
||||
* @see #components(Ingredient, ComponentChanges)
|
||||
*/
|
||||
public static Ingredient nbt(ItemStack stack, boolean strict) {
|
||||
public static Ingredient components(ItemStack stack) {
|
||||
Objects.requireNonNull(stack, "Stack cannot be null");
|
||||
|
||||
return nbt(Ingredient.ofItems(stack.getItem()), stack.getNbt(), strict);
|
||||
return components(Ingredient.ofItems(stack.getItem()), stack.getComponentChanges());
|
||||
}
|
||||
|
||||
private DefaultCustomIngredients() {
|
||||
|
|
|
@ -20,8 +20,8 @@ import net.fabricmc.api.ModInitializer;
|
|||
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.AllIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.AnyIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.ComponentsIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.DifferenceIngredient;
|
||||
import net.fabricmc.fabric.impl.recipe.ingredient.builtin.NbtIngredient;
|
||||
|
||||
/**
|
||||
* Register builtin custom ingredients.
|
||||
|
@ -32,6 +32,6 @@ public class CustomIngredientInit implements ModInitializer {
|
|||
CustomIngredientSerializer.register(AllIngredient.SERIALIZER);
|
||||
CustomIngredientSerializer.register(AnyIngredient.SERIALIZER);
|
||||
CustomIngredientSerializer.register(DifferenceIngredient.SERIALIZER);
|
||||
CustomIngredientSerializer.register(NbtIngredient.SERIALIZER);
|
||||
CustomIngredientSerializer.register(ComponentsIngredient.SERIALIZER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.component.ComponentChanges;
|
||||
import net.minecraft.component.DataComponentType;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredient;
|
||||
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
|
||||
|
||||
public class ComponentsIngredient implements CustomIngredient {
|
||||
public static final CustomIngredientSerializer<ComponentsIngredient> SERIALIZER = new Serializer();
|
||||
|
||||
private final Ingredient base;
|
||||
private final ComponentChanges components;
|
||||
|
||||
public ComponentsIngredient(Ingredient base, ComponentChanges components) {
|
||||
if (components.isEmpty()) {
|
||||
throw new IllegalArgumentException("ComponentIngredient must have at least one defined component");
|
||||
}
|
||||
|
||||
this.base = base;
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(ItemStack stack) {
|
||||
if (!base.test(stack)) return false;
|
||||
|
||||
// None strict matching
|
||||
for (Map.Entry<DataComponentType<?>, Optional<?>> entry : components.entrySet()) {
|
||||
final DataComponentType<?> type = entry.getKey();
|
||||
final Optional<?> value = entry.getValue();
|
||||
|
||||
if (value.isPresent()) {
|
||||
// Expect the stack to contain a matching component
|
||||
if (!stack.contains(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Objects.equals(value.get(), stack.get(type))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Expect the target stack to not contain this component
|
||||
if (stack.contains(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getMatchingStacks() {
|
||||
List<ItemStack> stacks = new ArrayList<>(List.of(base.getMatchingStacks()));
|
||||
stacks.replaceAll(stack -> {
|
||||
ItemStack copy = stack.copy();
|
||||
|
||||
stack.applyChanges(components);
|
||||
|
||||
return copy;
|
||||
});
|
||||
stacks.removeIf(stack -> !base.test(stack));
|
||||
return stacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresTesting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomIngredientSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
private Ingredient getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ComponentChanges getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
private static class Serializer implements CustomIngredientSerializer<ComponentsIngredient> {
|
||||
private static final Identifier ID = new Identifier("fabric", "components");
|
||||
private static final Codec<ComponentsIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
|
||||
private static final Codec<ComponentsIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
|
||||
private static final PacketCodec<RegistryByteBuf, ComponentsIngredient> PACKET_CODEC = PacketCodec.tuple(
|
||||
Ingredient.PACKET_CODEC, ComponentsIngredient::getBase,
|
||||
ComponentChanges.PACKET_CODEC, ComponentsIngredient::getComponents,
|
||||
ComponentsIngredient::new
|
||||
);
|
||||
|
||||
private static Codec<ComponentsIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
|
||||
return RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
ingredientCodec.fieldOf("base").forGetter(ComponentsIngredient::getBase),
|
||||
ComponentChanges.CODEC.fieldOf("components").forGetter(ComponentsIngredient::getComponents)
|
||||
).apply(instance, ComponentsIngredient::new)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getIdentifier() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<ComponentsIngredient> getCodec(boolean allowEmpty) {
|
||||
return allowEmpty ? ALLOW_EMPTY_CODEC : DISALLOW_EMPTY_CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketCodec<RegistryByteBuf, ComponentsIngredient> getPacketCodec() {
|
||||
return PACKET_CODEC;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtHelper;
|
||||
import net.minecraft.nbt.NbtSizeTracker;
|
||||
import net.minecraft.nbt.StringNbtReader;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.network.RegistryByteBuf;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.network.codec.PacketCodecs;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredient;
|
||||
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
|
||||
|
||||
public class NbtIngredient implements CustomIngredient {
|
||||
public static final CustomIngredientSerializer<NbtIngredient> SERIALIZER = new Serializer();
|
||||
|
||||
private final Ingredient base;
|
||||
@Nullable
|
||||
private final NbtCompound nbt;
|
||||
private final boolean strict;
|
||||
|
||||
public NbtIngredient(Ingredient base, @Nullable NbtCompound nbt, boolean strict) {
|
||||
if (nbt == null && !strict) {
|
||||
throw new IllegalArgumentException("NbtIngredient can only have null NBT in strict mode");
|
||||
}
|
||||
|
||||
this.base = base;
|
||||
this.nbt = nbt;
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(ItemStack stack) {
|
||||
if (!base.test(stack)) return false;
|
||||
|
||||
if (strict) {
|
||||
return Objects.equals(nbt, stack.getNbt());
|
||||
} else {
|
||||
return NbtHelper.matches(nbt, stack.getNbt(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getMatchingStacks() {
|
||||
List<ItemStack> stacks = new ArrayList<>(List.of(base.getMatchingStacks()));
|
||||
stacks.replaceAll(stack -> {
|
||||
ItemStack copy = stack.copy();
|
||||
|
||||
if (nbt != null) {
|
||||
copy.setNbt(nbt.copy());
|
||||
}
|
||||
|
||||
return copy;
|
||||
});
|
||||
stacks.removeIf(stack -> !base.test(stack));
|
||||
return stacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresTesting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomIngredientSerializer<?> getSerializer() {
|
||||
return SERIALIZER;
|
||||
}
|
||||
|
||||
private Ingredient getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private NbtCompound getNbt() {
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
private static class Serializer implements CustomIngredientSerializer<NbtIngredient> {
|
||||
private static final Identifier ID = new Identifier("fabric", "nbt");
|
||||
|
||||
// Supports decoding the NBT as a string as well as the object.
|
||||
private static final Codec<NbtCompound> NBT_CODEC = Codecs.xor(
|
||||
Codec.STRING, NbtCompound.CODEC
|
||||
).flatXmap(either -> either.map(s -> {
|
||||
try {
|
||||
return DataResult.success(StringNbtReader.parse(s));
|
||||
} catch (CommandSyntaxException e) {
|
||||
return DataResult.error(e::getMessage);
|
||||
}
|
||||
}, DataResult::success), nbtCompound -> DataResult.success(Either.left(nbtCompound.asString())));
|
||||
|
||||
private static final Codec<NbtIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
|
||||
private static final Codec<NbtIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
|
||||
private static final PacketCodec<RegistryByteBuf, NbtCompound> NULLABLE_NBT_PACKET_CODEC = new PacketCodec<>() {
|
||||
private static final NbtSizeTracker SIZE_TRACKER = NbtSizeTracker.of(PacketByteBuf.MAX_READ_NBT_SIZE);
|
||||
@Override
|
||||
@Nullable
|
||||
public NbtCompound decode(RegistryByteBuf buf) {
|
||||
if (buf.readBoolean() && buf.readNbt(SIZE_TRACKER) instanceof NbtCompound nbt) {
|
||||
return nbt;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(RegistryByteBuf buf, @Nullable NbtCompound value) {
|
||||
if (value == null) {
|
||||
buf.writeBoolean(false);
|
||||
} else {
|
||||
buf.writeBoolean(true);
|
||||
buf.writeNbt(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
private static final PacketCodec<RegistryByteBuf, NbtIngredient> PACKET_CODEC = PacketCodec.tuple(
|
||||
Ingredient.PACKET_CODEC, NbtIngredient::getBase,
|
||||
NULLABLE_NBT_PACKET_CODEC, NbtIngredient::getNbt,
|
||||
PacketCodecs.BOOL, NbtIngredient::isStrict,
|
||||
NbtIngredient::new
|
||||
);
|
||||
|
||||
private static Codec<NbtIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
|
||||
return RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
ingredientCodec.fieldOf("base").forGetter(NbtIngredient::getBase),
|
||||
NBT_CODEC.optionalFieldOf("nbt", null).forGetter(NbtIngredient::getNbt),
|
||||
Codec.BOOL.optionalFieldOf("strict", false).forGetter(NbtIngredient::isStrict)
|
||||
).apply(instance, NbtIngredient::new)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getIdentifier() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec<NbtIngredient> getCodec(boolean allowEmpty) {
|
||||
return allowEmpty ? ALLOW_EMPTY_CODEC : DISALLOW_EMPTY_CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketCodec<RegistryByteBuf, NbtIngredient> getPacketCodec() {
|
||||
return PACKET_CODEC;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
package net.fabricmc.fabric.test.recipe.ingredient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.minecraft.component.ComponentChanges;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.recipe.Ingredient;
|
||||
import net.minecraft.test.GameTest;
|
||||
import net.minecraft.test.GameTestException;
|
||||
|
@ -89,50 +89,42 @@ public class IngredientMatchTests {
|
|||
}
|
||||
|
||||
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
|
||||
public void testNbtIngredient(TestContext context) {
|
||||
for (boolean strict : List.of(true, false)) {
|
||||
NbtCompound undamagedNbt = new NbtCompound();
|
||||
undamagedNbt.putInt(ItemStack.DAMAGE_KEY, 0);
|
||||
public void testComponentIngredient(TestContext context) {
|
||||
final Ingredient baseIngredient = Ingredient.ofItems(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE);
|
||||
final Ingredient undamagedIngredient = DefaultCustomIngredients.components(
|
||||
baseIngredient,
|
||||
builder -> builder.add(DataComponentTypes.DAMAGE, 0)
|
||||
);
|
||||
final Ingredient noNameUndamagedIngredient = DefaultCustomIngredients.components(
|
||||
baseIngredient,
|
||||
builder -> builder
|
||||
.add(DataComponentTypes.DAMAGE, 0)
|
||||
.remove(DataComponentTypes.CUSTOM_NAME)
|
||||
);
|
||||
|
||||
Ingredient nbtIngredient = DefaultCustomIngredients.nbt(Ingredient.ofItems(Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE), undamagedNbt, strict);
|
||||
ItemStack renamedUndamagedDiamondPickaxe = new ItemStack(Items.DIAMOND_PICKAXE);
|
||||
renamedUndamagedDiamondPickaxe.set(DataComponentTypes.CUSTOM_NAME, Text.literal("Renamed"));
|
||||
assertEquals(true, undamagedIngredient.test(renamedUndamagedDiamondPickaxe));
|
||||
assertEquals(false, noNameUndamagedIngredient.test(renamedUndamagedDiamondPickaxe));
|
||||
|
||||
assertEquals(2, nbtIngredient.getMatchingStacks().length);
|
||||
assertEquals(Items.DIAMOND_PICKAXE, nbtIngredient.getMatchingStacks()[0].getItem());
|
||||
assertEquals(Items.NETHERITE_PICKAXE, nbtIngredient.getMatchingStacks()[1].getItem());
|
||||
assertEquals(undamagedNbt, nbtIngredient.getMatchingStacks()[0].getNbt());
|
||||
assertEquals(undamagedNbt, nbtIngredient.getMatchingStacks()[1].getNbt());
|
||||
assertEquals(false, nbtIngredient.isEmpty());
|
||||
assertEquals(2, undamagedIngredient.getMatchingStacks().length);
|
||||
ItemStack result0 = undamagedIngredient.getMatchingStacks()[0];
|
||||
ItemStack result1 = undamagedIngredient.getMatchingStacks()[1];
|
||||
|
||||
// Undamaged is fine
|
||||
assertEquals(true, nbtIngredient.test(new ItemStack(Items.DIAMOND_PICKAXE)));
|
||||
assertEquals(true, nbtIngredient.test(new ItemStack(Items.NETHERITE_PICKAXE)));
|
||||
assertEquals(Items.DIAMOND_PICKAXE, result0.getItem());
|
||||
assertEquals(Items.NETHERITE_PICKAXE, result1.getItem());
|
||||
assertEquals(ComponentChanges.EMPTY, result0.getComponentChanges());
|
||||
assertEquals(ComponentChanges.EMPTY, result1.getComponentChanges());
|
||||
assertEquals(false, undamagedIngredient.isEmpty());
|
||||
|
||||
// Damaged is not fine
|
||||
ItemStack damagedDiamondPickaxe = new ItemStack(Items.DIAMOND_PICKAXE);
|
||||
damagedDiamondPickaxe.setDamage(10);
|
||||
assertEquals(false, nbtIngredient.test(damagedDiamondPickaxe));
|
||||
// Undamaged is fine
|
||||
assertEquals(true, undamagedIngredient.test(new ItemStack(Items.DIAMOND_PICKAXE)));
|
||||
assertEquals(true, undamagedIngredient.test(new ItemStack(Items.NETHERITE_PICKAXE)));
|
||||
|
||||
// Renamed undamaged is only fine in partial matching
|
||||
ItemStack renamedUndamagedDiamondPickaxe = new ItemStack(Items.DIAMOND_PICKAXE);
|
||||
renamedUndamagedDiamondPickaxe.setCustomName(Text.literal("Renamed"));
|
||||
assertEquals(!strict, nbtIngredient.test(renamedUndamagedDiamondPickaxe));
|
||||
}
|
||||
|
||||
// Also test strict null NBT matching
|
||||
Ingredient noNbtIngredient = DefaultCustomIngredients.nbt(Ingredient.ofItems(Items.APPLE), null, true);
|
||||
|
||||
assertEquals(1, noNbtIngredient.getMatchingStacks().length);
|
||||
assertEquals(Items.APPLE, noNbtIngredient.getMatchingStacks()[0].getItem());
|
||||
assertEquals(null, noNbtIngredient.getMatchingStacks()[0].getNbt());
|
||||
assertEquals(false, noNbtIngredient.isEmpty());
|
||||
|
||||
// No NBT is fine
|
||||
assertEquals(true, noNbtIngredient.test(new ItemStack(Items.APPLE)));
|
||||
|
||||
// NBT is not fine
|
||||
ItemStack nbtApple = new ItemStack(Items.APPLE);
|
||||
nbtApple.setCustomName(Text.literal("Renamed"));
|
||||
assertEquals(false, noNbtIngredient.test(nbtApple));
|
||||
// Damaged is not fine
|
||||
ItemStack damagedDiamondPickaxe = new ItemStack(Items.DIAMOND_PICKAXE);
|
||||
damagedDiamondPickaxe.setDamage(10);
|
||||
assertEquals(false, undamagedIngredient.test(damagedDiamondPickaxe));
|
||||
|
||||
context.complete();
|
||||
}
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
"item": "minecraft:diamond_pickaxe"
|
||||
},
|
||||
{
|
||||
"fabric:type": "fabric:nbt",
|
||||
"fabric:type": "fabric:components",
|
||||
"base": {
|
||||
"item": "minecraft:diamond_pickaxe"
|
||||
},
|
||||
"nbt": "{Damage:0}",
|
||||
"components": {
|
||||
"minecraft:damage": 0
|
||||
},
|
||||
"strict": false
|
||||
},
|
||||
{
|
||||
|
@ -35,6 +37,6 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond_block"
|
||||
"id": "minecraft:diamond_block"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import net.minecraft.client.render.model.BakedQuad;
|
|||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -95,7 +96,7 @@ public class FrameBakedModel implements BakedModel {
|
|||
this.frameMesh.outputTo(context.getEmitter());
|
||||
|
||||
// Emit a scaled-down fence for testing, trying both materials again.
|
||||
RenderMaterial material = stack.hasCustomName() ? translucentEmissiveMaterial : translucentMaterial;
|
||||
RenderMaterial material = stack.contains(DataComponentTypes.CUSTOM_NAME) ? translucentEmissiveMaterial : translucentMaterial;
|
||||
|
||||
ItemStack innerItem = Items.CRAFTING_TABLE.getDefaultStack();
|
||||
BakedModel innerModel = MinecraftClient.getInstance().getItemRenderer().getModel(innerItem, null, null, 0);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond"
|
||||
"id": "minecraft:diamond"
|
||||
},
|
||||
"fabric:load_conditions": [
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond"
|
||||
"id": "minecraft:diamond"
|
||||
},
|
||||
"fabric:load_conditions": [
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond"
|
||||
"id": "minecraft:diamond"
|
||||
},
|
||||
"fabric:load_conditions": [
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:diamond"
|
||||
"id": "minecraft:diamond"
|
||||
},
|
||||
"fabric:load_conditions": [
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:dirt"
|
||||
"id": "minecraft:dirt"
|
||||
},
|
||||
"fabric:load_conditions": [
|
||||
{
|
||||
|
|
|
@ -97,7 +97,7 @@ public final class Networking implements ModInitializer {
|
|||
Identifier id = buf.readIdentifier();
|
||||
PacketCodec<RegistryByteBuf, D> codec = (PacketCodec<RegistryByteBuf, D>) CODEC_BY_ID.get(id);
|
||||
|
||||
return new OpenScreenPayload<>(id, buf.readByte(), TextCodecs.PACKET_CODEC.decode(buf), codec, codec == null ? null : codec.decode(buf));
|
||||
return new OpenScreenPayload<>(id, buf.readByte(), TextCodecs.REGISTRY_PACKET_CODEC.decode(buf), codec, codec == null ? null : codec.decode(buf));
|
||||
}
|
||||
|
||||
private void write(RegistryByteBuf buf) {
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
package net.fabricmc.fabric.test.screenhandler.item;
|
||||
|
||||
import net.minecraft.inventory.Inventories;
|
||||
import net.minecraft.component.DataComponentTypes;
|
||||
import net.minecraft.component.type.ContainerComponent;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
final class BagInventory implements ImplementedInventory {
|
||||
|
@ -27,11 +27,7 @@ final class BagInventory implements ImplementedInventory {
|
|||
|
||||
BagInventory(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
NbtCompound tag = stack.getSubNbt("Items");
|
||||
|
||||
if (tag != null) {
|
||||
Inventories.readNbt(tag, items);
|
||||
}
|
||||
stack.getOrDefault(DataComponentTypes.CONTAINER, ContainerComponent.fromStacks(items));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +37,6 @@ final class BagInventory implements ImplementedInventory {
|
|||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
NbtCompound tag = stack.getOrCreateSubNbt("Items");
|
||||
Inventories.writeNbt(tag, items);
|
||||
stack.set(DataComponentTypes.CONTAINER, ContainerComponent.fromStacks(items));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,11 +243,8 @@ transitive-accessible method net/minecraft/block/WetSpongeBlock <init> (Lnet/min
|
|||
transitive-accessible method net/minecraft/block/WitherSkullBlock <init> (Lnet/minecraft/block/AbstractBlock$Settings;)V
|
||||
|
||||
# Constructors of non-abstract item classes
|
||||
transitive-accessible method net/minecraft/item/AxeItem <init> (Lnet/minecraft/item/ToolMaterial;FFLnet/minecraft/item/Item$Settings;)V
|
||||
transitive-accessible method net/minecraft/item/HoeItem <init> (Lnet/minecraft/item/ToolMaterial;IFLnet/minecraft/item/Item$Settings;)V
|
||||
transitive-accessible method net/minecraft/item/MiningToolItem <init> (FFLnet/minecraft/item/ToolMaterial;Lnet/minecraft/registry/tag/TagKey;Lnet/minecraft/item/Item$Settings;)V
|
||||
transitive-accessible method net/minecraft/item/MiningToolItem <init> (Lnet/minecraft/item/ToolMaterial;Lnet/minecraft/registry/tag/TagKey;Lnet/minecraft/item/Item$Settings;)V
|
||||
transitive-accessible method net/minecraft/item/MusicDiscItem <init> (ILnet/minecraft/sound/SoundEvent;Lnet/minecraft/item/Item$Settings;I)V
|
||||
transitive-accessible method net/minecraft/item/PickaxeItem <init> (Lnet/minecraft/item/ToolMaterial;IFLnet/minecraft/item/Item$Settings;)V
|
||||
|
||||
# Protected static fields of RenderPhase
|
||||
transitive-accessible field net/minecraft/client/render/RenderPhase NO_TRANSPARENCY Lnet/minecraft/client/render/RenderPhase$Transparency;
|
||||
|
|
|
@ -3,8 +3,8 @@ org.gradle.parallel=true
|
|||
fabric.loom.multiProjectOptimisation=true
|
||||
|
||||
version=0.96.4
|
||||
minecraft_version=24w07a
|
||||
yarn_version=+build.1
|
||||
minecraft_version=24w09a
|
||||
yarn_version=+build.5
|
||||
loader_version=0.15.6
|
||||
installer_version=0.11.1
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ include 'fabric-resource-loader-v0'
|
|||
include 'fabric-screen-api-v1'
|
||||
include 'fabric-screen-handler-api-v1'
|
||||
include 'fabric-sound-api-v1'
|
||||
include 'fabric-transfer-api-v1'
|
||||
//include 'fabric-transfer-api-v1'
|
||||
include 'fabric-transitive-access-wideners-v1'
|
||||
|
||||
include 'deprecated'
|
||||
|
|
Loading…
Reference in a new issue