diff --git a/SpongeAPI b/SpongeAPI index d4641e160e8..c0f65a12e41 160000 --- a/SpongeAPI +++ b/SpongeAPI @@ -1 +1 @@ -Subproject commit d4641e160e878274d3ac3599d27fc6f583f33acd +Subproject commit c0f65a12e41afb4a6891efd0c6c00a7b0f2ddea4 diff --git a/src/accessors/java/org/spongepowered/common/accessor/world/entity/InteractionAccessor.java b/src/accessors/java/org/spongepowered/common/accessor/world/entity/InteractionAccessor.java new file mode 100644 index 00000000000..f890218652e --- /dev/null +++ b/src/accessors/java/org/spongepowered/common/accessor/world/entity/InteractionAccessor.java @@ -0,0 +1,41 @@ +/* + * 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.accessor.world.entity; + +import net.minecraft.world.entity.Interaction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Interaction.class) +public interface InteractionAccessor { + + @Invoker("getWidth") float invoker$getWidth(); + + @Invoker("getHeight") float invoker$getHeight(); + + @Invoker("setWidth") void invoker$setWidth(float width); + + @Invoker("setHeight") void invoker$setHeight(float height); +} diff --git a/src/accessors/resources/mixins.sponge.accessors.json b/src/accessors/resources/mixins.sponge.accessors.json index 2bd0ef591fc..44ecad6163c 100644 --- a/src/accessors/resources/mixins.sponge.accessors.json +++ b/src/accessors/resources/mixins.sponge.accessors.json @@ -66,6 +66,7 @@ "world.entity.EntityAccessor", "world.entity.EntityTypeAccessor", "world.entity.ExperienceOrbAccessor", + "world.entity.InteractionAccessor", "world.entity.LightningBoltAccessor", "world.entity.LivingEntityAccessor", "world.entity.MobAccessor", diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/DisplayEntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/DisplayEntityData.java index dd4bdfddca8..0702c7aacae 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/DisplayEntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/DisplayEntityData.java @@ -61,6 +61,9 @@ public static void register(final DataProviderRegistrator registrator) { .asMutable(Display.class) .create(Keys.TRANSFORM) .get(DisplayEntityData::getTransform) + .set((h, v) -> DisplayEntityData.setTransform(h, v.toMatrix())) + .create(Keys.MATRIX) + .get(DisplayEntityData::getMatrix) .set(DisplayEntityData::setTransform) .asMutable(DisplayAccessor.class) .create(Keys.BILLBOARD_TYPE) @@ -219,9 +222,17 @@ private static Transform getTransform(final Display display) { return transform; } - private static void setTransform(final Display h, final Transform transform) { + private static Matrix4d getMatrix(final Display display) { + var vanillaTransform = DisplayAccessor.invoker$createTransformation(display.getEntityData()); + var vMatrix = vanillaTransform.getMatrix(); + return Matrix4d.from( + vMatrix.get(0, 0), vMatrix.get(1, 0), vMatrix.get(2, 0), vMatrix.get(3, 0), + vMatrix.get(0, 1), vMatrix.get(1, 1), vMatrix.get(2, 1), vMatrix.get(3, 1), + vMatrix.get(0, 2), vMatrix.get(1, 2), vMatrix.get(2, 2), vMatrix.get(3, 2), + vMatrix.get(0, 3), vMatrix.get(1, 3), vMatrix.get(2, 3), vMatrix.get(3, 3)); + } - final Matrix4d matrix = transform.toMatrix(); + private static void setTransform(final Display h, final Matrix4d matrix) { var vMatrix = new org.joml.Matrix4f( (float) matrix.get(0, 0), (float) matrix.get(1, 0), (float) matrix.get(2, 0), (float) matrix.get(3, 0), (float) matrix.get(0, 1), (float) matrix.get(1, 1), (float) matrix.get(2, 1), (float) matrix.get(3, 1), diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java index 5e62f6e798b..69937fac579 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java @@ -249,6 +249,10 @@ public static void register(final DataProviderRegistrator registrator) { ((PortalProcessorBridge)h.portalProcess).bridge$init(h.level()); }) .delete(h -> h.portalProcess = null) + .create(Keys.BOUNDING_BOX_BASE_SIZE) + .get(h -> (double) h.getBbWidth()) + .create(Keys.BOUNDING_BOX_HEIGHT) + .get(h -> (double) h.getBbHeight()) .asMutable(EntityMaxAirBridge.class) .create(Keys.MAX_AIR) .get(EntityMaxAirBridge::bridge$getMaxAir) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index f77adffb98a..55f80e64fb7 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -76,6 +76,7 @@ public void registerProviders() { HorseData.register(this.registrator); HumanData.register(this.registrator); IdentifiableData.register(this.registrator); + InteractionData.register(this.registrator); InvulnerableData.register(this.registrator); IronGolemData.register(this.registrator); ItemData.register(this.registrator); diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/InteractionData.java b/src/main/java/org/spongepowered/common/data/provider/entity/InteractionData.java new file mode 100644 index 00000000000..363bcbacff2 --- /dev/null +++ b/src/main/java/org/spongepowered/common/data/provider/entity/InteractionData.java @@ -0,0 +1,49 @@ +/* + * 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.data.provider.entity; + +import org.spongepowered.api.data.Keys; +import org.spongepowered.common.accessor.world.entity.InteractionAccessor; +import org.spongepowered.common.data.provider.DataProviderRegistrator; + +public final class InteractionData { + + private InteractionData() { + } + + // @formatter:off + public static void register(final DataProviderRegistrator registrator) { + registrator + .asMutable(InteractionAccessor.class) + .create(Keys.BOUNDING_BOX_BASE_SIZE) + .get(h -> (double) h.invoker$getWidth()) + .set((h, v) -> h.invoker$setWidth(v.floatValue())) + .create(Keys.BOUNDING_BOX_HEIGHT) + .get(h -> (double) h.invoker$getHeight()) + .set((h, v) -> h.invoker$setHeight(v.floatValue())) + ; + } + // @formatter:on +} diff --git a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java index e08665640b4..894c657bf60 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeInventoryMenu.java @@ -370,17 +370,13 @@ private Boolean onClickLeft( public boolean onChange(final ItemStack newStack, final ItemStack oldStack, final Container container, final int slotIndex, final Slot slot) { - // readonly by default cancels top inventory changes . but can be overridden by change callbacks - if (this.readonly && !(slot.container instanceof PlayerInventory)) { - return false; - } - if (this.changeHandler != null) { final Cause cause = PhaseTracker.getCauseStackManager().currentCause(); return this.changeHandler.handle(cause, container, ((org.spongepowered.api.item.inventory.Slot) slot), slotIndex, ItemStackUtil.snapshotOf(oldStack), ItemStackUtil.snapshotOf(newStack)); } - return true; + // readonly by default cancels top inventory changes . but can be overridden by change callbacks + return !this.isReadOnly(slotIndex) || slot.container instanceof PlayerInventory; } } 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 c37c4dd9a56..2f2a7bd8dfb 100644 --- a/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java +++ b/src/main/java/org/spongepowered/common/inventory/custom/SpongeViewableInventoryBuilder.java @@ -138,6 +138,7 @@ private Slot newDummySlot() { // Slot definition Impl: public BuildingStep slotsAtIndizes(List source, List at) { Validate.isTrue(source.size() == at.size(), "Source and index list sizes differ"); + this.lastSlot = null; for (int i = 0; i < at.size(); i++) { Slot slot = source.get(i); Integer index = at.get(i); @@ -215,7 +216,9 @@ public BuildingStep grid(List source, Vector2i size, int offset) { // dummy @Override public BuildingStep item(ItemStackLike item) { - this.lastSlot.set(item); + if (this.lastSlot != null) { + this.lastSlot.set(item); + } return this; } diff --git a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java index d8db0a26fbb..79f0556afd9 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java +++ b/src/mixins/java/org/spongepowered/common/mixin/inventory/event/world/inventory/AbstractContainerMenuMixin_Inventory.java @@ -213,6 +213,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon try (final EffectTransactor ignored = transactor.logClickContainer(menu, slotId, dragType, clickType, player)) { this.impl$isClicking = true; this.shadow$doClick(slotId, dragType, clickType, player); + this.bridge$detectAndSendChanges(true, false); } finally { this.impl$isClicking = false; } @@ -283,7 +284,10 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon // Only call Menu Callbacks when clicking if (this.impl$isClicking && menu != null && !menu.onChange(newStack, oldStack, (org.spongepowered.api.item.inventory.Container) this, i, slot)) { - this.lastSlots.set(i, oldStack.copy()); // revert changes + // revert changes + oldStack = oldStack.copy(); + slot.set(oldStack); + this.lastSlots.set(i, oldStack); this.impl$sendSlotContents(i, oldStack); // Send reverted slots to clients } else { this.impl$capture(i, newStack, oldStack); // Capture changes for inventory events diff --git a/testplugins/src/main/java/org/spongepowered/test/entity/DisplayEntityTest.java b/testplugins/src/main/java/org/spongepowered/test/entity/DisplayEntityTest.java index f0317c60f4f..8e9a8b49597 100644 --- a/testplugins/src/main/java/org/spongepowered/test/entity/DisplayEntityTest.java +++ b/testplugins/src/main/java/org/spongepowered/test/entity/DisplayEntityTest.java @@ -50,6 +50,7 @@ import org.spongepowered.api.world.server.ServerLocation; import org.spongepowered.api.world.server.ServerWorld; import org.spongepowered.math.imaginary.Quaterniond; +import org.spongepowered.math.matrix.Matrix4d; import org.spongepowered.math.vector.Vector3d; import org.spongepowered.plugin.PluginContainer; import org.spongepowered.plugin.builtin.jvm.Plugin; @@ -83,6 +84,7 @@ public void onRegisterCommand(final RegisterCommandEvent event) { final int col5 = 3; final int col6 = 5; final int col7 = 6; + final int col8 = 7; var textDisplay = spawnEntity(player.world(), EntityTypes.TEXT_DISPLAY, centerPos, forwardDir, -4, -1); textDisplay.offer(Keys.DISPLAY_NAME, Component.text("DisplayEntityTest").color(NamedTextColor.GOLD)); textDisplay.offer(Keys.SEE_THROUGH_BLOCKS, true); @@ -247,6 +249,14 @@ public void onRegisterCommand(final RegisterCommandEvent event) { textDisplay.offer(Keys.INTERPOLATION_DURATION, Ticks.of(20)); textDisplay.offer(Keys.INTERPOLATION_DELAY, Ticks.of(20)); + blockDisplay = createEntity(player.world(), EntityTypes.BLOCK_DISPLAY, centerPos, forwardDir, col8, 0); + blockDisplay.offer(Keys.BLOCK_STATE, BlockTypes.CHERRY_SAPLING.get().defaultState()); + blockDisplay.offer(Keys.MATRIX, Matrix4d + .createRotation(Quaterniond.fromAxesAnglesDeg(0, 45, 0)) + .scale(0.5) + .rotate(Quaterniond.fromAxesAnglesDeg(45, 0, 0))); + player.world().spawnEntity(blockDisplay); + // TODO interpolate text opacity? });