Document and clean up StatsManager

This commit is contained in:
samczsun 2016-11-30 21:41:59 -05:00 committed by cnr
parent d291521ad1
commit 87eaeabd7f
12 changed files with 400 additions and 457 deletions

View File

@ -1,6 +1,7 @@
package mineplex.core.achievement.command;
import mineplex.core.stats.PlayerStats;
import org.bukkit.entity.Player;
import mineplex.core.achievement.AchievementManager;
@ -35,7 +36,7 @@ public class StatsCommand extends CommandBase<AchievementManager>
if (Plugin.getClientManager().hasRank(caller, Rank.MODERATOR)) attemptOffline(caller, args);
return;
}
if (/* StaffServer special case */Plugin.getIncognito() != null && Plugin.getIncognito().Get(target).Hidden)
{
UtilPlayer.message(caller,
@ -59,35 +60,17 @@ public class StatsCommand extends CommandBase<AchievementManager>
UtilPlayer.message(caller, F.main("Stats", "Attempting to look up offline stats..."));
final String playerName = args[0];
Plugin.runAsync(() -> {
try
Plugin.getStatsManager().getOfflinePlayerStats(args[0], stats ->
{
if (stats == null)
{
PlayerStats stats = Plugin.getStatsManager().getOfflinePlayerStats(playerName);
if (stats == null)
{
Plugin.runSync(() -> offlinePlayerNotFound(caller, playerName));
}
else
{
Plugin.runSync(() -> openShop(caller, playerName, stats));
}
} catch (SQLException e)
UtilPlayer.message(caller, F.main("Stats", "Offline Player " + F.elem(playerName) + " not found."));
}
else
{
Plugin.runSync(() -> UtilPlayer.message(caller, F.main("Stats", "There was an error trying to look up offline player " + F.elem(playerName))));
e.printStackTrace();
Plugin.openShop(caller, playerName, stats);
}
});
}
}
private void offlinePlayerNotFound(Player caller, String searchName)
{
UtilPlayer.message(caller, F.main("Stats", "Offline Player " + F.elem(searchName) + " not found."));
}
private void openShop(Player caller, String searchName, PlayerStats playerStats)
{
Plugin.openShop(caller, searchName, playerStats);
}
}

View File

@ -35,7 +35,7 @@ public class DonationRepository extends MinecraftRepository
}
/**
* Purchases a known sales package.. whatever that means
* Purchases a known sales package
*
* @param playerName The player name
* @param salesPackageId The package id
@ -58,7 +58,7 @@ public class DonationRepository extends MinecraftRepository
}
/**
* Purchases an unknown sales package... or something
* Purchases an unknown sales package
*
* @param playerName The name of the player
* @param packageName The name of the unknown package

View File

@ -1,41 +1,72 @@
package mineplex.core.stats;
import java.util.Set;
import mineplex.core.common.util.NautHashMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a player's statistic information. This object is thread-safe
*/
public class PlayerStats
{
private NautHashMap<String, Long> _statHash = new NautHashMap<String,Long>();
public long addStat(String statName, long value)
private final Object lock = new Object();
private Map<String, Long> _stats = new HashMap<>();
/**
* Add a value to the specified stat
*
* @param statName The name of the stat
* @param value The value, must be positive
* @return The new value for the specified stat
*/
long addStat(String statName, long value)
{
value = Math.max(0L, value);
if (!_statHash.containsKey(statName))
synchronized (lock)
{
_statHash.put(statName, 0L);
return _stats.merge(statName, Math.max(0, value), Long::sum);
}
_statHash.put(statName, _statHash.get(statName) + value);
return _statHash.get(statName);
}
public long setStat(String statName, long value)
{
_statHash.put(statName, value);
return _statHash.get(statName);
}
public long getStat(String statName)
{
return _statHash.containsKey(statName) ? _statHash.get(statName) : 0L;
}
public Set<String> getStatsNames()
{
return _statHash.keySet();
/**
* Sets the value of the specified stat
*
* @param statName The name of the stat
* @param value The value, must be positive
* @return The new value for the specified stat
*/
long setStat(String statName, long value)
{
synchronized (lock)
{
_stats.put(statName, value);
return value;
}
}
/**
* Gets the value for the specified stat
*
* @param statName The name of the stat
* @return The value of the stat if it exists, or 0 if it does not
*/
public long getStat(String statName)
{
synchronized (lock)
{
return _stats.getOrDefault(statName, 0L);
}
}
/**
* Returns a view of the all the stats. This view will not be updated
*/
public Map<String, Long> getStats()
{
synchronized (lock)
{
// make it unmodifiable so that people who try to edit it will get an exception instead of silently failing
return Collections.unmodifiableMap(new HashMap<>(_stats));
}
}
}

View File

@ -2,6 +2,22 @@ package mineplex.core.stats;
public class Stat
{
public int Id;
public String Name;
private int id;
private String name;
public Stat(int id, String name)
{
this.id = id;
this.name = name;
}
public int getId()
{
return id;
}
public String getName()
{
return name;
}
}

View File

@ -2,317 +2,270 @@ package mineplex.core.stats;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import mineplex.cache.player.PlayerInfo;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.cache.player.PlayerCache;
import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTasks;
import mineplex.core.stats.command.GiveStatCommand;
import mineplex.core.stats.command.MasterBuilderUnban;
import mineplex.core.stats.command.TimeCommand;
import mineplex.core.stats.event.StatChangeEvent;
import mineplex.core.thread.ThreadPool;
import mineplex.core.updater.UpdateType;
import mineplex.core.utils.UtilScheduler;
/**
* This manager handles player statistics
*/
public class StatsManager extends MiniDbClientPlugin<PlayerStats>
{
private static final Object _statSync = new Object();
private StatsRepository _repository;
private NautHashMap<String, Integer> _stats = new NautHashMap<String, Integer>();
private NautHashMap<UUID, NautHashMap<String, Long>> _statUploadQueue = new NautHashMap<>();
private NautHashMap<UUID, NautHashMap<String, Long>> _statUploadQueueOverRidable = new NautHashMap<>();
private static final Object STATS_LOCK = new Object();
private Runnable _saveRunnable;
public StatsManager(JavaPlugin plugin, CoreClientManager clientManager)
private final CoreClientManager _coreClientManager;
private final StatsRepository _repository;
private final Map<String, Integer> _stats = new HashMap<>();
private final Map<CoreClient, Map<String, Long>> _statUploadQueue = new HashMap<>();
private final Map<CoreClient, Map<String, Long>> _statUploadQueueOverRidable = new HashMap<>();
public StatsManager(JavaPlugin plugin, CoreClientManager clientManager)
{
super("Stats Manager", plugin, clientManager);
_repository = new StatsRepository(plugin);
if (_saveRunnable == null)
_repository = new StatsRepository();
_coreClientManager = clientManager;
UtilScheduler.runAsyncEvery(UpdateType.SEC, () ->
{
_saveRunnable = new Runnable()
{
public void run()
{
saveStats();
overRidableSaveStats();
}
};
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, _saveRunnable, 20L, 20L);
}
save(_statUploadQueue, _repository::saveStats, "normal");
save(_statUploadQueueOverRidable, map -> _repository.saveStats(map, true), "override");
});
for (Stat stat : _repository.retrieveStats())
{
_stats.put(stat.Name, stat.Id);
_stats.put(stat.getName(), stat.getId());
}
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event)
/**
* Gets offline stats for the specified player name
*
* @return A Future to listen to, if you are already off the main thread
*/
public Future<PlayerStats> getOfflinePlayerStats(String playerName)
{
PlayerStats playerStats = Get(event.getPlayer());
final int accountId = getClientManager().getAccountId(event.getPlayer());
for (String statName : playerStats.getStatsNames())
return getOfflinePlayerStats(playerName, null);
}
/**
* Gets offline stats for the specified player name
*
* @param action The action to perform with the fetched PlayerStats. This action will be performed on the main thread. Can be null
* @return A Future to listen to, should you already be off the main thread
*/
public Future<PlayerStats> getOfflinePlayerStats(String playerName, Consumer<PlayerStats> action)
{
return ThreadPool.ASYNC.submit(() ->
{
if (!_stats.containsKey(statName))
continue;
final int statId = _stats.get(statName);
if (playerStats.getStat(statName) == -1)
PlayerStats stats = _repository.loadOfflinePlayerStats(playerName);
UtilTasks.onMainThread(action).accept(stats);
return stats;
});
}
/**
* Increments a stat for the given player by the specified amount
*
* @param value The value, must be greater or equal to zero
*/
public void incrementStat(Player player, String statName, long value)
{
if (value < 0)
return;
long oldValue = Get(player).getStat(statName);
long newValue = Get(player).addStat(statName, value);
UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player.getName(), statName, oldValue, newValue));
registerNewStat(statName, () -> addToQueue(statName, player, value));
}
/**
* Sets the value of a stat for the given player
*
* @param value The value, must be greater or equal to zero
*/
public void setStat(Player player, String statName, long value)
{
if (value < 0)
return;
long oldValue = Get(player).getStat(statName);
Get(player).setStat(statName, value);
UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player.getName(), statName, oldValue, value));
registerNewStat(statName, () -> addToOverRidableQueue(statName, player, value));
}
/**
* Increments a stat for the given account ID of an <b>offline player</b> by the specified amount
*/
public void incrementStat(final int accountId, final String statName, final long value)
{
registerNewStat(statName, () ->
{
Map<Integer, Map<Integer, Long>> uploadQueue = new HashMap<>();
uploadQueue.computeIfAbsent(accountId, key -> new HashMap<>()).put(_stats.get(statName), value);
_repository.saveStats(uploadQueue, false);
});
}
/**
* Sets the value of a stat for the given account ID of an <b>offline player</b>
*
* @param value The value, must be greater or equal to zero
*/
public void setStat(final int accountId, final String statName, final long value)
{
if (value < 0)
return;
registerNewStat(statName, () ->
{
Map<Integer, Map<Integer, Long>> uploadQueue = new HashMap<>();
uploadQueue.computeIfAbsent(accountId, key -> new HashMap<>()).put(_stats.get(statName), value);
_repository.saveStats(uploadQueue, true);
});
}
private void addToOverRidableQueue(String statName, Player player, long value)
{
synchronized (STATS_LOCK)
{
_statUploadQueueOverRidable
.computeIfAbsent(_coreClientManager.Get(player), key -> new HashMap<>())
.put(statName, value);
}
}
private void addToQueue(String statName, Player player, long value)
{
synchronized (STATS_LOCK)
{
_statUploadQueue
.computeIfAbsent(_coreClientManager.Get(player), key -> new HashMap<>())
.merge(statName, value, Long::sum);
}
}
protected void save(Map<CoreClient, Map<String, Long>> statsMap, Consumer<Map<Integer, Map<Integer, Long>>> action, String type)
{
if (statsMap.isEmpty())
return;
Map<Integer, Map<Integer, Long>> uploadQueue = new HashMap<>();
try
{
synchronized (STATS_LOCK)
{
runAsync(new Runnable()
statsMap.entrySet().removeIf(entry ->
{
public void run()
CoreClient client = entry.getKey();
if (Bukkit.getPlayer(client.getUniqueId()) != null)
return false;
Map<Integer, Long> uploadStats = uploadQueue.computeIfAbsent(client.getAccountId(), key -> new HashMap<>());
entry.getValue().forEach((statName, amount) ->
{
_repository.setStat(accountId, statId, 0);
}
// Sanity check
if (_stats.containsKey(statName))
{
uploadStats.merge(_stats.get(statName), amount, Long::sum);
System.out.println(String.format("Saving stat '%s' for '%s', value '%s', type '%s'", statName, client.getName(), uploadStats.get(_stats.get(statName)), type));
}
});
return true;
});
}
}
}
public void incrementStat(final Player player, final String statName, final long value)
{
incrementStat(player, statName, value, false);
}
public void incrementStat(final Player player, final String statName, final long value, boolean overRide)
{
if (value <= 0)
return;
long newValue = Get(player).addStat(statName, value);
//Event
UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player.getName(), statName, newValue - value, newValue));
// Verify stat is in our local cache, if not add it remotely.
registerNewStat(statName, new Runnable()
{
@Override
public void run()
{
if(overRide)
{
addToOverRidableQueue(statName, player, value);
}
else
{
addToQueue(statName, player, value);
}
}
});
}
private void addToOverRidableQueue(String statName, Player player, long value)
{
synchronized (_statSync)
{
if (!_statUploadQueueOverRidable.containsKey(player.getUniqueId()))
_statUploadQueueOverRidable.put(player.getUniqueId(), new NautHashMap<String, Long>());
if (!_statUploadQueueOverRidable.get(player.getUniqueId()).containsKey(statName))
_statUploadQueueOverRidable.get(player.getUniqueId()).put(statName, 0L);
_statUploadQueueOverRidable.get(player.getUniqueId()).put(statName, _statUploadQueueOverRidable.get(player.getUniqueId()).get(statName) + value);
}
}
protected void overRidableSaveStats()
{
if (_statUploadQueueOverRidable.isEmpty())
return;
try
{
NautHashMap<Integer, NautHashMap<Integer, Long>> uploadQueue = new NautHashMap<Integer, NautHashMap<Integer, Long>>();
synchronized (_statSync)
{
for (Iterator<UUID> statIterator = _statUploadQueueOverRidable.keySet().iterator(); statIterator.hasNext();)
{
UUID player = statIterator.next();
if (Bukkit.getPlayer(player) != null)
continue;
try
{
PlayerInfo info = PlayerCache.getInstance().getPlayer(player);
uploadQueue.put(info.getAccountId(), new NautHashMap<>());
for (String statName : _statUploadQueueOverRidable.get(player).keySet())
{
int statId = _stats.get(statName);
uploadQueue.get(info.getAccountId()).put(statId, _statUploadQueueOverRidable.get(player).get(statName));
System.out.println(info.getName() + " saving stat : " + statName + " overriding " + _statUploadQueueOverRidable.get(player).get(statName));
}
statIterator.remove();
}
catch (Exception e)
{
//System.out.println("[StatsManager] AccountId was not set for " + player.getName());
}
}
}
_repository.saveStats(uploadQueue, true);
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
private void addToQueue(String statName, Player player, long value)
{
synchronized (_statSync)
finally
{
if (!_statUploadQueue.containsKey(player.getUniqueId()))
_statUploadQueue.put(player.getUniqueId(), new NautHashMap<String, Long>());
if (!_statUploadQueue.get(player.getUniqueId()).containsKey(statName))
_statUploadQueue.get(player.getUniqueId()).put(statName, 0L);
_statUploadQueue.get(player.getUniqueId()).put(statName, _statUploadQueue.get(player.getUniqueId()).get(statName) + value);
action.accept(uploadQueue);
}
}
protected void saveStats()
{
if (_statUploadQueue.isEmpty())
return;
try
{
NautHashMap<Integer, NautHashMap<Integer, Long>> uploadQueue = new NautHashMap<Integer, NautHashMap<Integer, Long>>();
synchronized (_statSync)
{
for (Iterator<UUID> statIterator = _statUploadQueue.keySet().iterator(); statIterator.hasNext();)
{
UUID player = statIterator.next();
if (Bukkit.getPlayer(player) != null)
continue;
try
{
PlayerInfo info = PlayerCache.getInstance().getPlayer(player);
uploadQueue.put(info.getAccountId(), new NautHashMap<Integer, Long>());
for (String statName : _statUploadQueue.get(player).keySet())
{
int statId = _stats.get(statName);
uploadQueue.get(info.getAccountId()).put(statId, _statUploadQueue.get(player).get(statName));
System.out.println(info.getName() + " saving stat : " + statName + " adding " + _statUploadQueue.get(player).get(statName));
}
statIterator.remove();
}
catch (Exception e)
{
//System.out.println("[StatsManager] AccountId was not set for " + player.getName());
}
}
}
_repository.saveStats(uploadQueue);
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
public boolean incrementStat(final int accountId, final String statName, final long value)
{
return incrementStat(accountId, statName, value, false);
}
public boolean incrementStat(final int accountId, final String statName, final long value, boolean overRide)
{
// This will register a new stat if we don't have one, otherwise it will just run the callback
registerNewStat(statName, new Runnable()
{
@Override
public void run()
{
final NautHashMap<Integer, NautHashMap<Integer, Long>> uploadQueue = new NautHashMap<Integer, NautHashMap<Integer, Long>>();
uploadQueue.put(accountId, new NautHashMap<Integer, Long>());
uploadQueue.get(accountId).put(_stats.get(statName), value);
_repository.saveStats(uploadQueue, overRide);
}
});
return true;
}
private void registerNewStat(final String statName, final Runnable callback)
{
runAsync(new Runnable()
runAsync(() ->
{
public void run()
synchronized (STATS_LOCK)
{
synchronized (_statSync)
if (_stats.containsKey(statName))
{
if (_stats.containsKey(statName))
{
if (callback != null) callback.run();
return;
}
_repository.addStat(statName);
_stats.clear();
for (Stat stat : _repository.retrieveStats())
{
_stats.put(stat.Name, stat.Id);
}
if (callback != null) callback.run();
return;
}
_repository.registerNewStat(statName);
_stats.clear();
for (Stat stat : _repository.retrieveStats())
{
_stats.put(stat.getName(), stat.getId());
}
if (callback != null) callback.run();
}
});
}
public int getStatId(String statName)
{
return _stats.get(statName);
}
@Override
protected PlayerStats addPlayer(UUID uuid)
@EventHandler
private void onPlayerJoin(PlayerJoinEvent event)
{
return new PlayerStats();
}
Set<String> statsToReset = new HashSet<>();
public PlayerStats getOfflinePlayerStats(String playerName) throws SQLException
{
return _repository.loadOfflinePlayerStats(playerName);
Get(event.getPlayer()).getStats().forEach((stat, amount) ->
{
if (!_stats.containsKey(stat))
return;
if (amount == -1)
{
statsToReset.add(stat);
}
});
statsToReset.forEach(stat ->
{
setStat(event.getPlayer(), stat, 0);
});
}
@Override
@ -323,10 +276,31 @@ public class StatsManager extends MiniDbClientPlugin<PlayerStats>
addCommand(new MasterBuilderUnban(this));
}
@Override
protected PlayerStats addPlayer(UUID uuid)
{
return new PlayerStats();
}
@Override
public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException
{
Set(uuid, _repository.loadClientInformation(resultSet));
PlayerStats playerStats = new PlayerStats();
while (resultSet.next())
{
try
{
playerStats.addStat(resultSet.getString(1), resultSet.getLong(2));
}
catch (Exception ex)
{
ex.printStackTrace();
playerStats.addStat(resultSet.getString(1), -1);
}
}
Set(uuid, playerStats);
}
@Override

View File

@ -1,19 +1,10 @@
package mineplex.core.stats;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.database.MinecraftRepository;
import mineplex.serverdata.database.DBPool;
import mineplex.serverdata.database.ResultSetCallable;
import mineplex.serverdata.database.column.ColumnVarChar;
import mineplex.database.Tables;
import org.bukkit.plugin.java.JavaPlugin;
import org.jooq.DSLContext;
import org.jooq.Insert;
import org.jooq.Record2;
@ -23,53 +14,68 @@ import org.jooq.Update;
import org.jooq.impl.DSL;
import org.jooq.types.ULong;
import mineplex.core.database.MinecraftRepository;
import mineplex.database.Tables;
import mineplex.serverdata.database.DBPool;
import mineplex.serverdata.database.column.ColumnVarChar;
public class StatsRepository extends MinecraftRepository
{
private static String RETRIEVE_STATS = "SELECT id, name FROM stats;";
private static String INSERT_STAT = "INSERT INTO stats (name) VALUES (?);";
private static final String RETRIEVE_STATS = "SELECT id, name FROM stats;";
private static final String INSERT_STAT = "INSERT INTO stats (name) VALUES (?);";
public StatsRepository(JavaPlugin plugin)
public StatsRepository()
{
super(DBPool.getAccount());
}
/**
* Retrieves all the remote registered stats
*
* @return The list of stats
*/
public List<Stat> retrieveStats()
{
final List<Stat> stats = new ArrayList<Stat>();
executeQuery(RETRIEVE_STATS, new ResultSetCallable()
{
public void processResultSet(ResultSet resultSet) throws SQLException
{
while (resultSet.next())
{
Stat stat = new Stat();
stat.Id = resultSet.getInt(1);
stat.Name = resultSet.getString(2);
List<Stat> stats = new ArrayList<>();
stats.add(stat);
}
executeQuery(RETRIEVE_STATS, resultSet ->
{
while (resultSet.next())
{
stats.add(new Stat(resultSet.getInt(1), resultSet.getString(2)));
}
});
return stats;
}
public void addStat(String name)
/**
* Registers a stat with the remote server
*
* @param name The name of the stat
*/
public void registerNewStat(String name)
{
executeUpdate(INSERT_STAT, new ColumnVarChar("name", 100, name));
}
public void saveStats(NautHashMap<Integer, NautHashMap<Integer, Long>> uploadQueue)
/**
* Saves the given stats
*
* @param uploadQueue A map of account ID to a map of stat IDS to values
*/
public void saveStats(Map<Integer, Map<Integer, Long>> uploadQueue)
{
saveStats(uploadQueue, false);
}
@SuppressWarnings("rawtypes")
public void saveStats(NautHashMap<Integer, NautHashMap<Integer, Long>> uploadQueue, boolean overRideStat)
/**
* Saves the given stats
*
* @param uploadQueue A map of account ID to a map of stat IDS to values
* @param overrideStat Whether to replace the remote value, or to add to it
*/
public void saveStats(Map<Integer, Map<Integer, Long>> uploadQueue, boolean overrideStat)
{
try
{
@ -82,22 +88,22 @@ public class StatsRepository extends MinecraftRepository
{
for (Integer statId : uploadQueue.get(accountId).keySet())
{
if(overRideStat)
if (overrideStat)
{
Update update = context
.update(Tables.accountStat)
.set(Tables.accountStat.value, ULong.valueOf(uploadQueue.get(accountId).get(statId)))
.where(Tables.accountStat.accountId.eq(accountId))
.and(Tables.accountStat.statId.eq(statId));
updates.add(update);
updates.add(update);
}
else
{
Update update = context
.update(Tables.accountStat)
.set(Tables.accountStat.value, Tables.accountStat.value.plus(uploadQueue.get(accountId).get(statId)))
.where(Tables.accountStat.accountId.eq(accountId))
.and(Tables.accountStat.statId.eq(statId));
.update(Tables.accountStat)
.set(Tables.accountStat.value, Tables.accountStat.value.plus(uploadQueue.get(accountId).get(statId)))
.where(Tables.accountStat.accountId.eq(accountId))
.and(Tables.accountStat.statId.eq(statId));
updates.add(update);
}
@ -129,6 +135,10 @@ public class StatsRepository extends MinecraftRepository
}
}
/**
* Gets offline stats for the specified player name. This performs SQL on the current thread
*/
public PlayerStats loadOfflinePlayerStats(String playerName)
{
PlayerStats playerStats = null;
@ -161,43 +171,4 @@ public class StatsRepository extends MinecraftRepository
return playerStats;
}
public PlayerStats loadClientInformation(ResultSet resultSet) throws SQLException
{
final PlayerStats playerStats = new PlayerStats();
while (resultSet.next())
{
try
{
playerStats.addStat(resultSet.getString(1), resultSet.getLong(2));
}
catch (Exception ex)
{
ex.printStackTrace();
playerStats.addStat(resultSet.getString(1), -1);
}
}
return playerStats;
}
public void setStat(int accountId, int statId, long value)
{
try
{
DSLContext context = DSL.using(getConnectionPool(), SQLDialect.MYSQL);
context
.update(Tables.accountStat)
.set(Tables.accountStat.value, ULong.valueOf(value))
.where(Tables.accountStat.accountId.eq(accountId))
.and(Tables.accountStat.statId.eq(statId))
.execute();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

View File

@ -53,7 +53,7 @@ public class GiveStatCommand extends CommandBase<StatsManager>
Plugin.incrementStat(player, statName, Integer.parseInt(args[args.length - 1]));
}
UtilPlayer.message(caller, F.main("Stats", "Applied " + F.elem(Integer.parseInt(args[args.length - 1]) + " " + statName) + " to " + F.elem(player.getName()) + "."));
UtilPlayer.message(caller, F.main("Stats", "Applied " + F.elem(Integer.parseInt(args[args.length - 1]) + " " + statName) + " to " + F.elem(player == null ? args[0] : player.getName()) + "."));
}
catch (Exception e)
{

View File

@ -72,7 +72,7 @@ public class MasterBuilderUnban extends CommandBase<StatsManager>
{
if(theClient != null)
{
Plugin.incrementStat(theClient.getAccountId(), "Global.Build Draw Abuse", 0, true); // True = Resets the stat
Plugin.setStat(theClient.getAccountId(), "Global.Build Draw Abuse", 0);
caller.sendMessage(F.main("MasterBuilder Unban", "The user " + target + " has been unbanned from Master Builders"));
}
else

View File

@ -35,36 +35,16 @@ public class TimeCommand extends CommandBase<StatsManager>
if (target == null)
{
Plugin.getPlugin().getServer().getScheduler().runTaskAsynchronously(Plugin.getPlugin(), new Runnable()
Plugin.getOfflinePlayerStats(args[0], stats ->
{
@Override
public void run()
if (stats == null)
{
try
{
final PlayerStats stats = Plugin.getOfflinePlayerStats(args[0]);
Plugin.getPlugin().getServer().getScheduler().runTask(Plugin.getPlugin(), new Runnable()
{
@Override
public void run()
{
if (stats == null)
{
UtilPlayer.message(caller, F.main("Time", "Player " + F.elem(args[0]) + " not found!"));
}
else
{
long time = stats.getStat("Global.TimeInGame");
UtilPlayer.message(caller, F.main("Time", F.name(args[0]) + " has spent " + F.elem(UtilTime.convertString(time * 1000L, 1, UtilTime.TimeUnit.FIT)) + " in game"));
}
}
});
}
catch (SQLException e)
{
e.printStackTrace();
}
UtilPlayer.message(caller, F.main("Time", "Player " + F.elem(args[0]) + " not found!"));
}
else
{
long time = stats.getStat("Global.TimeInGame");
UtilPlayer.message(caller, F.main("Time", F.name(args[0]) + " has spent " + F.elem(UtilTime.convertString(time * 1000L, 1, UtilTime.TimeUnit.FIT)) + " in game"));
}
});
}

View File

@ -12,4 +12,10 @@ public class UtilScheduler
Plugin plugin = UtilServer.getPlugin();
plugin.getServer().getScheduler().runTaskTimer(plugin, action, 0, (int) Math.ceil(speed.getMilliseconds() / 50.0));
}
public static void runAsyncEvery(UpdateType speed, Runnable action)
{
Plugin plugin = UtilServer.getPlugin();
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, action, 0, (int) Math.ceil(speed.getMilliseconds() / 50.0));
}
}

View File

@ -38,36 +38,16 @@ public class PlayTimeCommand extends CommandBase<StatsManager>
if (target == null)
{
Plugin.getPlugin().getServer().getScheduler().runTaskAsynchronously(Plugin.getPlugin(), new Runnable()
Plugin.getOfflinePlayerStats(args[0], stats ->
{
@Override
public void run()
if (stats == null)
{
try
{
final PlayerStats stats = Plugin.getOfflinePlayerStats(args[0]);
Plugin.getPlugin().getServer().getScheduler().runTask(Plugin.getPlugin(), new Runnable()
{
@Override
public void run()
{
if (stats == null)
{
UtilPlayer.message(caller, F.main("Clans", "Player " + F.elem(args[0]) + " not found!"));
}
else
{
long time = stats.getStat(ClansPlayerStats.PLAY_TIME.id());
UtilPlayer.message(caller, F.main("Clans", F.name(args[0]) + " has spent " + F.elem(UtilTime.convertString(time * 1000L, 1, UtilTime.TimeUnit.FIT)) + " playing Clans."));
}
}
});
}
catch (SQLException e)
{
UtilPlayer.message(caller, F.main("Clans", F.name(target.getName()) + " does not have any play time in Clans."));
}
UtilPlayer.message(caller, F.main("Clans", "Player " + F.elem(args[0]) + " not found!"));
}
else
{
long time = stats.getStat(ClansPlayerStats.PLAY_TIME.id());
UtilPlayer.message(caller, F.main("Clans", F.name(args[0]) + " has spent " + F.elem(UtilTime.convertString(time * 1000L, 1, UtilTime.TimeUnit.FIT)) + " playing Clans."));
}
});
}

View File

@ -10,6 +10,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@ -342,12 +343,13 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable
{
try
{
PlayerStats playerStats = statsManager.getOfflinePlayerStats(playerName);
PlayerStats playerStats = statsManager.getOfflinePlayerStats(playerName).get();
if (playerStats != null)
{
hauntedChestsOpened = (int) playerStats.getStat("Global.Treasure.Haunted");
}
} catch (SQLException e)
}
catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}