Skip to content

Commit

Permalink
Cancelling ClickContainerEvent.Primary removes the item in the clicke…
Browse files Browse the repository at this point in the history
…d slot (#3875)

* fix the issue #3862

* event was not cancelled with a double/triple click

* fix check and build

* change "broadcastAudience" to "systemSubject" and add the plugin "clickcontainereventcancelledtest" in sponge_plugins.json

* taking account of reviews

* the revenge of taking account of reviews

* the return of the taking account of reviews

Co-authored-by: Joni Aromaa <[email protected]>

---------

Co-authored-by: Joni Aromaa <[email protected]>
  • Loading branch information
AlexandreArcil and aromaa authored Dec 3, 2023
1 parent a23741c commit 67d5af2
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ public interface TrackedContainerBridge {

boolean bridge$capturePossible();

void bridge$detectAndSendChanges(boolean captureOnly);
void bridge$detectAndSendChanges(boolean capture, boolean synchronize);
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public static void handleCursorRestore(final Player player, final Transaction<It
}
final ItemStack cursor = ItemStackUtil.fromSnapshotToNative(cursorSnap);
player.containerMenu.setCarried(cursor);
player.containerMenu.setRemoteCarried(cursor);
if (player instanceof net.minecraft.server.level.ServerPlayer) {
((net.minecraft.server.level.ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(-1, player.containerMenu.getStateId(), -1, cursor));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
@Shadow protected abstract void shadow$updateDataSlotListeners(int $$0, int $$1);
@Shadow protected abstract void shadow$synchronizeDataSlotToRemote(int $$0, int $$1);
@Shadow protected abstract void shadow$synchronizeCarriedToRemote();
@Shadow public abstract void shadow$sendAllDataToRemote();
//@formatter:on

private boolean impl$isClicking; // Menu Callbacks are only called when clicking in a container
Expand Down Expand Up @@ -131,7 +132,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
if (((LevelBridge) player.level).bridge$isFake() || player.level.isClientSide || !(thisContainer.getSlot(slotId) instanceof ResultSlot)) {
return result;
}
this.bridge$detectAndSendChanges(true);
this.bridge$detectAndSendChanges(true, true);
final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
TrackingUtil.processBlockCaptures(context); // ClickContainerEvent -> CraftEvent -> PreviewEvent
// result is modified by the ClickMenuTransaction
Expand Down Expand Up @@ -162,6 +163,18 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon

}

@Inject(method = "broadcastFullState", at = @At("HEAD"))
private void impl$broadcastFullStateWithTransactions(final CallbackInfo ci) {
if (!PhaseTracker.SERVER.onSidedThread()) {
return;
}
this.bridge$detectAndSendChanges(false, false);
this.impl$broadcastDataSlots(false);
this.shadow$sendAllDataToRemote();
this.impl$captureSuccess = true; // Detect mod overrides
ci.cancel();
}

// broadcastChanges

/**
Expand All @@ -176,14 +189,14 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
if (!PhaseTracker.SERVER.onSidedThread()) {
return;
}
this.bridge$detectAndSendChanges(false);
this.bridge$detectAndSendChanges(false, true);
this.impl$captureSuccess = true; // Detect mod overrides
ci.cancel();
}


@Override
public void bridge$detectAndSendChanges(final boolean captureOnly) {
public void bridge$detectAndSendChanges(final boolean capture, final boolean synchronize) {
// Code-Flow changed from vanilla completely!

final SpongeInventoryMenu menu = ((MenuBridge)this).bridge$getMenu();
Expand Down Expand Up @@ -212,7 +225,7 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
} else {
this.impl$capture(i, newStack, oldStack); // Capture changes for inventory events

if (captureOnly) {
if (capture) {
continue;
}
// Perform vanilla logic - updating inventory stack - notify listeners
Expand All @@ -222,18 +235,22 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
for (final ContainerListener listener : this.containerListeners) {
listener.slotChanged(((AbstractContainerMenu) (Object) this), i, oldStack);
}
final ItemStack remoteStack = this.remoteSlots.get(i);
if (!ItemStack.matches(remoteStack, newStack)) {
this.remoteSlots.set(i, newStack.copy());
if (this.synchronizer != null) {
this.synchronizer.sendSlotChange(((AbstractContainerMenu) (Object) this), i, newStack);
if (synchronize) {
final ItemStack remoteStack = this.remoteSlots.get(i);
if (!ItemStack.matches(remoteStack, newStack)) {
this.remoteSlots.set(i, newStack.copy());
if (this.synchronizer != null) {
this.synchronizer.sendSlotChange(((AbstractContainerMenu) (Object) this), i, newStack);
}
}
}
}
}

this.shadow$synchronizeCarriedToRemote();
this.impl$broadcastDataSlots();
if (synchronize) {
this.shadow$synchronizeCarriedToRemote();
this.impl$broadcastDataSlots(true);
}
}

private void impl$sendSlotContents(final Integer i, final ItemStack oldStack) {
Expand All @@ -250,13 +267,15 @@ public abstract class AbstractContainerMenuMixin_Inventory implements TrackedCon
}
}

private void impl$broadcastDataSlots() {
private void impl$broadcastDataSlots(final boolean synchronize) {
for(int j = 0; j < this.dataSlots.size(); ++j) {
final DataSlot dataSlot = this.dataSlots.get(j);
if (dataSlot.checkAndClearUpdateFlag()) {
this.shadow$updateDataSlotListeners(j, dataSlot.get());
}
this.shadow$synchronizeDataSlotToRemote(j, dataSlot.get());
if (synchronize) {
this.shadow$synchronizeDataSlotToRemote(j, dataSlot.get());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* 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.test.interact;

import com.google.inject.Inject;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.parameter.CommandContext;
import org.spongepowered.api.event.EventContextKeys;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.item.inventory.container.ClickContainerEvent;
import org.spongepowered.api.registry.RegistryTypes;
import org.spongepowered.plugin.PluginContainer;
import org.spongepowered.plugin.builtin.jvm.Plugin;
import org.spongepowered.test.LoadableModule;

/**
* @author CanardNocturne
*/
@Plugin("clickcontainereventcancelledtest")
public class ClickContainerEventCancelledTest implements LoadableModule {

private final PluginContainer plugin;

@Inject
public ClickContainerEventCancelledTest(final PluginContainer plugin) {
this.plugin = plugin;
}

@Override
public void enable(final CommandContext ctx) {
Sponge.eventManager().registerListeners(this.plugin, new ClickContainerEventCancelledTest.ClickContainerListener());
}

public static class ClickContainerListener {
@Listener
private void onInteractItem(final ClickContainerEvent.Primary event) {
event.setCancelled(true);
Sponge.game().systemSubject().sendMessage(Identity.nil(), Component.text("/*************"));
Sponge.game().systemSubject().sendMessage(Identity.nil(), Component.text().append(Component.text("/* Event: ")).append(Component.text(event.getClass().getSimpleName())).build());
Sponge.game().systemSubject().sendMessage(Identity.nil(),
Component.text().append(Component.text("/* Hand: "))
.append(Component.text(event.context().get(EventContextKeys.USED_HAND).map(h -> RegistryTypes.HAND_TYPE.keyFor(Sponge.game(), h).formatted()).orElse("UNKNOWN")))
.build()
);
Sponge.game().systemSubject().sendMessage(Identity.nil(), Component.text().append(Component.text("/ Cause: ")).append(Component.text(event.cause().all().toString())).build());
Sponge.game().systemSubject().sendMessage(Identity.nil(), Component.text().append(Component.text("/ Context: ")).append(Component.text(event.context().toString())).build());
Sponge.game().systemSubject().sendMessage(Identity.nil(),
Component.text().append(Component.text("/ Cancelled: ")).append(Component.text(event.isCancelled())).build());
}
}



}
6 changes: 6 additions & 0 deletions testplugins/src/main/resources/META-INF/sponge_plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@
"name": "Display Entities Test",
"entrypoint": "org.spongepowered.test.entity.DisplayEntityTest",
"description": "Testing Display Entities"
},
{
"id": "clickcontainereventcancelledtest",
"name": "Click Container Event Cancelled Test",
"entrypoint": "org.spongepowered.test.interact.ClickContainerEventCancelledTest",
"description": "Testing Cancelling Click Container Primary Event"
}
]
}

0 comments on commit 67d5af2

Please sign in to comment.