Skip to content

Commit

Permalink
Abstract away the debug commands and a few other things - Only the ma…
Browse files Browse the repository at this point in the history
…tcher to go.
  • Loading branch information
me4502 committed Dec 20, 2018
1 parent 44b3ee0 commit db740e7
Show file tree
Hide file tree
Showing 17 changed files with 440 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ default Association getAssociation(List<ProtectedRegion> regions) {
*/
void setSaturation(double saturation);

/**
* Gets the exhaustion of this player.
*
* @return The exhaustion
*/
float getExhaustion();

/**
* Sets the exhaustion of this player.
*
* @param exhaustion The exhaustion
*/
void setExhaustion(float exhaustion);

/**
* Gets the players weather
*
Expand Down Expand Up @@ -160,4 +174,19 @@ default Association getAssociation(List<ProtectedRegion> regions) {
* Resets the players time to normal.
*/
void resetPlayerTime();

// TODO Move this to WorldEdit's Entity class - honestly most of this class could be a Facet
/**
* Gets the number of ticks the player is on fire for.
*
* @return The number of fire ticks
*/
int getFireTicks();

/**
* Sets the number of ticks the player is on fire for.
*
* @param fireTicks The fire ticks
*/
void setFireTicks(int fireTicks);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.internal.platform;

import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldguard.LocalPlayer;

public interface DebugHandler {

void testBreak(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException;

void testPlace(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException;

void testInteract(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException;

void testDamage(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ public interface WorldGuardPlatform {
*/
RegionContainer getRegionContainer();

/**
* Gets the handler for debug commands.
*
* @return The debug handler
*/
DebugHandler getDebugHandler();

/**
* Gets the servers default game mode.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.util;

import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityProperties;

public class Entities {

private Entities() {
}

/**
* Returns whether an entity should be removed for the halt activity mode.
*
* @param entity The entity
* @return true if it's to be removed
*/
public static boolean isIntensiveEntity(Entity entity) {
EntityProperties properties = entity.getFacet(EntityProperties.class);
return properties != null
&& (properties.isItem()
|| properties.isTNT()
|| properties.isExperienceOrb()
|| properties.isFallingBlock()
|| (properties.isLiving()
&& !(properties.isTamed())
&& !(properties.isPlayerDerived())
&& !properties.isArmorStand()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* 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;

import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.formatting.Style;
import com.sk89q.worldedit.util.paste.ActorCallbackPaste;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.event.debug.CancelLogging;
import com.sk89q.worldguard.bukkit.event.debug.LoggingBlockBreakEvent;
import com.sk89q.worldguard.bukkit.event.debug.LoggingBlockPlaceEvent;
import com.sk89q.worldguard.bukkit.event.debug.LoggingEntityDamageByEntityEvent;
import com.sk89q.worldguard.bukkit.event.debug.LoggingPlayerInteractEvent;
import com.sk89q.worldguard.bukkit.util.report.CancelReport;
import com.sk89q.worldguard.internal.platform.DebugHandler;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.util.BlockIterator;

import java.util.logging.Logger;

public class BukkitDebugHandler implements DebugHandler {

private static final Logger log = Logger.getLogger(BukkitDebugHandler.class.getCanonicalName());
private static final int MAX_TRACE_DISTANCE = 20;

private final WorldGuardPlugin plugin;

BukkitDebugHandler(WorldGuardPlugin plugin) {
this.plugin = plugin;
}

/**
* Simulate an event and print its report.
*
* @param receiver The receiver of the messages
* @param target The target
* @param event The event
* @param stacktraceMode Whether stack traces should be generated and posted
* @param <T> The type of event
*/
private <T extends Event & CancelLogging> void testEvent(CommandSender receiver, Player target, T event, boolean stacktraceMode) throws
CommandPermissionsException {
boolean isConsole = receiver instanceof ConsoleCommandSender;

if (!receiver.equals(target)) {
if (!isConsole) {
log.info(receiver.getName() + " is simulating an event on " + target.getName());
}

target.sendMessage(
ChatColor.RED + "(Please ignore any messages that may immediately follow.)");
}

Bukkit.getPluginManager().callEvent(event);
int start = new Exception().getStackTrace().length;
CancelReport report = new CancelReport(event, event.getCancels(), start);
report.setDetectingPlugin(!stacktraceMode);
String result = report.toString();

if (stacktraceMode) {
receiver.sendMessage(ChatColor.GRAY + "The report was printed to console.");
log.info("Event report for " + receiver.getName() + ":\n\n" + result);

plugin.checkPermission(receiver, "worldguard.debug.pastebin");
ActorCallbackPaste
.pastebin(WorldGuard.getInstance().getSupervisor(), plugin.wrapCommandSender(receiver), result, "Event debugging report: %s.txt");
} else {
receiver.sendMessage(result.replaceAll("(?m)^", ChatColor.AQUA.toString()));

if (result.length() >= 500 && !isConsole) {
receiver.sendMessage(ChatColor.GRAY + "The report was also printed to console.");
log.info("Event report for " + receiver.getName() + ":\n\n" + result);
}
}
}

/**
* Get the source of the test.
*
* @param sender The message sender
* @param target The provided target
* @param fromTarget Whether the source should be the target
* @return The source
* @throws CommandException Thrown if a condition is not met
*/
private Player getSource(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
if (fromTarget) {
return target;
} else {
if (sender instanceof Player) {
return (Player) sender;
} else {
throw new CommandException(
"If this command is not to be used in-game, use -t to run the test from the viewpoint of the given player rather than yourself.");
}
}
}

/**
* Find the first non-air block in a ray trace.
*
* @param sender The sender
* @param target The target
* @param fromTarget Whether the trace should originate from the target
* @return The block found
* @throws CommandException Throw on an incorrect parameter
*/
private Block traceBlock(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
Player source = getSource(sender, target, fromTarget);

BlockIterator it = new BlockIterator(source);
int i = 0;
while (it.hasNext() && i < MAX_TRACE_DISTANCE) {
Block block = it.next();
if (block.getType() != Material.AIR) {
return block;
}
i++;
}

throw new CommandException("Not currently looking at a block that is close enough.");
}

/**
* Find the first nearby entity in a ray trace.
*
* @param sender The sender
* @param target The target
* @param fromTarget Whether the trace should originate from the target
* @return The entity found
* @throws CommandException Throw on an incorrect parameter
*/
private Entity traceEntity(CommandSender sender, Player target, boolean fromTarget) throws CommandException {
Player source = getSource(sender, target, fromTarget);

BlockIterator it = new BlockIterator(source);
int i = 0;
while (it.hasNext() && i < MAX_TRACE_DISTANCE) {
Block block = it.next();

// A very in-accurate and slow search
Entity[] entities = block.getChunk().getEntities();
for (Entity entity : entities) {
if (!entity.equals(target) && entity.getLocation().distanceSquared(block.getLocation()) < 10) {
return entity;
}
}

i++;
}

throw new CommandException("Not currently looking at an entity that is close enough.");
}

@Override
public void testBreak(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException {
CommandSender bukkitSender = plugin.unwrapActor(sender);
Player bukkitTarget = BukkitAdapter.adapt(target);

Block block = traceBlock(bukkitSender, bukkitTarget, fromTarget);
sender.printRaw(Style.CYAN + "Testing BLOCK BREAK at " + Style.CYAN_DARK + block);
LoggingBlockBreakEvent event = new LoggingBlockBreakEvent(block, bukkitTarget);
testEvent(bukkitSender, bukkitTarget, event, stackTraceMode);
}

@Override
public void testPlace(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException {
CommandSender bukkitSender = plugin.unwrapActor(sender);
Player bukkitTarget = BukkitAdapter.adapt(target);

Block block = traceBlock(bukkitSender, bukkitTarget, fromTarget);
sender.printRaw(Style.CYAN + "Testing BLOCK PLACE at " + Style.CYAN_DARK + block);
LoggingBlockPlaceEvent event = new LoggingBlockPlaceEvent(block, block.getState(), block.getRelative(BlockFace.DOWN), bukkitTarget.getItemInHand(), bukkitTarget, true);
testEvent(bukkitSender, bukkitTarget, event, stackTraceMode);
}

@Override
public void testInteract(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException {
CommandSender bukkitSender = plugin.unwrapActor(sender);
Player bukkitTarget = BukkitAdapter.adapt(target);

Block block = traceBlock(bukkitSender, bukkitTarget, fromTarget);
sender.printRaw(Style.CYAN + "Testing BLOCK INTERACT at " + Style.CYAN_DARK + block);
LoggingPlayerInteractEvent event = new LoggingPlayerInteractEvent(bukkitTarget, Action.RIGHT_CLICK_BLOCK, bukkitTarget.getItemInHand(), block, BlockFace.SOUTH);
testEvent(bukkitSender, bukkitTarget, event, stackTraceMode);
}

@Override
public void testDamage(Actor sender, LocalPlayer target, boolean fromTarget, boolean stackTraceMode) throws CommandException {
CommandSender bukkitSender = plugin.unwrapActor(sender);
Player bukkitTarget = BukkitAdapter.adapt(target);
Entity entity = traceEntity(bukkitSender, bukkitTarget, fromTarget);
sender.printRaw(Style.CYAN + "Testing ENTITY DAMAGE on " + Style.CYAN_DARK + entity);
LoggingEntityDamageByEntityEvent event = new LoggingEntityDamageByEntityEvent(bukkitTarget, entity, EntityDamageEvent.DamageCause.ENTITY_ATTACK, 1);
testEvent(bukkitSender, bukkitTarget, event, stackTraceMode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ public void setSaturation(double saturation) {

}

@Override
public float getExhaustion() {
return 0;
}

@Override
public void setExhaustion(float exhaustion) {

}

@Override
public WeatherType getPlayerWeather() {
return WeatherTypes.CLEAR;
Expand Down
Loading

0 comments on commit db740e7

Please sign in to comment.