summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Essentials/src/com/earth2me/essentials/api/IGroups.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/api/ISettings.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/api/IUser.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/commands/Commandpowertool.java8
-rw-r--r--Essentials/src/com/earth2me/essentials/commands/Commandpowertooltoggle.java6
-rw-r--r--Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java2
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/General.java7
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java18
-rw-r--r--Essentials/src/com/earth2me/essentials/settings/Spawns.java22
-rw-r--r--Essentials/src/com/earth2me/essentials/user/User.java6
-rw-r--r--Essentials/src/com/earth2me/essentials/user/UserBase.java41
-rw-r--r--Essentials/src/com/earth2me/essentials/user/UserData.java25
-rw-r--r--EssentialsChat/src/com/earth2me/essentials/chat/EssentialsChatPlayer.java17
-rw-r--r--EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawn.java3
-rw-r--r--EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawnPlayerListener.java36
-rw-r--r--EssentialsSpawn/src/com/earth2me/essentials/spawn/SpawnStorage.java56
16 files changed, 215 insertions, 38 deletions
diff --git a/Essentials/src/com/earth2me/essentials/api/IGroups.java b/Essentials/src/com/earth2me/essentials/api/IGroups.java
index ba3751014..39a5f4182 100644
--- a/Essentials/src/com/earth2me/essentials/api/IGroups.java
+++ b/Essentials/src/com/earth2me/essentials/api/IGroups.java
@@ -17,4 +17,6 @@ public interface IGroups extends IStorageObjectHolder<Groups>
String getSuffix(IUser player);
int getHomeLimit(IUser player);
+
+ String getChatFormat(IUser player);
}
diff --git a/Essentials/src/com/earth2me/essentials/api/ISettings.java b/Essentials/src/com/earth2me/essentials/api/ISettings.java
index 6943fba4b..a445d21b4 100644
--- a/Essentials/src/com/earth2me/essentials/api/ISettings.java
+++ b/Essentials/src/com/earth2me/essentials/api/ISettings.java
@@ -6,11 +6,9 @@ import com.earth2me.essentials.storage.IStorageObjectHolder;
public interface ISettings extends IStorageObjectHolder<Settings>
{
-
public String getLocale();
public boolean isDebug();
public void setDebug(boolean b);
-
}
diff --git a/Essentials/src/com/earth2me/essentials/api/IUser.java b/Essentials/src/com/earth2me/essentials/api/IUser.java
index 0352f3dce..ed2a5cb61 100644
--- a/Essentials/src/com/earth2me/essentials/api/IUser.java
+++ b/Essentials/src/com/earth2me/essentials/api/IUser.java
@@ -40,7 +40,7 @@ public interface IUser extends Player, IStorageObjectHolder<UserData>, IReload,
Location getHome(String name) throws Exception;
- Location getHome(Location loc) throws Exception;
+ Location getHome(Location loc);
boolean isHidden();
diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandpowertool.java b/Essentials/src/com/earth2me/essentials/commands/Commandpowertool.java
index 64844fa5f..a1c91536a 100644
--- a/Essentials/src/com/earth2me/essentials/commands/Commandpowertool.java
+++ b/Essentials/src/com/earth2me/essentials/commands/Commandpowertool.java
@@ -26,7 +26,8 @@ public class Commandpowertool extends EssentialsCommand
// check to see if this is a clear all command
if (command != null && command.equalsIgnoreCase("d:"))
{
- user.clearAllPowertools();
+ user.acquireWriteLock();
+ user.getData().clearAllPowertools();
user.sendMessage(_("powerToolClearAll"));
return;
}
@@ -38,7 +39,7 @@ public class Commandpowertool extends EssentialsCommand
}
final String itemName = itemStack.getType().toString().toLowerCase(Locale.ENGLISH).replaceAll("_", " ");
- List<String> powertools = user.getPowertool(itemStack);
+ List<String> powertools = user.getData().getPowertool(itemStack.getType());
if (command != null && !command.isEmpty())
{
if (command.equalsIgnoreCase("l:"))
@@ -110,6 +111,7 @@ public class Commandpowertool extends EssentialsCommand
user.sendMessage(_("powerToolRemoveAll", itemName));
}
- user.setPowertool(itemStack, powertools);
+ user.acquireWriteLock();
+ user.getData().setPowertool(itemStack.getType(), powertools);
}
}
diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandpowertooltoggle.java b/Essentials/src/com/earth2me/essentials/commands/Commandpowertooltoggle.java
index 65eab2409..d1a44fd7e 100644
--- a/Essentials/src/com/earth2me/essentials/commands/Commandpowertooltoggle.java
+++ b/Essentials/src/com/earth2me/essentials/commands/Commandpowertooltoggle.java
@@ -15,12 +15,14 @@ public class Commandpowertooltoggle extends EssentialsCommand
@Override
protected void run(final Server server, final IUser user, final String commandLabel, final String[] args) throws Exception
{
- if (!user.hasPowerTools())
+ if (!user.getData().hasPowerTools())
{
user.sendMessage(_("noPowerTools"));
return;
}
- user.sendMessage(user.togglePowerToolsEnabled()
+ user.acquireWriteLock();
+ user.getData().setPowerToolsEnabled(!user.getData().isPowerToolsEnabled());
+ user.sendMessage(user.getData().isPowerToolsEnabled()
? _("powerToolsEnabled")
: _("powerToolsDisabled"));
}
diff --git a/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java
index bdb9d67b7..0a6cc23fe 100644
--- a/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java
+++ b/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java
@@ -304,7 +304,7 @@ public class EssentialsPlayerListener extends PlayerListener
final IUser user = ess.getUser(event.getPlayer());
user.acquireReadLock();
final ItemStack hand = user.getItemInHand();
- if (hand == null || hand.getType() == Material.AIR || !user.getData().isPowertoolsenabled())
+ if (hand == null || hand.getType() == Material.AIR || !user.getData().isPowerToolsEnabled())
{
return;
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/General.java b/Essentials/src/com/earth2me/essentials/settings/General.java
index 67cd0ee27..3b808fb41 100644
--- a/Essentials/src/com/earth2me/essentials/settings/General.java
+++ b/Essentials/src/com/earth2me/essentials/settings/General.java
@@ -25,13 +25,6 @@ public class General implements StorageObject
private String locale;
@Comment(
{
- "Should we announce to the server when someone logs in for the first time?",
- "If so, use this format, replacing {DISPLAYNAME} with the player name.",
- "If not, set to ''"
- })
- private String newPlayerAnnouncement = "&dWelcome {DISPLAYNAME} to the server!";
- @Comment(
- {
"The number of items given, if the quantity parameter is left out in /item or /give.",
"If this number is below 1, the maximum stack size size is given. If oversized stacks",
"is not enabled, any number higher then the maximum stack size results in more than one stack."
diff --git a/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java b/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java
index 0ddd2b758..2f0f016f6 100644
--- a/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java
+++ b/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java
@@ -3,6 +3,7 @@ package com.earth2me.essentials.settings;
import com.earth2me.essentials.Util;
import com.earth2me.essentials.api.IEssentials;
import com.earth2me.essentials.api.IGroups;
+import com.earth2me.essentials.api.ISettings;
import com.earth2me.essentials.api.IUser;
import com.earth2me.essentials.storage.AsyncStorageObjectHolder;
import java.io.File;
@@ -11,6 +12,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
+import lombok.Cleanup;
public class GroupsHolder extends AsyncStorageObjectHolder<Groups> implements IGroups
@@ -147,4 +149,20 @@ public class GroupsHolder extends AsyncStorageObjectHolder<Groups> implements IG
}
return 0;
}
+
+ @Override
+ public String getChatFormat(final IUser player)
+ {
+ for (GroupOptions groupOptions : getGroups(player))
+ {
+ if (groupOptions.getMessageFormat() != null)
+ {
+ return groupOptions.getMessageFormat();
+ }
+ }
+ @Cleanup
+ ISettings settings = ess.getSettings();
+ settings.acquireReadLock();
+ return settings.getData().getChat().getDefaultFormat();
+ }
}
diff --git a/Essentials/src/com/earth2me/essentials/settings/Spawns.java b/Essentials/src/com/earth2me/essentials/settings/Spawns.java
index a0afa450c..c35323dcd 100644
--- a/Essentials/src/com/earth2me/essentials/settings/Spawns.java
+++ b/Essentials/src/com/earth2me/essentials/settings/Spawns.java
@@ -1,5 +1,6 @@
package com.earth2me.essentials.settings;
+import com.earth2me.essentials.storage.Comment;
import com.earth2me.essentials.storage.MapValueType;
import com.earth2me.essentials.storage.StorageObject;
import java.util.HashMap;
@@ -13,6 +14,27 @@ import org.bukkit.Location;
@EqualsAndHashCode(callSuper = false)
public class Spawns implements StorageObject
{
+ @Comment(
+ {
+ "Should we announce to the server when someone logs in for the first time?",
+ "If so, use this format, replacing {DISPLAYNAME} with the player name.",
+ "If not, set to ''"
+ })
+ private String newPlayerAnnouncement = "&dWelcome {DISPLAYNAME} to the server!";
+ @Comment(
+ {
+ "Priority of the respawn event listener",
+ "Set this to lowest, if you want e.g. Multiverse to handle the respawning",
+ "Set this to normal, if you want EssentialsSpawn to handle the respawning",
+ "Set this to highest, if you want to force EssentialsSpawn to handle the respawning"
+ })
+ private String respawnPriority = "normal";
+ @Comment({
+ "When we spawn for the first time, which spawnpoint do we use?",
+ "Set to none if you want to use the spawn point of the world."
+ })
+ private String newbieSpawn = "none";
+ @Comment("List of all spawnpoints")
@MapValueType(Location.class)
private Map<String, Location> spawns = new HashMap<String, Location>();
}
diff --git a/Essentials/src/com/earth2me/essentials/user/User.java b/Essentials/src/com/earth2me/essentials/user/User.java
index 294e51d1d..6c5d50a1f 100644
--- a/Essentials/src/com/earth2me/essentials/user/User.java
+++ b/Essentials/src/com/earth2me/essentials/user/User.java
@@ -566,12 +566,6 @@ public class User extends UserBase implements IUser
}
@Override
- public Location getHome(Location loc) throws Exception
- {
- throw new UnsupportedOperationException("Not supported yet.");
- }
-
- @Override
public Location getHome(String name) throws Exception
{
throw new UnsupportedOperationException("Not supported yet.");
diff --git a/Essentials/src/com/earth2me/essentials/user/UserBase.java b/Essentials/src/com/earth2me/essentials/user/UserBase.java
index 4326f6218..47382a70e 100644
--- a/Essentials/src/com/earth2me/essentials/user/UserBase.java
+++ b/Essentials/src/com/earth2me/essentials/user/UserBase.java
@@ -397,4 +397,45 @@ public abstract class UserBase extends AsyncStorageObjectHolder<UserData> implem
unlock();
}
}
+
+ public Location getHome(Location loc)
+ {
+
+ acquireReadLock();
+ try
+ {
+ if (getData().getHomes() == null)
+ {
+ return null;
+ }
+ ArrayList<Location> worldHomes = new ArrayList<Location>();
+ for (Location location : getData().getHomes().values())
+ {
+ if (location.getWorld().equals(loc.getWorld())) {
+ worldHomes.add(location);
+ }
+ }
+ if (worldHomes.isEmpty()) {
+ return null;
+ }
+ if (worldHomes.size() == 1) {
+ return worldHomes.get(0);
+ }
+ double distance = Double.MAX_VALUE;
+ Location target = null;
+ for (Location location : worldHomes)
+ {
+ final double d = loc.distanceSquared(location);
+ if (d < distance) {
+ target = location;
+ distance = d;
+ }
+ }
+ return target;
+ }
+ finally
+ {
+ unlock();
+ }
+ }
}
diff --git a/Essentials/src/com/earth2me/essentials/user/UserData.java b/Essentials/src/com/earth2me/essentials/user/UserData.java
index b9eb61008..1e81d85da 100644
--- a/Essentials/src/com/earth2me/essentials/user/UserData.java
+++ b/Essentials/src/com/earth2me/essentials/user/UserData.java
@@ -49,7 +49,7 @@ public class UserData implements StorageObject
private String geolocation;
private boolean socialspy;
private boolean npc;
- private boolean powertoolsenabled;
+ private boolean powerToolsEnabled;
public UserData()
{
@@ -70,9 +70,30 @@ public class UserData implements StorageObject
return powerTools == null ? Collections.<String>emptyList() : powerTools.get(mat);
}
+
+ public boolean hasPowerTools()
+ {
+ return powerTools != null && !powerTools.isEmpty();
+ }
+
+ public void setPowertool(Material mat, List<String> commands)
+ {
+ if (powerTools == null)
+ {
+ powerTools = new HashMap<Material, List<String>>();
+ }
+ powerTools.put(mat, commands);
+ }
+
+ public void clearAllPowertools()
+ {
+ powerTools = null;
+ }
+
public void removeHome(String home)
{
- if (homes == null) {
+ if (homes == null)
+ {
return;
}
homes.remove(home);
diff --git a/EssentialsChat/src/com/earth2me/essentials/chat/EssentialsChatPlayer.java b/EssentialsChat/src/com/earth2me/essentials/chat/EssentialsChatPlayer.java
index 17cc7c2f3..d42d341a0 100644
--- a/EssentialsChat/src/com/earth2me/essentials/chat/EssentialsChatPlayer.java
+++ b/EssentialsChat/src/com/earth2me/essentials/chat/EssentialsChatPlayer.java
@@ -4,7 +4,9 @@ import com.earth2me.essentials.ChargeException;
import static com.earth2me.essentials.I18n._;
import com.earth2me.essentials.api.IEssentials;
import com.earth2me.essentials.Trade;
+import com.earth2me.essentials.api.ISettings;
import com.earth2me.essentials.api.IUser;
+import com.earth2me.essentials.settings.GroupOptions;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Logger;
@@ -111,8 +113,9 @@ public abstract class EssentialsChatPlayer extends PlayerListener
if (user.isAuthorized("essentials.chat.color"))
{
event.setMessage(event.getMessage().replaceAll("&([0-9a-f])", "\u00a7$1"));
- }
- event.setFormat(ess.getSettings().getChatFormat(user.getGroup()).replace('&', '\u00a7').replace("\u00a7\u00a7", "&").replace("{DISPLAYNAME}", "%1$s").replace("{GROUP}", user.getGroup()).replace("{MESSAGE}", "%2$s").replace("{WORLDNAME}", user.getWorld().getName()).replace("{SHORTWORLDNAME}", user.getWorld().getName().substring(0, 1).toUpperCase(Locale.ENGLISH)));
+ }
+ String format = ess.getGroups().getChatFormat(user);
+ event.setFormat(format.replace('&', '\u00a7').replace("\u00a7\u00a7", "&").replace("{DISPLAYNAME}", "%1$s").replace("{GROUP}", user.getGroup()).replace("{MESSAGE}", "%2$s").replace("{WORLDNAME}", user.getWorld().getName()).replace("{SHORTWORLDNAME}", user.getWorld().getName().substring(0, 1).toUpperCase(Locale.ENGLISH)));
}
protected String getChatType(final String message)
@@ -132,8 +135,14 @@ public abstract class EssentialsChatPlayer extends PlayerListener
protected void handleLocalChat(final Map<PlayerChatEvent, String> charges, final PlayerChatEvent event)
{
-
- long radius = ess.getSettings().getChatRadius();
+ long radius = 0;
+ ISettings settings = ess.getSettings();
+ settings.acquireReadLock();
+ try {
+ radius = settings.getData().getChat().getLocalRadius();
+ } finally {
+ settings.unlock();
+ }
radius *= radius;
final IUser user = ess.getUser(event.getPlayer());
diff --git a/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawn.java b/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawn.java
index 7eb62238a..7376ed8c4 100644
--- a/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawn.java
+++ b/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawn.java
@@ -5,6 +5,7 @@ import static com.earth2me.essentials.I18n._;
import com.earth2me.essentials.api.ICommandHandler;
import com.earth2me.essentials.api.IEssentials;
import com.earth2me.essentials.api.IEssentialsModule;
+import com.earth2me.essentials.api.ISettings;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
@@ -43,7 +44,7 @@ public class EssentialsSpawn extends JavaPlugin
commandHandler = new EssentialsCommandHandler(EssentialsSpawn.class.getClassLoader(), "com.earth2me.essentials.spawn.Command", "essentials.", spawns, ess);
final EssentialsSpawnPlayerListener playerListener = new EssentialsSpawnPlayerListener(ess, spawns);
- pluginManager.registerEvent(Type.PLAYER_RESPAWN, playerListener, ess.getSettings().getRespawnPriority(), this);
+ pluginManager.registerEvent(Type.PLAYER_RESPAWN, playerListener, spawns.getRespawnPriority(), this);
pluginManager.registerEvent(Type.PLAYER_JOIN, playerListener, Priority.Low, this);
LOGGER.info(_("loadinfo", this.getDescription().getName(), this.getDescription().getVersion(), "essentials team"));
diff --git a/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawnPlayerListener.java b/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawnPlayerListener.java
index 4c4a60997..a345b3f30 100644
--- a/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawnPlayerListener.java
+++ b/EssentialsSpawn/src/com/earth2me/essentials/spawn/EssentialsSpawnPlayerListener.java
@@ -2,6 +2,7 @@ package com.earth2me.essentials.spawn;
import static com.earth2me.essentials.I18n._;
import com.earth2me.essentials.api.IEssentials;
+import com.earth2me.essentials.api.ISettings;
import com.earth2me.essentials.api.IUser;
import java.util.logging.Level;
import org.bukkit.Bukkit;
@@ -28,8 +29,16 @@ public class EssentialsSpawnPlayerListener extends PlayerListener
public void onPlayerRespawn(final PlayerRespawnEvent event)
{
final IUser user = ess.getUser(event.getPlayer());
-
- if (ess.getSettings().getRespawnAtHome())
+
+ boolean respawnAtHome = false;
+ ISettings settings = ess.getSettings();
+ settings.acquireReadLock();
+ try {
+ respawnAtHome = ess.getSettings().getData().getCommands().getHome().isRespawnAtHome();
+ } finally {
+ settings.unlock();
+ }
+ if (respawnAtHome)
{
Location home = user.getHome(user.getLocation());
if (home == null)
@@ -53,20 +62,29 @@ public class EssentialsSpawnPlayerListener extends PlayerListener
public void onPlayerJoin(final PlayerJoinEvent event)
{
final IUser user = ess.getUser(event.getPlayer());
+ user.acquireReadLock();
+ try
+ {
- if (!user.isNew() || user.getBedSpawnLocation() != null)
+ if (!user.getData().isNewplayer() || user.getBedSpawnLocation() != null)
+ {
+ return;
+ }
+ user.acquireWriteLock();
+ user.getData().setNewplayer(false);
+ }
+ finally
{
- return;
+ user.unlock();
}
- user.setNew(false);
- if (!"none".equalsIgnoreCase(ess.getSettings().getNewbieSpawn()))
+ if (spawns.getNewbieSpawn() != null)
{
ess.scheduleSyncDelayedTask(new NewPlayerTeleport(user));
}
- if (ess.getSettings().getAnnounceNewPlayers())
+ if (spawns.getAnnounceNewPlayers())
{
- ess.broadcastMessage(user, ess.getSettings().getAnnounceNewPlayerFormat(user));
+ ess.broadcastMessage(user, spawns.getAnnounceNewPlayerFormat(user));
}
}
@@ -85,7 +103,7 @@ public class EssentialsSpawnPlayerListener extends PlayerListener
{
try
{
- Location spawn = spawns.getSpawn(ess.getSettings().getNewbieSpawn());
+ Location spawn = spawns.getNewbieSpawn();
if (spawn != null)
{
user.getTeleport().now(spawn, false, TeleportCause.PLUGIN);
diff --git a/EssentialsSpawn/src/com/earth2me/essentials/spawn/SpawnStorage.java b/EssentialsSpawn/src/com/earth2me/essentials/spawn/SpawnStorage.java
index 61304fbf4..0c351c753 100644
--- a/EssentialsSpawn/src/com/earth2me/essentials/spawn/SpawnStorage.java
+++ b/EssentialsSpawn/src/com/earth2me/essentials/spawn/SpawnStorage.java
@@ -2,6 +2,7 @@ package com.earth2me.essentials.spawn;
import com.earth2me.essentials.api.IEssentials;
import com.earth2me.essentials.api.IEssentialsModule;
+import com.earth2me.essentials.api.IUser;
import com.earth2me.essentials.settings.Spawns;
import com.earth2me.essentials.storage.AsyncStorageObjectHolder;
import java.io.File;
@@ -10,6 +11,7 @@ import java.util.Locale;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.World;
+import org.bukkit.event.Event.Priority;
public class SpawnStorage extends AsyncStorageObjectHolder<Spawns> implements IEssentialsModule
@@ -87,4 +89,58 @@ public class SpawnStorage extends AsyncStorageObjectHolder<Spawns> implements IE
}
return ess.getServer().getWorlds().get(0).getSpawnLocation();
}
+
+ public Priority getRespawnPriority()
+ {
+ acquireReadLock();
+ try
+ {
+ for (Priority priority : Priority.values())
+ {
+ if (priority.toString().equalsIgnoreCase(getData().getRespawnPriority())) {
+ return priority;
+ }
+ }
+ return Priority.Normal;
+ } finally {
+ unlock();
+ }
+ }
+
+ public Location getNewbieSpawn()
+ {
+ acquireReadLock();
+ try
+ {
+ if (getData().getNewbieSpawn() == null || getData().getNewbieSpawn().isEmpty() ||
+ getData().getNewbieSpawn().equalsIgnoreCase("none")) {
+ return null;
+ }
+ return getSpawn(getData().getNewbieSpawn());
+ } finally {
+ unlock();
+ }
+ }
+
+ public boolean getAnnounceNewPlayers()
+ {
+ acquireReadLock();
+ try
+ {
+ return getData().getNewPlayerAnnouncement() != null && !getData().getNewPlayerAnnouncement().isEmpty();
+ } finally {
+ unlock();
+ }
+ }
+
+ public String getAnnounceNewPlayerFormat(IUser user)
+ {
+ acquireReadLock();
+ try
+ {
+ return getData().getNewPlayerAnnouncement().replace('&', '§').replace("§§", "&").replace("{PLAYER}", user.getDisplayName()).replace("{DISPLAYNAME}", user.getDisplayName()).replace("{GROUP}", user.getGroup()).replace("{USERNAME}", user.getName()).replace("{ADDRESS}", user.getAddress().toString());
+ } finally {
+ unlock();
+ }
+ }
}