mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-29 04:28:21 +01:00
Add PotionEffectManager
This commit is contained in:
parent
d4110632a4
commit
50b44e46e0
@ -33,6 +33,7 @@ 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;
|
||||
@ -116,6 +117,7 @@ public final class MinecraftServer {
|
||||
private static DimensionTypeManager dimensionTypeManager;
|
||||
private static BiomeManager biomeManager;
|
||||
private static AdvancementManager advancementManager;
|
||||
private static PotionEffectManager potionEffectManager;
|
||||
|
||||
private static ExtensionManager extensionManager;
|
||||
|
||||
@ -177,6 +179,7 @@ public final class MinecraftServer {
|
||||
dimensionTypeManager = new DimensionTypeManager();
|
||||
biomeManager = new BiomeManager();
|
||||
advancementManager = new AdvancementManager();
|
||||
potionEffectManager = new PotionEffectManager();
|
||||
|
||||
updateManager = new UpdateManager();
|
||||
|
||||
@ -621,6 +624,16 @@ 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}.
|
||||
*
|
||||
|
@ -14,6 +14,7 @@ import net.minestom.server.network.packet.client.play.ClientPlayerDiggingPacket;
|
||||
import net.minestom.server.network.packet.server.play.AcknowledgePlayerDiggingPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityEffectPacket;
|
||||
import net.minestom.server.network.packet.server.play.RemoveEntityEffectPacket;
|
||||
import net.minestom.server.potion.Potion;
|
||||
import net.minestom.server.potion.PotionEffect;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
|
||||
@ -189,10 +190,14 @@ public class PlayerDiggingListener {
|
||||
|
||||
EntityEffectPacket entityEffectPacket = new EntityEffectPacket();
|
||||
entityEffectPacket.entityId = player.getEntityId();
|
||||
entityEffectPacket.effect = PotionEffect.MINING_FATIGUE;
|
||||
entityEffectPacket.amplifier = -1;
|
||||
entityEffectPacket.duration = 0;
|
||||
entityEffectPacket.flags = 0;
|
||||
entityEffectPacket.potion = new Potion(
|
||||
PotionEffect.MINING_FATIGUE,
|
||||
(byte) -1,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
player.getPlayerConnection().sendPacket(entityEffectPacket);
|
||||
}
|
||||
|
||||
|
@ -2,25 +2,22 @@ package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.potion.PotionEffect;
|
||||
import net.minestom.server.potion.Potion;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EntityEffectPacket implements ServerPacket {
|
||||
|
||||
public int entityId;
|
||||
public PotionEffect effect;
|
||||
public byte amplifier;
|
||||
public int duration;
|
||||
public byte flags;
|
||||
public Potion potion;
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeVarInt(entityId);
|
||||
writer.writeByte((byte) effect.getId());
|
||||
writer.writeByte(amplifier);
|
||||
writer.writeVarInt(duration);
|
||||
writer.writeByte(flags);
|
||||
writer.writeByte((byte) potion.effect.getId());
|
||||
writer.writeByte(potion.amplifier);
|
||||
writer.writeVarInt(potion.duration);
|
||||
writer.writeByte(potion.getFlags());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
58
src/main/java/net/minestom/server/potion/Potion.java
Normal file
58
src/main/java/net/minestom/server/potion/Potion.java
Normal file
@ -0,0 +1,58 @@
|
||||
package net.minestom.server.potion;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.EntityEffectPacket;
|
||||
import net.minestom.server.network.packet.server.play.RemoveEntityEffectPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Potion {
|
||||
public PotionEffect effect;
|
||||
public byte amplifier;
|
||||
public int duration;
|
||||
public boolean ambient;
|
||||
public boolean particles;
|
||||
public boolean icon;
|
||||
|
||||
public Potion(PotionEffect effect, byte amplifier, int duration) {
|
||||
this(effect, amplifier, duration, true, true, false);
|
||||
}
|
||||
|
||||
public Potion(PotionEffect effect, byte amplifier, int duration, boolean particles) {
|
||||
this(effect, amplifier, duration, particles, true, false);
|
||||
}
|
||||
|
||||
public Potion(PotionEffect effect, byte amplifier, int duration, boolean particles, boolean icon) {
|
||||
this(effect, amplifier, duration, particles, icon, false);
|
||||
}
|
||||
|
||||
public Potion(PotionEffect effect, byte amplifier, int duration, boolean particles, boolean icon, boolean ambient) {
|
||||
this.effect = effect;
|
||||
this.amplifier = amplifier;
|
||||
this.duration = duration;
|
||||
this.particles = particles;
|
||||
this.icon = icon;
|
||||
this.ambient = ambient;
|
||||
}
|
||||
|
||||
public byte getFlags() {
|
||||
byte computed = 0x00;
|
||||
if (ambient) computed = (byte)(computed | 0x01);
|
||||
if (particles) computed = (byte)(computed | 0x02);
|
||||
if (icon) computed = (byte)(computed | 0x04);
|
||||
return computed;
|
||||
}
|
||||
|
||||
public void sendAddPacket(@NotNull Player player) {
|
||||
EntityEffectPacket eep = new EntityEffectPacket();
|
||||
eep.entityId = player.getEntityId();
|
||||
eep.potion = this;
|
||||
player.sendPacketToViewersAndSelf(eep);
|
||||
}
|
||||
|
||||
public void sendRemovePacket(@NotNull Player player) {
|
||||
RemoveEntityEffectPacket reep = new RemoveEntityEffectPacket();
|
||||
reep.entityId = player.getEntityId();
|
||||
reep.effect = effect;
|
||||
player.sendPacketToViewersAndSelf(reep);
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
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<UUID, ArrayList<PotionTask>> 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<PotionTask> 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<PotionTask> 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<PotionTask> 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<PotionTask> 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<PotionTask> 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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
25
src/main/java/net/minestom/server/potion/PotionTask.java
Normal file
25
src/main/java/net/minestom/server/potion/PotionTask.java
Normal file
@ -0,0 +1,25 @@
|
||||
package net.minestom.server.potion;
|
||||
|
||||
import javafx.util.Pair;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
|
||||
public class PotionTask extends Pair<Potion, PotionTimeTask> {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
27
src/main/java/net/minestom/server/potion/PotionTimeTask.java
Normal file
27
src/main/java/net/minestom/server/potion/PotionTimeTask.java
Normal file
@ -0,0 +1,27 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package net.minestom.server.potion;
|
||||
|
||||
public class PotionTimeTaskHolder {
|
||||
/**
|
||||
* Only updates when task is paused
|
||||
*/
|
||||
public Long timeRemaining;
|
||||
|
||||
public PotionTimeTaskHolder() {
|
||||
// TODO: Implement persist
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ public class Main {
|
||||
commandManager.register(new ShutdownCommand());
|
||||
commandManager.register(new TeleportCommand());
|
||||
commandManager.register(new PlayersCommand());
|
||||
commandManager.register(new PotionCommand());
|
||||
|
||||
commandManager.setUnknownCommandCallback((sender, command) -> sender.sendMessage("unknown command"));
|
||||
|
||||
|
@ -29,6 +29,7 @@ import net.minestom.server.item.Material;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.server.play.PlayerListHeaderAndFooterPacket;
|
||||
import net.minestom.server.ping.ResponseDataConsumer;
|
||||
import net.minestom.server.timer.TaskBuilder;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Vector;
|
||||
|
53
src/test/java/demo/commands/PotionCommand.java
Normal file
53
src/test/java/demo/commands/PotionCommand.java
Normal file
@ -0,0 +1,53 @@
|
||||
package demo.commands;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
import net.minestom.server.command.builder.Arguments;
|
||||
import net.minestom.server.command.builder.Command;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
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 {
|
||||
|
||||
public PotionCommand() {
|
||||
super("potion");
|
||||
|
||||
setCondition(this::condition);
|
||||
|
||||
setDefaultExecutor(((sender, args) -> {
|
||||
sender.sendMessage("Usage: /potion [type] [duration (seconds)]");
|
||||
}));
|
||||
|
||||
Argument potionArg = ArgumentType.Potion("potion");
|
||||
Argument durationArg = ArgumentType.Integer("duration");
|
||||
|
||||
addSyntax(this::onPotionCommand, potionArg, durationArg);
|
||||
}
|
||||
|
||||
private boolean condition(CommandSender sender, String commandString) {
|
||||
if (!sender.isPlayer()) {
|
||||
sender.sendMessage("The command is only available for players");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onPotionCommand(CommandSender sender, Arguments args) {
|
||||
final Player player = (Player) sender;
|
||||
final PotionEffect potion = args.getPotionEffect("potion");
|
||||
final int duration = args.getInteger("duration");
|
||||
|
||||
MinecraftServer.getPotionEffectManager().addPotion(player, new Potion(
|
||||
potion,
|
||||
(byte) 1,
|
||||
duration * 20
|
||||
));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user