Compare commits

..
Author SHA1 Message Date
benwoo1110 cc3996ca76 Implement new queue command system. 2021-03-09 20:54:42 +08:00
Ben Woo 7c59dcbcb9 Merge pull request #2494 from benwoo1110/property-fix
Fix cannot remove block currency with mvm set command.
2021-03-04 15:32:34 +08:00
Ben Woo 15cacba7c9 Merge pull request #2573 from Multiverse/java-11
Fix compiling with Java 11+
2021-03-02 09:01:38 +08:00
Ben Woo adbe88daa6 Merge pull request #2565 from Multiverse/fis-respawn-anchor
Add respawn anchor support.
2021-03-02 00:36:43 +08:00
Kermina Awad 5350c012f7 fix compiling on java 15 2021-02-25 17:48:17 -05:00
benwoo1110 a91f377cf5 Fix compile on java 11. 2021-02-24 16:40:21 +08:00
Ben Woo c3ae5ac210 Merge pull request #2539 from Multiverse/disable_buscript
Add a Config Option to Disable Buscript
2021-02-24 14:12:35 +08:00
Ben Woo f4ce740c06 Merge pull request #2568 from Multiverse/fullname-face-direction
Add support for fullname face direction.
2021-02-24 14:09:56 +08:00
Kermina Awad 3ff8d34053 add config option to disable buscript 2021-02-23 14:38:54 -05:00
benwoo1110 f362f09380 Add support for fullname face direction.
So we can do `w:world:north` on top of the current ``w:world:n`.
2021-02-21 17:19:18 +08:00
benwoo1110 84a9db597a Add respawn anchor support. 2021-02-19 00:57:19 +08:00
benwoo1110 48601e4215 Fix cannot remove block currency with mvm set command.
Setting currency to 0 is now considered as no currency value.
2020-11-27 21:14:27 +08:00
29 changed files with 786 additions and 119 deletions

No files matched your search

+20 -16
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.onarandombox.multiversecore</groupId>
<artifactId>Multiverse-Core</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>4.2.3-SNAPSHOT</version>
<name>Multiverse-Core</name>
<description>World Management Plugin</description>
<properties>
@@ -22,6 +22,10 @@
<id>onarandombox</id>
<url>http://repo.onarandombox.com/content/groups/public</url>
</repository>
<repository>
<id>spigot</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>vault-repo</id>
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
@@ -211,7 +215,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
@@ -260,13 +264,19 @@
<plugin>
<groupId>se.eris</groupId>
<artifactId>notnull-instrumenter-maven-plugin</artifactId>
<version>0.6.8</version>
<version>1.0.0</version>
<executions>
<execution>
<goals>
<goal>instrument</goal>
<goal>tests-instrument</goal>
</goals>
<configuration>
<notNull>
<param>org.jetbrains.annotations.NotNull</param>
<param>javax.validation.constraints.NotNull</param>
</notNull>
</configuration>
</execution>
</executions>
</plugin>
@@ -275,10 +285,10 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- SerializationConfig Dependency -->
<dependency>
@@ -307,12 +317,6 @@
<artifactId>CommandHandler</artifactId>
<version>11</version>
</dependency>
<!-- End of CommandHandler Dependency -->
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.dumptruckman.minecraft</groupId>
<artifactId>buscript</artifactId>
@@ -355,21 +359,21 @@
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.0</version>
<version>2.0.9</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>2.0.0</version>
<version>2.0.9</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.0</version>
<version>2.0.9</version>
<type>jar</type>
<scope>test</scope>
</dependency>
@@ -20,20 +20,28 @@ import com.onarandombox.MultiverseCore.exceptions.PropertyDoesNotExistException;
import me.main__.util.SerializationConfig.ChangeDeniedException;
import me.main__.util.SerializationConfig.NoSuchPropertyException;
import me.main__.util.SerializationConfig.VirtualProperty;
import net.minidev.json.JSONObject;
import org.bukkit.*;
import org.bukkit.ChatColor;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldType;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.SerializableAs;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable;
import org.json.simple.JSONObject;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
/**
* The implementation of a Multiverse handled world.
@@ -68,6 +68,7 @@ import com.onarandombox.MultiverseCore.commands.TeleportCommand;
import com.onarandombox.MultiverseCore.commands.UnloadCommand;
import com.onarandombox.MultiverseCore.commands.VersionCommand;
import com.onarandombox.MultiverseCore.commands.WhoCommand;
import com.onarandombox.MultiverseCore.commandtools.queue.CommandQueueManager;
import com.onarandombox.MultiverseCore.destination.AnchorDestination;
import com.onarandombox.MultiverseCore.destination.BedDestination;
import com.onarandombox.MultiverseCore.destination.CannonDestination;
@@ -88,6 +89,7 @@ import com.onarandombox.MultiverseCore.listeners.MVWeatherListener;
import com.onarandombox.MultiverseCore.listeners.MVWorldInitListener;
import com.onarandombox.MultiverseCore.listeners.MVWorldListener;
import com.onarandombox.MultiverseCore.utils.AnchorManager;
import com.onarandombox.MultiverseCore.utils.CompatibilityLayer;
import com.onarandombox.MultiverseCore.utils.MVEconomist;
import com.onarandombox.MultiverseCore.utils.MVMessaging;
import com.onarandombox.MultiverseCore.utils.MVPermissions;
@@ -203,6 +205,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Setup our Map for our Commands using the CommandHandler.
private CommandHandler commandHandler;
private CommandQueueManager commandQueueManager;
private static final String LOG_TAG = "[Multiverse-Core]";
@@ -254,6 +257,8 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Setup our SafeTTeleporter
this.safeTTeleporter = new SimpleSafeTTeleporter(this);
this.unsafeCallWrapper = new UnsafeCallWrapper(this);
// Setup our CompatibilityLayer
CompatibilityLayer.init();
}
@@ -285,6 +290,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
// Setup the command manager
this.commandHandler = new CommandHandler(this, this.ph);
this.commandQueueManager = new CommandQueueManager(this);
// Call the Function to assign all the Commands to their Class.
this.registerCommands();
@@ -353,13 +359,16 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
* Initializes the buscript javascript library.
*/
private void initializeBuscript() {
try {
buscript = new Buscript(this);
// Add global variable "multiverse" to javascript environment
buscript.setScriptVariable("multiverse", this);
} catch (NullPointerException e) {
buscript = null;
Logging.warning("Buscript failed to load! The script command will be disabled!");
buscript = null;
if (this.getMVConfig().getEnableBuscript()) {
try {
buscript = new Buscript(this);
// Add global variable "multiverse" to javascript environment
buscript.setScriptVariable("multiverse", this);
} catch (NullPointerException e) {
Logging.warning("Buscript failed to load! The script command will be disabled!");
}
}
}
@@ -383,6 +392,7 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
pm.registerEvents(this.entityListener, this);
pm.registerEvents(this.weatherListener, this);
pm.registerEvents(this.portalListener, this);
Logging.info(ChatColor.GREEN + "We are aware of the warning about the deprecated event. There is no alternative that allows us to do what we need to do and performance impact is negligible. It is safe to ignore.");
pm.registerEvents(this.worldListener, this);
pm.registerEvents(new MVMapListener(this), this);
}
@@ -910,6 +920,15 @@ public class MultiverseCore extends JavaPlugin implements MVPlugin, Core {
return this.commandHandler;
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public CommandQueueManager getCommandQueueManager() {
return commandQueueManager;
}
/**
* Gets the log-tag.
*
@@ -56,6 +56,8 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
@Property
private volatile boolean displaypermerrors;
@Property
private volatile boolean enablebuscript;
@Property
private volatile int globaldebug;
@Property
private volatile boolean silentstart;
@@ -99,6 +101,7 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
teleportintercept = true;
firstspawnoverride = true;
displaypermerrors = true;
enablebuscript = true;
globaldebug = 0;
messagecooldown = 5000;
teleportcooldown = 1000;
@@ -213,6 +216,22 @@ public class MultiverseCoreConfiguration extends SerializationConfig implements
return this.displaypermerrors;
}
/**
* {@inheritDoc}
*/
@Override
public boolean getEnableBuscript() {
return this.enablebuscript;
}
/**
* {@inheritDoc}
*/
@Override
public void setEnableBuscript(boolean enableBuscript) {
this.enablebuscript = enableBuscript;
}
/**
* {@inheritDoc}
*/
@@ -8,6 +8,7 @@
package com.onarandombox.MultiverseCore.api;
import buscript.Buscript;
import com.onarandombox.MultiverseCore.commandtools.queue.CommandQueueManager;
import com.onarandombox.MultiverseCore.destination.DestinationFactory;
import com.onarandombox.MultiverseCore.utils.AnchorManager;
import com.onarandombox.MultiverseCore.utils.MVEconomist;
@@ -86,6 +87,15 @@ public interface Core {
*/
CommandHandler getCommandHandler();
/**
* Manager for command that requires /mv confirm before execution.
*
* @return A non-null {@link CommandQueueManager}.
* @deprecated To be moved to new command manager in 5.0.0
*/
@Deprecated
CommandQueueManager getCommandQueueManager();
/**
* Gets the factory class responsible for loading many different destinations
* on demand.
@@ -86,6 +86,18 @@ public interface MultiverseCoreConfig extends ConfigurationSerializable {
*/
boolean getDisplayPermErrors();
/**
* Sets enableBuscript.
* @param enableBuscript The new value.
*/
void setEnableBuscript(boolean enableBuscript);
/**
* Gets enableBuscript.
* @return enableBuscript.
*/
boolean getEnableBuscript();
/**
* Sets firstSpawnOverride.
* @param firstSpawnOverride The new value.
@@ -33,7 +33,7 @@ public class ConfirmCommand extends MultiverseCommand {
@Override
public void runCommand(CommandSender sender, List<String> args) {
this.plugin.getCommandHandler().confirmQueuedCommand(sender);
this.plugin.getCommandQueueManager().runQueuedCommand(sender);
}
}
@@ -8,9 +8,11 @@
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -35,11 +37,24 @@ public class DeleteCommand extends MultiverseCommand {
public void runCommand(CommandSender sender, List<String> args) {
String worldName = args.get(0);
Class<?>[] paramTypes = {String.class};
List<Object> objectArgs = new ArrayList<Object>(args);
this.plugin.getCommandHandler()
.queueCommand(sender, "mvdelete", "deleteWorld", objectArgs,
paramTypes, ChatColor.GREEN + "World '" + worldName + "' Deleted!",
ChatColor.RED + "World '" + worldName + "' could NOT be deleted!");
this.plugin.getCommandQueueManager().addToQueue(new QueuedCommand(
sender,
deleteRunnable(sender, worldName),
String.format("Are you sure you want to delete world '%s'? You cannot undo this action.", worldName)
));
}
private Runnable deleteRunnable(@NotNull CommandSender sender,
@NotNull String worldName) {
return () -> {
sender.sendMessage(String.format("Deleting world '%s'...", worldName));
if (this.plugin.getMVWorldManager().deleteWorld(worldName)) {
sender.sendMessage(String.format("%sWorld %s was deleted!", ChatColor.GREEN, worldName));
return;
}
sender.sendMessage(String.format("%sThere was an issue deleting '%s'! Please check console for errors.",
ChatColor.RED, worldName));
};
}
}
@@ -8,9 +8,11 @@
package com.onarandombox.MultiverseCore.commands;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.PermissionDefault;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -37,17 +39,30 @@ public class RegenCommand extends MultiverseCommand {
@Override
public void runCommand(CommandSender sender, List<String> args) {
Boolean useseed = (!(args.size() == 1));
Boolean randomseed = (args.size() == 2 && args.get(1).equalsIgnoreCase("-s"));
String worldName = args.get(0);
boolean useseed = (!(args.size() == 1));
boolean randomseed = (args.size() == 2 && args.get(1).equalsIgnoreCase("-s"));
String seed = (args.size() == 3) ? args.get(2) : "";
Class<?>[] paramTypes = {String.class, Boolean.class, Boolean.class, String.class};
List<Object> objectArgs = new ArrayList<Object>();
objectArgs.add(args.get(0));
objectArgs.add(useseed);
objectArgs.add(randomseed);
objectArgs.add(seed);
this.plugin.getCommandHandler().queueCommand(sender, "mvregen", "regenWorld", objectArgs,
paramTypes, ChatColor.GREEN + "World Regenerated!", ChatColor.RED + "World could NOT be regenerated!");
this.plugin.getCommandQueueManager().addToQueue(new QueuedCommand(
sender,
doWorldRegen(sender, worldName, useseed, randomseed, seed),
String.format("Are you sure you want to regen '%s'? You cannot undo this action.", worldName)
));
}
private Runnable doWorldRegen(@NotNull CommandSender sender,
@NotNull String worldName,
boolean useSeed,
boolean randomSeed,
@NotNull String seed) {
return () -> {
if (this.plugin.getMVWorldManager().regenWorld(worldName, useSeed, randomSeed, seed)) {
sender.sendMessage(ChatColor.GREEN + "World Regenerated!");
return;
}
sender.sendMessage(ChatColor.RED + "World could NOT be regenerated!");
};
}
}
@@ -11,6 +11,7 @@ import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.Teleporter;
import com.onarandombox.MultiverseCore.api.MVDestination;
import com.onarandombox.MultiverseCore.commandtools.queue.QueuedCommand;
import com.onarandombox.MultiverseCore.destination.CustomTeleporterDestination;
import com.onarandombox.MultiverseCore.destination.DestinationFactory;
import com.onarandombox.MultiverseCore.destination.InvalidDestination;
@@ -165,24 +166,27 @@ public class TeleportCommand extends MultiverseCommand {
if (result == TeleportResult.FAIL_UNSAFE) {
Logging.fine("Could not teleport " + teleportee.getName()
+ " to " + plugin.getLocationManipulation().strCoordsRaw(d.getLocation(teleportee)));
Logging.fine("Queueing Command");
Class<?>[] paramTypes = { CommandSender.class, Player.class, Location.class };
List<Object> items = new ArrayList<Object>();
items.add(teleporter);
items.add(teleportee);
items.add(d.getLocation(teleportee));
String player = "you";
if (!teleportee.equals(teleporter)) {
player = teleportee.getName();
}
String message = String.format("%sMultiverse %sdid not teleport %s%s %sto %s%s %sbecause it was unsafe.",
ChatColor.GREEN, ChatColor.WHITE, ChatColor.AQUA, player, ChatColor.WHITE, ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE);
this.plugin.getCommandHandler().queueCommand(sender, "mvteleport", "teleportPlayer", items,
paramTypes, message, "Would you like to try anyway?", "", "", UNSAFE_TELEPORT_EXPIRE_DELAY);
this.plugin.getCommandQueueManager().addToQueue(new QueuedCommand(
sender,
doUnsafeTeleport(teleporter, teleportee, d.getLocation(teleportee)),
String.format("%sMultiverse %sdid not teleport %s%s %sto %s%s %sbecause it was unsafe. Would you like to try anyway?",
ChatColor.GREEN, ChatColor.WHITE, ChatColor.AQUA, player, ChatColor.WHITE, ChatColor.DARK_AQUA, d.getName(), ChatColor.WHITE),
UNSAFE_TELEPORT_EXPIRE_DELAY
));
}
// else: Player was teleported successfully (or the tp event was fired I should say)
}
private Runnable doUnsafeTeleport(CommandSender teleporter, Player player, Location location) {
return () -> this.plugin.getSafeTTeleporter().safelyTeleport(teleporter, player, location, false);
}
private boolean checkSendPermissions(CommandSender teleporter, Player teleportee, MVDestination destination) {
if (teleporter.equals(teleportee)) {
if (!this.plugin.getMVPerms().hasPermission(teleporter, "multiverse.teleport.self." + destination.getIdentifier(), true)) {
@@ -64,6 +64,7 @@ public class VersionCommand extends MultiverseCommand {
+ "[Multiverse-Core] teleportintercept: " + plugin.getMVConfig().getTeleportIntercept() + '\n'
+ "[Multiverse-Core] firstspawnoverride: " + plugin.getMVConfig().getFirstSpawnOverride() + '\n'
+ "[Multiverse-Core] displaypermerrors: " + plugin.getMVConfig().getDisplayPermErrors() + '\n'
+ "[Multiverse-Core] enablebuscript: " + plugin.getMVConfig().getEnableBuscript() + '\n'
+ "[Multiverse-Core] globaldebug: " + plugin.getMVConfig().getGlobalDebug() + '\n'
+ "[Multiverse-Core] silentstart: " + plugin.getMVConfig().getSilentStart() + '\n'
+ "[Multiverse-Core] messagecooldown: " + plugin.getMessaging().getCooldown() + '\n'
@@ -0,0 +1,158 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2020. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commandtools.queue;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.block.data.type.CommandBlock;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.WeakHashMap;
/**
* Managers the queuing of dangerous commands that needs to use '/mv confirm' before executing.
*/
public class CommandQueueManager {
private static final long TICKS_PER_SECOND = 20;
private static final DummyCommandBlockSender COMMAND_BLOCK = new DummyCommandBlockSender();
private final MultiverseCore plugin;
private final Map<CommandSender, QueuedCommand> queuedCommandMap;
public CommandQueueManager(@NotNull MultiverseCore plugin) {
this.plugin = plugin;
this.queuedCommandMap = new WeakHashMap<>();
}
/**
* Adds a queue command into queue.
*
* @param queuedCommand The queue command to add.
*/
public void addToQueue(QueuedCommand queuedCommand) {
CommandSender targetSender = parseSender(queuedCommand.getSender());
// Since only one command is stored in queue per sender, we remove the old one.
this.removeFromQueue(targetSender);
Logging.finer("Add new command to queue for sender %s.", targetSender);
this.queuedCommandMap.put(targetSender, queuedCommand);
queuedCommand.setExpireTask(runExpireLater(queuedCommand));
queuedCommand.getSender().sendMessage(queuedCommand.getPrompt());
queuedCommand.getSender().sendMessage(String.format("Run %s/mv confirm %sto continue. This will expire in %s seconds.",
ChatColor.GREEN, ChatColor.WHITE, queuedCommand.getValidDuration()));
}
/**
* Expire task that remove {@link QueuedCommand} from queue after valid duration defined.
*
* @param queuedCommand Command to run the expire task on.
* @return The expire {@link BukkitTask}.
*/
@NotNull
private BukkitTask runExpireLater(@NotNull QueuedCommand queuedCommand) {
return Bukkit.getScheduler().runTaskLater(
this.plugin,
expireRunnable(queuedCommand),
queuedCommand.getValidDuration() * TICKS_PER_SECOND
);
}
/**
* Runnable responsible for expiring the queued command.
*
* @param queuedCommand Command to create the expire task on.
* @return The expire runnable.
*/
@NotNull
private Runnable expireRunnable(@NotNull QueuedCommand queuedCommand) {
return () -> {
CommandSender targetSender = parseSender(queuedCommand.getSender());
QueuedCommand matchingQueuedCommand = this.queuedCommandMap.get(targetSender);
if (!queuedCommand.equals(matchingQueuedCommand) || queuedCommand.getExpireTask().isCancelled()) {
// To be safe, but this shouldn't happen since we cancel old commands before add new once.
Logging.finer("This is an old queue command already.");
return;
}
queuedCommand.getSender().sendMessage("Your queued command has expired.");
this.queuedCommandMap.remove(queuedCommand.getSender());
};
}
/**
* Runs the command in queue for the given sender, if any.
*
* @param sender {@link CommandSender} that confirmed the command.
* @return True if queued command ran successfully, else false.
*/
public boolean runQueuedCommand(@NotNull CommandSender sender) {
CommandSender targetSender = parseSender(sender);
QueuedCommand queuedCommand = this.queuedCommandMap.get(targetSender);
if (queuedCommand == null) {
sender.sendMessage(ChatColor.RED + "You do not have any commands in queue.");
return false;
}
Logging.finer("Running queued command...");
queuedCommand.getAction().run();
return removeFromQueue(targetSender);
}
/**
* Since only one command is stored in queue per sender, we remove the old one.
*
* @param sender The {@link CommandSender} that executed the command.
* @return True if queue command is removed from sender successfully, else false.
*/
public boolean removeFromQueue(@NotNull CommandSender sender) {
CommandSender targetSender = parseSender(sender);
QueuedCommand previousCommand = this.queuedCommandMap.remove(targetSender);
if (previousCommand == null) {
Logging.finer("No queue command to remove for sender %s.", targetSender.getName());
return false;
}
previousCommand.getExpireTask().cancel();
Logging.finer("Removed queue command for sender %s.", targetSender.getName());
return true;
}
/**
* To allow all CommandBlocks to be a common sender with use of {@link DummyCommandBlockSender}.
* So confirm command can be used for a queue command on another command block.
*
* @param sender The sender to parse.
* @return The sender, or if its a command block, a {@link DummyCommandBlockSender}.
*/
@NotNull
private CommandSender parseSender(@NotNull CommandSender sender) {
Logging.fine(sender.getClass().getName());
if (isCommandBlock(sender)) {
Logging.finer("Is command block.");
return COMMAND_BLOCK;
}
return sender;
}
/**
* Check if sender is a command block.
*
* @param sender The sender to check on.
* @return True if sender is a command block, else false.
*/
private boolean isCommandBlock(@NotNull CommandSender sender) {
return sender instanceof BlockCommandSender
&& ((BlockCommandSender) sender).getBlock().getBlockData() instanceof CommandBlock;
}
}
@@ -0,0 +1,104 @@
package com.onarandombox.MultiverseCore.commandtools.queue;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
/**
* Used by {@link CommandQueueManager}, so different commands block can be recognised as one.
*/
class DummyCommandBlockSender implements CommandSender {
@Override
public void sendMessage(@NotNull String message) {
throw new UnsupportedOperationException();
}
@Override
public void sendMessage(@NotNull String[] messages) {
throw new UnsupportedOperationException();
}
@Override
public @NotNull Server getServer() {
return Bukkit.getServer();
}
@Override
public @NotNull String getName() {
return "DummyCommandBlockSender";
}
@Override
public boolean isPermissionSet(@NotNull String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean isPermissionSet(@NotNull Permission perm) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasPermission(@NotNull String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasPermission(@NotNull Permission perm) {
throw new UnsupportedOperationException();
}
@Override
public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value) {
throw new UnsupportedOperationException();
}
@Override
public @NotNull PermissionAttachment addAttachment(@NotNull Plugin plugin) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, @NotNull String name, boolean value, int ticks) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable PermissionAttachment addAttachment(@NotNull Plugin plugin, int ticks) {
throw new UnsupportedOperationException();
}
@Override
public void removeAttachment(@NotNull PermissionAttachment attachment) {
throw new UnsupportedOperationException();
}
@Override
public void recalculatePermissions() {
throw new UnsupportedOperationException();
}
@Override
public @NotNull Set<PermissionAttachmentInfo> getEffectivePermissions() {
throw new UnsupportedOperationException();
}
@Override
public boolean isOp() {
return true;
}
@Override
public void setOp(boolean value) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,86 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2020. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.commandtools.queue;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
/**
* Represents a single command used in {@link CommandQueueManager} for confirming before running potentially
* dangerous action.
*/
public class QueuedCommand {
private static final String DEFAULT_PROMPT_MESSAGE = "The command you are trying to run is deemed dangerous.";
private static final int DEFAULT_VALID_TIME = 10;
private final CommandSender sender;
private final Runnable action;
private final String prompt;
private final int validDuration;
private BukkitTask expireTask;
public QueuedCommand(CommandSender sender, Runnable action) {
this(sender, action, DEFAULT_PROMPT_MESSAGE, DEFAULT_VALID_TIME);
}
public QueuedCommand(CommandSender sender, Runnable action, String prompt) {
this(sender, action, prompt, DEFAULT_VALID_TIME);
}
public QueuedCommand(CommandSender sender, Runnable action, int validDuration) {
this(sender, action, DEFAULT_PROMPT_MESSAGE, validDuration);
}
/**
* Creates a new queue command, to be registered at {@link CommandQueueManager#addToQueue(QueuedCommand)}.
*
* @param sender The sender that ran the command needed for confirmation.
* @param action The logic to execute upon confirming.
* @param prompt Question to ask sender to confirm.
* @param validDuration Duration in which the command is valid for confirm in seconds.
*/
public QueuedCommand(CommandSender sender, Runnable action, String prompt, int validDuration) {
this.sender = sender;
this.action = action;
this.prompt = prompt;
this.validDuration = validDuration;
}
@NotNull
CommandSender getSender() {
return sender;
}
@NotNull
String getPrompt() {
return prompt;
}
int getValidDuration() {
return validDuration;
}
@NotNull
Runnable getAction() {
return action;
}
@NotNull
BukkitTask getExpireTask() {
return expireTask;
}
void setExpireTask(@NotNull BukkitTask expireTask) {
if (this.expireTask != null) {
throw new IllegalStateException("This queue command already has an expire task. You can't register twice!");
}
this.expireTask = expireTask;
}
}
@@ -0,0 +1,4 @@
/**
* Manager queuing of dangerous commands in need of confirmation.
*/
package com.onarandombox.MultiverseCore.commandtools.queue;
@@ -22,6 +22,8 @@ public class EntryFee extends SerializationConfig {
@Nullable
private Material currency;
private final Material DISABLED_MATERIAL = Material.AIR;
public EntryFee() {
super();
}
@@ -51,6 +53,9 @@ public class EntryFee extends SerializationConfig {
*/
@Nullable
public Material getCurrency() {
if (currency == null || currency.equals(DISABLED_MATERIAL)) {
return null;
}
return currency;
}
@@ -0,0 +1,7 @@
package com.onarandombox.MultiverseCore.enums;
public enum RespawnType {
BED,
ANCHOR,
OTHER
}
@@ -15,7 +15,9 @@ import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import com.onarandombox.MultiverseCore.enums.RespawnType;
import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.utils.CompatibilityLayer;
import com.onarandombox.MultiverseCore.utils.PermissionTools;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -69,9 +71,16 @@ public class MVPlayerListener implements Listener {
return;
}
RespawnType respawnType = RespawnType.OTHER;
if (event.isBedSpawn()) {
respawnType = RespawnType.BED;
}
if (CompatibilityLayer.isAnchorSpawn(event)) {
respawnType = RespawnType.ANCHOR;
}
if (mvWorld.getBedRespawn() && event.isBedSpawn()) {
Logging.fine("Spawning " + event.getPlayer().getName() + " at their bed");
if (mvWorld.getBedRespawn() && (respawnType == RespawnType.BED || respawnType == RespawnType.ANCHOR)) {
Logging.fine("Spawning %s at their %s", event.getPlayer().getName(), respawnType);
return;
}
@@ -305,7 +314,15 @@ public class MVPlayerListener implements Listener {
+ "' because enforceaccess is off.");
}
if (!plugin.getMVConfig().isUsingDefaultPortalSearch()) {
event.setSearchRadius(this.plugin.getMVConfig().getPortalSearchRadius());
try {
Class.forName("org.bukkit.TravelAgent");
if (event.getPortalTravelAgent() != null) {
event.getPortalTravelAgent().setSearchRadius(plugin.getMVConfig().getPortalSearchRadius());
}
} catch (ClassNotFoundException ignore) {
Logging.fine("TravelAgent not available for PlayerPortalEvent for " + event.getPlayer().getName());
}
}
}
@@ -12,7 +12,6 @@ import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MultiverseWorld;
import org.bukkit.Material;
import org.bukkit.PortalType;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
@@ -34,48 +33,31 @@ public class MVPortalListener implements Listener {
}
/**
* This is called when a portal is formed.
* @param event The event where a portal was create or formed due to a world link
* This is called when an entity creates a portal.
*
* @param event The event where an entity created a portal.
*/
@EventHandler
public void entityPortalCreate(EntityCreatePortalEvent event) {
if (event.isCancelled() || event.getBlocks().size() == 0) {
return;
}
MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(event.getEntity().getWorld());
// We have to do it like this due to a bug in 1.1-R3
if (world != null && !world.getAllowedPortals().isPortalAllowed(event.getPortalType())) {
event.setCancelled(true);
}
}
/**
* This is called when a portal is created as the result of another world being linked.
* @param event The event where a portal was formed due to a world link
*/
@EventHandler(ignoreCancelled = true)
public void portalForm(PortalCreateEvent event) {
Logging.fine("Attempting to create portal at '%s' with reason: %s", event.getWorld().getName(), event.getReason());
MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(event.getWorld());
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PortalCreateEvent.", event.getWorld().getName());
return;
}
PortalType targetType;
switch (event.getReason()) {
case FIRE:
// Ensure portal by flint and steel actually creates nether
boolean isNether = false;
for (BlockState block : event.getBlocks()) {
if (block.getType() == Material.NETHER_PORTAL) {
isNether = true;
break;
}
}
if (!isNether) {
return;
}
targetType = PortalType.NETHER;
break;
case NETHER_PAIR:
targetType = PortalType.NETHER;
break;
case END_PLATFORM:
targetType = PortalType.ENDER;
break;
default:
Logging.fine("Portal created is not NETHER or ENDER type. Ignoring...");
return;
}
if (!world.getAllowedPortals().isPortalAllowed(targetType)) {
Logging.fine("Cancelling creation of %s portal because portalForm disallows.", targetType);
if (world != null && !world.getAllowedPortals().isPortalAllowed(PortalType.NETHER)) {
Logging.fine("Cancelling creation of nether portal because portalForm disallows.");
event.setCancelled(true);
}
}
@@ -90,21 +72,15 @@ public class MVPortalListener implements Listener {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.END_PORTAL_FRAME) {
if (event.getClickedBlock().getType() != Material.END_PORTAL_FRAME) {
return;
}
if (event.getItem() == null || event.getItem().getType() != Material.ENDER_EYE) {
return;
}
MultiverseWorld world = this.plugin.getMVWorldManager().getMVWorld(event.getPlayer().getWorld());
if (world == null) {
Logging.fine("World '%s' is not managed by Multiverse! Ignoring at PlayerInteractEvent.", event.getPlayer().getWorld().getName());
return;
}
if (!world.getAllowedPortals().isPortalAllowed(PortalType.ENDER)) {
Logging.fine("Cancelling creation of ENDER portal because portalForm disallows.");
if (world != null && !world.getAllowedPortals().isPortalAllowed(PortalType.ENDER)) {
Logging.fine("Cancelling creation of ender portal because portalForm disallows.");
event.setCancelled(true);
}
}
@@ -0,0 +1,111 @@
package com.onarandombox.MultiverseCore.utils;
import java.util.logging.Level;
import com.dumptruckman.minecraft.util.Logging;
import com.onarandombox.MultiverseCore.api.SafeTTeleporter;
import com.onarandombox.MultiverseCore.destination.CannonDestination;
import org.bukkit.Location;
import org.bukkit.TravelAgent;
import org.bukkit.event.player.PlayerPortalEvent;
public class BukkitTravelAgent implements TravelAgent {
private final MVTravelAgent agent;
public BukkitTravelAgent(MVTravelAgent agent) {
this.agent = agent;
}
/**
* {@inheritDoc}
*/
@Override
public BukkitTravelAgent setSearchRadius(int radius) {
return this;
}
/**
* {@inheritDoc}
*/
@Override
public int getSearchRadius() {
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public BukkitTravelAgent setCreationRadius(int radius) {
return this;
}
/**
* {@inheritDoc}
*/
@Override
public int getCreationRadius() {
return 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean getCanCreatePortal() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void setCanCreatePortal(boolean create) {
}
/**
* {@inheritDoc}
*/
@Override
public Location findOrCreate(Location location) {
return this.getSafeLocation();
}
/**
* {@inheritDoc}
*/
@Override
public Location findPortal(Location location) {
return this.getSafeLocation();
}
/**
* {@inheritDoc}
*/
@Override
public boolean createPortal(Location location) {
return false;
}
private Location getSafeLocation() {
// At this time, these can never use the velocity.
if (agent.destination instanceof CannonDestination) {
Logging.fine("Using Stock TP method. This cannon will have 0 velocity");
}
SafeTTeleporter teleporter = agent.core.getSafeTTeleporter();
Location newLoc = agent.destination.getLocation(agent.player);
if (agent.destination.useSafeTeleporter()) {
newLoc = teleporter.getSafeLocation(agent.player, agent.destination);
}
if (newLoc == null) {
return agent.player.getLocation();
}
return newLoc;
}
public void setPortalEventTravelAgent(PlayerPortalEvent event) {
event.setPortalTravelAgent(this);
event.useTravelAgent(true);
}
}
@@ -0,0 +1,46 @@
package com.onarandombox.MultiverseCore.utils;
import com.dumptruckman.minecraft.util.Logging;
import org.bukkit.Bukkit;
import org.bukkit.event.player.PlayerRespawnEvent;
import java.lang.reflect.Method;
/**
* A utility class to enable version specific minecraft features.
*/
public class CompatibilityLayer {
private static Method checkAnchorSpawn;
/**
* Initialise the reflection methods.
*/
public static void init() {
try {
checkAnchorSpawn = PlayerRespawnEvent.class.getDeclaredMethod("isAnchorSpawn");
} catch (NoSuchMethodException e) {
Logging.fine("%s does not support respawn anchors.", Bukkit.getVersion());
}
}
/**
* Check if the respawn point is of respawn anchor type.
* Introduced in minecraft 1.16
*
* @param event A player respawn event.
* @return If the respawn location is an anchor point.
*/
public static boolean isAnchorSpawn(PlayerRespawnEvent event) {
if (checkAnchorSpawn == null) {
return false;
}
try {
return (boolean) checkAnchorSpawn.invoke(event);
} catch (Exception e) {
Logging.warning("Error checking for: %s", checkAnchorSpawn);
e.printStackTrace();
}
return false;
}
}
@@ -0,0 +1,27 @@
/******************************************************************************
* Multiverse 2 Copyright (c) the Multiverse Team 2011. *
* Multiverse 2 is licensed under the BSD License. *
* For more information please check the README.md file included *
* with this project. *
******************************************************************************/
package com.onarandombox.MultiverseCore.utils;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVDestination;
import org.bukkit.entity.Player;
/**
* The Multiverse TravelAgent.
*/
public class MVTravelAgent {
protected MVDestination destination;
protected MultiverseCore core;
protected Player player;
public MVTravelAgent(MultiverseCore multiverseCore, MVDestination d, Player p) {
this.destination = d;
this.core = multiverseCore;
this.player = p;
}
}
@@ -40,6 +40,15 @@ public class SimpleLocationManipulation implements LocationManipulation {
orientationInts.put("w", 90);
orientationInts.put("nw", 135);
orientationInts.put("north", 180);
orientationInts.put("northeast", 225);
orientationInts.put("east", 270);
orientationInts.put("southeast", 315);
orientationInts.put("south", 0);
orientationInts.put("southwest", 45);
orientationInts.put("west", 90);
orientationInts.put("northwest", 135);
// "freeze" the map:
ORIENTATION_INTS = Collections.unmodifiableMap(orientationInts);
// END CHECKSTYLE-SUPPRESSION: MagicNumberCheck
@@ -1,8 +1,8 @@
package com.onarandombox.MultiverseCore.utils.webpaste;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import java.util.Map;
@@ -1,8 +1,8 @@
package com.onarandombox.MultiverseCore.utils.webpaste;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import java.util.HashMap;
@@ -1,9 +1,8 @@
package com.onarandombox.MultiverseCore.utils.webpaste;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import java.util.Map;
@@ -1,9 +1,9 @@
package com.onarandombox.MultiverseCore.utils.webpaste;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import java.util.HashMap;
@@ -50,6 +50,10 @@ public class TestEntryFeeConversion {
WorldProperties props = new WorldProperties(config);
assertNull(props.entryfee.getCurrency());
entryFee.put("currency", 0);
props = new WorldProperties(config);
assertNull(props.entryfee.getCurrency());
entryFee.put("currency", 1);
props = new WorldProperties(config);
assertEquals(Material.STONE, props.entryfee.getCurrency());
@@ -214,11 +214,18 @@ public class TestInstanceCreator {
serverfield.set(core, mockServer);
// Set buscript
Buscript buscript = PowerMockito.spy(new Buscript(core));
Buscript buscript;
Field buscriptfield = MultiverseCore.class.getDeclaredField("buscript");
buscriptfield.setAccessible(true);
try {
buscript = PowerMockito.spy(new Buscript(core));
when(buscript.getPlugin()).thenReturn(core);
} catch (NullPointerException e) {
buscript = null;
}
buscriptfield.set(core, buscript);
when(buscript.getPlugin()).thenReturn(core);
// Set worldManager
WorldManager wm = PowerMockito.spy(new WorldManager(core));