GriefDefender/bukkit/src/main/java/com/griefdefender/listener/CommonEntityEventHandler.java

345 lines
17 KiB
Java

/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* 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 com.griefdefender.listener;
import java.lang.ref.WeakReference;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.inventory.ItemStack;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GDTimings;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.ChatType;
import com.griefdefender.api.ChatTypes;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.permission.flag.Flags;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.cache.MessageCache;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.configuration.MessageStorage;
import com.griefdefender.event.GDBorderClaimEvent;
import com.griefdefender.internal.registry.ItemTypeRegistryModule;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.permission.flag.GDFlags;
import com.griefdefender.storage.BaseStorage;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
public class CommonEntityEventHandler {
private static CommonEntityEventHandler instance;
public static CommonEntityEventHandler getInstance() {
return instance;
}
static {
instance = new CommonEntityEventHandler();
}
private final BaseStorage storage;
public CommonEntityEventHandler() {
this.storage = GriefDefenderPlugin.getInstance().dataStore;
}
public boolean onEntityMove(Event event, Location fromLocation, Location toLocation, Entity targetEntity){
final Vector3i fromPos = VecHelper.toVector3i(fromLocation);
final Vector3i toPos = VecHelper.toVector3i(toLocation);
if (fromPos.equals(toPos)) {
return true;
}
if ((!GDFlags.ENTER_CLAIM && !GDFlags.EXIT_CLAIM)) {
return true;
}
final Player player = targetEntity instanceof Player ? (Player) targetEntity : null;
final GDPermissionUser user = player != null ? PermissionHolderCache.getInstance().getOrCreateUser(player) : null;
if (user != null) {
if (user.getInternalPlayerData().teleportDelay > 0) {
if (!toPos.equals(VecHelper.toVector3i(user.getInternalPlayerData().teleportSourceLocation))) {
user.getInternalPlayerData().teleportDelay = 0;
TextAdapter.sendComponent(player, MessageCache.getInstance().TELEPORT_MOVE_CANCEL);
}
}
}
final World world = targetEntity.getWorld();
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
return true;
}
final boolean enterBlacklisted = GriefDefenderPlugin.isSourceIdBlacklisted(Flags.ENTER_CLAIM.getName(), targetEntity, world.getUID());
final boolean exitBlacklisted = GriefDefenderPlugin.isSourceIdBlacklisted(Flags.EXIT_CLAIM.getName(), targetEntity, world.getUID());
if (enterBlacklisted && exitBlacklisted) {
return true;
}
GDTimings.ENTITY_MOVE_EVENT.startTiming();
GDClaim fromClaim = null;
GDClaim toClaim = this.storage.getClaimAt(toLocation);
if (user != null) {
fromClaim = this.storage.getClaimAtPlayer(user.getInternalPlayerData(), fromLocation);
} else {
fromClaim = this.storage.getClaimAt(fromLocation);
}
if (GDFlags.ENTER_CLAIM && !enterBlacklisted && user != null && user.getInternalPlayerData().lastClaim != null) {
final GDClaim lastClaim = (GDClaim) user.getInternalPlayerData().lastClaim.get();
if (lastClaim != null && lastClaim != fromClaim) {
if (GDPermissionManager.getInstance().getFinalPermission(event, toLocation, toClaim, GDPermissions.ENTER_CLAIM, targetEntity, targetEntity, player, TrustTypes.ACCESSOR, false) == Tristate.FALSE) {
Location claimCorner = new Location(toLocation.getWorld(), toClaim.lesserBoundaryCorner.getX(), targetEntity.getLocation().getBlockY(), toClaim.greaterBoundaryCorner.getZ());
targetEntity.teleport(claimCorner);
}
}
}
if (fromClaim == toClaim) {
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return true;
}
GDBorderClaimEvent gpEvent = new GDBorderClaimEvent(targetEntity, fromClaim, toClaim);
if (user != null && toClaim.isUserTrusted(user, TrustTypes.ACCESSOR)) {
GriefDefender.getEventManager().post(gpEvent);
if (gpEvent.cancelled()) {
if (targetEntity instanceof Vehicle) {
final Vehicle vehicle = (Vehicle) targetEntity;
vehicle.teleport(fromLocation);
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return false;
}
if (event instanceof Cancellable) {
((Cancellable) event).setCancelled(true);
}
final Component cancelMessage = gpEvent.getMessage().orElse(null);
if (player != null && cancelMessage != null) {
TextAdapter.sendComponent(player, cancelMessage);
}
return false;
} else {
final boolean showGpPrefix = GriefDefenderPlugin.getGlobalConfig().getConfig().message.enterExitShowGdPrefix;
user.getInternalPlayerData().lastClaim = new WeakReference<>(toClaim);
TextComponent welcomeMessage = (TextComponent) gpEvent.getEnterMessage().orElse(null);
if (welcomeMessage != null && !welcomeMessage.equals(TextComponent.empty())) {
ChatType chatType = gpEvent.getEnterMessageChatType();
if (chatType == ChatTypes.ACTION_BAR) {
TextAdapter.sendActionBar(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(welcomeMessage)
.build());
} else {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(welcomeMessage)
.build());
}
}
Component farewellMessage = gpEvent.getExitMessage().orElse(null);
if (farewellMessage != null && !farewellMessage.equals(TextComponent.empty())) {
ChatType chatType = gpEvent.getExitMessageChatType();
if (chatType == ChatTypes.ACTION_BAR) {
TextAdapter.sendActionBar(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(farewellMessage)
.build());
} else {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(farewellMessage)
.build());
}
}
if (toClaim.isInTown()) {
user.getInternalPlayerData().inTown = true;
} else {
user.getInternalPlayerData().inTown = false;
}
}
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return true;
}
if (fromClaim != toClaim) {
boolean enterCancelled = false;
boolean exitCancelled = false;
// enter
if (GDFlags.ENTER_CLAIM && !enterBlacklisted && GDPermissionManager.getInstance().getFinalPermission(event, toLocation, toClaim, GDPermissions.ENTER_CLAIM, targetEntity, targetEntity, user) == Tristate.FALSE) {
enterCancelled = true;
gpEvent.cancelled(true);
}
// exit
if (GDFlags.EXIT_CLAIM && !exitBlacklisted && GDPermissionManager.getInstance().getFinalPermission(event, fromLocation, fromClaim, GDPermissions.EXIT_CLAIM, targetEntity, targetEntity, user) == Tristate.FALSE) {
exitCancelled = true;
gpEvent.cancelled(true);
}
GriefDefender.getEventManager().post(gpEvent);
if (gpEvent.cancelled()) {
final Component cancelMessage = gpEvent.getMessage().orElse(null);
if (exitCancelled) {
if (cancelMessage != null && player != null) {
GriefDefenderPlugin.sendClaimDenyMessage(fromClaim, player, MessageCache.getInstance().PERMISSION_CLAIM_EXIT);
}
} else if (enterCancelled) {
if (cancelMessage != null && player != null) {
GriefDefenderPlugin.sendClaimDenyMessage(toClaim, player, MessageCache.getInstance().PERMISSION_CLAIM_ENTER);
}
}
if (cancelMessage != null && player != null) {
TextAdapter.sendComponent(player, cancelMessage);
}
if (targetEntity instanceof Vehicle) {
final Vehicle vehicle = (Vehicle) targetEntity;
vehicle.teleport(fromLocation);
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return false;
}
if (event instanceof Cancellable) {
((Cancellable) event).setCancelled(true);
}
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return false;
}
if (user != null) {
final boolean showGpPrefix = GriefDefenderPlugin.getGlobalConfig().getConfig().message.enterExitShowGdPrefix;
user.getInternalPlayerData().lastClaim = new WeakReference<>(toClaim);
Component welcomeMessage = gpEvent.getEnterMessage().orElse(null);
if (welcomeMessage != null && !welcomeMessage.equals(TextComponent.empty())) {
ChatType chatType = gpEvent.getEnterMessageChatType();
if (chatType == ChatTypes.ACTION_BAR) {
TextAdapter.sendActionBar(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(welcomeMessage)
.build());
} else {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(welcomeMessage)
.build());
}
}
Component farewellMessage = gpEvent.getExitMessage().orElse(null);
if (farewellMessage != null && !farewellMessage.equals(TextComponent.empty())) {
ChatType chatType = gpEvent.getExitMessageChatType();
if (chatType == ChatTypes.ACTION_BAR) {
TextAdapter.sendActionBar(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(farewellMessage)
.build());
} else {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append(showGpPrefix ? GriefDefenderPlugin.GD_TEXT : TextComponent.empty())
.append(farewellMessage)
.build());
}
}
if (toClaim.isInTown()) {
user.getInternalPlayerData().inTown = true;
} else {
user.getInternalPlayerData().inTown = false;
}
checkPlayerFlight(player, user.getInternalPlayerData(), fromClaim, toClaim);
}
}
GDTimings.ENTITY_MOVE_EVENT.stopTiming();
return true;
}
private void checkPlayerFlight(Player player, GDPlayerData playerData, GDClaim fromClaim, GDClaim toClaim) {
final GameMode gameMode = player.getGameMode();
if (gameMode == GameMode.CREATIVE || gameMode == GameMode.SPECTATOR) {
return;
}
if (fromClaim == toClaim || !player.isFlying()) {
// only handle player-fly in enter/exit
return;
}
final Boolean noFly = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_FLIGHT, toClaim);
final boolean adminFly = player.hasPermission(GDPermissions.BYPASS_OPTION);
final boolean ownerFly = toClaim.isBasicClaim() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_BASIC) : toClaim.isTown() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_TOWN) : false;
if (player.getUniqueId().equals(toClaim.getOwnerUniqueId()) && ownerFly) {
return;
}
if (!adminFly && noFly) {
player.setAllowFlight(false);
player.setFlying(false);
playerData.ignoreFallDamage = true;
GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().OPTION_PLAYER_DENY_FLIGHT);
}
}
public void sendInteractEntityDenyMessage(ItemStack playerItem, Entity entity, GDClaim claim, Player player) {
if (entity instanceof Player || (claim.getData() != null && !claim.getData().allowDenyMessages())) {
return;
}
final String entityId = entity.getType().getName() == null ? entity.getType().name().toLowerCase() : entity.getType().getName();
if (playerItem == null || playerItem.getType() == Material.AIR) {
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.PERMISSION_INTERACT_ENTITY, ImmutableMap.of(
"player", claim.getOwnerName(),
"entity", entityId));
GriefDefenderPlugin.sendClaimDenyMessage(claim, player, message);
} else {
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.PERMISSION_INTERACT_ITEM_ENTITY, ImmutableMap.of(
"item", ItemTypeRegistryModule.getInstance().getNMSKey(playerItem),
"entity", entityId));
GriefDefenderPlugin.sendClaimDenyMessage(claim, player, message);
}
}
}