mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-27 01:55:41 -05:00
Modify Enchantment and Fabric Component Map Builder Extensions (#4085)
* modify effects event
* give impaling fire aspect
* add fabric component map builder
* change interface name to match event
* gametests for weird impaling enchantment
* fix checkstyle issues
* fabric map builder javadoc
* modify effects javadoc
* fix checkstyle issues
* prefer extension methods over add
* add enchantment source
* fix missing asterisk on fabricitemstack javadoc
* switch to enchantment builder
* fix effects list
* fix checkstyle
* add note on exclusive set to javadoc
* add fabric component builder extensions to default component testmod
* remove threadlocal usage from mixin
* remove modid prefix from accessors
* remove unused import
* fix recursive invoker
* add test to automatically check modified item name
(cherry picked from commit d5debaed0e
)
This commit is contained in:
parent
50ed0faf3a
commit
ebc0bc7d18
18 changed files with 808 additions and 5 deletions
|
@ -1,6 +1,6 @@
|
||||||
version = getSubprojectVersion(project)
|
version = getSubprojectVersion(project)
|
||||||
|
|
||||||
moduleDependencies(project, ['fabric-api-base'])
|
moduleDependencies(project, ['fabric-api-base', 'fabric-resource-loader-v0'])
|
||||||
|
|
||||||
testDependencies(project, [
|
testDependencies(project, [
|
||||||
':fabric-content-registries-v0',
|
':fabric-content-registries-v0',
|
||||||
|
|
|
@ -18,6 +18,7 @@ package net.fabricmc.fabric.api.item.v1;
|
||||||
|
|
||||||
import net.minecraft.enchantment.Enchantment;
|
import net.minecraft.enchantment.Enchantment;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
import net.minecraft.registry.entry.RegistryEntry;
|
import net.minecraft.registry.entry.RegistryEntry;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.event.Event;
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
@ -64,6 +65,27 @@ public final class EnchantmentEvents {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event that allows an {@link Enchantment} to be modified without needing to fully override an enchantment.
|
||||||
|
*
|
||||||
|
* <p>This should only be used to modify the behavior of <em>external</em> enchantments, where 'external' means
|
||||||
|
* either vanilla or from another mod. For instance, a mod might add a bleed effect to Sharpness (and only Sharpness).
|
||||||
|
* For your own enchantments, you should simply define them in your mod's data pack. See the
|
||||||
|
* <a href="https://minecraft.wiki/w/Enchantment_definition">Enchantment Definition page</a> on the Minecraft Wiki
|
||||||
|
* for more information.
|
||||||
|
*
|
||||||
|
* <p>Note: If you wish to modify the exclusive set of the enchantment, consider extending the
|
||||||
|
* {@linkplain net.minecraft.registry.tag.EnchantmentTags relevant tag} through your mod's data pack instead.
|
||||||
|
*/
|
||||||
|
public static final Event<Modify> MODIFY = EventFactory.createArrayBacked(
|
||||||
|
Modify.class,
|
||||||
|
callbacks -> (key, builder, source) -> {
|
||||||
|
for (Modify callback : callbacks) {
|
||||||
|
callback.modify(key, builder, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface AllowEnchanting {
|
public interface AllowEnchanting {
|
||||||
/**
|
/**
|
||||||
|
@ -82,4 +104,20 @@ public final class EnchantmentEvents {
|
||||||
EnchantingContext enchantingContext
|
EnchantingContext enchantingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Modify {
|
||||||
|
/**
|
||||||
|
* Modifies the effects of an {@link Enchantment}.
|
||||||
|
*
|
||||||
|
* @param key The ID of the enchantment
|
||||||
|
* @param builder The enchantment builder
|
||||||
|
* @param source The source of the enchantment
|
||||||
|
*/
|
||||||
|
void modify(
|
||||||
|
RegistryKey<Enchantment> key,
|
||||||
|
Enchantment.Builder builder,
|
||||||
|
EnchantmentSource source
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines where an enchantment has been loaded from.
|
||||||
|
*/
|
||||||
|
public enum EnchantmentSource {
|
||||||
|
/**
|
||||||
|
* An enchantment loaded from the vanilla data pack.
|
||||||
|
*/
|
||||||
|
VANILLA(true),
|
||||||
|
/**
|
||||||
|
* An enchantment loaded from mods' bundled resources.
|
||||||
|
*
|
||||||
|
* <p>This includes the additional builtin data packs registered by mods
|
||||||
|
* with Fabric Resource Loader.
|
||||||
|
*/
|
||||||
|
MOD(true),
|
||||||
|
/**
|
||||||
|
* An enchantment loaded from an external data pack.
|
||||||
|
*/
|
||||||
|
DATA_PACK(false);
|
||||||
|
|
||||||
|
private final boolean builtin;
|
||||||
|
|
||||||
|
EnchantmentSource(boolean builtin) {
|
||||||
|
this.builtin = builtin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this enchantment source is builtin and bundled in the vanilla or mod resources.
|
||||||
|
*
|
||||||
|
* <p>{@link #VANILLA} and {@link #MOD} are builtin.
|
||||||
|
*
|
||||||
|
* @return {@code true} if builtin, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
public boolean isBuiltin() {
|
||||||
|
return builtin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import net.minecraft.component.ComponentType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fabric-provided extensions for {@link net.minecraft.component.ComponentMap.Builder}.
|
||||||
|
*
|
||||||
|
* <p>Note: This interface is automatically implemented on all component map builders via Mixin and interface injection.
|
||||||
|
*/
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
|
public interface FabricComponentMapBuilder {
|
||||||
|
/**
|
||||||
|
* Gets the current value for the component type in the builder, or creates and adds a new value if it is not present.
|
||||||
|
*
|
||||||
|
* @param type The component type
|
||||||
|
* @param fallback The supplier for the default data value if the type is not in this map yet. The value given by this supplier
|
||||||
|
* may not be null.
|
||||||
|
* @param <T> The type of the component data
|
||||||
|
* @return Returns the current value in the map builder, or the default value provided by the fallback if not present
|
||||||
|
* @see #getOrEmpty(ComponentType)
|
||||||
|
*/
|
||||||
|
default <T> T getOrCreate(ComponentType<T> type, Supplier<@NotNull T> fallback) {
|
||||||
|
throw new AssertionError("Implemented in Mixin");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current value for the component type in the builder, or creates and adds a new value if it is not present.
|
||||||
|
*
|
||||||
|
* @param type The component type
|
||||||
|
* @param defaultValue The default data value if the type is not in this map yet
|
||||||
|
* @param <T> The type of the component data
|
||||||
|
* @return Returns the current value in the map builder, or the default value if not present
|
||||||
|
*/
|
||||||
|
default <T> T getOrDefault(ComponentType<T> type, @NotNull T defaultValue) {
|
||||||
|
Objects.requireNonNull(defaultValue, "Cannot insert null values to component map builder");
|
||||||
|
return getOrCreate(type, () -> defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For list component types specifically, returns a mutable list of values currently held in the builder for the given
|
||||||
|
* component type. If the type is not registered to this builder yet, this will create and add a new empty list to the builder
|
||||||
|
* for the type, and return that.
|
||||||
|
*
|
||||||
|
* @param type The component type. The component must be a list-type.
|
||||||
|
* @param <T> The type of the component entry data
|
||||||
|
* @return Returns a mutable list of values for the type.
|
||||||
|
*/
|
||||||
|
default <T> List<T> getOrEmpty(ComponentType<List<T>> type) {
|
||||||
|
throw new AssertionError("Implemented in Mixin");
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ import net.minecraft.registry.entry.RegistryEntry;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.util.TriState;
|
import net.fabricmc.fabric.api.util.TriState;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Fabric-provided extensions for {@link ItemStack}.
|
* Fabric-provided extensions for {@link ItemStack}.
|
||||||
* This interface is automatically implemented on all item stacks via Mixin and interface injection.
|
* This interface is automatically implemented on all item stacks via Mixin and interface injection.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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.item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.minecraft.component.ComponentType;
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
import net.minecraft.resource.Resource;
|
||||||
|
import net.minecraft.resource.ResourcePackSource;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.item.v1.EnchantmentEvents;
|
||||||
|
import net.fabricmc.fabric.api.item.v1.EnchantmentSource;
|
||||||
|
import net.fabricmc.fabric.impl.resource.loader.BuiltinModResourcePackSource;
|
||||||
|
import net.fabricmc.fabric.impl.resource.loader.FabricResource;
|
||||||
|
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackCreator;
|
||||||
|
import net.fabricmc.fabric.mixin.item.EnchantmentBuilderAccessor;
|
||||||
|
|
||||||
|
public class EnchantmentUtil {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Enchantment modify(RegistryKey<Enchantment> key, Enchantment originalEnchantment, EnchantmentSource source) {
|
||||||
|
Enchantment.Builder builder = Enchantment.builder(originalEnchantment.definition());
|
||||||
|
EnchantmentBuilderAccessor accessor = (EnchantmentBuilderAccessor) builder;
|
||||||
|
|
||||||
|
builder.exclusiveSet(originalEnchantment.exclusiveSet());
|
||||||
|
accessor.getEffectMap().addAll(originalEnchantment.effects());
|
||||||
|
|
||||||
|
originalEnchantment.effects().stream()
|
||||||
|
.forEach(component -> {
|
||||||
|
if (component.value() instanceof List<?> valueList) {
|
||||||
|
// component type cast is checked by the value
|
||||||
|
accessor.invokeGetEffectsList((ComponentType<List<Object>>) component.type())
|
||||||
|
.addAll(valueList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
EnchantmentEvents.MODIFY.invoker().modify(key, builder, source);
|
||||||
|
|
||||||
|
return new Enchantment(
|
||||||
|
originalEnchantment.description(),
|
||||||
|
accessor.getDefinition(),
|
||||||
|
accessor.getExclusiveSet(),
|
||||||
|
accessor.getEffectMap().build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EnchantmentSource determineSource(Resource resource) {
|
||||||
|
if (resource != null) {
|
||||||
|
ResourcePackSource packSource = ((FabricResource) resource).getFabricPackSource();
|
||||||
|
|
||||||
|
if (packSource == ResourcePackSource.BUILTIN) {
|
||||||
|
return EnchantmentSource.VANILLA;
|
||||||
|
} else if (packSource == ModResourcePackCreator.RESOURCE_PACK_SOURCE || packSource instanceof BuiltinModResourcePackSource) {
|
||||||
|
return EnchantmentSource.MOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not builtin or mod, assume external data pack.
|
||||||
|
// It might also be a virtual enchantment injected via mixin instead of being loaded
|
||||||
|
// from a resource, but we can't determine that here.
|
||||||
|
return EnchantmentSource.DATA_PACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnchantmentUtil() { }
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.item;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import net.minecraft.component.ComponentMap;
|
||||||
|
import net.minecraft.component.ComponentType;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.item.v1.FabricComponentMapBuilder;
|
||||||
|
|
||||||
|
@Mixin(ComponentMap.Builder.class)
|
||||||
|
abstract class ComponentMapBuilderMixin implements FabricComponentMapBuilder {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private Reference2ObjectMap<ComponentType<?>, Object> components;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
public abstract <T> ComponentMap.Builder add(ComponentType<T> type, @Nullable T value);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T getOrCreate(ComponentType<T> type, Supplier<@NotNull T> fallback) {
|
||||||
|
if (!this.components.containsKey(type)) {
|
||||||
|
T defaultValue = fallback.get();
|
||||||
|
Objects.requireNonNull(defaultValue, "Cannot insert null values to component map builder");
|
||||||
|
this.add(type, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (T) this.components.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> getOrEmpty(ComponentType<List<T>> type) {
|
||||||
|
// creating a new array list guarantees that the list in the map is mutable
|
||||||
|
List<T> existing = new ArrayList<>(this.getOrCreate(type, Collections::emptyList));
|
||||||
|
this.add(type, existing);
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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.item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import net.minecraft.component.ComponentMap;
|
||||||
|
import net.minecraft.component.ComponentType;
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.registry.entry.RegistryEntryList;
|
||||||
|
|
||||||
|
@Mixin(Enchantment.Builder.class)
|
||||||
|
public interface EnchantmentBuilderAccessor {
|
||||||
|
@Accessor("definition")
|
||||||
|
Enchantment.Definition getDefinition();
|
||||||
|
|
||||||
|
@Accessor("exclusiveSet")
|
||||||
|
RegistryEntryList<Enchantment> getExclusiveSet();
|
||||||
|
|
||||||
|
@Accessor("effectMap")
|
||||||
|
ComponentMap.Builder getEffectMap();
|
||||||
|
|
||||||
|
@Invoker("getEffectsList")
|
||||||
|
<E> List<E> invokeGetEffectsList(ComponentType<List<E>> type);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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.item;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import com.mojang.serialization.Decoder;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.registry.MutableRegistry;
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
import net.minecraft.registry.RegistryLoader;
|
||||||
|
import net.minecraft.registry.RegistryOps;
|
||||||
|
import net.minecraft.registry.entry.RegistryEntry;
|
||||||
|
import net.minecraft.registry.entry.RegistryEntryInfo;
|
||||||
|
import net.minecraft.resource.Resource;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.impl.item.EnchantmentUtil;
|
||||||
|
|
||||||
|
@Mixin(RegistryLoader.class)
|
||||||
|
abstract class RegistryLoaderMixin {
|
||||||
|
@WrapOperation(
|
||||||
|
method = "parseAndAdd",
|
||||||
|
at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/registry/MutableRegistry;add(Lnet/minecraft/registry/RegistryKey;Ljava/lang/Object;Lnet/minecraft/registry/entry/RegistryEntryInfo;)Lnet/minecraft/registry/entry/RegistryEntry$Reference;"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T> RegistryEntry.Reference<T> enchantmentKey(
|
||||||
|
MutableRegistry<T> instance,
|
||||||
|
RegistryKey<T> objectKey,
|
||||||
|
Object object,
|
||||||
|
RegistryEntryInfo registryEntryInfo,
|
||||||
|
Operation<RegistryEntry.Reference<T>> original,
|
||||||
|
MutableRegistry<T> registry,
|
||||||
|
Decoder<T> decoder,
|
||||||
|
RegistryOps<JsonElement> ops,
|
||||||
|
RegistryKey<T> registryKey,
|
||||||
|
Resource resource,
|
||||||
|
RegistryEntryInfo entryInfo
|
||||||
|
) {
|
||||||
|
if (object instanceof Enchantment enchantment) {
|
||||||
|
object = EnchantmentUtil.modify((RegistryKey<Enchantment>) objectKey, enchantment, EnchantmentUtil.determineSource(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
return original.call(instance, registryKey, object, registryEntryInfo);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@
|
||||||
"AbstractFurnaceBlockEntityMixin",
|
"AbstractFurnaceBlockEntityMixin",
|
||||||
"AnvilScreenHandlerMixin",
|
"AnvilScreenHandlerMixin",
|
||||||
"BrewingStandBlockEntityMixin",
|
"BrewingStandBlockEntityMixin",
|
||||||
|
"ComponentMapBuilderMixin",
|
||||||
|
"EnchantmentBuilderAccessor",
|
||||||
"EnchantCommandMixin",
|
"EnchantCommandMixin",
|
||||||
"EnchantmentHelperMixin",
|
"EnchantmentHelperMixin",
|
||||||
"EnchantRandomlyLootFunctionMixin",
|
"EnchantRandomlyLootFunctionMixin",
|
||||||
|
@ -15,7 +17,8 @@
|
||||||
"ItemStackMixin",
|
"ItemStackMixin",
|
||||||
"LivingEntityMixin",
|
"LivingEntityMixin",
|
||||||
"RecipeMixin",
|
"RecipeMixin",
|
||||||
"RegistriesMixin"
|
"RegistriesMixin",
|
||||||
|
"RegistryLoaderMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
"loom:injected_interfaces": {
|
"loom:injected_interfaces": {
|
||||||
"net/minecraft/class_1792": ["net/fabricmc/fabric/api/item/v1/FabricItem"],
|
"net/minecraft/class_1792": ["net/fabricmc/fabric/api/item/v1/FabricItem"],
|
||||||
"net/minecraft/class_1792\u0024class_1793": ["net/fabricmc/fabric/api/item/v1/FabricItem\u0024Settings"],
|
"net/minecraft/class_1792\u0024class_1793": ["net/fabricmc/fabric/api/item/v1/FabricItem\u0024Settings"],
|
||||||
"net/minecraft/class_1799": ["net/fabricmc/fabric/api/item/v1/FabricItemStack"]
|
"net/minecraft/class_1799": ["net/fabricmc/fabric/api/item/v1/FabricItemStack"],
|
||||||
|
"net/minecraft/class_9323\u0024class_9324": ["net/fabricmc/fabric/api/item/v1/FabricComponentMapBuilder"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.component.EnchantmentEffectComponentTypes;
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.EnchantmentLevelBasedValue;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEffectTarget;
|
||||||
|
import net.minecraft.enchantment.effect.entity.IgniteEnchantmentEffect;
|
||||||
|
import net.minecraft.enchantment.effect.value.AddEnchantmentEffect;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.loot.condition.DamageSourcePropertiesLootCondition;
|
||||||
|
import net.minecraft.loot.condition.EntityPropertiesLootCondition;
|
||||||
|
import net.minecraft.loot.context.LootContext;
|
||||||
|
import net.minecraft.predicate.entity.DamageSourcePredicate;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicate;
|
||||||
|
import net.minecraft.predicate.entity.EntityTypePredicate;
|
||||||
|
import net.minecraft.registry.RegistryKey;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ModInitializer;
|
||||||
|
import net.fabricmc.fabric.api.item.v1.EnchantmentEvents;
|
||||||
|
|
||||||
|
public class CustomEnchantmentEffectsTest implements ModInitializer {
|
||||||
|
// weird impaling is a copy of impaling used for testing (just in case minecraft changes impaling for some reason)
|
||||||
|
public static final RegistryKey<Enchantment> WEIRD_IMPALING = RegistryKey.of(
|
||||||
|
RegistryKeys.ENCHANTMENT,
|
||||||
|
Identifier.of("fabric-item-api-v1-testmod", "weird_impaling")
|
||||||
|
);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
EnchantmentEvents.MODIFY.register(
|
||||||
|
(key, builder, source) -> {
|
||||||
|
if (source.isBuiltin() && key == WEIRD_IMPALING) {
|
||||||
|
// make impaling set things on fire
|
||||||
|
builder.addEffect(
|
||||||
|
EnchantmentEffectComponentTypes.POST_ATTACK,
|
||||||
|
EnchantmentEffectTarget.ATTACKER,
|
||||||
|
EnchantmentEffectTarget.VICTIM,
|
||||||
|
new IgniteEnchantmentEffect(EnchantmentLevelBasedValue.linear(4.0f)),
|
||||||
|
DamageSourcePropertiesLootCondition.builder(
|
||||||
|
DamageSourcePredicate.Builder.create().isDirect(true)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// add bonus impaling damage to zombie
|
||||||
|
builder.addEffect(
|
||||||
|
EnchantmentEffectComponentTypes.DAMAGE,
|
||||||
|
new AddEnchantmentEffect(EnchantmentLevelBasedValue.linear(2.5f)),
|
||||||
|
EntityPropertiesLootCondition.builder(
|
||||||
|
LootContext.EntityTarget.THIS,
|
||||||
|
EntityPredicate.Builder.create()
|
||||||
|
.type(EntityTypePredicate.create(EntityType.ZOMBIE))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,6 +51,14 @@ public class DefaultItemComponentTest implements ModInitializer {
|
||||||
// Remove the food component from beef
|
// Remove the food component from beef
|
||||||
builder.add(DataComponentTypes.FOOD, null);
|
builder.add(DataComponentTypes.FOOD, null);
|
||||||
});
|
});
|
||||||
|
// add a word to the start of diamond pickaxe name
|
||||||
|
context.modify(Items.DIAMOND_PICKAXE, builder -> {
|
||||||
|
Text baseName = builder.getOrCreate(
|
||||||
|
DataComponentTypes.ITEM_NAME,
|
||||||
|
Items.DIAMOND_PICKAXE::getName
|
||||||
|
);
|
||||||
|
builder.add(DataComponentTypes.ITEM_NAME, prependModifiedLiteral(baseName));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Make all fireworks glint
|
// Make all fireworks glint
|
||||||
|
@ -60,4 +68,9 @@ public class DefaultItemComponentTest implements ModInitializer {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Text prependModifiedLiteral(Text name) {
|
||||||
|
return Text.literal("Modified ")
|
||||||
|
.append(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* 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.gametest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import net.minecraft.component.EnchantmentEffectComponentTypes;
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentEffectEntry;
|
||||||
|
import net.minecraft.enchantment.effect.EnchantmentValueEffect;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.mob.CreeperEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.registry.DynamicRegistryManager;
|
||||||
|
import net.minecraft.registry.Registry;
|
||||||
|
import net.minecraft.registry.RegistryKeys;
|
||||||
|
import net.minecraft.registry.entry.RegistryEntry;
|
||||||
|
import net.minecraft.test.GameTest;
|
||||||
|
import net.minecraft.test.GameTestException;
|
||||||
|
import net.minecraft.test.TestContext;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.GameMode;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
||||||
|
import net.fabricmc.fabric.test.item.CustomEnchantmentEffectsTest;
|
||||||
|
|
||||||
|
public class CustomEnchantmentEffectsGameTest implements FabricGameTest {
|
||||||
|
@GameTest(templateName = "fabric-item-api-v1-testmod:bedrock_platform")
|
||||||
|
public void weirdImpalingSetsFireToTargets(TestContext context) {
|
||||||
|
BlockPos pos = new BlockPos(3, 3, 3);
|
||||||
|
CreeperEntity creeper = context.spawnEntity(EntityType.CREEPER, pos);
|
||||||
|
PlayerEntity player = context.createMockPlayer(GameMode.CREATIVE);
|
||||||
|
|
||||||
|
ItemStack trident = Items.TRIDENT.getDefaultStack();
|
||||||
|
Optional<RegistryEntry.Reference<Enchantment>> impaling = getEnchantmentRegistry(context)
|
||||||
|
.getEntry(CustomEnchantmentEffectsTest.WEIRD_IMPALING);
|
||||||
|
if (impaling.isEmpty()) {
|
||||||
|
throw new GameTestException("Weird Impaling enchantment is not present");
|
||||||
|
}
|
||||||
|
|
||||||
|
trident.addEnchantment(impaling.get(), 1);
|
||||||
|
|
||||||
|
player.setStackInHand(Hand.MAIN_HAND, trident);
|
||||||
|
|
||||||
|
context.expectEntityWithData(pos, EntityType.CREEPER, Entity::isOnFire, false);
|
||||||
|
player.attack(creeper);
|
||||||
|
context.expectEntityWithDataEnd(pos, EntityType.CREEPER, Entity::isOnFire, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GameTest(templateName = EMPTY_STRUCTURE)
|
||||||
|
public void weirdImpalingHasTwoDamageEffects(TestContext context) {
|
||||||
|
Enchantment impaling = getEnchantmentRegistry(context).get(CustomEnchantmentEffectsTest.WEIRD_IMPALING);
|
||||||
|
|
||||||
|
if (impaling == null) {
|
||||||
|
throw new GameTestException("Weird Impaling enchantment is not present");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EnchantmentEffectEntry<EnchantmentValueEffect>> damageEffects = impaling
|
||||||
|
.getEffect(EnchantmentEffectComponentTypes.DAMAGE);
|
||||||
|
|
||||||
|
context.assertTrue(
|
||||||
|
damageEffects.size() == 2,
|
||||||
|
String.format("Weird Impaling has %d damage effect(s), not the expected 2", damageEffects.size())
|
||||||
|
);
|
||||||
|
context.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Registry<Enchantment> getEnchantmentRegistry(TestContext context) {
|
||||||
|
DynamicRegistryManager registryManager = context.getWorld().getRegistryManager();
|
||||||
|
return registryManager.get(RegistryKeys.ENCHANTMENT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import net.minecraft.component.DataComponentTypes;
|
import net.minecraft.component.DataComponentTypes;
|
||||||
import net.minecraft.component.type.FireworksComponent;
|
import net.minecraft.component.type.FireworksComponent;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.test.GameTest;
|
import net.minecraft.test.GameTest;
|
||||||
|
@ -28,6 +29,7 @@ import net.minecraft.test.TestContext;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
||||||
|
import net.fabricmc.fabric.test.item.DefaultItemComponentTest;
|
||||||
|
|
||||||
public class DefaultItemComponentGameTest implements FabricGameTest {
|
public class DefaultItemComponentGameTest implements FabricGameTest {
|
||||||
@GameTest(templateName = EMPTY_STRUCTURE)
|
@GameTest(templateName = EMPTY_STRUCTURE)
|
||||||
|
@ -73,4 +75,20 @@ public class DefaultItemComponentGameTest implements FabricGameTest {
|
||||||
|
|
||||||
context.complete();
|
context.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GameTest(templateName = EMPTY_STRUCTURE)
|
||||||
|
public void diamondPickaxeIsRenamed(TestContext context) {
|
||||||
|
Item testItem = Items.DIAMOND_PICKAXE;
|
||||||
|
ItemStack stack = testItem.getDefaultStack();
|
||||||
|
|
||||||
|
Text itemName = stack.getOrDefault(DataComponentTypes.ITEM_NAME, Text.literal(""));
|
||||||
|
Text expectedName = DefaultItemComponentTest.prependModifiedLiteral(testItem.getName());
|
||||||
|
|
||||||
|
String errorMessage = "Expected '%s' to be contained in '%s', but it was not!";
|
||||||
|
|
||||||
|
// if they contain each other, then they are equal
|
||||||
|
context.assertTrue(itemName.contains(expectedName), errorMessage.formatted(expectedName, itemName));
|
||||||
|
context.assertTrue(expectedName.contains(itemName), errorMessage.formatted(itemName, expectedName));
|
||||||
|
context.complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"description": {
|
||||||
|
"text": "Weird Impaling"
|
||||||
|
},
|
||||||
|
"exclusive_set": "#minecraft:exclusive_set/damage",
|
||||||
|
"supported_items": "#minecraft:enchantable/trident",
|
||||||
|
"weight": 2,
|
||||||
|
"max_level": 5,
|
||||||
|
"min_cost": {
|
||||||
|
"base": 1,
|
||||||
|
"per_level_above_first": 8
|
||||||
|
},
|
||||||
|
"max_cost": {
|
||||||
|
"base": 21,
|
||||||
|
"per_level_above_first": 8
|
||||||
|
},
|
||||||
|
"anvil_cost": 4,
|
||||||
|
"slots": [
|
||||||
|
"mainhand"
|
||||||
|
],
|
||||||
|
"effects": {
|
||||||
|
"minecraft:damage": [
|
||||||
|
{
|
||||||
|
"effect": {
|
||||||
|
"type": "minecraft:add",
|
||||||
|
"value": {
|
||||||
|
"type": "minecraft:linear",
|
||||||
|
"base": 2.5,
|
||||||
|
"per_level_above_first": 2.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requirements": {
|
||||||
|
"condition": "minecraft:entity_properties",
|
||||||
|
"entity": "this",
|
||||||
|
"predicate": {
|
||||||
|
"type": "#minecraft:sensitive_to_impaling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
{
|
||||||
|
DataVersion: 3955,
|
||||||
|
size: [5, 5, 5],
|
||||||
|
data: [
|
||||||
|
{pos: [0, 0, 0], state: "minecraft:bedrock"},
|
||||||
|
{pos: [0, 0, 1], state: "minecraft:bedrock"},
|
||||||
|
{pos: [0, 0, 2], state: "minecraft:bedrock"},
|
||||||
|
{pos: [0, 0, 3], state: "minecraft:bedrock"},
|
||||||
|
{pos: [0, 0, 4], state: "minecraft:bedrock"},
|
||||||
|
{pos: [1, 0, 0], state: "minecraft:bedrock"},
|
||||||
|
{pos: [1, 0, 1], state: "minecraft:bedrock"},
|
||||||
|
{pos: [1, 0, 2], state: "minecraft:bedrock"},
|
||||||
|
{pos: [1, 0, 3], state: "minecraft:bedrock"},
|
||||||
|
{pos: [1, 0, 4], state: "minecraft:bedrock"},
|
||||||
|
{pos: [2, 0, 0], state: "minecraft:bedrock"},
|
||||||
|
{pos: [2, 0, 1], state: "minecraft:bedrock"},
|
||||||
|
{pos: [2, 0, 2], state: "minecraft:bedrock"},
|
||||||
|
{pos: [2, 0, 3], state: "minecraft:bedrock"},
|
||||||
|
{pos: [2, 0, 4], state: "minecraft:bedrock"},
|
||||||
|
{pos: [3, 0, 0], state: "minecraft:bedrock"},
|
||||||
|
{pos: [3, 0, 1], state: "minecraft:bedrock"},
|
||||||
|
{pos: [3, 0, 2], state: "minecraft:bedrock"},
|
||||||
|
{pos: [3, 0, 3], state: "minecraft:bedrock"},
|
||||||
|
{pos: [3, 0, 4], state: "minecraft:bedrock"},
|
||||||
|
{pos: [4, 0, 0], state: "minecraft:bedrock"},
|
||||||
|
{pos: [4, 0, 1], state: "minecraft:bedrock"},
|
||||||
|
{pos: [4, 0, 2], state: "minecraft:bedrock"},
|
||||||
|
{pos: [4, 0, 3], state: "minecraft:bedrock"},
|
||||||
|
{pos: [4, 0, 4], state: "minecraft:bedrock"},
|
||||||
|
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||||
|
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||||
|
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||||
|
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||||
|
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||||
|
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||||
|
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||||
|
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||||
|
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||||
|
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||||
|
{pos: [2, 1, 0], state: "minecraft:air"},
|
||||||
|
{pos: [2, 1, 1], state: "minecraft:air"},
|
||||||
|
{pos: [2, 1, 2], state: "minecraft:air"},
|
||||||
|
{pos: [2, 1, 3], state: "minecraft:air"},
|
||||||
|
{pos: [2, 1, 4], state: "minecraft:air"},
|
||||||
|
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||||
|
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||||
|
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||||
|
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||||
|
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||||
|
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||||
|
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||||
|
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||||
|
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||||
|
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||||
|
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||||
|
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||||
|
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||||
|
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||||
|
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||||
|
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||||
|
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||||
|
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||||
|
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||||
|
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||||
|
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||||
|
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||||
|
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||||
|
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||||
|
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||||
|
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||||
|
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||||
|
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||||
|
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||||
|
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||||
|
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||||
|
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||||
|
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||||
|
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||||
|
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||||
|
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||||
|
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||||
|
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||||
|
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||||
|
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||||
|
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||||
|
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||||
|
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||||
|
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||||
|
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||||
|
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||||
|
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||||
|
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||||
|
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||||
|
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||||
|
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||||
|
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||||
|
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||||
|
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||||
|
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||||
|
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||||
|
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||||
|
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||||
|
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||||
|
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||||
|
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||||
|
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||||
|
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||||
|
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||||
|
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||||
|
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||||
|
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||||
|
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||||
|
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||||
|
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||||
|
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||||
|
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||||
|
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||||
|
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||||
|
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||||
|
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||||
|
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||||
|
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||||
|
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||||
|
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||||
|
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||||
|
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||||
|
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||||
|
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||||
|
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||||
|
],
|
||||||
|
entities: [],
|
||||||
|
palette: [
|
||||||
|
"minecraft:bedrock",
|
||||||
|
"minecraft:air"
|
||||||
|
]
|
||||||
|
}
|
|
@ -13,13 +13,15 @@
|
||||||
"net.fabricmc.fabric.test.item.CustomDamageTest",
|
"net.fabricmc.fabric.test.item.CustomDamageTest",
|
||||||
"net.fabricmc.fabric.test.item.DefaultItemComponentTest",
|
"net.fabricmc.fabric.test.item.DefaultItemComponentTest",
|
||||||
"net.fabricmc.fabric.test.item.ItemUpdateAnimationTest",
|
"net.fabricmc.fabric.test.item.ItemUpdateAnimationTest",
|
||||||
"net.fabricmc.fabric.test.item.ArmorKnockbackResistanceTest"
|
"net.fabricmc.fabric.test.item.ArmorKnockbackResistanceTest",
|
||||||
|
"net.fabricmc.fabric.test.item.CustomEnchantmentEffectsTest"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"net.fabricmc.fabric.test.item.client.TooltipTests"
|
"net.fabricmc.fabric.test.item.client.TooltipTests"
|
||||||
],
|
],
|
||||||
"fabric-gametest" : [
|
"fabric-gametest" : [
|
||||||
"net.fabricmc.fabric.test.item.gametest.BrewingStandGameTest",
|
"net.fabricmc.fabric.test.item.gametest.BrewingStandGameTest",
|
||||||
|
"net.fabricmc.fabric.test.item.gametest.CustomEnchantmentEffectsGameTest",
|
||||||
"net.fabricmc.fabric.test.item.gametest.DefaultItemComponentGameTest",
|
"net.fabricmc.fabric.test.item.gametest.DefaultItemComponentGameTest",
|
||||||
"net.fabricmc.fabric.test.item.gametest.FurnaceGameTest",
|
"net.fabricmc.fabric.test.item.gametest.FurnaceGameTest",
|
||||||
"net.fabricmc.fabric.test.item.gametest.RecipeGameTest"
|
"net.fabricmc.fabric.test.item.gametest.RecipeGameTest"
|
||||||
|
|
Loading…
Reference in a new issue