diff --git a/src/main/java/me/trouper/alias/AliasContext.java b/src/main/java/me/trouper/alias/AliasContext.java index 4af82c9..b73deb9 100644 --- a/src/main/java/me/trouper/alias/AliasContext.java +++ b/src/main/java/me/trouper/alias/AliasContext.java @@ -4,6 +4,7 @@ import me.trouper.alias.data.Common; import me.trouper.alias.data.DataManager; import me.trouper.alias.data.JsonSerializable; import me.trouper.alias.server.AutoRegistrar; +import me.trouper.alias.server.events.listeners.FreezeListener; import me.trouper.alias.server.events.listeners.GuiListener; import me.trouper.alias.server.events.listeners.SpawnListener; import me.trouper.alias.server.events.listeners.WandListener; @@ -11,6 +12,7 @@ import me.trouper.alias.server.systems.TaskManager; import me.trouper.alias.server.systems.Text; import me.trouper.alias.server.systems.Verbose; import me.trouper.alias.server.systems.display.DisplayManager; +import me.trouper.alias.server.systems.freeze.FreezeManager; import me.trouper.alias.server.update.AutoUpdater; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; @@ -27,6 +29,7 @@ public class AliasContext { private final Text text; private final Verbose verbose; private final DisplayManager displayManager; + private final FreezeManager freezeManager; private boolean enabled = false; public AliasContext(JavaPlugin plugin, Common common) { @@ -38,6 +41,7 @@ public class AliasContext { this.text = new Text(this); this.verbose = new Verbose(this); this.displayManager = new DisplayManager(this); + this.freezeManager = new FreezeManager(this); } /** @@ -57,6 +61,7 @@ public class AliasContext { Bukkit.getPluginManager().registerEvents(new GuiListener(),getPlugin()); Bukkit.getPluginManager().registerEvents(new SpawnListener(this),getPlugin()); Bukkit.getPluginManager().registerEvents(new WandListener(this),getPlugin()); + Bukkit.getPluginManager().registerEvents(new FreezeListener(this),getPlugin()); List> copy = new ArrayList<>(autoRegistrar.getSerializables()); for (JsonSerializable serializable : copy) { dataManager.load(serializable.getClass()); @@ -96,4 +101,5 @@ public class AliasContext { public DisplayManager getDisplayManager() { return displayManager; } public DataManager getDataManager() { return dataManager; } public AutoUpdater getAutoUpdater() { return autoUpdater; } + public FreezeManager getFreezeManager() { return freezeManager; } } \ No newline at end of file diff --git a/src/main/java/me/trouper/alias/server/events/listeners/FreezeListener.java b/src/main/java/me/trouper/alias/server/events/listeners/FreezeListener.java new file mode 100644 index 0000000..c944e7b --- /dev/null +++ b/src/main/java/me/trouper/alias/server/events/listeners/FreezeListener.java @@ -0,0 +1,81 @@ +package me.trouper.alias.server.events.listeners; + +import me.trouper.alias.AliasContext; +import me.trouper.alias.server.systems.freeze.FreezeSession; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class FreezeListener implements Listener { + + private final AliasContext context; + + public FreezeListener(AliasContext context) { + this.context = context; + } + + @EventHandler + public void onMove(PlayerMoveEvent e) { + Player p = e.getPlayer(); + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze == null) return; + if (!freeze.canMove()) { + if (!e.getFrom().toVector().equals(e.getTo().toVector())) { + e.setTo(e.getFrom()); + } + } + freeze.handleMove(p); + } + + @EventHandler + public void onInteract(PlayerInteractEvent e) { + Player p = e.getPlayer(); + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze == null) return; + if (!freeze.canInt()) e.setCancelled(true); + freeze.handleInteract(p); + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent e) { + Player p = e.getPlayer(); + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze == null) return; + if (!freeze.getAllowedCommands().contains(e.getMessage().split(" ")[0])) { + e.setCancelled(true); + } + freeze.handleCommand(p); + } + + @EventHandler + public void onDamageByEntity(EntityDamageByEntityEvent e) { + if (!(e.getEntity() instanceof Player p)) return; + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze == null) return; + if (!freeze.canDmg()) e.setCancelled(true); + freeze.handleDamage(p); + } + + @EventHandler + public void onDamageByBlock(EntityDamageByBlockEvent e) { + if (!(e.getEntity() instanceof Player p)) return; + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze == null) return; + if (!freeze.canDmg()) e.setCancelled(true); + freeze.handleDamage(p); + } + + @EventHandler + public void onQuit(PlayerQuitEvent e) { + OfflinePlayer p = e.getPlayer(); + FreezeSession freeze = context.getFreezeManager().getSession(p.getUniqueId()); + if (freeze != null) freeze.handleQuit(p); + } +} diff --git a/src/main/java/me/trouper/alias/server/systems/freeze/FreezeManager.java b/src/main/java/me/trouper/alias/server/systems/freeze/FreezeManager.java new file mode 100644 index 0000000..7f30424 --- /dev/null +++ b/src/main/java/me/trouper/alias/server/systems/freeze/FreezeManager.java @@ -0,0 +1,32 @@ +package me.trouper.alias.server.systems.freeze; + +import me.trouper.alias.AliasContext; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class FreezeManager { + private final AliasContext context; + private final Map sessions = new ConcurrentHashMap<>(); + + public FreezeManager(AliasContext context) { + this.context = context; + } + + void register(FreezeSession session) { + sessions.put(session.uuid(), session); + } + + void unregister(UUID uuid) { + sessions.remove(uuid); + } + + public FreezeSession getSession(UUID uuid) { + return sessions.get(uuid); + } + + public boolean isFrozen(UUID uuid) { + return sessions.containsKey(uuid); + } +} diff --git a/src/main/java/me/trouper/alias/server/systems/freeze/FreezeSession.java b/src/main/java/me/trouper/alias/server/systems/freeze/FreezeSession.java new file mode 100644 index 0000000..2454d3b --- /dev/null +++ b/src/main/java/me/trouper/alias/server/systems/freeze/FreezeSession.java @@ -0,0 +1,151 @@ +package me.trouper.alias.server.systems.freeze; + +import me.trouper.alias.AliasContext; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; + +public class FreezeSession { + private final AliasContext context; + private final UUID targetUuid; + private final Location backLocation; + private final boolean allowMovement; + private final boolean allowDamage; + private final Set allowedCommands; + private final boolean allowInteract; + + private final Consumer onMove; + private final Consumer onInteract; + private final Consumer onDamage; + private final Consumer onCommand; + private final Consumer onQuit; + private final Runnable onStart; + private final Runnable onThaw; + + private final Duration duration; + private BukkitTask thawTask; + + private FreezeSession(AliasContext context, Builder b) { + this.context = context; + this.targetUuid = b.targetUuid; + this.backLocation = b.backLocation; + this.allowMovement = b.allowMovement; + this.allowDamage = b.allowDamage; + this.allowedCommands = b.allowedCommands; + this.allowInteract = b.allowInteract; + + this.onMove = b.onMove; + this.onInteract = b.onInteract; + this.onDamage = b.onDamage; + this.onCommand = b.onCommand; + this.onQuit = b.onQuit; + this.onStart = b.onStart; + this.onThaw = b.onThaw; + + this.duration = b.duration; + } + + public void start() { + context.getFreezeManager().register(this); + if (onStart != null) onStart.run(); + + if (!duration.isZero()) { + thawTask = context.getPlugin().getServer().getScheduler().runTaskLater(context.getPlugin(), this::thaw, duration.toMillis() / 50); + } + } + + public void thaw() { + context.getFreezeManager().unregister(targetUuid); + if (thawTask != null) thawTask.cancel(); + Player p = Bukkit.getPlayer(targetUuid); + if (p != null) { + p.teleport(backLocation); + } + if (onThaw != null) onThaw.run(); + } + + public UUID uuid() { return targetUuid; } + public boolean canMove() { return allowMovement; } + public boolean canDmg() { return allowDamage; } + public Set getAllowedCommands() { return allowedCommands; } + public boolean canInt() { return allowInteract; } + + public void handleMove(Player p) { + if (onMove != null) onMove.accept(p); + } + + public void handleInteract(Player p) { + if (onInteract != null) onInteract.accept(p); + } + + public void handleDamage(Player p) { + if (onDamage != null) onDamage.accept(p); + } + + public void handleCommand(Player p) { + if (onCommand != null) onCommand.accept(p); + } + + public void handleQuit(OfflinePlayer p) { + if (onQuit != null) onQuit.accept(p); + } + + public static class Builder { + private final AliasContext context; + + private final UUID targetUuid; + private final Location backLocation; + + private boolean allowMovement = false; + private boolean allowDamage = false; + private final Set allowedCommands = new HashSet<>(); + private boolean allowInteract = false; + + private Consumer onMove = null; + private Consumer onInteract = null; + private Consumer onDamage = null; + private Consumer onCommand = null; + private Consumer onQuit = null; + private Runnable onStart = null; + private Runnable onThaw = null; + + private Duration duration = Duration.ZERO; + + public Builder(AliasContext context, UUID target, Location backLocation) { + this.context = context; + this.targetUuid = target; + this.backLocation = backLocation; + } + + public Builder allowMovement() { this.allowMovement = true; return this; } + public Builder allowDamage() { this.allowDamage = true; return this; } + public Builder allowCommands(Set allowedCommands) { this.allowedCommands.addAll(allowedCommands); return this; } + public Builder allowInteract() { this.allowInteract = true; return this; } + + public Builder onMove(Consumer c) { this.onMove = c; return this; } + public Builder onInteract(Consumer c) { this.onInteract = c; return this; } + public Builder onDamage(Consumer c) { this.onDamage = c; return this; } + public Builder onCommand(Consumer c) { this.onCommand = c; return this; } + public Builder onQuit(Consumer c){ this.onQuit = c; return this; } + public Builder onStart(Runnable r) { this.onStart = r; return this; } + public Builder onThaw(Runnable r) { this.onThaw = r; return this; } + + public Builder duration(Duration d) { + this.duration = d != null ? d : Duration.ZERO; + return this; + } + + public FreezeSession build() { + return new FreezeSession(context, this); + } + } +}