mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-12 08:18:35 +00:00
Copy paste/merge FAWE classes to this WorldEdit fork
- so certain people can look at the diff and complain about my sloppy code :( Signed-off-by: Jesse Boyd <jessepaleg@gmail.com>
This commit is contained in:
@ -19,19 +19,22 @@
|
||||
|
||||
package com.sk89q.worldedit.session;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.transform.Identity;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Holds the clipboard and the current transform on the clipboard.
|
||||
*/
|
||||
public class ClipboardHolder {
|
||||
|
||||
private final Clipboard clipboard;
|
||||
private Clipboard clipboard;
|
||||
private Transform transform = new Identity();
|
||||
|
||||
/**
|
||||
@ -44,18 +47,44 @@ public class ClipboardHolder {
|
||||
this.clipboard = clipboard;
|
||||
}
|
||||
|
||||
protected ClipboardHolder() {}
|
||||
|
||||
/**
|
||||
* Get the clipboard.
|
||||
* <p>
|
||||
* If there is a transformation applied, the returned clipboard will
|
||||
* not contain its effect.
|
||||
*
|
||||
* @deprecated FAWE supports multiple loaded schematics {@link #getClipboards()}
|
||||
* @return the clipboard
|
||||
*/
|
||||
@Deprecated
|
||||
public Clipboard getClipboard() {
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all currently held clipboards
|
||||
* @return
|
||||
*/
|
||||
public List<Clipboard> getClipboards() {
|
||||
return Collections.singletonList(getClipboard());
|
||||
}
|
||||
|
||||
public boolean contains(Clipboard clipboard) {
|
||||
return this.clipboard == clipboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all end ClipboardHolders<br/>
|
||||
* - Usually this will return itself.<br/>
|
||||
* - If this is a multi clipboard, it will return the children
|
||||
* @return Set of end ClipboardHolders
|
||||
*/
|
||||
public List<ClipboardHolder> getHolders() {
|
||||
return Collections.singletonList(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transform.
|
||||
*
|
||||
@ -84,4 +113,15 @@ public class ClipboardHolder {
|
||||
return new PasteBuilder(this, targetExtent);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (clipboard instanceof BlockArrayClipboard) {
|
||||
((BlockArrayClipboard) clipboard).close();
|
||||
}
|
||||
clipboard = null;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return ClipboardHolder.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.sk89q.worldedit.session;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
|
||||
public class DelegateClipboardHolder extends ClipboardHolder {
|
||||
private final ClipboardHolder parent;
|
||||
|
||||
public DelegateClipboardHolder(ClipboardHolder holder) {
|
||||
super(holder.getClipboard());
|
||||
this.parent = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard() {
|
||||
return parent.getClipboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(Transform transform) {
|
||||
parent.setTransform(transform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transform getTransform() {
|
||||
return parent.getTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasteBuilder createPaste(Extent targetExtent) {
|
||||
return parent.createPaste(targetExtent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
parent.close();
|
||||
}
|
||||
}
|
@ -19,17 +19,23 @@
|
||||
|
||||
package com.sk89q.worldedit.session;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Builds an operation to paste the contents of a clipboard.
|
||||
*/
|
||||
@ -41,14 +47,17 @@ public class PasteBuilder {
|
||||
|
||||
private Vector to = new Vector();
|
||||
private boolean ignoreAirBlocks;
|
||||
private boolean ignoreBiomes;
|
||||
private boolean ignoreEntities;
|
||||
private RegionFunction canApply;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param holder the clipboard holder
|
||||
* @param targetExtent an extent
|
||||
* @param holder the clipboard holder
|
||||
* @param targetExtent an extent
|
||||
*/
|
||||
PasteBuilder(ClipboardHolder holder, Extent targetExtent) {
|
||||
public PasteBuilder(ClipboardHolder holder, Extent targetExtent) {
|
||||
checkNotNull(holder);
|
||||
checkNotNull(targetExtent);
|
||||
this.clipboard = holder.getClipboard();
|
||||
@ -77,19 +86,53 @@ public class PasteBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder ignoreBiomes(boolean ignoreBiomes) {
|
||||
this.ignoreBiomes = ignoreBiomes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder ignoreEntities(boolean ignoreEntities) {
|
||||
this.ignoreEntities = ignoreEntities;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder filter(RegionFunction function) {
|
||||
this.canApply = function;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the operation.
|
||||
*
|
||||
* @return the operation
|
||||
*/
|
||||
public Operation build() {
|
||||
BlockTransformExtent extent = new BlockTransformExtent(clipboard, transform);
|
||||
Extent extent = clipboard;
|
||||
if (!transform.isIdentity()) {
|
||||
extent = new BlockTransformExtent(extent, transform);
|
||||
}
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), targetExtent, to);
|
||||
copy.setTransform(transform);
|
||||
copy.setCopyEntities(!ignoreEntities);
|
||||
copy.setCopyBiomes((!ignoreBiomes) && (!(clipboard instanceof BlockArrayClipboard) || ((BlockArrayClipboard) clipboard).IMP.hasBiomes()));
|
||||
if (this.canApply != null) {
|
||||
copy.setFilterFunction(this.canApply);
|
||||
}
|
||||
if (targetExtent instanceof EditSession) {
|
||||
Mask sourceMask = ((EditSession) targetExtent).getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(extent);
|
||||
copy.setSourceMask(sourceMask);
|
||||
((EditSession) targetExtent).setSourceMask(null);
|
||||
}
|
||||
}
|
||||
if (ignoreAirBlocks) {
|
||||
copy.setSourceMask(new ExistingBlockMask(clipboard));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return PasteBuilder.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.session;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.boydti.fawe.object.collection.SoftHashMap;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
@ -39,35 +36,41 @@ import com.sk89q.worldedit.world.gamemode.GameModes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
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.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Session manager for WorldEdit.
|
||||
*
|
||||
* <p>
|
||||
* <p>Get a reference to one from {@link WorldEdit}.</p>
|
||||
*
|
||||
* <p>
|
||||
* <p>While this class is thread-safe, the returned session may not be.</p>
|
||||
*/
|
||||
public class SessionManager {
|
||||
|
||||
@Deprecated
|
||||
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<>();
|
||||
private final Map<UUID, SessionHolder> sessions = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
private final Map<UUID, Reference<SessionHolder>> softSessions = new SoftHashMap<>();
|
||||
|
||||
private SessionStore store = new VoidStore();
|
||||
private File path;
|
||||
|
||||
/**
|
||||
* Create a new session manager.
|
||||
@ -79,7 +82,6 @@ public class SessionManager {
|
||||
this.worldEdit = worldEdit;
|
||||
|
||||
worldEdit.getEventBus().register(this);
|
||||
timer.schedule(new SessionTracker(), FLUSH_PERIOD, FLUSH_PERIOD);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +92,7 @@ public class SessionManager {
|
||||
*/
|
||||
public synchronized boolean contains(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
return sessions.containsKey(getKey(owner));
|
||||
return sessions.containsKey(getKey(owner)) || softSessions.containsKey(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +110,24 @@ public class SessionManager {
|
||||
return holder.session;
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<UUID, Reference<SessionHolder>>> iter = softSessions.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<UUID, Reference<SessionHolder>> entry = iter.next();
|
||||
UUID key = entry.getKey();
|
||||
SessionHolder holder = entry.getValue().get();
|
||||
if (holder == null) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
String test = holder.key.getName();
|
||||
if (test != null && name.equals(test)) {
|
||||
// if (holder.key.isActive()) {
|
||||
iter.remove();
|
||||
sessions.put(key, holder);
|
||||
// }
|
||||
return holder.session;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -122,12 +141,24 @@ public class SessionManager {
|
||||
@Nullable
|
||||
public synchronized LocalSession getIfPresent(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
SessionHolder stored = sessions.get(getKey(owner));
|
||||
UUID key = getKey(owner);
|
||||
SessionHolder stored = sessions.get(key);
|
||||
if (stored != null) {
|
||||
return stored.session;
|
||||
} else {
|
||||
return null;
|
||||
Reference<SessionHolder> reference = softSessions.get(key);
|
||||
if (reference != null) {
|
||||
stored = reference.get();
|
||||
if (stored != null) {
|
||||
// if (stored.key.isActive()) {
|
||||
softSessions.remove(key);
|
||||
sessions.put(key, stored);
|
||||
// }
|
||||
return stored.session;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,7 +179,7 @@ public class SessionManager {
|
||||
try {
|
||||
session = store.load(getKey(sessionKey));
|
||||
session.postLoad();
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
log.log(Level.WARNING, "Failed to load saved session", e);
|
||||
session = new LocalSession();
|
||||
}
|
||||
@ -156,10 +187,7 @@ public class SessionManager {
|
||||
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));
|
||||
}
|
||||
sessions.put(getKey(owner), new SessionHolder(sessionKey, session));
|
||||
}
|
||||
|
||||
// Set the limit on the number of blocks that an operation can
|
||||
@ -193,41 +221,27 @@ public class SessionManager {
|
||||
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((Callable<Object>) () -> {
|
||||
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;
|
||||
private void save(SessionHolder holder) {
|
||||
SessionKey key = holder.key;
|
||||
holder.session.setClipboard(null);
|
||||
if (key.isPersistent()) {
|
||||
try {
|
||||
if (holder.session.compareAndResetDirty()) {
|
||||
if (holder.session.save()) {
|
||||
store.save(getKey(key), holder.session);
|
||||
} else if (path != null) {
|
||||
File file = new File(path, getKey(key) + ".json");
|
||||
if (file.exists()) {
|
||||
if (!file.delete()) {
|
||||
file.deleteOnExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.log(Level.WARNING, "Failed to write session for UUID " + getKey(key), e);
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return sessions;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,13 +277,29 @@ public class SessionManager {
|
||||
*/
|
||||
public synchronized void remove(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
sessions.remove(getKey(owner));
|
||||
SessionHolder session = sessions.remove(getKey(owner));
|
||||
if (session != null) {
|
||||
save(session);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void forget(SessionOwner owner) {
|
||||
checkNotNull(owner);
|
||||
UUID key = getKey(owner);
|
||||
SessionHolder holder = sessions.remove(key);
|
||||
if (holder != null) {
|
||||
softSessions.put(key, new SoftReference(holder));
|
||||
save(holder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all sessions.
|
||||
*/
|
||||
public synchronized void clear() {
|
||||
for (Map.Entry<UUID, SessionHolder> entry : sessions.entrySet()) {
|
||||
save(entry.getValue());
|
||||
}
|
||||
sessions.clear();
|
||||
}
|
||||
|
||||
@ -278,6 +308,7 @@ public class SessionManager {
|
||||
LocalConfiguration config = event.getConfiguration();
|
||||
File dir = new File(config.getWorkingDirectory(), "sessions");
|
||||
store = new JsonFileSessionStore(dir);
|
||||
this.path = dir;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,42 +325,9 @@ public class SessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static Class<?> inject() {
|
||||
return SessionManager.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -21,8 +21,8 @@ package com.sk89q.worldedit.session.request;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@ -32,9 +32,18 @@ public final class Request {
|
||||
|
||||
private static final ThreadLocal<Request> threadLocal = ThreadLocal.withInitial(Request::new);
|
||||
|
||||
private @Nullable World world;
|
||||
private @Nullable LocalSession session;
|
||||
private @Nullable EditSession editSession;
|
||||
private
|
||||
@Nullable
|
||||
World world;
|
||||
private
|
||||
@Nullable
|
||||
LocalSession session;
|
||||
private
|
||||
@Nullable
|
||||
EditSession editSession;
|
||||
private
|
||||
@Nullable
|
||||
Extent extent;
|
||||
|
||||
private Request() {
|
||||
}
|
||||
@ -44,7 +53,9 @@ public final class Request {
|
||||
*
|
||||
* @return the world, which may be null
|
||||
*/
|
||||
public @Nullable World getWorld() {
|
||||
public
|
||||
@Nullable
|
||||
World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@ -57,12 +68,27 @@ public final class Request {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void setExtent(@Nullable Extent extent) {
|
||||
this.extent = extent;
|
||||
}
|
||||
|
||||
public
|
||||
@Nullable
|
||||
Extent getExtent() {
|
||||
if (extent != null) return extent;
|
||||
if (editSession != null) return editSession;
|
||||
if (world != null) return world;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request session.
|
||||
*
|
||||
* @return the session, which may be null
|
||||
*/
|
||||
public @Nullable LocalSession getSession() {
|
||||
public
|
||||
@Nullable
|
||||
LocalSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@ -80,7 +106,9 @@ public final class Request {
|
||||
*
|
||||
* @return the edit session, which may be null
|
||||
*/
|
||||
public @Nullable EditSession getEditSession() {
|
||||
public
|
||||
@Nullable
|
||||
EditSession getEditSession() {
|
||||
return editSession;
|
||||
}
|
||||
|
||||
@ -108,4 +136,8 @@ public final class Request {
|
||||
public static void reset() {
|
||||
threadLocal.remove();
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Request.class;
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.session.request;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.regions.NullRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.session.storage;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonIOException;
|
||||
@ -40,6 +38,8 @@ 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.
|
||||
*
|
||||
|
Reference in New Issue
Block a user