mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-11-04 20:06:06 +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;
|
||||
|
||||
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.internal.cui.CUIEvent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
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 WorldEditPlugin plugin;
|
||||
|
||||
@ -44,6 +52,11 @@ public class BukkitCommandSender implements Actor {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return DEFAULT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return sender.getName();
|
||||
@ -93,7 +106,7 @@ public class BukkitCommandSender implements Actor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(String permission) throws WorldEditPermissionException {
|
||||
public void checkPermission(String permission) throws AuthorizationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,4 +128,29 @@ public class BukkitCommandSender implements Actor {
|
||||
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.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitPlayer extends LocalPlayer {
|
||||
|
||||
private Player player;
|
||||
private WorldEditPlugin plugin;
|
||||
|
||||
@ -46,6 +50,11 @@ public class BukkitPlayer extends LocalPlayer {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack itemStack = player.getItemInHand();
|
||||
@ -192,4 +201,48 @@ public class BukkitPlayer extends LocalPlayer {
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
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.PlayerGameModeChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
/**
|
||||
* Handles all events thrown in relation to a Player
|
||||
@ -62,20 +61,6 @@ public class WorldEditListener implements Listener {
|
||||
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)
|
||||
public void onGamemode(PlayerGameModeChangeEvent event) {
|
||||
if (!plugin.getInternalPlatform().isHookingEvents()) {
|
||||
|
@ -110,9 +110,6 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
||||
// Now we can register events
|
||||
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
|
||||
// Forge WorldEdit and there's (probably) not going to be any other
|
||||
// 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.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@ -34,6 +35,7 @@ import net.minecraft.network.packet.Packet250CustomPayload;
|
||||
import net.minecraft.util.ChatMessageComponent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
@ -41,13 +43,21 @@ public class ForgePlayer extends AbstractPlayerActor {
|
||||
|
||||
protected ForgePlayer(EntityPlayerMP player) {
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUniqueID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
ItemStack is = this.player.getCurrentEquippedItem();
|
||||
return is == null ? 0 : is.itemID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.username;
|
||||
}
|
||||
@ -67,26 +77,32 @@ public class ForgePlayer extends AbstractPlayerActor {
|
||||
this.player.cameraPitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getPosition() {
|
||||
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() {
|
||||
return ForgeWorldEdit.inst.getWorld(this.player.worldObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getPitch() {
|
||||
return this.player.rotationPitch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getYaw() {
|
||||
return this.player.rotationYaw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(int type, int amt) {
|
||||
this.player.inventory.addItemStackToInventory(new ItemStack(type, amt, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
@ -97,42 +113,50 @@ public class ForgePlayer extends AbstractPlayerActor {
|
||||
this.player.playerNetServerHandler.sendPacketToPlayer(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a77" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7d" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendChatToPlayer(ChatMessageComponent.createFromText("\u00a7c" + part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector pos, float pitch, float yaw) {
|
||||
this.player.playerNetServerHandler.setPlayerLocation(pos.getX(), pos.getY(), pos.getZ(), pitch, yaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return ForgeUtil.hasPermission(this.player, perm);
|
||||
}
|
||||
@ -143,4 +167,45 @@ public class ForgePlayer extends AbstractPlayerActor {
|
||||
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.EventHandler;
|
||||
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.registry.TickRegistry;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@ -84,6 +91,8 @@ public class ForgeWorldEdit {
|
||||
|
||||
config = new ForgeConfiguration(this);
|
||||
config.load();
|
||||
|
||||
TickRegistry.registerTickHandler(ThreadSafeCache.getInstance(), Side.SERVER);
|
||||
}
|
||||
|
||||
@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.session.ClipboardHolder;
|
||||
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.snapshot.Snapshot;
|
||||
|
||||
@ -52,57 +49,102 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
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 history and settings. Sessions are not tied particularly to any
|
||||
* player and can be shuffled between players, saved, and loaded.
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores session information.
|
||||
*/
|
||||
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;
|
||||
public static int EXPIRATION_GRACE = 600000;
|
||||
// Non-session related fields
|
||||
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;
|
||||
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;
|
||||
// Saved properties
|
||||
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.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return
|
||||
* @return the timezone
|
||||
*/
|
||||
public TimeZone getTimeZone() {
|
||||
return timezone;
|
||||
@ -111,9 +153,10 @@ public class LocalSession {
|
||||
/**
|
||||
* Set the session's timezone.
|
||||
*
|
||||
* @param timezone
|
||||
* @param timezone the user's timezone
|
||||
*/
|
||||
public void setTimezone(TimeZone timezone) {
|
||||
checkNotNull(timezone);
|
||||
this.timezone = timezone;
|
||||
}
|
||||
|
||||
@ -129,9 +172,11 @@ public class LocalSession {
|
||||
* Remember an edit session for the undo history. If the history maximum
|
||||
* size is reached, old edit sessions will be discarded.
|
||||
*
|
||||
* @param editSession
|
||||
* @param editSession the edit session
|
||||
*/
|
||||
public void remember(EditSession editSession) {
|
||||
checkNotNull(editSession);
|
||||
|
||||
// Don't store anything if no changes were made
|
||||
if (editSession.size() == 0) return;
|
||||
|
||||
@ -149,8 +194,8 @@ public class LocalSession {
|
||||
/**
|
||||
* Performs an undo.
|
||||
*
|
||||
* @param newBlockBag
|
||||
* @param player
|
||||
* @param newBlockBag a new block bag
|
||||
* @param player the player
|
||||
* @return whether anything was undone
|
||||
*/
|
||||
public EditSession undo(BlockBag newBlockBag, LocalPlayer player) {
|
||||
@ -160,11 +205,13 @@ public class LocalSession {
|
||||
/**
|
||||
* Performs an undo.
|
||||
*
|
||||
* @param newBlockBag
|
||||
* @param player
|
||||
* @param newBlockBag a new block bag
|
||||
* @param player the player
|
||||
* @return whether anything was undone
|
||||
*/
|
||||
public EditSession undo(BlockBag newBlockBag, Player player) {
|
||||
checkNotNull(newBlockBag);
|
||||
checkNotNull(player);
|
||||
--historyPointer;
|
||||
if (historyPointer >= 0) {
|
||||
EditSession editSession = history.get(historyPointer);
|
||||
@ -183,8 +230,8 @@ public class LocalSession {
|
||||
/**
|
||||
* Performs a redo
|
||||
*
|
||||
* @param newBlockBag
|
||||
* @param player
|
||||
* @param newBlockBag a new block bag
|
||||
* @param player the player
|
||||
* @return whether anything was redone
|
||||
*/
|
||||
public EditSession redo(BlockBag newBlockBag, LocalPlayer player) {
|
||||
@ -194,11 +241,13 @@ public class LocalSession {
|
||||
/**
|
||||
* Performs a redo
|
||||
*
|
||||
* @param newBlockBag
|
||||
* @param player
|
||||
* @param newBlockBag a new block bag
|
||||
* @param player the player
|
||||
* @return whether anything was redone
|
||||
*/
|
||||
public EditSession redo(BlockBag newBlockBag, Player player) {
|
||||
checkNotNull(newBlockBag);
|
||||
checkNotNull(player);
|
||||
if (historyPointer < history.size()) {
|
||||
EditSession editSession = history.get(historyPointer);
|
||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
||||
@ -213,6 +262,9 @@ public class LocalSession {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getRegionSelector(World)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RegionSelector getRegionSelector(LocalWorld world) {
|
||||
return getRegionSelector((World) world);
|
||||
@ -222,10 +274,11 @@ public class LocalSession {
|
||||
* Get the region selector for defining the selection. If the selection
|
||||
* was defined for a different world, the old selection will be discarded.
|
||||
*
|
||||
* @param world
|
||||
* @return position
|
||||
* @param world the world
|
||||
* @return position the position
|
||||
*/
|
||||
public RegionSelector getRegionSelector(World world) {
|
||||
checkNotNull(world);
|
||||
if (selector.getIncompleteRegion().getWorld() == null) {
|
||||
selector = new CuboidRegionSelector(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
|
||||
* this region selector isn't used blindly.
|
||||
*
|
||||
* @return position
|
||||
* @deprecated use {@link #getRegionSelector(World)}
|
||||
*/
|
||||
@Deprecated
|
||||
public RegionSelector getRegionSelector() {
|
||||
return selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #setRegionSelector(World, RegionSelector)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRegionSelector(LocalWorld world, RegionSelector selector) {
|
||||
setRegionSelector((World) world, selector);
|
||||
@ -254,10 +307,12 @@ public class LocalSession {
|
||||
/**
|
||||
* Set the region selector.
|
||||
*
|
||||
* @param world
|
||||
* @param selector
|
||||
* @param world the world
|
||||
* @param selector the selector
|
||||
*/
|
||||
public void setRegionSelector(World world, RegionSelector selector) {
|
||||
checkNotNull(world);
|
||||
checkNotNull(selector);
|
||||
selector.getIncompleteRegion().setWorld(world);
|
||||
this.selector = selector;
|
||||
}
|
||||
@ -265,13 +320,16 @@ public class LocalSession {
|
||||
/**
|
||||
* Returns true if the region is fully defined.
|
||||
*
|
||||
* @return
|
||||
* @return true if a region selection is defined
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isRegionDefined() {
|
||||
return selector.isDefined();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #isSelectionDefined(World)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isSelectionDefined(LocalWorld world) {
|
||||
return isSelectionDefined((World) world);
|
||||
@ -280,10 +338,11 @@ public class LocalSession {
|
||||
/**
|
||||
* Returns true if the region is fully defined for the specified world.
|
||||
*
|
||||
* @param world
|
||||
* @return
|
||||
* @param world the world
|
||||
* @return true if a region selection is defined
|
||||
*/
|
||||
public boolean isSelectionDefined(World world) {
|
||||
checkNotNull(world);
|
||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||
return false;
|
||||
}
|
||||
@ -291,16 +350,16 @@ public class LocalSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use <code>getSelection()</code>.
|
||||
*
|
||||
* @return region
|
||||
* @throws IncompleteRegionException
|
||||
* @deprecated use {@link #getSelection(World)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
return selector.getRegion();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getSelection(World)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Region getSelection(LocalWorld world) throws IncompleteRegionException {
|
||||
return getSelection((World) world);
|
||||
@ -309,14 +368,15 @@ public class LocalSession {
|
||||
/**
|
||||
* Get the selection region. If you change the region, you should
|
||||
* 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.
|
||||
*
|
||||
* @param world
|
||||
* @return region
|
||||
* @throws IncompleteRegionException
|
||||
* @param world the world
|
||||
* @return a region
|
||||
* @throws IncompleteRegionException if no region is selected
|
||||
*/
|
||||
public Region getSelection(World world) throws IncompleteRegionException {
|
||||
checkNotNull(world);
|
||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
@ -326,7 +386,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Get the selection world.
|
||||
*
|
||||
* @return
|
||||
* @return the the world of the selection
|
||||
*/
|
||||
public World getSelectionWorld() {
|
||||
return selector.getIncompleteRegion().getWorld();
|
||||
@ -335,7 +395,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Gets the clipboard.
|
||||
*
|
||||
* @return clipboard, may be null
|
||||
* @return clipboard
|
||||
* @throws EmptyClipboardException thrown if no clipboard is set
|
||||
*/
|
||||
public ClipboardHolder getClipboard() throws EmptyClipboardException {
|
||||
@ -368,7 +428,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Change tool control setting.
|
||||
*
|
||||
* @param toolControl
|
||||
* @param toolControl true to enable tool control
|
||||
*/
|
||||
public void setToolControl(boolean toolControl) {
|
||||
this.toolControl = toolControl;
|
||||
@ -386,7 +446,7 @@ public class LocalSession {
|
||||
/**
|
||||
* 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) {
|
||||
this.maxBlocksChanged = maxBlocksChanged;
|
||||
@ -418,7 +478,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Toggle the super pick axe.
|
||||
*
|
||||
* @return status
|
||||
* @return whether the super pick axe is now enabled
|
||||
*/
|
||||
public boolean toggleSuperPickAxe() {
|
||||
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
|
||||
* @return position
|
||||
* @throws IncompleteRegionException
|
||||
* @param player the player
|
||||
* @return the position to use
|
||||
* @throws IncompleteRegionException thrown if a region is not fully selected
|
||||
*/
|
||||
public Vector getPlacementPosition(Player player) throws IncompleteRegionException {
|
||||
checkNotNull(player);
|
||||
if (!placeAtPos1) {
|
||||
return player.getBlockIn();
|
||||
}
|
||||
@ -443,7 +505,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Toggle placement position.
|
||||
*
|
||||
* @return
|
||||
* @return whether "place at position 1" is now enabled
|
||||
*/
|
||||
public boolean togglePlacementPosition() {
|
||||
placeAtPos1 = !placeAtPos1;
|
||||
@ -453,10 +515,12 @@ public class LocalSession {
|
||||
/**
|
||||
* Get a block bag for a player.
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
* @param player the player to get the block bag for
|
||||
* @return a block bag
|
||||
*/
|
||||
@Nullable
|
||||
public BlockBag getBlockBag(Player player) {
|
||||
checkNotNull(player);
|
||||
if (!useInventory) {
|
||||
return null;
|
||||
}
|
||||
@ -468,6 +532,7 @@ public class LocalSession {
|
||||
*
|
||||
* @return the snapshot
|
||||
*/
|
||||
@Nullable
|
||||
public Snapshot getSnapshot() {
|
||||
return snapshot;
|
||||
}
|
||||
@ -475,34 +540,38 @@ public class LocalSession {
|
||||
/**
|
||||
* Select a snapshot.
|
||||
*
|
||||
* @param snapshot
|
||||
* @param snapshot a snapshot
|
||||
*/
|
||||
public void setSnapshot(Snapshot snapshot) {
|
||||
public void setSnapshot(@Nullable Snapshot snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the superPickaxeMode
|
||||
* Get the assigned block tool.
|
||||
*
|
||||
* @return the super pickaxe tool mode
|
||||
*/
|
||||
public BlockTool getSuperPickaxe() {
|
||||
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) {
|
||||
checkNotNull(tool);
|
||||
this.pickaxeMode = tool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tool assigned to the item.
|
||||
*
|
||||
* @param item
|
||||
* @return the tool
|
||||
* @param item the item type ID
|
||||
* @return the tool, which may be {@link null}
|
||||
*/
|
||||
@Nullable
|
||||
public Tool getTool(int 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
|
||||
* brush tool.
|
||||
*
|
||||
* @param item
|
||||
* @return the tool
|
||||
* @throws InvalidToolBindException
|
||||
* @param item the item type ID
|
||||
* @return the tool, or {@code null}
|
||||
* @throws InvalidToolBindException if the item can't be bound to that item
|
||||
*/
|
||||
@Nullable
|
||||
public BrushTool getBrushTool(int item) throws InvalidToolBindException {
|
||||
Tool tool = getTool(item);
|
||||
|
||||
@ -530,11 +600,11 @@ public class LocalSession {
|
||||
/**
|
||||
* Set the tool.
|
||||
*
|
||||
* @param item
|
||||
* @param tool the tool to set
|
||||
* @throws InvalidToolBindException
|
||||
* @param item the item type ID
|
||||
* @param tool the tool to set, which can be {@code null}
|
||||
* @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) {
|
||||
throw new InvalidToolBindException(item, "Blocks can't be used");
|
||||
} else if (item == config.wandItem) {
|
||||
@ -549,7 +619,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Returns whether inventory usage is enabled for this session.
|
||||
*
|
||||
* @return the useInventory
|
||||
* @return if inventory is being used
|
||||
*/
|
||||
public boolean isUsingInventory() {
|
||||
return useInventory;
|
||||
@ -558,7 +628,7 @@ public class LocalSession {
|
||||
/**
|
||||
* 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) {
|
||||
this.useInventory = useInventory;
|
||||
@ -567,8 +637,9 @@ public class LocalSession {
|
||||
/**
|
||||
* Get the last script used.
|
||||
*
|
||||
* @return the lastScript
|
||||
* @return the last script's name
|
||||
*/
|
||||
@Nullable
|
||||
public String getLastScript() {
|
||||
return lastScript;
|
||||
}
|
||||
@ -576,58 +647,55 @@ public class LocalSession {
|
||||
/**
|
||||
* 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;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the player the WorldEdit version.
|
||||
*
|
||||
* @param player
|
||||
* @param player the player
|
||||
*/
|
||||
@SuppressWarnings({"PointlessBooleanExpression", "ConstantConditions"})
|
||||
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 event
|
||||
* @param actor the actor
|
||||
* @param event the event
|
||||
*/
|
||||
public void dispatchCUIEvent(Actor player, CUIEvent event) {
|
||||
public void dispatchCUIEvent(Actor actor, CUIEvent event) {
|
||||
checkNotNull(actor);
|
||||
checkNotNull(event);
|
||||
|
||||
if (hasCUISupport) {
|
||||
player.dispatchCUIEvent(event);
|
||||
actor.dispatchCUIEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
dispatchCUISelection(player);
|
||||
dispatchCUISelection(actor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the selection information.
|
||||
*
|
||||
* @param player
|
||||
* @param actor the actor
|
||||
*/
|
||||
public void dispatchCUISelection(Player player) {
|
||||
public void dispatchCUISelection(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
|
||||
if (!hasCUISupport) {
|
||||
return;
|
||||
}
|
||||
@ -636,17 +704,24 @@ public class LocalSession {
|
||||
CUIRegion tempSel = (CUIRegion) selector;
|
||||
|
||||
if (tempSel.getProtocolVersion() > cuiVersion) {
|
||||
player.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID()));
|
||||
tempSel.describeLegacyCUI(this, player);
|
||||
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID()));
|
||||
tempSel.describeLegacyCUI(this, actor);
|
||||
} else {
|
||||
player.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID()));
|
||||
tempSel.describeCUI(this, player);
|
||||
actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID()));
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
@ -655,15 +730,22 @@ public class LocalSession {
|
||||
CUIRegion tempSel = (CUIRegion) selector;
|
||||
|
||||
if (tempSel.getProtocolVersion() > cuiVersion) {
|
||||
tempSel.describeLegacyCUI(this, player);
|
||||
tempSel.describeLegacyCUI(this, actor);
|
||||
} else {
|
||||
tempSel.describeCUI(this, player);
|
||||
tempSel.describeCUI(this, actor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a CUI initialization message.
|
||||
*
|
||||
* @param text the message
|
||||
*/
|
||||
public void handleCUIInitializationMessage(String text) {
|
||||
checkNotNull(text);
|
||||
|
||||
String[] split = text.split("\\|");
|
||||
if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message
|
||||
setCUISupport(true);
|
||||
@ -678,7 +760,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Gets the status of CUI support.
|
||||
*
|
||||
* @return
|
||||
* @return true if CUI is enabled
|
||||
*/
|
||||
public boolean hasCUISupport() {
|
||||
return hasCUISupport;
|
||||
@ -687,7 +769,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Sets the status of CUI support.
|
||||
*
|
||||
* @param support
|
||||
* @param support true if CUI is enabled
|
||||
*/
|
||||
public void setCUISupport(boolean support) {
|
||||
hasCUISupport = support;
|
||||
@ -696,7 +778,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Gets the client's CUI protocol version
|
||||
*
|
||||
* @return
|
||||
* @return the CUI version
|
||||
*/
|
||||
public int getCUIVersion() {
|
||||
return cuiVersion;
|
||||
@ -705,7 +787,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Sets the client's CUI protocol version
|
||||
*
|
||||
* @param cuiVersion
|
||||
* @param cuiVersion the CUI version
|
||||
*/
|
||||
public void setCUIVersion(int cuiVersion) {
|
||||
this.cuiVersion = cuiVersion;
|
||||
@ -714,10 +796,13 @@ public class LocalSession {
|
||||
/**
|
||||
* Detect date from a user's input.
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
* @param input the input to parse
|
||||
* @return a date
|
||||
*/
|
||||
@Nullable
|
||||
public Calendar detectDate(String input) {
|
||||
checkNotNull(input);
|
||||
|
||||
Time.setTimeZone(getTimeZone());
|
||||
Options opt = new com.sk89q.jchronic.Options();
|
||||
opt.setNow(Calendar.getInstance(getTimeZone()));
|
||||
@ -730,27 +815,9 @@ public class LocalSession {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the last update time for calculating expiration.
|
||||
*/
|
||||
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 use {@link #createEditSession(Player)}
|
||||
*/
|
||||
@Deprecated
|
||||
public EditSession createEditSession(LocalPlayer player) {
|
||||
return createEditSession((Player) player);
|
||||
}
|
||||
@ -758,11 +825,13 @@ public class LocalSession {
|
||||
/**
|
||||
* Construct a new edit session.
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
* @param player the player
|
||||
* @return an edit session
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public EditSession createEditSession(Player player) {
|
||||
checkNotNull(player);
|
||||
|
||||
BlockBag blockBag = getBlockBag(player);
|
||||
|
||||
// Create an edit session
|
||||
@ -779,7 +848,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Checks if the session has fast mode enabled.
|
||||
*
|
||||
* @return
|
||||
* @return true if fast mode is enabled
|
||||
*/
|
||||
public boolean hasFastMode() {
|
||||
return fastMode;
|
||||
@ -788,7 +857,7 @@ public class LocalSession {
|
||||
/**
|
||||
* Set fast mode.
|
||||
*
|
||||
* @param fastMode
|
||||
* @param fastMode true if fast mode is enabled
|
||||
*/
|
||||
public void setFastMode(boolean 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.
|
||||
*
|
||||
|
@ -24,6 +24,7 @@ import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
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.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
@ -78,6 +79,7 @@ public class WorldEditCommands {
|
||||
@CommandPermissions("worldedit.reload")
|
||||
public void reload(Actor actor) throws WorldEditException {
|
||||
we.getServer().reload();
|
||||
we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||
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/>.
|
||||
*/
|
||||
|
||||
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 {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public WorldEditPermissionException() {
|
||||
super("You don't have permission to do this.");
|
||||
}
|
||||
public class PlatformInitializeEvent extends Event {
|
||||
}
|
@ -19,13 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||
import com.sk89q.worldedit.BlockWorldVector;
|
||||
import com.sk89q.worldedit.LocalPlayer;
|
||||
import com.sk89q.worldedit.NotABlockException;
|
||||
import com.sk89q.worldedit.PlayerDirection;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.WorldEditPermissionException;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.WorldVectorFace;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
@ -464,9 +464,9 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(String permission) throws WorldEditPermissionException {
|
||||
public void checkPermission(String permission) throws AuthorizationException {
|
||||
if (!hasPermission(permission)) {
|
||||
throw new WorldEditPermissionException();
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,16 +19,17 @@
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditPermissionException;
|
||||
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;
|
||||
|
||||
/**
|
||||
* An object that can perform actions in WorldEdit.
|
||||
*/
|
||||
public interface Actor {
|
||||
public interface Actor extends Identifiable, SessionOwner, Subject {
|
||||
|
||||
/**
|
||||
* Get the name of the actor.
|
||||
@ -72,30 +73,6 @@ public interface Actor {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -19,12 +19,22 @@
|
||||
|
||||
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.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.event.platform.BlockInteractEvent;
|
||||
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||
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.PlayerInputEvent;
|
||||
import com.sk89q.worldedit.internal.ServerInterfaceAdapter;
|
||||
@ -34,8 +44,13 @@ import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
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.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -56,6 +71,8 @@ public class PlatformManager {
|
||||
private final List<Platform> platforms = new ArrayList<Platform>();
|
||||
private final Map<Capability, Platform> preferences = new EnumMap<Capability, Platform>(Capability.class);
|
||||
private @Nullable String firstSeenVersion;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final AtomicBoolean configured = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
* Create a new platform manager.
|
||||
@ -163,6 +180,11 @@ public class PlatformManager {
|
||||
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
|
||||
public void handlePlatformReady(PlatformReadyEvent event) {
|
||||
choosePreferred();
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
worldEdit.getEventBus().post(new PlatformInitializeEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -25,11 +25,14 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
class PlayerProxy extends AbstractPlayerActor {
|
||||
@ -50,6 +53,11 @@ class PlayerProxy extends AbstractPlayerActor {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return basePlayer.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemInHand() {
|
||||
return basePlayer.getItemInHand();
|
||||
@ -145,4 +153,9 @@ class PlayerProxy extends AbstractPlayerActor {
|
||||
public <T> T getFacet(Class<? extends T> 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;
|
||||
|
||||
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.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 java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Session manager for WorldEdit.
|
||||
* </p>
|
||||
* Get a reference to one from {@link WorldEdit}.
|
||||
* </p>
|
||||
* While this class is thread-safe, the returned session may not be.
|
||||
*
|
||||
* <p>Get a reference to one from {@link WorldEdit}.</p>
|
||||
*
|
||||
* <p>While this class is thread-safe, the returned session may not be.</p>
|
||||
*/
|
||||
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 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.
|
||||
@ -48,73 +73,98 @@ public class SessionManager {
|
||||
* @param worldEdit a WorldEdit instance
|
||||
*/
|
||||
public SessionManager(WorldEdit worldEdit) {
|
||||
checkNotNull(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
|
||||
*/
|
||||
public synchronized boolean contains(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
return sessions.containsKey(getKey(actor));
|
||||
public synchronized boolean contains(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
return sessions.containsKey(getKey(owner));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session for an actor and return it if it exists, otherwise
|
||||
* return <code>null</code>.
|
||||
* Find a session by its name specified by {@link SessionKey#getName()}.
|
||||
*
|
||||
* @param actor the actor
|
||||
* @return the session for the actor, if it exists
|
||||
* @param name the name
|
||||
* @return the session, if found, otherwise {@code null}
|
||||
*/
|
||||
public synchronized @Nullable LocalSession find(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
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) {
|
||||
@Nullable
|
||||
public synchronized LocalSession findByName(String 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
|
||||
*/
|
||||
public synchronized LocalSession get(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
public synchronized LocalSession get(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
|
||||
LocalSession session;
|
||||
LocalSession session = getIfPresent(owner);
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
SessionKey sessionKey = owner.getSessionKey();
|
||||
|
||||
if (sessions.containsKey(actor.getName())) {
|
||||
session = sessions.get(actor.getName());
|
||||
} else {
|
||||
session = new LocalSession(config);
|
||||
// No session exists yet -- create one
|
||||
if (session == null) {
|
||||
try {
|
||||
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);
|
||||
// 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
|
||||
// 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
|
||||
int currentChangeLimit = session.getBlockChangeLimit();
|
||||
|
||||
if (!actor.hasPermission("worldedit.limit.unrestricted")
|
||||
&& config.maxChangeLimit > -1) {
|
||||
|
||||
if (!owner.hasPermission("worldedit.limit.unrestricted") && config.maxChangeLimit > -1) {
|
||||
// If the default limit is infinite but there is a maximum
|
||||
// limit, make sure to not have it be overridden
|
||||
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
|
||||
session.setUseInventory(config.useInventory
|
||||
&& !(config.useInventoryOverride
|
||||
&& (actor.hasPermission("worldedit.inventory.unrestricted")
|
||||
|| (config.useInventoryCreativeOverride && (!(actor instanceof Player) || ((Player) actor).hasCreativeMode())))));
|
||||
&& (owner.hasPermission("worldedit.inventory.unrestricted")
|
||||
|| (config.useInventoryCreativeOverride && (!(owner instanceof Player) || ((Player) owner).hasCreativeMode())))));
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key to use in the map for an actor.
|
||||
* Save a map of sessions to disk.
|
||||
*
|
||||
* @param actor the actor
|
||||
* @return the key object
|
||||
* @param sessions a map of sessions to save
|
||||
* @return a future that completes on save or error
|
||||
*/
|
||||
protected String getKey(Actor actor) {
|
||||
return actor.getName();
|
||||
private ListenableFuture<?> commit(final Map<SessionKey, LocalSession> sessions) {
|
||||
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) {
|
||||
checkNotNull(actor);
|
||||
LocalSession session = find(actor);
|
||||
if (session != null) {
|
||||
session.update();
|
||||
protected UUID getKey(SessionOwner owner) {
|
||||
return getKey(owner.getSessionKey());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
checkNotNull(actor);
|
||||
sessions.remove(actor.getName());
|
||||
public synchronized void remove(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
sessions.remove(getKey(owner));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,18 +273,61 @@ public class SessionManager {
|
||||
sessions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove expired sessions with the given session checker.
|
||||
*
|
||||
* @param checker the session checker
|
||||
*/
|
||||
public synchronized void removeExpired(SessionCheck checker) {
|
||||
Iterator<Map.Entry<String, LocalSession>> it = sessions.entrySet().iterator();
|
||||
@Subscribe
|
||||
public void onConfigurationLoad(ConfigurationLoadEvent event) {
|
||||
LocalConfiguration config = event.getConfiguration();
|
||||
File dir = new File(config.getWorkingDirectory(), "sessions");
|
||||
store = new JsonFileSessionStore(dir);
|
||||
}
|
||||
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, LocalSession> entry = it.next();
|
||||
if (entry.getValue().hasExpired() && !checker.isOnlinePlayer(entry.getKey())) {
|
||||
it.remove();
|
||||
/**
|
||||
* Stores the owner of a session, the session, and the last active time.
|
||||
*/
|
||||
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/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
package com.sk89q.worldedit.session.storage;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import com.sk89q.worldedit.SessionCheck;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
|
||||
import java.io.IOException;
|
||||
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;
|
||||
private SessionCheck checker;
|
||||
|
||||
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
|
||||
public LocalSession load(UUID id) throws IOException {
|
||||
return new LocalSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
worldEdit.flushExpiredSessions(checker);
|
||||
public void save(UUID id, LocalSession session) throws IOException {
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +1,36 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Used to discard old sessions.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public interface SessionCheck {
|
||||
|
||||
/**
|
||||
* Checks if a player is online.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public boolean isOnlinePlayer(String name);
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents an object that can be identified by a UUID.
|
||||
*/
|
||||
public interface Identifiable {
|
||||
|
||||
/**
|
||||
* Get the UUID for this object.
|
||||
*
|
||||
* @return the UUID
|
||||
*/
|
||||
UUID getUniqueId();
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ package com.sk89q.worldedit.util;
|
||||
import com.sk89q.util.yaml.YAMLProcessor;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.session.SessionManager;
|
||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -106,7 +107,7 @@ public class YAMLConfiguration extends LocalConfiguration {
|
||||
|
||||
allowSymlinks = config.getBoolean("files.allow-symbolic-links", false);
|
||||
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);
|
||||
|
||||
|
@ -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