Switch to Gradle. Use git log --follow for history.

This converts the project into a multi-module Gradle build.

By default, Git does not show history past a rename, so use git log
--follow to see further history.
This commit is contained in:
sk89q
2014-11-14 11:27:39 -08:00
parent 44559cde68
commit 7192780251
714 changed files with 333 additions and 834 deletions

View File

@ -0,0 +1,101 @@
/*
* 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.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.registry.WorldData;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Holds the clipboard and the current transform on the clipboard.
*/
public class ClipboardHolder {
private final WorldData worldData;
private final Clipboard clipboard;
private Transform transform = new Identity();
/**
* Create a new instance with the given clipboard.
*
* @param clipboard the clipboard
* @param worldData the mapping of blocks, entities, and so on
*/
public ClipboardHolder(Clipboard clipboard, WorldData worldData) {
checkNotNull(clipboard);
checkNotNull(worldData);
this.clipboard = clipboard;
this.worldData = worldData;
}
/**
* Get the mapping used for blocks, entities, and so on.
*
* @return the mapping
*/
public WorldData getWorldData() {
return worldData;
}
/**
* Get the clipboard.
* <p>
* If there is a transformation applied, the returned clipboard will
* not contain its effect.
*
* @return the clipboard
*/
public Clipboard getClipboard() {
return clipboard;
}
/**
* Set the transform.
*
* @param transform the transform
*/
public void setTransform(Transform transform) {
checkNotNull(transform);
this.transform = transform;
}
/**
* Get the transform.
*
* @return the transform
*/
public Transform getTransform() {
return transform;
}
/**
* Create a builder for an operation to paste this clipboard.
*
* @return a builder
*/
public PasteBuilder createPaste(Extent targetExtent, WorldData targetWorldData) {
return new PasteBuilder(this, targetExtent, targetWorldData);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.registry.WorldData;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Builds an operation to paste the contents of a clipboard.
*/
public class PasteBuilder {
private final Clipboard clipboard;
private final WorldData worldData;
private final Transform transform;
private final Extent targetExtent;
private final WorldData targetWorldData;
private Vector to = new Vector();
private boolean ignoreAirBlocks;
/**
* Create a new instance.
*
* @param holder the clipboard holder
* @param targetExtent an extent
* @param targetWorldData world data of the target
*/
PasteBuilder(ClipboardHolder holder, Extent targetExtent, WorldData targetWorldData) {
checkNotNull(holder);
checkNotNull(targetExtent);
checkNotNull(targetWorldData);
this.clipboard = holder.getClipboard();
this.worldData = holder.getWorldData();
this.transform = holder.getTransform();
this.targetExtent = targetExtent;
this.targetWorldData = targetWorldData;
}
/**
* Set the target location.
*
* @param to the target location
* @return this builder instance
*/
public PasteBuilder to(Vector to) {
this.to = to;
return this;
}
/**
* Set whether air blocks in the source are skipped over when pasting.
*
* @return this builder instance
*/
public PasteBuilder ignoreAirBlocks(boolean ignoreAirBlocks) {
this.ignoreAirBlocks = ignoreAirBlocks;
return this;
}
/**
* Build the operation.
*
* @return the operation
*/
public Operation build() {
BlockTransformExtent extent = new BlockTransformExtent(clipboard, transform, targetWorldData.getBlockRegistry());
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), targetExtent, to);
copy.setTransform(transform);
if (ignoreAirBlocks) {
copy.setSourceMask(new ExistingBlockMask(clipboard));
}
return copy;
}
}

View 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();
}

View File

@ -0,0 +1,336 @@
/*
* 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.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.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>
*
* <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 Map<UUID, SessionHolder> sessions = new HashMap<UUID, SessionHolder>();
private SessionStore store = new VoidStore();
/**
* Create a new session manager.
*
* @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 owner.
*
* @param owner the owner
* @return true if a session exists
*/
public synchronized boolean contains(SessionOwner owner) {
checkNotNull(owner);
return sessions.containsKey(getKey(owner));
}
/**
* Find a session by its name specified by {@link SessionKey#getName()}.
*
* @param name the name
* @return the session, if found, otherwise {@code null}
*/
@Nullable
public synchronized LocalSession findByName(String name) {
checkNotNull(name);
for (SessionHolder holder : sessions.values()) {
String test = holder.key.getName();
if (test != null && name.equals(test)) {
return holder.session;
}
}
return null;
}
/**
* Gets the session for an owner and return it if it exists, otherwise
* return {@code null}.
*
* @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(SessionOwner owner) {
checkNotNull(owner);
LocalSession session = getIfPresent(owner);
LocalConfiguration config = worldEdit.getConfiguration();
SessionKey sessionKey = owner.getSessionKey();
// No session exists yet -- create one
if (session == null) {
try {
session = store.load(getKey(sessionKey));
session.postLoad();
} 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 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 owner has an override or there
// is no limit. There is also a default limit
int currentChangeLimit = session.getBlockChangeLimit();
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) {
if (currentChangeLimit < 0 || currentChangeLimit > config.maxChangeLimit) {
session.setBlockChangeLimit(config.maxChangeLimit);
}
} else {
// Bound the change limit
int maxChangeLimit = config.maxChangeLimit;
if (currentChangeLimit == -1 || currentChangeLimit > maxChangeLimit) {
session.setBlockChangeLimit(maxChangeLimit);
}
}
}
// Have the session use inventory if it's enabled and the owner
// doesn't have an override
session.setUseInventory(config.useInventory
&& !(config.useInventoryOverride
&& (owner.hasPermission("worldedit.inventory.unrestricted")
|| (config.useInventoryCreativeOverride && (!(owner instanceof Player) || ((Player) owner).hasCreativeMode())))));
return session;
}
/**
* Save a map of sessions to disk.
*
* @param sessions a map of sessions to save
* @return a future that completes on save or error
*/
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;
}
});
}
/**
* Get the key to use in the map for an owner.
*
* @param owner the owner
* @return the key object
*/
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 owner if one exists.
*
* @param owner the owner
*/
public synchronized void remove(SessionOwner owner) {
checkNotNull(owner);
sessions.remove(getKey(owner));
}
/**
* Remove all sessions.
*/
public synchronized void clear() {
sessions.clear();
}
@Subscribe
public void onConfigurationLoad(ConfigurationLoadEvent event) {
LocalConfiguration config = event.getConfiguration();
File dir = new File(config.getWorkingDirectory(), "sessions");
store = new JsonFileSessionStore(dir);
}
/**
* 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);
}
}
}
}
}

View File

@ -0,0 +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.session;
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();
}

View File

@ -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);
}
}

View File

@ -0,0 +1,116 @@
/*
* 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.request;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
/**
* Describes the current request using a {@link ThreadLocal}.
*/
public final class Request {
private static final ThreadLocal<Request> threadLocal =
new ThreadLocal<Request>() {
@Override protected Request initialValue() {
return new Request();
}
};
private @Nullable World world;
private @Nullable LocalSession session;
private @Nullable EditSession editSession;
private Request() {
}
/**
* Get the request world.
*
* @return the world, which may be null
*/
public @Nullable World getWorld() {
return world;
}
/**
* Set the request world.
*
* @param world the world, which may be null
*/
public void setWorld(@Nullable World world) {
this.world = world;
}
/**
* Get the request session.
*
* @return the session, which may be null
*/
public @Nullable LocalSession getSession() {
return session;
}
/**
* Get the request session.
*
* @param session the session, which may be null
*/
public void setSession(@Nullable LocalSession session) {
this.session = session;
}
/**
* Get the {@link EditSession}.
*
* @return the edit session, which may be null
*/
public @Nullable EditSession getEditSession() {
return editSession;
}
/**
* Set the {@link EditSession}.
*
* @param editSession the edit session, which may be null
*/
public void setEditSession(@Nullable EditSession editSession) {
this.editSession = editSession;
}
/**
* Get the current request, which is specific to the current thread.
*
* @return the current request
*/
public static Request request() {
return threadLocal.get();
}
/**
* Reset the current request and clear all fields.
*/
public static void reset() {
threadLocal.remove();
}
}

View File

@ -0,0 +1,156 @@
/*
* 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.request;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.world.World;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* A region that mirrors the current selection according to the current
* {@link LocalSession} and {@link LocalWorld} set on the current
* {@link Request}.
*
* <p>If a selection cannot be taken, then the selection will be assumed to be
* that of a {@link NullRegion}.</p>
*/
public class RequestSelection implements Region {
/**
* Get the delegate region.
*
* @return the delegate region
*/
protected Region getRegion() {
LocalSession session = Request.request().getSession();
World world = Request.request().getWorld();
if (session != null && world != null) {
try {
return session.getSelection(world);
} catch (IncompleteRegionException ignored) {
}
}
return new NullRegion();
}
@Override
public Vector getMinimumPoint() {
return getRegion().getMinimumPoint();
}
@Override
public Vector getMaximumPoint() {
return getRegion().getMaximumPoint();
}
@Override
public Vector getCenter() {
return getRegion().getCenter();
}
@Override
public int getArea() {
return getRegion().getArea();
}
@Override
public int getWidth() {
return getRegion().getWidth();
}
@Override
public int getHeight() {
return getRegion().getHeight();
}
@Override
public int getLength() {
return getRegion().getLength();
}
@Override
public void expand(Vector... changes) throws RegionOperationException {
getRegion().expand(changes);
}
@Override
public void contract(Vector... changes) throws RegionOperationException {
getRegion().contract(changes);
}
@Override
public void shift(Vector change) throws RegionOperationException {
getRegion().shift(change);
}
@Override
public boolean contains(Vector position) {
return getRegion().contains(position);
}
@Override
public Set<Vector2D> getChunks() {
return getRegion().getChunks();
}
@Override
public Set<Vector> getChunkCubes() {
return getRegion().getChunkCubes();
}
@Override
public World getWorld() {
return getRegion().getWorld();
}
@Override
public void setWorld(LocalWorld world) {
setWorld((World) world);
}
@Override
public void setWorld(World world) {
getRegion().setWorld(world);
}
@Override
public Region clone() {
return this;
}
@Override
public List<BlockVector2D> polygonize(int maxPoints) {
return getRegion().polygonize(maxPoints);
}
@Override
public Iterator<BlockVector> iterator() {
return getRegion().iterator();
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}

View File

@ -0,0 +1,41 @@
/*
* 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;
/**
* A session store that doesn't know how to store sessions.
*/
public class VoidStore implements SessionStore {
@Override
public LocalSession load(UUID id) throws IOException {
return new LocalSession();
}
@Override
public void save(UUID id, LocalSession session) throws IOException {
}
}