mirror of
https://github.com/itHotL/PlayerStats.git
synced 2025-02-02 23:31:21 +01:00
Made ShareCommand more better, added feedback for no-share-allowed
This commit is contained in:
parent
ce8b870560
commit
1c8d77e9cd
@ -47,7 +47,7 @@ public class Main extends JavaPlugin {
|
||||
PluginCommand reloadcmd = this.getCommand("statisticreload");
|
||||
if (reloadcmd != null) reloadcmd.setExecutor(new ReloadCommand(threadManager));
|
||||
PluginCommand sharecmd = this.getCommand("statisticshare");
|
||||
if (sharecmd != null) sharecmd.setExecutor(new ShareCommand(shareManager));
|
||||
if (sharecmd != null) sharecmd.setExecutor(new ShareCommand(shareManager, messageWriter));
|
||||
|
||||
//register the listener
|
||||
Bukkit.getPluginManager().registerEvents(new JoinListener(threadManager), this);
|
||||
|
@ -8,9 +8,11 @@ import net.kyori.adventure.text.TextComponent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -23,18 +25,20 @@ public final class ShareManager {
|
||||
private static boolean isEnabled;
|
||||
private static int waitingTime;
|
||||
|
||||
private volatile AtomicInteger resultID; //always starts with value 0
|
||||
private ConcurrentHashMap<UUID, StatResult> statResults = null;
|
||||
private ConcurrentHashMap<String, Instant> shareTimeStamp = null;
|
||||
private volatile AtomicInteger resultID;
|
||||
private ConcurrentHashMap<UUID, StatResult> statResultQueue;
|
||||
private ConcurrentHashMap<String, Instant> shareTimeStamp;
|
||||
private ArrayBlockingQueue<UUID> sharedResults;
|
||||
|
||||
private ShareManager(ConfigHandler config) {
|
||||
isEnabled = config.enableStatSharing();
|
||||
waitingTime = config.getStatShareWaitingTime();
|
||||
|
||||
if (isEnabled) {
|
||||
resultID = new AtomicInteger();
|
||||
statResults = new ConcurrentHashMap<>();
|
||||
resultID = new AtomicInteger(); //always starts with value 0
|
||||
statResultQueue = new ConcurrentHashMap<>();
|
||||
shareTimeStamp = new ConcurrentHashMap<>();
|
||||
sharedResults = new ArrayBlockingQueue<>(500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,15 +59,19 @@ public final class ShareManager {
|
||||
isEnabled = config.enableStatSharing();
|
||||
waitingTime = config.getStatShareWaitingTime();
|
||||
|
||||
//if we went from disabled to enabled, initialize the HashMaps
|
||||
if (isEnabled && statResults == null) {
|
||||
statResults = new ConcurrentHashMap<>();
|
||||
shareTimeStamp = new ConcurrentHashMap<>();
|
||||
|
||||
if (isEnabled) { //reset the sharedResultsQueue
|
||||
sharedResults = new ArrayBlockingQueue<>(500);
|
||||
if (statResultQueue == null) { //if we went from disabled to enabled, initialize the HashMaps
|
||||
statResultQueue = new ConcurrentHashMap<>();
|
||||
shareTimeStamp = new ConcurrentHashMap<>();
|
||||
}
|
||||
}
|
||||
//if we went from enabled to disabled, purge the existing data
|
||||
else if (!isEnabled && statResults != null) {
|
||||
statResults = null;
|
||||
else if (statResultQueue != null) {
|
||||
statResultQueue = null;
|
||||
shareTimeStamp = null;
|
||||
sharedResults = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,22 +85,38 @@ public final class ShareManager {
|
||||
int ID = getNextIDNumber();
|
||||
UUID identifier = UUID.randomUUID();
|
||||
|
||||
statResults.put(identifier, new StatResult(playerName, statResult, ID, identifier));
|
||||
statResultQueue.put(identifier, new StatResult(playerName, statResult, ID, identifier));
|
||||
MyLogger.logMsg("Saving statResults with no. " + ID, DebugLevel.MEDIUM);
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public @Nullable TextComponent getResultMessage(String playerName, UUID identifier) {
|
||||
if (statResults.containsKey(identifier) && playerCanShare(playerName)) {
|
||||
/** Takes a statResult from the internal ConcurrentHashmap,
|
||||
puts the current time in the shareTimeStamp (ConcurrentHashMap),
|
||||
puts the shareCode (UUID) in the sharedResults (ArrayBlockingQueue),
|
||||
and returns the statResult. If no statResult was found, returns null.*/
|
||||
public @Nullable TextComponent getStatResult(String playerName, UUID identifier) {
|
||||
if (statResultQueue.containsKey(identifier)) {
|
||||
shareTimeStamp.put(playerName, Instant.now());
|
||||
return statResults.remove(identifier).statResult();
|
||||
|
||||
if (!sharedResults.offer(identifier)) { //create a new ArrayBlockingQueue if our queue is full
|
||||
ArrayBlockingQueue<UUID> newQueue = new ArrayBlockingQueue<>(500);
|
||||
|
||||
synchronized (this) { //put the last 50 values in the new Queue
|
||||
UUID[] lastValues = sharedResults.toArray(new UUID[0]);
|
||||
Arrays.stream(Arrays.copyOfRange(lastValues, 450, 499))
|
||||
.parallel().iterator()
|
||||
.forEachRemaining(newQueue::offer);
|
||||
sharedResults = newQueue;
|
||||
}
|
||||
sharedResults.offer(identifier);
|
||||
}
|
||||
return statResultQueue.remove(identifier).statResult();
|
||||
} else {
|
||||
//TODO send error-message if on time-out, and error-message if request is already shared
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean playerCanShare(String playerName) {
|
||||
public boolean isOnCoolDown(String playerName) {
|
||||
if (waitingTime == 0 || !shareTimeStamp.containsKey(playerName)) {
|
||||
return true;
|
||||
} else {
|
||||
@ -101,10 +125,14 @@ public final class ShareManager {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean requestAlreadyShared(UUID shareCode) {
|
||||
return sharedResults.contains(shareCode);
|
||||
}
|
||||
|
||||
/** If the given player already has more than x (in this case 25) StatResults saved,
|
||||
remove the oldest one.*/
|
||||
private void removeExcessResults(String playerName) {
|
||||
List<StatResult> alreadySavedResults = statResults.values()
|
||||
List<StatResult> alreadySavedResults = statResultQueue.values()
|
||||
.parallelStream()
|
||||
.filter(result -> result.playerName().equalsIgnoreCase(playerName))
|
||||
.toList();
|
||||
@ -114,8 +142,8 @@ public final class ShareManager {
|
||||
.parallelStream()
|
||||
.min(Comparator.comparing(StatResult::ID))
|
||||
.orElseThrow().uuid();
|
||||
MyLogger.logMsg("Removing old stat no. " + statResults.get(uuid).ID() + " for player " + playerName, DebugLevel.MEDIUM);
|
||||
statResults.remove(uuid);
|
||||
MyLogger.logMsg("Removing old stat no. " + statResultQueue.get(uuid).ID() + " for player " + playerName, DebugLevel.MEDIUM);
|
||||
statResultQueue.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,10 @@ package com.gmail.artemis.the.gr8.playerstats.commands;
|
||||
|
||||
import com.gmail.artemis.the.gr8.playerstats.Main;
|
||||
import com.gmail.artemis.the.gr8.playerstats.ShareManager;
|
||||
import com.gmail.artemis.the.gr8.playerstats.msg.MessageWriter;
|
||||
import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -14,18 +17,39 @@ public class ShareCommand implements CommandExecutor {
|
||||
|
||||
private static BukkitAudiences adventure;
|
||||
private static ShareManager shareManager;
|
||||
private final MessageWriter messageWriter;
|
||||
|
||||
public ShareCommand(ShareManager s) {
|
||||
public ShareCommand(ShareManager s, MessageWriter m) {
|
||||
adventure = Main.adventure();
|
||||
shareManager = s;
|
||||
messageWriter = m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, String label, String[] args) {
|
||||
adventure.all().sendMessage(shareManager.getResultMessage(sender.getName(), UUID.fromString(args[0])));
|
||||
//TODO send feedback if stat-result is null:
|
||||
//can't share again yet (time-out)
|
||||
//already shared this result (not in statResult list anymore)
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
|
||||
if (args.length == 1 && shareManager.isEnabled()) {
|
||||
UUID shareCode;
|
||||
try {
|
||||
shareCode = UUID.fromString(args[0]);
|
||||
} catch (IllegalArgumentException e) {
|
||||
MyLogger.logException(e, "ShareCommand", "/statshare is being called without a valid UUID argument");
|
||||
return false;
|
||||
}
|
||||
if (shareManager.isOnCoolDown(sender.getName())) {
|
||||
adventure.sender(sender).sendMessage(messageWriter.stillOnShareCoolDown());
|
||||
}
|
||||
else if (shareManager.requestAlreadyShared(shareCode)) {
|
||||
adventure.sender(sender).sendMessage(messageWriter.resultsAlreadyShared());
|
||||
}
|
||||
else {
|
||||
TextComponent result = shareManager.getStatResult(sender.getName(), shareCode);
|
||||
if (result == null) { //at this point the only possible cause of statResult being null is the request being older than 25 player-requests ago
|
||||
adventure.sender(sender).sendMessage(messageWriter.statResultsTooOld());
|
||||
} else {
|
||||
adventure.all().sendMessage(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,10 @@ public class ComponentFactory {
|
||||
return text().color(PluginColor.MEDIUM_BLUE.getColor()).build();
|
||||
}
|
||||
|
||||
public TextComponent messageAccentComponent() {
|
||||
return text().color(PluginColor.LIGHT_GOLD.getColor()).build();
|
||||
}
|
||||
|
||||
public TextComponent.Builder playerNameBuilder(String playerName, Target selection) {
|
||||
return getComponentBuilder(playerName,
|
||||
getColorFromString(config.getPlayerNameDecoration(selection, false)),
|
||||
|
@ -108,6 +108,29 @@ public class MessageWriter {
|
||||
"Please wait for your previous lookup to finish!"));
|
||||
}
|
||||
|
||||
public TextComponent stillOnShareCoolDown() {
|
||||
return componentFactory.pluginPrefixComponent(false)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content("You need to wait")
|
||||
.append(space())
|
||||
.append(componentFactory.messageAccentComponent().content(config.getStatShareWaitingTime() + ""))
|
||||
.append(space()))
|
||||
.append(text("minutes before you are able to share again!"));
|
||||
}
|
||||
|
||||
public TextComponent resultsAlreadyShared() {
|
||||
return componentFactory.pluginPrefixComponent(false)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content("You already shared these results!"));
|
||||
}
|
||||
|
||||
public TextComponent statResultsTooOld() {
|
||||
return componentFactory.pluginPrefixComponent(false)
|
||||
.append(space())
|
||||
.append(componentFactory.messageComponent().content(
|
||||
"It has been too long since you looked up this statistic, please repeat the original look-up if you want to share it!"));
|
||||
}
|
||||
|
||||
public TextComponent unknownError(boolean isBukkitConsole) {
|
||||
return componentFactory.pluginPrefixComponent(isBukkitConsole)
|
||||
.append(space())
|
||||
|
@ -85,7 +85,7 @@ public class StatThread extends Thread {
|
||||
case SERVER -> messageWriter.formatServerStat(getServerTotal(), request);
|
||||
};
|
||||
|
||||
if (shareManager.isEnabled()) {
|
||||
if (shareManager.isEnabled() && request.getCommandSender().hasPermission("playerstats.share")) {
|
||||
UUID shareCode = shareManager.saveStatResult(request.getCommandSender().getName(), statResult);
|
||||
statResult = messageWriter.addShareButton(statResult, shareCode);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ permissions:
|
||||
default: true
|
||||
playerstats.share:
|
||||
description: allows sharing stats in chat
|
||||
default: true
|
||||
default: op
|
||||
playerstats.reload:
|
||||
description: allows usage of /statreload
|
||||
default: op
|
Loading…
Reference in New Issue
Block a user