24w36a (#4068)
Some checks failed
Build / build (21-ubuntu) (push) Has been cancelled
Build / client_test (push) Has been cancelled
Build / server_test (push) Has been cancelled
Build / check_resources (push) Has been cancelled

* 24w36a

* Some fixes

* More work

* Fixes

* Update yarn

* Update fabric loader

* Bump versions
This commit is contained in:
modmuss 2024-09-05 11:42:30 +01:00 committed by GitHub
parent 2ade441e60
commit d48ec150ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
127 changed files with 493 additions and 943 deletions

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-command-api-v2": "*" "fabric-command-api-v2": "*"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-command-api-v2": "*" "fabric-command-api-v2": "*"
}, },

View file

@ -21,7 +21,7 @@
] ]
}, },
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.18.2" "minecraft": ">=1.18.2"
}, },
"description": "Contains common tags used by mods for vanilla things.", "description": "Contains common tags used by mods for vanilla things.",

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-key-binding-api-v1": "*" "fabric-key-binding-api-v1": "*"
}, },
"description": "Keybinding registry API.", "description": "Keybinding registry API.",

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-resource-loader-v0": "*" "fabric-resource-loader-v0": "*"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-block-view-api-v2": "*" "fabric-block-view-api-v2": "*"
}, },
"description": "Thread-safe hooks for block entity data use during terrain rendering.", "description": "Thread-safe hooks for block entity data use during terrain rendering.",

View file

@ -21,7 +21,7 @@
] ]
}, },
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.15-alpha.19.39.a", "minecraft": ">=1.15-alpha.19.39.a",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-rendering-v1": "*" "fabric-rendering-v1": "*"

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Contains the essentials for Fabric API modules.", "description": "Contains the essentials for Fabric API modules.",
"custom": { "custom": {

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-lifecycle-events-v1": "*" "fabric-lifecycle-events-v1": "*"
}, },

View file

@ -46,19 +46,19 @@ public class FabricApiLookupTest implements ModInitializer {
// It's meant to work with unsided containers: chests, dispensers, droppers and hoppers. // It's meant to work with unsided containers: chests, dispensers, droppers and hoppers.
public static final RegistryKey<Block> CHUTE_BLOCK_KEY = keyOf("chute"); public static final RegistryKey<Block> CHUTE_BLOCK_KEY = keyOf("chute");
public static final ChuteBlock CHUTE_BLOCK = new ChuteBlock(AbstractBlock.Settings.create().registryKey(CHUTE_BLOCK_KEY)); public static final ChuteBlock CHUTE_BLOCK = new ChuteBlock(AbstractBlock.Settings.create().registryKey(CHUTE_BLOCK_KEY));
public static final BlockItem CHUTE_ITEM = new BlockItem(CHUTE_BLOCK, new Item.Settings()); public static final BlockItem CHUTE_ITEM = new BlockItem(CHUTE_BLOCK, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, CHUTE_BLOCK_KEY.getValue())));
public static BlockEntityType<ChuteBlockEntity> CHUTE_BLOCK_ENTITY_TYPE; public static BlockEntityType<ChuteBlockEntity> CHUTE_BLOCK_ENTITY_TYPE;
// Cobble gen - Block without model that can generate infinite cobblestone when placed above a chute. // Cobble gen - Block without model that can generate infinite cobblestone when placed above a chute.
// It's meant to test BlockApiLookup#registerSelf. // It's meant to test BlockApiLookup#registerSelf.
public static final RegistryKey<Block> COBBLE_GEN_BLOCK_KEY = keyOf("cobble_gen"); public static final RegistryKey<Block> COBBLE_GEN_BLOCK_KEY = keyOf("cobble_gen");
public static final CobbleGenBlock COBBLE_GEN_BLOCK = new CobbleGenBlock(AbstractBlock.Settings.create().registryKey(COBBLE_GEN_BLOCK_KEY)); public static final CobbleGenBlock COBBLE_GEN_BLOCK = new CobbleGenBlock(AbstractBlock.Settings.create().registryKey(COBBLE_GEN_BLOCK_KEY));
public static final BlockItem COBBLE_GEN_ITEM = new BlockItem(COBBLE_GEN_BLOCK, new Item.Settings()); public static final BlockItem COBBLE_GEN_ITEM = new BlockItem(COBBLE_GEN_BLOCK, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, COBBLE_GEN_BLOCK_KEY.getValue())));
public static BlockEntityType<CobbleGenBlockEntity> COBBLE_GEN_BLOCK_ENTITY_TYPE; public static BlockEntityType<CobbleGenBlockEntity> COBBLE_GEN_BLOCK_ENTITY_TYPE;
// Testing for item api lookups is done in the `item` package. // Testing for item api lookups is done in the `item` package.
public static final RegistryKey<Block> INSPECTOR_BLOCK_KEY = keyOf("inspector"); public static final RegistryKey<Block> INSPECTOR_BLOCK_KEY = keyOf("inspector");
public static final InspectorBlock INSPECTOR_BLOCK = new InspectorBlock(AbstractBlock.Settings.create().registryKey(INSPECTOR_BLOCK_KEY)); public static final InspectorBlock INSPECTOR_BLOCK = new InspectorBlock(AbstractBlock.Settings.create().registryKey(INSPECTOR_BLOCK_KEY));
public static final BlockItem INSPECTOR_ITEM = new BlockItem(INSPECTOR_BLOCK, new Item.Settings()); public static final BlockItem INSPECTOR_ITEM = new BlockItem(INSPECTOR_BLOCK, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, INSPECTOR_BLOCK_KEY.getValue())));
private static RegistryKey<Block> keyOf(String id) { private static RegistryKey<Block> keyOf(String id) {
return RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, id)); return RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(MOD_ID, id));

View file

@ -19,9 +19,12 @@ package net.fabricmc.fabric.test.lookup.item;
import static net.fabricmc.fabric.test.lookup.FabricApiLookupTest.ensureException; import static net.fabricmc.fabric.test.lookup.FabricApiLookupTest.ensureException;
import net.minecraft.component.DataComponentTypes; import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.Item;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -33,10 +36,11 @@ public class FabricItemApiLookupTest {
public static final ItemApiLookup<Inspectable, Void> INSPECTABLE = public static final ItemApiLookup<Inspectable, Void> INSPECTABLE =
ItemApiLookup.get(Identifier.of("testmod", "inspectable"), Inspectable.class, Void.class); ItemApiLookup.get(Identifier.of("testmod", "inspectable"), Inspectable.class, Void.class);
public static final InspectableItem HELLO_ITEM = new InspectableItem("Hello Fabric API tester!"); public static final RegistryKey<Item> HELLO_ITEM_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of(FabricApiLookupTest.MOD_ID, "hello"));
public static final InspectableItem HELLO_ITEM = new InspectableItem("Hello Fabric API tester!", new Item.Settings().registryKey(HELLO_ITEM_KEY));
public static void onInitialize() { public static void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of(FabricApiLookupTest.MOD_ID, "hello"), HELLO_ITEM); Registry.register(Registries.ITEM, HELLO_ITEM_KEY, HELLO_ITEM);
// Diamonds and diamond blocks can be inspected and will also print their name. // Diamonds and diamond blocks can be inspected and will also print their name.
INSPECTABLE.registerForItems((stack, ignored) -> () -> { INSPECTABLE.registerForItems((stack, ignored) -> () -> {

View file

@ -24,8 +24,8 @@ import net.fabricmc.fabric.test.lookup.api.Inspectable;
public class InspectableItem extends Item implements Inspectable { public class InspectableItem extends Item implements Inspectable {
private final String inspectionResult; private final String inspectionResult;
public InspectableItem(String inspectionResult) { public InspectableItem(String inspectionResult, Item.Settings settings) {
super(new Settings()); super(settings);
this.inspectionResult = inspectionResult; this.inspectionResult = inspectionResult;
} }

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.16.2" "minecraft": ">=1.16.2"
}, },
"description": "Hooks for adding biomes to the default world generator.", "description": "Hooks for adding biomes to the default world generator.",

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"entrypoints": { "entrypoints": {
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Hooks for block views", "description": "Hooks for block views",
"mixins": [ "mixins": [

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.15-alpha.19.38.b", "minecraft": ">=1.15-alpha.19.38.b",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Adds the ability to load tags from the local mods.", "description": "Adds the ability to load tags from the local mods.",
"custom": { "custom": {

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"minecraft": ">1.19-alpha.22.11.a" "minecraft": ">1.19-alpha.22.11.a"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-lifecycle-events-v1": "*", "fabric-lifecycle-events-v1": "*",
"fabric-resource-loader-v0": "*" "fabric-resource-loader-v0": "*"

View file

@ -150,9 +150,9 @@ public final class ContentRegistryTest implements ModInitializer {
LOGGER.info("SculkSensorFrequencyRegistry test passed!"); LOGGER.info("SculkSensorFrequencyRegistry test passed!");
} }
var dirtyPotion = new DirtyPotionItem(new Item.Settings().maxCount(1)); RegistryKey<Item> dirtyPotionKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-content-registries-v0-testmod", "dirty_potion"));
Registry.register(Registries.ITEM, Identifier.of("fabric-content-registries-v0-testmod", "dirty_potion"), var dirtyPotion = new DirtyPotionItem(new Item.Settings().maxCount(1).registryKey(dirtyPotionKey));
dirtyPotion); Registry.register(Registries.ITEM, dirtyPotionKey, dirtyPotion);
/* Mods should use BrewingRecipeRegistry.registerPotionType(Item), which is access widened by fabric-transitive-access-wideners-v1 /* Mods should use BrewingRecipeRegistry.registerPotionType(Item), which is access widened by fabric-transitive-access-wideners-v1
* This testmod uses an accessor due to Loom limitations that prevent TAWs from applying across Gradle subproject boundaries */ * This testmod uses an accessor due to Loom limitations that prevent TAWs from applying across Gradle subproject boundaries */
FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> { FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> {

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.18.2" "minecraft": ">=1.18.2"
}, },
"description": "Contains common tags used by mods for vanilla things.", "description": "Contains common tags used by mods for vanilla things.",

View file

@ -21,7 +21,7 @@
] ]
}, },
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.20.5-beta.1", "minecraft": ">=1.20.5-beta.1",
"fabric-lifecycle-events-v1": "*" "fabric-lifecycle-events-v1": "*"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Adds Fabric-related debug info to crash reports.", "description": "Adds Fabric-related debug info to crash reports.",
"mixins": [ "mixins": [

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-entity-events-v1": "*", "fabric-entity-events-v1": "*",
"fabric-object-builder-api-v1": "*" "fabric-object-builder-api-v1": "*"
}, },

View file

@ -16,19 +16,22 @@
package net.fabricmc.fabric.test.attachment.gametest; package net.fabricmc.fabric.test.attachment.gametest;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnReason; import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.DrownedEntity;
import net.minecraft.entity.mob.ZombieEntity;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.test.GameTest; import net.minecraft.test.GameTest;
import net.minecraft.test.GameTestException; import net.minecraft.test.GameTestException;
import net.minecraft.test.TestContext; import net.minecraft.test.TestContext;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.TeleportTarget; import net.minecraft.world.TeleportTarget;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -36,6 +39,7 @@ import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry;
import net.fabricmc.fabric.api.attachment.v1.AttachmentType; import net.fabricmc.fabric.api.attachment.v1.AttachmentType;
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest; import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
import net.fabricmc.fabric.test.attachment.AttachmentTestMod; import net.fabricmc.fabric.test.attachment.AttachmentTestMod;
import net.fabricmc.fabric.test.attachment.mixin.ZombieEntityAccessor;
public class AttachmentCopyTests implements FabricGameTest { public class AttachmentCopyTests implements FabricGameTest {
// using a lambda type because serialization shouldn't play a role in this // using a lambda type because serialization shouldn't play a role in this
@ -74,10 +78,19 @@ public class AttachmentCopyTests implements FabricGameTest {
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
public void testMobConversion(TestContext context) { public void testMobConversion(TestContext context) {
MobEntity mob = Objects.requireNonNull(EntityType.ZOMBIE.create(context.getWorld(), SpawnReason.SPAWN_EGG)); ZombieEntity mob = context.spawnEntity(EntityType.ZOMBIE, BlockPos.ORIGIN);
mob.setAttached(DUMMY, () -> 42); mob.setAttached(DUMMY, () -> 42);
mob.setAttached(COPY_ON_DEATH, () -> 42); mob.setAttached(COPY_ON_DEATH, () -> 42);
MobEntity converted = mob.convertTo(EntityType.DROWNED, false);
ZombieEntityAccessor zombieEntityAccessor = (ZombieEntityAccessor) mob;
zombieEntityAccessor.invokeConvertTo(EntityType.DROWNED);
List<DrownedEntity> drowned = context.getEntities(EntityType.DROWNED);
if (drowned.size() != 1) {
throw new GameTestException("Conversion failed");
}
DrownedEntity converted = drowned.getFirst();
if (converted == null) throw new GameTestException("Conversion failed"); if (converted == null) throw new GameTestException("Conversion failed");
if (converted.hasAttached(DUMMY)) { if (converted.hasAttached(DUMMY)) {

View file

@ -14,15 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package net.fabricmc.fabric.test.entity.event; package net.fabricmc.fabric.test.attachment.mixin;
import net.minecraft.item.ArmorItem; import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.item.ArmorMaterials; import org.spongepowered.asm.mixin.gen.Invoker;
import net.fabricmc.fabric.api.entity.event.v1.FabricElytraItem; import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.ZombieEntity;
public class DiamondElytraItem extends ArmorItem implements FabricElytraItem { @Mixin(ZombieEntity.class)
public DiamondElytraItem() { public interface ZombieEntityAccessor {
super(ArmorMaterials.DIAMOND, Type.CHESTPLATE, new Settings().maxCount(1).maxDamage(100)); @Invoker("convertTo")
} void invokeConvertTo(EntityType<? extends ZombieEntity> entityType);
} }

View file

@ -3,7 +3,8 @@
"package": "net.fabricmc.fabric.test.attachment.mixin", "package": "net.fabricmc.fabric.test.attachment.mixin",
"compatibilityLevel": "JAVA_21", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
"BlockEntityTypeAccessor" "BlockEntityTypeAccessor",
"ZombieEntityAccessor"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View file

@ -317,8 +317,8 @@ transitive-accessible method net/minecraft/data/client/ItemModelGenerator regist
transitive-accessible method net/minecraft/data/client/ItemModelGenerator uploadArmor (Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)V transitive-accessible method net/minecraft/data/client/ItemModelGenerator uploadArmor (Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)V
transitive-accessible method net/minecraft/data/client/ItemModelGenerator uploadArmor (Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)V transitive-accessible method net/minecraft/data/client/ItemModelGenerator uploadArmor (Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;Lnet/minecraft/util/Identifier;)V
transitive-accessible method net/minecraft/data/client/ItemModelGenerator suffixTrim (Lnet/minecraft/util/Identifier;Ljava/lang/String;)Lnet/minecraft/util/Identifier; transitive-accessible method net/minecraft/data/client/ItemModelGenerator suffixTrim (Lnet/minecraft/util/Identifier;Ljava/lang/String;)Lnet/minecraft/util/Identifier;
transitive-accessible method net/minecraft/data/client/ItemModelGenerator createArmorJson (Lnet/minecraft/util/Identifier;Ljava/util/Map;Lnet/minecraft/registry/entry/RegistryEntry;)Lcom/google/gson/JsonObject; transitive-accessible method net/minecraft/data/client/ItemModelGenerator createArmorJson (Lnet/minecraft/util/Identifier;Ljava/util/Map;Lnet/minecraft/util/Identifier;)Lcom/google/gson/JsonObject;
transitive-accessible method net/minecraft/data/client/ItemModelGenerator registerArmor (Lnet/minecraft/item/ArmorItem;)V transitive-accessible method net/minecraft/data/client/ItemModelGenerator registerArmor (Lnet/minecraft/item/Item;Lnet/minecraft/util/Identifier;Lnet/minecraft/item/equipment/EquipmentModel;Lnet/minecraft/entity/EquipmentSlot;)V
transitive-extendable method net/minecraft/data/MetadataProvider getName ()Ljava/lang/String; transitive-extendable method net/minecraft/data/MetadataProvider getName ()Ljava/lang/String;
transitive-extendable method net/minecraft/data/SnbtProvider getName ()Ljava/lang/String; transitive-extendable method net/minecraft/data/SnbtProvider getName ()Ljava/lang/String;
transitive-extendable method net/minecraft/data/client/ModelProvider getName ()Ljava/lang/String; transitive-extendable method net/minecraft/data/client/ModelProvider getName ()Ljava/lang/String;

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Allows for automatic data generation.", "description": "Allows for automatic data generation.",
"mixins": [ "mixins": [

View file

@ -88,7 +88,7 @@ public class DataGeneratorTestContent implements ModInitializer {
Block block = Registry.register(Registries.BLOCK, identifier, new Block(settings.registryKey(RegistryKey.of(RegistryKeys.BLOCK, identifier)))); Block block = Registry.register(Registries.BLOCK, identifier, new Block(settings.registryKey(RegistryKey.of(RegistryKeys.BLOCK, identifier))));
if (hasItem) { if (hasItem) {
Registry.register(Registries.ITEM, identifier, new BlockItem(block, new Item.Settings())); Registry.register(Registries.ITEM, identifier, new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, identifier))));
} }
return block; return block;

View file

@ -15,7 +15,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.16-rc.3", "minecraft": ">=1.16-rc.3",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },

View file

@ -1,57 +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.mixin.client.entity.event.elytra;
import com.mojang.authlib.GameProfile;
import org.spongepowered.asm.mixin.Final;
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.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket;
@SuppressWarnings("unused")
@Mixin(ClientPlayerEntity.class)
abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
super(world, profile);
throw new AssertionError();
}
@Shadow
@Final
private ClientPlayNetworkHandler networkHandler;
/**
* Call {@link #checkFallFlying()} even if the player is not wearing {@link Items#ELYTRA} to allow custom elytra flight.
*/
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/entity/EquipmentSlot;CHEST:Lnet/minecraft/entity/EquipmentSlot;"), method = "tickMovement", slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isClimbing()Z"), to = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;checkFallFlying()Z")), allow = 1)
void injectElytraStart(CallbackInfo info) {
// Note that if fall flying is not ALLOWed, checkFallFlying will return false and nothing will happen.
if (this.checkFallFlying()) {
networkHandler.sendPacket(new ClientCommandC2SPacket(this, ClientCommandC2SPacket.Mode.START_FALL_FLYING));
}
}
}

View file

@ -1,12 +0,0 @@
{
"required": true,
"package": "net.fabricmc.fabric.mixin.client.entity.event",
"compatibilityLevel": "JAVA_21",
"client": [
"elytra.ClientPlayerEntityMixin"
],
"injectors": {
"defaultRequire": 1,
"maxShiftBy": 3
}
}

View file

@ -16,9 +16,8 @@
package net.fabricmc.fabric.api.entity.event.v1; package net.fabricmc.fabric.api.entity.event.v1;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.event.EventFactory;
@ -45,7 +44,7 @@ public final class EntityElytraEvents {
* An event to grant elytra flight to living entities when some condition is met. * An event to grant elytra flight to living entities when some condition is met.
* Will be called when players try to start elytra flight by pressing space in mid-air, and every tick for all flying living entities to check if elytra flight is still allowed. * Will be called when players try to start elytra flight by pressing space in mid-air, and every tick for all flying living entities to check if elytra flight is still allowed.
* *
* <p>Items that wish to enable custom elytra flight when worn in the chest equipment slot can simply implement {@link FabricElytraItem} instead of registering a listener. * <p>Items that wish to enable custom elytra flight when worn in the chest equipment slot can add the {@link DataComponentTypes#GLIDER} component to an item.
*/ */
public static final Event<Custom> CUSTOM = EventFactory.createArrayBacked(Custom.class, listeners -> (entity, tickElytra) -> { public static final Event<Custom> CUSTOM = EventFactory.createArrayBacked(Custom.class, listeners -> (entity, tickElytra) -> {
for (Custom listener : listeners) { for (Custom listener : listeners) {
@ -57,18 +56,6 @@ public final class EntityElytraEvents {
return false; return false;
}); });
static {
CUSTOM.register((entity, tickElytra) -> {
ItemStack chestStack = entity.getEquippedStack(EquipmentSlot.CHEST);
if (chestStack.getItem() instanceof FabricElytraItem fabricElytraItem) {
return fabricElytraItem.useCustomElytra(entity, chestStack, tickElytra);
}
return false;
});
}
@FunctionalInterface @FunctionalInterface
public interface Allow { public interface Allow {
/** /**

View file

@ -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.api.entity.event.v1;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ElytraItem;
import net.minecraft.item.ItemStack;
import net.minecraft.world.event.GameEvent;
/**
* An interface that can be implemented on an item to provide custom elytra flight when it is worn in the {@link EquipmentSlot#CHEST} slot.
*
* <p>To disable cape rendering when this item is worn (like the vanilla elytra item), have a look at {@code LivingEntityFeatureRenderEvents}.
*/
public interface FabricElytraItem {
/**
* Try to use this custom elytra.
*
* @param entity the entity
* @param chestStack the stack currently worn in the chest slot, will always be of this item
* @param tickElytra true to tick the elytra, false to only perform the check; vanilla-like elytras can use {@link #doVanillaElytraTick} to handle ticking
* @return true to enable elytra flight for the entity
*/
default boolean useCustomElytra(LivingEntity entity, ItemStack chestStack, boolean tickElytra) {
if (ElytraItem.isUsable(chestStack)) {
if (tickElytra) {
doVanillaElytraTick(entity, chestStack);
}
return true;
}
return false;
}
/**
* A helper to perform the default vanilla elytra tick logic: damage the elytra every 20 ticks, and send a game event every 10 ticks.
*/
default void doVanillaElytraTick(LivingEntity entity, ItemStack chestStack) {
int nextRoll = entity.getFallFlyingTicks() + 1;
if (!entity.getWorld().isClient && nextRoll % 10 == 0) {
if ((nextRoll / 10) % 2 == 0) {
chestStack.damage(1, entity, EquipmentSlot.CHEST);
}
entity.emitGameEvent(GameEvent.ELYTRA_GLIDE);
}
}
}

View file

@ -17,6 +17,7 @@
package net.fabricmc.fabric.api.entity.event.v1; package net.fabricmc.fabric.api.entity.event.v1;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.conversion.EntityConversionContext;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
@ -166,9 +167,9 @@ public final class ServerLivingEntityEvents {
* *
* @param previous the previous entity instance * @param previous the previous entity instance
* @param converted the new instance for the converted entity * @param converted the new instance for the converted entity
* @param keepEquipment whether the converted entity should keep the previous one's equipment, like armor * @param conversionContext the context used for the conversion
*/ */
void onConversion(MobEntity previous, MobEntity converted, boolean keepEquipment); void onConversion(MobEntity previous, MobEntity converted, EntityConversionContext conversionContext);
} }
private ServerLivingEntityEvents() { private ServerLivingEntityEvents() {

View file

@ -22,15 +22,16 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.conversion.EntityConversionContext;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents; import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
@Mixin(MobEntity.class) @Mixin(MobEntity.class)
public class MobEntityMixin { public class MobEntityMixin {
@ModifyArg(method = "convertTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z")) @ModifyArg(method = "convertTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntityAndPassengers(Lnet/minecraft/entity/Entity;)V"))
private Entity afterEntityConverted(Entity converted, @Local(argsOnly = true) boolean keepEquipment) { private Entity afterEntityConverted(Entity converted, @Local(argsOnly = true) EntityConversionContext conversionContext) {
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion((MobEntity) (Object) this, (MobEntity) converted, keepEquipment); ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion((MobEntity) (Object) this, (MobEntity) converted, conversionContext);
return converted; return converted;
} }
} }

View file

@ -1,39 +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.mixin.entity.event;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.MooshroomEntity;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
@Mixin(MooshroomEntity.class)
class MooshroomEntityMixin {
@ModifyArg(
method = "sheared",
at = @At(ordinal = 0, value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z")
)
private Entity afterMooshroomConversion(Entity converted) {
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion((MooshroomEntity) (Object) this, (MobEntity) converted, false);
return converted;
}
}

View file

@ -1,46 +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.mixin.entity.event;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.passive.PigEntity;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
@Mixin(PigEntity.class)
abstract class PigEntityMixin extends AnimalEntity {
protected PigEntityMixin(EntityType<? extends AnimalEntity> entityType, World world) {
super(entityType, world);
}
@ModifyArg(
method = "onStruckByLightning",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntity(Lnet/minecraft/entity/Entity;)Z")
)
private Entity afterPiglinConversion(Entity converted) {
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
return converted;
}
}

View file

@ -1,46 +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.mixin.entity.event;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.FishEntity;
import net.minecraft.entity.passive.TadpoleEntity;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
@Mixin(TadpoleEntity.class)
abstract class TadpoleEntityMixin extends FishEntity {
TadpoleEntityMixin(EntityType<? extends FishEntity> entityType, World world) {
super(entityType, world);
}
@ModifyArg(
method = "growUp",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntityAndPassengers(Lnet/minecraft/entity/Entity;)V")
)
private Entity afterGrowingUpToFrog(Entity converted) {
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
return converted;
}
}

View file

@ -1,46 +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.mixin.entity.event;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.passive.MerchantEntity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
@Mixin(VillagerEntity.class)
abstract class VillagerEntityMixin extends MerchantEntity {
VillagerEntityMixin(EntityType<? extends MerchantEntity> entityType, World world) {
super(entityType, world);
}
@ModifyArg(
method = "onStruckByLightning",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;spawnEntityAndPassengers(Lnet/minecraft/entity/Entity;)V")
)
private Entity afterWitchConversion(Entity converted) {
ServerLivingEntityEvents.MOB_CONVERSION.invoker().onConversion(this, (MobEntity) converted, false);
return converted;
}
}

View file

@ -1,44 +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.mixin.entity.event.elytra;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.ElytraFlightController;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.fabricmc.fabric.api.entity.event.v1.EntityElytraEvents;
@Mixin(ElytraFlightController.class)
public class ElytraFlightControllerMixin {
@Shadow
@Final
private LivingEntity entity;
@WrapOperation(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z"))
private boolean checkAllowEvent(ItemStack instance, Item item, Operation<Boolean> original) {
// ALLOW event is checked by LivingEntityMixin.
return original.call(instance, item) || EntityElytraEvents.CUSTOM.invoker().useCustomElytra(this.entity, false);
}
}

View file

@ -20,10 +20,12 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.fabricmc.fabric.api.entity.event.v1.EntityElytraEvents; import net.fabricmc.fabric.api.entity.event.v1.EntityElytraEvents;
@ -40,14 +42,14 @@ abstract class LivingEntityMixin extends Entity {
* Handle ALLOW and CUSTOM {@link EntityElytraEvents} when an entity is fall flying. * Handle ALLOW and CUSTOM {@link EntityElytraEvents} when an entity is fall flying.
*/ */
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getEquippedStack(Lnet/minecraft/entity/EquipmentSlot;)Lnet/minecraft/item/ItemStack;"), method = "tickFallFlying()V", allow = 1, cancellable = true) @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getEquippedStack(Lnet/minecraft/entity/EquipmentSlot;)Lnet/minecraft/item/ItemStack;"), method = "tickGliding()V", allow = 1, cancellable = true)
void injectElytraTick(CallbackInfo info) { void injectElytraTick(CallbackInfo info) {
LivingEntity self = (LivingEntity) (Object) this; LivingEntity self = (LivingEntity) (Object) this;
if (!EntityElytraEvents.ALLOW.invoker().allowElytraFlight(self)) { if (!EntityElytraEvents.ALLOW.invoker().allowElytraFlight(self)) {
// The entity is already fall flying by now, we just need to stop it. // The entity is already fall flying by now, we just need to stop it.
if (!getWorld().isClient) { if (!getWorld().isClient) {
setFlag(Entity.FALL_FLYING_FLAG_INDEX, false); setFlag(Entity.GLIDING_FLAG_INDEX, false);
} }
info.cancel(); info.cancel();
@ -58,4 +60,19 @@ abstract class LivingEntityMixin extends Entity {
info.cancel(); info.cancel();
} }
} }
@SuppressWarnings("ConstantConditions")
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/entity/EquipmentSlot;VALUES:Ljava/util/List;"), method = "canGlide", allow = 1, cancellable = true)
void injectElytraCheck(CallbackInfoReturnable<Boolean> cir) {
PlayerEntity self = (PlayerEntity) (Object) this;
if (!EntityElytraEvents.ALLOW.invoker().allowElytraFlight(self)) {
cir.setReturnValue(false);
return; // Return to prevent the rest of this injector from running.
}
if (EntityElytraEvents.CUSTOM.invoker().useCustomElytra(self, false)) {
cir.setReturnValue(true);
}
}
} }

View file

@ -1,62 +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.mixin.entity.event.elytra;
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.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.entity.event.v1.EntityElytraEvents;
@SuppressWarnings("unused")
@Mixin(PlayerEntity.class)
abstract class PlayerEntityMixin extends LivingEntity {
PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
throw new AssertionError();
}
@Shadow
public abstract void startFallFlying();
/**
* Allow the server-side and client-side elytra checks to fail when {@link EntityElytraEvents#ALLOW} blocks flight,
* and otherwise to succeed for elytra flight through {@link EntityElytraEvents#CUSTOM}.
*/
@SuppressWarnings("ConstantConditions")
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/entity/EquipmentSlot;CHEST:Lnet/minecraft/entity/EquipmentSlot;"), method = "checkFallFlying()Z", allow = 1, cancellable = true)
void injectElytraCheck(CallbackInfoReturnable<Boolean> cir) {
PlayerEntity self = (PlayerEntity) (Object) this;
if (!EntityElytraEvents.ALLOW.invoker().allowElytraFlight(self)) {
cir.setReturnValue(false);
return; // Return to prevent the rest of this injector from running.
}
if (EntityElytraEvents.CUSTOM.invoker().useCustomElytra(self, false)) {
startFallFlying();
cir.setReturnValue(true);
}
}
}

View file

@ -6,16 +6,10 @@
"EntityMixin", "EntityMixin",
"LivingEntityMixin", "LivingEntityMixin",
"MobEntityMixin", "MobEntityMixin",
"MooshroomEntityMixin",
"PigEntityMixin",
"PlayerEntityMixin", "PlayerEntityMixin",
"PlayerManagerMixin", "PlayerManagerMixin",
"ServerPlayerEntityMixin", "ServerPlayerEntityMixin",
"TadpoleEntityMixin", "elytra.LivingEntityMixin"
"VillagerEntityMixin",
"elytra.ElytraFlightControllerMixin",
"elytra.LivingEntityMixin",
"elytra.PlayerEntityMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1, "defaultRequire": 1,

View file

@ -16,15 +16,11 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Events to hook into entities.", "description": "Events to hook into entities.",
"mixins": [ "mixins": [
"fabric-entity-events-v1.mixins.json", "fabric-entity-events-v1.mixins.json"
{
"config": "fabric-entity-events-v1.client.mixins.json",
"environment": "client"
}
], ],
"custom": { "custom": {
"fabric-api:module-lifecycle": "stable" "fabric-api:module-lifecycle": "stable"

View file

@ -23,6 +23,7 @@ import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.component.DataComponentTypes; import net.minecraft.component.DataComponentTypes;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.damage.DamageTypes; import net.minecraft.entity.damage.DamageTypes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
@ -30,15 +31,18 @@ import net.minecraft.item.BlockItem;
import net.minecraft.item.Item; 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.item.equipment.EquipmentModels;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.CommandManager;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Unit;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -58,13 +62,14 @@ public final class EntityEventTests implements ModInitializer {
Identifier.of("fabric-entity-events-v1-testmod", "test_bed") Identifier.of("fabric-entity-events-v1-testmod", "test_bed")
); );
public static final Block TEST_BED = new TestBedBlock(AbstractBlock.Settings.create().strength(1, 1).registryKey(TEST_BED_KEY)); public static final Block TEST_BED = new TestBedBlock(AbstractBlock.Settings.create().strength(1, 1).registryKey(TEST_BED_KEY));
public static final Item DIAMOND_ELYTRA = new DiamondElytraItem(); public static final RegistryKey<Item> DIAMOND_ELYTRA_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-entity-events-v1-testmod", "diamond_elytra"));
public static final Item DIAMOND_ELYTRA = new Item(new Item.Settings().component(DataComponentTypes.GLIDER, Unit.INSTANCE).equippable(EquipmentSlot.CHEST, SoundEvents.ITEM_ARMOR_EQUIP_ELYTRA, EquipmentModels.ELYTRA).registryKey(DIAMOND_ELYTRA_KEY));
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.BLOCK, TEST_BED_KEY, TEST_BED); Registry.register(Registries.BLOCK, TEST_BED_KEY, TEST_BED);
Registry.register(Registries.ITEM, TEST_BED_KEY.getValue(), new BlockItem(TEST_BED, new Item.Settings())); Registry.register(Registries.ITEM, TEST_BED_KEY.getValue(), new BlockItem(TEST_BED, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, TEST_BED_KEY.getValue()))));
Registry.register(Registries.ITEM, Identifier.of("fabric-entity-events-v1-testmod", "diamond_elytra"), DIAMOND_ELYTRA); Registry.register(Registries.ITEM, DIAMOND_ELYTRA_KEY, DIAMOND_ELYTRA);
ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register((world, entity, killed) -> { ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register((world, entity, killed) -> {
LOGGER.info("Entity {} Killed: {}", entity, killed); LOGGER.info("Entity {} Killed: {}", entity, killed);

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-networking-api-v1": "*", "fabric-networking-api-v1": "*",
"minecraft": ">=1.15-alpha.19.37.a" "minecraft": ">=1.15-alpha.19.37.a"

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Allows registration of custom game rules.", "description": "Allows registration of custom game rules.",
"mixins": [ "mixins": [

View file

@ -21,7 +21,7 @@
] ]
}, },
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-resource-loader-v0": "*" "fabric-resource-loader-v0": "*"
}, },
"description": "Allows registration of custom game tests.", "description": "Allows registration of custom game tests.",

View file

@ -23,7 +23,7 @@
} }
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Hooks for items", "description": "Hooks for items",

View file

@ -16,45 +16,47 @@
package net.fabricmc.fabric.test.item; package net.fabricmc.fabric.test.item;
import java.util.EnumMap; import java.util.Map;
import java.util.List;
import net.minecraft.item.ArmorItem; import net.minecraft.item.ArmorItem;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.Items; import net.minecraft.item.equipment.ArmorMaterial;
import net.minecraft.item.equipment.EquipmentType;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class ArmorKnockbackResistanceTest implements ModInitializer { public class ArmorKnockbackResistanceTest implements ModInitializer {
private static final RegistryEntry<ArmorMaterial> WOOD_ARMOR = Registry.registerReference(Registries.ARMOR_MATERIAL, Identifier.of("fabric-item-api-v1-testmod", "wood"), createTestArmorMaterial()); private static final ArmorMaterial WOOD_ARMOR = createTestArmorMaterial();
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of("fabric-item-api-v1-testmod", RegistryKey<Item> registryKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-item-api-v1-testmod", "wooden_boots"));
"wooden_boots"), new ArmorItem(WOOD_ARMOR, ArmorItem.Type.BOOTS, new Item.Settings())); Registry.register(Registries.ITEM, registryKey, new ArmorItem(WOOD_ARMOR, EquipmentType.BOOTS, new Item.Settings().registryKey(registryKey)));
} }
private static ArmorMaterial createTestArmorMaterial() { private static ArmorMaterial createTestArmorMaterial() {
return new ArmorMaterial( return new ArmorMaterial(
Util.make(new EnumMap<>(ArmorItem.Type.class), (map) -> {
map.put(ArmorItem.Type.BOOTS, 1);
map.put(ArmorItem.Type.LEGGINGS, 2);
map.put(ArmorItem.Type.CHESTPLATE, 3);
map.put(ArmorItem.Type.HELMET, 1);
map.put(ArmorItem.Type.BODY, 3);
}),
SoundEvents.ITEM_ARMOR_EQUIP_LEATHER,
(stack) -> stack.getItem() == Items.LEATHER,
List.of(new ArmorMaterial.Layer(Identifier.of("fabric-item-api-v1-testmod", "wood"))),
0, 0,
0.5F Map.of(
EquipmentType.BOOTS, 1,
EquipmentType.LEGGINGS, 2,
EquipmentType.CHESTPLATE, 3,
EquipmentType.HELMET, 1,
EquipmentType.BODY, 3
),
1,
SoundEvents.ITEM_ARMOR_EQUIP_LEATHER,
0,
0.5F,
ItemTags.REPAIRS_LEATHER_ARMOR,
Identifier.of("fabric-item-api-v1-testmod", "wood")
); );
} }
} }

View file

@ -29,6 +29,8 @@ import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.potion.Potions; import net.minecraft.potion.Potions;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.tag.EnchantmentTags; import net.minecraft.registry.tag.EnchantmentTags;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@ -55,11 +57,12 @@ public class CustomDamageTest implements ModInitializer {
} }
}; };
// Do this static init *after* the damage handler otherwise it's still null while inside the constructor // Do this static init *after* the damage handler otherwise it's still null while inside the constructor
public static final Item WEIRD_PICK = new WeirdPick(); public static final RegistryKey<Item> WEIRD_PICK_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-item-api-v1-testmod", "weird_pickaxe"));
public static final Item WEIRD_PICK = new WeirdPick(WEIRD_PICK_KEY);
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of("fabric-item-api-v1-testmod", "weird_pickaxe"), WEIRD_PICK); Registry.register(Registries.ITEM, WEIRD_PICK_KEY, WEIRD_PICK);
FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> builder.registerPotionRecipe(Potions.WATER, WEIRD_PICK, Potions.AWKWARD)); FabricBrewingRecipeRegistryBuilder.BUILD.register(builder -> builder.registerPotionRecipe(Potions.WATER, WEIRD_PICK, Potions.AWKWARD));
EnchantmentEvents.ALLOW_ENCHANTING.register(((enchantment, target, enchantingContext) -> { EnchantmentEvents.ALLOW_ENCHANTING.register(((enchantment, target, enchantingContext) -> {
if (target.isOf(Items.DIAMOND_PICKAXE) && enchantment.matchesKey(Enchantments.SHARPNESS) && EnchantmentHelper.hasAnyEnchantmentsIn(target, EnchantmentTags.MINING_EXCLUSIVE_SET)) { if (target.isOf(Items.DIAMOND_PICKAXE) && enchantment.matchesKey(Enchantments.SHARPNESS) && EnchantmentHelper.hasAnyEnchantmentsIn(target, EnchantmentTags.MINING_EXCLUSIVE_SET)) {
@ -71,8 +74,8 @@ public class CustomDamageTest implements ModInitializer {
} }
public static class WeirdPick extends PickaxeItem { public static class WeirdPick extends PickaxeItem {
protected WeirdPick() { protected WeirdPick(RegistryKey<Item> registryKey) {
super(ToolMaterial.GOLD, 3f, 5f, new Item.Settings().customDamage(WEIRD_DAMAGE_HANDLER)); super(ToolMaterial.GOLD, 3f, 5f, new Item.Settings().customDamage(WEIRD_DAMAGE_HANDLER).registryKey(registryKey));
} }
@Override @Override

View file

@ -17,9 +17,12 @@
package net.fabricmc.fabric.test.item; package net.fabricmc.fabric.test.item;
import net.minecraft.component.ComponentType; import net.minecraft.component.ComponentType;
import net.minecraft.item.Item;
import net.minecraft.network.codec.PacketCodecs; import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.Codecs; import net.minecraft.util.dynamic.Codecs;
@ -31,7 +34,10 @@ public class ItemUpdateAnimationTest implements ModInitializer {
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of("fabric-item-api-v1-testmod", "updating_allowed"), new UpdatingItem(true)); RegistryKey<Item> updatingAllowedKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-item-api-v1-testmod", "updating_allowed"));
Registry.register(Registries.ITEM, Identifier.of("fabric-item-api-v1-testmod", "updating_disallowed"), new UpdatingItem(false)); RegistryKey<Item> updatingDisallowedKey = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-item-api-v1-testmod", "updating_disallowed"));
Registry.register(Registries.ITEM, updatingAllowedKey, new UpdatingItem(true, new Item.Settings().registryKey(updatingAllowedKey)));
Registry.register(Registries.ITEM, updatingDisallowedKey, new UpdatingItem(false, new Item.Settings().registryKey(updatingDisallowedKey)));
} }
} }

View file

@ -37,8 +37,8 @@ public class UpdatingItem extends Item {
private final boolean allowUpdateAnimation; private final boolean allowUpdateAnimation;
public UpdatingItem(boolean allowUpdateAnimation) { public UpdatingItem(boolean allowUpdateAnimation, Item.Settings settings) {
super(new Settings() super(settings
.component(DataComponentTypes.ATTRIBUTE_MODIFIERS, AttributeModifiersComponent.builder() .component(DataComponentTypes.ATTRIBUTE_MODIFIERS, AttributeModifiersComponent.builder()
.add(EntityAttributes.ATTACK_DAMAGE, PLUS_FIVE, AttributeModifierSlot.MAINHAND) .add(EntityAttributes.ATTACK_DAMAGE, PLUS_FIVE, AttributeModifierSlot.MAINHAND)
.build() .build()

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-resource-loader-v0": "*" "fabric-resource-loader-v0": "*"
}, },

View file

@ -37,13 +37,14 @@ import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
public class ItemGroupTest implements ModInitializer { public class ItemGroupTest implements ModInitializer {
private static final String MOD_ID = "fabric-item-group-api-v1-testmod"; private static final String MOD_ID = "fabric-item-group-api-v1-testmod";
private static Item TEST_ITEM; private static final RegistryKey<Item> ITEM_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of(MOD_ID, "item_test_group"));
private static final Item TEST_ITEM = new Item(new Item.Settings().registryKey(ITEM_KEY));
private static final RegistryKey<ItemGroup> ITEM_GROUP = RegistryKey.of(RegistryKeys.ITEM_GROUP, Identifier.of(MOD_ID, "test_group")); private static final RegistryKey<ItemGroup> ITEM_GROUP = RegistryKey.of(RegistryKeys.ITEM_GROUP, Identifier.of(MOD_ID, "test_group"));
@Override @Override
public void onInitialize() { public void onInitialize() {
TEST_ITEM = Registry.register(Registries.ITEM, Identifier.of("fabric-item-groups-v0-testmod", "item_test_group"), new Item(new Item.Settings())); Registry.register(Registries.ITEM, Identifier.of("fabric-item-groups-v0-testmod", "item_test_group"), TEST_ITEM);
Registry.register(Registries.ITEM_GROUP, ITEM_GROUP, FabricItemGroup.builder() Registry.register(Registries.ITEM_GROUP, ITEM_GROUP, FabricItemGroup.builder()
.displayName(Text.literal("Test Item Group")) .displayName(Text.literal("Test Item Group"))

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Key Binding registry API.", "description": "Key Binding registry API.",
"mixins": [ "mixins": [

View file

@ -55,7 +55,7 @@ public abstract class ClientChunkManagerMixin {
} }
} }
@Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;method_62893(ILnet/minecraft/world/chunk/WorldChunk;)V"), locals = LocalCapture.CAPTURE_FAILHARD) @Inject(method = "unload", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientChunkManager$ClientChunkMap;unloadChunk(ILnet/minecraft/world/chunk/WorldChunk;)V"), locals = LocalCapture.CAPTURE_FAILHARD)
private void onChunkUnload(ChunkPos pos, CallbackInfo ci, int i, WorldChunk chunk) { private void onChunkUnload(ChunkPos pos, CallbackInfo ci, int i, WorldChunk chunk) {
ClientChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, chunk); ClientChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, chunk);
} }

View file

@ -18,12 +18,12 @@ package net.fabricmc.fabric.mixin.event.lifecycle;
import java.util.Map; import java.util.Map;
import com.llamalad7.mixinextras.sugar.Local;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
@ -33,8 +33,8 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
@Mixin(LivingEntity.class) @Mixin(LivingEntity.class)
public abstract class LivingEntityMixin { public abstract class LivingEntityMixin {
@Inject(method = "getEquipmentChanges", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"), locals = LocalCapture.CAPTURE_FAILHARD) @Inject(method = "getEquipmentChanges", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))
private void getEquipmentChanges(CallbackInfoReturnable<@Nullable Map<EquipmentSlot, ItemStack>> cir, Map<EquipmentSlot, ItemStack> changes, EquipmentSlot[] slots, int slotsSize, int slotIndex, EquipmentSlot equipmentSlot, ItemStack previousStack, ItemStack currentStack) { private void getEquipmentChanges(CallbackInfoReturnable<@Nullable Map<EquipmentSlot, ItemStack>> cir, @Local EquipmentSlot equipmentSlot, @Local(ordinal = 0) ItemStack previousStack, @Local(ordinal = 1) ItemStack currentStack) {
ServerEntityEvents.EQUIPMENT_CHANGE.invoker().onChange((LivingEntity) (Object) this, equipmentSlot, previousStack, currentStack); ServerEntityEvents.EQUIPMENT_CHANGE.invoker().onChange((LivingEntity) (Object) this, equipmentSlot, previousStack, currentStack);
} }
} }

View file

@ -16,6 +16,8 @@
package net.fabricmc.fabric.mixin.event.lifecycle; package net.fabricmc.fabric.mixin.event.lifecycle;
import java.util.concurrent.CompletableFuture;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -27,6 +29,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.server.world.ChunkHolder; import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerChunkLoadingManager; import net.minecraft.server.world.ServerChunkLoadingManager;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.chunk.WorldChunk;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
@ -35,17 +38,16 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
public abstract class ServerChunkLoadingManagerMixin { public abstract class ServerChunkLoadingManagerMixin {
@Shadow @Shadow
@Final @Final
private ServerWorld world; ServerWorld world;
// Chunk (Un)Load events, An explanation:
// Must of this code is wrapped inside of futures and consumers, so it's generally a mess.
/** /**
* Injection is inside of tryUnloadChunk. * Injection is inside of tryUnloadChunk.
* We inject just after "setLoadedToWorld" is made false, since here the WorldChunk is guaranteed to be unloaded. * We inject just after "setLoadedToWorld" is made false, since here the WorldChunk is guaranteed to be unloaded.
*/ */
@Inject(method = "method_60440", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/WorldChunk;setLoadedToWorld(Z)V", shift = At.Shift.AFTER)) @Inject(method = "method_60440", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerChunkLoadingManager;save(Lnet/minecraft/world/chunk/Chunk;)Z"))
private void onChunkUnload(ChunkHolder chunkHolder, long l, CallbackInfo ci, @Local WorldChunk chunk) { private void onChunkUnload(ChunkHolder chunkHolder, CompletableFuture<?> completableFuture, long l, CallbackInfo ci, @Local Chunk chunk) {
ServerChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, chunk); if (chunk instanceof WorldChunk worldChunk) {
ServerChunkEvents.CHUNK_UNLOAD.invoker().onChunkUnload(this.world, worldChunk);
}
} }
} }

View file

@ -31,7 +31,7 @@
} }
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Events for the game's lifecycle.", "description": "Events for the game's lifecycle.",

View file

@ -18,9 +18,10 @@ package net.fabricmc.fabric.mixin.loot;
import java.util.Map; import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DynamicOps;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@ -37,7 +38,7 @@ import net.fabricmc.fabric.impl.loot.LootUtil;
@Mixin(JsonDataLoader.class) @Mixin(JsonDataLoader.class)
public class JsonDataLoaderMixin { public class JsonDataLoaderMixin {
@Inject(method = "load", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/resource/ResourceFinder;toResourceId(Lnet/minecraft/util/Identifier;)Lnet/minecraft/util/Identifier;", shift = At.Shift.AFTER)) @Inject(method = "load", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/resource/ResourceFinder;toResourceId(Lnet/minecraft/util/Identifier;)Lnet/minecraft/util/Identifier;", shift = At.Shift.AFTER))
private static void fillSourceMap(ResourceManager manager, String dataType, Gson gson, Map<Identifier, JsonElement> results, CallbackInfo ci, @Local Map.Entry<Identifier, Resource> entry, @Local(ordinal = 1) Identifier id) { private static <T> void fillSourceMap(ResourceManager manager, String dataType, DynamicOps<JsonElement> dynamicOps, Codec<T> codec, Map<Identifier, T> results, CallbackInfo ci, @Local Map.Entry<Identifier, Resource> entry, @Local(ordinal = 1) Identifier id) {
if (!LootDataType.LOOT_TABLES.registryKey().getValue().getPath().equals(dataType)) return; if (!LootDataType.LOOT_TABLES.registryKey().getValue().getPath().equals(dataType)) return;
LootUtil.SOURCES.get().put(id, LootUtil.determineSource(entry.getValue())); LootUtil.SOURCES.get().put(id, LootUtil.determineSource(entry.getValue()));

View file

@ -17,11 +17,10 @@
package net.fabricmc.fabric.mixin.loot; package net.fabricmc.fabric.mixin.loot;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@ -80,9 +79,9 @@ abstract class ReloadableRegistriesMixin {
}), fn, executor); }), fn, executor);
} }
@WrapOperation(method = "method_61239", at = @At(value = "INVOKE", target = "Ljava/util/Optional;ifPresent(Ljava/util/function/Consumer;)V")) @Inject(method = "method_61240", at = @At(value = "INVOKE", target = "Ljava/util/Map;forEach(Ljava/util/function/BiConsumer;)V"))
private static <T> void modifyLootTable(Optional<T> optionalTable, Consumer<? super T> action, Operation<Void> original, @Local(argsOnly = true) Identifier id, @Local(argsOnly = true) RegistryOps<JsonElement> ops) { private static <T> void modifyLootTable(LootDataType<T> lootDataType, ResourceManager resourceManager, RegistryOps<JsonElement> registryOps, CallbackInfoReturnable<MutableRegistry<?>> cir, @Local Map<Identifier, T> map) {
original.call(optionalTable.map(table -> modifyLootTable(table, id, ops)), action); map.replaceAll((identifier, t) -> modifyLootTable(t, identifier, registryOps));
} }
@Unique @Unique

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-resource-loader-v0": "*" "fabric-resource-loader-v0": "*"
}, },

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Adds message-related hooks.", "description": "Adds message-related hooks.",

View file

@ -46,7 +46,7 @@ public final class DelegatingUnbakedModel implements UnbakedModel {
} }
@Override @Override
public void resolve(Resolver resolver, ModelType modelType) { public void resolve(Resolver resolver) {
resolver.resolve(delegate); resolver.resolve(delegate);
} }

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Provides hooks for model loading.", "description": "Provides hooks for model loading.",

View file

@ -98,7 +98,7 @@ public class ModelTestModClient implements ClientModInitializer {
Identifier id = context.resourceId(); Identifier id = context.resourceId();
if (id != null && id.equals(BROWN_GLAZED_TERRACOTTA_MODEL_ID)) { if (id != null && id.equals(BROWN_GLAZED_TERRACOTTA_MODEL_ID)) {
return context.baker().getModel(MissingModel.ID); return MissingModel.create();
} }
return model; return model;

View file

@ -26,7 +26,7 @@
}, },
"accessWidener": "fabric-networking-api-v1.accesswidener", "accessWidener": "fabric-networking-api-v1.accesswidener",
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Low-level, vanilla protocol oriented networking hooks.", "description": "Low-level, vanilla protocol oriented networking hooks.",

View file

@ -32,8 +32,6 @@ import net.minecraft.util.math.BlockPos;
/** /**
* Fabric's version of BlockEntityType.Builder with additional convenience methods. * Fabric's version of BlockEntityType.Builder with additional convenience methods.
* *
* <p>Alternatively, use the access widener for {@link BlockEntityType.BlockEntityFactory}
* in Fabric Transitive Access Wideners (v1).
*/ */
public final class FabricBlockEntityTypeBuilder<T extends BlockEntity> { public final class FabricBlockEntityTypeBuilder<T extends BlockEntity> {
private final Factory<? extends T> factory; private final Factory<? extends T> factory;

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Builders for objects vanilla has locked down.", "description": "Builders for objects vanilla has locked down.",

View file

@ -30,6 +30,7 @@ import net.minecraft.item.Item;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -73,7 +74,7 @@ public class BlockEntityTypeBuilderTest implements ModInitializer {
private static void register(RegistryKey<Block> id, Block block) { private static void register(RegistryKey<Block> id, Block block) {
Registry.register(Registries.BLOCK, id, block); Registry.register(Registries.BLOCK, id, block);
Item item = new BlockItem(block, new Item.Settings()); Item item = new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, id.getValue())));
Registry.register(Registries.ITEM, id.getValue(), item); Registry.register(Registries.ITEM, id.getValue(), item);
} }

View file

@ -32,6 +32,7 @@ import net.minecraft.item.SignItem;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
@ -50,8 +51,8 @@ public class TealSignTest implements ModInitializer {
public static final HangingSignBlock TEAL_HANGING_SIGN = new HangingSignBlock(TEAL_WOOD_TYPE, AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN).registryKey(TEAL_HANGING_SIGN_KEY)); public static final HangingSignBlock TEAL_HANGING_SIGN = new HangingSignBlock(TEAL_WOOD_TYPE, AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN).registryKey(TEAL_HANGING_SIGN_KEY));
public static final RegistryKey<Block> TEAL_WALL_HANGING_SIGN_KEY = ObjectBuilderTestConstants.block("teal_wall_hanging_sign"); public static final RegistryKey<Block> TEAL_WALL_HANGING_SIGN_KEY = ObjectBuilderTestConstants.block("teal_wall_hanging_sign");
public static final WallHangingSignBlock TEAL_WALL_HANGING_SIGN = new WallHangingSignBlock(TEAL_WOOD_TYPE, AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN).registryKey(TEAL_WALL_HANGING_SIGN_KEY)); public static final WallHangingSignBlock TEAL_WALL_HANGING_SIGN = new WallHangingSignBlock(TEAL_WOOD_TYPE, AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN).registryKey(TEAL_WALL_HANGING_SIGN_KEY));
public static final SignItem TEAL_SIGN_ITEM = new SignItem(new Item.Settings(), TEAL_SIGN, TEAL_WALL_SIGN); public static final SignItem TEAL_SIGN_ITEM = new SignItem(TEAL_SIGN, TEAL_WALL_SIGN, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, TEAL_SIGN_KEY.getValue())));
public static final HangingSignItem TEAL_HANGING_SIGN_ITEM = new HangingSignItem(TEAL_HANGING_SIGN, TEAL_WALL_HANGING_SIGN, new Item.Settings()); public static final HangingSignItem TEAL_HANGING_SIGN_ITEM = new HangingSignItem(TEAL_HANGING_SIGN, TEAL_WALL_HANGING_SIGN, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, TEAL_HANGING_SIGN_KEY.getValue())));
@Override @Override
public void onInitialize() { public void onInitialize() {

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3" "fabricloader": ">=0.16.4"
}, },
"description": "Hooks for registering custom particles.", "description": "Hooks for registering custom particles.",
"mixins": [ "mixins": [

View file

@ -68,6 +68,6 @@ public final class ParticleTestSetup implements ModInitializer {
private static void registerBlock(RegistryKey<Block> key, Block block) { private static void registerBlock(RegistryKey<Block> key, Block block) {
Registry.register(Registries.BLOCK, key, block); Registry.register(Registries.BLOCK, key, block);
Registry.register(Registries.ITEM, key.getValue(), new BlockItem(block, new Item.Settings())); Registry.register(Registries.ITEM, key.getValue(), new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, key.getValue()))));
} }
} }

View file

@ -20,7 +20,7 @@
], ],
"accessWidener": "fabric-recipe-api-v1.accesswidener", "accessWidener": "fabric-recipe-api-v1.accesswidener",
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-networking-api-v1": "*" "fabric-networking-api-v1": "*"
}, },
"entrypoints": { "entrypoints": {

View file

@ -1,49 +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.mixin.registry.sync.client;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.spongepowered.asm.mixin.Final;
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.CallbackInfo;
import net.minecraft.client.render.item.ItemModels;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.registry.Registries;
import net.fabricmc.fabric.impl.registry.sync.trackers.Int2ObjectMapTracker;
@Mixin(ItemModels.class)
public class ItemModelsMixin {
@Final
@Shadow
public Int2ObjectMap<ModelIdentifier> modelIds;
@Final
@Shadow
private Int2ObjectMap<BakedModel> models;
@Inject(method = "<init>", at = @At("RETURN"))
public void onInit(BakedModelManager bakedModelManager, CallbackInfo info) {
Int2ObjectMapTracker.register(Registries.ITEM, "ItemModels.modelIds", modelIds);
Int2ObjectMapTracker.register(Registries.ITEM, "ItemModels.models", models);
}
}

View file

@ -7,7 +7,6 @@
"ClientRegistriesMixin", "ClientRegistriesMixin",
"ClientRegistriesDynamicRegistriesAccessor", "ClientRegistriesDynamicRegistriesAccessor",
"ItemColorsMixin", "ItemColorsMixin",
"ItemModelsMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"ParticleManagerMixin" "ParticleManagerMixin"
], ],

View file

@ -204,10 +204,6 @@ public class FabricRegistryInit implements ModInitializer {
RegistryAttributeHolder.get(Registries.MAP_DECORATION_TYPE) RegistryAttributeHolder.get(Registries.MAP_DECORATION_TYPE)
.addAttribute(RegistryAttribute.SYNCED); .addAttribute(RegistryAttribute.SYNCED);
// Synced via PacketCodecs.registry
RegistryAttributeHolder.get(Registries.ARMOR_MATERIAL)
.addAttribute(RegistryAttribute.SYNCED);
// Synced via PacketCodecs.registry // Synced via PacketCodecs.registry
RegistryAttributeHolder.get(Registries.CONSUME_EFFECT_TYPE) RegistryAttributeHolder.get(Registries.CONSUME_EFFECT_TYPE)
.addAttribute(RegistryAttribute.SYNCED); .addAttribute(RegistryAttribute.SYNCED);

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-networking-api-v1": "*" "fabric-networking-api-v1": "*"
}, },

View file

@ -159,7 +159,7 @@ public class RegistrySyncTest implements ModInitializer {
Registry.register(Registries.BLOCK, id, block); Registry.register(Registries.BLOCK, id, block);
if (REGISTER_ITEMS) { if (REGISTER_ITEMS) {
BlockItem blockItem = new BlockItem(block, new Item.Settings()); BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, id)));
Registry.register(Registries.ITEM, id, blockItem); Registry.register(Registries.ITEM, id, blockItem);
} }
} }

View file

@ -19,10 +19,8 @@ package net.fabricmc.fabric.mixin.renderer.client;
import java.util.BitSet; import java.util.BitSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.commons.lang3.tuple.Pair;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -32,7 +30,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.MultipartBakedModel; import net.minecraft.client.render.model.MultipartBakedModel;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -46,7 +43,7 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
public class MultipartBakedModelMixin implements FabricBakedModel { public class MultipartBakedModelMixin implements FabricBakedModel {
@Shadow @Shadow
@Final @Final
private List<Pair<Predicate<BlockState>, BakedModel>> components; private List<MultipartBakedModel.class_10204> components;
@Shadow @Shadow
@Final @Final
@ -61,9 +58,9 @@ public class MultipartBakedModelMixin implements FabricBakedModel {
} }
@Inject(at = @At("RETURN"), method = "<init>") @Inject(at = @At("RETURN"), method = "<init>")
private void onInit(List<Pair<Predicate<BlockState>, BakedModel>> components, CallbackInfo cb) { private void onInit(List<MultipartBakedModel.class_10204> components, CallbackInfo cb) {
for (Pair<Predicate<BlockState>, BakedModel> component : components) { for (MultipartBakedModel.class_10204 component : components) {
if (!component.getRight().isVanillaAdapter()) { if (!component.model().isVanillaAdapter()) {
isVanilla = false; isVanilla = false;
break; break;
} }
@ -78,9 +75,9 @@ public class MultipartBakedModelMixin implements FabricBakedModel {
bitSet = new BitSet(); bitSet = new BitSet();
for (int i = 0; i < this.components.size(); i++) { for (int i = 0; i < this.components.size(); i++) {
Pair<Predicate<BlockState>, BakedModel> pair = components.get(i); MultipartBakedModel.class_10204 component = components.get(i);
if (pair.getLeft().test(state)) { if (component.condition().test(state)) {
bitSet.set(i); bitSet.set(i);
} }
} }
@ -98,7 +95,7 @@ public class MultipartBakedModelMixin implements FabricBakedModel {
for (int i = 0; i < this.components.size(); i++) { for (int i = 0; i < this.components.size(); i++) {
if (bitSet.get(i)) { if (bitSet.get(i)) {
components.get(i).getRight().emitBlockQuads(blockView, state, pos, subModelRandomSupplier, context); components.get(i).model().emitBlockQuads(blockView, state, pos, subModelRandomSupplier, context);
} }
} }
} }

View file

@ -16,7 +16,6 @@
package net.fabricmc.fabric.mixin.renderer.client; package net.fabricmc.fabric.mixin.renderer.client;
import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -31,8 +30,8 @@ import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.WeightedBakedModel; import net.minecraft.client.render.model.WeightedBakedModel;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DataPool;
import net.minecraft.util.collection.Weighted; import net.minecraft.util.collection.Weighted;
import net.minecraft.util.collection.Weighting;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockRenderView;
@ -44,17 +43,14 @@ import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
public class WeightedBakedModelMixin implements FabricBakedModel { public class WeightedBakedModelMixin implements FabricBakedModel {
@Shadow @Shadow
@Final @Final
private int totalWeight; private DataPool<BakedModel> models;
@Shadow
@Final
private List<Weighted.Present<BakedModel>> models;
@Unique @Unique
boolean isVanilla = true; boolean isVanilla = true;
@Inject(at = @At("RETURN"), method = "<init>") @Inject(at = @At("RETURN"), method = "<init>")
private void onInit(List<Weighted.Present<BakedModel>> models, CallbackInfo cb) { private void onInit(DataPool<BakedModel> dataPool, CallbackInfo cb) {
for (int i = 0; i < models.size(); i++) { for (Weighted.Present<BakedModel> model : models.getEntries()) {
if (!models.get(i).data().isVanillaAdapter()) { if (!model.data().isVanillaAdapter()) {
isVanilla = false; isVanilla = false;
break; break;
} }
@ -68,12 +64,12 @@ public class WeightedBakedModelMixin implements FabricBakedModel {
@Override @Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) { public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
Weighted.Present<BakedModel> selected = Weighting.getAt(this.models, Math.abs((int) randomSupplier.get().nextLong()) % this.totalWeight).orElse(null); BakedModel selected = this.models.getDataOrEmpty(randomSupplier.get()).orElse(null);
if (selected != null) { if (selected != null) {
selected.data().emitBlockQuads(blockView, state, pos, () -> { selected.emitBlockQuads(blockView, state, pos, () -> {
Random random = randomSupplier.get(); Random random = randomSupplier.get();
random.nextLong(); // Imitate vanilla modifying the random before passing it to the submodel random.nextInt(); // Imitate vanilla modifying the random before passing it to the submodel
return random; return random;
}, context); }, context);
} }
@ -81,12 +77,12 @@ public class WeightedBakedModelMixin implements FabricBakedModel {
@Override @Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) { public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
Weighted.Present<BakedModel> selected = Weighting.getAt(this.models, Math.abs((int) randomSupplier.get().nextLong()) % this.totalWeight).orElse(null); BakedModel selected = this.models.getDataOrEmpty(randomSupplier.get()).orElse(null);
if (selected != null) { if (selected != null) {
selected.data().emitItemQuads(stack, () -> { selected.emitItemQuads(stack, () -> {
Random random = randomSupplier.get(); Random random = randomSupplier.get();
random.nextLong(); // Imitate vanilla modifying the random before passing it to the submodel random.nextInt(); // Imitate vanilla modifying the random before passing it to the submodel
return random; return random;
}, context); }, context);
} }

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.15-alpha.19.39.a", "minecraft": ">=1.15-alpha.19.39.a",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },

View file

@ -46,12 +46,12 @@ public final class Registration {
FRAME_VARIANT_BLOCK, FRAME_VARIANT_BLOCK,
}; };
public static final Item FRAME_ITEM = register("frame", new BlockItem(FRAME_BLOCK, new Item.Settings())); public static final Item FRAME_ITEM = registerItem("frame", (settings) -> new BlockItem(FRAME_BLOCK, settings));
public static final Item FRAME_MULTIPART_ITEM = register("frame_multipart", new BlockItem(FRAME_MULTIPART_BLOCK, new Item.Settings())); public static final Item FRAME_MULTIPART_ITEM = registerItem("frame_multipart", (settings) -> new BlockItem(FRAME_MULTIPART_BLOCK, settings));
public static final Item FRAME_VARIANT_ITEM = register("frame_variant", new BlockItem(FRAME_VARIANT_BLOCK, new Item.Settings())); public static final Item FRAME_VARIANT_ITEM = registerItem("frame_variant", (settings) -> new BlockItem(FRAME_VARIANT_BLOCK, settings));
public static final Item PILLAR_ITEM = register("pillar", new BlockItem(PILLAR_BLOCK, new Item.Settings())); public static final Item PILLAR_ITEM = registerItem("pillar", (settings) -> new BlockItem(PILLAR_BLOCK, settings));
public static final Item OCTAGONAL_COLUMN_ITEM = register("octagonal_column", new BlockItem(OCTAGONAL_COLUMN_BLOCK, new Item.Settings())); public static final Item OCTAGONAL_COLUMN_ITEM = registerItem("octagonal_column", (settings) -> new BlockItem(OCTAGONAL_COLUMN_BLOCK, settings));
public static final Item RIVERSTONE_ITEM = register("riverstone", new BlockItem(RIVERSTONE_BLOCK, new Item.Settings())); public static final Item RIVERSTONE_ITEM = registerItem("riverstone", (settings) -> new BlockItem(RIVERSTONE_BLOCK, settings));
public static final BlockEntityType<FrameBlockEntity> FRAME_BLOCK_ENTITY_TYPE = register("frame", FabricBlockEntityTypeBuilder.create(FrameBlockEntity::new, FRAME_BLOCKS).build()); public static final BlockEntityType<FrameBlockEntity> FRAME_BLOCK_ENTITY_TYPE = register("frame", FabricBlockEntityTypeBuilder.create(FrameBlockEntity::new, FRAME_BLOCKS).build());
@ -61,8 +61,9 @@ public final class Registration {
return Registry.register(Registries.BLOCK, id, constructor.apply(settings.registryKey(RegistryKey.of(RegistryKeys.BLOCK, id)))); return Registry.register(Registries.BLOCK, id, constructor.apply(settings.registryKey(RegistryKey.of(RegistryKeys.BLOCK, id))));
} }
private static <T extends Item> T register(String path, T item) { private static <T extends Item> T registerItem(String path, Function<Item.Settings, T> itemFunction) {
return Registry.register(Registries.ITEM, RendererTest.id(path), item); RegistryKey<Item> registryKey = RegistryKey.of(RegistryKeys.ITEM, RendererTest.id(path));
return Registry.register(Registries.ITEM, registryKey, itemFunction.apply(new Item.Settings().registryKey(registryKey)));
} }
private static <T extends BlockEntityType<?>> T register(String path, T blockEntityType) { private static <T extends BlockEntityType<?>> T register(String path, T blockEntityType) {

View file

@ -40,7 +40,7 @@ public class FrameUnbakedModel implements UnbakedModel {
private static final SpriteIdentifier OBSIDIAN_SPRITE_ID = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, Identifier.ofVanilla("block/obsidian")); private static final SpriteIdentifier OBSIDIAN_SPRITE_ID = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, Identifier.ofVanilla("block/obsidian"));
@Override @Override
public void resolve(Resolver resolver, ModelType currentlyResolvingType) { public void resolve(Resolver resolver) {
} }
/* /*

View file

@ -55,7 +55,7 @@ public class OctagonalColumnUnbakedModel implements UnbakedModel {
} }
@Override @Override
public void resolve(Resolver resolver, ModelType currentlyResolvingType) { public void resolve(Resolver resolver) {
} }
@Override @Override

View file

@ -38,7 +38,7 @@ public class PillarUnbakedModel implements UnbakedModel {
.toList(); .toList();
@Override @Override
public void resolve(Resolver resolver, ModelType currentlyResolvingType) { public void resolve(Resolver resolver) {
} }
@Nullable @Nullable

View file

@ -19,7 +19,6 @@ package net.fabricmc.fabric.test.renderer.client;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -31,7 +30,7 @@ import net.minecraft.client.render.model.WeightedBakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.util.collection.Weighted; import net.minecraft.util.collection.DataPool;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
@ -51,16 +50,7 @@ public class RandomSupplierTest implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
var checkingModel = new RandomCheckingBakedModel(); WeightedBakedModel weightedAgain = createWeightedBakedModel();
var weighted = new WeightedBakedModel(List.of(
Weighted.of(checkingModel, 1),
Weighted.of(checkingModel, 2)));
var multipart = new MultipartBakedModel(List.of(
Pair.of(state -> true, weighted),
Pair.of(state -> true, weighted)));
var weightedAgain = new WeightedBakedModel(List.of(
Weighted.of(multipart, 1),
Weighted.of(multipart, 2)));
long startingSeed = 42; long startingSeed = 42;
Random random = Random.create(); Random random = Random.create();
@ -78,6 +68,25 @@ public class RandomSupplierTest implements ClientModInitializer {
weightedAgain.emitBlockQuads(null, Blocks.STONE.getDefaultState(), BlockPos.ORIGIN, randomSupplier, null); weightedAgain.emitBlockQuads(null, Blocks.STONE.getDefaultState(), BlockPos.ORIGIN, randomSupplier, null);
} }
private static WeightedBakedModel createWeightedBakedModel() {
var checkingModel = new RandomCheckingBakedModel();
DataPool.Builder<BakedModel> weightedBuilder = DataPool.builder();
weightedBuilder.add(checkingModel, 1);
weightedBuilder.add(checkingModel, 2);
var weighted = new WeightedBakedModel(weightedBuilder.build());
var multipart = new MultipartBakedModel(List.of(
new MultipartBakedModel.class_10204(state -> true, weighted),
new MultipartBakedModel.class_10204(state -> true, weighted)));
DataPool.Builder<BakedModel> weightedAgainBuilder = DataPool.builder();
weightedAgainBuilder.add(multipart, 1);
weightedAgainBuilder.add(multipart, 2);
return new WeightedBakedModel(weightedAgainBuilder.build());
}
private static class RandomCheckingBakedModel implements BakedModel { private static class RandomCheckingBakedModel implements BakedModel {
@Override @Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) { public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {

View file

@ -33,7 +33,7 @@ public class RiverstoneUnbakedModel implements UnbakedModel {
private static final Identifier GOLD_BLOCK_MODEL_ID = Identifier.ofVanilla("block/gold_block"); private static final Identifier GOLD_BLOCK_MODEL_ID = Identifier.ofVanilla("block/gold_block");
@Override @Override
public void resolve(Resolver resolver, ModelType currentlyResolvingType) { public void resolve(Resolver resolver) {
resolver.resolve(STONE_MODEL_ID); resolver.resolve(STONE_MODEL_ID);
resolver.resolve(GOLD_BLOCK_MODEL_ID); resolver.resolve(GOLD_BLOCK_MODEL_ID);
} }

View file

@ -43,7 +43,7 @@ public abstract class ItemRendererMixin {
@Unique @Unique
private final ThreadLocal<ItemRenderContext> fabric_contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(colors)); private final ThreadLocal<ItemRenderContext> fabric_contexts = ThreadLocal.withInitial(() -> new ItemRenderContext(colors));
@Inject(method = "method_62476", at = @At(value = "HEAD"), cancellable = true) @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/render/model/json/ModelTransformationMode;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;Z)V", at = @At(value = "HEAD"), cancellable = true)
public void hook_renderItem(ItemStack stack, ModelTransformationMode transformMode, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, boolean notInHand, CallbackInfo ci) { public void hook_renderItem(ItemStack stack, ModelTransformationMode transformMode, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int light, int overlay, BakedModel model, boolean notInHand, CallbackInfo ci) {
if (!model.isVanillaAdapter()) { if (!model.isVanillaAdapter()) {
fabric_contexts.get().renderModel(stack, transformMode, matrixStack, vertexConsumerProvider, light, overlay, model); fabric_contexts.get().renderModel(stack, transformMode, matrixStack, vertexConsumerProvider, light, overlay, model);

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"minecraft": ">=1.15-alpha.19.39.a", "minecraft": ">=1.15-alpha.19.39.a",
"fabric-api-base": "*", "fabric-api-base": "*",
"fabric-renderer-api-v1": "*" "fabric-renderer-api-v1": "*"

View file

@ -15,7 +15,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Hooks for registering fluid renders.", "description": "Hooks for registering fluid renders.",

View file

@ -16,24 +16,26 @@
package net.fabricmc.fabric.mixin.client.rendering; package net.fabricmc.fabric.mixin.client.rendering;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.CapeFeatureRenderer; import net.minecraft.client.render.entity.feature.CapeFeatureRenderer;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack;
import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRenderEvents; import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRenderEvents;
@Mixin(CapeFeatureRenderer.class) @Mixin(CapeFeatureRenderer.class)
public class CapeFeatureRendererMixin { public class CapeFeatureRendererMixin {
@Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/item/Items;ELYTRA:Lnet/minecraft/item/Item;"), method = "render", require = 1, allow = 1, cancellable = true) @WrapOperation(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/feature/CapeFeatureRenderer;method_64075(Lnet/minecraft/item/ItemStack;)Z"), method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/PlayerEntityRenderState;FF)V")
public void injectCapeRenderCheck(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, PlayerEntityRenderState state, float limbAngle, float limbDistance, CallbackInfo ci) { public boolean injectCapeRenderCheck(CapeFeatureRenderer instance, ItemStack itemStack, Operation<Boolean> original, @Local(argsOnly = true) PlayerEntityRenderState state) {
if (!LivingEntityFeatureRenderEvents.ALLOW_CAPE_RENDER.invoker().allowCapeRender(state)) { if (!LivingEntityFeatureRenderEvents.ALLOW_CAPE_RENDER.invoker().allowCapeRender(state)) {
ci.cancel(); return false;
} }
return original.call(instance, itemStack);
} }
} }

View file

@ -16,7 +16,7 @@
"FabricMC" "FabricMC"
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.3", "fabricloader": ">=0.16.4",
"fabric-api-base": "*" "fabric-api-base": "*"
}, },
"description": "Hooks and registries for rendering-related things.", "description": "Hooks and registries for rendering-related things.",

View file

@ -19,15 +19,18 @@ package net.fabricmc.fabric.test.rendering;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class CustomAtlasSourcesTestInit implements ModInitializer { public class CustomAtlasSourcesTestInit implements ModInitializer {
public static final Item DOUBLE_IRON_INGOT = new Item(new Item.Settings()); public static final RegistryKey<Item> DOUBLE_IRON_INGOT_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-rendering-v1-testmod", "double_iron_ingot"));
public static final Item DOUBLE_IRON_INGOT = new Item(new Item.Settings().registryKey(DOUBLE_IRON_INGOT_KEY));
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of("fabric-rendering-v1-testmod", "double_iron_ingot"), DOUBLE_IRON_INGOT); Registry.register(Registries.ITEM, DOUBLE_IRON_INGOT_KEY, DOUBLE_IRON_INGOT);
} }
} }

View file

@ -31,7 +31,7 @@ import net.fabricmc.api.ModInitializer;
public class CustomColorResolverTestInit implements ModInitializer { public class CustomColorResolverTestInit implements ModInitializer {
public static final RegistryKey<Block> KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of("fabric-rendering-v1-testmod", "custom_color_block")); public static final RegistryKey<Block> KEY = RegistryKey.of(RegistryKeys.BLOCK, Identifier.of("fabric-rendering-v1-testmod", "custom_color_block"));
public static final Block CUSTOM_COLOR_BLOCK = new Block(AbstractBlock.Settings.create().registryKey(KEY)); public static final Block CUSTOM_COLOR_BLOCK = new Block(AbstractBlock.Settings.create().registryKey(KEY));
public static final Item CUSTOM_COLOR_BLOCK_ITEM = new BlockItem(CUSTOM_COLOR_BLOCK, new Item.Settings()); public static final Item CUSTOM_COLOR_BLOCK_ITEM = new BlockItem(CUSTOM_COLOR_BLOCK, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, KEY.getValue())));
@Override @Override
public void onInitialize() { public void onInitialize() {

View file

@ -16,44 +16,47 @@
package net.fabricmc.fabric.test.rendering; package net.fabricmc.fabric.test.rendering;
import java.util.EnumMap; import java.util.Map;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import net.minecraft.item.ArmorItem; import net.minecraft.item.ArmorItem;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.equipment.ArmorMaterial;
import net.minecraft.item.equipment.EquipmentType;
import net.minecraft.item.tooltip.TooltipData; import net.minecraft.item.tooltip.TooltipData;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class TooltipComponentTestInit implements ModInitializer { public class TooltipComponentTestInit implements ModInitializer {
public static Item CUSTOM_TOOLTIP_ITEM = new CustomTooltipItem(); public static final RegistryKey<Item> CUSTOM_TOOLTIP_ITEM_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-rendering-v1-testmod", "custom_tooltip"));
public static RegistryEntry<ArmorMaterial> TEST_ARMOR_MATERIAL = Registry.registerReference(Registries.ARMOR_MATERIAL, Identifier.of("fabric-rendering-v1-testmod", "test_material"), createTestArmorMaterial()); public static final Item CUSTOM_TOOLTIP_ITEM = new CustomTooltipItem(new Item.Settings().registryKey(CUSTOM_TOOLTIP_ITEM_KEY));
public static Item CUSTOM_ARMOR_ITEM = new ArmorItem(TEST_ARMOR_MATERIAL, ArmorItem.Type.CHESTPLATE, new Item.Settings());
public static final ArmorMaterial TEST_ARMOR_MATERIAL = createTestArmorMaterial();
public static final RegistryKey<Item> CUSTOM_ARMOR_ITEM_KEY = RegistryKey.of(RegistryKeys.ITEM, Identifier.of("fabric-rendering-v1-testmod", "test_chest"));
public static final Item CUSTOM_ARMOR_ITEM = new ArmorItem(TEST_ARMOR_MATERIAL, EquipmentType.CHESTPLATE, new Item.Settings().registryKey(CUSTOM_ARMOR_ITEM_KEY));
@Override @Override
public void onInitialize() { public void onInitialize() {
Registry.register(Registries.ITEM, Identifier.of("fabric-rendering-v1-testmod", "custom_tooltip"), CUSTOM_TOOLTIP_ITEM); Registry.register(Registries.ITEM, CUSTOM_TOOLTIP_ITEM_KEY, CUSTOM_TOOLTIP_ITEM);
Registry.register(Registries.ITEM, Identifier.of("fabric-rendering-v1-testmod", "test_chest"), CUSTOM_ARMOR_ITEM); Registry.register(Registries.ITEM, CUSTOM_ARMOR_ITEM_KEY, CUSTOM_ARMOR_ITEM);
} }
private static class CustomTooltipItem extends Item { private static class CustomTooltipItem extends Item {
CustomTooltipItem() { CustomTooltipItem(Settings settings) {
super(new Settings()); super(settings);
} }
@Override @Override
public Optional<TooltipData> getTooltipData(ItemStack stack) { public Optional<TooltipData> getTooltipData(ItemStack stack) {
return Optional.of(new Data(stack.getTranslationKey())); return Optional.of(new Data(stack.getItem().getTranslationKey()));
} }
} }
@ -62,18 +65,20 @@ public class TooltipComponentTestInit implements ModInitializer {
private static ArmorMaterial createTestArmorMaterial() { private static ArmorMaterial createTestArmorMaterial() {
return new ArmorMaterial( return new ArmorMaterial(
Util.make(new EnumMap<>(ArmorItem.Type.class), (map) -> { 0,
map.put(ArmorItem.Type.BOOTS, 1); Map.of(
map.put(ArmorItem.Type.LEGGINGS, 2); EquipmentType.BOOTS, 1,
map.put(ArmorItem.Type.CHESTPLATE, 3); EquipmentType.LEGGINGS, 2,
map.put(ArmorItem.Type.HELMET, 1); EquipmentType.CHESTPLATE, 3,
map.put(ArmorItem.Type.BODY, 3); EquipmentType.HELMET, 1,
}), EquipmentType.BODY, 3
SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, ),
(stack) -> stack.getItem() == Items.LEATHER, 1,
List.of(new ArmorMaterial.Layer(Identifier.of("fabric-rendering-v1-testmod", "test_material"))), SoundEvents.ITEM_ARMOR_EQUIP_LEATHER,
0, 0,
0 0.5F,
ItemTags.REPAIRS_LEATHER_ARMOR,
Identifier.of("fabric-rendering-v1-testmod", "test_material")
); );
} }
} }

View file

@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@ -114,7 +115,7 @@ public final class ResourceConditionsImpl implements ModInitializer {
* - any call to {@link #tagsPopulated} will check the tags from the failed reload instead of failing directly. * - any call to {@link #tagsPopulated} will check the tags from the failed reload instead of failing directly.
* This is probably acceptable. * This is probably acceptable.
*/ */
public static final ThreadLocal<Map<RegistryKey<?>, Set<Identifier>>> LOADED_TAGS = new ThreadLocal<>(); public static final AtomicReference<Map<RegistryKey<?>, Set<Identifier>>> LOADED_TAGS = new AtomicReference<>();
public static void setTags(List<Registry.PendingTagLoad<?>> tags) { public static void setTags(List<Registry.PendingTagLoad<?>> tags) {
Map<RegistryKey<?>, Set<Identifier>> tagMap = new IdentityHashMap<>(); Map<RegistryKey<?>, Set<Identifier>> tagMap = new IdentityHashMap<>();
@ -123,7 +124,9 @@ public final class ResourceConditionsImpl implements ModInitializer {
tagMap.put(registryTags.getKey(), registryTags.getLookup().streamTagKeys().map(TagKey::id).collect(Collectors.toSet())); tagMap.put(registryTags.getKey(), registryTags.getLookup().streamTagKeys().map(TagKey::id).collect(Collectors.toSet()));
} }
LOADED_TAGS.set(tagMap); if (LOADED_TAGS.getAndSet(tagMap) != null) {
throw new IllegalStateException("Tags already captured, this should not happen");
}
} }
// Cannot use registry because tags are not loaded to the registry at this stage yet. // Cannot use registry because tags are not loaded to the registry at this stage yet.

Some files were not shown because too many files have changed in this diff Show more