diff --git a/src/main/java/me/makkuusen/timing/system/TimingSystemConfiguration.java b/src/main/java/me/makkuusen/timing/system/TimingSystemConfiguration.java index 60357b41..de2bffd0 100644 --- a/src/main/java/me/makkuusen/timing/system/TimingSystemConfiguration.java +++ b/src/main/java/me/makkuusen/timing/system/TimingSystemConfiguration.java @@ -35,6 +35,7 @@ public class TimingSystemConfiguration { private Integer pushToPassFullChargeTime; private Double pushToPassForwardAccel; private Integer pushToPassStartingCharge; + private Boolean pushToPassParticlesToggle; private final boolean frostHexAddOnEnabled; private final boolean medalsAddOnEnabled; private final boolean medalsShowNextMedal; @@ -82,6 +83,7 @@ public class TimingSystemConfiguration { pushToPassFullChargeTime = plugin.getConfig().getInt("pushtopass.fullChargeTime", 60000); pushToPassForwardAccel = plugin.getConfig().getDouble("pushtopass.forwardAccel", 0.05); pushToPassStartingCharge = plugin.getConfig().getInt("pushtopass.startingCharge", 0); + pushToPassParticlesToggle = plugin.getConfig().getBoolean("pushtopass.particlestoggle", true); frostHexAddOnEnabled = plugin.getConfig().getBoolean("frosthexaddon.enabled"); medalsAddOnEnabled = plugin.getConfig().getBoolean("medalsaddon.enabled"); medalsShowNextMedal = plugin.getConfig().getBoolean("medalsaddon.showNextMedal"); @@ -172,6 +174,10 @@ public void setPushToPassStartingCharge(int value) { pushToPassStartingCharge = value; } + public void setPushToPassParticlesToggle(boolean value) { + pushToPassParticlesToggle = value; + } + public T getDatabaseType() { // This could maybe be improved but I have no idea :P return (T) databaseType; diff --git a/src/main/java/me/makkuusen/timing/system/commands/CommandTimingSystem.java b/src/main/java/me/makkuusen/timing/system/commands/CommandTimingSystem.java index a3a1d5bc..98a58b92 100644 --- a/src/main/java/me/makkuusen/timing/system/commands/CommandTimingSystem.java +++ b/src/main/java/me/makkuusen/timing/system/commands/CommandTimingSystem.java @@ -15,6 +15,7 @@ import me.makkuusen.timing.system.track.tags.TrackTag; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextColor; +import org.bukkit.block.data.type.Switch; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -171,6 +172,14 @@ public static void onPushToPassStartingChargeChange(CommandSender sender, int va Text.send(sender, Success.SAVED); } + @Subcommand("pushtopass|p2p particlestoggle") + @CommandCompletion("") + @CommandPermission("%permissiontimingsystem_pushtopass_set_particlestoggle") + public static void onPushToPassParticlesToggle(CommandSender sender, boolean value) { + TimingSystem.configuration.setPushToPassParticlesToggle(value); + Text.send(sender, Success.SAVED); + } + @Subcommand("shortname") @CommandCompletion(" @players") @CommandPermission("%permissiontimingsystem_shortname_others") diff --git a/src/main/java/me/makkuusen/timing/system/drs/PushToPass.java b/src/main/java/me/makkuusen/timing/system/drs/PushToPass.java index 65ca4fea..8d6cb8b4 100644 --- a/src/main/java/me/makkuusen/timing/system/drs/PushToPass.java +++ b/src/main/java/me/makkuusen/timing/system/drs/PushToPass.java @@ -10,6 +10,8 @@ import me.makkuusen.timing.system.participant.Driver; import me.makkuusen.timing.system.track.Track; import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; @@ -32,6 +34,8 @@ public class PushToPass { private static final Map preP2PForwardAccel = new HashMap<>(); private static final short PACKET_ID_SET_FORWARD_ACCELERATION = 11; private static final long TOGGLE_COOLDOWN_MS = 500; + private static final Map trailTaskIds = new HashMap<>(); + private static final Long TRAIL_PARTICLE_TICK_SPACING = 1L; /** * Activates push to pass for a player if they have charge available @@ -58,6 +62,7 @@ public static void activatePushToPass(Player player) { preP2PForwardAccel.put(playerId, originalAccel); data.setActive(true); + startTrail(player); double forwardAccel = TimingSystem.configuration.getPushToPassForwardAccel(); sendForwardAccelerationPacket(player, (float) forwardAccel); @@ -78,6 +83,7 @@ public static void deactivatePushToPass(Player player) { data.updateCharge(); data.setActive(false); + stopTrail(playerId); Float originalAccel = preP2PForwardAccel.remove(playerId); if (originalAccel != null) { @@ -121,6 +127,7 @@ public static void togglePushToPass(Player player) { */ public static void initializePushToPass(UUID playerId) { int startingCharge = TimingSystem.configuration.getPushToPassStartingCharge(); + PushToPassData data = new PushToPassData(startingCharge); pushToPassPlayers.put(playerId, data); @@ -134,6 +141,7 @@ public static void initializePushToPass(UUID playerId) { * Cleans up push to pass data for a player */ public static void cleanupPlayer(UUID playerId) { + stopTrail(playerId); PushToPassData data = pushToPassPlayers.remove(playerId); toggleCooldowns.remove(playerId); preP2PForwardAccel.remove(playerId); @@ -237,6 +245,62 @@ public static void updateAllCharges() { } } + /** + * Activates particle trail for a player + */ + private static void startTrail(Player player) { + UUID playerId = player.getUniqueId(); + if (trailTaskIds.containsKey(playerId) || !TimingSystem.configuration.getPushToPassParticlesToggle()) { + return; + } + + Color teamColor = EventDatabase.getDriverFromRunningHeat(playerId) + .map(driver -> hexToColor(driver.getTPlayer().getSettings().getHexColor())) + .orElse(Color.fromRGB(255, 100, 255)); + + int taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask( + TimingSystem.getPlugin(), + () -> { + boolean particleToggle = TimingSystem.configuration.getPushToPassParticlesToggle(); + if (!player.isOnline() || !particleToggle) { + stopTrail(playerId); + return; + } + spawnTrailParticles(player, teamColor); + }, + 0L, + TRAIL_PARTICLE_TICK_SPACING + ); + + trailTaskIds.put(playerId, taskId); + } + + /** + * Deactivates particle trail for a player + */ + private static void stopTrail(UUID playerId) { + Integer taskId = trailTaskIds.remove(playerId); + if (taskId != null) { + Bukkit.getScheduler().cancelTask(taskId); + } + } + + /** + * Spawns Particle Trail for Player + */ + private static void spawnTrailParticles(Player player, Color color) { + var location = player.getLocation(); + var direction = location.getDirection().normalize().multiply(-0.5); + var spawnLoc = location.clone().add(direction).add(0, 0.3, 0); + + player.getWorld().spawnParticle( + Particle.DUST, + spawnLoc, + 3, 0.1, 0.1, 0.1, 0.0, + new Particle.DustOptions(color, 1.5f) + ); + } + private static void updateDriverScoreboard(UUID playerId) { var maybeDriver = TimingSystemAPI.getDriverFromRunningHeat(playerId); if (maybeDriver.isPresent()) { @@ -284,6 +348,19 @@ public static void reDisplayBossBar(Player player) { } } + private static Color hexToColor(String hex) { + try { + if (hex == null || hex.isEmpty()) return Color.WHITE; + hex = hex.replace("#", ""); + int r = Integer.parseInt(hex.substring(0, 2), 16); + int g = Integer.parseInt(hex.substring(2, 4), 16); + int b = Integer.parseInt(hex.substring(4, 6), 16); + return Color.fromRGB(r, g, b); + } catch (Exception e) { + return Color.WHITE; + } + } + @Getter private static class PushToPassData { private double chargePercent; diff --git a/src/main/java/me/makkuusen/timing/system/permissions/PermissionTimingSystem.java b/src/main/java/me/makkuusen/timing/system/permissions/PermissionTimingSystem.java index 67d1f6a2..4f7d750f 100644 --- a/src/main/java/me/makkuusen/timing/system/permissions/PermissionTimingSystem.java +++ b/src/main/java/me/makkuusen/timing/system/permissions/PermissionTimingSystem.java @@ -23,6 +23,7 @@ public enum PermissionTimingSystem implements Permissions { PUSHTOPASS_SET_FULLCHARGETIME, PUSHTOPASS_SET_FORWARDACCEL, PUSHTOPASS_SET_STARTINGCHARGE, + PUSHTOPASS_SET_PARTICLETOGGLE, COLOR_SET_NAMED, COLOR_SET_HEX, GHOST; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5b73d371..55e2db6e 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -76,6 +76,7 @@ pushtopass: fullChargeTime: 60000 forwardAccel: 0.05 startingCharge: 0 + particlesToggle: true sql: databaseType: SQLite # Options: MySQL, MariaDB, SQLite host: '127.0.0.1' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fd68c52e..9f797451 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -197,6 +197,7 @@ permissions: timingsystem.pushtopass.set.fullchargetime: true timingsystem.pushtopass.set.forwardaccel: true timingsystem.pushtopass.set.startingcharge: true + timingsystem.pushtopass.set.particlestoggle: true timingsystem.team.create: true timingsystem.team.delete: true timingsystem.team.manage: true