diff --git a/SpongeAPI b/SpongeAPI index fcfb9213f66..0ba43afee9f 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit fcfb9213f66959667ae63523d593e2e5cf567af9 +Subproject commit 0ba43afee9fc35e5478ee09cbd7ce8bf1ca50167 diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7a0e8d0074b..4af7b96a5e2 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -485,6 +485,14 @@ + + + + + + + + @@ -508,6 +516,11 @@ + + + + + @@ -587,6 +600,14 @@ + + + + + + + + @@ -665,6 +686,11 @@ + + + + + @@ -2255,6 +2281,14 @@ + + + + + + + + diff --git a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java index 07c6de04c64..dfa469a4a84 100644 --- a/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java +++ b/src/main/java/org/spongepowered/common/event/inventory/InventoryEventFactory.java @@ -38,6 +38,7 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.EnchantmentMenu; +import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.MerchantMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentInstance; @@ -239,9 +240,8 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) return true; } - public static @org.checkerframework.checker.nullness.qual.Nullable AbstractContainerMenu displayContainer(final ServerPlayer player, final Inventory inventory, final Component displayName) { - final net.minecraft.world.inventory.AbstractContainerMenu previousContainer = player.containerMenu; - final net.minecraft.world.inventory.AbstractContainerMenu container; + public static @Nullable AbstractContainerMenu displayContainer(final ServerPlayer player, final Inventory inventory, final Component displayName) { + final AbstractContainerMenu previousContainer = player.containerMenu; Optional viewable = inventory.asViewable(); if (viewable.isPresent()) { @@ -276,8 +276,7 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) horse.openCustomInventoryScreen(player); } - container = player.containerMenu; - + final AbstractContainerMenu container = player.containerMenu; if (previousContainer == container) { return null; } @@ -300,6 +299,27 @@ public static boolean callInteractContainerOpenEvent(final ServerPlayer player) return container; } + public static @Nullable AbstractContainerMenu displayContainer(final ServerPlayer player, final MenuType type, Component displayName) { + final AbstractContainerMenu previousContainer = player.containerMenu; + + if (displayName == null) { + displayName = Component.text("CustomContainer"); + } + + final MenuProvider menuProvider = new SimpleMenuProvider((menuId, playerInv, p) -> type.create(menuId, playerInv), SpongeAdventure.asVanilla(displayName)); + player.openMenu(menuProvider); + final AbstractContainerMenu container = player.containerMenu; + if (previousContainer == container) { + return null; + } + + if (!InventoryEventFactory.callInteractContainerOpenEvent(player)) { + return null; + } + + return player.containerMenu; + } + public static TransferInventoryEvent.Pre callTransferPre(final Inventory source, final Inventory destination) { PhaseTracker.getCauseStackManager().pushCause(source); final TransferInventoryEvent.Pre event = SpongeEventFactory.createTransferInventoryEventPre( diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java index 23b0461ecdd..3c70687523f 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java @@ -136,6 +136,7 @@ private Slot newDummySlot() { } // Slot definition Impl: + @Override public BuildingStep slotsAtIndizes(List source, List at) { Validate.isTrue(source.size() == at.size(), "Source and index list sizes differ"); for (int i = 0; i < at.size(); i++) { @@ -148,10 +149,12 @@ public BuildingStep slotsAtIndizes(List source, List at) { } // complex redirects - (source/index list generation) + @Override public BuildingStep slotsAtPositions(List source, List at) { return this.slotsAtIndizes(source, at.stream().map(this::posToIndex).collect(Collectors.toList())); } + @Override public DummyStep fillDummy() { Slot slot = this.newDummySlot(); List indizes = IntStream.range(0, this.info.size).boxed().filter(idx -> !this.slotDefinitions.containsKey(idx)).collect(Collectors.toList()); @@ -160,6 +163,7 @@ public DummyStep fillDummy() { return this; } + @Override public DummyStep dummySlots(int count, int offset) { Slot slot = this.newDummySlot(); List source = Stream.generate(() -> slot).limit(count).collect(Collectors.toList()); @@ -167,11 +171,13 @@ public DummyStep dummySlots(int count, int offset) { return this; } + @Override public BuildingStep slots(List source, int offset) { List indizes = IntStream.range(offset, offset + source.size()).boxed().collect(Collectors.toList()); return this.slotsAtIndizes(source, indizes); } + @Override public DummyStep dummyGrid(Vector2i size, Vector2i offset) { Slot slot = this.newDummySlot(); List source = Stream.generate(() -> slot).limit(size.x() * size.y()).collect(Collectors.toList()); @@ -179,6 +185,7 @@ public DummyStep dummyGrid(Vector2i size, Vector2i offset) { return this; } + @Override public BuildingStep grid(List source, Vector2i size, Vector2i offset) { int xMin = offset.x(); int yMin = offset.y(); @@ -196,14 +203,17 @@ public BuildingStep grid(List source, Vector2i size, Vector2i offset) { // simple redirects + @Override public DummyStep dummySlots(int count, Vector2i offset) { return this.dummySlots(count, this.posToIndex(offset)); } + @Override public BuildingStep slots(List source, Vector2i offset) { return this.slots(source, this.posToIndex(offset)); } + @Override public DummyStep dummyGrid(Vector2i size, int offset) { return this.dummyGrid(size, this.indexToPos(offset)); } @@ -225,6 +235,7 @@ public EndStep plugin(final PluginContainer plugin) { return this; } + @Override public EndStep identity(UUID uuid) { this.identity = uuid; return this; diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/data/BlockEntity_DataHolderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/data/BlockEntity_DataHolderMixin_API.java new file mode 100644 index 00000000000..823b337eeee --- /dev/null +++ b/src/mixins/java/org/spongepowered/common/mixin/api/data/BlockEntity_DataHolderMixin_API.java @@ -0,0 +1,44 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.common.mixin.api.data; + +import org.spongepowered.api.block.BlockState; +import org.spongepowered.api.block.entity.BlockEntity; +import org.spongepowered.api.data.DataHolder; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.common.data.holder.SpongeMutableDataHolder; + +import java.util.Arrays; +import java.util.List; + +@Mixin(net.minecraft.world.level.block.entity.BlockEntity.class) +public abstract class BlockEntity_DataHolderMixin_API implements DataHolder, SpongeMutableDataHolder { + + @Override + public List impl$delegateDataHolder() { + final BlockState state = ((BlockEntity) this).block(); + return Arrays.asList(this, state, state.type()); + } +} diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/data/DataHolderMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/data/DataHolderMixin_API.java index 846e1d75c4a..4d2a31a5efc 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/data/DataHolderMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/data/DataHolderMixin_API.java @@ -26,12 +26,11 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; import org.spongepowered.api.data.DataHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.data.holder.SpongeMutableDataHolder; -@Mixin(value = {BlockEntity.class, Entity.class, ItemStack.class}, priority = 899) +@Mixin(value = {Entity.class, ItemStack.class}, priority = 899) public abstract class DataHolderMixin_API implements DataHolder, SpongeMutableDataHolder { } diff --git a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java index e17fe5ef9a8..67914d7391d 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/block/entity/BlockEntityMixin_API.java @@ -183,5 +183,4 @@ public Set> getValues() { protected Set> api$getVanillaValues() { return new HashSet<>(); } - } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java index 3c4711ab9f7..c0913065f32 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/api/server/level/ServerPlayerMixin_Inventory_API.java @@ -25,9 +25,11 @@ package org.spongepowered.common.mixin.inventory.api.server.level; import net.kyori.adventure.text.Component; +import net.minecraft.world.inventory.MenuType; import org.checkerframework.checker.nullness.qual.NonNull; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.item.inventory.Container; +import org.spongepowered.api.item.inventory.ContainerType; import org.spongepowered.api.item.inventory.Inventory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.common.bridge.world.inventory.container.ContainerBridge; @@ -64,6 +66,20 @@ public Optional openInventory(final Inventory inventory, final Compon return Optional.ofNullable((Container) InventoryEventFactory.displayContainer((net.minecraft.server.level.ServerPlayer) (Object) this, inventory, displayName)); } + @Override + public Optional openInventory(final ContainerType type) { + return this.openInventory(type, null); + } + + @Override + public Optional openInventory(final ContainerType type, final Component displayName) { + final ContainerBridge openContainer = (ContainerBridge) this.containerMenu; + if (openContainer.bridge$isInUse()) { + throw new UnsupportedOperationException("This player is currently modifying an open container. Opening a new one must be delayed!"); + } + return Optional.ofNullable((Container) InventoryEventFactory.displayContainer((net.minecraft.server.level.ServerPlayer) (Object) this, (MenuType) type, displayName)); + } + @Override public boolean closeInventory() throws IllegalArgumentException { final net.minecraft.world.inventory.AbstractContainerMenu openContainer = this.containerMenu; diff --git a/src/mixins/resources/mixins.sponge.api.json b/src/mixins/resources/mixins.sponge.api.json index 621a2304140..ff00fce102a 100644 --- a/src/mixins/resources/mixins.sponge.api.json +++ b/src/mixins/resources/mixins.sponge.api.json @@ -5,6 +5,7 @@ "mixinPriority": 1100, "mixins": [ "common.entity.living.HumanEntityMixin_API", + "data.BlockEntity_DataHolderMixin_API", "data.DataHolderMixin_API", "data.persistence.DataContainerMixin_API", "entity.ai.goal.AbstractGoalMixin_API",