-
-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement example PlayerDelayedCommandAPICommand
- Loading branch information
1 parent
dbbccf3
commit 0270eca
Showing
6 changed files
with
199 additions
and
9 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
examples/bukkit/delayed-commands/src/main/java/io/github/jorelali/Main.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
package io.github.jorelali; | ||
|
||
import io.github.jorelali.delayedapicommand.DelayedAPICommands; | ||
import io.github.jorelali.delayhandler.DelayHandlerCommands; | ||
import org.bukkit.plugin.java.JavaPlugin; | ||
|
||
public class Main extends JavaPlugin { | ||
@Override | ||
public void onEnable() { | ||
DelayHandlerCommands.registerCommands(); | ||
DelayedAPICommands.registerCommands(); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...layed-commands/src/main/java/io/github/jorelali/delayedapicommand/DelayedAPICommands.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package io.github.jorelali.delayedapicommand; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
public class DelayedAPICommands { | ||
public static void registerCommands() { | ||
// PlayerDelayedCommandAPICommand has all the functions of a CommandAPICommand, but also adds delay to any | ||
// executors given by the `executesPlayer` methods | ||
|
||
// PerPlayerDelayedCommandAPICommand keeps track of the delay for each player that uses it | ||
new PerPlayerDelayedCommandAPICommand("delayedAPICommandPerPlayer", 10, TimeUnit.SECONDS) | ||
.executesPlayer(info -> { | ||
info.sender().sendMessage("You ran delayedAPICommandPerPlayer"); | ||
}) | ||
.register(); | ||
|
||
// GlobalPlayerDelayedCommandAPICommand shares its delay for all players | ||
new GlobalPlayerDelayedCommandAPICommand("delayedAPICommandGlobal", 10, TimeUnit.SECONDS) | ||
.executesPlayer((player, args) -> { | ||
player.sendMessage("You ran delayedAPICommandGlobal"); | ||
}) | ||
.register(); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
.../main/java/io/github/jorelali/delayedapicommand/GlobalPlayerDelayedCommandAPICommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.github.jorelali.delayedapicommand; | ||
|
||
import dev.jorel.commandapi.CommandAPI; | ||
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; | ||
import org.bukkit.entity.Player; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
// This shares its delay for all players | ||
public class GlobalPlayerDelayedCommandAPICommand extends PlayerDelayedCommandAPICommand { | ||
// The next time when this command will be allowed to run | ||
// The default time is 0, which is always in the past, so the command will always be run the first time | ||
private long nextTime = 0; | ||
|
||
public GlobalPlayerDelayedCommandAPICommand(String commandName, long time, TimeUnit timeUnit) { | ||
super(commandName, time, timeUnit); | ||
} | ||
|
||
@Override | ||
void throwExceptionIfCannotRun(Player player) throws WrapperCommandSyntaxException { | ||
// We don't have to worry about this overflowing for about 290 million years | ||
// https://stackoverflow.com/questions/2978452/when-will-system-currenttimemillis-overflow | ||
// This code will reward your patience by letting you run the command without waiting | ||
long currentTime = System.currentTimeMillis(); | ||
|
||
// If it isn't time to run the command yet, throw the exception | ||
if(currentTime < nextTime) { | ||
throw CommandAPI.failWithString( | ||
"This command cannot be run for another " | ||
+ getDurationString(nextTime - currentTime) | ||
); | ||
} | ||
|
||
// If the command is run, set the next possible time | ||
nextTime = currentTime + delay; | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...src/main/java/io/github/jorelali/delayedapicommand/PerPlayerDelayedCommandAPICommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package io.github.jorelali.delayedapicommand; | ||
|
||
import dev.jorel.commandapi.CommandAPI; | ||
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; | ||
import org.bukkit.entity.Player; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.UUID; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
// This keeps track of the delay for each player that uses it | ||
public class PerPlayerDelayedCommandAPICommand extends PlayerDelayedCommandAPICommand { | ||
// Use UUID here in case player leaves and rejoins server to get around delay | ||
private final Map<UUID, Long> nextTimesPerPlayer = new HashMap<>(); | ||
|
||
public PerPlayerDelayedCommandAPICommand(String commandName, long time, TimeUnit timeUnit) { | ||
super(commandName, time, timeUnit); | ||
} | ||
|
||
@Override | ||
void throwExceptionIfCannotRun(Player player) throws WrapperCommandSyntaxException { | ||
// Get the next time when this player is allowed to run the command | ||
// The default time is 0, which is always in the past, so the command will always be run the first time | ||
long nextTime = nextTimesPerPlayer.getOrDefault(player.getUniqueId(), 0L); | ||
long currentTime = System.currentTimeMillis(); | ||
|
||
// If it isn't time to run the command yet, throw the exception | ||
if(currentTime < nextTime) { | ||
throw CommandAPI.failWithString( | ||
"You must wait " | ||
+ getDurationString(nextTime - currentTime) | ||
+ " before running this command again" | ||
); | ||
} | ||
|
||
// If the command is run, set the next possible time | ||
nextTimesPerPlayer.put(player.getUniqueId(), currentTime + delay); | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
...ds/src/main/java/io/github/jorelali/delayedapicommand/PlayerDelayedCommandAPICommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package io.github.jorelali.delayedapicommand; | ||
|
||
import dev.jorel.commandapi.CommandAPICommand; | ||
import dev.jorel.commandapi.exceptions.WrapperCommandSyntaxException; | ||
import dev.jorel.commandapi.executors.*; | ||
import org.bukkit.entity.Player; | ||
|
||
import java.time.Duration; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
// This class extends CommandAPICommand to implement delayed commands | ||
public abstract class PlayerDelayedCommandAPICommand extends CommandAPICommand { | ||
protected final long delay; | ||
|
||
public PlayerDelayedCommandAPICommand(String commandName, long time, TimeUnit timeUnit) { | ||
super(commandName); | ||
// Delay is the value in milliseconds | ||
delay = timeUnit.toMillis(time); | ||
} | ||
|
||
// This method is implemented by the child classes | ||
// If the command is currently delayed for the player, an exception should be thrown | ||
abstract void throwExceptionIfCannotRun(Player player) throws WrapperCommandSyntaxException; | ||
|
||
// This helper method formats a millisecond duration into a String representing how long is left in the delay | ||
static String getDurationString(long millis) { | ||
Duration duration = Duration.ofMillis(millis); | ||
|
||
long days = duration.toDays(); | ||
long hours = duration.toHours() % 24; | ||
long minutes = duration.toMinutes() % 60; | ||
long seconds = duration.getSeconds() % 60; | ||
|
||
String durationString; | ||
if(days != 0) durationString = days + ":" + hours + ":" + minutes + " days"; | ||
else if (hours != 0) durationString = hours + ":" + minutes + ":" + seconds + "hours"; | ||
else if (minutes != 0) durationString = minutes + ":" + seconds + "minutes"; | ||
else if (seconds != 1) durationString = seconds + " seconds"; | ||
else durationString = "1 second"; | ||
|
||
return durationString; | ||
} | ||
|
||
// Override the usual executes methods to replace the executor with a delayed executor | ||
// They take one CommandAPI executor and uses it inside a new executor | ||
// The new executor also uses the throwExceptionIfCannotRun method to stop | ||
// command execution if the command's delay is currently in effect | ||
@Override | ||
public CommandAPICommand executesPlayer(PlayerExecutionInfo executor) { | ||
super.executesPlayer(info -> { | ||
throwExceptionIfCannotRun(info.sender()); | ||
executor.run(info); | ||
}); | ||
|
||
return this; | ||
} | ||
|
||
@Override | ||
public CommandAPICommand executesPlayer(PlayerCommandExecutor executor) { | ||
super.executesPlayer((player, args) -> { | ||
throwExceptionIfCannotRun(player); | ||
executor.run(player, args); | ||
}); | ||
|
||
return this; | ||
} | ||
|
||
@Override | ||
public CommandAPICommand executesPlayer(PlayerResultingExecutionInfo executor) { | ||
super.executesPlayer(info -> { | ||
throwExceptionIfCannotRun(info.sender()); | ||
return executor.run(info); | ||
}); | ||
|
||
return this; | ||
} | ||
|
||
@Override | ||
public CommandAPICommand executesPlayer(PlayerResultingCommandExecutor executor) { | ||
super.executesPlayer((player, args) -> { | ||
throwExceptionIfCannotRun(player); | ||
executor.run(player, args); | ||
}); | ||
|
||
return this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters