Skip to content

Commit

Permalink
Added expiration timer to sessions. Sessions will now last up to 10 m…
Browse files Browse the repository at this point in the history
…inutes (by default) before removed, so you can quickly disconnect (or crash) and come back and still maintain your history.
  • Loading branch information
sk89q committed May 2, 2011
1 parent a18546d commit d71d4a8
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 34 deletions.
18 changes: 18 additions & 0 deletions src/main/java/com/sk89q/worldedit/LocalSession.java
Expand Up @@ -51,9 +51,11 @@
*/
public class LocalSession {
public static int MAX_HISTORY_SIZE = 15;
public static int EXPIRATION_GRACE = 600000;

private LocalConfiguration config;

private long expirationTime = 0;
private LocalWorld selectionWorld;
private RegionSelector selector = new CuboidRegionSelector();
private boolean placeAtPos1 = false;
Expand Down Expand Up @@ -615,4 +617,20 @@ public Calendar detectDate(String input) {
return date.getBeginCalendar();
}
}

/**
* 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;
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/sk89q/worldedit/SessionCheck.java
@@ -0,0 +1,37 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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);

}
116 changes: 83 additions & 33 deletions src/main/java/com/sk89q/worldedit/WorldEdit.java
Expand Up @@ -129,42 +129,46 @@ public boolean hasPermission(LocalPlayer player, String perm) {
* @return
*/
public LocalSession getSession(LocalPlayer player) {
if (sessions.containsKey(player.getName())) {
return sessions.get(player.getName());
}

LocalSession session = new LocalSession(config);
LocalSession session;

// Set the limit on the number of blocks that an operation can
// change at once, or don't if the player has an override or there
// is no limit. There is also a default limit
if (!player.hasPermission("worldedit.limit.unrestricted")
&& config.maxChangeLimit > -1) {
synchronized (sessions) {
if (sessions.containsKey(player.getName())) {
return sessions.get(player.getName());
}

// If the default limit is infinite but there is a maximum
// limit, make sure to not have it be overridden
if (config.defaultChangeLimit < 0) {
session.setBlockChangeLimit(config.maxChangeLimit);
session = new LocalSession(config);

// Set the limit on the number of blocks that an operation can
// change at once, or don't if the player has an override or there
// is no limit. There is also a default limit
if (!player.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) {
session.setBlockChangeLimit(config.maxChangeLimit);
} else {
// Bound the change limit
int limit = Math.min(config.defaultChangeLimit,
config.maxChangeLimit);
session.setBlockChangeLimit(limit);
}
} else {
// Bound the change limit
int limit = Math.min(config.defaultChangeLimit,
config.maxChangeLimit);
session.setBlockChangeLimit(limit);
// No change limit or override
session.setBlockChangeLimit(config.defaultChangeLimit);
}
} else {
// No change limit or override
session.setBlockChangeLimit(config.defaultChangeLimit);

// Have the session use inventory if it's enabled and the player
// doesn't have an override
session.setUseInventory(config.useInventory
&& (!config.useInventoryOverride
|| !player.hasPermission("worldedit.inventory.unrestricted")));

// Remember the session
sessions.put(player.getName(), session);
}

// Have the session use inventory if it's enabled and the player
// doesn't have an override
session.setUseInventory(config.useInventory
&& (!config.useInventoryOverride
|| !player.hasPermission("worldedit.inventory.unrestricted")));

// Remember the session
sessions.put(player.getName(), session);

return session;
}

Expand All @@ -175,7 +179,9 @@ public LocalSession getSession(LocalPlayer player) {
* @return
*/
public boolean hasSession(LocalPlayer player) {
return sessions.containsKey(player.getName());
synchronized (sessions) {
return sessions.containsKey(player.getName());
}
}

/**
Expand Down Expand Up @@ -726,14 +732,18 @@ public CuboidClipboard.FlipDirection getFlipDirection(
* @param player
*/
public void removeSession(LocalPlayer player) {
sessions.remove(player.getName());
synchronized (sessions) {
sessions.remove(player.getName());
}
}

/**
* Remove all sessions.
*/
public void clearSessions() {
sessions.clear();
synchronized (sessions) {
sessions.clear();
}
}

/**
Expand Down Expand Up @@ -788,9 +798,49 @@ public Map<String, String> getCommands() {
*
* @param player
*/
@Deprecated
public void handleDisconnect(LocalPlayer player) {
forgetPlayer(player);
}

/**
*
* @param player
*/
public void markExpire(LocalPlayer player) {
synchronized (sessions) {
LocalSession session = sessions.get(player.getName());
if (session != null) {
session.update();
}
}
}

/**
* Forget a player.
*
* @param player
*/
public void forgetPlayer(LocalPlayer player) {
removeSession(player);
}

/*
* Flush expired sessions.
*/
public void flushExpiredSessions(SessionCheck checker) {
synchronized (sessions) {
Iterator<Map.Entry<String, LocalSession>> it = sessions.entrySet().iterator();

while (it.hasNext()) {
Map.Entry<String, LocalSession> entry = it.next();
if (entry.getValue().hasExpired()
&& !checker.isOnlinePlayer(entry.getKey())) {
it.remove();
}
}
}
}

/**
* Called on arm swing.
Expand Down
Expand Up @@ -82,6 +82,7 @@ public void load() {
noOpPermissions = config.getBoolean("no-op-permissions", false);

LocalSession.MAX_HISTORY_SIZE = Math.max(15, config.getInt("history.size", 15));
LocalSession.EXPIRATION_GRACE = config.getInt("history.expiration", 10) * 60 * 1000;

String snapshotsDir = config.getString("snapshots.directory", "");
if (!snapshotsDir.trim().equals("")) {
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/com/sk89q/worldedit/bukkit/SessionTimer.java
@@ -0,0 +1,51 @@
// $Id$
/*
* WorldEdit
* Copyright (C) 2010, 2011 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.bukkit;

import org.bukkit.Server;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.SessionCheck;
import com.sk89q.worldedit.WorldEdit;

/**
* Used to remove expired sessions in Bukkit.
*
* @author sk89q
*/
public class SessionTimer implements Runnable {

private WorldEdit worldEdit;
private SessionCheck checker;

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

public void run() {
worldEdit.flushExpiredSessions(checker);
}

}
Expand Up @@ -79,7 +79,7 @@ public WorldEditPlayerListener(WorldEditPlugin plugin) {
*/
@Override
public void onPlayerQuit(PlayerQuitEvent event) {
plugin.getWorldEdit().handleDisconnect(wrapPlayer(event.getPlayer()));
plugin.getWorldEdit().markExpire(wrapPlayer(event.getPlayer()));
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java
Expand Up @@ -101,6 +101,9 @@ public void onEnable() {

// Now we can register events!
registerEvents();

getServer().getScheduler().scheduleAsyncRepeatingTask(this,
new SessionTimer(controller, getServer()), 120, 120);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/sk89q/worldedit/tools/BrushTool.java
Expand Up @@ -83,6 +83,7 @@ public void setMask(Mask filter) {
* Set the brush.
*
* @param brush
* @param perm
*/
public void setBrush(Brush brush, String perm) {
this.brush = brush;
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/config.yml
Expand Up @@ -52,6 +52,7 @@ saving:

history:
size: 15
expiration: 10

wand-item: 271
shell-save-type:
Expand Down

0 comments on commit d71d4a8

Please sign in to comment.