Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/checkstyle/import-control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</subpackage>

<subpackage name="bukkit">
<allow pkg="org.mockito"/>
<allow pkg="org.bukkit"/>
<allow pkg="org.bstats.bukkit"/>
<allow pkg="org.bstats.charts"/>
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ flyway-core = "org.flywaydb:flyway-core:3.0"
commandbook = "com.sk89q:commandbook:2.3"

hamcrest-library = "org.hamcrest:hamcrest-library:2.2"
mockito-core = "org.mockito:mockito-core:5.22.0"

# Mojang-provided libraries, CHECK AGAINST MINECRAFT for versions
guava = "com.google.guava:guava:33.6.0-jre"
Expand Down
3 changes: 3 additions & 0 deletions worldguard-bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ dependencies {

"implementation"(libs.paperLib)
"implementation"(libs.bstats.bukkit)

"testImplementation"(libs.paperApi)
"testImplementation"(libs.mockito.core)
}

tasks.named<Copy>("processResources") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Item;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.Player;
import org.bukkit.entity.SulfurCube;
import org.bukkit.entity.Tameable;
Expand All @@ -66,8 +67,10 @@
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerTakeLecternBookEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
import org.bukkit.inventory.InventoryHolder;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -423,7 +426,10 @@ public void onUseEntity(UseEntityEvent event) {
&& ((ItemFrame) entity).getItem().getType() != Material.AIR) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.ITEM_FRAME_ROTATE));
what = "change that";
} else if (event.getOriginalEvent() instanceof InventoryOpenEvent || event.getOriginalEvent() instanceof InventoryMoveItemEvent) {
} else if (event.getOriginalEvent() instanceof InventoryOpenEvent
|| event.getOriginalEvent() instanceof InventoryMoveItemEvent
|| (event.getOriginalEvent() instanceof PlayerInteractEntityEvent
&& entity instanceof Minecart && entity instanceof InventoryHolder)) {
canUse = query.testBuild(BukkitAdapter.adapt(target), associable, combine(event, Flags.CHEST_ACCESS));
what = "open that";
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldguard.bukkit.listener;

import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.internal.platform.WorldGuardPlatform;
import com.sk89q.worldguard.protection.RegionResultSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Minecart;
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.entity.minecart.StorageMinecart;
import org.bukkit.event.Event;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

class RegionProtectionListenerTest {

@Test
void chestAccessAllowsInitialInventoryMinecartClick() {
assertFalse(checkUse(StorageMinecart.class, EntityType.CHEST_MINECART,
PlayerInteractEntityEvent.class, State.ALLOW));
assertFalse(checkUse(HopperMinecart.class, EntityType.HOPPER_MINECART,
PlayerInteractEntityEvent.class, State.ALLOW));
}

@Test
void chestAccessStillDeniesInventoryMinecartClick() {
assertTrue(checkUse(StorageMinecart.class, EntityType.CHEST_MINECART,
PlayerInteractEntityEvent.class, State.DENY));
}

@Test
void inventoryOpenAndTransferStillUseChestAccess() {
assertFalse(checkUse(StorageMinecart.class, EntityType.CHEST_MINECART,
InventoryOpenEvent.class, State.ALLOW));
assertTrue(checkUse(StorageMinecart.class, EntityType.CHEST_MINECART,
InventoryMoveItemEvent.class, State.DENY));
}

@Test
void chestAccessDoesNotAllowOtherEntityChanges() {
assertTrue(checkUse(ArmorStand.class, EntityType.ARMOR_STAND,
PlayerInteractEntityEvent.class, State.ALLOW));
}

@Test
void ordinaryMinecartStillDefersToMountProtection() {
assertFalse(checkUse(Minecart.class, EntityType.MINECART,
PlayerInteractEntityEvent.class, State.DENY));
}

private <T extends Entity> boolean checkUse(
Class<T> entityClass, EntityType type,
Class<? extends Event> eventClass, State chestAccess) {
ProtectedCuboidRegion region = new ProtectedCuboidRegion("test",
BlockVector3.at(-1, 0, -1), BlockVector3.at(1, 100, 1));
region.setFlag(Flags.CHEST_ACCESS, chestAccess);
RegionQuery query = mock(RegionQuery.class, CALLS_REAL_METHODS);
doReturn(new RegionResultSet(new ArrayList<>(List.of(region)), null)).when(query)
.getApplicableRegions(any(com.sk89q.worldedit.util.Location.class));

WorldGuard worldGuard = mock(WorldGuard.class);
WorldGuardPlatform platform = mock(WorldGuardPlatform.class);
RegionContainer container = mock(RegionContainer.class);
when(worldGuard.getPlatform()).thenReturn(platform);
when(platform.getRegionContainer()).thenReturn(container);
when(container.createQuery()).thenReturn(query);

World world = mock(World.class);
T entity = mock(entityClass);
when(entity.getType()).thenReturn(type);
when(entity.getLocation()).thenReturn(new Location(world, 0, 64, 0));
UseEntityEvent event = new UseEntityEvent(mock(eventClass), Cause.unknown(), entity);
event.setSilent(true);

var worldEditWorld = mock(com.sk89q.worldedit.world.World.class);
var worldEditLocation = new com.sk89q.worldedit.util.Location(
worldEditWorld, 0, 64, 0);
try (MockedStatic<WorldGuard> guard = mockStatic(WorldGuard.class);
MockedStatic<AbstractListener> listener = mockStatic(AbstractListener.class);
MockedStatic<BukkitAdapter> adapter = mockStatic(BukkitAdapter.class)) {
guard.when(WorldGuard::getInstance).thenReturn(worldGuard);
listener.when(() -> AbstractListener.isRegionSupportEnabled(world)).thenReturn(true);
adapter.when(() -> BukkitAdapter.adapt(any(Location.class)))
.thenReturn(worldEditLocation);
new RegionProtectionListener(mock(WorldGuardPlugin.class)).onUseEntity(event);
}
return event.isCancelled();
}
}