From d7883d29ff53af51de9f0a27723c2459c08bbb09 Mon Sep 17 00:00:00 2001 From: ThatCreeper Date: Wed, 30 Dec 2020 18:29:07 -0600 Subject: [PATCH] Rewrite Potions --- .../net/minestom/server/MinecraftServer.java | 13 -- .../net/minestom/server/entity/Entity.java | 67 +++++++ .../net/minestom/server/potion/Potion.java | 13 +- .../server/potion/PotionEffectManager.java | 185 ------------------ .../minestom/server/potion/PotionTask.java | 25 --- .../server/potion/PotionTimeTask.java | 27 --- .../server/potion/PotionTimeTaskHolder.java | 12 -- .../java/demo/commands/PotionCommand.java | 11 +- 8 files changed, 79 insertions(+), 274 deletions(-) delete mode 100644 src/main/java/net/minestom/server/potion/PotionEffectManager.java delete mode 100644 src/main/java/net/minestom/server/potion/PotionTask.java delete mode 100644 src/main/java/net/minestom/server/potion/PotionTimeTask.java delete mode 100644 src/main/java/net/minestom/server/potion/PotionTimeTaskHolder.java diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index 41d446fbd..1cf608505 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -33,7 +33,6 @@ import net.minestom.server.network.packet.server.play.UpdateViewDistancePacket; import net.minestom.server.particle.Particle; import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.potion.PotionEffect; -import net.minestom.server.potion.PotionEffectManager; import net.minestom.server.potion.PotionType; import net.minestom.server.recipe.RecipeManager; import net.minestom.server.registry.ResourceGatherer; @@ -117,7 +116,6 @@ public final class MinecraftServer { private static DimensionTypeManager dimensionTypeManager; private static BiomeManager biomeManager; private static AdvancementManager advancementManager; - private static PotionEffectManager potionEffectManager; private static ExtensionManager extensionManager; @@ -179,7 +177,6 @@ public final class MinecraftServer { dimensionTypeManager = new DimensionTypeManager(); biomeManager = new BiomeManager(); advancementManager = new AdvancementManager(); - potionEffectManager = new PotionEffectManager(); updateManager = new UpdateManager(); @@ -624,16 +621,6 @@ public final class MinecraftServer { return advancementManager; } - /** - * Gets the manager handling potions. - * - * @return the potion effect manager - */ - public static PotionEffectManager getPotionEffectManager() { - checkInitStatus(potionEffectManager); - return potionEffectManager; - } - /** * Get the manager handling {@link Extension}. * diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index ecaccd763..4a05ca143 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -22,6 +22,8 @@ import net.minestom.server.instance.block.CustomBlock; import net.minestom.server.network.packet.server.play.*; import net.minestom.server.permission.Permission; import net.minestom.server.permission.PermissionHandler; +import net.minestom.server.potion.Potion; +import net.minestom.server.potion.PotionEffect; import net.minestom.server.thread.ThreadProvider; import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.Position; @@ -130,6 +132,9 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P protected boolean noGravity; protected Pose pose = Pose.STANDING; + private ArrayList effects = new ArrayList<>(); + private ArrayList effectTimes = new ArrayList<>(); + // list of scheduled tasks to be executed during the next entity tick protected final Queue> nextTick = Queues.newConcurrentLinkedQueue(); @@ -396,6 +401,29 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P return; } + // remove expired effects + { + if (effects.size() > 0) { + boolean foundToRemove = true; + while (foundToRemove) { + foundToRemove = false; + int i = 0; + while (i < effects.size()) { + if (effects.get(i).duration * 50 + + effectTimes.get(i) <= System.nanoTime() / 1000000) { + foundToRemove = true; + break; + } + i++; + } + if (foundToRemove) { + effects.remove(i); + effectTimes.remove(i); + } + } + } + } + // scheduled tasks if (!nextTick.isEmpty()) { Consumer callback; @@ -1442,6 +1470,45 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer, P DYING } + public List getActiveEffects() { + return effects; + } + + /** + * Removes effect from entity, if it has it. + * + * @param effect The effect to remove + */ + public void removeEffect(@NotNull PotionEffect effect) { + if (effects.size() == 0) return; + int i = 0; + boolean found = false; + while (i < effects.size()) { + if (effects.get(i).effect == effect) { + found = true; + break; + } + i++; + } + if (found) { + effects.get(i).sendRemovePacket(this); + effects.remove(i); + effectTimes.remove(i); + } + } + + /** + * Adds an effect to an entity + * + * @param potion The potion to add + */ + public void addEffect(@NotNull Potion potion) { + removeEffect(potion.effect); + effects.add(potion); + effectTimes.add(System.nanoTime() / 1000000); + potion.sendAddPacket(this); + } + protected boolean shouldRemove() { return shouldRemove; } diff --git a/src/main/java/net/minestom/server/potion/Potion.java b/src/main/java/net/minestom/server/potion/Potion.java index e86cc10ab..65e3d0d30 100644 --- a/src/main/java/net/minestom/server/potion/Potion.java +++ b/src/main/java/net/minestom/server/potion/Potion.java @@ -1,5 +1,6 @@ package net.minestom.server.potion; +import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.play.EntityEffectPacket; import net.minestom.server.network.packet.server.play.RemoveEntityEffectPacket; @@ -42,17 +43,17 @@ public class Potion { return computed; } - public void sendAddPacket(@NotNull Player player) { + public void sendAddPacket(@NotNull Entity entity) { EntityEffectPacket eep = new EntityEffectPacket(); - eep.entityId = player.getEntityId(); + eep.entityId = entity.getEntityId(); eep.potion = this; - player.sendPacketToViewersAndSelf(eep); + entity.sendPacketToViewersAndSelf(eep); } - public void sendRemovePacket(@NotNull Player player) { + public void sendRemovePacket(@NotNull Entity entity) { RemoveEntityEffectPacket reep = new RemoveEntityEffectPacket(); - reep.entityId = player.getEntityId(); + reep.entityId = entity.getEntityId(); reep.effect = effect; - player.sendPacketToViewersAndSelf(reep); + entity.sendPacketToViewersAndSelf(reep); } } diff --git a/src/main/java/net/minestom/server/potion/PotionEffectManager.java b/src/main/java/net/minestom/server/potion/PotionEffectManager.java deleted file mode 100644 index bb4d47533..000000000 --- a/src/main/java/net/minestom/server/potion/PotionEffectManager.java +++ /dev/null @@ -1,185 +0,0 @@ -package net.minestom.server.potion; - -import net.minestom.server.MinecraftServer; -import net.minestom.server.entity.Player; -import net.minestom.server.event.GlobalEventHandler; -import net.minestom.server.event.player.PlayerDisconnectEvent; -import net.minestom.server.event.player.PlayerSpawnEvent; -import net.minestom.server.timer.SchedulerManager; -import net.minestom.server.utils.time.TimeUnit; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; - -/** - * Manages active potion effects on players - */ -public class PotionEffectManager { - - private HashMap> playerEffects; - private boolean persistEffects = false; - - /** - * Creates a new PotionEffectManager - */ - public PotionEffectManager() { - playerEffects = new HashMap<>(); - - addEventHandlers(); - } - - /** - * Returns the active effects of a player. - * - * @param player The player to get the effects of. - * @return Null if no active effects, otherwise the active effects. - */ - public @Nullable List getActiveEffects(@Nullable Player player) { - if (player == null) return null; - return playerEffects.get(player.getUuid()); - } - - /** - * Returns a {@link PotionTask} on a player of a type {@link PotionEffect} - * - * @param player The player with the effect. - * @param potionEffect The type of potion to look for. - * @return Null if the player does not have the effect, otherwise the effect. - */ - public @Nullable PotionTask getPotionTask(@Nullable Player player, @Nullable PotionEffect potionEffect) { - if (player == null) return null; - if (potionEffect == null) return null; - - ArrayList potionTasks = playerEffects.get(player.getUuid()); - if (potionTasks == null) return null; - - for (PotionTask potionTask : potionTasks) { - if (potionTask.getPotion().effect == potionEffect) { - return potionTask; - } - } - return null; - } - - /** - * Returns if the player has an effect of specified type. - * - * @param player The player to check. - * @param potionEffect The type of potion to check for. - * @return If the player has a potion effect with the specified type. - */ - public boolean hasPotionEffect(@Nullable Player player, @Nullable PotionEffect potionEffect) { - return getPotionTask(player, potionEffect) != null; - } - - /** - * Removes the {@link PotionTask}. - * - * @param task The {@link PotionTask} to remove. - */ - public void removeEffect(@NotNull PotionTask task) { - task.getValue().task.cancel(); - for (UUID uuid : playerEffects.keySet()) { - if (playerEffects.get(uuid).contains(task)) { - playerEffects.get(uuid).remove(task); - Player player = MinecraftServer.getConnectionManager().getPlayer(uuid); - if (player != null && player.isOnline()) { - task.getPotion().sendRemovePacket(player); - } - return; - } - } - } - - /** - * If the player has a potion of type effect, remove it. - * - * @param player The player to remove from. - * @param effect The {@link PotionEffect} to remove. - */ - public void removeEffect(@NotNull Player player, @NotNull PotionEffect effect) { - PotionTask task = null; - ArrayList potionTasks = playerEffects.get(player.getUuid()); - if (potionTasks == null) return; - for (PotionTask potionTask : potionTasks) { - if (potionTask.getPotion().effect == effect) { - task = potionTask; - break; - } - } - if (task == null) return; - removeEffect(task); - } - - /** - * Clears a player's effects. - * - * @param player The player to clear. - */ - public void clearEffects(@Nullable Player player) { - if (player == null) return; - - ArrayList potionTasks = playerEffects.get(player.getUuid()); - if (potionTasks == null) return; - for (PotionTask potionTask : potionTasks) { - potionTask.getValue().task.cancel(); - if (player.isOnline()) { - potionTask.getPotion().sendRemovePacket(player); - } - } - potionTasks.clear(); - playerEffects.remove(player.getUuid()); - } - - /** - * Gives a player a potion effect. - * - * @param player The player to give to. - * @param potion The {@link Potion} to give. - */ - public void addPotion(@Nullable Player player, @Nullable Potion potion) { - if (player == null) return; - if (potion == null) return; - removeEffect(player, potion.effect); - ArrayList potionTasks = playerEffects.computeIfAbsent(player.getUuid(), k -> new ArrayList<>()); - SchedulerManager schedulerManager = MinecraftServer.getSchedulerManager(); - PotionTimeTask ptt = new PotionTimeTask(MinecraftServer.getSchedulerManager(), - TimeUnit.TICK.toMilliseconds(potion.duration)); - potionTasks.add(new PotionTask(potion, ptt)); - potion.sendAddPacket(player); - } - -// NOT IMPLEMENTED -// public void setPersistEffects(Boolean persistEffects) { -// this.persistEffects = persistEffects; -// } -// -// public boolean getPersistEffects() { -// return persistEffects; -// } - - /** - * Adds a {@link PlayerSpawnEvent} and {@link PlayerDisconnectEvent} handler to pause and resume potion effects. - */ - private void addEventHandlers() { - GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler(); - globalEventHandler.addEventCallback(PlayerSpawnEvent.class, playerSpawnEvent -> { - if (persistEffects) { - // TODO: Implement persist - } - }); - - globalEventHandler.addEventCallback(PlayerDisconnectEvent.class, playerDisconnectEvent -> { - if (persistEffects) { - // TODO: Implement persist - } else { - clearEffects(playerDisconnectEvent.getPlayer()); - } - }); - } - -} diff --git a/src/main/java/net/minestom/server/potion/PotionTask.java b/src/main/java/net/minestom/server/potion/PotionTask.java deleted file mode 100644 index 466fd3a9a..000000000 --- a/src/main/java/net/minestom/server/potion/PotionTask.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.minestom.server.potion; - -import javafx.util.Pair; -import net.minestom.server.MinecraftServer; - -public class PotionTask extends Pair { - /** - * Creates a new PotionTask - * - * @param potion The {@link Potion} - * @param task The {@link PotionTimeTask} - */ - public PotionTask(Potion potion, PotionTimeTask task) { - super(potion, task); - task.potionTask = this; - } - - public Potion getPotion() { - return this.getKey(); - } - - public void removeEffect() { - MinecraftServer.getPotionEffectManager().removeEffect(this); - } -} diff --git a/src/main/java/net/minestom/server/potion/PotionTimeTask.java b/src/main/java/net/minestom/server/potion/PotionTimeTask.java deleted file mode 100644 index fcabf442c..000000000 --- a/src/main/java/net/minestom/server/potion/PotionTimeTask.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.minestom.server.potion; - -import net.minestom.server.timer.SchedulerManager; -import net.minestom.server.timer.Task; -import net.minestom.server.utils.time.TimeUnit; -import org.jetbrains.annotations.NotNull; - -public class PotionTimeTask { - - public Long remainingTime; - public Task task; - public PotionTask potionTask; - - /** - * Creates a task. - * - * @param schedulerManager The manager for the task - * @param delay The time to delay - */ - public PotionTimeTask(@NotNull SchedulerManager schedulerManager, long delay) { - Runnable runTask = () -> { - potionTask.removeEffect(); - }; - task = schedulerManager.buildTask(runTask).delay(delay, TimeUnit.MILLISECOND).schedule(); - this.remainingTime = delay; - } -} diff --git a/src/main/java/net/minestom/server/potion/PotionTimeTaskHolder.java b/src/main/java/net/minestom/server/potion/PotionTimeTaskHolder.java deleted file mode 100644 index b833a8c9c..000000000 --- a/src/main/java/net/minestom/server/potion/PotionTimeTaskHolder.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.minestom.server.potion; - -public class PotionTimeTaskHolder { - /** - * Only updates when task is paused - */ - public Long timeRemaining; - - public PotionTimeTaskHolder() { - // TODO: Implement persist - } -} diff --git a/src/test/java/demo/commands/PotionCommand.java b/src/test/java/demo/commands/PotionCommand.java index 64451e1a5..76f5f0385 100644 --- a/src/test/java/demo/commands/PotionCommand.java +++ b/src/test/java/demo/commands/PotionCommand.java @@ -9,9 +9,6 @@ import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.entity.Player; import net.minestom.server.potion.Potion; import net.minestom.server.potion.PotionEffect; -import net.minestom.server.potion.PotionTask; - -import java.util.List; public class PotionCommand extends Command { @@ -43,10 +40,12 @@ public class PotionCommand extends Command { final PotionEffect potion = args.getPotionEffect("potion"); final int duration = args.getInteger("duration"); - MinecraftServer.getPotionEffectManager().addPotion(player, new Potion( + player.sendMessage(player.getActiveEffects().toString()); + + player.addEffect(new Potion( potion, - (byte) 1, - duration * 20 + (byte) 0, + duration )); }