Document and clean up StatsManager
This commit is contained in:
parent
d291521ad1
commit
87eaeabd7f
|
@ -1,6 +1,7 @@
|
|||
package mineplex.core.achievement.command;
|
||||
|
||||
import mineplex.core.stats.PlayerStats;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import mineplex.core.achievement.AchievementManager;
|
||||
|
@ -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 ->
|
||||
{
|
||||
PlayerStats stats = Plugin.getStatsManager().getOfflinePlayerStats(playerName);
|
||||
|
||||
if (stats == null)
|
||||
{
|
||||
Plugin.runSync(() -> offlinePlayerNotFound(caller, playerName));
|
||||
UtilPlayer.message(caller, F.main("Stats", "Offline Player " + F.elem(playerName) + " not found."));
|
||||
}
|
||||
else
|
||||
{
|
||||
Plugin.runSync(() -> openShop(caller, playerName, stats));
|
||||
}
|
||||
} catch (SQLException e)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>();
|
||||
private final Object lock = new Object();
|
||||
|
||||
public long addStat(String statName, long value)
|
||||
{
|
||||
value = Math.max(0L, value);
|
||||
private Map<String, Long> _stats = new HashMap<>();
|
||||
|
||||
if (!_statHash.containsKey(statName))
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
_statHash.put(statName, 0L);
|
||||
synchronized (lock)
|
||||
{
|
||||
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)
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
_statHash.put(statName, value);
|
||||
|
||||
return _statHash.get(statName);
|
||||
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)
|
||||
{
|
||||
return _statHash.containsKey(statName) ? _statHash.get(statName) : 0L;
|
||||
synchronized (lock)
|
||||
{
|
||||
return _stats.getOrDefault(statName, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getStatsNames()
|
||||
/**
|
||||
* Returns a view of the all the stats. This view will not be updated
|
||||
*/
|
||||
public Map<String, Long> getStats()
|
||||
{
|
||||
return _statHash.keySet();
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,279 +2,229 @@ 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 static final Object STATS_LOCK = new Object();
|
||||
|
||||
private StatsRepository _repository;
|
||||
private final CoreClientManager _coreClientManager;
|
||||
private final 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 Runnable _saveRunnable;
|
||||
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);
|
||||
_repository = new StatsRepository();
|
||||
_coreClientManager = clientManager;
|
||||
|
||||
if (_saveRunnable == null)
|
||||
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())
|
||||
{
|
||||
if (!_stats.containsKey(statName))
|
||||
continue;
|
||||
|
||||
final int statId = _stats.get(statName);
|
||||
|
||||
if (playerStats.getStat(statName) == -1)
|
||||
{
|
||||
runAsync(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
_repository.setStat(accountId, statId, 0);
|
||||
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(() ->
|
||||
{
|
||||
PlayerStats stats = _repository.loadOfflinePlayerStats(playerName);
|
||||
UtilTasks.onMainThread(action).accept(stats);
|
||||
return stats;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
/**
|
||||
* 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)
|
||||
if (value < 0)
|
||||
return;
|
||||
|
||||
long oldValue = Get(player).getStat(statName);
|
||||
long newValue = Get(player).addStat(statName, value);
|
||||
|
||||
//Event
|
||||
UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player.getName(), statName, newValue - value, newValue));
|
||||
UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player.getName(), statName, oldValue, newValue));
|
||||
registerNewStat(statName, () -> addToQueue(statName, player, value));
|
||||
}
|
||||
|
||||
// Verify stat is in our local cache, if not add it remotely.
|
||||
registerNewStat(statName, new Runnable()
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(overRide)
|
||||
{
|
||||
addToOverRidableQueue(statName, player, 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));
|
||||
}
|
||||
else
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
addToQueue(statName, player, 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 (_statSync)
|
||||
synchronized (STATS_LOCK)
|
||||
{
|
||||
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();
|
||||
_statUploadQueueOverRidable
|
||||
.computeIfAbsent(_coreClientManager.Get(player), key -> new HashMap<>())
|
||||
.put(statName, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToQueue(String statName, Player player, long value)
|
||||
{
|
||||
synchronized (_statSync)
|
||||
synchronized (STATS_LOCK)
|
||||
{
|
||||
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);
|
||||
_statUploadQueue
|
||||
.computeIfAbsent(_coreClientManager.Get(player), key -> new HashMap<>())
|
||||
.merge(statName, value, Long::sum);
|
||||
}
|
||||
}
|
||||
|
||||
protected void saveStats()
|
||||
protected void save(Map<CoreClient, Map<String, Long>> statsMap, Consumer<Map<Integer, Map<Integer, Long>>> action, String type)
|
||||
{
|
||||
if (_statUploadQueue.isEmpty())
|
||||
if (statsMap.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;
|
||||
Map<Integer, Map<Integer, Long>> uploadQueue = new HashMap<>();
|
||||
|
||||
try
|
||||
{
|
||||
PlayerInfo info = PlayerCache.getInstance().getPlayer(player);
|
||||
|
||||
uploadQueue.put(info.getAccountId(), new NautHashMap<Integer, Long>());
|
||||
|
||||
for (String statName : _statUploadQueue.get(player).keySet())
|
||||
synchronized (STATS_LOCK)
|
||||
{
|
||||
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)
|
||||
statsMap.entrySet().removeIf(entry ->
|
||||
{
|
||||
//System.out.println("[StatsManager] AccountId was not set for " + player.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
CoreClient client = entry.getKey();
|
||||
if (Bukkit.getPlayer(client.getUniqueId()) != null)
|
||||
return false;
|
||||
|
||||
_repository.saveStats(uploadQueue);
|
||||
Map<Integer, Long> uploadStats = uploadQueue.computeIfAbsent(client.getAccountId(), key -> new HashMap<>());
|
||||
|
||||
entry.getValue().forEach((statName, amount) ->
|
||||
{
|
||||
// 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
action.accept(uploadQueue);
|
||||
}
|
||||
|
||||
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 (_statSync)
|
||||
synchronized (STATS_LOCK)
|
||||
{
|
||||
if (_stats.containsKey(statName))
|
||||
{
|
||||
|
@ -282,37 +232,40 @@ public class StatsManager extends MiniDbClientPlugin<PlayerStats>
|
|||
return;
|
||||
}
|
||||
|
||||
_repository.addStat(statName);
|
||||
_repository.registerNewStat(statName);
|
||||
|
||||
_stats.clear();
|
||||
|
||||
for (Stat stat : _repository.retrieveStats())
|
||||
{
|
||||
_stats.put(stat.Name, stat.Id);
|
||||
_stats.put(stat.getName(), stat.getId());
|
||||
}
|
||||
|
||||
if (callback != null) callback.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getStatId(String statName)
|
||||
@EventHandler
|
||||
private void onPlayerJoin(PlayerJoinEvent event)
|
||||
{
|
||||
return _stats.get(statName);
|
||||
Set<String> statsToReset = new HashSet<>();
|
||||
|
||||
Get(event.getPlayer()).getStats().forEach((stat, amount) ->
|
||||
{
|
||||
if (!_stats.containsKey(stat))
|
||||
return;
|
||||
|
||||
if (amount == -1)
|
||||
{
|
||||
statsToReset.add(stat);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected PlayerStats addPlayer(UUID uuid)
|
||||
statsToReset.forEach(stat ->
|
||||
{
|
||||
return new PlayerStats();
|
||||
}
|
||||
|
||||
public PlayerStats getOfflinePlayerStats(String playerName) throws SQLException
|
||||
{
|
||||
return _repository.loadOfflinePlayerStats(playerName);
|
||||
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
|
||||
|
|
|
@ -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>();
|
||||
List<Stat> stats = new ArrayList<>();
|
||||
|
||||
executeQuery(RETRIEVE_STATS, new ResultSetCallable()
|
||||
{
|
||||
public void processResultSet(ResultSet resultSet) throws SQLException
|
||||
executeQuery(RETRIEVE_STATS, resultSet ->
|
||||
{
|
||||
while (resultSet.next())
|
||||
{
|
||||
Stat stat = new Stat();
|
||||
|
||||
stat.Id = resultSet.getInt(1);
|
||||
stat.Name = resultSet.getString(2);
|
||||
|
||||
stats.add(stat);
|
||||
}
|
||||
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,7 +88,7 @@ public class StatsRepository extends MinecraftRepository
|
|||
{
|
||||
for (Integer statId : uploadQueue.get(accountId).keySet())
|
||||
{
|
||||
if(overRideStat)
|
||||
if (overrideStat)
|
||||
{
|
||||
Update update = context
|
||||
.update(Tables.accountStat)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -35,19 +35,7 @@ public class TimeCommand extends CommandBase<StatsManager>
|
|||
|
||||
if (target == null)
|
||||
{
|
||||
Plugin.getPlugin().getServer().getScheduler().runTaskAsynchronously(Plugin.getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
final PlayerStats stats = Plugin.getOfflinePlayerStats(args[0]);
|
||||
|
||||
Plugin.getPlugin().getServer().getScheduler().runTask(Plugin.getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
Plugin.getOfflinePlayerStats(args[0], stats ->
|
||||
{
|
||||
if (stats == null)
|
||||
{
|
||||
|
@ -58,14 +46,6 @@ public class TimeCommand extends CommandBase<StatsManager>
|
|||
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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,19 +38,7 @@ public class PlayTimeCommand extends CommandBase<StatsManager>
|
|||
|
||||
if (target == null)
|
||||
{
|
||||
Plugin.getPlugin().getServer().getScheduler().runTaskAsynchronously(Plugin.getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
final PlayerStats stats = Plugin.getOfflinePlayerStats(args[0]);
|
||||
|
||||
Plugin.getPlugin().getServer().getScheduler().runTask(Plugin.getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
Plugin.getOfflinePlayerStats(args[0], stats ->
|
||||
{
|
||||
if (stats == null)
|
||||
{
|
||||
|
@ -61,14 +49,6 @@ public class PlayTimeCommand extends CommandBase<StatsManager>
|
|||
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."));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue