mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Rewrite session code and add support for persistent sessions.
This commit is contained in:
parent
e95eeefa2b
commit
aaeaf19fc8
@ -19,19 +19,27 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.bukkit;
|
package com.sk89q.worldedit.bukkit;
|
||||||
|
|
||||||
import com.sk89q.worldedit.WorldEditPermissionException;
|
import com.sk89q.worldedit.session.SessionKey;
|
||||||
|
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
public class BukkitCommandSender implements Actor {
|
public class BukkitCommandSender implements Actor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One time generated ID.
|
||||||
|
*/
|
||||||
|
private static final UUID DEFAULT_ID = UUID.fromString("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be");
|
||||||
|
|
||||||
private CommandSender sender;
|
private CommandSender sender;
|
||||||
private WorldEditPlugin plugin;
|
private WorldEditPlugin plugin;
|
||||||
|
|
||||||
@ -44,6 +52,11 @@ public class BukkitCommandSender implements Actor {
|
|||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return DEFAULT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return sender.getName();
|
return sender.getName();
|
||||||
@ -93,7 +106,7 @@ public class BukkitCommandSender implements Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkPermission(String permission) throws WorldEditPermissionException {
|
public void checkPermission(String permission) throws AuthorizationException {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -115,4 +128,29 @@ public class BukkitCommandSender implements Actor {
|
|||||||
public void dispatchCUIEvent(CUIEvent event) {
|
public void dispatchCUIEvent(CUIEvent event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionKey getSessionKey() {
|
||||||
|
return new SessionKey() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPersistent() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return DEFAULT_ID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,18 @@ import com.sk89q.worldedit.blocks.BaseBlock;
|
|||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
|
import com.sk89q.worldedit.session.SessionKey;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class BukkitPlayer extends LocalPlayer {
|
public class BukkitPlayer extends LocalPlayer {
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
private WorldEditPlugin plugin;
|
private WorldEditPlugin plugin;
|
||||||
|
|
||||||
@ -46,6 +50,11 @@ public class BukkitPlayer extends LocalPlayer {
|
|||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return player.getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemInHand() {
|
public int getItemInHand() {
|
||||||
ItemStack itemStack = player.getItemInHand();
|
ItemStack itemStack = player.getItemInHand();
|
||||||
@ -192,4 +201,48 @@ public class BukkitPlayer extends LocalPlayer {
|
|||||||
public <T> T getFacet(Class<? extends T> cls) {
|
public <T> T getFacet(Class<? extends T> cls) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionKey getSessionKey() {
|
||||||
|
return new SessionKeyImpl(this.player.getUniqueId(), player.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SessionKeyImpl implements SessionKey {
|
||||||
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
|
private final UUID uuid;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private SessionKeyImpl(UUID uuid, String name) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
// This is a thread safe call on CraftBukkit because it uses a
|
||||||
|
// CopyOnWrite list for the list of players, but the Bukkit
|
||||||
|
// specification doesn't require thread safety (though the
|
||||||
|
// spec is extremely incomplete)
|
||||||
|
return Bukkit.getServer().getPlayerExact(name) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPersistent() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ import org.bukkit.event.block.Action;
|
|||||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles all events thrown in relation to a Player
|
* Handles all events thrown in relation to a Player
|
||||||
@ -62,20 +61,6 @@ public class WorldEditListener implements Listener {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player leaves a server
|
|
||||||
*
|
|
||||||
* @param event Relevant event details
|
|
||||||
*/
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
if (!plugin.getInternalPlatform().isHookingEvents()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin.getWorldEdit().markExpire(plugin.wrapPlayer(event.getPlayer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onGamemode(PlayerGameModeChangeEvent event) {
|
public void onGamemode(PlayerGameModeChangeEvent event) {
|
||||||
if (!plugin.getInternalPlatform().isHookingEvents()) {
|
if (!plugin.getInternalPlatform().isHookingEvents()) {
|
||||||
|
@ -110,9 +110,6 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
// Now we can register events
|
// Now we can register events
|
||||||
getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
|
getServer().getPluginManager().registerEvents(new WorldEditListener(this), this);
|
||||||
|
|
||||||
// Register session timer
|
|
||||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new SessionTimer(worldEdit, getServer()), 120, 120);
|
|
||||||
|
|
||||||
// If we are on MCPC+/Cauldron, then Forge will have already loaded
|
// If we are on MCPC+/Cauldron, then Forge will have already loaded
|
||||||
// Forge WorldEdit and there's (probably) not going to be any other
|
// Forge WorldEdit and there's (probably) not going to be any other
|
||||||
// platforms to be worried about... at the current time of writing
|
// platforms to be worried about... at the current time of writing
|
||||||
|
@ -27,6 +27,7 @@ import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
|||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
|
import com.sk89q.worldedit.session.SessionKey;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@ -34,6 +35,7 @@ import net.minecraft.network.packet.Packet250CustomPayload;
|
|||||||
import net.minecraft.util.ChatMessageComponent;
|
import net.minecraft.util.ChatMessageComponent;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ForgePlayer extends AbstractPlayerActor {
|
public class ForgePlayer extends AbstractPlayerActor {
|
||||||
|
|
||||||
@ -41,13 +43,21 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
|
|
||||||
protected ForgePlayer(EntityPlayerMP player) {
|
protected ForgePlayer(EntityPlayerMP player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return player.getUniqueID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getItemInHand() {
|
public int getItemInHand() {
|
||||||
ItemStack is = this.player.getCurrentEquippedItem();
|
ItemStack is = this.player.getCurrentEquippedItem();
|
||||||
return is == null ? 0 : is.itemID;
|
return is == null ? 0 : is.itemID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.player.username;
|
return this.player.username;
|
||||||
}
|
}
|
||||||
@ -67,26 +77,32 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
this.player.cameraPitch);
|
this.player.cameraPitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public WorldVector getPosition() {
|
public WorldVector getPosition() {
|
||||||
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
return new WorldVector(LocalWorldAdapter.adapt(ForgeWorldEdit.inst.getWorld(this.player.worldObj)), this.player.posX, this.player.posY, this.player.posZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public com.sk89q.worldedit.world.World getWorld() {
|
public com.sk89q.worldedit.world.World getWorld() {
|
||||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double getPitch() {
|
public double getPitch() {
|
||||||
return this.player.rotationPitch;
|
return this.player.rotationPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double getYaw() {
|
public double getYaw() {
|
||||||
return this.player.rotationYaw;
|
return this.player.rotationYaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void giveItem(int type, int amt) {
|
public void giveItem(int type, int amt) {
|
||||||
this.player.inventory.addItemStackToInventory(new ItemStack(type, amt, 0));
|
this.player.inventory.addItemStackToInventory(new ItemStack(type, amt, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dispatchCUIEvent(CUIEvent event) {
|
public void dispatchCUIEvent(CUIEvent event) {
|
||||||
String[] params = event.getParameters();
|
String[] params = event.getParameters();
|
||||||
String send = event.getTypeId();
|
String send = event.getTypeId();
|
||||||
@ -97,42 +113,50 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
this.player.playerNetServerHandler.sendPacketToPlayer(packet);
|
this.player.playerNetServerHandler.sendPacketToPlayer(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void printRaw(String msg) {
|
public void printRaw(String msg) {
|
||||||
for (String part : msg.split("\n")) {
|
for (String part : msg.split("\n")) {
|
||||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText(part));
|
this.player.sendChatToPlayer(ChatMessageComponent.createFromText(part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void printDebug(String msg) {
|
public void printDebug(String msg) {
|
||||||
for (String part : msg.split("\n")) {
|
for (String part : msg.split("\n")) {
|
||||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a77" + part));
|
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a77" + part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void print(String msg) {
|
public void print(String msg) {
|
||||||
for (String part : msg.split("\n")) {
|
for (String part : msg.split("\n")) {
|
||||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7d" + part));
|
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7d" + part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void printError(String msg) {
|
public void printError(String msg) {
|
||||||
for (String part : msg.split("\n")) {
|
for (String part : msg.split("\n")) {
|
||||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7c" + part));
|
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7c" + part));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||||
this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), pitch, yaw);
|
this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), pitch, yaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String[] getGroups() {
|
public String[] getGroups() {
|
||||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public BlockBag getInventoryBlockBag() {
|
public BlockBag getInventoryBlockBag() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean hasPermission(String perm) {
|
public boolean hasPermission(String perm) {
|
||||||
return ForgeUtil.hasPermission(this.player, perm);
|
return ForgeUtil.hasPermission(this.player, perm);
|
||||||
}
|
}
|
||||||
@ -143,4 +167,45 @@ public class ForgePlayer extends AbstractPlayerActor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionKey getSessionKey() {
|
||||||
|
return new SessionKeyImpl(player.getUniqueID(), player.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SessionKeyImpl implements SessionKey {
|
||||||
|
// If not static, this will leak a reference
|
||||||
|
|
||||||
|
private final UUID uuid;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private SessionKeyImpl(UUID uuid, String name) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
// We can't directly check if the player is online because
|
||||||
|
// the list of players is not thread safe
|
||||||
|
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPersistent() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -32,8 +32,15 @@ import cpw.mods.fml.common.FMLLog;
|
|||||||
import cpw.mods.fml.common.Mod;
|
import cpw.mods.fml.common.Mod;
|
||||||
import cpw.mods.fml.common.Mod.EventHandler;
|
import cpw.mods.fml.common.Mod.EventHandler;
|
||||||
import cpw.mods.fml.common.Mod.Instance;
|
import cpw.mods.fml.common.Mod.Instance;
|
||||||
import cpw.mods.fml.common.event.*;
|
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLServerAboutToStartEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLServerStartedEvent;
|
||||||
|
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||||
import cpw.mods.fml.common.network.NetworkMod;
|
import cpw.mods.fml.common.network.NetworkMod;
|
||||||
|
import cpw.mods.fml.common.registry.TickRegistry;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
@ -84,6 +91,8 @@ public class ForgeWorldEdit {
|
|||||||
|
|
||||||
config = new ForgeConfiguration(this);
|
config = new ForgeConfiguration(this);
|
||||||
config.load();
|
config.load();
|
||||||
|
|
||||||
|
TickRegistry.registerTickHandler(ThreadSafeCache.getInstance(), Side.SERVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.forge;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
|
import cpw.mods.fml.common.ITickHandler;
|
||||||
|
import cpw.mods.fml.common.TickType;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches data that cannot be accessed from another thread safely.
|
||||||
|
*/
|
||||||
|
class ThreadSafeCache implements ITickHandler {
|
||||||
|
|
||||||
|
private static final long REFRESH_DELAY = 1000 * 30;
|
||||||
|
private static final ThreadSafeCache INSTANCE = new ThreadSafeCache();
|
||||||
|
private Set<UUID> onlineIds = Collections.emptySet();
|
||||||
|
private long lastRefresh = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an concurrent-safe set of UUIDs of online players.
|
||||||
|
*
|
||||||
|
* @return a set of UUIDs
|
||||||
|
*/
|
||||||
|
public Set<UUID> getOnlineIds() {
|
||||||
|
return onlineIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tickStart(EnumSet<TickType> type, Object... tickData) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (now - lastRefresh > REFRESH_DELAY) {
|
||||||
|
Set<UUID> onlineIds = new HashSet<UUID>();
|
||||||
|
|
||||||
|
for (Object object : FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().playerEntityList) {
|
||||||
|
if (object != null) {
|
||||||
|
EntityPlayerMP player = (EntityPlayerMP) object;
|
||||||
|
onlineIds.add(player.getUniqueID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onlineIds = new CopyOnWriteArraySet<UUID>(onlineIds);
|
||||||
|
|
||||||
|
lastRefresh = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tickEnd(EnumSet<TickType> type, Object... tickData) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnumSet<TickType> ticks() {
|
||||||
|
return EnumSet.of(TickType.SERVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLabel() {
|
||||||
|
return "WorldEdit Cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ThreadSafeCache getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -40,9 +40,6 @@ import com.sk89q.worldedit.regions.RegionSelector;
|
|||||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||||
import com.sk89q.worldedit.session.request.Request;
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
|
||||||
import com.sk89q.worldedit.util.formatting.Style;
|
|
||||||
import com.sk89q.worldedit.util.formatting.StyledFragment;
|
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||||
|
|
||||||
@ -52,57 +49,102 @@ import java.util.HashMap;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of this represents the WorldEdit session of a user. A session
|
* Stores session information.
|
||||||
* stores history and settings. Sessions are not tied particularly to any
|
|
||||||
* player and can be shuffled between players, saved, and loaded.
|
|
||||||
*
|
|
||||||
* @author sk89q
|
|
||||||
*/
|
*/
|
||||||
public class LocalSession {
|
public class LocalSession {
|
||||||
|
|
||||||
private static final boolean SHOW_HELP_MESSAGE = false;
|
public transient static int MAX_HISTORY_SIZE = 15;
|
||||||
|
|
||||||
public static int MAX_HISTORY_SIZE = 15;
|
// Non-session related fields
|
||||||
public static int EXPIRATION_GRACE = 600000;
|
private transient LocalConfiguration config;
|
||||||
|
private transient final AtomicBoolean dirty = new AtomicBoolean();
|
||||||
|
|
||||||
private LocalConfiguration config;
|
// Session related
|
||||||
|
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||||
|
private transient boolean placeAtPos1 = false;
|
||||||
|
private transient LinkedList<EditSession> history = new LinkedList<EditSession>();
|
||||||
|
private transient int historyPointer = 0;
|
||||||
|
private transient ClipboardHolder clipboard;
|
||||||
|
private transient boolean toolControl = true;
|
||||||
|
private transient boolean superPickaxe = false;
|
||||||
|
private transient BlockTool pickaxeMode = new SinglePickaxe();
|
||||||
|
private transient Map<Integer, Tool> tools = new HashMap<Integer, Tool>();
|
||||||
|
private transient int maxBlocksChanged = -1;
|
||||||
|
private transient boolean useInventory;
|
||||||
|
private transient Snapshot snapshot;
|
||||||
|
private transient boolean hasCUISupport = false;
|
||||||
|
private transient int cuiVersion = -1;
|
||||||
|
private transient boolean fastMode = false;
|
||||||
|
private transient Mask mask;
|
||||||
|
private transient TimeZone timezone = TimeZone.getDefault();
|
||||||
|
|
||||||
private long expirationTime = System.currentTimeMillis() + EXPIRATION_GRACE;
|
// Saved properties
|
||||||
private RegionSelector selector = new CuboidRegionSelector();
|
|
||||||
private boolean placeAtPos1 = false;
|
|
||||||
private LinkedList<EditSession> history = new LinkedList<EditSession>();
|
|
||||||
private int historyPointer = 0;
|
|
||||||
private ClipboardHolder clipboard;
|
|
||||||
private boolean toolControl = true;
|
|
||||||
private boolean superPickaxe = false;
|
|
||||||
private BlockTool pickaxeMode = new SinglePickaxe();
|
|
||||||
private Map<Integer, Tool> tools = new HashMap<Integer, Tool>();
|
|
||||||
private int maxBlocksChanged = -1;
|
|
||||||
private boolean useInventory;
|
|
||||||
private Snapshot snapshot;
|
|
||||||
private String lastScript;
|
private String lastScript;
|
||||||
private boolean beenToldVersion = false;
|
|
||||||
private boolean hasCUISupport = false;
|
|
||||||
private int cuiVersion = -1;
|
|
||||||
private boolean fastMode = false;
|
|
||||||
private Mask mask;
|
|
||||||
private TimeZone timezone = TimeZone.getDefault();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the object.
|
* Construct the object.
|
||||||
*
|
*
|
||||||
* @param config
|
* <p>{@link #setConfiguration(LocalConfiguration)} should be called
|
||||||
|
* later with configuration.</p>
|
||||||
*/
|
*/
|
||||||
public LocalSession(LocalConfiguration config) {
|
public LocalSession() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the object.
|
||||||
|
*
|
||||||
|
* @param config the configuration
|
||||||
|
*/
|
||||||
|
public LocalSession(@Nullable LocalConfiguration config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the configuration.
|
||||||
|
*
|
||||||
|
* @param config the configuration
|
||||||
|
*/
|
||||||
|
public void setConfiguration(LocalConfiguration config) {
|
||||||
|
checkNotNull(config);
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether this session is "dirty" and has changes that needs to
|
||||||
|
* be committed.
|
||||||
|
*
|
||||||
|
* @return true if dirty
|
||||||
|
*/
|
||||||
|
public boolean isDirty() {
|
||||||
|
return dirty.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this session as dirty.
|
||||||
|
*/
|
||||||
|
private void setDirty() {
|
||||||
|
dirty.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether this session is "dirty" and has changes that needs to
|
||||||
|
* be committed, and reset it to {@code false}.
|
||||||
|
*
|
||||||
|
* @return true if the dirty value was {@code true}
|
||||||
|
*/
|
||||||
|
public boolean compareAndResetDirty() {
|
||||||
|
return dirty.compareAndSet(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the session's timezone.
|
* Get the session's timezone.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the timezone
|
||||||
*/
|
*/
|
||||||
public TimeZone getTimeZone() {
|
public TimeZone getTimeZone() {
|
||||||
return timezone;
|
return timezone;
|
||||||
@ -111,9 +153,10 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the session's timezone.
|
* Set the session's timezone.
|
||||||
*
|
*
|
||||||
* @param timezone
|
* @param timezone the user's timezone
|
||||||
*/
|
*/
|
||||||
public void setTimezone(TimeZone timezone) {
|
public void setTimezone(TimeZone timezone) {
|
||||||
|
checkNotNull(timezone);
|
||||||
this.timezone = timezone;
|
this.timezone = timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +172,11 @@ public class LocalSession {
|
|||||||
* Remember an edit session for the undo history. If the history maximum
|
* Remember an edit session for the undo history. If the history maximum
|
||||||
* size is reached, old edit sessions will be discarded.
|
* size is reached, old edit sessions will be discarded.
|
||||||
*
|
*
|
||||||
* @param editSession
|
* @param editSession the edit session
|
||||||
*/
|
*/
|
||||||
public void remember(EditSession editSession) {
|
public void remember(EditSession editSession) {
|
||||||
|
checkNotNull(editSession);
|
||||||
|
|
||||||
// Don't store anything if no changes were made
|
// Don't store anything if no changes were made
|
||||||
if (editSession.size() == 0) return;
|
if (editSession.size() == 0) return;
|
||||||
|
|
||||||
@ -149,8 +194,8 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Performs an undo.
|
* Performs an undo.
|
||||||
*
|
*
|
||||||
* @param newBlockBag
|
* @param newBlockBag a new block bag
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return whether anything was undone
|
* @return whether anything was undone
|
||||||
*/
|
*/
|
||||||
public EditSession undo(BlockBag newBlockBag, LocalPlayer player) {
|
public EditSession undo(BlockBag newBlockBag, LocalPlayer player) {
|
||||||
@ -160,11 +205,13 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Performs an undo.
|
* Performs an undo.
|
||||||
*
|
*
|
||||||
* @param newBlockBag
|
* @param newBlockBag a new block bag
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return whether anything was undone
|
* @return whether anything was undone
|
||||||
*/
|
*/
|
||||||
public EditSession undo(BlockBag newBlockBag, Player player) {
|
public EditSession undo(BlockBag newBlockBag, Player player) {
|
||||||
|
checkNotNull(newBlockBag);
|
||||||
|
checkNotNull(player);
|
||||||
--historyPointer;
|
--historyPointer;
|
||||||
if (historyPointer >= 0) {
|
if (historyPointer >= 0) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
EditSession editSession = history.get(historyPointer);
|
||||||
@ -183,8 +230,8 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Performs a redo
|
* Performs a redo
|
||||||
*
|
*
|
||||||
* @param newBlockBag
|
* @param newBlockBag a new block bag
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return whether anything was redone
|
* @return whether anything was redone
|
||||||
*/
|
*/
|
||||||
public EditSession redo(BlockBag newBlockBag, LocalPlayer player) {
|
public EditSession redo(BlockBag newBlockBag, LocalPlayer player) {
|
||||||
@ -194,11 +241,13 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Performs a redo
|
* Performs a redo
|
||||||
*
|
*
|
||||||
* @param newBlockBag
|
* @param newBlockBag a new block bag
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return whether anything was redone
|
* @return whether anything was redone
|
||||||
*/
|
*/
|
||||||
public EditSession redo(BlockBag newBlockBag, Player player) {
|
public EditSession redo(BlockBag newBlockBag, Player player) {
|
||||||
|
checkNotNull(newBlockBag);
|
||||||
|
checkNotNull(player);
|
||||||
if (historyPointer < history.size()) {
|
if (historyPointer < history.size()) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
EditSession editSession = history.get(historyPointer);
|
||||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
||||||
@ -213,6 +262,9 @@ public class LocalSession {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getRegionSelector(World)}
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public RegionSelector getRegionSelector(LocalWorld world) {
|
public RegionSelector getRegionSelector(LocalWorld world) {
|
||||||
return getRegionSelector((World) world);
|
return getRegionSelector((World) world);
|
||||||
@ -222,10 +274,11 @@ public class LocalSession {
|
|||||||
* Get the region selector for defining the selection. If the selection
|
* Get the region selector for defining the selection. If the selection
|
||||||
* was defined for a different world, the old selection will be discarded.
|
* was defined for a different world, the old selection will be discarded.
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world
|
||||||
* @return position
|
* @return position the position
|
||||||
*/
|
*/
|
||||||
public RegionSelector getRegionSelector(World world) {
|
public RegionSelector getRegionSelector(World world) {
|
||||||
|
checkNotNull(world);
|
||||||
if (selector.getIncompleteRegion().getWorld() == null) {
|
if (selector.getIncompleteRegion().getWorld() == null) {
|
||||||
selector = new CuboidRegionSelector(world);
|
selector = new CuboidRegionSelector(world);
|
||||||
} else if (!selector.getIncompleteRegion().getWorld().equals(world)) {
|
} else if (!selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||||
@ -236,16 +289,16 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the region selector. This won't check worlds so make sure that
|
* @deprecated use {@link #getRegionSelector(World)}
|
||||||
* this region selector isn't used blindly.
|
|
||||||
*
|
|
||||||
* @return position
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public RegionSelector getRegionSelector() {
|
public RegionSelector getRegionSelector() {
|
||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #setRegionSelector(World, RegionSelector)}
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setRegionSelector(LocalWorld world, RegionSelector selector) {
|
public void setRegionSelector(LocalWorld world, RegionSelector selector) {
|
||||||
setRegionSelector((World) world, selector);
|
setRegionSelector((World) world, selector);
|
||||||
@ -254,10 +307,12 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the region selector.
|
* Set the region selector.
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world
|
||||||
* @param selector
|
* @param selector the selector
|
||||||
*/
|
*/
|
||||||
public void setRegionSelector(World world, RegionSelector selector) {
|
public void setRegionSelector(World world, RegionSelector selector) {
|
||||||
|
checkNotNull(world);
|
||||||
|
checkNotNull(selector);
|
||||||
selector.getIncompleteRegion().setWorld(world);
|
selector.getIncompleteRegion().setWorld(world);
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
}
|
}
|
||||||
@ -265,13 +320,16 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Returns true if the region is fully defined.
|
* Returns true if the region is fully defined.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if a region selection is defined
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isRegionDefined() {
|
public boolean isRegionDefined() {
|
||||||
return selector.isDefined();
|
return selector.isDefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #isSelectionDefined(World)}
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isSelectionDefined(LocalWorld world) {
|
public boolean isSelectionDefined(LocalWorld world) {
|
||||||
return isSelectionDefined((World) world);
|
return isSelectionDefined((World) world);
|
||||||
@ -280,10 +338,11 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Returns true if the region is fully defined for the specified world.
|
* Returns true if the region is fully defined for the specified world.
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world
|
||||||
* @return
|
* @return true if a region selection is defined
|
||||||
*/
|
*/
|
||||||
public boolean isSelectionDefined(World world) {
|
public boolean isSelectionDefined(World world) {
|
||||||
|
checkNotNull(world);
|
||||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -291,16 +350,16 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use <code>getSelection()</code>.
|
* @deprecated use {@link #getSelection(World)}
|
||||||
*
|
|
||||||
* @return region
|
|
||||||
* @throws IncompleteRegionException
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Region getRegion() throws IncompleteRegionException {
|
public Region getRegion() throws IncompleteRegionException {
|
||||||
return selector.getRegion();
|
return selector.getRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #getSelection(World)}
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Region getSelection(LocalWorld world) throws IncompleteRegionException {
|
public Region getSelection(LocalWorld world) throws IncompleteRegionException {
|
||||||
return getSelection((World) world);
|
return getSelection((World) world);
|
||||||
@ -309,14 +368,15 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Get the selection region. If you change the region, you should
|
* Get the selection region. If you change the region, you should
|
||||||
* call learnRegionChanges(). If the selection is defined in
|
* call learnRegionChanges(). If the selection is defined in
|
||||||
* a different world, the <code>IncompleteRegionException</code>
|
* a different world, the {@code IncompleteRegionException}
|
||||||
* exception will be thrown.
|
* exception will be thrown.
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world the world
|
||||||
* @return region
|
* @return a region
|
||||||
* @throws IncompleteRegionException
|
* @throws IncompleteRegionException if no region is selected
|
||||||
*/
|
*/
|
||||||
public Region getSelection(World world) throws IncompleteRegionException {
|
public Region getSelection(World world) throws IncompleteRegionException {
|
||||||
|
checkNotNull(world);
|
||||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||||
throw new IncompleteRegionException();
|
throw new IncompleteRegionException();
|
||||||
}
|
}
|
||||||
@ -326,7 +386,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Get the selection world.
|
* Get the selection world.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the the world of the selection
|
||||||
*/
|
*/
|
||||||
public World getSelectionWorld() {
|
public World getSelectionWorld() {
|
||||||
return selector.getIncompleteRegion().getWorld();
|
return selector.getIncompleteRegion().getWorld();
|
||||||
@ -335,7 +395,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Gets the clipboard.
|
* Gets the clipboard.
|
||||||
*
|
*
|
||||||
* @return clipboard, may be null
|
* @return clipboard
|
||||||
* @throws EmptyClipboardException thrown if no clipboard is set
|
* @throws EmptyClipboardException thrown if no clipboard is set
|
||||||
*/
|
*/
|
||||||
public ClipboardHolder getClipboard() throws EmptyClipboardException {
|
public ClipboardHolder getClipboard() throws EmptyClipboardException {
|
||||||
@ -368,7 +428,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Change tool control setting.
|
* Change tool control setting.
|
||||||
*
|
*
|
||||||
* @param toolControl
|
* @param toolControl true to enable tool control
|
||||||
*/
|
*/
|
||||||
public void setToolControl(boolean toolControl) {
|
public void setToolControl(boolean toolControl) {
|
||||||
this.toolControl = toolControl;
|
this.toolControl = toolControl;
|
||||||
@ -386,7 +446,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the maximum number of blocks that can be changed.
|
* Set the maximum number of blocks that can be changed.
|
||||||
*
|
*
|
||||||
* @param maxBlocksChanged
|
* @param maxBlocksChanged the maximum number of blocks changed
|
||||||
*/
|
*/
|
||||||
public void setBlockChangeLimit(int maxBlocksChanged) {
|
public void setBlockChangeLimit(int maxBlocksChanged) {
|
||||||
this.maxBlocksChanged = maxBlocksChanged;
|
this.maxBlocksChanged = maxBlocksChanged;
|
||||||
@ -418,7 +478,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Toggle the super pick axe.
|
* Toggle the super pick axe.
|
||||||
*
|
*
|
||||||
* @return status
|
* @return whether the super pick axe is now enabled
|
||||||
*/
|
*/
|
||||||
public boolean toggleSuperPickAxe() {
|
public boolean toggleSuperPickAxe() {
|
||||||
superPickaxe = !superPickaxe;
|
superPickaxe = !superPickaxe;
|
||||||
@ -426,13 +486,15 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the placement position.
|
* Get the position use for commands that take a center point
|
||||||
|
* (i.e. //forestgen, etc.).
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return position
|
* @return the position to use
|
||||||
* @throws IncompleteRegionException
|
* @throws IncompleteRegionException thrown if a region is not fully selected
|
||||||
*/
|
*/
|
||||||
public Vector getPlacementPosition(Player player) throws IncompleteRegionException {
|
public Vector getPlacementPosition(Player player) throws IncompleteRegionException {
|
||||||
|
checkNotNull(player);
|
||||||
if (!placeAtPos1) {
|
if (!placeAtPos1) {
|
||||||
return player.getBlockIn();
|
return player.getBlockIn();
|
||||||
}
|
}
|
||||||
@ -443,7 +505,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Toggle placement position.
|
* Toggle placement position.
|
||||||
*
|
*
|
||||||
* @return
|
* @return whether "place at position 1" is now enabled
|
||||||
*/
|
*/
|
||||||
public boolean togglePlacementPosition() {
|
public boolean togglePlacementPosition() {
|
||||||
placeAtPos1 = !placeAtPos1;
|
placeAtPos1 = !placeAtPos1;
|
||||||
@ -453,10 +515,12 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Get a block bag for a player.
|
* Get a block bag for a player.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player the player to get the block bag for
|
||||||
* @return
|
* @return a block bag
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public BlockBag getBlockBag(Player player) {
|
public BlockBag getBlockBag(Player player) {
|
||||||
|
checkNotNull(player);
|
||||||
if (!useInventory) {
|
if (!useInventory) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -468,6 +532,7 @@ public class LocalSession {
|
|||||||
*
|
*
|
||||||
* @return the snapshot
|
* @return the snapshot
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public Snapshot getSnapshot() {
|
public Snapshot getSnapshot() {
|
||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
@ -475,34 +540,38 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Select a snapshot.
|
* Select a snapshot.
|
||||||
*
|
*
|
||||||
* @param snapshot
|
* @param snapshot a snapshot
|
||||||
*/
|
*/
|
||||||
public void setSnapshot(Snapshot snapshot) {
|
public void setSnapshot(@Nullable Snapshot snapshot) {
|
||||||
this.snapshot = snapshot;
|
this.snapshot = snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the superPickaxeMode
|
* Get the assigned block tool.
|
||||||
|
*
|
||||||
|
* @return the super pickaxe tool mode
|
||||||
*/
|
*/
|
||||||
public BlockTool getSuperPickaxe() {
|
public BlockTool getSuperPickaxe() {
|
||||||
return pickaxeMode;
|
return pickaxeMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the super pickaxe tool.
|
* Set the super pick axe tool.
|
||||||
*
|
*
|
||||||
* @param tool
|
* @param tool the tool to set
|
||||||
*/
|
*/
|
||||||
public void setSuperPickaxe(BlockTool tool) {
|
public void setSuperPickaxe(BlockTool tool) {
|
||||||
|
checkNotNull(tool);
|
||||||
this.pickaxeMode = tool;
|
this.pickaxeMode = tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the tool assigned to the item.
|
* Get the tool assigned to the item.
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the item type ID
|
||||||
* @return the tool
|
* @return the tool, which may be {@link null}
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public Tool getTool(int item) {
|
public Tool getTool(int item) {
|
||||||
return tools.get(item);
|
return tools.get(item);
|
||||||
}
|
}
|
||||||
@ -512,10 +581,11 @@ public class LocalSession {
|
|||||||
* or the tool is not assigned, the slot will be replaced with the
|
* or the tool is not assigned, the slot will be replaced with the
|
||||||
* brush tool.
|
* brush tool.
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the item type ID
|
||||||
* @return the tool
|
* @return the tool, or {@code null}
|
||||||
* @throws InvalidToolBindException
|
* @throws InvalidToolBindException if the item can't be bound to that item
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public BrushTool getBrushTool(int item) throws InvalidToolBindException {
|
public BrushTool getBrushTool(int item) throws InvalidToolBindException {
|
||||||
Tool tool = getTool(item);
|
Tool tool = getTool(item);
|
||||||
|
|
||||||
@ -530,11 +600,11 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the tool.
|
* Set the tool.
|
||||||
*
|
*
|
||||||
* @param item
|
* @param item the item type ID
|
||||||
* @param tool the tool to set
|
* @param tool the tool to set, which can be {@code null}
|
||||||
* @throws InvalidToolBindException
|
* @throws InvalidToolBindException if the item can't be bound to that item
|
||||||
*/
|
*/
|
||||||
public void setTool(int item, Tool tool) throws InvalidToolBindException {
|
public void setTool(int item, @Nullable Tool tool) throws InvalidToolBindException {
|
||||||
if (item > 0 && item < 255) {
|
if (item > 0 && item < 255) {
|
||||||
throw new InvalidToolBindException(item, "Blocks can't be used");
|
throw new InvalidToolBindException(item, "Blocks can't be used");
|
||||||
} else if (item == config.wandItem) {
|
} else if (item == config.wandItem) {
|
||||||
@ -549,7 +619,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Returns whether inventory usage is enabled for this session.
|
* Returns whether inventory usage is enabled for this session.
|
||||||
*
|
*
|
||||||
* @return the useInventory
|
* @return if inventory is being used
|
||||||
*/
|
*/
|
||||||
public boolean isUsingInventory() {
|
public boolean isUsingInventory() {
|
||||||
return useInventory;
|
return useInventory;
|
||||||
@ -558,7 +628,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the state of inventory usage.
|
* Set the state of inventory usage.
|
||||||
*
|
*
|
||||||
* @param useInventory the useInventory to set
|
* @param useInventory if inventory is to be used
|
||||||
*/
|
*/
|
||||||
public void setUseInventory(boolean useInventory) {
|
public void setUseInventory(boolean useInventory) {
|
||||||
this.useInventory = useInventory;
|
this.useInventory = useInventory;
|
||||||
@ -567,8 +637,9 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Get the last script used.
|
* Get the last script used.
|
||||||
*
|
*
|
||||||
* @return the lastScript
|
* @return the last script's name
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public String getLastScript() {
|
public String getLastScript() {
|
||||||
return lastScript;
|
return lastScript;
|
||||||
}
|
}
|
||||||
@ -576,58 +647,55 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set the last script used.
|
* Set the last script used.
|
||||||
*
|
*
|
||||||
* @param lastScript the lastScript to set
|
* @param lastScript the last script's name
|
||||||
*/
|
*/
|
||||||
public void setLastScript(String lastScript) {
|
public void setLastScript(@Nullable String lastScript) {
|
||||||
this.lastScript = lastScript;
|
this.lastScript = lastScript;
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the player the WorldEdit version.
|
* Tell the player the WorldEdit version.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player the player
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"PointlessBooleanExpression", "ConstantConditions"})
|
|
||||||
public void tellVersion(Actor player) {
|
public void tellVersion(Actor player) {
|
||||||
if (config.showHelpInfo && SHOW_HELP_MESSAGE) {
|
|
||||||
if (!beenToldVersion) {
|
|
||||||
StyledFragment fragment = new StyledFragment(Style.GRAY_DARK);
|
|
||||||
fragment.append("Need help with WorldEdit? Ask us on IRC (irc.esper.net #sk89q) or on our forums @ http://forum.enginehub.org");
|
|
||||||
player.printRaw(ColorCodeBuilder.asColorCodes(fragment));
|
|
||||||
beenToldVersion = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a CUI event but only if the player has CUI support.
|
* Dispatch a CUI event but only if the actor has CUI support.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param actor the actor
|
||||||
* @param event
|
* @param event the event
|
||||||
*/
|
*/
|
||||||
public void dispatchCUIEvent(Actor player, CUIEvent event) {
|
public void dispatchCUIEvent(Actor actor, CUIEvent event) {
|
||||||
|
checkNotNull(actor);
|
||||||
|
checkNotNull(event);
|
||||||
|
|
||||||
if (hasCUISupport) {
|
if (hasCUISupport) {
|
||||||
player.dispatchCUIEvent(event);
|
actor.dispatchCUIEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch the initial setup CUI messages.
|
* Dispatch the initial setup CUI messages.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param actor the actor
|
||||||
*/
|
*/
|
||||||
public void dispatchCUISetup(Player player) {
|
public void dispatchCUISetup(Actor actor) {
|
||||||
if (selector != null) {
|
if (selector != null) {
|
||||||
dispatchCUISelection(player);
|
dispatchCUISelection(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the selection information.
|
* Send the selection information.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param actor the actor
|
||||||
*/
|
*/
|
||||||
public void dispatchCUISelection(Player player) {
|
public void dispatchCUISelection(Actor actor) {
|
||||||
|
checkNotNull(actor);
|
||||||
|
|
||||||
if (!hasCUISupport) {
|
if (!hasCUISupport) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -636,17 +704,24 @@ public class LocalSession {
|
|||||||
CUIRegion tempSel = (CUIRegion) selector;
|
CUIRegion tempSel = (CUIRegion) selector;
|
||||||
|
|
||||||
if (tempSel.getProtocolVersion() > cuiVersion) {
|
if (tempSel.getProtocolVersion() > cuiVersion) {
|
||||||
player.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID()));
|
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID()));
|
||||||
tempSel.describeLegacyCUI(this, player);
|
tempSel.describeLegacyCUI(this, actor);
|
||||||
} else {
|
} else {
|
||||||
player.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID()));
|
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID()));
|
||||||
tempSel.describeCUI(this, player);
|
tempSel.describeCUI(this, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void describeCUI(Actor player) {
|
/**
|
||||||
|
* Describe the selection to the CUI actor.
|
||||||
|
*
|
||||||
|
* @param actor the actor
|
||||||
|
*/
|
||||||
|
public void describeCUI(Actor actor) {
|
||||||
|
checkNotNull(actor);
|
||||||
|
|
||||||
if (!hasCUISupport) {
|
if (!hasCUISupport) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -655,15 +730,22 @@ public class LocalSession {
|
|||||||
CUIRegion tempSel = (CUIRegion) selector;
|
CUIRegion tempSel = (CUIRegion) selector;
|
||||||
|
|
||||||
if (tempSel.getProtocolVersion() > cuiVersion) {
|
if (tempSel.getProtocolVersion() > cuiVersion) {
|
||||||
tempSel.describeLegacyCUI(this, player);
|
tempSel.describeLegacyCUI(this, actor);
|
||||||
} else {
|
} else {
|
||||||
tempSel.describeCUI(this, player);
|
tempSel.describeCUI(this, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a CUI initialization message.
|
||||||
|
*
|
||||||
|
* @param text the message
|
||||||
|
*/
|
||||||
public void handleCUIInitializationMessage(String text) {
|
public void handleCUIInitializationMessage(String text) {
|
||||||
|
checkNotNull(text);
|
||||||
|
|
||||||
String[] split = text.split("\\|");
|
String[] split = text.split("\\|");
|
||||||
if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message
|
if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message
|
||||||
setCUISupport(true);
|
setCUISupport(true);
|
||||||
@ -678,7 +760,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Gets the status of CUI support.
|
* Gets the status of CUI support.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if CUI is enabled
|
||||||
*/
|
*/
|
||||||
public boolean hasCUISupport() {
|
public boolean hasCUISupport() {
|
||||||
return hasCUISupport;
|
return hasCUISupport;
|
||||||
@ -687,7 +769,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Sets the status of CUI support.
|
* Sets the status of CUI support.
|
||||||
*
|
*
|
||||||
* @param support
|
* @param support true if CUI is enabled
|
||||||
*/
|
*/
|
||||||
public void setCUISupport(boolean support) {
|
public void setCUISupport(boolean support) {
|
||||||
hasCUISupport = support;
|
hasCUISupport = support;
|
||||||
@ -696,7 +778,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Gets the client's CUI protocol version
|
* Gets the client's CUI protocol version
|
||||||
*
|
*
|
||||||
* @return
|
* @return the CUI version
|
||||||
*/
|
*/
|
||||||
public int getCUIVersion() {
|
public int getCUIVersion() {
|
||||||
return cuiVersion;
|
return cuiVersion;
|
||||||
@ -705,7 +787,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Sets the client's CUI protocol version
|
* Sets the client's CUI protocol version
|
||||||
*
|
*
|
||||||
* @param cuiVersion
|
* @param cuiVersion the CUI version
|
||||||
*/
|
*/
|
||||||
public void setCUIVersion(int cuiVersion) {
|
public void setCUIVersion(int cuiVersion) {
|
||||||
this.cuiVersion = cuiVersion;
|
this.cuiVersion = cuiVersion;
|
||||||
@ -714,10 +796,13 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Detect date from a user's input.
|
* Detect date from a user's input.
|
||||||
*
|
*
|
||||||
* @param input
|
* @param input the input to parse
|
||||||
* @return
|
* @return a date
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public Calendar detectDate(String input) {
|
public Calendar detectDate(String input) {
|
||||||
|
checkNotNull(input);
|
||||||
|
|
||||||
Time.setTimeZone(getTimeZone());
|
Time.setTimeZone(getTimeZone());
|
||||||
Options opt = new com.sk89q.jchronic.Options();
|
Options opt = new com.sk89q.jchronic.Options();
|
||||||
opt.setNow(Calendar.getInstance(getTimeZone()));
|
opt.setNow(Calendar.getInstance(getTimeZone()));
|
||||||
@ -730,27 +815,9 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the last update time for calculating expiration.
|
* @deprecated use {@link #createEditSession(Player)}
|
||||||
*/
|
|
||||||
public void update() {
|
|
||||||
expirationTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this session has expired.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean hasExpired() {
|
|
||||||
return System.currentTimeMillis() - expirationTime > EXPIRATION_GRACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new edit session.
|
|
||||||
*
|
|
||||||
* @param player
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public EditSession createEditSession(LocalPlayer player) {
|
public EditSession createEditSession(LocalPlayer player) {
|
||||||
return createEditSession((Player) player);
|
return createEditSession((Player) player);
|
||||||
}
|
}
|
||||||
@ -758,11 +825,13 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Construct a new edit session.
|
* Construct a new edit session.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player the player
|
||||||
* @return
|
* @return an edit session
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public EditSession createEditSession(Player player) {
|
public EditSession createEditSession(Player player) {
|
||||||
|
checkNotNull(player);
|
||||||
|
|
||||||
BlockBag blockBag = getBlockBag(player);
|
BlockBag blockBag = getBlockBag(player);
|
||||||
|
|
||||||
// Create an edit session
|
// Create an edit session
|
||||||
@ -779,7 +848,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Checks if the session has fast mode enabled.
|
* Checks if the session has fast mode enabled.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if fast mode is enabled
|
||||||
*/
|
*/
|
||||||
public boolean hasFastMode() {
|
public boolean hasFastMode() {
|
||||||
return fastMode;
|
return fastMode;
|
||||||
@ -788,7 +857,7 @@ public class LocalSession {
|
|||||||
/**
|
/**
|
||||||
* Set fast mode.
|
* Set fast mode.
|
||||||
*
|
*
|
||||||
* @param fastMode
|
* @param fastMode true if fast mode is enabled
|
||||||
*/
|
*/
|
||||||
public void setFastMode(boolean fastMode) {
|
public void setFastMode(boolean fastMode) {
|
||||||
this.fastMode = fastMode;
|
this.fastMode = fastMode;
|
||||||
|
@ -660,41 +660,6 @@ public class WorldEdit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a disconnection.
|
|
||||||
*
|
|
||||||
* @param player the player
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void handleDisconnect(Player player) {
|
|
||||||
forgetPlayer(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark for expiration of the session.
|
|
||||||
*
|
|
||||||
* @param player the player
|
|
||||||
*/
|
|
||||||
public void markExpire(Player player) {
|
|
||||||
sessions.markforExpiration(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forget a player.
|
|
||||||
*
|
|
||||||
* @param player the player
|
|
||||||
*/
|
|
||||||
public void forgetPlayer(Player player) {
|
|
||||||
sessions.remove(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flush expired sessions.
|
|
||||||
*/
|
|
||||||
public void flushExpiredSessions(SessionCheck checker) {
|
|
||||||
sessions.removeExpired(checker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on arm swing.
|
* Called on arm swing.
|
||||||
*
|
*
|
||||||
|
@ -24,6 +24,7 @@ import com.sk89q.minecraft.util.commands.CommandContext;
|
|||||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.*;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
|
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.extension.platform.Platform;
|
||||||
@ -78,6 +79,7 @@ public class WorldEditCommands {
|
|||||||
@CommandPermissions("worldedit.reload")
|
@CommandPermissions("worldedit.reload")
|
||||||
public void reload(Actor actor) throws WorldEditException {
|
public void reload(Actor actor) throws WorldEditException {
|
||||||
we.getServer().reload();
|
we.getServer().reload();
|
||||||
|
we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||||
actor.print("Configuration reloaded!");
|
actor.print("Configuration reloaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.event.platform;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
|
import com.sk89q.worldedit.event.Event;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raised when the configuration has been loaded or re-loaded.
|
||||||
|
*/
|
||||||
|
public class ConfigurationLoadEvent extends Event {
|
||||||
|
|
||||||
|
private final LocalConfiguration configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param configuration the new configuration
|
||||||
|
*/
|
||||||
|
public ConfigurationLoadEvent(LocalConfiguration configuration) {
|
||||||
|
checkNotNull(configuration);
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration.
|
||||||
|
*
|
||||||
|
* @return the configuration
|
||||||
|
*/
|
||||||
|
public LocalConfiguration getConfiguration() {
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,15 +17,15 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit;
|
package com.sk89q.worldedit.event.platform;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.event.Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author zml2008
|
* Fired when configuration has been loaded and the platform is in the
|
||||||
|
* intialization stage.
|
||||||
|
*
|
||||||
|
* <p>This event is fired once.</p>
|
||||||
*/
|
*/
|
||||||
public class WorldEditPermissionException extends WorldEditException {
|
public class PlatformInitializeEvent extends Event {
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public WorldEditPermissionException() {
|
|
||||||
super("You don't have permission to do this.");
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -19,13 +19,13 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extension.platform;
|
package com.sk89q.worldedit.extension.platform;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||||
import com.sk89q.worldedit.BlockWorldVector;
|
import com.sk89q.worldedit.BlockWorldVector;
|
||||||
import com.sk89q.worldedit.LocalPlayer;
|
import com.sk89q.worldedit.LocalPlayer;
|
||||||
import com.sk89q.worldedit.NotABlockException;
|
import com.sk89q.worldedit.NotABlockException;
|
||||||
import com.sk89q.worldedit.PlayerDirection;
|
import com.sk89q.worldedit.PlayerDirection;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.WorldEditPermissionException;
|
|
||||||
import com.sk89q.worldedit.WorldVector;
|
import com.sk89q.worldedit.WorldVector;
|
||||||
import com.sk89q.worldedit.WorldVectorFace;
|
import com.sk89q.worldedit.WorldVectorFace;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
@ -464,9 +464,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkPermission(String permission) throws WorldEditPermissionException {
|
public void checkPermission(String permission) throws AuthorizationException {
|
||||||
if (!hasPermission(permission)) {
|
if (!hasPermission(permission)) {
|
||||||
throw new WorldEditPermissionException();
|
throw new AuthorizationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,16 +19,17 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extension.platform;
|
package com.sk89q.worldedit.extension.platform;
|
||||||
|
|
||||||
import com.sk89q.worldedit.WorldEditPermissionException;
|
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.session.SessionOwner;
|
||||||
|
import com.sk89q.worldedit.util.Identifiable;
|
||||||
|
import com.sk89q.worldedit.util.auth.Subject;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object that can perform actions in WorldEdit.
|
* An object that can perform actions in WorldEdit.
|
||||||
*/
|
*/
|
||||||
public interface Actor {
|
public interface Actor extends Identifiable, SessionOwner, Subject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the actor.
|
* Get the name of the actor.
|
||||||
@ -72,30 +73,6 @@ public interface Actor {
|
|||||||
*/
|
*/
|
||||||
boolean canDestroyBedrock();
|
boolean canDestroyBedrock();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a actor's list of groups.
|
|
||||||
*
|
|
||||||
* @return an array containing a group name per entry
|
|
||||||
*/
|
|
||||||
String[] getGroups();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a player has permission.
|
|
||||||
*
|
|
||||||
* @param perm The permission to check
|
|
||||||
* @return true if the player has that permission
|
|
||||||
*/
|
|
||||||
boolean hasPermission(String perm);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether this actor has the given permission, and throw an
|
|
||||||
* exception if not.
|
|
||||||
*
|
|
||||||
* @param permission the permission
|
|
||||||
* @throws WorldEditPermissionException thrown if permission is not availabe
|
|
||||||
*/
|
|
||||||
void checkPermission(String permission) throws WorldEditPermissionException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether this actor is a player.
|
* Return whether this actor is a player.
|
||||||
*
|
*
|
||||||
|
@ -19,12 +19,22 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extension.platform;
|
package com.sk89q.worldedit.extension.platform;
|
||||||
|
|
||||||
import com.sk89q.worldedit.*;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.ServerInterface;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.command.tool.*;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
|
import com.sk89q.worldedit.WorldVector;
|
||||||
|
import com.sk89q.worldedit.command.tool.BlockTool;
|
||||||
|
import com.sk89q.worldedit.command.tool.DoubleActionBlockTool;
|
||||||
|
import com.sk89q.worldedit.command.tool.DoubleActionTraceTool;
|
||||||
|
import com.sk89q.worldedit.command.tool.Tool;
|
||||||
|
import com.sk89q.worldedit.command.tool.TraceTool;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
|
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||||
import com.sk89q.worldedit.event.platform.Interaction;
|
import com.sk89q.worldedit.event.platform.Interaction;
|
||||||
|
import com.sk89q.worldedit.event.platform.PlatformInitializeEvent;
|
||||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||||
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
|
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
|
||||||
import com.sk89q.worldedit.internal.ServerInterfaceAdapter;
|
import com.sk89q.worldedit.internal.ServerInterfaceAdapter;
|
||||||
@ -34,8 +44,13 @@ import com.sk89q.worldedit.util.eventbus.Subscribe;
|
|||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -56,6 +71,8 @@ public class PlatformManager {
|
|||||||
private final List<Platform> platforms = new ArrayList<Platform>();
|
private final List<Platform> platforms = new ArrayList<Platform>();
|
||||||
private final Map<Capability, Platform> preferences = new EnumMap<Capability, Platform>(Capability.class);
|
private final Map<Capability, Platform> preferences = new EnumMap<Capability, Platform>(Capability.class);
|
||||||
private @Nullable String firstSeenVersion;
|
private @Nullable String firstSeenVersion;
|
||||||
|
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||||
|
private final AtomicBoolean configured = new AtomicBoolean();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new platform manager.
|
* Create a new platform manager.
|
||||||
@ -163,6 +180,11 @@ public class PlatformManager {
|
|||||||
capability.initialize(this, preferred);
|
capability.initialize(this, preferred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fire configuration event
|
||||||
|
if (preferences.containsKey(Capability.CONFIGURATION) && configured.compareAndSet(false, true)) {
|
||||||
|
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -276,6 +298,9 @@ public class PlatformManager {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void handlePlatformReady(PlatformReadyEvent event) {
|
public void handlePlatformReady(PlatformReadyEvent event) {
|
||||||
choosePreferred();
|
choosePreferred();
|
||||||
|
if (initialized.compareAndSet(false, true)) {
|
||||||
|
worldEdit.getEventBus().post(new PlatformInitializeEvent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -25,11 +25,14 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
|||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
|
import com.sk89q.worldedit.session.SessionKey;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
class PlayerProxy extends AbstractPlayerActor {
|
class PlayerProxy extends AbstractPlayerActor {
|
||||||
@ -50,6 +53,11 @@ class PlayerProxy extends AbstractPlayerActor {
|
|||||||
this.world = world;
|
this.world = world;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return basePlayer.getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemInHand() {
|
public int getItemInHand() {
|
||||||
return basePlayer.getItemInHand();
|
return basePlayer.getItemInHand();
|
||||||
@ -145,4 +153,9 @@ class PlayerProxy extends AbstractPlayerActor {
|
|||||||
public <T> T getFacet(Class<? extends T> cls) {
|
public <T> T getFacet(Class<? extends T> cls) {
|
||||||
return basePlayer.getFacet(cls);
|
return basePlayer.getFacet(cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionKey getSessionKey() {
|
||||||
|
return basePlayer.getSessionKey();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raised when the session is missing.
|
||||||
|
*/
|
||||||
|
public class MissingSessionException extends Exception {
|
||||||
|
|
||||||
|
public MissingSessionException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MissingSessionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MissingSessionException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MissingSessionException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
62
src/main/java/com/sk89q/worldedit/session/SessionKey.java
Normal file
62
src/main/java/com/sk89q/worldedit/session/SessionKey.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.util.Identifiable;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides information about a session.
|
||||||
|
*
|
||||||
|
* <p>A reference for this object may be kept around for a long time.</p>
|
||||||
|
*/
|
||||||
|
public interface SessionKey extends Identifiable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name for this session, if one is available, so that it can
|
||||||
|
* be referred to by others.
|
||||||
|
*
|
||||||
|
* @return a name or {@code null}
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the session is still active. Sessions that are inactive
|
||||||
|
* for a prolonged amount of time may be removed. If this method
|
||||||
|
* always returns {@code false}, the the related session may never
|
||||||
|
* be stored.
|
||||||
|
*
|
||||||
|
* <p>This method may be called from any thread, so this call
|
||||||
|
* must be thread safe.</p>
|
||||||
|
*
|
||||||
|
* @return true if active
|
||||||
|
*/
|
||||||
|
boolean isActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this session should be persisted.
|
||||||
|
*
|
||||||
|
* @return true if persistent
|
||||||
|
*/
|
||||||
|
boolean isPersistent();
|
||||||
|
|
||||||
|
}
|
@ -19,28 +19,53 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.session;
|
package com.sk89q.worldedit.session;
|
||||||
|
|
||||||
import com.sk89q.worldedit.*;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||||
|
import com.sk89q.worldedit.session.storage.JsonFileSessionStore;
|
||||||
|
import com.sk89q.worldedit.session.storage.SessionStore;
|
||||||
|
import com.sk89q.worldedit.session.storage.VoidStore;
|
||||||
|
import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors;
|
||||||
|
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session manager for WorldEdit.
|
* Session manager for WorldEdit.
|
||||||
* </p>
|
*
|
||||||
* Get a reference to one from {@link WorldEdit}.
|
* <p>Get a reference to one from {@link WorldEdit}.</p>
|
||||||
* </p>
|
*
|
||||||
* While this class is thread-safe, the returned session may not be.
|
* <p>While this class is thread-safe, the returned session may not be.</p>
|
||||||
*/
|
*/
|
||||||
public class SessionManager {
|
public class SessionManager {
|
||||||
|
|
||||||
|
public static int EXPIRATION_GRACE = 600000;
|
||||||
|
private static final int FLUSH_PERIOD = 1000 * 30;
|
||||||
|
private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5));
|
||||||
|
private static final Logger log = Logger.getLogger(SessionManager.class.getCanonicalName());
|
||||||
|
private final Timer timer = new Timer();
|
||||||
private final WorldEdit worldEdit;
|
private final WorldEdit worldEdit;
|
||||||
private final HashMap<String, LocalSession> sessions = new HashMap<String, LocalSession>();
|
private final Map<UUID, SessionHolder> sessions = new HashMap<UUID, SessionHolder>();
|
||||||
|
private SessionStore store = new VoidStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new session manager.
|
* Create a new session manager.
|
||||||
@ -48,73 +73,98 @@ public class SessionManager {
|
|||||||
* @param worldEdit a WorldEdit instance
|
* @param worldEdit a WorldEdit instance
|
||||||
*/
|
*/
|
||||||
public SessionManager(WorldEdit worldEdit) {
|
public SessionManager(WorldEdit worldEdit) {
|
||||||
|
checkNotNull(worldEdit);
|
||||||
this.worldEdit = worldEdit;
|
this.worldEdit = worldEdit;
|
||||||
|
|
||||||
|
worldEdit.getEventBus().register(this);
|
||||||
|
timer.schedule(new SessionTracker(), FLUSH_PERIOD, FLUSH_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get whether a session exists for the given actor.
|
* Get whether a session exists for the given owner.
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param owner the owner
|
||||||
* @return true if a session exists
|
* @return true if a session exists
|
||||||
*/
|
*/
|
||||||
public synchronized boolean contains(Actor actor) {
|
public synchronized boolean contains(SessionOwner owner) {
|
||||||
checkNotNull(actor);
|
checkNotNull(owner);
|
||||||
return sessions.containsKey(getKey(actor));
|
return sessions.containsKey(getKey(owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the session for an actor and return it if it exists, otherwise
|
* Find a session by its name specified by {@link SessionKey#getName()}.
|
||||||
* return <code>null</code>.
|
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param name the name
|
||||||
* @return the session for the actor, if it exists
|
* @return the session, if found, otherwise {@code null}
|
||||||
*/
|
*/
|
||||||
public synchronized @Nullable LocalSession find(Actor actor) {
|
@Nullable
|
||||||
checkNotNull(actor);
|
public synchronized LocalSession findByName(String name) {
|
||||||
return sessions.get(getKey(actor));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the session for someone named by the given name and return it if
|
|
||||||
* it exists, otherwise return <code>null</code>.
|
|
||||||
*
|
|
||||||
* @param name the actor's name
|
|
||||||
* @return the session for the actor, if it exists
|
|
||||||
*/
|
|
||||||
public synchronized @Nullable LocalSession findByName(String name) {
|
|
||||||
checkNotNull(name);
|
checkNotNull(name);
|
||||||
return sessions.get(name);
|
for (SessionHolder holder : sessions.values()) {
|
||||||
|
String test = holder.key.getName();
|
||||||
|
if (test != null && name.equals(test)) {
|
||||||
|
return holder.session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the session for an actor and create one if one doesn't exist.
|
* Gets the session for an owner and return it if it exists, otherwise
|
||||||
|
* return {@code null}.
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param owner the owner
|
||||||
|
* @return the session for the owner, if it exists
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public synchronized LocalSession getIfPresent(SessionOwner owner) {
|
||||||
|
checkNotNull(owner);
|
||||||
|
SessionHolder stored = sessions.get(getKey(owner));
|
||||||
|
if (stored != null) {
|
||||||
|
return stored.session;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the session for an owner and create one if one doesn't exist.
|
||||||
|
*
|
||||||
|
* @param owner the owner
|
||||||
* @return a session
|
* @return a session
|
||||||
*/
|
*/
|
||||||
public synchronized LocalSession get(Actor actor) {
|
public synchronized LocalSession get(SessionOwner owner) {
|
||||||
checkNotNull(actor);
|
checkNotNull(owner);
|
||||||
|
|
||||||
LocalSession session;
|
LocalSession session = getIfPresent(owner);
|
||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
SessionKey sessionKey = owner.getSessionKey();
|
||||||
|
|
||||||
if (sessions.containsKey(actor.getName())) {
|
// No session exists yet -- create one
|
||||||
session = sessions.get(actor.getName());
|
if (session == null) {
|
||||||
} else {
|
try {
|
||||||
session = new LocalSession(config);
|
session = store.load(getKey(sessionKey));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.WARNING, "Failed to load saved session", e);
|
||||||
|
session = new LocalSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
session.setConfiguration(config);
|
||||||
session.setBlockChangeLimit(config.defaultChangeLimit);
|
session.setBlockChangeLimit(config.defaultChangeLimit);
|
||||||
// Remember the session
|
|
||||||
sessions.put(actor.getName(), session);
|
// Remember the session if the session is still active
|
||||||
|
if (sessionKey.isActive()) {
|
||||||
|
sessions.put(getKey(owner), new SessionHolder(sessionKey, session));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the limit on the number of blocks that an operation can
|
// Set the limit on the number of blocks that an operation can
|
||||||
// change at once, or don't if the actor has an override or there
|
// change at once, or don't if the owner has an override or there
|
||||||
// is no limit. There is also a default limit
|
// is no limit. There is also a default limit
|
||||||
int currentChangeLimit = session.getBlockChangeLimit();
|
int currentChangeLimit = session.getBlockChangeLimit();
|
||||||
|
|
||||||
if (!actor.hasPermission("worldedit.limit.unrestricted")
|
if (!owner.hasPermission("worldedit.limit.unrestricted") && config.maxChangeLimit > -1) {
|
||||||
&& config.maxChangeLimit > -1) {
|
|
||||||
|
|
||||||
// If the default limit is infinite but there is a maximum
|
// If the default limit is infinite but there is a maximum
|
||||||
// limit, make sure to not have it be overridden
|
// limit, make sure to not have it be overridden
|
||||||
if (config.defaultChangeLimit < 0) {
|
if (config.defaultChangeLimit < 0) {
|
||||||
@ -130,47 +180,90 @@ public class SessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have the session use inventory if it's enabled and the actor
|
// Have the session use inventory if it's enabled and the owner
|
||||||
// doesn't have an override
|
// doesn't have an override
|
||||||
session.setUseInventory(config.useInventory
|
session.setUseInventory(config.useInventory
|
||||||
&& !(config.useInventoryOverride
|
&& !(config.useInventoryOverride
|
||||||
&& (actor.hasPermission("worldedit.inventory.unrestricted")
|
&& (owner.hasPermission("worldedit.inventory.unrestricted")
|
||||||
|| (config.useInventoryCreativeOverride && (!(actor instanceof Player) || ((Player) actor).hasCreativeMode())))));
|
|| (config.useInventoryCreativeOverride && (!(owner instanceof Player) || ((Player) owner).hasCreativeMode())))));
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the key to use in the map for an actor.
|
* Save a map of sessions to disk.
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param sessions a map of sessions to save
|
||||||
* @return the key object
|
* @return a future that completes on save or error
|
||||||
*/
|
*/
|
||||||
protected String getKey(Actor actor) {
|
private ListenableFuture<?> commit(final Map<SessionKey, LocalSession> sessions) {
|
||||||
return actor.getName();
|
checkNotNull(sessions);
|
||||||
|
|
||||||
|
if (sessions.isEmpty()) {
|
||||||
|
return Futures.immediateFuture(sessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executorService.submit(new Callable<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object call() throws Exception {
|
||||||
|
Exception exception = null;
|
||||||
|
|
||||||
|
for (Map.Entry<SessionKey, LocalSession> entry : sessions.entrySet()) {
|
||||||
|
SessionKey key = entry.getKey();
|
||||||
|
|
||||||
|
if (key.isPersistent()) {
|
||||||
|
try {
|
||||||
|
store.save(getKey(key), entry.getValue());
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.WARNING, "Failed to write session for UUID " + getKey(key), e);
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exception != null) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark for expiration.
|
* Get the key to use in the map for an owner.
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param owner the owner
|
||||||
|
* @return the key object
|
||||||
*/
|
*/
|
||||||
public synchronized void markforExpiration(Actor actor) {
|
protected UUID getKey(SessionOwner owner) {
|
||||||
checkNotNull(actor);
|
return getKey(owner.getSessionKey());
|
||||||
LocalSession session = find(actor);
|
}
|
||||||
if (session != null) {
|
|
||||||
session.update();
|
|
||||||
|
/**
|
||||||
|
* Get the key to use in the map for a {@code SessionKey}.
|
||||||
|
*
|
||||||
|
* @param key the session key object
|
||||||
|
* @return the key object
|
||||||
|
*/
|
||||||
|
protected UUID getKey(SessionKey key) {
|
||||||
|
String forcedKey = System.getProperty("worldedit.session.uuidOverride");
|
||||||
|
if (forcedKey != null) {
|
||||||
|
return UUID.fromString(forcedKey);
|
||||||
|
} else {
|
||||||
|
return key.getUniqueId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the session for the given actor if one exists.
|
* Remove the session for the given owner if one exists.
|
||||||
*
|
*
|
||||||
* @param actor the actor
|
* @param owner the owner
|
||||||
*/
|
*/
|
||||||
public synchronized void remove(Actor actor) {
|
public synchronized void remove(SessionOwner owner) {
|
||||||
checkNotNull(actor);
|
checkNotNull(owner);
|
||||||
sessions.remove(actor.getName());
|
sessions.remove(getKey(owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,18 +273,61 @@ public class SessionManager {
|
|||||||
sessions.clear();
|
sessions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Subscribe
|
||||||
* Remove expired sessions with the given session checker.
|
public void onConfigurationLoad(ConfigurationLoadEvent event) {
|
||||||
*
|
LocalConfiguration config = event.getConfiguration();
|
||||||
* @param checker the session checker
|
File dir = new File(config.getWorkingDirectory(), "sessions");
|
||||||
*/
|
store = new JsonFileSessionStore(dir);
|
||||||
public synchronized void removeExpired(SessionCheck checker) {
|
}
|
||||||
Iterator<Map.Entry<String, LocalSession>> it = sessions.entrySet().iterator();
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
/**
|
||||||
Map.Entry<String, LocalSession> entry = it.next();
|
* Stores the owner of a session, the session, and the last active time.
|
||||||
if (entry.getValue().hasExpired() && !checker.isOnlinePlayer(entry.getKey())) {
|
*/
|
||||||
it.remove();
|
private static class SessionHolder {
|
||||||
|
private final SessionKey key;
|
||||||
|
private final LocalSession session;
|
||||||
|
private long lastActive = System.currentTimeMillis();
|
||||||
|
|
||||||
|
private SessionHolder(SessionKey key, LocalSession session) {
|
||||||
|
this.key = key;
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes inactive sessions after they have been inactive for a period
|
||||||
|
* of time. Commits them as well.
|
||||||
|
*/
|
||||||
|
private class SessionTracker extends TimerTask {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (SessionManager.this) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
Iterator<SessionHolder> it = sessions.values().iterator();
|
||||||
|
Map<SessionKey, LocalSession> saveQueue = new HashMap<SessionKey, LocalSession>();
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
SessionHolder stored = it.next();
|
||||||
|
if (stored.key.isActive()) {
|
||||||
|
stored.lastActive = now;
|
||||||
|
|
||||||
|
if (stored.session.compareAndResetDirty()) {
|
||||||
|
saveQueue.put(stored.key, stored.session);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (now - stored.lastActive > EXPIRATION_GRACE) {
|
||||||
|
if (stored.session.compareAndResetDirty()) {
|
||||||
|
saveQueue.put(stored.key, stored.session);
|
||||||
|
}
|
||||||
|
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!saveQueue.isEmpty()) {
|
||||||
|
commit(saveQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
src/main/java/com/sk89q/worldedit/session/SessionOwner.java
Normal file
37
src/main/java/com/sk89q/worldedit/session/SessionOwner.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.util.Identifiable;
|
||||||
|
import com.sk89q.worldedit.util.auth.Subject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that owns a session.
|
||||||
|
*/
|
||||||
|
public interface SessionOwner extends Subject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an object describing this session.
|
||||||
|
*
|
||||||
|
* @return the status object
|
||||||
|
*/
|
||||||
|
SessionKey getSessionKey();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown if the session cannot be persisted
|
||||||
|
* (because {@link SessionKey#isPersistent()} returns false).
|
||||||
|
*/
|
||||||
|
public class TransientSessionException extends Exception {
|
||||||
|
|
||||||
|
public TransientSessionException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransientSessionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransientSessionException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransientSessionException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session.storage;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonIOException;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.util.gson.GsonUtil;
|
||||||
|
import com.sk89q.worldedit.util.io.Closer;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores sessions as JSON files in a directory.
|
||||||
|
*
|
||||||
|
* <p>Currently, this implementation doesn't handle thread safety very well.</p>
|
||||||
|
*/
|
||||||
|
public class JsonFileSessionStore implements SessionStore {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger(JsonFileSessionStore.class.getCanonicalName());
|
||||||
|
private final Gson gson;
|
||||||
|
private final File dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new session store.
|
||||||
|
*
|
||||||
|
* @param dir the directory
|
||||||
|
*/
|
||||||
|
public JsonFileSessionStore(File dir) {
|
||||||
|
checkNotNull(dir);
|
||||||
|
|
||||||
|
if (!dir.isDirectory()) {
|
||||||
|
if (!dir.mkdirs()) {
|
||||||
|
log.log(Level.WARNING, "Failed to create directory '" + dir.getPath() + "' for sessions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dir = dir;
|
||||||
|
|
||||||
|
GsonBuilder builder = GsonUtil.createBuilder();
|
||||||
|
gson = builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path for the given UUID.
|
||||||
|
*
|
||||||
|
* @param id the ID
|
||||||
|
* @return the file
|
||||||
|
*/
|
||||||
|
private File getPath(UUID id) {
|
||||||
|
checkNotNull(id);
|
||||||
|
return new File(dir, id + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalSession load(UUID id) throws IOException {
|
||||||
|
File file = getPath(id);
|
||||||
|
Closer closer = Closer.create();
|
||||||
|
try {
|
||||||
|
FileReader fr = closer.register(new FileReader(file));
|
||||||
|
BufferedReader br = closer.register(new BufferedReader(fr));
|
||||||
|
return gson.fromJson(br, LocalSession.class);
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return new LocalSession();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
closer.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(UUID id, LocalSession session) throws IOException {
|
||||||
|
File finalFile = getPath(id);
|
||||||
|
File tempFile = new File(finalFile.getParentFile(), finalFile.getName() + ".tmp");
|
||||||
|
Closer closer = Closer.create();
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileWriter fr = closer.register(new FileWriter(tempFile));
|
||||||
|
BufferedWriter bw = closer.register(new BufferedWriter(fr));
|
||||||
|
gson.toJson(session, bw);
|
||||||
|
} catch (JsonIOException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
closer.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalFile.exists()) {
|
||||||
|
if (!finalFile.delete()) {
|
||||||
|
log.log(Level.WARNING, "Failed to delete " + finalFile.getPath() + " so the .tmp file can replace it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tempFile.renameTo(finalFile)) {
|
||||||
|
log.log(Level.WARNING, "Failed to rename temporary session file to " + finalFile.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.session.storage;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits sessions to disk.
|
||||||
|
*
|
||||||
|
* <p>Both {@link #load(UUID)} and {@link #save(UUID, LocalSession)} may be
|
||||||
|
* called at the same in different threads, so implementations should
|
||||||
|
* be aware of this issue.</p>
|
||||||
|
*/
|
||||||
|
public interface SessionStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a session identified by the given UUID.
|
||||||
|
*
|
||||||
|
* <p>If the session does not exist (has never been saved), then
|
||||||
|
* a new {@link LocalSession} must be returned.</p>
|
||||||
|
*
|
||||||
|
* @param id the UUID
|
||||||
|
* @return a session
|
||||||
|
* @throws IOException thrown on read error
|
||||||
|
*/
|
||||||
|
LocalSession load(UUID id) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given session identified by the given UUID.
|
||||||
|
*
|
||||||
|
* @param id the UUID
|
||||||
|
* @param session a session
|
||||||
|
* @throws IOException thrown on read error
|
||||||
|
*/
|
||||||
|
void save(UUID id, LocalSession session) throws IOException;
|
||||||
|
|
||||||
|
}
|
@ -17,34 +17,25 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.bukkit;
|
package com.sk89q.worldedit.session.storage;
|
||||||
|
|
||||||
import org.bukkit.Server;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import com.sk89q.worldedit.SessionCheck;
|
import java.io.IOException;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to remove expired sessions in Bukkit.
|
* A session store that doesn't know how to store sessions.
|
||||||
*/
|
*/
|
||||||
class SessionTimer implements Runnable {
|
public class VoidStore implements SessionStore {
|
||||||
|
|
||||||
private WorldEdit worldEdit;
|
@Override
|
||||||
private SessionCheck checker;
|
public LocalSession load(UUID id) throws IOException {
|
||||||
|
return new LocalSession();
|
||||||
SessionTimer(WorldEdit worldEdit, final Server server) {
|
|
||||||
this.worldEdit = worldEdit;
|
|
||||||
this.checker = new SessionCheck() {
|
|
||||||
public boolean isOnlinePlayer(String name) {
|
|
||||||
Player player = server.getPlayer(name);
|
|
||||||
return player != null && player.isOnline();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void save(UUID id, LocalSession session) throws IOException {
|
||||||
worldEdit.flushExpiredSessions(checker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -17,21 +17,20 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit;
|
package com.sk89q.worldedit.util;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to discard old sessions.
|
* Represents an object that can be identified by a UUID.
|
||||||
*
|
|
||||||
* @author sk89q
|
|
||||||
*/
|
*/
|
||||||
public interface SessionCheck {
|
public interface Identifiable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a player is online.
|
* Get the UUID for this object.
|
||||||
*
|
*
|
||||||
* @param name
|
* @return the UUID
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public boolean isOnlinePlayer(String name);
|
UUID getUniqueId();
|
||||||
|
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ package com.sk89q.worldedit.util;
|
|||||||
import com.sk89q.util.yaml.YAMLProcessor;
|
import com.sk89q.util.yaml.YAMLProcessor;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.session.SessionManager;
|
||||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -106,7 +107,7 @@ public class YAMLConfiguration extends LocalConfiguration {
|
|||||||
|
|
||||||
allowSymlinks = config.getBoolean("files.allow-symbolic-links", false);
|
allowSymlinks = config.getBoolean("files.allow-symbolic-links", false);
|
||||||
LocalSession.MAX_HISTORY_SIZE = Math.max(0, config.getInt("history.size", 15));
|
LocalSession.MAX_HISTORY_SIZE = Math.max(0, config.getInt("history.size", 15));
|
||||||
LocalSession.EXPIRATION_GRACE = config.getInt("history.expiration", 10) * 60 * 1000;
|
SessionManager.EXPIRATION_GRACE = config.getInt("history.expiration", 10) * 60 * 1000;
|
||||||
|
|
||||||
showHelpInfo = config.getBoolean("show-help-on-first-use", true);
|
showHelpInfo = config.getBoolean("show-help-on-first-use", true);
|
||||||
|
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.util.auth;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raised when authorization is not granted.
|
||||||
|
*/
|
||||||
|
public class AuthorizationException extends WorldEditException {
|
||||||
|
|
||||||
|
public AuthorizationException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
51
src/main/java/com/sk89q/worldedit/util/auth/Subject.java
Normal file
51
src/main/java/com/sk89q/worldedit/util/auth/Subject.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.util.auth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subject has authorization attached to it.
|
||||||
|
*/
|
||||||
|
public interface Subject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of groups that this subject is a part of.
|
||||||
|
*
|
||||||
|
* @return an array containing a group name per entry
|
||||||
|
*/
|
||||||
|
String[] getGroups();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this subject has been granted the given permission
|
||||||
|
* and throw an exception on error.
|
||||||
|
*
|
||||||
|
* @param permission the permission
|
||||||
|
* @throws AuthorizationException thrown if not permitted
|
||||||
|
*/
|
||||||
|
void checkPermission(String permission) throws AuthorizationException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this subject has the given permission.
|
||||||
|
*
|
||||||
|
* @param permission the permission
|
||||||
|
* @return true if permission is granted
|
||||||
|
*/
|
||||||
|
boolean hasPermission(String permission);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.util.concurrency;
|
||||||
|
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Even more {@code ExecutorService} factory methods.
|
||||||
|
*/
|
||||||
|
public final class EvenMoreExecutors {
|
||||||
|
|
||||||
|
private EvenMoreExecutors() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a thread pool that creates new threads as needed up to
|
||||||
|
* a maximum number of threads, but will reuse previously constructed
|
||||||
|
* threads when they are available.
|
||||||
|
*
|
||||||
|
* @param minThreads the minimum number of threads to have at a given time
|
||||||
|
* @param maxThreads the maximum number of threads to have at a given time
|
||||||
|
* @param queueSize the size of the queue before new submissions are rejected
|
||||||
|
* @return the newly created thread pool
|
||||||
|
*/
|
||||||
|
public static ExecutorService newBoundedCachedThreadPool(int minThreads, int maxThreads, int queueSize) {
|
||||||
|
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
|
||||||
|
minThreads, maxThreads,
|
||||||
|
60L, TimeUnit.SECONDS,
|
||||||
|
new ArrayBlockingQueue<Runnable>(queueSize));
|
||||||
|
threadPoolExecutor.allowCoreThreadTimeOut(true);
|
||||||
|
return threadPoolExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java
Normal file
44
src/main/java/com/sk89q/worldedit/util/gson/GsonUtil.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit 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.worldedit.util.gson;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.sk89q.worldedit.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for Google's GSON library.
|
||||||
|
*/
|
||||||
|
public final class GsonUtil {
|
||||||
|
|
||||||
|
private GsonUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a standard {@link GsonBuilder} for WorldEdit.
|
||||||
|
*
|
||||||
|
* @return a builder
|
||||||
|
*/
|
||||||
|
public static GsonBuilder createBuilder() {
|
||||||
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
|
gsonBuilder.registerTypeAdapter(Vector.class, new VectorAdapter());
|
||||||
|
return gsonBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user