0

15 Commits
v1.5 ... v1.8

11 changed files with 272 additions and 16 deletions

View File

@@ -14,6 +14,7 @@ repositories {
mavenLocal()
mavenCentral()
maven { url 'https://hub.spigotmc.org/nexus/content/groups/public' }
maven { url 'https://dmx-mc-project.gitlab.io/maven-repository/' }
}
ext {
@@ -25,7 +26,8 @@ ext {
'org.yaml:snakeyaml'
]],
commons_text: 'org.apache.commons:commons-text:1.9',
lombok: 'org.projectlombok:lombok:1.18.12'
lombok: 'org.projectlombok:lombok:1.18.12',
reflection_object: 'ru.dmitriymx:reflection-object:1.0-BETA'
]
}
@@ -44,4 +46,5 @@ dependencies {
compileOnly2 libs.bukkit
implementation libs.commons_text
implementation libs.reflection_object
}

View File

@@ -1,3 +1,3 @@
projectGroup=ghast
projectName=ghast-tools
projectVersion=1.5
projectVersion=1.8

View File

@@ -0,0 +1,27 @@
package ghast;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.util.Vector;
@UtilityClass
@SuppressWarnings("unused")
public class EffectsHelper {
public void playSound(Location location, Sound sound, float pitch) {
location.getWorld().playSound(location, sound, SoundCategory.MASTER, 1.0f, pitch);
}
public void particle(Location location, Particle particle, double dx, double dy, double dz, double speed, int amount) {
location.getWorld().spawnParticle(particle, location, amount, dx, dy, dz, speed);
}
//TODO нужно проверить
public void particle(Location location, Particle particle, Vector vector, double speed, int amount) {
particle(location, particle, vector.getX(), vector.getY(), vector.getZ(), speed, amount);
}
}

View File

@@ -0,0 +1,8 @@
package ghast.command;
import org.bukkit.command.CommandSender;
public interface CommandExecuter {
void execute(CommandSender sender, String[] args);
}

View File

@@ -0,0 +1,71 @@
package ghast.command;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import ru.dmitriymx.reflection.ReflectionObject;
@UtilityClass
@SuppressWarnings("unused")
public class CommandManager {
public Builder create(String name) {
return new Builder(name);
}
public void register(String name, CommandExecuter executer) {
create(name).executer(executer).register();
}
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public static class Builder {
private final String name;
private CommandExecuter executer;
private ErrorConsumer errorConsumer;
private Boolean onlyPlayer;
private String deniedMessage;
public Builder executer(CommandExecuter executer) {
this.executer = executer;
return this;
}
public Builder onError(ErrorConsumer errorConsumer) {
this.errorConsumer = errorConsumer;
return this;
}
public Builder useOnlyPlayer(String deniedMessage) {
this.onlyPlayer = true;
this.deniedMessage = deniedMessage;
return this;
}
public Builder useOnlyPlayer() {
return useOnlyPlayer(null);
}
public Builder useOnlyConsole(String deniedMessage) {
this.onlyPlayer = false;
this.deniedMessage = deniedMessage;
return this;
}
public Builder useOnlyConsole() {
return useOnlyConsole(null);
}
public void register() {
//TODO для Paper такие "извращения" не требуются. Нужно продумать.
new ReflectionObject(Bukkit.getServer())
.method("getCommandMap").invoke()
.method("register", String.class, Command.class).invoke(
name, new CommandWrapper(name, this.onlyPlayer, this.deniedMessage,
this.executer, this.errorConsumer)
);
}
}
}

View File

@@ -0,0 +1,71 @@
package ghast.command;
import ghast.XLog;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.entity.Player;
class CommandWrapper extends BukkitCommand {
private static final String DEFAULT_DENIED_MESSAGE_PLAYERS = ChatColor.RED + "This command use only players";
private static final String DEFAULT_DENIED_MESSAGE_CONSOLE = ChatColor.RED + "This command use only in console";
private static final ErrorConsumer DEFAULT_ERROR_CONSUMER =
(sender, commandName, args, exception) -> {
sender.sendMessage(String.format("%sError execute command '%s'!", ChatColor.RED, commandName));
XLog.error("Error execute command ''{0}'' with args ''{1}''",
commandName, String.join(" ", args), exception);
};
private final CommandExecuter executer;
private final ErrorConsumer errorConsumer;
private final Boolean onlyPlayer;
private String deniedMessage;
protected CommandWrapper(String name, Boolean onlyPlayer, String deniedMessage,
CommandExecuter executer, ErrorConsumer errorConsumer) {
super(name);
this.onlyPlayer = onlyPlayer;
this.executer = executer;
if (onlyPlayer != null) {
if (deniedMessage == null) {
this.deniedMessage = Boolean.TRUE.equals(onlyPlayer) ? DEFAULT_DENIED_MESSAGE_PLAYERS
: DEFAULT_DENIED_MESSAGE_CONSOLE;
} else {
this.deniedMessage = deniedMessage;
}
}
if(errorConsumer == null) {
this.errorConsumer = DEFAULT_ERROR_CONSUMER;
} else {
this.errorConsumer = errorConsumer;
}
}
@Override
@SuppressWarnings("java:S1066")
public boolean execute(CommandSender commandSender, String commandName, String[] args) {
if (Boolean.TRUE.equals(onlyPlayer)) {
if (!(commandSender instanceof Player)) {
commandSender.sendMessage(deniedMessage);
return true;
}
} else if (Boolean.FALSE.equals(onlyPlayer)) { // use console only
if (commandSender instanceof Player) {
commandSender.sendMessage(deniedMessage);
return true;
}
}
try {
executer.execute(commandSender, args);
return true;
} catch (Exception e) {
errorConsumer.accept(commandSender, commandName, args, e);
return false;
}
}
}

View File

@@ -0,0 +1,8 @@
package ghast.command;
import org.bukkit.command.CommandSender;
public interface ErrorConsumer {
void accept(CommandSender sender, String commandName, String[] args, Exception exception);
}

View File

@@ -0,0 +1,20 @@
package ghast.scheduler;
import lombok.RequiredArgsConstructor;
import org.bukkit.scheduler.BukkitTask;
@RequiredArgsConstructor
public class BukkitScheduleTask implements ScheduleTask {
private final BukkitTask bukkitTask;
@Override
public boolean isCanceled() {
return bukkitTask.isCancelled();
}
@Override
public void cancel() {
bukkitTask.cancel();
}
}

View File

@@ -0,0 +1,21 @@
package ghast.scheduler;
import lombok.RequiredArgsConstructor;
import java.util.concurrent.Future;
@RequiredArgsConstructor
public class JavaScheduleTask implements ScheduleTask {
private final Future<?> future;
@Override
public boolean isCanceled() {
return future.isCancelled();
}
@Override
public void cancel() {
future.cancel(true);
}
}

View File

@@ -1,11 +1,13 @@
package ghast;
package ghast.scheduler;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import ghast.GhastTools;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.*;
@@ -45,48 +47,65 @@ public class ScheduleManager {
return this;
}
public void execute(Runnable runnable) {
public ScheduleTask execute(Runnable runnable) {
if (useBukkitScheduler) {
createBukkitSchedule(runnable);
return createBukkitSchedule(runnable);
} else {
createSchedule(runnable);
return createSchedule(runnable);
}
}
private void createBukkitSchedule(Runnable runnable) {
private ScheduleTask createBukkitSchedule(Runnable runnable) {
BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
BukkitScheduleTask resultTask;
if (this.afterMs == null && this.everyMs == null) {
bukkitScheduler.runTask(GhastTools.getPlugin(), runnable);
BukkitTask bukkitTask = bukkitScheduler.runTask(GhastTools.getPlugin(), runnable);
resultTask = new BukkitScheduleTask(bukkitTask);
} else if (this.everyMs != null) {
long everyTicks = this.everyMs / MS_PER_ONE_TICK;
long afterTicks = this.afterMs != null ? this.afterMs / MS_PER_ONE_TICK : 0;
bukkitScheduler.runTaskTimer(GhastTools.getPlugin(), runnable, afterTicks, everyTicks);
BukkitTask bukkitTask = bukkitScheduler.runTaskTimer(GhastTools.getPlugin(), runnable, afterTicks,
everyTicks);
resultTask = new BukkitScheduleTask(bukkitTask);
} else {
long ticks = this.afterMs / MS_PER_ONE_TICK;
bukkitScheduler.runTaskLater(GhastTools.getPlugin(), runnable, ticks);
}
BukkitTask bukkitTask = bukkitScheduler.runTaskLater(GhastTools.getPlugin(), runnable, ticks);
resultTask = new BukkitScheduleTask(bukkitTask);
}
private void createSchedule(Runnable runnable) {
return resultTask;
}
private ScheduleTask createSchedule(Runnable runnable) {
ExecutorService executorService;
JavaScheduleTask resultTask;
if (this.afterMs == null && this.everyMs == null) {
executorService = Executors.newSingleThreadExecutor(THREAD_FACTORY);
executorService.execute(runnable);
Future<?> future = executorService.submit(runnable);
resultTask = new JavaScheduleTask(future);
} else if (this.everyMs != null) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, THREAD_FACTORY);
scheduledExecutorService.scheduleAtFixedRate(runnable,
ScheduledExecutorService scheduledExecutorService
= Executors.newScheduledThreadPool(1, THREAD_FACTORY);
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(runnable,
this.afterMs != null ? this.afterMs : 0,
everyMs, TimeUnit.MILLISECONDS);
resultTask = new JavaScheduleTask(scheduledFuture);
executorService = scheduledExecutorService;
} else {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1, THREAD_FACTORY);
scheduledExecutorService.schedule(runnable, afterMs, TimeUnit.MILLISECONDS);
ScheduledExecutorService scheduledExecutorService
= Executors.newScheduledThreadPool(1, THREAD_FACTORY);
ScheduledFuture<?> schedule = scheduledExecutorService
.schedule(runnable, afterMs, TimeUnit.MILLISECONDS);
resultTask = new JavaScheduleTask(schedule);
executorService = scheduledExecutorService;
}
executorService.shutdown();
return resultTask;
}
}
}

View File

@@ -0,0 +1,8 @@
package ghast.scheduler;
public interface ScheduleTask {
boolean isCanceled();
void cancel();
}