Squashed commit of the following:

commit 5bd49a4e2feebe07a75ffbca440bf23ac5cfa8ea
Author: Piecuuu <56731916+Piecuuu@users.noreply.github.com>
Date:   Mon Feb 23 18:21:46 2026 +0100

    commands for best ks

commit 251cec40ac405d21e080f2a4c2638c8803237b43
Author: Piecuuu <56731916+Piecuuu@users.noreply.github.com>
Date:   Mon Feb 23 18:21:35 2026 +0100

    add ks + best ks placeholder (for tablist)

commit 713e30b19bc52db3ed77f21854d6566cd6ea8c6b
Author: Piecuuu <56731916+Piecuuu@users.noreply.github.com>
Date:   Mon Feb 23 16:53:36 2026 +0100

    refactor + best ks
This commit is contained in:
Piecuuu 2026-02-23 18:23:08 +01:00
parent 3fe1638e41
commit 21577f8e1d
4 changed files with 145 additions and 19 deletions

View file

@ -32,6 +32,14 @@ public class KillstreakCommand {
.then(Commands.argument("profile", ArgumentTypes.playerProfiles()) .then(Commands.argument("profile", ArgumentTypes.playerProfiles())
.requires(s -> s.getSender().hasPermission("ks.admin.get")) .requires(s -> s.getSender().hasPermission("ks.admin.get"))
.executes(KillstreakCommand::getOtherKillstreak) .executes(KillstreakCommand::getOtherKillstreak)
.then(Commands.literal("best")
.requires(s -> s.getSender().hasPermission("ks.admin.get.best"))
.executes(KillstreakCommand::getOtherBestKillstreak)
)
)
.then(Commands.literal("best")
.requires(s -> s.getSender().hasPermission("ks.get.best"))
.executes(KillstreakCommand::getOwnBestKillstreak)
) )
) )
.then(Commands.literal("set") .then(Commands.literal("set")
@ -42,7 +50,12 @@ public class KillstreakCommand {
) )
.then(Commands.literal("reset") .then(Commands.literal("reset")
.requires(s -> s.getSender().hasPermission("ks.admin.reset")) .requires(s -> s.getSender().hasPermission("ks.admin.reset"))
.then(playerArgument.executes(KillstreakCommand::resetKillstreak)) .then(playerArgument
.executes(KillstreakCommand::resetKillstreak)
.then(Commands.literal("best")
.executes(KillstreakCommand::resetBestKillstreak)
)
)
); );
return ks.build(); return ks.build();
@ -62,6 +75,27 @@ public class KillstreakCommand {
return offlinePlayer; return offlinePlayer;
} }
private static int getOwnBestKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
final Entity entity = ctx.getSource().getExecutor();
if(!(entity instanceof Player p)) return 0;
KillstreakManager km = KillstreakManager.getInstance();
final long killstreak = km.getBestKillstreak(p);
ctx.getSource().getSender().sendMessage(km.getBestKillstreakComponent(killstreak));
return 1;
}
private static int getOtherBestKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
final OfflinePlayer offlinePlayer = getOfflinePlayerFromCtx(ctx);
KillstreakManager km = KillstreakManager.getInstance();
final long killstreak = km.getBestKillstreak(offlinePlayer);
ctx.getSource().getSender().sendMessage(km.getBestKillstreakComponent(killstreak));
return 1;
}
private static int resetKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException { private static int resetKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
final Player player = getFirstPlayerFromCtx(ctx); final Player player = getFirstPlayerFromCtx(ctx);
KillstreakManager km = KillstreakManager.getInstance(); KillstreakManager km = KillstreakManager.getInstance();
@ -72,6 +106,16 @@ public class KillstreakCommand {
return 1; return 1;
} }
private static int resetBestKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
final Player player = getFirstPlayerFromCtx(ctx);
KillstreakManager km = KillstreakManager.getInstance();
km.setBestKillstreak(player, 0L);
ctx.getSource().getSender().sendMessage(km.getBestKillstreakComponent(0L));
return 1;
}
private static int setKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException { private static int setKillstreak(CommandContext<CommandSourceStack> ctx) throws CommandSyntaxException {
final Player player = getFirstPlayerFromCtx(ctx); final Player player = getFirstPlayerFromCtx(ctx);
final long killstreak = LongArgumentType.getLong(ctx, "killstreak"); final long killstreak = LongArgumentType.getLong(ctx, "killstreak");

View file

@ -2,6 +2,9 @@ package pl.piecuu.killstreak;
import me.clip.placeholderapi.expansion.PlaceholderExpansion; import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -45,8 +48,44 @@ public class KillstreakExpansion extends PlaceholderExpansion {
final Component output = km.getKillstreakComponent(killstreak); final Component output = km.getKillstreakComponent(killstreak);
return MiniMessage.miniMessage().serialize(output); return MiniMessage.miniMessage().serialize(output);
} else if(identifier.equalsIgnoreCase("killstreak_tab")) {
KillstreakManager km = KillstreakManager.getInstance();
final long killstreak = km.getInvisKillstreak(p);
final long bestKillstreak = km.getBestKillstreak(p);
final Component bestComponent = km.getBestKillstreakComponent(bestKillstreak);
if(killstreak == 0 && bestKillstreak > 0)
return MiniMessage.miniMessage().serialize(bestComponent);
else if(killstreak == 0) return "";
Component output = km.getKillstreakComponent(killstreak);
if(bestKillstreak > killstreak) {
output = output
.appendSpace()
.append(Component.text("|", TextColor.color(
KillstreakExpansion.mix(
output.children().getLast().color(),
bestComponent.children().getFirst().color(),
0.6
)
)).decoration(TextDecoration.BOLD, true))
.appendSpace()
.append(bestComponent);
}
return MiniMessage.miniMessage().serialize(output);
} }
return null; return null;
} }
private static TextColor mix(TextColor c1, TextColor c2, double ratio) {
ratio = Math.max(0, Math.min(1, ratio));
double inverse = 1.0 - ratio;
int r = (int) (c1.red() * inverse + c2.red() * ratio);
int g = (int) (c1.green() * inverse + c2.green() * ratio);
int b = (int) (c1.blue() * inverse + c2.blue() * ratio);
return TextColor.color(r, g, b);
}
} }

View file

@ -1,5 +1,7 @@
package pl.piecuu.killstreak; package pl.piecuu.killstreak;
import java.util.Map;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -8,6 +10,7 @@ import org.bukkit.persistence.PersistentDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.format.TextDecoration.State;
import pl.piecuu.invisninja.InvisNinja; import pl.piecuu.invisninja.InvisNinja;
public class KillstreakManager { public class KillstreakManager {
@ -16,6 +19,7 @@ public class KillstreakManager {
return instance; return instance;
} }
public NamespacedKey playerKillstreakKey; public NamespacedKey playerKillstreakKey;
public NamespacedKey playerBestKillstreakKey;
public NamespacedKey playerInvisKSKey; public NamespacedKey playerInvisKSKey;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -25,60 +29,95 @@ public class KillstreakManager {
instance = this; instance = this;
this.playerKillstreakKey = new NamespacedKey(plugin, "playerKillstreakKey"); this.playerKillstreakKey = new NamespacedKey(plugin, "playerKillstreakKey");
this.playerInvisKSKey = new NamespacedKey(plugin, "playerInvisKSKey"); this.playerInvisKSKey = new NamespacedKey(plugin, "playerInvisKSKey");
this.playerBestKillstreakKey = new NamespacedKey(plugin, "playerBestKillstreakKey");
}
public long getBestKillstreak(OfflinePlayer player) {
return this.getLongFromPDC(player, playerBestKillstreakKey);
}
public void setBestKillstreak(Player player, long bestKillstreak) {
this.setLongFromPDC(player, playerBestKillstreakKey, bestKillstreak);
}
public void normaliseBestKillstreak(Player player) {
long killstreak = this.getKillstreak(player);
this.setBestKillstreak(player, killstreak);
} }
public void setKillstreak(Player player, long streak) { public void setKillstreak(Player player, long streak) {
if(streak < 0) return; this.setLongFromPDC(player, playerKillstreakKey, streak);
player.getPersistentDataContainer().set(playerKillstreakKey, PersistentDataType.LONG, streak);
if(Killstreak.getInvisNinja() == null || !InvisNinja.isPlayerInvisible(player)) {
setInvisKillstreak(player, streak);
}
} }
public void setInvisKillstreak(Player player, long streak) { public void setInvisKillstreak(Player player, long streak) {
if(streak < 0) return; this.setLongFromPDC(player, playerInvisKSKey, streak);
player.getPersistentDataContainer().set(playerInvisKSKey, PersistentDataType.LONG, streak);
} }
public long getInvisKillstreak(Player player) { public long getInvisKillstreak(Player player) {
if(Killstreak.getInvisNinja() == null || !InvisNinja.isPlayerInvisible(player)) return getKillstreak(player); final long realKS = this.getLongFromPDC(player, playerInvisKSKey);
return player.getPersistentDataContainer().getOrDefault(playerInvisKSKey, PersistentDataType.LONG, 0L); if(Killstreak.getInvisNinja() == null || !InvisNinja.isPlayerInvisible(player)) {
long ks = this.getKillstreak(player);
if(ks > this.getBestKillstreak(player)) this.normaliseBestKillstreak(player);
this.setInvisKillstreak(player, ks);
return ks;
}
return realKS;
} }
public long getKillstreak(OfflinePlayer player) { public long getKillstreak(OfflinePlayer player) {
return player.getPersistentDataContainer().getOrDefault(playerKillstreakKey, PersistentDataType.LONG, 0L); return this.getLongFromPDC(player, playerKillstreakKey);
} }
public long increaseKillstreak(Player player, long amount) { public long increaseKillstreak(Player player, long amount) {
long killstreak = this.getKillstreak(player); long killstreak = this.getKillstreak(player);
killstreak += amount; killstreak += amount;
this.setKillstreak(player, killstreak); this.setKillstreak(player, killstreak);
return killstreak; return killstreak;
} }
public void resetKillstreak(Player player) { public void resetKillstreak(Player player) {
setKillstreak(player, 0L); this.setKillstreak(player, 0L);
} }
private long getLongFromPDC(OfflinePlayer player, NamespacedKey key) {
return player.getPersistentDataContainer().getOrDefault(key, PersistentDataType.LONG, 0L);
}
private void setLongFromPDC(Player player, NamespacedKey key, long value) {
if(value < 0) return;
player.getPersistentDataContainer().set(key, PersistentDataType.LONG, value);
}
public boolean shouldAnnounceKillstreak(long killstreak, Player p) { public boolean shouldAnnounceKillstreak(long killstreak, Player p) {
if(Killstreak.getInvisNinja() != null && InvisNinja.isPlayerInvisible(p)) return false; if(Killstreak.getInvisNinja() != null && InvisNinja.isPlayerInvisible(p)) return false;
return killstreak >= 5 && killstreak % 5 == 0;
return (killstreak >= 5 && killstreak % 5 == 0);
} }
public int getColor(long killstreak) { public int getColor(long killstreak) {
if(killstreak == 0) return 0xffffff; if(killstreak == 0) return 0xffffff;
else if(killstreak == 1) return 0xfbffa8; // washed out yellow else if(killstreak == 1) return 0xfbffa8; // washed out yellow
else if(killstreak < 5) return 0xfae92f; // yellow else if(killstreak < 5) return 0xfae92f; // yellow
else if(killstreak < 10) return 0xe6aa1e; // orange orange else if(killstreak < 10) return 0xe6aa1e; // orange orange
else if(killstreak < 15) return 0xe6711e; // darker orange else if(killstreak < 15) return 0xe6711e; // darker orange
else if(killstreak < 20) return 0xf54320; // intense red else if(killstreak < 20) return 0xf54320; // intense red
else if(killstreak < 30) return 0xde5291; // some fuckass pink else if(killstreak < 30) return 0xde5291; // some fuckass pink
else return 0xde1ff0; // very intensive magenta else return 0xde1ff0; // very intensive magenta
} }
public Component getKillstreakComponent(long killstreak) { public Component getKillstreakComponent(long killstreak) {
return Component.text("🔥", TextColor.color(0xff931f)) // 0xd18449 return Component.text("🔥", TextColor.color(0xff931f)) // 0xd18449
.append(Component.text(killstreak).color(TextColor.color(this.getColor(killstreak))).decoration(TextDecoration.BOLD, true)); .append(Component.text(killstreak).color(TextColor.color(this.getColor(killstreak))).decoration(TextDecoration.BOLD, true));
} }
public Component getBestKillstreakComponent(long bestKillstreak) {
return Component.text("🔥", TextColor.color(0x9c9c9c))
.append(Component.text(bestKillstreak).color(TextColor.color(0xababab)))
.decorations(Map.of(
TextDecoration.STRIKETHROUGH, State.TRUE,
TextDecoration.BOLD, State.TRUE
));
}
} }

View file

@ -7,8 +7,12 @@ api-version: '1.21.11'
permissions: permissions:
ks.get: ks.get:
default: true default: true
ks.get.best:
default: true
ks.admin.get: ks.admin.get:
default: op default: op
ks.admin.get.best:
default: op
ks.admin.set: ks.admin.set:
default: op default: op
ks.admin.reset: ks.admin.reset: