Add ghast speed command with configurable speed levels

This commit is contained in:
akastijn 2025-07-20 04:36:02 +02:00
parent d6d7269fee
commit 7f6d4c4b36
8 changed files with 267 additions and 1 deletions

View File

@ -1,6 +1,7 @@
package com.alttd.playerutils;
import com.alttd.playerutils.commands.PlayerUtilsCommand;
import com.alttd.playerutils.commands.playerutils_subcommands.GhastSpeed;
import com.alttd.playerutils.commands.playerutils_subcommands.RotateBlock;
import com.alttd.playerutils.config.Config;
import com.alttd.playerutils.config.KeyStorage;
@ -47,6 +48,10 @@ public final class PlayerUtils extends JavaPlugin {
RotateBlockEvent rotateBlockEvent = new RotateBlockEvent(logger);
pluginManager.registerEvents(rotateBlockEvent, this);
playerUtilsCommand.addSubCommand(new RotateBlock(rotateBlockEvent));
GhastSpeedEvent ghastSpeedEvent = new GhastSpeedEvent(logger);
pluginManager.registerEvents(ghastSpeedEvent, this);
playerUtilsCommand.addSubCommand(new GhastSpeed(logger, ghastSpeedEvent));
}
public void reloadConfigs() {

View File

@ -0,0 +1,11 @@
package com.alttd.playerutils.commands.argument_parser;
import org.bukkit.command.CommandSender;
import java.util.Optional;
public interface ArgumentParser<T> {
Optional<T> parse(CommandSender commandSender, String argument);
}

View File

@ -0,0 +1,23 @@
package com.alttd.playerutils.commands.argument_parser;
import com.alttd.playerutils.config.Messages;
import com.alttd.playerutils.data_objects.GHAST_SPEED;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Optional;
public class GhastSpeedParser implements ArgumentParser<GHAST_SPEED> {
@Override
public Optional<GHAST_SPEED> parse(CommandSender commandSender, String speed) {
GHAST_SPEED ghastSpeed;
try {
ghastSpeed = GHAST_SPEED.valueOf(speed.toUpperCase());
} catch (IllegalArgumentException e) {
return Optional.empty();
}
return Optional.of(ghastSpeed);
}
}

View File

@ -0,0 +1,21 @@
package com.alttd.playerutils.commands.argument_parser;
import com.alttd.playerutils.config.Messages;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Optional;
public class OnlinePlayerParser implements ArgumentParser<Player> {
@Override
public Optional<Player> parse(CommandSender commandSender, String playerName) {
Player player = commandSender.getServer().getPlayer(playerName);
if (player == null || !player.isOnline()) {
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_NOT_FOUND, Placeholder.parsed("player", playerName));
return Optional.empty();
}
return Optional.of(player);
}
}

View File

@ -0,0 +1,93 @@
package com.alttd.playerutils.commands.playerutils_subcommands;
import com.alttd.playerutils.commands.SubCommand;
import com.alttd.playerutils.commands.argument_parser.GhastSpeedParser;
import com.alttd.playerutils.config.Messages;
import com.alttd.playerutils.data_objects.GHAST_SPEED;
import com.alttd.playerutils.event_listeners.GhastSpeedEvent;
import com.alttd.playerutils.util.Logger;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HappyGhast;
import org.bukkit.entity.Player;
import java.util.*;
public class GhastSpeed extends SubCommand {
private final static GhastSpeedParser GHAST_SPEED_PARSER = new GhastSpeedParser();
private final static int GHAST_SPEED_ARG = 1;
private final Logger logger;
private final GhastSpeedEvent ghastSpeedEvent;
public GhastSpeed(Logger logger, GhastSpeedEvent ghastSpeedEvent) {
this.logger = logger;
this.ghastSpeedEvent = ghastSpeedEvent;
}
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (args.length != 2) {
return false;
}
if (!(commandSender instanceof Player player)) {
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return true;
}
Optional<GHAST_SPEED> parsedGhastSpeed = GHAST_SPEED_PARSER.parse(commandSender, args[GHAST_SPEED_ARG]);
if (parsedGhastSpeed.isEmpty()) {
return false;
}
GHAST_SPEED ghastSpeed = parsedGhastSpeed.get();
if (!(player.getVehicle() instanceof HappyGhast happyGhast)) {
commandSender.sendRichMessage(Messages.GHAST_SPEED.NOT_RIDING_A_GHAST);
return true;
}
AttributeInstance attribute = happyGhast.getAttribute(Attribute.FLYING_SPEED);
if (attribute == null) {
commandSender.sendRichMessage(Messages.GHAST_SPEED.FAILED_TO_SET_SPEED);
return true;
}
if (!commandSender.hasPermission(getPermission() + "." + ghastSpeed.name().toLowerCase())) {
commandSender.sendRichMessage(Messages.GENERIC.NO_PERMISSION,
Placeholder.parsed("permission", getPermission() + "." +
ghastSpeed.name().toLowerCase()));
return true;
}
double newSpeed = GHAST_SPEED.getSpeed(ghastSpeed);
ghastSpeedEvent.setNewSpeed(player.getUniqueId(), ghastSpeed);
attribute.setBaseValue(newSpeed);
commandSender.sendRichMessage(Messages.GHAST_SPEED.NEW_SPEED_SET_TO,
Placeholder.parsed("speed", String.valueOf(newSpeed)));
return true;
}
@Override
public String getName() {
return "ghastspeed";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
if (args.length == 2) {
return Arrays.stream(GHAST_SPEED.values())
.map(GHAST_SPEED::name)
.filter(name -> commandSender.hasPermission(
getPermission() + "." + name.toLowerCase())).toList();
}
return List.of();
}
@Override
public String getHelpMessage() {
return Messages.HELP.GHAST_SPEED;
}
}

View File

@ -1,6 +1,7 @@
package com.alttd.playerutils.config;
import com.alttd.playerutils.util.Logger;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
@ -35,6 +36,7 @@ public class Messages extends AbstractConfig {
public static String RELOAD = "<green>Reload the configs for PlayerUtils: <gold>/pu reload</gold></green>";
public static String ROTATE_BLOCK = "<green>Enable rotating blocks with a blaze rod: <gold>/pu rotateblock</gold></green>";
public static String KEY = "<green>Receive a key that you are owed: <gold>/pu key</gold></green>";
public static String GHAST_SPEED = "<green>Set the speed of a ghast: <gold>/pu ghastspeed <speed></gold></green>";
@SuppressWarnings("unused")
private static void load() {
@ -45,6 +47,7 @@ public class Messages extends AbstractConfig {
XP_CALC = config.getString(prefix, "xp-calc", XP_CALC);
RELOAD = config.getString(prefix, "reload", RELOAD);
ROTATE_BLOCK = config.getString(prefix, "rotate-block", ROTATE_BLOCK);
GHAST_SPEED = config.getString(prefix, "ghast-speed", GHAST_SPEED);
}
}
@ -157,13 +160,29 @@ public class Messages extends AbstractConfig {
}
}
public static class GHAST_SPEED {
private static final String prefix = "pu-command.ghast-speed.";
public static String NOT_RIDING_A_GHAST = "<red>You are not riding a ghast</red>";
public static String FAILED_TO_SET_SPEED = "<red>Failed to set ghast speed</red>";
public static String NEW_SPEED_SET_TO = "<green>New speed set to <speed></green>";
@SuppressWarnings("unused")
private static void load() {
NOT_RIDING_A_GHAST = config.getString(prefix, "not-riding-a-ghast", NOT_RIDING_A_GHAST);
FAILED_TO_SET_SPEED = config.getString(prefix, "failed-to-set-speed", FAILED_TO_SET_SPEED);
NEW_SPEED_SET_TO = config.getString(prefix, "new-speed-set-to", NEW_SPEED_SET_TO);
}
}
public static class BLOCK_BLOCK_USE {
private static final String prefix = "block-block-use.";
public static String BLOCKED = "<red>You are not powerful enough!</red>";
public static String BLOCKED = "<red>You are not powerful enough!</red>";
@SuppressWarnings("unused")
private static void load() {
BLOCKED = config.getString(prefix, "blocked", BLOCKED);
}
}
}

View File

@ -0,0 +1,19 @@
package com.alttd.playerutils.data_objects;
public enum GHAST_SPEED {
SLOW,
NORMAL,
FAST,
VERY_FAST,
EXTREMELY_FAST;
public static double getSpeed(GHAST_SPEED ghastSpeed) {
return switch (ghastSpeed) {
case SLOW -> 0.025;
case NORMAL -> 0.05;
case FAST -> 0.075;
case VERY_FAST -> 0.1;
case EXTREMELY_FAST -> 0.125;
};
}
}

View File

@ -0,0 +1,75 @@
package com.alttd.playerutils.event_listeners;
import com.alttd.playerutils.data_objects.GHAST_SPEED;
import com.alttd.playerutils.util.Logger;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HappyGhast;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.entity.EntityMountEvent;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.UUID;
public class GhastSpeedEvent implements Listener {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(GhastSpeedEvent.class);
private final Logger logger;
private final HashMap<UUID, GHAST_SPEED> lastSetSpeed = new HashMap<>();
public GhastSpeedEvent(Logger logger) {
this.logger = logger;
}
@EventHandler
public void onEntityMount(EntityMountEvent event) {
if (!(event.getEntity() instanceof Player player)) {
return;
}
Entity mount = event.getMount();
if (!(mount instanceof HappyGhast happyGhast)) {
return;
}
GHAST_SPEED ghastSpeed = lastSetSpeed.get(player.getUniqueId());
if (ghastSpeed == null) {
return;
}
AttributeInstance attribute = happyGhast.getAttribute(Attribute.FLYING_SPEED);
if (attribute == null) {
return;
}
attribute.setBaseValue(GHAST_SPEED.getSpeed(ghastSpeed));
}
@EventHandler
public void onEntityDismount(EntityDismountEvent event) {
if (!(event.getDismounted() instanceof HappyGhast happyGhast)) {
return;
}
if (happyGhast.getPassengers().size() >= 2) {
return;
}
AttributeInstance attribute = happyGhast.getAttribute(Attribute.FLYING_SPEED);
if (attribute == null) {
return;
}
attribute.setBaseValue(GHAST_SPEED.getSpeed(GHAST_SPEED.NORMAL));
}
public void setNewSpeed(UUID uuid, GHAST_SPEED speed) {
lastSetSpeed.put(uuid, speed);
}
}