diff --git a/API/src/main/java/fr/maxlego08/essentials/api/Configuration.java b/API/src/main/java/fr/maxlego08/essentials/api/Configuration.java index d706d81d..edbdd4e3 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/Configuration.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/Configuration.java @@ -3,6 +3,7 @@ import fr.maxlego08.essentials.api.chat.ChatCooldown; import fr.maxlego08.essentials.api.commands.CommandCooldown; import fr.maxlego08.essentials.api.commands.CommandRestriction; +import fr.maxlego08.essentials.api.config.models.NearDirectionReplacements; import fr.maxlego08.essentials.api.configuration.ReplacePlaceholder; import fr.maxlego08.essentials.api.server.RedisConfiguration; import fr.maxlego08.essentials.api.server.ServerType; @@ -151,6 +152,15 @@ public interface Configuration extends ConfigurationFile { */ List getNearPermissions(); + /** + * Returns the set of directional replacements (arrows or labels) used to display + * the relative position of nearby players. + * + * @return a {@link NearDirectionReplacements} instance containing direction symbols + * @since 1.0.3.2 + */ + NearDirectionReplacements getNearDirectionReplacements(); + /** * Retrieves the near distance allowed for a specific permissible entity. * @@ -159,6 +169,28 @@ public interface Configuration extends ConfigurationFile { */ double getNearDistance(Permissible permissible); + /** + * Returns the world time value used by the /day command. + * + * @return the configured day time value + */ + long getDayTime(); + + /** + * Returns the world time value used by the /night command. + * + * @return the configured night time value + */ + long getNightTime(); + + /** + * Indicates whether world time changes should be animated + * (e.g. /day, /night commands). + * + * @return {@code true} if smooth world time changes are enabled + */ + boolean isTimeSmoothChangeEnabled(); + /** * Checks if command logging is enabled. * diff --git a/API/src/main/java/fr/maxlego08/essentials/api/commands/Permission.java b/API/src/main/java/fr/maxlego08/essentials/api/commands/Permission.java index 7fef5e64..ea5b34fc 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/commands/Permission.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/commands/Permission.java @@ -29,6 +29,11 @@ public enum Permission { ESSENTIALS_VANISH_OTHER, ESSENTIALS_VANISH_SEE, ESSENTIALS_HEAL, + ESSENTIALS_HEAL_ALL("Allows to heal another player"), + ESSENTIALS_HEAL_OTHER("Allows to heal all players on the server"), + ESSENTIALS_LIGHTING, + ESSENTIALS_LIGHTING_ALL("Allows to strike another player with lightning"), + ESSENTIALS_LIGHTING_OTHER("Allows to strike all players on the server with lightning"), ESSENTIALS_SPEED, ESSENTIALS_WALK_SPEED, ESSENTIALS_FLY_SPEED, @@ -44,10 +49,11 @@ public enum Permission { ESSENTIALS_TP_WORLD_OTHER("Allows to teleport another player into a world"), ESSENTIALS_TRASH, ESSENTIALS_FEED, + ESSENTIALS_FEED_OTHER("Allows to feed another player"), + ESSENTIALS_FEED_ALL("Allows to feed all players on the server"), ESSENTIALS_INVSEE, ESSENTIALS_INVSEE_OFFLINE("Allows to listen to the inventory of an offline player"), - ESSENTIALS_FEED_OTHER("Allows to feed another player"), - ESSENTIALS_HEAL_OTHER("Allows to heal another player"), + ESSENTIALS_EXT_OTHER("Allows to feed another player"), ESSENTIALS_CRAFT, ESSENTIALS_ENCHANTING, ESSENTIALS_INVSEE_INTERACT("Allows to interact with a player’s inventory"), diff --git a/API/src/main/java/fr/maxlego08/essentials/api/config/models/NearDirectionReplacements.java b/API/src/main/java/fr/maxlego08/essentials/api/config/models/NearDirectionReplacements.java new file mode 100644 index 00000000..33452aa1 --- /dev/null +++ b/API/src/main/java/fr/maxlego08/essentials/api/config/models/NearDirectionReplacements.java @@ -0,0 +1,23 @@ +package fr.maxlego08.essentials.api.config.models; + +public record NearDirectionReplacements( + String forwardReplacement, + String forwardRightReplacement, + String rightReplacement, + String backRightReplacement, + String backReplacement, + String backLeftReplacement, + String leftReplacement, + String forwardLeftReplacement +) { + public static final NearDirectionReplacements DEFAULT = new NearDirectionReplacements( + "↑", + "↗", + "→", + "↘", + "↓", + "↙", + "←", + "↖" + ); +} diff --git a/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java b/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java index f28e1408..01c5b122 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java @@ -51,6 +51,8 @@ public enum Message { COMMAND_ESSENTIALS("zEssentials, version %version%"), COMMAND_GAMEMODE("&fSet game mode&e %gamemode% &ffor &b%player%&f."), COMMAND_GAMEMODE_INVALID("You need to specify a valid player."), + COMMAND_TIME_ERROR("You need to specify a world."), + COMMAND_TIME_ALREADY_CHANGING("Time is already changing in &f%world%."), COMMAND_DAY("&fYou have just brought &edaylight&f into the world %world%&f."), COMMAND_NIGHT("&fYou have just brought &enightfall&f into the world %world%&f."), COMMAND_SUN("&fYou have just brought the &esun&f into the world %world%&f."), @@ -85,9 +87,19 @@ public enum Message { COMMAND_NIGHT_VISION_DISABLE("&7Night vision disable &7for &f%player%."), COMMAND_PHANTOMS_ENABLE("&7Phantom spawning enable &7for &f%player%."), COMMAND_PHANTOMS_DISABLE("&7Phantom spawning disable &7for &f%player%."), + COMMAND_EXT_SENDER("&7You just extinguished the player &f%player%&7."), + COMMAND_EXT_RECEIVER("You are no longer burning."), + COMMAND_EXT_ERROR("You cannot extinguish someone who is dead!"), + COMMAND_HEAL_ALL("&7You just healed all players on the server."), COMMAND_HEAL_SENDER("&7You just healed the player &f%player%&7."), COMMAND_HEAL_RECEIVER("You have been healed."), COMMAND_HEAL_ERROR("You cannot heal someone who is dead !"), + COMMAND_LIGHTING_ALL("&7You just struck all players with lightning."), + COMMAND_LIGHTING("&7You just summoned lightning at the targeted location."), + COMMAND_LIGHTING_SENDER("&7You just summoned lightning at the location of &f%player%&7."), + COMMAND_LIGHTING_RECEIVER("&cYou have been struck by lightning."), + COMMAND_LIGHTING_ERROR("You cannot strike a dead player with lightning!"), + COMMAND_FEED_ALL("&7You just feed all players on the server."), COMMAND_FEED_SENDER("&7You just feed the player &f%player%&7."), COMMAND_FEED_RECEIVER("You have been feed."), COMMAND_FEED_ERROR("You cannot feed someone who is dead !"), @@ -183,6 +195,7 @@ public enum Message { DESCRIPTION_FLY_REMOVE("Removed the fly time"), DESCRIPTION_FLY_SET("Set the fly time"), DESCRIPTION_HEAL("Heal a player"), + DESCRIPTION_LIGHTING("Strike a player with lightning"), DESCRIPTION_AFK("Toggle your AFK status"), DESCRIPTION_SUN("Set the sun in your world"), DESCRIPTION_ENDERCHEST("Open your enderchest"), @@ -680,11 +693,10 @@ public enum Message { COMMAND_REPAIR_SUCCESS("You just fixed the item in your hand."), COMMAND_REPAIR_ALL_ERROR("You have no items to repair."), COMMAND_REPAIR_ALL_SUCCESS("You have just repaired all the items in your inventory"), - COMMAND_EXT("&fBy the will of Maxlego08, you no longer burn."), COMMAND_NEAR_EMPTY("No player near to you."), COMMAND_NEAR_PLAYER("&fPlayers near to you&7:%players%"), - COMMAND_NEAR_INFO(" &7%player% &8(&e%distance%m&8)"), + COMMAND_NEAR_INFO("&6%direction% &7%player% &8(&e%distance%m&8)"), COMMAND_PLAY_TIME( "&7You played&8: %playtime%", "&7Current session&8: %playtime_session%" diff --git a/API/src/main/java/fr/maxlego08/essentials/api/server/EssentialsServer.java b/API/src/main/java/fr/maxlego08/essentials/api/server/EssentialsServer.java index fe385aee..d6a82ee1 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/server/EssentialsServer.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/server/EssentialsServer.java @@ -7,6 +7,7 @@ import fr.maxlego08.essentials.api.user.User; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.UUID; @@ -37,6 +38,18 @@ public interface EssentialsServer { */ List getPlayersNames(); + /** + * Gets the list of names of all online players + * that are visible to the given command sender. + * + *

Player visibility may depend on permissions, + * vanish state, or other server-side rules.

+ * + * @param sender the command sender for whom player visibility is evaluated + * @return a list of visible online player names + */ + List getVisiblePlayerNames(@NotNull CommandSender sender); + /** * Sends a message to a player with the given UUID. * diff --git a/Hooks/Redis/src/main/java/fr/maxlego08/essentials/hooks/redis/RedisServer.java b/Hooks/Redis/src/main/java/fr/maxlego08/essentials/hooks/redis/RedisServer.java index 8149db9e..a33ef999 100644 --- a/Hooks/Redis/src/main/java/fr/maxlego08/essentials/hooks/redis/RedisServer.java +++ b/Hooks/Redis/src/main/java/fr/maxlego08/essentials/hooks/redis/RedisServer.java @@ -36,6 +36,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.jetbrains.annotations.NotNull; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; @@ -115,6 +116,11 @@ public List getPlayersNames() { return new ArrayList<>(this.playerCache.getPlayers()); } + @Override + public List getVisiblePlayerNames(@NotNull CommandSender sender) { + return getPlayersNames(); // ToDO: think about the way to implement visible players filtering + } + @Override public List getOfflinePlayersNames() { return this.plugin.getConfiguration().isEnableOfflinePlayersName() ? Arrays.stream(Bukkit.getOfflinePlayers()).map(OfflinePlayer::getName).toList() : getPlayersNames(); diff --git a/src/main/java/fr/maxlego08/essentials/MainConfiguration.java b/src/main/java/fr/maxlego08/essentials/MainConfiguration.java index 6dc6ef9e..0876e279 100644 --- a/src/main/java/fr/maxlego08/essentials/MainConfiguration.java +++ b/src/main/java/fr/maxlego08/essentials/MainConfiguration.java @@ -4,6 +4,7 @@ import fr.maxlego08.essentials.api.chat.ChatCooldown; import fr.maxlego08.essentials.api.commands.CommandCooldown; import fr.maxlego08.essentials.api.commands.CommandRestriction; +import fr.maxlego08.essentials.api.config.models.NearDirectionReplacements; import fr.maxlego08.essentials.api.configuration.NonLoadable; import fr.maxlego08.essentials.api.configuration.ReplacePlaceholder; import fr.maxlego08.essentials.api.configuration.ReplacePlaceholderElement; @@ -23,16 +24,12 @@ import fr.maxlego08.sarah.database.DatabaseType; import org.bukkit.Bukkit; import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.permissions.Permissible; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.stream.LongStream; public class MainConfiguration extends YamlLoader implements Configuration { @@ -44,7 +41,13 @@ public class MainConfiguration extends YamlLoader implements Configuration { private final StorageType storageType = StorageType.JSON; private final List messageColors = new ArrayList<>(); private final List cooldowns = new ArrayList<>(); + private double nearDistance; + @NonLoadable + private NearDirectionReplacements nearDirectionReplacements = NearDirectionReplacements.DEFAULT; private final List nearPermissions = new ArrayList<>(); + private long dayTime = 1000; + private long nightTime = 13000; + private boolean timeSmoothChange = false; private final List disableFlyWorld = new ArrayList<>(); private final List disableBackWorld = new ArrayList<>(); @NonLoadable @@ -61,7 +64,6 @@ public class MainConfiguration extends YamlLoader implements Configuration { private DatabaseConfiguration databaseConfiguration; private ServerType serverType; private RedisConfiguration redisConfiguration; - private double nearDistance; private SimpleDateFormat simpleDateFormat; private List replacePlaceholders = new ArrayList<>(); private List randomWords; @@ -155,6 +157,21 @@ public void load() { configuration.getBoolean("database-configuration.debug"), DatabaseType.MYSQL ); + + final ConfigurationSection nearDirSection = configuration.getConfigurationSection("near-direction-replacements"); + if (nearDirSection != null) { + this.nearDirectionReplacements = new NearDirectionReplacements( + configuration.getString("forward", "↑"), + configuration.getString("forward-right", "↗"), + configuration.getString("right", "→"), + configuration.getString("back-right", "↘"), + configuration.getString("back", "↓"), + configuration.getString("back-left", "↙"), + configuration.getString("left", "←"), + configuration.getString("forward-left", "↖") + ); + } + this.cooldownCommands = this.cooldowns.stream().flatMapToLong(cooldown -> LongStream.of(cooldown.cooldown(), cooldown.messages())).toArray(); this.simpleDateFormat = this.globalDateFormat == null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") : new SimpleDateFormat(this.globalDateFormat); this.flyTaskAnnounce = configuration.getLongList("fly-task-announce"); @@ -261,13 +278,13 @@ public List getSmeltableMaterials() { } @Override - public List getNearPermissions() { - return nearPermissions; + public double getDefaultNearDistance() { + return nearDistance; } @Override - public double getDefaultNearDistance() { - return nearDistance; + public NearDirectionReplacements getNearDirectionReplacements() { + return this.nearDirectionReplacements; } @Override @@ -275,6 +292,26 @@ public double getNearDistance(Permissible permissible) { return this.nearPermissions.stream().filter(nearDistance -> permissible.hasPermission(nearDistance.permission())).map(NearDistance::distance).findFirst().orElse(this.nearDistance); } + @Override + public List getNearPermissions() { + return nearPermissions; + } + + @Override + public long getDayTime() { + return this.dayTime; + } + + @Override + public long getNightTime() { + return this.nightTime; + } + + @Override + public boolean isTimeSmoothChangeEnabled() { + return this.timeSmoothChange; + } + @Override public boolean isEnableCommandLog() { return this.enableCommandLog; diff --git a/src/main/java/fr/maxlego08/essentials/commands/CommandLoader.java b/src/main/java/fr/maxlego08/essentials/commands/CommandLoader.java index e3ba4f0e..e5beff9d 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/CommandLoader.java +++ b/src/main/java/fr/maxlego08/essentials/commands/CommandLoader.java @@ -78,28 +78,8 @@ import fr.maxlego08.essentials.commands.commands.teleport.CommandTeleportToHere; import fr.maxlego08.essentials.commands.commands.teleport.CommandTeleportWorld; import fr.maxlego08.essentials.commands.commands.teleport.CommandTop; -import fr.maxlego08.essentials.commands.commands.utils.CommandAfk; -import fr.maxlego08.essentials.commands.commands.utils.CommandCompact; -import fr.maxlego08.essentials.commands.commands.utils.CommandCompactAll; -import fr.maxlego08.essentials.commands.commands.utils.CommandCraft; -import fr.maxlego08.essentials.commands.commands.utils.CommandExt; -import fr.maxlego08.essentials.commands.commands.utils.CommandFeed; -import fr.maxlego08.essentials.commands.commands.utils.CommandFurnace; -import fr.maxlego08.essentials.commands.commands.utils.CommandHat; -import fr.maxlego08.essentials.commands.commands.utils.CommandHeal; -import fr.maxlego08.essentials.commands.commands.utils.CommandMore; -import fr.maxlego08.essentials.commands.commands.utils.CommandNear; -import fr.maxlego08.essentials.commands.commands.utils.CommandNightVision; -import fr.maxlego08.essentials.commands.commands.utils.CommandPhantoms; -import fr.maxlego08.essentials.commands.commands.utils.CommandPlayTime; -import fr.maxlego08.essentials.commands.commands.utils.CommandRepair; -import fr.maxlego08.essentials.commands.commands.utils.CommandRepairAll; -import fr.maxlego08.essentials.commands.commands.utils.CommandRules; +import fr.maxlego08.essentials.commands.commands.utils.*; import fr.maxlego08.essentials.commands.commands.utils.lag.CommandLag; -import fr.maxlego08.essentials.commands.commands.utils.CommandSudo; -import fr.maxlego08.essentials.commands.commands.utils.CommandSuicide; -import fr.maxlego08.essentials.commands.commands.utils.CommandTrash; -import fr.maxlego08.essentials.commands.commands.utils.CommandVersion; import fr.maxlego08.essentials.commands.commands.utils.admins.CommandEnchant; import fr.maxlego08.essentials.commands.commands.utils.admins.CommandFlySpeed; import fr.maxlego08.essentials.commands.commands.utils.admins.CommandGod; @@ -173,6 +153,7 @@ public void loadCommands(CommandManager commandManager) { register("god", CommandGod.class); register("vanish", CommandVanish.class, "v"); register("heal", CommandHeal.class); + register("lightning", CommandLightning.class, "strike"); register("more", CommandMore.class); register("worldtp", CommandTeleportWorld.class, "wtp"); register("trash", CommandTrash.class, "poubelle"); diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/random/CommandTeleportRandomOther.java b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/random/CommandTeleportRandomOther.java index a0733969..505939a5 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/random/CommandTeleportRandomOther.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/random/CommandTeleportRandomOther.java @@ -15,12 +15,12 @@ public class CommandTeleportRandomOther extends VCommand { public CommandTeleportRandomOther(EssentialsPlugin plugin) { super(plugin); - this.setModule(TeleportationModule.class); - this.setPermission(Permission.ESSENTIALS_TP_RANDOM_OTHER); - this.setDescription(Message.DESCRIPTION_TP_RANDOM_OTHER); - this.addSubCommand("other"); - this.addRequireArg("player", getOnlinePlayers()); - this.addRequireArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList()); + super.setModule(TeleportationModule.class); + super.setPermission(Permission.ESSENTIALS_TP_RANDOM_OTHER); + super.setDescription(Message.DESCRIPTION_TP_RANDOM_OTHER); + super.addSubCommand("other"); + super.addRequirePlayerNameArg(); + super.addRequireArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).toList()); } @Override diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandExt.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandExt.java index 415637b3..8afd1651 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandExt.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandExt.java @@ -5,19 +5,42 @@ import fr.maxlego08.essentials.api.commands.Permission; import fr.maxlego08.essentials.api.messages.Message; import fr.maxlego08.essentials.zutils.utils.commands.VCommand; +import org.bukkit.entity.Player; public class CommandExt extends VCommand { public CommandExt(EssentialsPlugin plugin) { super(plugin); this.setPermission(Permission.ESSENTIALS_EXT); this.setDescription(Message.DESCRIPTION_EXT); + this.addOptionalArg("player", getVisiblePlayerNames()); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { + Player player = this.argAsPlayer(0, this.player); + + if (player == null) return CommandResultType.SYNTAX_ERROR; + + if (player != this.player && !hasPermission(sender, Permission.ESSENTIALS_FEED_OTHER)) { + player = this.player; + } + + if (!player.isValid()) { + message(sender, Message.COMMAND_EXT_ERROR); + return CommandResultType.DEFAULT; + } + this.player.setFireTicks(0); - message(sender, Message.COMMAND_EXT); + + if (player == sender) { + + message(sender, Message.COMMAND_EXT_RECEIVER); + } else { + + message(sender, Message.COMMAND_EXT_SENDER, "%player%", player.getName()); + message(player, Message.COMMAND_EXT_RECEIVER); + } return CommandResultType.SUCCESS; } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandFeed.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandFeed.java index 69d5b4e3..2bf310d6 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandFeed.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandFeed.java @@ -7,36 +7,72 @@ import fr.maxlego08.essentials.zutils.utils.commands.VCommand; import org.bukkit.entity.Player; +import java.util.ArrayList; + public class CommandFeed extends VCommand { + public CommandFeed(EssentialsPlugin plugin) { super(plugin); this.setPermission(Permission.ESSENTIALS_FEED); this.setDescription(Message.DESCRIPTION_FEED); - this.addOptionalArg("player"); + this.addOptionalArg("player", (a, b) -> new ArrayList<>(plugin.getEssentialsServer().getVisiblePlayerNames(this.sender)) {{ + add("*"); + }}); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { + String arg = this.argAsString(0); - Player player = this.argAsPlayer(0, this.player); + if ("*".equals(arg)) { + return feedAllPlayers(plugin); + } + + return feedSinglePlayer(); + } + + private CommandResultType feedAllPlayers(EssentialsPlugin plugin) { + if (!hasPermission(sender, Permission.ESSENTIALS_FEED_ALL)) { + return CommandResultType.NO_PERMISSION; + } + + for (Player target : plugin.getServer().getOnlinePlayers()) { + if (!target.isValid()) continue; + feedPlayer(target); + message(target, Message.COMMAND_FEED_RECEIVER); + } + + message(sender, Message.COMMAND_FEED_ALL); + return CommandResultType.SUCCESS; + } + private CommandResultType feedSinglePlayer() { + Player player = this.argAsPlayer(0, this.player); if (player == null) return CommandResultType.SYNTAX_ERROR; if (player != this.player && !hasPermission(sender, Permission.ESSENTIALS_FEED_OTHER)) { player = this.player; } - player.setFoodLevel(20); + if (!player.isValid()) { + message(sender, Message.COMMAND_FEED_ERROR); + return CommandResultType.DEFAULT; + } - if (player == sender) { + feedPlayer(player); + if (player == sender) { message(sender, Message.COMMAND_FEED_RECEIVER); } else { - message(sender, Message.COMMAND_FEED_SENDER, "%player%", player.getName()); message(player, Message.COMMAND_FEED_RECEIVER); } return CommandResultType.SUCCESS; } + + private void feedPlayer(Player player) { + player.setFoodLevel(20); + player.setSaturation(20); + } } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandHeal.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandHeal.java index 4625dd93..d9823aff 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandHeal.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandHeal.java @@ -10,19 +10,46 @@ import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffectType; +import java.util.ArrayList; + public class CommandHeal extends VCommand { public CommandHeal(EssentialsPlugin plugin) { super(plugin); - this.setPermission(Permission.ESSENTIALS_HEAL); - this.setDescription(Message.DESCRIPTION_HEAL); - this.addOptionalArg("player"); + super.setPermission(Permission.ESSENTIALS_HEAL); + super.setDescription(Message.DESCRIPTION_HEAL); + super.addOptionalArg("player", (a, b) -> new ArrayList<>(this.plugin.getEssentialsServer().getVisiblePlayerNames(this.sender)) {{ + add("*"); + }}); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { + String arg = this.argAsString(0); - Player player = this.argAsPlayer(0, this.player); + if ("*".equals(arg)) { + return healAllPlayers(plugin); + } + + return healSinglePlayer(plugin); + } + + private CommandResultType healAllPlayers(EssentialsPlugin plugin) { + if (!hasPermission(sender, Permission.ESSENTIALS_HEAL_ALL)) { + return CommandResultType.NO_PERMISSION; + } + for (Player target : plugin.getServer().getOnlinePlayers()) { + if (!target.isValid()) continue; + healPlayer(plugin, target); + message(target, Message.COMMAND_HEAL_RECEIVER); + } + + message(sender, Message.COMMAND_HEAL_ALL); + return CommandResultType.SUCCESS; + } + + private CommandResultType healSinglePlayer(EssentialsPlugin plugin) { + Player player = this.argAsPlayer(0, this.player); if (player == null) return CommandResultType.SYNTAX_ERROR; if (player != this.player && !hasPermission(sender, Permission.ESSENTIALS_HEAL_OTHER)) { @@ -34,25 +61,30 @@ protected CommandResultType perform(EssentialsPlugin plugin) { return CommandResultType.DEFAULT; } - player.setHealth(player.getAttribute(AttributeUtils.getAttribute("max_health")).getBaseValue()); - player.setFoodLevel(20); - player.setFireTicks(0); - Player finalPlayer = player; - var user = plugin.getUser(player.getUniqueId()); - player.getActivePotionEffects().forEach(potionEffect -> { - if (potionEffect.getType() == PotionEffectType.NIGHT_VISION && user.getOption(Option.NIGHT_VISION)) return; - finalPlayer.removePotionEffect(potionEffect.getType()); - }); + healPlayer(plugin, player); if (player == sender) { - message(sender, Message.COMMAND_HEAL_RECEIVER); } else { - message(sender, Message.COMMAND_HEAL_SENDER, "%player%", player.getName()); message(player, Message.COMMAND_HEAL_RECEIVER); } return CommandResultType.SUCCESS; } + + private void healPlayer(EssentialsPlugin plugin, Player player) { + player.setHealth( + player.getAttribute(AttributeUtils.getAttribute("max_health")).getBaseValue() + ); + player.setFoodLevel(20); + player.setFireTicks(0); + + var user = plugin.getUser(player.getUniqueId()); + player.getActivePotionEffects().forEach(effect -> { + if (effect.getType() == PotionEffectType.NIGHT_VISION + && user.getOption(Option.NIGHT_VISION)) return; + player.removePotionEffect(effect.getType()); + }); + } } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandLightning.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandLightning.java new file mode 100644 index 00000000..29f8dc25 --- /dev/null +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandLightning.java @@ -0,0 +1,100 @@ +package fr.maxlego08.essentials.commands.commands.utils; + +import fr.maxlego08.essentials.api.EssentialsPlugin; +import fr.maxlego08.essentials.api.commands.CommandResultType; +import fr.maxlego08.essentials.api.commands.Permission; +import fr.maxlego08.essentials.api.messages.Message; +import fr.maxlego08.essentials.zutils.utils.commands.VCommand; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + + +public final class CommandLightning extends VCommand { + + public CommandLightning(EssentialsPlugin plugin) { + super(plugin); + this.setPermission(Permission.ESSENTIALS_LIGHTING); + this.setDescription(Message.DESCRIPTION_LIGHTING); + this.addOptionalArg("player", (a, b) -> new ArrayList<>(plugin.getEssentialsServer().getVisiblePlayerNames(this.sender)) {{ + add("*"); + }}); + this.addOptionalArg("visual-flag", (a, b) -> List.of("--only-visual")); + } + + @Override + protected CommandResultType perform(EssentialsPlugin plugin) { + String arg = this.argAsString(0); + + if ("*".equals(arg)) { + return strikeAllPlayers(plugin); + } + + return strikeSinglePlayer(); + } + + private CommandResultType strikeAllPlayers(EssentialsPlugin plugin) { + if (!hasPermission(sender, Permission.ESSENTIALS_LIGHTING_ALL)) { + return CommandResultType.NO_PERMISSION; + } + + boolean visual = this.argAsString(1, "").equals("--only-visual"); + + for (Player target : plugin.getServer().getOnlinePlayers()) { + if (!target.isValid()) continue; + strike(target.getLocation(), visual); + message(target, Message.COMMAND_LIGHTING_RECEIVER); + } + + message(sender, Message.COMMAND_LIGHTING_ALL); + return CommandResultType.SUCCESS; + } + + private CommandResultType strikeSinglePlayer() { + String arg = this.argAsString(0); + Player player = this.player; + if (arg != null && hasPermission(sender, Permission.ESSENTIALS_LIGHTING_OTHER)) { + player = Bukkit.getPlayer(arg); + if (player == null) return CommandResultType.SYNTAX_ERROR; + } + + if (!player.isValid()) { + message(sender, Message.COMMAND_LIGHTING_ERROR); + return CommandResultType.DEFAULT; + } + + Location location; + + if (arg == null) { + final Block targetBlockExact = player.getTargetBlock(null, 100); + location = targetBlockExact.getLocation().add(.5d, 0, .5d); + + message(sender, Message.COMMAND_LIGHTING); + } else if (player == this.player){ + location = player.getLocation(); + + message(player, Message.COMMAND_LIGHTING_RECEIVER); + } else { + location = player.getLocation(); + + message(sender, Message.COMMAND_LIGHTING_SENDER, "%player%", player.getName()); + message(player, Message.COMMAND_LIGHTING_RECEIVER); + } + + strike(location, this.argAsString(1, "").equals("--only-visual")); + + return CommandResultType.SUCCESS; + } + + private void strike(Location location, boolean visual) { + if (visual) { + location.getWorld().strikeLightning(location); + } else { + location.getWorld().strikeLightningEffect(location); + } + } +} diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandNear.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandNear.java index cf5ce768..a5ac5606 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandNear.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/CommandNear.java @@ -3,16 +3,20 @@ import fr.maxlego08.essentials.api.EssentialsPlugin; import fr.maxlego08.essentials.api.commands.CommandResultType; import fr.maxlego08.essentials.api.commands.Permission; +import fr.maxlego08.essentials.api.config.models.NearDirectionReplacements; import fr.maxlego08.essentials.api.messages.Message; -import fr.maxlego08.essentials.api.user.Option; -import fr.maxlego08.essentials.api.user.User; import fr.maxlego08.essentials.zutils.utils.commands.VCommand; import org.bukkit.entity.Player; +import org.bukkit.util.Vector; import java.text.DecimalFormat; +import java.util.Collection; import java.util.List; public class CommandNear extends VCommand { + + private static final DecimalFormat DISTANCE_FORMAT = new DecimalFormat("#.##"); + public CommandNear(EssentialsPlugin plugin) { super(plugin); this.setPermission(Permission.ESSENTIALS_NEAR); @@ -24,18 +28,51 @@ public CommandNear(EssentialsPlugin plugin) { protected CommandResultType perform(EssentialsPlugin plugin) { double distance = plugin.getConfiguration().getNearDistance(this.player); - List players = this.player.getWorld().getNearbyPlayers(this.player.getLocation(), distance).stream().filter(player -> { - User user = plugin.getUser(player.getUniqueId()); - return user == null || !user.getOption(Option.VANISH); - }).filter(player -> player != this.player).toList(); + Collection players = this.player.getWorld().getNearbyPlayers(this.player.getLocation(), distance, player -> + player != this.player && !isVanishedFor(this.player, player) + ); if (players.isEmpty()) { message(sender, Message.COMMAND_NEAR_EMPTY); } else { - DecimalFormat decimalFormat = new DecimalFormat("#.##"); - message(sender, Message.COMMAND_NEAR_PLAYER, "%players%", String.join(",", players.stream().map(player -> getMessage(Message.COMMAND_NEAR_INFO, "%player%", player.getName(), "%distance%", decimalFormat.format(player.getLocation().distance(this.player.getLocation())))).toList())); + StringBuilder playersInfo = new StringBuilder(); + + for (Player target : players) { + double dist = target.getLocation().distance(player.getLocation()); + String direction = getDirection(player, target); + + String info = getMessage( + Message.COMMAND_NEAR_INFO, + "%player%", target.getName(), + "%distance%", DISTANCE_FORMAT.format(dist), + "%direction%", direction + ); + if (playersInfo.length() > 0) playersInfo.append(", "); + playersInfo.append(info); + } + + message(sender, Message.COMMAND_NEAR_PLAYER, "%players%", playersInfo.toString()); } return CommandResultType.SUCCESS; } + + private String getDirection(Player from, Player to) { + Vector look = from.getLocation().getDirection().setY(0).normalize(); + Vector targetDir = to.getLocation().toVector().subtract(from.getLocation().toVector()).setY(0).normalize(); + + double angle = Math.toDegrees(Math.atan2(targetDir.getX(), targetDir.getZ()) - Math.atan2(look.getX(), look.getZ())); + angle = (angle + 360) % 360; + + NearDirectionReplacements conf = plugin.getConfiguration().getNearDirectionReplacements(); + + if (angle <= 22.5 || angle > 337.5) return conf.forwardReplacement(); + if (angle <= 67.5) return conf.forwardLeftReplacement(); + if (angle <= 112.5) return conf.leftReplacement(); + if (angle <= 157.5) return conf.backLeftReplacement(); + if (angle <= 202.5) return conf.backReplacement(); + if (angle <= 247.5) return conf.backRightReplacement(); + if (angle <= 292.5) return conf.rightReplacement(); + return conf.forwardRightReplacement(); + } } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandGod.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandGod.java index cdf6748d..3b8a0ed7 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandGod.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandGod.java @@ -24,7 +24,7 @@ public CommandGod(EssentialsPlugin plugin) { super(plugin); this.setPermission(Permission.ESSENTIALS_GOD); this.setDescription(Message.DESCRIPTION_GOD); - this.addOptionalArg("player", getOnlinePlayers()); + this.addOptionalArg("player", getVisiblePlayerNames()); } @Override diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandVanish.java b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandVanish.java index e7b2121a..95d1da9d 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandVanish.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/utils/admins/CommandVanish.java @@ -15,7 +15,7 @@ public CommandVanish(EssentialsPlugin plugin) { super(plugin); this.setPermission(Permission.ESSENTIALS_VANISH); this.setDescription(Message.DESCRIPTION_VANISH); - this.addOptionalArg("player", getOnlinePlayers()); + this.addOptionalArg("player", getVisiblePlayerNames()); } @Override diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandDay.java b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandDay.java index d2f20ba0..78c6cca8 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandDay.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandDay.java @@ -9,25 +9,43 @@ import org.bukkit.World; import org.bukkit.generator.WorldInfo; +import java.util.UUID; import java.util.stream.Collectors; public class CommandDay extends VCommand { public CommandDay(EssentialsPlugin plugin) { super(plugin); - this.setPermission(Permission.ESSENTIALS_DAY); - this.setDescription(Message.DESCRIPTION_DAY); - this.addOptionalArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).collect(Collectors.toList())); + super.setPermission(Permission.ESSENTIALS_DAY); + super.setDescription(Message.DESCRIPTION_DAY); + super.addOptionalArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).collect(Collectors.toList())); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { - World world = this.argAsWorld(0, isPlayer() ? this.player.getWorld() : null); - world.setFullTime(1000); + if (world == null) { + message(sender, Message.COMMAND_TIME_ERROR); + return CommandResultType.SYNTAX_ERROR; + } + + UUID worldId = world.getUID(); + + if (TimeTransition.isWorldTimeChanging(worldId)) { + message(sender, Message.COMMAND_TIME_ALREADY_CHANGING, "%world%", world.getName()); + return CommandResultType.DEFAULT; + } + + long dayTime = plugin.getConfiguration().getDayTime(); + boolean smooth = plugin.getConfiguration().isTimeSmoothChangeEnabled(); - message(this.sender, Message.COMMAND_DAY, "%world%", world.getName()); + if (smooth) { + TimeTransition.transitionWorldTime(plugin, world, dayTime); + } else { + world.setFullTime(dayTime); + } + message(sender, Message.COMMAND_DAY, "%world%", world.getName()); return CommandResultType.SUCCESS; } } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandNight.java b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandNight.java index 3aa42d8d..0c411b2a 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandNight.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandNight.java @@ -9,25 +9,43 @@ import org.bukkit.World; import org.bukkit.generator.WorldInfo; +import java.util.UUID; import java.util.stream.Collectors; public class CommandNight extends VCommand { public CommandNight(EssentialsPlugin plugin) { super(plugin); - this.setPermission(Permission.ESSENTIALS_NIGHT); - this.setDescription(Message.DESCRIPTION_NIGHT); - this.addOptionalArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).collect(Collectors.toList())); + super.setPermission(Permission.ESSENTIALS_NIGHT); + super.setDescription(Message.DESCRIPTION_NIGHT); + super.addOptionalArg("world", (a, b) -> Bukkit.getWorlds().stream().map(WorldInfo::getName).collect(Collectors.toList())); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { + World world = super.argAsWorld(0, isPlayer() ? this.player.getWorld() : null); + if (world == null) { + message(sender, Message.COMMAND_TIME_ERROR); + return CommandResultType.SYNTAX_ERROR; + } - World world = this.argAsWorld(0, isPlayer() ? this.player.getWorld() : null); - world.setFullTime(13000); + UUID worldId = world.getUID(); - message(this.sender, Message.COMMAND_NIGHT, "%world%", world.getName()); + if (TimeTransition.isWorldTimeChanging(worldId)) { + message(sender, Message.COMMAND_TIME_ALREADY_CHANGING, "%world%", world.getName()); + return CommandResultType.DEFAULT; + } + long nightTime = plugin.getConfiguration().getNightTime(); + boolean smooth = plugin.getConfiguration().isTimeSmoothChangeEnabled(); + + if (smooth) { + TimeTransition.transitionWorldTime(plugin, world, nightTime); + } else { + world.setFullTime(nightTime); + } + + message(sender, Message.COMMAND_NIGHT, "%world%", world.getName()); return CommandResultType.SUCCESS; } } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandPlayerTime.java b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandPlayerTime.java index 4e7b0ae8..00272546 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandPlayerTime.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/CommandPlayerTime.java @@ -12,10 +12,10 @@ public class CommandPlayerTime extends VCommand { public CommandPlayerTime(EssentialsPlugin plugin) { super(plugin); - this.setPermission(Permission.ESSENTIALS_PLAYER_TIME); - this.setDescription(Message.DESCRIPTION_PLAYER_TIME); - this.addOptionalArg("time", (a, b) -> Arrays.asList("0", "500", "1000", "1500", "2000")); - this.onlyPlayers(); + super.setPermission(Permission.ESSENTIALS_PLAYER_TIME); + super.setDescription(Message.DESCRIPTION_PLAYER_TIME); + super.addOptionalArg("time", (a, b) -> Arrays.asList("0", "500", "1000", "1500", "2000")); + super.onlyPlayers(); } @Override @@ -34,7 +34,7 @@ protected CommandResultType perform(EssentialsPlugin plugin) { time -= time % 24000L; time += 24000L + ticks; - player.setPlayerTime(time, true); + player.setPlayerTime(time, false); message(player, Message.COMMAND_PLAYER_TIME_CHANGE); } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/weather/TimeTransition.java b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/TimeTransition.java new file mode 100644 index 00000000..35306f85 --- /dev/null +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/weather/TimeTransition.java @@ -0,0 +1,59 @@ +package fr.maxlego08.essentials.commands.commands.weather; + +import fr.maxlego08.essentials.api.EssentialsPlugin; +import fr.maxlego08.essentials.api.nms.PlayerUtil; +import fr.maxlego08.menu.zcore.utils.nms.NmsVersion; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Constructor; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Utility class for smooth time transitions in worlds and for players + */ +class TimeTransition { + + private static final long WORLD_TIME_STEP = 150; + + static final Set TIME_CHANGING_WORLDS = ConcurrentHashMap.newKeySet(); + + /** + * Smoothly transitions world time to target time + */ + static void transitionWorldTime(EssentialsPlugin plugin, World world, long targetTime) { + UUID worldId = world.getUID(); + TIME_CHANGING_WORLDS.add(worldId); + + long startTime = world.getFullTime(); + long diff = (targetTime - startTime + 24000) % 24000; + + new BukkitRunnable() { + long progressed = 0; + + @Override + public void run() { + if (progressed >= diff) { + world.setFullTime(targetTime); + TIME_CHANGING_WORLDS.remove(worldId); + cancel(); + return; + } + + world.setFullTime(world.getFullTime() + WORLD_TIME_STEP); + progressed += WORLD_TIME_STEP; + } + }.runTaskTimer(plugin, 0L, 1L); + } + + /** + * Checks if world time is currently being changed + */ + static boolean isWorldTimeChanging(UUID worldId) { + return TIME_CHANGING_WORLDS.contains(worldId); + } +} diff --git a/src/main/java/fr/maxlego08/essentials/server/PaperServer.java b/src/main/java/fr/maxlego08/essentials/server/PaperServer.java index 757301bc..4dbce9b2 100644 --- a/src/main/java/fr/maxlego08/essentials/server/PaperServer.java +++ b/src/main/java/fr/maxlego08/essentials/server/PaperServer.java @@ -16,6 +16,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; @@ -44,7 +45,13 @@ public void onDisable() { @Override public List getPlayersNames() { - return Bukkit.getOnlinePlayers().stream().filter(this::isNotVanished).map(Player::getName).toList(); + return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); + } + + @Override + public List getVisiblePlayerNames(@NotNull CommandSender sender) { + if (!(sender instanceof Player player)) return getPlayersNames(); + return Bukkit.getOnlinePlayers().stream().filter(target -> !isVanishedFor(target, player)).map(Player::getName).toList(); } @Override diff --git a/src/main/java/fr/maxlego08/essentials/server/SpigotServer.java b/src/main/java/fr/maxlego08/essentials/server/SpigotServer.java index 9c0e4d4a..772d3ccb 100644 --- a/src/main/java/fr/maxlego08/essentials/server/SpigotServer.java +++ b/src/main/java/fr/maxlego08/essentials/server/SpigotServer.java @@ -13,6 +13,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; @@ -41,6 +42,11 @@ public List getPlayersNames() { return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } + @Override + public List getVisiblePlayerNames(@NotNull CommandSender sender) { + return getPlayersNames(); + } + @Override public List getOfflinePlayersNames() { return this.plugin.getConfiguration().isEnableOfflinePlayersName() ? Arrays.stream(Bukkit.getOfflinePlayers()).map(OfflinePlayer::getName).toList() : getPlayersNames(); diff --git a/src/main/java/fr/maxlego08/essentials/zutils/utils/ZUtils.java b/src/main/java/fr/maxlego08/essentials/zutils/utils/ZUtils.java index 678a4bbe..c357c381 100644 --- a/src/main/java/fr/maxlego08/essentials/zutils/utils/ZUtils.java +++ b/src/main/java/fr/maxlego08/essentials/zutils/utils/ZUtils.java @@ -68,6 +68,13 @@ private boolean isBlockUnsafe(World world, int x, int y, int z) { return block.isEmpty() || block.isLiquid(); } + protected boolean isVanishedFor(Player target, Player viewer) { + if (target == viewer) return false; + if (!isVanished(target)) return false; + return !hasPermission(viewer, Permission.ESSENTIALS_VANISH_SEE) && + !hasPermission(viewer, Permission.ESSENTIALS_VANISH); + } + protected boolean isVanished(Player player) { for (MetadataValue metadataValue : player.getMetadata("vanished")) { if (metadataValue.asBoolean()) return true; diff --git a/src/main/java/fr/maxlego08/essentials/zutils/utils/commands/VCommand.java b/src/main/java/fr/maxlego08/essentials/zutils/utils/commands/VCommand.java index cbfba535..c7cc17d7 100644 --- a/src/main/java/fr/maxlego08/essentials/zutils/utils/commands/VCommand.java +++ b/src/main/java/fr/maxlego08/essentials/zutils/utils/commands/VCommand.java @@ -2,11 +2,7 @@ import fr.maxlego08.essentials.api.Configuration; import fr.maxlego08.essentials.api.EssentialsPlugin; -import fr.maxlego08.essentials.api.commands.CommandResultType; -import fr.maxlego08.essentials.api.commands.EssentialsCommand; -import fr.maxlego08.essentials.api.commands.Permission; -import fr.maxlego08.essentials.api.commands.Tab; -import fr.maxlego08.essentials.api.commands.TabCompletion; +import fr.maxlego08.essentials.api.commands.*; import fr.maxlego08.essentials.api.messages.Message; import fr.maxlego08.essentials.api.modules.Module; import fr.maxlego08.essentials.api.user.Option; @@ -15,14 +11,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; public abstract class VCommand extends Arguments implements EssentialsCommand { @@ -259,7 +248,7 @@ protected void addRequireArg(String message) { } protected void addRequirePlayerNameArg() { - this.addRequireArg("player", getOnlinePlayers()); + this.addRequireArg("player", getVisiblePlayerNames()); } protected void addRequireOfflinePlayerNameArg() { @@ -276,10 +265,14 @@ protected void addRequireArg(String message, TabCompletion runnable) { this.addCompletion(index - 1, runnable); } - protected TabCompletion getOnlinePlayers() { + protected TabCompletion getOnlinePlayerNames() { return (a, b) -> this.plugin.getEssentialsServer().getPlayersNames(); } + protected TabCompletion getVisiblePlayerNames() { + return (a, b) -> this.plugin.getEssentialsServer().getVisiblePlayerNames(this.sender); + } + protected TabCompletion getOfflinePlayers() { return (a, b) -> this.plugin.getEssentialsServer().getOfflinePlayersNames(); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 41638c7a..9626d2f0 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -157,11 +157,30 @@ smeltable-materials: - from: KELP to: DRIED_KELP +# Default value returned by placeholders when no data is available +placeholder-empty: "Empty" + # Default distance for /near near-distance: 50.0 -# Default value returned by placeholders when no data is available -placeholder-empty: "Empty" +# Displays target's direction in /near +near-direction-replacements: + forward: "↑" + forward-right: "↗" + right: "→" + back-right: "↘" + back: "↓" + back-left: "↙" + left: "←" + forward-left: "↖" + +# World time set by the /day command +day-time: 1000 +# World time set by the /night command +night-time: 13000 + +# Animate world time change (/day, /night) +time-smooth-change: false # Set a distance by permission for /near near-permissions: diff --git a/src/main/resources/messages/message_zh.yml b/src/main/resources/messages/message_zh.yml index bbd1fd72..d79433d5 100644 --- a/src/main/resources/messages/message_zh.yml +++ b/src/main/resources/messages/message_zh.yml @@ -52,6 +52,8 @@ command-gamemode-invalid: 您需要指定一个有效的玩家。 # 天气命令 +command-time-error: "你需要指定一个世界" +command-time-already-changing: "&f%world% 的时间已经在改变中。" command-day: '&f您刚刚带来了 &edaylight&f 到世界 %world%&f。' command-night: '&f您刚刚带来了 &enightfall&f 到世界 %world%&f。' command-sun: '&f您刚刚带来了 &esun&f 到世界 %world%&f。' @@ -70,11 +72,21 @@ command-vanish-enable: '&7隐身模式 启用 &7给 &f%player% command-vanish-disable: '&7隐身模式 禁用 &7给 &f%player%。' command-night-vision-enable: '&7夜视 启用 &7给 &f%player%。' command-night-vision-disable: '&7夜视 禁用 &7给 &f%player%。' +command-ext-sender: "&7你已为玩家 &f%player%&7 扑灭了火焰。" +command-ext-receiver: "你已不再着火。" +command-ext-error: "你无法为已死亡的玩家灭火!" +command-heal-all: "&7你已治疗服务器中的所有玩家。" command-heal-sender: '&7您刚刚治愈了玩家 &f%player%&7。' command-heal-receiver: 您已被治愈。 command-heal-error: 您不能治愈一个已经死亡的人! +command-lighting-all: "&7你刚刚用闪电击中了所有玩家。" +command-lighting: "&7你刚在目标位置召唤了闪电。" +command-lighting-sender: "&7你刚在玩家 &f%player%&7 的位置召唤了闪电。" +command-lighting-receiver: "&c你被闪电击中了!" +command-lighting-error: "你不能用闪电击中已死亡的玩家!" command-more-error: 您不能对手中的物品执行此操作。 command-more-success: '&7您刚刚把手中的物品数量设为了 &f64&7。' +command-feed-all: "&7你已为服务器中的所有玩家补充了饱食度。" command-feed-sender: '&7您刚刚喂饱了玩家 &f%player%&7。' command-feed-receiver: 您已被喂饱。 command-feed-error: 您不能喂饱一个已经死亡的人! @@ -120,10 +132,9 @@ command-repair-error: 您手上的物品无法修复。 command-repair-success: 您刚刚修复了手上的物品。 command-repair-all-error: 您没有可修复的物品。 command-repair-all-success: 您刚刚修复了背包中的所有物品。 -command-ext: '&f由Maxlego08的意志,您不再燃烧。' command-near-empty: 附近没有其他玩家。 command-near-player: '&f附近的玩家&7:%players%' -command-near-info: ' &7%player% &8(&e%distance%m&8)' +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - '&7您玩了&8: %playtime%' - '&7当前会话&8: %playtime_session%' @@ -292,6 +303,7 @@ description-tp-all: 将所有玩家传送到您的位置 description-god: 切换上帝模式 description-vanish: 切换隐身模式 description-heal: 治愈一名玩家 +description-lighting: 用闪电击中玩家 description-more: 获得更多物品 description-tp-world: 传送到另一个世界 description-trash: 打开垃圾桶 diff --git a/src/main/resources/messages/messages.yml b/src/main/resources/messages/messages.yml index 815d1990..fa9f8317 100644 --- a/src/main/resources/messages/messages.yml +++ b/src/main/resources/messages/messages.yml @@ -53,6 +53,8 @@ command-gamemode-invalid: "You need to specify a valid player." # Weather commands +command-time-error: "You need to specify a world." +command-time-already-changing: "Time is already changing in &f%world%." command-day: "&fYou have just brought &edaylight&f into the world %world%&f." command-night: "&fYou have just brought &enightfall&f into the world %world%&f." command-sun: "&fYou have just brought the &esun&f into the world %world%&f." @@ -73,11 +75,21 @@ command-night-vision-enable: "&7Night vision enable &7for &f%player%disable &7for &f%player%." command-phantoms-enable: "&7Phantom spawning enable &7for &f%player%." command-phantoms-disable: "&7Phantom spawning disable &7for &f%player%." +command-ext-sender: "&7You just extinguished the player &f%player%&7." +command-ext-receiver: "You are no longer burning." +command-ext-error: "You cannot extinguish someone who is dead!" +command-heal-all: "&7You just healed all players on the server." command-heal-sender: "&7You just healed the player &f%player%&7." command-heal-receiver: "You have been healed." -command-heal-error: "You cannot heal someone who is dead !" +command-heal-error: "You cannot heal someone who is dead!" +command-lighting-all: "&7You just struck all players with lightning." +command-lighting: "&7You just summoned lightning at the targeted location." +command-lighting-sender: "&7You just summoned lightning at the location of &f%player%&7." +command-lighting-receiver: "&cYou have been struck by lightning." +command-lighting-error: "You cannot strike a dead player with lightning!" command-more-error: "You cannot make this order in item in hand." command-more-success: "&7You just put your item to &f64&7." +command-feed-all: "&7You just feed all players on the server." command-feed-sender: "&7You just feed the player &f%player%&7." command-feed-receiver: "You have been feed." command-feed-error: "You cannot feed someone who is dead !" @@ -121,10 +133,9 @@ command-repair-error: "The item in your hand cannot be repaired." command-repair-success: "You just fixed the item in your hand." command-repair-all-error: "You have no items to repair." command-repair-all-success: "You have just repaired all the items in your inventory." -command-ext: "&fBy the will of Maxlego08, you no longer burn." command-near-empty: "No player near to you." command-near-player: "&fPlayers near to you&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7You played&8: %playtime%" - "&7Current session&8: %playtime_session%" @@ -297,6 +308,7 @@ description-tp-all: "Teleport all players to your position" description-god: "Toggle god mode" description-vanish: "Toggle vanish mode" description-heal: "Heal a player" +description-lighting: "Strike a player with lightning" description-more: "Get more items" description-tp-world: "Teleport to another world" description-trash: "Open a trash can" diff --git a/src/main/resources/messages/messages_de.yml b/src/main/resources/messages/messages_de.yml index 7d236840..230732ab 100644 --- a/src/main/resources/messages/messages_de.yml +++ b/src/main/resources/messages/messages_de.yml @@ -59,6 +59,8 @@ command-gamemode-invalid: "Du musst einen gültigen Spieler angeben." # Wetterbefehle +command-time-error: "Du musst eine Welt angeben." +command-time-already-changing: "Die Zeit ändert sich bereits in &f%world%." command-day: "&fDu hast gerade &eTageslicht&f in die Welt %world%&f gebracht." command-night: "&fDu hast gerade &eNacht&f in die Welt %world%&f gebracht." command-sun: "&fDu hast gerade die &eSonne&f in die Welt %world%&f gebracht." @@ -80,11 +82,21 @@ command-night-vision-enable: "&7Nachtsicht aktiviert &7für &f%player%< command-night-vision-disable: "&7Nachtsicht deaktiviert &7für &f%player%." command-phantoms-enable: "&7Phantom-Spawn aktiviert &7für &f%player%." command-phantoms-disable: "&7Phantom-Spawn deaktiviert &7für &f%player%." +command-ext-sender: "&7Du hast den Spieler &f%player%&7 gelöscht." +command-ext-receiver: "Du brennst jetzt nicht mehr." +command-ext-error: "Du kannst keinen toten Spieler löschen!" +command-heal-all: "&7Du hast alle Spieler auf dem Server geheilt." command-heal-sender: "&7Du hast gerade den Spieler &f%player%&7 geheilt." command-heal-receiver: "Du wurdest geheilt." command-heal-error: "Du kannst niemanden heilen, der tot ist!" +command-lighting-all: "&7Du hast gerade alle Spieler mit einem Blitz getroffen." +command-lighting: "&7Du hast gerade einen Blitz an der Zielposition beschworen." +command-lighting-sender: "&7Du hast gerade einen Blitz an der Position von &f%player%&7 beschworen." +command-lighting-receiver: "&cDu wurdest vom Blitz getroffen." +command-lighting-error: "Du kannst keinen toten Spieler mit einem Blitz treffen!" command-more-error: "Du kannst diesen Befehl nicht auf das aktuelle Item in der Hand anwenden." command-more-success: "&7Du hast dein Item auf &f64&7 gesetzt." +command-feed-all: "&7Du hast alle Spieler auf dem Server gesättigt." command-feed-sender: "&7Du hast gerade den Spieler &f%player%&7 gesättigt." command-feed-receiver: "Du wurdest gesättigt." command-feed-error: "Du kannst niemanden sättigen, der tot ist!" @@ -116,10 +128,9 @@ command-repair-error: "Das Item in deiner Hand kann nicht repariert werde command-repair-success: "Du hast gerade das Item in deiner Hand repariert." command-repair-all-error: "Du hast keine Items zum Reparieren." command-repair-all-success: "Du hast gerade alle Items in deinem Inventar repariert." -command-ext: "&fDurch den Willen von Maxlego08 brennst du nicht mehr." command-near-empty: "Keine Spieler in deiner Nähe." command-near-player: "&fSpieler in deiner Nähe&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7Du hast gespielt&8: %playtime%" - "&7Aktuelle Sitzung&8: %playtime_session%" @@ -276,6 +287,7 @@ description-tp-all: "Alle Spieler zu deiner Position teleportieren" description-god: "Gottmodus ein- oder ausschalten" description-vanish: "Vanish-Modus ein- oder ausschalten" description-heal: "Einen Spieler heilen" +description-lighting: "Treffe einen Spieler mit Blitz" description-more: "Mehr Gegenstände erhalten" description-tp-world: "In eine andere Welt teleportieren" description-trash: "Mülleimer öffnen" diff --git a/src/main/resources/messages/messages_es.yml b/src/main/resources/messages/messages_es.yml index 79fee004..cbd3dcd3 100644 --- a/src/main/resources/messages/messages_es.yml +++ b/src/main/resources/messages/messages_es.yml @@ -51,6 +51,8 @@ command-gamemode: "&fModo de juego establecido a&e %gamemode%&f para &b%player%& command-gamemode-invalid: "Necesitas especificar un jugador válido." # Comandos del clima +command-time-error: "Du musst eine Welt angeben." +command-time-already-changing: "Die Zeit ändert sich bereits in &f%world%." command-day: "&fHas traído &eluz del día&f al mundo %world%&f." command-night: "&fHas traído &enoche&f al mundo %world%&f." command-sun: "&fHas traído el &esol&f al mundo %world%&f." @@ -70,11 +72,21 @@ command-night-vision-enable: "&7Visión nocturna habilitada &7para &f%p command-night-vision-disable: "&7Visión nocturna deshabilitada &7para &f%player%." command-phantoms-enable: "&7Generación de fantasmas habilitada &7para &f%player%." command-phantoms-disable: "&7Generación de fantasmas deshabilitada &7para &f%player%." +command-ext-sender: "&7Acabas de apagar al jugador &f%player%&7." +command-ext-receiver: "Ya no estás en llamas." +command-ext-error: "¡No puedes apagar a alguien que está muerto!" +command-heal-all: "&7Has curado a todos los jugadores del servidor." command-heal-sender: "&7Acabas de curar al jugador &f%player%&7." command-heal-receiver: "Has sido curado." command-heal-error: "¡No puedes curar a alguien que está muerto!" +command-lighting-all: "&7Acabas de golpear a todos los jugadores con un rayo." +command-lighting: "&7Acabas de invocar un rayo en la ubicación seleccionada." +command-lighting-sender: "&7Acabas de invocar un rayo en la ubicación de &f%player%&7." +command-lighting-receiver: "&c¡Has sido alcanzado por un rayo!" +command-lighting-error: "¡No puedes golpear a un jugador muerto con un rayo!" command-more-error: "No puedes ejecutar esta orden con el objeto en mano." command-more-success: "&7Acabas de aumentar la cantidad de tu objeto a &f64&7." +command-feed-all: "&7Has alimentado a todos los jugadores del servidor." command-feed-sender: "&7Acabas de alimentar al jugador &f%player%&7." command-feed-receiver: "Has sido alimentado." command-feed-error: "¡No puedes alimentar a alguien que está muerto!" @@ -106,10 +118,9 @@ command-repair-error: "El objeto en tu mano no se puede reparar." command-repair-success: "Acabas de reparar el objeto en tu mano." command-repair-all-error: "No tienes ítems para reparar." command-repair-all-success: "Acabas de reparar todos los objetos en tu inventario." -command-ext: "&fPor la voluntad de Maxlego08, ya no ardes." command-near-empty: "No hay jugadores cerca de ti." command-near-player: "&fJugadores cercanos a ti&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7Has jugado&8: %playtime%" - "&7Sesión actual&8: %playtime_session%" @@ -258,6 +269,7 @@ description-tp-all: "Teletransportar a todos los jugadores a tu posición" description-god: "Activar/Desactivar el modo dios" description-vanish: "Activar/Desactivar el modo vanish" description-heal: "Curar a un jugador" +description-lighting: "Golpea a un jugador con un rayo" description-more: "Obtener más artículos" description-tp-world: "Teletransportarse a otro mundo" description-trash: "Abrir una papelera" diff --git a/src/main/resources/messages/messages_fr.yml b/src/main/resources/messages/messages_fr.yml index e7814341..1c8306b5 100644 --- a/src/main/resources/messages/messages_fr.yml +++ b/src/main/resources/messages/messages_fr.yml @@ -52,6 +52,8 @@ command-gamemode: "&fMode de jeu&e %gamemode%&f défini pour &b%player%&f." command-gamemode-invalid: "Vous devez spécifier un joueur valide." # Commandes de météo +command-time-error: "Tu dois indiquer un monde." +command-time-already-changing: "Le temps est déjà en train de changer dans &f%world%." command-day: "&fVous venez d'apporter la &elumière du jour&f dans le monde %world%&f." command-night: "&fVous venez d'apporter la &enuit&f dans le monde %world%&f." command-sun: "&fVous venez d'apporter le &esoleil&f dans le monde %world%&f." @@ -71,11 +73,21 @@ command-night-vision-enable: "&7Vision nocturne activé &7pour &f%playe command-night-vision-disable: "&7Vision nocturne désactivé &7pour &f%player%." command-phantoms-enable: "&7Apparition des fantômes activée &7pour &f%player%." command-phantoms-disable: "&7Apparition des fantômes désactivée &7pour &f%player%." +command-ext-sender: "&7Tu as éteint le joueur &f%player%&7." +command-ext-receiver: "Tu ne brûles plus." +command-ext-error: "Impossible d’éteindre un joueur mort !" +command-heal-all: "&7Tu as soigné tous les joueurs du serveur." command-heal-sender: "&7Vous venez de soigner le joueur &f%player%&7." command-heal-receiver: "Vous avez été soigné." command-heal-error: "Vous ne pouvez pas soigner quelqu'un qui est mort !" +command-lighting-all: "&7Tu viens de frapper tous les joueurs avec la foudre." +command-lighting: "&7Tu as invoqué la foudre à l’emplacement ciblé." +command-lighting-sender: "&7Tu as invoqué la foudre à l’emplacement de &f%player%&7." +command-lighting-receiver: "&cTu as été frappé par la foudre !" +command-lighting-error: "Impossible de frapper un joueur mort avec la foudre !" command-more-error: "Vous ne pouvez pas effectuer cette commande sur l'objet en main." command-more-success: "&7Vous venez de mettre votre objet à &f64&7." +command-feed-all: "&7Tu as nourri tous les joueurs du serveur." command-feed-sender: "&7Vous venez de nourrir le joueur &f%player%&7." command-feed-receiver: "Vous avez été nourri." command-feed-error: "Vous ne pouvez pas nourrir quelqu'un qui est mort !" @@ -119,10 +131,9 @@ command-repair-error: "L'objet dans votre main ne peut pas être réparé command-repair-success: "Vous venez de réparer l'objet dans votre main." command-repair-all-error: "Vous n'avez aucun objet à réparer." command-repair-all-success: "Vous venez de réparer tous les objets dans votre inventaire." -command-ext: "&fPar la volonté de Maxlego08, vous ne brûlez plus." command-near-empty: "Aucun joueur à proximité de vous." command-near-player: "&fJoueurs à proximité de vous&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7Vous avez joué&8: %playtime%" - "&7Session en cours&8: %playtime_session%" @@ -292,6 +303,7 @@ description-tp-all: "Téléporter tous les joueurs à votre position" description-god: "Activer/désactiver le mode divin" description-vanish: "Activer/désactiver le mode vanish" description-heal: "Soigner un joueur" +description-lighting: "Frapper un joueur avec la foudre" description-more: "Obtenir plus d'objets" description-tp-world: "Se téléporter vers un autre monde" description-trash: "Ouvrir une poubelle" diff --git a/src/main/resources/messages/messages_it.yml b/src/main/resources/messages/messages_it.yml index a533c058..b5fb5784 100644 --- a/src/main/resources/messages/messages_it.yml +++ b/src/main/resources/messages/messages_it.yml @@ -53,6 +53,8 @@ command-gamemode-invalid: "Giocatore non valido." # Weather commands +command-time-error: "Devi specificare un mondo." +command-time-already-changing: "Il tempo sta già cambiando in &f%world%." command-day: "&fHai fatto diventare &egiorno&f nel mondo %world%&f." command-night: "&ffHai fatto diventare &enightfall&f nel mondo %world%&f." command-sun: "&ffHai fatto diventare &esun&f nel mondo %world%&f." @@ -73,11 +75,21 @@ command-night-vision-enable: "&7Visione notturna abilitata &7per &f%pla command-night-vision-disable: "&7Visione notturna disabilitata &7per &f%player%." command-phantoms-enable: "&7Generazione dei fantasmi abilitata &7per &f%player%." command-phantoms-disable: "&7Generazione dei fantasmi disabilitata &7per &f%player%." +command-ext-sender: "&7Hai spento il fuoco del giocatore &f%player%&7." +command-ext-receiver: "Non stai più bruciando." +command-ext-error: "Non puoi spegnere qualcuno che è morto!" +command-heal-all: "&7Hai curato tutti i giocatori del server." command-heal-sender: "&7Hai appena curato &f%player%&7." command-heal-receiver: "Sei appena stato curato." command-heal-error: "Non puoi curare qualcuno che è morto!" +command-lighting-all: "&7Hai appena colpito tutti i giocatori con un fulmine." +command-lighting: "&7Hai appena evocato un fulmine nella posizione selezionata." +command-lighting-sender: "&7Hai appena evocato un fulmine sulla posizione di &f%player%&7." +command-lighting-receiver: "&cSei stato colpito da un fulmine!" +command-lighting-error: "Non puoi colpire un giocatore morto con un fulmine!" command-more-error: "You cannot make this order in item in hand." command-more-success: "&7You just put your item to &f64&7." +command-feed-all: "&7Hai sfamato tutti i giocatori del server." command-feed-sender: "&7Hai appena sfamato &f%player%&7." command-feed-receiver: "Sei stato sfamato." command-feed-error: "Non puoi dar da mangiare a giocatori morti!" @@ -108,10 +120,9 @@ command-repair-error: "L'oggetto che stai tenendo non può essere riparat command-repair-success: "Hai riparato l'oggetto che stai tenendo in mano." command-repair-all-error: "Non hai nessun oggetto da riparare." command-repair-all-success: "Hai appena riparato tutti gli oggetti nel tuo inventario." -command-ext: "&fPer il volere di Maxlego08, non bruci più." command-near-empty: "Nessun giocatore in vicinanza." command-near-player: "&fGiocatori vicini a te&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7You played&8: %playtime%" - "&7Current session&8: %playtime_session%" @@ -254,6 +265,7 @@ description-tpa-cancel: "Cancella una richiesta di teletrasporto" description-god: "Attiva o disattiva la modalità God" description-vanish: "Attiva o disattiva la modalità vanish" description-heal: "Cura un giocatore" +description-lighting: "Colpisci un giocatore con un fulmine" description-more: "Ottieni più oggetti" description-tp-world: "Teletrasportati in un altro mondo" description-trash: "Apri il cestino della spazzatura" diff --git a/src/main/resources/messages/messages_nl.yml b/src/main/resources/messages/messages_nl.yml index 31d96865..22900002 100644 --- a/src/main/resources/messages/messages_nl.yml +++ b/src/main/resources/messages/messages_nl.yml @@ -53,6 +53,8 @@ command-gamemode-invalid: "Je moet een geldige speler specificeren." # Weer commando's +command-time-error: "Je moet een wereld opgeven." +command-time-already-changing: "De tijd verandert al in &f%world%." command-day: "&fJe hebt zojuist &edaglicht&f gebracht in de wereld %world%&f." command-night: "&fJe hebt zojuist &enacht&f gebracht in de wereld %world%&f." command-sun: "&fJe hebt zojuist de &ezon&f gebracht in de wereld %world%&f." @@ -73,11 +75,21 @@ command-night-vision-enable: "&7Night vision ingeschakeld &7voor &f%pla command-night-vision-disable: "&7Night vision uitgeschakeld &7voor &f%player%." command-phantoms-enable: "&7Phantom-spawn ingeschakeld &7voor &f%player%." command-phantoms-disable: "&7Phantom-spawn uitgeschakeld &7voor &f%player%." +command-ext-sender: "&7Je hebt de speler &f%player%&7 geblust." +command-ext-receiver: "Je staat niet meer in brand." +command-ext-error: "Je kunt geen dode speler blussen!" +command-heal-all: "&7Je hebt alle spelers op de server genezen." command-heal-sender: "&7Je hebt zojuist de speler &f%player%&7 genezen." command-heal-receiver: "Je bent genezen." command-heal-error: "Je kunt iemand die dood is niet genezen!" +command-lighting-all: "&7Je hebt zojuist alle spelers met bliksem getroffen." +command-lighting: "&7Je hebt zojuist bliksem op de geselecteerde locatie opgeroepen." +command-lighting-sender: "&7Je hebt zojuist bliksem op de locatie van &f%player%&7 opgeroepen." +command-lighting-receiver: "&cJe bent door de bliksem getroffen." +command-lighting-error: "Je kunt een dode speler niet met bliksem treffen!" command-more-error: "Je kunt dit commando niet uitvoeren zonder een item in de hand." command-more-success: "&7Je hebt je item zojuist op &f64&7 gezet." +command-feed-all: "&7Je hebt alle spelers op de server gevoed." command-feed-sender: "&7Je hebt zojuist de speler &f%player%&7 gevoed." command-feed-receiver: "Je bent gevoed." command-feed-error: "Je kunt iemand die dood is niet voeden!" @@ -121,10 +133,9 @@ command-repair-error: "Het item in je hand kan niet gerepareerd worden." command-repair-success: "Je hebt zojuist het item in je hand gerepareerd." command-repair-all-error: "Je hebt geen items om te repareren." command-repair-all-success: "Je hebt zojuist alle items in je inventaris gerepareerd." -command-ext: "&fDoor de wil van Maxlego08 brand je niet langer." command-near-empty: "Er is geen speler in de buurt van jou." command-near-player: "&fSpelers in de buurt van jou&7:%players%" -command-near-info: " &7%player% &8(&e%distance%m&8)" +command-near-info: "&6%direction% &7%player% &8(&e%distance%m&8)" command-play-time: - "&7Totale Speeltijd&8: %playtime%" - "&7Huidige Sessie&8: %playtime_session%" @@ -297,6 +308,7 @@ description-tp-all: "Teleport alle spelers naar je positie" description-god: "Schakel godmodus in of uit" description-vanish: "Schakel vanishmodus in of uit" description-heal: "Genees een speler" +description-lighting: "Colpisci un giocatore con un fulmine" description-more: "Krijg meer items" description-tp-world: "Teleporteer naar een andere wereld" description-trash: "Open een prullenbak"