commit 2cee7aef28874a3e93e92b5d50ffb482369b9704 Author: Piecuuu <56731916+Piecuuu@users.noreply.github.com> Date: Sat Feb 21 19:45:03 2026 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2977c0e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build/ +bin/ +.gradle/ +.vscode/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a10d331 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright 2026 Piecuu + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..6f6369a --- /dev/null +++ b/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'java' +} + +group = 'pl.piecuu' +version = '1.0' + +java { + toolchain.languageVersion = JavaLanguageVersion.of(21) +} + +repositories { + mavenCentral() + mavenLocal() + maven { + url = 'https://repo.extendedclip.com/releases/' + } +} + +dependencies { + compileOnly "pl.piecuu.jajoptak:leaf-api:1.21.11-R0.1-SNAPSHOT" + compileOnly "me.clip:placeholderapi:2.11.7" +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} diff --git a/src/main/java/pl/piecuu/killstreak/Killstreak.java b/src/main/java/pl/piecuu/killstreak/Killstreak.java new file mode 100644 index 0000000..6ecb26a --- /dev/null +++ b/src/main/java/pl/piecuu/killstreak/Killstreak.java @@ -0,0 +1,20 @@ +package pl.piecuu.killstreak; + +import org.bukkit.Bukkit; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +public class Killstreak extends JavaPlugin implements Listener { + @Override + public void onEnable() { + if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { + new KillstreakExpansion().register(); + new KillstreakManager(this); + Bukkit.getPluginManager().registerEvents(this, this); + Bukkit.getPluginManager().registerEvents(new PlayerManager(this), this); + } else { + getLogger().warning("Could not find PlaceholderAPI! This plugin is required."); + Bukkit.getPluginManager().disablePlugin(this); + } + } +} diff --git a/src/main/java/pl/piecuu/killstreak/KillstreakExpansion.java b/src/main/java/pl/piecuu/killstreak/KillstreakExpansion.java new file mode 100644 index 0000000..9cb54a7 --- /dev/null +++ b/src/main/java/pl/piecuu/killstreak/KillstreakExpansion.java @@ -0,0 +1,45 @@ +package pl.piecuu.killstreak; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import net.kyori.adventure.text.minimessage.MiniMessage; + +public class KillstreakExpansion extends PlaceholderExpansion { + @Override @NotNull + public String getAuthor() { + return "Piecuu"; + } + + @Override @NotNull + public String getIdentifier() { + return "ks"; + } + + @Override @NotNull + public String getVersion() { + return "1.0.0"; + } + + @Override + public boolean persist() { + return true; + } + + @Override + public String onPlaceholderRequest(Player p, String identifier) { + if(p == null) return null; + if(identifier.equalsIgnoreCase("killstreak")) { + KillstreakManager km = KillstreakManager.getInstance(); + final long killstreak = km.getKillstreak(p); + if(killstreak == 0) return ""; + + final Component output = km.getKillstreakComponent(killstreak); + return MiniMessage.miniMessage().serialize(output); + } + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/pl/piecuu/killstreak/KillstreakManager.java b/src/main/java/pl/piecuu/killstreak/KillstreakManager.java new file mode 100644 index 0000000..a580b5a --- /dev/null +++ b/src/main/java/pl/piecuu/killstreak/KillstreakManager.java @@ -0,0 +1,65 @@ +package pl.piecuu.killstreak; + +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.persistence.PersistentDataType; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; + +public class KillstreakManager { + private static KillstreakManager instance; + public static KillstreakManager getInstance() { + return instance; + } + public NamespacedKey playerKillstreakKey; + + private Killstreak plugin; + public KillstreakManager(Killstreak plugin) { + this.plugin = plugin; + instance = this; + this.playerKillstreakKey = new NamespacedKey(plugin, "playerKillstreakKey"); + } + + + public void setKillstreak(Player player, long streak) { + if(streak < 0) return; + player.getPersistentDataContainer().set(playerKillstreakKey, PersistentDataType.LONG, streak); + } + + public long getKillstreak(Player player) { + return player.getPersistentDataContainer().getOrDefault(playerKillstreakKey, PersistentDataType.LONG, 0L); + } + + public long increaseKillstreak(Player player, long amount) { + long killstreak = this.getKillstreak(player); + killstreak += amount; + this.setKillstreak(player, killstreak); + return killstreak; + } + + public void resetKillstreak(Player player) { + setKillstreak(player, 0L); + } + + public boolean shouldAnnounceKillstreak(long killstreak) { + return killstreak >= 5 && killstreak % 5 == 0; + } + + public int getColor(long killstreak) { + if(killstreak == 0) return 0x0; + else if(killstreak == 1) return 0x858585; // dark grey + else if(killstreak < 5) return 0xfae92f; // yellow + else if(killstreak < 10) return 0xe6aa1e; // orange orange + else if(killstreak < 15) return 0xe6711e; // darker orange + else if(killstreak < 20) return 0xf54320; // intense red + else if(killstreak < 30) return 0xde5291; // some fuckass pink + else return 0xde1ff0; // very intensive magenta + } + + public Component getKillstreakComponent(long killstreak) { + return Component.text("🔥", TextColor.color(0xff931f)) // 0xd18449 + .append(Component.text(killstreak).color(TextColor.color(this.getColor(killstreak))).decoration(TextDecoration.BOLD, true)); + } +} diff --git a/src/main/java/pl/piecuu/killstreak/PlayerManager.java b/src/main/java/pl/piecuu/killstreak/PlayerManager.java new file mode 100644 index 0000000..3506ae3 --- /dev/null +++ b/src/main/java/pl/piecuu/killstreak/PlayerManager.java @@ -0,0 +1,70 @@ +package pl.piecuu.killstreak; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.scheduler.BukkitRunnable; + +public class PlayerManager implements Listener { + private Killstreak plugin; + public PlayerManager(Killstreak plugin) { + this.plugin = plugin; + } + + private void playDeathSound(Player p) { + (new BukkitRunnable() { + private long times = 0L; + public void run() { + if(times >= 3) { + this.cancel(); + } + p.playSound(Sound.sound(Key.key("block.note_block.bass"), Sound.Source.PLAYER, 5f, 1f)); + times++; + } + }).runTaskTimer(plugin, 0L, 3L); + } + + private void playKillSound(Player p) { + p.playSound(Sound.sound(Key.key("entity.arrow.hit_player"), Sound.Source.PLAYER, 1f, 1f)); + } + + @EventHandler + public void onPlayerDeath(PlayerDeathEvent e) { + KillstreakManager km = KillstreakManager.getInstance(); + Player p = e.getPlayer(); + long pKillstreak = km.getKillstreak(p); + if(pKillstreak >= 3) { + this.playDeathSound(p); + + final TextColor redColor = TextColor.color(0xff3f2e); + final Component component = p.displayName() + .append(Component.text(" stracił killstreak ", redColor)) + .append(km.getKillstreakComponent(pKillstreak)); + plugin.getServer().broadcast(component); + } + km.resetKillstreak(p); + + Entity causingEntity = e.getDamageSource().getCausingEntity(); + if(causingEntity == null || !(causingEntity instanceof Player attacker)) return; + + final long killstreak = km.increaseKillstreak(attacker, 1L); + if(killstreak >= 3) this.playKillSound(p); + + if(km.shouldAnnounceKillstreak(killstreak)) { + final TextColor blueColor = TextColor.color(0x40b5e3); + final Component component = attacker.displayName() + .append(Component.text(" osiągnął killstreak ").color(blueColor)) + .append(km.getKillstreakComponent(killstreak)) + .append(Component.text(" zabijając ", blueColor)) + .append(p.displayName()); + plugin.getServer().broadcast(component); + } + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..e22e72c --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,7 @@ +name: killstreak +version: 1.0 +author: Piecuu +main: pl.piecuu.killstreak.Killstreak +api-version: '1.21.11' + +depend: ["PlaceholderAPI"] \ No newline at end of file