42 Commits
Author SHA1 Message Date
Luka de Vrij 7de536d4b3 1.2? 2023-07-22 16:45:49 +02:00
Luka de Vrij 5488d4d72d Merge branch 'main' of https://github.com/LifelessNerd/PureKitPvP 2023-07-22 00:08:43 +02:00
Luka de Vrij f2d36d9f85 Open chest inventory fix 2023-07-22 00:08:41 +02:00
Luka de Vrij f9d5b687a4 Update GetCustomItem.java
tab update
2023-07-19 23:58:29 +02:00
Luka de Vrij 3df3dfb0c9 +2 kill effects 2023-07-18 21:34:45 +02:00
Luka de Vrij e3a83fe225 KitsGUI permissions + config add
also warning of world plugin is active in on stratup
2023-07-17 22:52:15 +02:00
Luka de Vrij df8c74ac09 bugfixes. small additions
The big Un-italicizing of 2023
Projectile trail for arrows
ChickenPreventer for eggs
Child addition to custom mobs via commands
2023-07-16 23:17:53 +02:00
Luka de Vrij 6fc21c8229 draft voor page 2 van kits 2023-07-15 23:53:29 +02:00
Luka de Vrij 4470a4ea21 KillMessages
en taffes veel bug fixes
2023-07-12 00:01:55 +02:00
Luka de Vrij 56653d938d 1.20.1 paper + camel fix
1.20.1
2023-07-10 22:55:08 +02:00
Luka 10814c981a Kill Message WIP + fixes/minor features
Level in chat
Projectile Trails
Kill Message WIP
Auto-/kit on death
2023-06-19 23:25:49 +02:00
Luka 610e102c08 KillEffects done
Golden head bug fix
2023-06-17 23:24:59 +02:00
Luka 614deac7da bugfixes
- Adrenaline no longer interferes with Scout
- Golden Head as Killitem now has ItemMeta aswell; making it functional
2023-05-26 22:34:08 +02:00
Luka 19b017f7f0 kleine go back button 2023-05-15 23:23:29 +02:00
Luka f0087503f1 fall damage bug fixed, cosmetics progress 2023-05-14 23:28:14 +02:00
Luka d71ebdc54e new perks and shit 2023-05-13 23:31:58 +02:00
Luka e7e6348ebe new perk?
needs testing
2023-05-12 23:14:49 +02:00
Luka 2de2c502b0 Zombie and skeleton mobs work 2023-05-12 18:06:39 +02:00
Luka 7ba4ef1063 extra perks + kleine patch 2023-05-09 23:12:54 +02:00
Luka 6bbab07bb5 patch
perk balancing
snowballs geven poison/snowballs fixed
assist op zelf is niet meer mogelijk
death xp naar 0
2023-05-07 22:54:36 +02:00
Luka daea1242a0 untested - cosmetics inventories 2023-04-19 23:50:40 +02:00
Luka 35c7f54e31 Cosmetics - nog geen menu - enkel samples 2023-04-18 23:13:16 +02:00
Luka 2685c1570a draft for cosmetics 2023-04-17 23:59:04 +02:00
Luka d33408169e niets eigenlijk 2023-02-07 23:57:44 +01:00
Luka c64a63a02c Perks exploit fixed + custom mobs implemented
The custom mobs command is still full of NPE's tho
2023-01-31 23:42:03 +01:00
Luka 06b8b36042 tabcomplete command 2023-01-30 23:18:13 +01:00
Luka 6e69f1b06f command finalized 2023-01-29 23:11:45 +01:00
Luka ee3886a162 CustomMob basic command draft + target behaviour is mediocre but functional 2023-01-27 23:35:46 +01:00
Luka 831cdf7ef6 Merge branch 'main' of https://github.com/LifelessNerd/PureKitPvP 2022-11-08 17:58:21 +01:00
Luka 91cd1ef1d9 every time 2022-11-08 17:58:10 +01:00
Luka de Vrij 4a603ee65d Update README.md
1.1 update
2022-11-08 17:56:32 +01:00
Luka 78295a4dd3 1.1 release
perks
2022-11-08 17:56:15 +01:00
Luka ab68294a6f Perk GUI
WIP
2022-11-08 00:25:50 +01:00
LifelessNerd 0e3e0b6675 mobile change 2022-10-23 17:43:13 +02:00
Luka 8513b8f1da wot 2022-10-21 23:51:14 +02:00
Luka f4be22124e ComponentUtils
setLore added, needs testing tho
2022-10-20 23:53:13 +02:00
Luka e225a9b373 Perk redesign draft, nieuwe perks 2022-10-19 23:12:22 +02:00
Luka e07872a82d perks, fixes
new perks, setperk all argument, kitstats sorted draft
2022-10-18 23:25:11 +02:00
Luka 96d42f3e29 Notoriety perk 2022-10-17 23:39:13 +02:00
Luka 803e18c8a5 PERKS 2022-10-17 00:25:00 +02:00
Luka 4952ff1209 Merge branch 'main' of https://github.com/LifelessNerd/PureKitPvP 2022-08-10 15:06:02 +02:00
Luka a78ae48e5f 1.0 release 2022-08-10 15:05:56 +02:00
64 changed files with 3422 additions and 260 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" />
</component>
</module>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="PureKitPvP" />
</profile>
</annotationProcessing>
</component>
</project>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/PureKitsFork/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/PureKitsFork/src/main/resources" charset="UTF-8" />
</component>
</project>
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="sonatype" />
<option name="name" value="sonatype" />
<option name="url" value="https://oss.sonatype.org/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="papermc-repo" />
<option name="name" value="papermc-repo" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<list size="1">
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/PureKitsFork/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/PureKitPvP.iml" filepath="$PROJECT_DIR$/.idea/PureKitPvP.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>PAPER</platformType>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
</module>
+6 -6
View File
@@ -6,12 +6,12 @@
<groupId>me.lifelessnerd.purekitpvp</groupId>
<artifactId>PureKitPvP</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.2</version>
<packaging>jar</packaging>
<name>PureKitPvP</name>
<description>PureKits fork, customised</description>
<description>Full KitPvP experience, customizable kits and items</description>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -24,8 +24,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
<plugin>
@@ -55,7 +55,7 @@
<repositories>
<repository>
<id>papermc-repo</id>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
@@ -68,7 +68,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.19-R0.1-SNAPSHOT</version>
<version>1.20.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -1,9 +1,8 @@
package me.lifelessnerd.purekitpvp;
import me.lifelessnerd.purekitpvp.createKit.CreateKit;
import me.lifelessnerd.purekitpvp.createKit.DeleteKit;
import me.lifelessnerd.purekitpvp.createKit.KitIcon;
import me.lifelessnerd.purekitpvp.createKit.SetKillItem;
import me.lifelessnerd.purekitpvp.custommobs.CustomMobCommand;
import me.lifelessnerd.purekitpvp.files.MobSpawnConfig;
import me.lifelessnerd.purekitpvp.createKit.*;
import me.lifelessnerd.purekitpvp.customitems.GetCustomItem;
import me.lifelessnerd.purekitpvp.customitems.loottablelogic.CreateLootTable;
import me.lifelessnerd.purekitpvp.files.KitConfig;
@@ -14,27 +13,33 @@ import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.entity.*;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import static org.bukkit.Bukkit.getPlayer;
import static org.bukkit.Bukkit.getServer;
public class AdminCommandManager implements TabExecutor {
ArrayList<Subcommand> subcommands = new ArrayList<>();
Plugin plugin;
public AdminCommandManager(Plugin plugin){
public AdminCommandManager(Plugin plugin) {
subcommands.add(new CreateKit(plugin));
subcommands.add(new DeleteKit(plugin));
subcommands.add(new ResetKit());
subcommands.add(new SetKillItem(plugin));
//subcommands.add(new SetPerk(plugin));
subcommands.add(new CreateLootTable(plugin));
subcommands.add(new GetCustomItem());
subcommands.add(new CustomMobCommand());
subcommands.add(new GetKitStats(plugin));
subcommands.add(new HelpCommand(subcommands, plugin));
subcommands.add(new AdminHelpCommand(subcommands, plugin));
subcommands.add(new InfoCommand());
subcommands.add(new ReloadPlugin(plugin));
this.plugin = plugin;
@@ -43,25 +48,25 @@ public class AdminCommandManager implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)){
if (!(sender instanceof Player)) {
sender.sendMessage("The console cannot perform these commands.");
return false;
}
Player player = (Player) sender;
if(!(player.hasPermission("purekitpvp.admin.*"))){
if (!(player.hasPermission("purekitpvp.admin.*"))) {
player.sendMessage(ChatColor.RED + "You do not have permission!");
return true;
}
if (args.length < 1){
if (args.length < 1) {
player.sendMessage("Please specify what function to use.");
return false;
}
//Check for names of subcommands in arg
for (int i = 0; i < getSubcommands().size(); i++){
if (args[0].equalsIgnoreCase(getSubcommands().get(i).getName())){
for (int i = 0; i < getSubcommands().size(); i++) {
if (args[0].equalsIgnoreCase(getSubcommands().get(i).getName())) {
boolean result = getSubcommands().get(i).perform(player, args);
return true; // All help dialogs are done in-class with player.sendMessage
}
@@ -73,85 +78,93 @@ public class AdminCommandManager implements TabExecutor {
}
public ArrayList<Subcommand> getSubcommands(){
public ArrayList<Subcommand> getSubcommands() {
return subcommands;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if(args.length == 1) {
if (args.length == 1) {
List<String> arguments = new ArrayList<>();
for (Subcommand subcommand : subcommands){
for (Subcommand subcommand : subcommands) {
arguments.add(subcommand.getName());
}
return arguments;
}
if (args[0].equalsIgnoreCase("getcustomitem")){
if (args[0].equalsIgnoreCase("getcustomitem")) {
if (args[1].equalsIgnoreCase("random_chest")){
if (args[1].equalsIgnoreCase("random_chest")) {
List<String> arguments = new ArrayList<>(LootTablesConfig.get().getKeys(false));
return arguments;
} else if (args[1].equalsIgnoreCase("golden_head")) {
return new ArrayList<>();
} else if (args[1].equalsIgnoreCase("custom_mob_egg")) {
return new ArrayList<>(MobSpawnConfig.get().getKeys(false));
}
else if (args[1].equalsIgnoreCase("golden_head")){
if (args.length > 3) {
return new ArrayList<>();
}
List<String> arguments = new ArrayList<>();
arguments.add("random_chest");
arguments.add("golden_head");
arguments.add("custom_mob_egg");
return arguments;
}
if (args[0].equalsIgnoreCase("createloottable")){
if (args[0].equalsIgnoreCase("createloottable")) {
if (args.length == 2){
if (args.length == 2) {
List<String> arguments = new ArrayList<>();
arguments.add("<name>");
return arguments;
}
if (args.length == 3){
if (args.length == 3) {
List<String> arguments = new ArrayList<>();
arguments.add("<lore>");
return arguments;
}
if (args.length == 4){
if (args.length == 4) {
List<String> arguments = new ArrayList<>();
arguments.add("<displayName>");
return arguments;
}
}
if (args[0].equalsIgnoreCase("setkillitem")){
if (args[0].equalsIgnoreCase("setkillitem")) {
if (args.length == 2){
if (args.length == 2) {
List<String> autoComplete = new ArrayList<>();
for(String key : KitConfig.get().getConfigurationSection("kits.").getKeys(false)){
for (String key : KitConfig.get().getConfigurationSection("kits.").getKeys(false)) {
key = key.toLowerCase();
autoComplete.add(key);
};
}
;
return autoComplete;
}
}
if (args[0].equalsIgnoreCase("deletekit")){
if (args[0].equalsIgnoreCase("deletekit")) {
if (args.length == 2){
if (args.length == 2) {
List<String> autoComplete = new ArrayList<>();
for(String key : KitConfig.get().getConfigurationSection("kits.").getKeys(false)){
for (String key : KitConfig.get().getConfigurationSection("kits.").getKeys(false)) {
key = key.toLowerCase();
autoComplete.add(key);
};
}
;
return autoComplete;
}
}
if (args[0].equalsIgnoreCase("createkit")){
if (args[0].equalsIgnoreCase("createkit")) {
if (args.length == 2){
if (args.length == 2) {
List<String> arguments = new ArrayList<>();
arguments.add("<kitName>");
return arguments;
}
if (args.length == 3){
if (args.length == 3) {
List<String> arguments = new ArrayList<>();
arguments.add("&1");
arguments.add("&2");
@@ -166,23 +179,77 @@ public class AdminCommandManager implements TabExecutor {
return arguments;
}
if (args.length == 4){
if (args.length == 4) {
KitIcon kitIconLib = new KitIcon();
return Arrays.asList(kitIconLib.materialList);
}
if (args.length == 5){
if (args.length == 5) {
List<String> arguments = new ArrayList<>();
arguments.add("kit.other");
return arguments;
}
if (args.length == 6){
if (args.length == 6) {
KitIcon kitIconLib = new KitIcon();
return Arrays.asList(kitIconLib.materialList);
}
}
if (args[0].equalsIgnoreCase("custommob")) {
if (args.length == 2) {
List<String> arguments = new ArrayList<>();
arguments.add("create");
arguments.add("set");
arguments.add("delete");
return arguments;
}
if (args[1].equalsIgnoreCase("create")) {
if (args.length == 3) {
List<String> arguments = new ArrayList<>();
arguments.add("<identifier>");
return arguments;
}
if (args.length == 4) {
List<EntityType> entities = Arrays.asList(EntityType.values());
ArrayList<String> arguments = new ArrayList<>();
// AAAH LAMBDA IN JAVA? sure
Consumer<EntityType> method = (entityType) -> {
Entity entity;
try {
// This is stupid, only reason i am keeping this here is because it won't run that often
entity = getServer().getWorlds().get(0).spawnEntity(getServer().getWorlds().get(0).getSpawnLocation(), entityType);
if (entity instanceof Monster) {
arguments.add(entityType.toString().toLowerCase());
}
entity.remove();
} catch(Exception e){
// System.out.println(entityType);
}
};
entities.forEach(method);
return arguments;
}
}
if (args[1].equalsIgnoreCase("set")) {
if (args.length == 3) {
return new ArrayList<>(MobSpawnConfig.get().getKeys(false));
}
if (args.length == 4) {
String[] possibleArgs = {"helmet", "chestplate", "leggings", "boots", "mainhand", "offhand", "child"};
return Arrays.asList(possibleArgs);
}
if (args.length == 5){
if (args[3].equalsIgnoreCase("child")){
String[] possibleArgs = {"true", "false"};
return Arrays.asList(possibleArgs);
}
}
}
if (args.length == 3) {
return new ArrayList<>(MobSpawnConfig.get().getKeys(false));
}
}
return new ArrayList<>();
}
}
@@ -0,0 +1,72 @@
package me.lifelessnerd.purekitpvp;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
public class AdminHelpCommand extends Subcommand {
Plugin plugin;
ArrayList<Subcommand> subcommands;
public AdminHelpCommand(ArrayList<Subcommand> subcommands, Plugin plugin) {
this.plugin = plugin;
this.subcommands = subcommands;
}
@Override
public String getName() {
return "help";
}
@Override
public String[] getAliases() {
return null;
}
@Override
public String getDescription() {
return "Get a list of all commands";
}
@Override
public String getSyntax() {
return "/purekitpvp help";
}
@Override
public boolean perform(Player player, String[] args) {
if (args.length == 1){
String message = """
&bPureKitPvP - Help Menu
&a/kit &r- &eOpen up the kit menu
&a/getkit <kit> &r- &eGet a kit directly
&a/suicide &r- &eCommit suicide (if enabled)
&a/stats <player> &r- &eGet PVP stats of a player
&a/purekitpvphelp &r- &eShow this menu for non-admins
&bFor admin commands, see &a/pkpvp help 2&b!
""";
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
if (args.length >= 2){
if (args[1].equalsIgnoreCase("2")){
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&bPureKitPvP - Admin Commands"));
for (Subcommand subcommand : subcommands){
String message =
"&a" + subcommand.getSyntax() + " &r- &e" + subcommand.getDescription();
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
}
}
return true;
}
}
@@ -1,80 +1,30 @@
package me.lifelessnerd.purekitpvp;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
public class HelpCommand extends Subcommand {
Plugin plugin;
ArrayList<Subcommand> subcommands;
public HelpCommand(ArrayList<Subcommand> subcommands, Plugin plugin) {
this.plugin = plugin;
this.subcommands = subcommands;
}
import org.jetbrains.annotations.NotNull;
public class HelpCommand implements CommandExecutor {
@Override
public String getName() {
return "help";
}
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
@Override
public String[] getAliases() {
return null;
}
if (!(sender instanceof Player player)){
return false;
}
@Override
public String getDescription() {
return "Get a list of all commands";
}
@Override
public String getSyntax() {
return "/purekitpvp help";
}
@Override
public boolean perform(Player player, String[] args) {
if (args.length == 1){
String message = """
String message = """
&bPureKitPvP - Help Menu
&a/kit &r- &eOpen up the kit menu
&a/getkit <kit> &r- &eGet a kit directly
&a/suicide &r- &eCommit suicide (if enabled)
&a/stats <player> &r- &eGet PVP stats of a player
&a/perks &r- &eSelect perks
&bFor admin commands, see &a/pkpvp help 2&b!
""";
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
if (args.length >= 2){
if (args[1].equalsIgnoreCase("2")){
if (!(player.hasPermission("purekitpvp.admin.*"))){
player.sendMessage("No permission!");
return true;
}//Obsolete, any AdminCommandManager subcommands require admin perm
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&bPureKitPvP - Admin Commands"));
for (Subcommand subcommand : subcommands){
String message =
"&a" + subcommand.getSyntax() + " &r- &e" + subcommand.getDescription();
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
}
}
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
return true;
}
}
@@ -4,6 +4,8 @@ import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
public class InfoCommand extends Subcommand{
@Override
public String getName() {
return "info";
@@ -29,11 +31,11 @@ public class InfoCommand extends Subcommand{
String message =
"""
&bPureKitPvP - version 1.0
&bPureKitPvP - version 1.2
&6SpigotMC: &ohttps://bit.ly/PureKitPvPSpigotMC
&6Github: &ohttps://github.com/LifelessNerd/PureKitPvP
&6Developer: &ohttps://twitter.com/NerdLifeless
&rIf you have any problems, bugs or glitches, reach out to me via any of the links above.
&rIf you have any problems, bugs or glitches, please do reach out to me via any of the links above.
""";
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
@@ -0,0 +1,17 @@
package me.lifelessnerd.purekitpvp;
import org.bukkit.plugin.Plugin;
public class PluginGetter {
static Plugin plugin;
public PluginGetter(Plugin plugin) {
PluginGetter.plugin = plugin;
}
public static Plugin Plugin(){
return plugin;
}
}
@@ -1,14 +1,23 @@
package me.lifelessnerd.purekitpvp;
import me.lifelessnerd.purekitpvp.combathandlers.*;
import me.lifelessnerd.purekitpvp.combathandlers.leveling.PlayerLevelChat;
import me.lifelessnerd.purekitpvp.combathandlers.libs.commands.Suicide;
import me.lifelessnerd.purekitpvp.combathandlers.VoidKiller;
import me.lifelessnerd.purekitpvp.combathandlers.mobhandler.OnPlayerSpawnMob;
import me.lifelessnerd.purekitpvp.combathandlers.killhandler.DeathHandler;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsCommand;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsGUIListener;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.KillEffectInventory;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.KillMessageInventory;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.ProjectileTrailInventory;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners.KillEffect;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners.KillMessage;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners.ProjectileTrail;
import me.lifelessnerd.purekitpvp.perks.perkCommand.PerkCommand;
import me.lifelessnerd.purekitpvp.perks.perkCommand.PerkGUIListener;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkFireHandler;
import me.lifelessnerd.purekitpvp.customitems.GoldenHeadEat;
import me.lifelessnerd.purekitpvp.customitems.OpenRandomChest;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.files.KitStatsConfig;
import me.lifelessnerd.purekitpvp.files.LootTablesConfig;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import me.lifelessnerd.purekitpvp.files.*;
import me.lifelessnerd.purekitpvp.kitCommand.GUIListener;
import me.lifelessnerd.purekitpvp.kitCommand.GetKit;
import me.lifelessnerd.purekitpvp.kitCommand.KitsGUI;
@@ -21,7 +30,7 @@ public final class PureKitPvP extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("Enabled PureKitPvP");
getConfig().options().copyDefaults();
saveDefaultConfig();
@@ -32,11 +41,15 @@ public final class PureKitPvP extends JavaPlugin {
//Might create problems, I tried to just keep value null but then the entire value didn't show up until I created a kit
//Which is not too bad either so whatever, if there are any problems ever change this and hope for the best
//Otherwise find a way to make a path without a value, like: kits: , instead of kits: ''
//TODO: fix this with createConfiguration if I feel like it, tbf it works fine
//: fix this with createConfiguration if I feel like it, tbf it works fine (IT DOES)
KitConfig.get().options().copyDefaults(true);
KitConfig.save();
PerkData.setup();
PerkData.get().options().copyDefaults(true);
PerkData.save();
KitStatsConfig.setup();
KitStatsConfig.get().options().copyDefaults(true);
KitStatsConfig.save();
@@ -45,17 +58,29 @@ public final class PureKitPvP extends JavaPlugin {
LootTablesConfig.get().options().copyDefaults(true);
LootTablesConfig.save();
MobSpawnConfig.setup();
MobSpawnConfig.get().options().copyDefaults(true);
MobSpawnConfig.save();
PlayerStatsConfig.setup();
PlayerStatsConfig.get().options().copyDefaults(true);
PlayerStatsConfig.save();
CosmeticsConfig.setup();
CosmeticsConfig.get().options().copyDefaults(true);
CosmeticsConfig.save();
getCommand("getkit").setExecutor(new GetKit(this));
getCommand("kit").setExecutor(new KitsGUI(this));
getCommand("perk").setExecutor(new PerkCommand(this));
getCommand("suicide").setExecutor(new Suicide(this));
getCommand("getstats").setExecutor(new GetStats(this));
getCommand("purekitpvphelp").setExecutor(new HelpCommand());
getCommand("purekitpvp").setExecutor(new AdminCommandManager(this));
getCommand("cosmetics").setExecutor(new CosmeticsCommand(this));
getServer().getPluginManager().registerEvents(new GetKit(this), this);
getServer().getPluginManager().registerEvents(new GUIListener(this), this);
getServer().getPluginManager().registerEvents(new PerkGUIListener(this), this);
getServer().getPluginManager().registerEvents(new DeathHandler(this), this);
getServer().getPluginManager().registerEvents(new VoidKiller(this), this);
getServer().getPluginManager().registerEvents(new ProjectilesThrownStat(this), this);
@@ -63,11 +88,29 @@ public final class PureKitPvP extends JavaPlugin {
getServer().getPluginManager().registerEvents(new GoldenHeadEat(this), this);
getServer().getPluginManager().registerEvents(new OpenRandomChest(this), this);
getServer().getPluginManager().registerEvents(new OnPlayerSpawnMob(this), this);
getServer().getPluginManager().registerEvents(new PearlListener(this), this);
getServer().getPluginManager().registerEvents(new HealthEvents(this), this);
getServer().getPluginManager().registerEvents(new PlayerLevelChat(this), this);
getServer().getPluginManager().registerEvents(new ChickenPrevention(this), this);
getServer().getPluginManager().registerEvents(new PickupListener(this), this);
getServer().getPluginManager().registerEvents(new CosmeticsGUIListener(this), this);
getServer().getPluginManager().registerEvents(new KillEffect(this), this);
getServer().getPluginManager().registerEvents(new KillEffectInventory(this), this);
getServer().getPluginManager().registerEvents(new ProjectileTrail(this), this);
getServer().getPluginManager().registerEvents(new ProjectileTrailInventory(this), this);
getServer().getPluginManager().registerEvents(new KillMessageInventory(this), this);
PerkFireHandler.plugin = this; //idk? fixes npe?
PluginGetter.plugin = this; //this is dumb but used in 2 instances
getLogger().info("Enabled PureKitPvP");
getLogger().warning("Plugin active in world " + getConfig().getString("world") + ". To change this, see the config.");
}
@Override
public void onDisable() {
getLogger().info("Goodbye!");
}
}
@@ -1,9 +1,6 @@
package me.lifelessnerd.purekitpvp;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.files.KitStatsConfig;
import me.lifelessnerd.purekitpvp.files.LootTablesConfig;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import me.lifelessnerd.purekitpvp.files.*;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@@ -39,17 +36,28 @@ public class ReloadPlugin extends Subcommand {
@Override
public boolean perform(Player player, String[] args) {
//TODO Reload should read the files, even if they are manually edited, and load them into the plugin
// NO WORKIE
KitConfig.reload();
KitConfig.save();
KitStatsConfig.reload();
KitStatsConfig.save();
LootTablesConfig.reload();
LootTablesConfig.save();
PlayerStatsConfig.reload();
PlayerStatsConfig.save();
PerkData.reload();
PerkData.save();
MobSpawnConfig.reload();
MobSpawnConfig.save();
CosmeticsConfig.reload();
CosmeticsConfig.save();
plugin.reloadConfig();
plugin.getConfig();
plugin.saveConfig();
@@ -1,5 +1,6 @@
package me.lifelessnerd.purekitpvp;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
@@ -0,0 +1,35 @@
package me.lifelessnerd.purekitpvp.combathandlers;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.plugin.Plugin;
public class ChickenPrevention implements Listener {
public Plugin plugin;
public ChickenPrevention(Plugin plugin){
this.plugin = plugin;
}
@EventHandler
public void onChickenSpawn(EntitySpawnEvent event) {
if (!(plugin.getConfig().getBoolean("chicken-prevention"))){
return;
}
Entity spawned = event.getEntity();
if (!(spawned.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (spawned.getType().equals(EntityType.CHICKEN)){
event.setCancelled(true);
}
}
}
// This class prevents chicken from spawning -> some kits may have eggs for combo material, they would spawn chicken, not anymore
@@ -0,0 +1,48 @@
package me.lifelessnerd.purekitpvp.combathandlers;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkFireHandler;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.plugin.Plugin;
public class HealthEvents implements Listener {
public static Plugin plugin;
public HealthEvents(Plugin plugin){
HealthEvents.plugin = plugin;
}
@EventHandler
public void onHealthRegen(EntityRegainHealthEvent event){
if (!(event.getEntity() instanceof Player)){
return;
}
Player player = (Player) event.getEntity();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
PerkFireHandler.fireHealthPerks(player);
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event){
if (!(event.getEntity() instanceof Player)){
return;
}
Player player = (Player) event.getEntity();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
PerkFireHandler.fireHealthPerks(player);
}
}
@@ -0,0 +1,47 @@
package me.lifelessnerd.purekitpvp.combathandlers;
import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkFireHandler;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.EnderPearl;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.spigotmc.event.entity.EntityDismountEvent;
public class PearlListener implements Listener {
Plugin plugin;
public PearlListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onProjectileThrow(PlayerLaunchProjectileEvent event) {
if (!(event.getProjectile() instanceof EnderPearl)){
return;
}
Player player = event.getPlayer();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
PerkFireHandler.fireEnderpearlPerks(player, event);
}
@EventHandler
public void onDismount(EntityDismountEvent e) {
if(e.getDismounted() instanceof EnderPearl) {
e.getDismounted().remove();
}
}
}
@@ -0,0 +1,42 @@
package me.lifelessnerd.purekitpvp.combathandlers;
import me.lifelessnerd.purekitpvp.PureKitPvP;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerAttemptPickupItemEvent;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
public class PickupListener implements Listener {
Plugin plugin;
public PickupListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onItemPickup(PlayerAttemptPickupItemEvent e){
Player player = e.getPlayer();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
return;
}
Item itemOnGround = e.getItem();
PersistentDataContainer itemContainer = itemOnGround.getPersistentDataContainer();
NamespacedKey key = new NamespacedKey(plugin, "cosmetic");
if (itemContainer.get(key, PersistentDataType.BOOLEAN) == null){
return;
}
if (!(itemContainer.get(key, PersistentDataType.BOOLEAN))){ //lies
return;
}
e.setCancelled(true);
}
}
@@ -1,8 +1,11 @@
package me.lifelessnerd.purekitpvp.combathandlers.killhandler;
import me.lifelessnerd.purekitpvp.combathandlers.PlayerLeveling;
import me.lifelessnerd.purekitpvp.combathandlers.leveling.PlayerLeveling;
import me.lifelessnerd.purekitpvp.combathandlers.libs.DamageCauseLib;
import me.lifelessnerd.purekitpvp.combathandlers.mobhandler.MobRemover;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners.KillEffect;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners.KillMessage;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkFireHandler;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import me.lifelessnerd.purekitpvp.utils.DoubleUtils;
@@ -25,6 +28,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
import java.util.ArrayList;
import java.util.HashMap;
@@ -32,6 +36,13 @@ import java.util.logging.Level;
public class DeathHandler implements Listener {
// To whoever sees this; I profoundly apologise: this code is garbage
// It hangs together with duct tape and iterative bug fixes everywhere
// I should really redesign or at least clean up this class
// But I feel like I would just make it worse; so I probably won't ever do that
// good luck trying to read what is going on
// You can ping me, but I won't probably know either
Plugin plugin;
public DeathHandler(Plugin plugin) {
@@ -54,13 +65,21 @@ public class DeathHandler implements Listener {
Bukkit.getScheduler().runTaskLater((Plugin)this.plugin, () ->
player.teleport(new Location(player.getWorld(), x, y, z, 0, 0)), 1L);
Bukkit.getScheduler().runTaskLater((Plugin)this.plugin, () ->
player.setHealth(20), 2L);
player.getInventory().clear();
player.getActivePotionEffects().clear();
player.setExp(0f);
player.setLevel(0);
player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 5, 254)); //Kinda jank, works tho
Bukkit.getScheduler().runTaskLater((Plugin)this.plugin, () -> {
player.getInventory().clear();
player.getActivePotionEffects().clear();
player.setExp(0f);
player.setLevel(0);
player.setArrowsInBody(0);
player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 5, 254)); //Kinda jank, works tho
player.setFireTicks(0);
player.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 5, 1));
player.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, 10 , 1));
player.setHealth(20);
player.chat("/kit");
}, 2L);
DamageCauseLib damageCauseLib = new DamageCauseLib();
@@ -71,7 +90,7 @@ public class DeathHandler implements Listener {
String message = "&c&lYou died!";
player.sendMessage(ChatColor.translateAlternateColorCodes('&',message));
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Death Recap:"));
// Printing process and formatting
int totalDamageDone = 0;
for (String hashmapKey : damageData.damageDistributionMap.keySet()){
totalDamageDone += damageData.damageDistributionMap.get(hashmapKey);
@@ -95,38 +114,47 @@ public class DeathHandler implements Listener {
}
//Broadcasting and stuff
// use 'lastPlayerBlow' to determine kill message and such
String deathMessage = player.getName();
String credit = " was killed by a mysterious force";
String deathMessage = "";
String lastEnvironmentHit;
String credit = ""; // Needed for later
boolean playerInvolved = true;
//Check who should get credit
if (damageData.lastPlayerDamager == null && damageData.lastOtherDamager != null){
//This means the player was completely killed by environment, no player killer
// Except when the killer is a zombie of a player -> handled down below
lastEnvironmentHit = damageData.lastOtherDamager;
credit = damageCauseLib.deathMessages.get(lastEnvironmentHit);
deathMessage = KillMessage.create.byEnvironment(player.getName(), lastEnvironmentHit);
playerInvolved = false;
}
if (damageData.lastPlayerDamager != null && damageData.lastOtherDamager != null){
//This means player got damage from both
credit = damageData.lastPlayerDamager;
deathMessage += " was killed by ";
// deathMessage += " was killed by ";
// System.out.println(damageData.lastOtherDamager);
// if (damageData.lastOtherDamager.equalsIgnoreCase("VOID")){
// System.out.println("thrown in void");
// }
if (e.getEntity().getLastDamageCause().getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK)){
deathMessage = KillMessage.create.byPlayer(player.getName(), damageData.lastPlayerDamager);
} else {
deathMessage = KillMessage.create.byEnvironmentAndPlayer(player.getName(), damageData.lastPlayerDamager, damageData.lastOtherDamager);
}
}
if (damageData.lastPlayerDamager != null && damageData.lastOtherDamager == null){
//Means player has only been hit by other players
credit = damageData.lastPlayerDamager;
deathMessage += " was killed by ";
deathMessage = KillMessage.create.byPlayer(player.getName(), damageData.lastPlayerDamager);
}
deathMessage = deathMessage + credit;
// deathMessage = deathMessage + credit;
// Death message shows who got credit, broadcast to every player in pvp world
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getWorld() == player.getWorld()) {
@@ -151,7 +179,9 @@ public class DeathHandler implements Listener {
String highestAssistor = null;
for (String key2 : damageData.damageDistributionMap.keySet()){
if (!(key2.equalsIgnoreCase(credit)) && pvpPlayers.contains(key2)){ // Dont count the killer in the assist check
if (!(key2.equalsIgnoreCase(credit)) && pvpPlayers.contains(key2) && pvpPlayers.contains(player.getName())){
// Don't count the killer in the assist check
// Don't count the killed player himself in the assist check
//Only check players for assist
if (highestAssistor == null){
highestAssistor = key2;
@@ -175,10 +205,6 @@ public class DeathHandler implements Listener {
player.getPersistentDataContainer().remove(key);
player.setFireTicks(0);
player.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 5, 1));
player.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, 10 , 1));
//Sound effects and such
player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_HURT, 1,0);
@@ -211,8 +237,8 @@ public class DeathHandler implements Listener {
//update level
PlayerLeveling.createLevelXPPath(player.getName());
PlayerLeveling.addExperience(player, 1, "Death"); // 1 for DEATH
PlayerLeveling.updateLevels();
// PlayerLeveling.addExperience(player, 1, "Death"); // 1 for DEATH// Ah no: can be exploited
// PlayerLeveling.updateLevels();
//remove any mobs player spawned
MobRemover.removeMobs(player);
@@ -264,7 +290,7 @@ public class DeathHandler implements Listener {
if (creditStats.getInt(creditPlayer.getName() + ".killstreak") >= 5) {
int duration = plugin.getConfig().getInt("killstreak-glowing-duration");
creditPlayer.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, duration * 20, 2));
creditPlayer.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, duration * 20, 2, true, false));
}
}
@@ -297,6 +323,8 @@ public class DeathHandler implements Listener {
if (!(KitConfig.get().getString("kits." + kitName + ".killitem") == null)) {
ItemStack fromFile = (ItemStack) KitConfig.get().get("kits." + kitName + ".killitem");
killItem.setType(fromFile.getType());
killItem.setAmount(fromFile.getAmount());
killItem.setItemMeta(fromFile.getItemMeta());
creditPlayer.getInventory().addItem(killItem);
}
@@ -304,6 +332,11 @@ public class DeathHandler implements Listener {
plugin.getLogger().log(Level.SEVERE, exception.toString()); //TODO throws here. think i fixed it but not sure
}
//PerkHandler
PerkFireHandler.fireKillPerks(creditPlayer);
//The killcosmetic that the creditPlayer has fires
KillEffect.fireKillCosmetic(player, creditPlayer);
} else {
@@ -336,7 +369,8 @@ public class DeathHandler implements Listener {
assistor.sendActionBar(actionBarText);
//update level
//update level TODO: check this: I think this is in the wrong spot since it doesn't seem to work?
// Need a 3rd player or alt to test
PlayerLeveling.createLevelXPPath(assistor.getName());
PlayerLeveling.addExperience(assistor, 3, "Assist"); // 3 for assists
PlayerLeveling.updateLevels();
@@ -353,8 +387,6 @@ public class DeathHandler implements Listener {
}
}
}
@@ -362,7 +394,11 @@ public class DeathHandler implements Listener {
public void onPlayerCombatHit(EntityDamageByEntityEvent event){
Player player = null;
Player damager = null;
// HAND TO HAND COMBAT
// HAND-TO-HAND COMBAT
if (!(event.getEntity().getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
// If the entity that is damaged is in this world, the entire event should be in this world
return;
} // This function should make all other copies obsolete - removed all affected copies (I think)
if (event.getDamager() instanceof Player && event.getEntity() instanceof Player) {
@@ -374,34 +410,47 @@ public class DeathHandler implements Listener {
return;
}
} else if (event.getDamager() instanceof Arrow && event.getEntity() instanceof Player) {
PerkFireHandler.fireCombatPerks(player, damager);
PerkFireHandler.fireVampirePerk(event);
} else if ((event.getDamager() instanceof Arrow || event.getDamager() instanceof SpectralArrow) && event.getEntity() instanceof Player) {
//This branch is a fuckin nightmare: too many hacked in exceptions because fucking spectral arrows and fucking skeletons
//Projectile combat
player = (Player) event.getEntity();
Arrow arrow = (Arrow) event.getDamager();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
return;
}
if(((AbstractArrow) event.getDamager()).getShooter() instanceof Player){
player = (Player) event.getEntity();
if (event.getDamager() instanceof Arrow) {
Arrow arrow = (Arrow) event.getDamager();
damager = (Player) arrow.getShooter();
} else {
SpectralArrow arrow = (SpectralArrow) event.getDamager();
damager = (Player) arrow.getShooter();
}
PerkFireHandler.fireRangedPerks(event, damager);
double damage = event.getDamage();
double playerHP = player.getHealth() - damage;
if (playerHP < 0) {
playerHP = 0;
}
damager.sendMessage(ChatColor.translateAlternateColorCodes(
'&', "&a" + player.getName() + " &cis on &a" + (int) playerHP + " &cHP."));
} else if(((AbstractArrow) event.getDamager()).getShooter() instanceof Monster){
// Shooter is a skeleton probably
player = (Player) event.getEntity();
Monster skeleton = (Monster) ((AbstractArrow) event.getDamager()).getShooter();
String mobName = skeleton.getName();
damager = Bukkit.getPlayerExact(mobName.split("'s")[0]);
damager = (Player) arrow.getShooter();
double damage = event.getDamage();
double playerHP = player.getHealth() - damage;
if (playerHP < 0){
playerHP = 0;
}
damager.sendMessage(ChatColor.translateAlternateColorCodes(
'&', "&a" + player.getName() + " &cis on &a" + (int) playerHP + " &cHP."));
} else if (event.getDamager() instanceof ThrownPotion && event.getEntity() instanceof Player){
//Splash potion threw (only potions that do damage, only those are seen by this event)
player = (Player) event.getEntity();
ThrownPotion potion = (ThrownPotion) event.getDamager();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
return;
}
damager = (Player) potion.getShooter(); //works
double damage = event.getDamage();
double playerHP = player.getHealth() - damage;
@@ -413,14 +462,10 @@ public class DeathHandler implements Listener {
} else if (event.getDamager() instanceof Trident && event.getEntity() instanceof Player){
//Splash potion threw (only potions that do damage, only those are seen by this event)
//Trident
player = (Player) event.getEntity();
Trident trident = (Trident) event.getDamager();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
return;
}
damager = (Player) trident.getShooter(); //works
double damage = event.getDamage();
double playerHP = player.getHealth() - damage;
@@ -430,8 +475,27 @@ public class DeathHandler implements Listener {
damager.sendMessage(ChatColor.translateAlternateColorCodes(
'&', "&a" + player.getName() + " &cis on &a" + (int) playerHP + " &cHP."));
} else {
} else if (event.getDamager() instanceof Monster && event.getEntity() instanceof Player) {
String mobName = event.getDamager().getName();
damager = Bukkit.getPlayerExact(mobName.split("'s")[0]);
player = ((Player) event.getEntity()).getPlayer();
} else if (event.getDamager() instanceof EnderPearl && event.getEntity() instanceof Player) {
PerkFireHandler.fireEnderpearlDamagePerks((Player) event.getEntity(), event);
return;
}
else if (event.getDamager() instanceof Firework && event.getEntity() instanceof Player){
Firework fw = (Firework) event.getDamager();
if (fw.getShooter() instanceof Player){
player = (Player) event.getEntity();
damager = (Player) fw.getShooter();
} else {return;}
}
else {
//If we end up here idk what happened but nothing relevant (probably a zombie hitting a pig or something)
return;
}
@@ -479,7 +543,6 @@ public class DeathHandler implements Listener {
//Put the edited object back in the player
player.getPersistentDataContainer().set(key, new PlayerDamageDistributionDataType(), pulledPlayerData);
}
@EventHandler
@@ -506,14 +569,40 @@ public class DeathHandler implements Listener {
}
if (event.getCause() == EntityDamageEvent.DamageCause.MAGIC){
return;
}
int damageAmount = (int) event.getDamage();
EntityDamageEvent.DamageCause cause = event.getCause();
// This branch prevents fall damage from happening in the spawn area; it also returns so that it does not get added to damageDistribution
if (event.getCause() == EntityDamageEvent.DamageCause.FALL){
Location fallLocation = player.getLocation();
// - 0.5 because block and player location are off by 0.5 because Minecraft
double minX = plugin.getConfig().getDouble("respawnX") - 0.5 - plugin.getConfig().getInt("spawn-radius");
double maxX = plugin.getConfig().getDouble("respawnX") - 0.5 + plugin.getConfig().getInt("spawn-radius");
double minZ = plugin.getConfig().getDouble("respawnZ") - 0.5 - plugin.getConfig().getInt("spawn-radius");
double maxZ = plugin.getConfig().getDouble("respawnZ") - 0.5 + plugin.getConfig().getInt("spawn-radius");
if(fallLocation.getBlockX() >= minX && fallLocation.getBlockX() <= maxX){
if(fallLocation.getBlockZ() >= minZ && fallLocation.getBlockZ() <= maxZ) { // If inside spawn square
// event.setDamage(0);
event.setCancelled(true); //might have other implications - none found
return;
}
}
}
// This branch negates any firework damage if it is of killeffect origin -> fireworks from a crossbow still count
if (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION) {
EntityDamageByEntityEvent newEvent = (EntityDamageByEntityEvent) event;
if (newEvent.getDamager() instanceof Firework fw) {
if (fw.hasMetadata("nodamage")) {
event.setCancelled(true);
return;
}
}
}
//If player has just started combat, make a dataContainer with the empty object above
NamespacedKey key = new NamespacedKey(plugin, "damageDistributionInfo");
@@ -568,6 +657,9 @@ public class DeathHandler implements Listener {
if (event.getEntity() instanceof Snowball | event.getEntity() instanceof Egg){
shooter = (Player) event.getEntity().getShooter();
PerkFireHandler.fireSnowballPerks(event, player, shooter);
}
else {
return;
@@ -0,0 +1,35 @@
package me.lifelessnerd.purekitpvp.combathandlers.leveling;
import io.papermc.paper.event.player.AsyncChatEvent;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.plugin.Plugin;
public class PlayerLevelChat implements Listener {
public Plugin plugin;
public PlayerLevelChat(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event){
// Some shenanigans regarding async, but should be fine for this use case
if (!(plugin.getConfig().getBoolean("level-chat"))){
return;
}
Player player = event.getPlayer();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
event.setFormat("[" + PlayerStatsConfig.get().getString(player.getName() + ".level") + "] " + event.getFormat());
}
}
@@ -1,4 +1,4 @@
package me.lifelessnerd.purekitpvp.combathandlers;
package me.lifelessnerd.purekitpvp.combathandlers.leveling;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import org.bukkit.Bukkit;
@@ -36,6 +36,7 @@ public class DamageCauseLib {
deathMessages.put("DRYOUT"," had no more water");
deathMessages.put("FREEZE"," froze to death");
deathMessages.put("SONIC_BOOM"," got pummeled by a Warden");
deathMessages.put("MONSTER", " was killed by a mob, what a noob.");
damageCauseTranslations.put("CONTACT"," Cactus");
damageCauseTranslations.put("SUFFOCATION"," Suffocation");
@@ -64,6 +65,7 @@ public class DamageCauseLib {
damageCauseTranslations.put("DRYOUT"," Dryout");
damageCauseTranslations.put("FREEZE"," Freezing");
damageCauseTranslations.put("SONIC_BOOM"," Warden");
damageCauseTranslations.put("MONSTER"," Custom Mob");
}
}
@@ -0,0 +1,48 @@
package me.lifelessnerd.purekitpvp.combathandlers.libs;
import java.util.ArrayList;
import java.util.HashMap;
public class DeathCauseLib {
public HashMap<String, String> defaultDeathMessages = new HashMap<>();
public ArrayList<String> defaultKillMessages = new ArrayList<>();
public HashMap<String, String> flexDeathMessages = new HashMap<>();
public ArrayList<String> flexKillMessages = new ArrayList<>();
public HashMap<String, String> nerdDeathMessages = new HashMap<>();
public ArrayList<String> nerdKillMessages = new ArrayList<>();
public DeathCauseLib() {
defaultDeathMessages.put("VOID", " was thrown into the void by {killer}");
defaultDeathMessages.put("LAVA", " jumped into lava trying to escape {killer}");
defaultDeathMessages.put("FIRE", " stood in fire trying to escape {killer}");
defaultDeathMessages.put("FIRE_TICK", " burnt to a crisp trying to escape {killer}");
defaultDeathMessages.put("ENTITY_EXPLOSION", " exploded trying to escape {killer}");
defaultDeathMessages.put("FALL", " fell off a cliff trying to escape {killer}");
defaultKillMessages.add(" was killed by {killer}");
flexDeathMessages.put("VOID", " was yeeted into the void by {killer}");
flexDeathMessages.put("LAVA", " jumped in lava, he couldn't kill {killer}");
flexDeathMessages.put("FIRE", " stood in fire trying to escape {killer}");
flexDeathMessages.put("FIRE_TICK", " burnt to a crisp trying to escape {killer}");
flexDeathMessages.put("ENTITY_EXPLOSION", " exploded trying to escape {killer}");
flexDeathMessages.put("FALL", " was thrown off a cliff by {killer}");
flexKillMessages.add(" became kill #{kills} of {killer}");
nerdDeathMessages.put("VOID", " was thrown into the void by {killer}");
nerdDeathMessages.put("LAVA", " jumped into lava trying to escape {killer}");
nerdDeathMessages.put("FIRE", " stood in fire trying to escape {killer}");
nerdDeathMessages.put("FIRE_TICK", " burnt to a crisp trying to escape {killer}");
nerdDeathMessages.put("ENTITY_EXPLOSION", " exploded trying to escape {killer}");
nerdDeathMessages.put("FALL", " thought this was Borderlands, being chased by {killer}");
nerdKillMessages.add(" was Ctrl+Alt+Deleted by {killer}");
}
}
@@ -7,6 +7,7 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull;
public class Suicide implements CommandExecutor {
@@ -30,9 +31,13 @@ public class Suicide implements CommandExecutor {
}
player.setHealth(1);
for(PotionEffect effect:player.getActivePotionEffects()){
//Now use the method Player#removePotionEffect to remove the potion effect. This method accepts a PotionEffectType, so we need to get the type of the effect variable, and then remove it:
player.removePotionEffect(effect.getType());
}
player.teleport(new Location(player.getWorld(),
player.getLocation().getX(),
plugin.getConfig().getDouble("voidY") - 150.0,
plugin.getConfig().getDouble("voidY"),
player.getLocation().getY()
));
@@ -1,25 +1,34 @@
package me.lifelessnerd.purekitpvp.combathandlers.mobhandler;
import me.lifelessnerd.purekitpvp.PluginGetter;
import me.lifelessnerd.purekitpvp.files.MobSpawnConfig;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Player;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.*;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.SpawnEgg;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
public class OnPlayerSpawnMob implements Listener {
Plugin plugin;
@@ -39,30 +48,86 @@ public class OnPlayerSpawnMob implements Listener {
return;
}
if (!(e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.RIGHT_CLICK_AIR)) {
if (!(e.getAction() == Action.RIGHT_CLICK_BLOCK)) {
return;
}
Component itemDisplayName = player.getInventory().getItemInMainHand().displayName();
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
String itemName = serializer.serialize(itemDisplayName);
if (!(itemName.contains("Spawn Egg"))) {
if (!(player.getInventory().getItemInMainHand().getType().toString().contains("_SPAWN_EGG"))){
return;
}
String[] entityToBeSpawnedList = player.getInventory().getItemInMainHand().getType().toString().split("_SPAWN_EGG");
String entityToBeSpawned = entityToBeSpawnedList[0];
EntityType entityTypeTBS;
ItemStack item = player.getInventory().getItemInMainHand();
boolean customMob = false;
if (item.getItemMeta().getPersistentDataContainer().has(new NamespacedKey(plugin, "custom_mob_id"), PersistentDataType.STRING)){
// Custom Mob has been attempted to spawn
String customMobId = item.getItemMeta().getPersistentDataContainer().get(new NamespacedKey(plugin, "custom_mob_id"), PersistentDataType.STRING);
String mobType = MobSpawnConfig.get().getString(customMobId + ".type");
entityTypeTBS = EntityType.valueOf(mobType);
customMob = true;
}
else {
String[] entityToBeSpawnedList = item.getType().toString().split("_SPAWN_EGG");
String entityToBeSpawned = entityToBeSpawnedList[0];
EntityType entityTypeTBS = EntityType.valueOf(entityToBeSpawned);
entityTypeTBS = EntityType.valueOf(entityToBeSpawned);
}
Location lookPlace = e.getInteractionPoint();
Entity spawnedEntity = player.getWorld().spawnEntity(lookPlace, entityTypeTBS);
if (spawnedEntity instanceof Horse){
((Horse) spawnedEntity).setTamed(true);
((Horse) spawnedEntity).getInventory().addItem(new ItemStack(Material.SADDLE));
if (spawnedEntity instanceof Chicken){
if (plugin.getConfig().getBoolean("chicken-prevention")){
player.sendMessage(Component.text("ChickenPrevention prevented your chicken from spawning.").color(NamedTextColor.RED));
return;
}
}
if (spawnedEntity instanceof AbstractHorse) {
((AbstractHorse) spawnedEntity).setTamed(true);
((AbstractHorse) spawnedEntity).getInventory().addItem(new ItemStack(Material.SADDLE));
}
if (spawnedEntity instanceof Monster) {
Player closestPlayer = getNearestPlayer(player);
((Monster) spawnedEntity).setTarget(closestPlayer);
// System.out.println(spawnedEntity + "'s target set to " + closestPlayer);
spawnedEntity.customName(Component.text(player.getName() + "'s " + spawnedEntity.getType().name()));
spawnedEntity.getPersistentDataContainer().set(new NamespacedKey(plugin, "custom_mob"), PersistentDataType.INTEGER, 1);
}
if (customMob) {
String customModId = item.getItemMeta().getPersistentDataContainer().get(new NamespacedKey(plugin, "custom_mob_id"), PersistentDataType.STRING);
// System.out.println(customModId);
if (spawnedEntity instanceof Mob){
ItemStack mainHand = MobSpawnConfig.get().getItemStack(customModId + ".mainhand");
((Mob) spawnedEntity).getEquipment().setItemInMainHand(mainHand);
ItemStack offHand = MobSpawnConfig.get().getItemStack(customModId + ".offhand");
((Mob) spawnedEntity).getEquipment().setItemInOffHand(offHand);
ItemStack boots = MobSpawnConfig.get().getItemStack(customModId + ".boots");
((Mob) spawnedEntity).getEquipment().setBoots(boots);
ItemStack chestplate = MobSpawnConfig.get().getItemStack(customModId + ".chestplate");
((Mob) spawnedEntity).getEquipment().setChestplate(chestplate);
ItemStack leggings = MobSpawnConfig.get().getItemStack(customModId + ".leggings");
((Mob) spawnedEntity).getEquipment().setLeggings(leggings);
ItemStack helmet = MobSpawnConfig.get().getItemStack(customModId + ".helmet");
((Mob) spawnedEntity).getEquipment().setHelmet(helmet);
}
if (spawnedEntity instanceof Zombie) {
if (MobSpawnConfig.get().getBoolean(customModId + ".child")) {
((Zombie) spawnedEntity).setBaby();
}
((Zombie) spawnedEntity).setVisualFire(false);
((Zombie) spawnedEntity).addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 1000000, 20, false, false));
}
if (spawnedEntity instanceof Skeleton) {
((Skeleton) spawnedEntity).setVisualFire(false);
((Skeleton) spawnedEntity).addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 1000000, 20, false, false));
}
}
toBeCancelled = true;
@@ -76,11 +141,23 @@ public class OnPlayerSpawnMob implements Listener {
}, 10L);
mobOwners.put(spawnedEntity, player);
ItemStack heldItem = player.getInventory().getItemInMainHand();
player.getInventory().remove(heldItem);
int amount = item.getAmount();
item.setAmount(amount - 1);
player.getInventory().remove(item);
player.getInventory().setItemInMainHand(item);
}
// Stolen from https://www.spigotmc.org/threads/how-do-i-get-the-nearest-player.506654/
public static @Nullable Player getNearestPlayer(Player player) {
World world = player.getWorld();
Location location = player.getLocation();
ArrayList<Player> playersInWorld = new ArrayList<>(world.getEntitiesByClass(Player.class));
if(playersInWorld.size()==1) return null;
playersInWorld.remove(player); //Removes player itself
playersInWorld.sort(Comparator.comparingDouble(o -> o.getLocation().distanceSquared(location)));
return playersInWorld.get(0);
}
@EventHandler
public void playerSpawnCreature(CreatureSpawnEvent e) {
@@ -95,4 +172,26 @@ public class OnPlayerSpawnMob implements Listener {
}
}
@EventHandler
public void mobTargetEvent(EntityTargetEvent e){
Entity entity = e.getEntity();
Entity target = e.getTarget();
if (!(entity.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (!(entity instanceof Monster)) {
return;
}
e.setCancelled(true);
String entityName = entity.getName();
String playerName = entityName.split("'s")[0]; // Gets name of player who spawned it
Player player = Bukkit.getPlayerExact(playerName); // TODOX: This is quite janky, requires testing: seems to work!
Player closestPlayer = getNearestPlayer(player); // NPE has no effect it seems; target becomes null and zombie is fine with that
((Monster) entity).setTarget(closestPlayer);
// System.out.println(entity + "'s target set to " + closestPlayer);
}
}
@@ -0,0 +1,85 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand;
import me.lifelessnerd.purekitpvp.kitCommand.GetKit;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class CosmeticsCommand implements CommandExecutor {
Plugin plugin;
public CosmeticsCommand(Plugin plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
player.sendMessage(ChatColor.RED + "You can only use this menu in " + ChatColor.GRAY + plugin.getConfig().getString("world"));
return true;
}
//Create inventory GUI
TextComponent invTitle = Component.text("Cosmetics Menu").color(TextColor.color(255, 150, 20));
Inventory cosmeticsInventory = Bukkit.createInventory(null, 54, invTitle);
// Kill cosmetics button
ItemStack killEffectButton = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta killEffectButtonMeta = killEffectButton.getItemMeta();
killEffectButtonMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
killEffectButtonMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
killEffectButtonMeta.displayName(Component.text("Kill Effect").color(TextColor.color(200, 152, 0)).decoration(TextDecoration.ITALIC, false));
List<Component> loreList2 = new ArrayList<>();
TextComponent txt21 = Component.text("Change your kill effect cosmetic!").color(TextColor.color(100,100,100)).decoration(TextDecoration.ITALIC, false);
loreList2.add(txt21);
killEffectButtonMeta.lore(loreList2);
killEffectButton.setItemMeta(killEffectButtonMeta);
cosmeticsInventory.setItem(20, killEffectButton);
ItemStack trailEffectButton = new ItemStack(Material.ARROW);
ItemMeta trailEffectButtonItemMeta = trailEffectButton.getItemMeta();
trailEffectButtonItemMeta.displayName(Component.text("Projectile Trail").color(TextColor.color(200, 152, 0)).decoration(TextDecoration.ITALIC, false));
List<Component> loreList3 = new ArrayList<>();
TextComponent txt22 = Component.text("Change your projectile trail cosmetic!").color(TextColor.color(100,100,100)).decoration(TextDecoration.ITALIC, false);
loreList3.add(txt22);
trailEffectButtonItemMeta.lore(loreList3);
trailEffectButton.setItemMeta(trailEffectButtonItemMeta);
cosmeticsInventory.setItem(22, trailEffectButton);
ItemStack killMessageEffect = new ItemStack(Material.OAK_SIGN);
ItemMeta killMessageEffectItemMeta = killMessageEffect.getItemMeta();
killMessageEffectItemMeta.displayName(Component.text("Kill Message").color(TextColor.color(200, 152, 0)).decoration(TextDecoration.ITALIC, false));
List<Component> loreList = new ArrayList<>();
TextComponent txt = Component.text("Change your kill message cosmetic!").color(TextColor.color(100,100,100)).decoration(TextDecoration.ITALIC, false);
loreList.add(txt);
killMessageEffectItemMeta.lore(loreList);
killMessageEffect.setItemMeta(killMessageEffectItemMeta);
cosmeticsInventory.setItem(24, killMessageEffect);
player.openInventory(cosmeticsInventory);
return true;
}
}
@@ -0,0 +1,56 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.KillEffectInventory;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.KillMessageInventory;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories.ProjectileTrailInventory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
public class CosmeticsGUIListener implements Listener {
Plugin plugin;
public CosmeticsGUIListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
Player player = (Player) e.getWhoClicked();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (!(e.getView().title().toString().contains("Cosmetics Menu"))) {
return;
}
if (e.getCurrentItem() == null){
return;
}
ItemStack clickedItem = e.getCurrentItem();
e.setCancelled(true);
Component itemDisplayName = clickedItem.displayName();
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
String itemName = serializer.serialize(itemDisplayName);
itemName = itemName.substring(1, itemName.length() - 1); // For some reason the itemname has [] around it; frick Component
switch(itemName){
case "Kill Effect":
KillEffectInventory.openKillEffectInventory(player);
return;
case "Projectile Trail":
ProjectileTrailInventory.openProjectileTrailInventory(player);
return;
case "Kill Message":
KillMessageInventory.openKillMessageInventory(player);
return;
}
}
}
@@ -0,0 +1,37 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand;
import org.bukkit.Material;
import java.util.HashMap;
public class CosmeticsLib {
public HashMap<String, Material> killEffects = new HashMap<>();
public HashMap<String, Material> messageEffects = new HashMap<>();
public HashMap<String, Material> trailEffects = new HashMap<>();
public CosmeticsLib() {
killEffects.put("firework", Material.FIREWORK_ROCKET);
killEffects.put("blood_explosion", Material.REDSTONE);
killEffects.put("ritual", Material.FIRE_CHARGE);
killEffects.put("tornado", Material.STRING);
killEffects.put("cow_rocket", Material.COW_SPAWN_EGG);
killEffects.put("dragon_breath", Material.DRAGON_BREATH);
killEffects.put("diamond_rain", Material.DIAMOND);
messageEffects.put("default", Material.DIAMOND_SWORD);
messageEffects.put("flex", Material.GOLDEN_APPLE);
messageEffects.put("nerd", Material.GLASS);
trailEffects.put("none", Material.BARRIER);
trailEffects.put("flame", Material.FIRE_CHARGE);
trailEffects.put("sparkle", Material.END_ROD);
trailEffects.put("water_drip", Material.LILY_PAD);
trailEffects.put("heart", Material.GOLD_INGOT);
trailEffects.put("firework", Material.FIREWORK_ROCKET);
trailEffects.put("totem", Material.TOTEM_OF_UNDYING);
trailEffects.put("smoke", Material.CAMPFIRE);
}
}
@@ -0,0 +1,118 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsCommand;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsLib;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
public class KillEffectInventory implements Listener {
static Plugin plugin; // static?
public KillEffectInventory(Plugin plugin) {
KillEffectInventory.plugin = plugin;
} // could make this this.plugin
public static void openKillEffectInventory(Player player){
// This method is responsible for drawing items in inventory on clicking 'Kill Effect'
CosmeticsLib lib = new CosmeticsLib();
TextComponent invTitle = Component.text("Change Kill Effect").color(TextColor.color(255, 150, 20));
Inventory cosmeticsInventory = Bukkit.createInventory(null, 54, invTitle);
for (String killEffect : lib.killEffects.keySet()) {
ItemStack effectItem = new ItemStack(lib.killEffects.get(killEffect), 1);
ItemMeta itemMeta = effectItem.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
Component displayName = Component.text(MyStringUtils.cosmeticIdToItemName(killEffect));
//MEH: This 4x is not needed; just once at the start and then add green to that item?
String configValue = CosmeticsConfig.get().getString("kill_effect." + player.getName());
// if player is not present in file; add it to config and try again
if (configValue == null){
CosmeticsConfig.get().set(player.getName(), plugin.getConfig().getString("default-kill-effect"));
CosmeticsConfig.save();
CosmeticsConfig.reload();
configValue = CosmeticsConfig.get().getString("kill_effect." + player.getName());
}
if (configValue.equalsIgnoreCase(killEffect)){
displayName = displayName.color(NamedTextColor.GREEN).decoration(TextDecoration.ITALIC, false);
displayName = displayName.decoration(TextDecoration.BOLD, true);
itemMeta.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
} else {
displayName = displayName.color(NamedTextColor.RED).decoration(TextDecoration.ITALIC, false);;
}
itemMeta.displayName(displayName);
effectItem.setItemMeta(itemMeta);
cosmeticsInventory.addItem(effectItem);
}
ItemStack backArrow = new ItemStack(Material.ARROW);
ItemMeta backArrowIM = backArrow.getItemMeta();
backArrowIM.displayName(Component.text("Go Back").decoration(TextDecoration.ITALIC, false).color(NamedTextColor.GREEN));
backArrow.setItemMeta(backArrowIM);
cosmeticsInventory.setItem(49, backArrow);
player.openInventory(cosmeticsInventory);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
// This method is responsible for logic after a cosmetics item is clicked
Player player = (Player) e.getWhoClicked();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (!(e.getView().title().toString().contains("Change Kill Effect"))) {
return;
}
ItemStack clickedItem = e.getCurrentItem();
if (clickedItem == null){
return;
}
e.setCancelled(true);
String itemDisplayName = MyStringUtils.componentToString(clickedItem.displayName());
String attachedCosmeticName = MyStringUtils.itemNameToCosmeticId(itemDisplayName);
// Do stuff to the config with this string
// System.out.println(attachedCosmeticName);
if (itemDisplayName.equalsIgnoreCase("Go Back")){
player.closeInventory();
player.chat("/cosmetics");
return;
}
CosmeticsConfig.get().set("kill_effect." + player.getName(), attachedCosmeticName);
CosmeticsConfig.save();
CosmeticsConfig.reload();
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1,0);
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Selected " + "&c" + itemDisplayName));
e.getInventory().close(); // This is a choice I made, may not be optimal
}
}
@@ -0,0 +1,116 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsLib;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
public class KillMessageInventory implements Listener {
static Plugin plugin; // static?
public KillMessageInventory(Plugin plugin) {
KillMessageInventory.plugin = plugin;
} // could make this this.plugin
public static void openKillMessageInventory(Player player){
// This method is responsible for drawing items in inventory on clicking 'Projectile Trail'
CosmeticsLib lib = new CosmeticsLib();
TextComponent invTitle = Component.text("Change Kill Message").color(TextColor.color(255, 150, 20));
Inventory cosmeticsInventory = Bukkit.createInventory(null, 54, invTitle);
for (String messageEffect : lib.messageEffects.keySet()) {
ItemStack effectItem = new ItemStack(lib.messageEffects.get(messageEffect), 1);
ItemMeta itemMeta = effectItem.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
Component displayName = Component.text(MyStringUtils.cosmeticIdToItemName(messageEffect));
//MEH: This 4x is not needed; just once at the start and then add green to that item?
String configValue = CosmeticsConfig.get().getString("kill_message." + player.getName());
// if player is not present in file; add it to config and try again
if (configValue == null){
CosmeticsConfig.get().set("kill_message." + player.getName(), "default");
CosmeticsConfig.save();
CosmeticsConfig.reload();
configValue = CosmeticsConfig.get().getString("kill_message." + player.getName());
}
if (configValue.equalsIgnoreCase(messageEffect)){
displayName = displayName.color(NamedTextColor.GREEN).decoration(TextDecoration.ITALIC, false);
displayName = displayName.decoration(TextDecoration.BOLD, true);
itemMeta.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
} else {
displayName = displayName.color(NamedTextColor.RED).decoration(TextDecoration.ITALIC, false);;
}
itemMeta.displayName(displayName);
effectItem.setItemMeta(itemMeta);
cosmeticsInventory.addItem(effectItem);
}
ItemStack backArrow = new ItemStack(Material.ARROW);
ItemMeta backArrowIM = backArrow.getItemMeta();
backArrowIM.displayName(Component.text("Go Back").decoration(TextDecoration.ITALIC, false).color(NamedTextColor.GREEN));
backArrow.setItemMeta(backArrowIM);
cosmeticsInventory.setItem(49, backArrow);
player.openInventory(cosmeticsInventory);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
// This method is responsible for logic after a cosmetics item is clicked
Player player = (Player) e.getWhoClicked();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (!(e.getView().title().toString().contains("Change Kill Message"))) {
return;
}
ItemStack clickedItem = e.getCurrentItem();
if (clickedItem == null){
return;
}
e.setCancelled(true);
String itemDisplayName = MyStringUtils.componentToString(clickedItem.displayName());
String attachedCosmeticName = MyStringUtils.itemNameToCosmeticId(itemDisplayName);
// Do stuff to the config with this string
// System.out.println(attachedCosmeticName);
if (itemDisplayName.equalsIgnoreCase("Go Back")){
player.closeInventory();
player.chat("/cosmetics");
return;
}
CosmeticsConfig.get().set("kill_message." + player.getName(), attachedCosmeticName);
CosmeticsConfig.save();
CosmeticsConfig.reload();
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1,0);
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Selected " + "&c" + itemDisplayName));
e.getInventory().close(); // This is a choice I made, may not be optimal
}
}
@@ -0,0 +1,117 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.inventories;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsLib;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
public class ProjectileTrailInventory implements Listener {
static Plugin plugin; // static?
public ProjectileTrailInventory(Plugin plugin) {
ProjectileTrailInventory.plugin = plugin;
} // could make this this.plugin
public static void openProjectileTrailInventory(Player player){
// This method is responsible for drawing items in inventory on clicking 'Projectile Trail'
CosmeticsLib lib = new CosmeticsLib();
TextComponent invTitle = Component.text("Change Projectile Trail").color(TextColor.color(255, 150, 20));
Inventory cosmeticsInventory = Bukkit.createInventory(null, 54, invTitle);
for (String projectileTrail : lib.trailEffects.keySet()) {
ItemStack effectItem = new ItemStack(lib.trailEffects.get(projectileTrail), 1);
ItemMeta itemMeta = effectItem.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
Component displayName = Component.text(MyStringUtils.cosmeticIdToItemName(projectileTrail));
//MEH: This 4x is not needed; just once at the start and then add green to that item?
String configValue = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
// if player is not present in file; add it to config and try again
if (configValue == null){
CosmeticsConfig.get().set("projectile_trail." + player.getName(), plugin.getConfig().getString("default-projectile-trail"));
CosmeticsConfig.save();
CosmeticsConfig.reload();
configValue = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
}
if (configValue.equalsIgnoreCase(projectileTrail)){
displayName = displayName.color(NamedTextColor.GREEN).decoration(TextDecoration.ITALIC, false);
displayName = displayName.decoration(TextDecoration.BOLD, true);
itemMeta.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
} else {
displayName = displayName.color(NamedTextColor.RED).decoration(TextDecoration.ITALIC, false);;
}
itemMeta.displayName(displayName);
effectItem.setItemMeta(itemMeta);
cosmeticsInventory.addItem(effectItem);
}
ItemStack backArrow = new ItemStack(Material.ARROW);
ItemMeta backArrowIM = backArrow.getItemMeta();
backArrowIM.displayName(Component.text("Go Back").decoration(TextDecoration.ITALIC, false).color(NamedTextColor.GREEN));
backArrow.setItemMeta(backArrowIM);
cosmeticsInventory.setItem(49, backArrow);
player.openInventory(cosmeticsInventory);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
// This method is responsible for logic after a cosmetics item is clicked
Player player = (Player) e.getWhoClicked();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (!(e.getView().title().toString().contains("Change Projectile Trail"))) {
return;
}
ItemStack clickedItem = e.getCurrentItem();
if (clickedItem == null){
return;
}
e.setCancelled(true);
String itemDisplayName = MyStringUtils.componentToString(clickedItem.displayName());
String attachedCosmeticName = MyStringUtils.itemNameToCosmeticId(itemDisplayName);
// Do stuff to the config with this string
// System.out.println(attachedCosmeticName);
if (itemDisplayName.equalsIgnoreCase("Go Back")){
player.closeInventory();
player.chat("/cosmetics");
return;
}
CosmeticsConfig.get().set("projectile_trail." + player.getName(), attachedCosmeticName);
CosmeticsConfig.save();
CosmeticsConfig.reload();
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1,0);
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7Selected " + "&c" + itemDisplayName));
e.getInventory().close(); // This is a choice I made, may not be optimal
}
}
@@ -0,0 +1,207 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import net.kyori.adventure.text.Component;
import org.bukkit.*;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import javax.swing.text.html.HTMLDocument;
import java.util.logging.Level;
public class KillEffect implements Listener {
public static Plugin plugin;
public KillEffect(Plugin plugin) {
KillEffect.plugin = plugin;
}
public static void fireKillCosmetic(Player player, Player creditPlayer) {
String activeCosmetic = "firework";
try {
// This construct is weird; it works tho
activeCosmetic = CosmeticsConfig.get().getString("kill_effect." + creditPlayer.getName());
if (activeCosmetic == null){
throw new NullPointerException("Player is not defined in Cosmetics config! They have been added with default.");
}
} catch (Exception e) {
String configValue = CosmeticsConfig.get().getString("kill_effect." + creditPlayer.getName());
// if player is not present in file; add it to config and try again
if (configValue == null){
CosmeticsConfig.get().set("kill_effect." + creditPlayer.getName(), plugin.getConfig().getString("default-kill-effect"));
CosmeticsConfig.save();
CosmeticsConfig.reload();
activeCosmetic = CosmeticsConfig.get().getString("kill_effect." + creditPlayer.getName());
}
plugin.getLogger().log(Level.INFO, e.getMessage());
} // If something in the config is wrong; switch statement will pick default and do nothing
Location killLocation = player.getLocation();
Location killerLocation = creditPlayer.getLocation();
switch (activeCosmetic) { // NPE lies, try catch above fixes this
case "firework" -> {
firework(killLocation);
}
case "blood_explosion" -> {
bloodExplosion(killLocation);
}
case "ritual" -> {
ritual(killLocation);
}
case "tornado" -> {
tornado(killLocation);
}
case "cow_rocket" -> {
cow_rocket(killLocation);
}
case "dragon_breath" -> {
dragon_breath(killLocation);
}
case "diamond_rain" -> {
diamond_rain(killLocation);
}
default -> {
//Idk how you would end up here: Do nothing
}
}
}
public static void firework(Location location) {
location = location.add(0,1.4,0);
Firework fw = (Firework) location.getWorld().spawnEntity(location, EntityType.FIREWORK);
FireworkMeta fwm = fw.getFireworkMeta();
fwm.addEffect(FireworkEffect.builder().withColor(Color.RED).withColor(Color.WHITE).flicker(true).build());
fw.setMetadata("nodamage", new FixedMetadataValue(plugin, true));
fw.setFireworkMeta(fwm);
fw.detonate();
}
@EventHandler
public void preventFireworkDamage(EntityDamageByEntityEvent e) {
if (e.getDamager() instanceof Firework) {
Firework fw = (Firework) e.getDamager();
if (fw.hasMetadata("nodamage")) {
e.setCancelled(true);
}
}
}
public static void bloodExplosion(Location location) {
for (float i = 0.5f; i < 1.8f; i += 0.1) {
location.getWorld().spawnParticle(
Particle.BLOCK_CRACK,
location.add(0,i,0),
20,
Material.REDSTONE_BLOCK.createBlockData()
);
}
}
public static void ritual(Location location) {
for (int i = 0; i < 360; i += 20) {
Location flameloc = location.add(0,1.2,0);
flameloc.setZ(flameloc.getZ() + Math.cos(i) * 0.7);
flameloc.setX(flameloc.getX() + Math.sin(i) * 0.7);
location.getWorld().spawnParticle(Particle.FLAME, flameloc, 10, 0, 0, 0, 0.001);
}
for (int i = 0; i < 360; i += 10) {
Location flameloc = location.add(0,0.6,0);
flameloc.setZ(flameloc.getZ() + Math.cos(i) * 1.5);
flameloc.setX(flameloc.getX() + Math.sin(i) * 1.5);
location.getWorld().spawnParticle(Particle.FLAME, flameloc, 10, 0, 0, 0, 0.001);
}
for (int i = 0; i < 360; i += 5) {
Location flameloc = location;
double extendedZ = flameloc.getZ() + Math.cos(i) / 2;
double extendedX = flameloc.getZ() + Math.cos(i) / 2;
flameloc.setZ(flameloc.getZ() + Math.cos(i) * 2);
flameloc.setX(flameloc.getX() + Math.sin(i) * 2);
location.getWorld().spawnParticle(Particle.CLOUD, flameloc, 1, extendedX, 0, extendedZ, 0.001);
}
}
public static void tornado(Location location) {
for (double i = 1; i < 4; i = i + 0.4) {
double newY = location.getY() + i;
for (double j = 0; j < 360; j += 20) {
double newZ = (location.getZ() + Math.cos(j) * (1 * Math.sqrt(i) - 0.5));
double newX = (location.getX() + Math.sin(j) * (1 * Math.sqrt(i) - 0.5));
location.getWorld().spawnParticle(Particle.FLAME, newX, newY, newZ, 1, 0.1, 0.5, 0.1, 0.001);
}
}
location.getWorld().playSound(location, Sound.ENTITY_ENDER_DRAGON_SHOOT, 1f, 1);
}
public static void cow_rocket(Location location) {
Entity cow = location.getWorld().spawnEntity(location, EntityType.COW);
cow.setGravity(false);
cow.teleport(location.add(0,2,0));
new BukkitRunnable() {
int i = 0;
@Override
public void run () {
cow.teleport(location.add(0,0.2,0));
cow.getLocation().getWorld().playSound(location, Sound.BLOCK_NOTE_BLOCK_PLING, 1, i*0.1f);
cow.getLocation().getWorld().spawnParticle(Particle.GLOW_SQUID_INK, location, 2,0.1, 0.1, 0.1, 0.001);
if (i >= 16){
this.cancel();
cow.remove();
cow.getLocation().createExplosion(0, false, false);
}
i++;
}
}.runTaskTimer(plugin, 0, 1);
}
private static void dragon_breath(Location location) {
location.getWorld().spawnParticle(Particle.DRAGON_BREATH, location, 500, 0.2, 1, 0.2, 0.05);
location.getWorld().playSound(location, Sound.BLOCK_ENCHANTMENT_TABLE_USE, 1, 1);
}
private static void diamond_rain(Location location){
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
ItemStack is = new ItemStack(Material.DIAMOND, 1);
ItemMeta im = is.getItemMeta();
im.displayName(Component.text(i)); // Change display name so they do not stack
is.setItemMeta(im);
Item dropped = location.getWorld().dropItemNaturally(location, is);
dropped.getPersistentDataContainer().set(new NamespacedKey(plugin, "cosmetic"), PersistentDataType.BOOLEAN, true);
// PDC attached to entity instead if itemstack, these (apparently) do not transfer between states
location.getWorld().playSound(location, Sound.ENTITY_ITEM_PICKUP, 1, 1);
Bukkit.getScheduler().runTaskLater(plugin, dropped::remove, 100L); // IDEA lambda magic
if (i >= 10){
this.cancel();
}
i++;
}
}.runTaskTimer(plugin, 0, 2);
}
}
@@ -0,0 +1,98 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners;
import me.lifelessnerd.purekitpvp.PluginGetter;
import me.lifelessnerd.purekitpvp.combathandlers.libs.DamageCauseLib;
import me.lifelessnerd.purekitpvp.combathandlers.libs.DeathCauseLib;
import me.lifelessnerd.purekitpvp.cosmetics.cosmeticsCommand.CosmeticsCommand;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Set;
import java.util.logging.Level;
public class KillMessage {
public static class create {
public static String byEnvironment(String player, String lastEnvironmentHit){
// System.out.println("byEnvironment");
DamageCauseLib damageCauseLib = new DamageCauseLib();
return player + damageCauseLib.deathMessages.get(lastEnvironmentHit);
}
public static String byEnvironmentAndPlayer(String player, String killer, String environmentHit){
// System.out.println("byEnvironmentAndPlayer");
DeathCauseLib deathCauseLib = new DeathCauseLib();
Set<String> interestingCauses = deathCauseLib.defaultDeathMessages.keySet();
if(interestingCauses.contains(environmentHit)){
String preprocessed = player + getCosmeticMessage(player, environmentHit, false);
return preprocessed.replace("{killer}", killer);
} else {
return (player + getCosmeticMessage(player, environmentHit, true)).replace("{killer}", killer);
}
}
public static String byPlayer(String player, String killer){
// System.out.println("byPlayer");
String preprocessed = getCosmeticMessage(killer, null, true);
// System.out.println(preprocessed);
return player + preprocessed.replace("{killer}", killer);
}
}
public static String getCosmeticMessage(String player, String environmentHit, boolean killMessage) {
DeathCauseLib deathCauseLib = new DeathCauseLib();
String activeCosmetic = "default";
try {
// This construct is weird; it works tho
activeCosmetic = CosmeticsConfig.get().getString("kill_message." + player);
if (activeCosmetic == null) {
throw new NullPointerException("Player is not defined in Cosmetics config! They have been added with default.");
}
} catch (Exception e) {
String configValue = CosmeticsConfig.get().getString("kill_message." + player);
// if player is not present in file; add it to config and try again
if (configValue == null) {
CosmeticsConfig.get().set("kill_message." + player, "default");
CosmeticsConfig.save();
CosmeticsConfig.reload();
activeCosmetic = CosmeticsConfig.get().getString("kill_effect." + player);
}
PluginGetter.Plugin().getLogger().log(Level.INFO, e.getMessage());
} // If something in the config is wrong; switch statement will pick default and do nothing
if (killMessage) {
switch (activeCosmetic) {
case "flex":
int kills = 1;
String killsString;
try {
kills = PlayerStatsConfig.get().getInt(player + ".kills");
} catch(Exception e){
kills = 1;
}
killsString = Integer.toString(kills + 1);
return (deathCauseLib.flexKillMessages.get(0)).replace("{kills}", killsString);
case "nerd":
return deathCauseLib.nerdKillMessages.get(0);
case "default":
return deathCauseLib.defaultKillMessages.get(0);
}
} else {
// Death message
switch (activeCosmetic) {
case "flex":
return deathCauseLib.flexDeathMessages.get(environmentHit);
case "nerd":
return deathCauseLib.nerdDeathMessages.get(environmentHit);
case "default":
return deathCauseLib.defaultDeathMessages.get(environmentHit);
}
}
PluginGetter.Plugin().getLogger().warning("Kill Message Cosmetics Error: config file contains faulty values!");
return "???";
}
}
@@ -0,0 +1,173 @@
package me.lifelessnerd.purekitpvp.cosmetics.cosmeticsListeners;
import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent;
import me.lifelessnerd.purekitpvp.files.CosmeticsConfig;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.AbstractArrow;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
public class ProjectileTrail implements Listener {
/* TODO: THIS CLASS HAS DUPOLICATE CODE because of the difference in events -> can be circumvented by passing projectile and player
TODO: can it? since one is projectile and the other is abstractarrow?? CROSSBOWS are added but is a projectile*/
Plugin plugin;
public ProjectileTrail(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onProjectileLaunch(PlayerLaunchProjectileEvent e) {
Player player = e.getPlayer();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
String trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
if(trail == null){
CosmeticsConfig.get().set("projectile_trail." + player, "none");
CosmeticsConfig.save();
CosmeticsConfig.reload();
trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
}
// Inspiration from https://github.com/iInvisibilities/spiraltrails/blob/main/SpiralFactory.java
// Not used right now, maybe in the future: this would allow for spirals and such
Projectile projectile = e.getProjectile();
// System.out.println(projectile.toString());
int rotationSpeed = 30;
final double INCREMENT = (2 * Math.PI) / rotationSpeed;
new BukkitRunnable() {
double circlePointOffset = 0;
Location lastLocation = player.getEyeLocation();
@Override
public void run() {
if(projectile.isDead() || projectile.isOnGround()) {
this.cancel();
return;
}
String trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
// Could be removed: pass trail into the runnable once at event (How?)
// How? with a class that implements Runnable - a lot of code -> this is fine
Location location = projectile.getLocation();
// System.out.println(trail);
switch(trail){
case "none":
return;
case "flame":
location.getWorld().spawnParticle(Particle.FLAME, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "sparkle":
location.getWorld().spawnParticle(Particle.END_ROD, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "water_drip":
location.getWorld().spawnParticle(Particle.DRIP_WATER, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "heart":
location.getWorld().spawnParticle(Particle.HEART, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "firework":
location.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "totem":
location.getWorld().spawnParticle(Particle.TOTEM, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "smoke":
location.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
default:
break;
}
}
}.runTaskTimer(plugin, 2, plugin.getConfig().getInt("projectile-trail-period"));
}
@EventHandler
public void onArrowShoot(EntityShootBowEvent e){
if (!(e.getEntity() instanceof Player player)){
return;
}
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
String trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
if(trail == null){
CosmeticsConfig.get().set("projectile_trail." + player, "none");
CosmeticsConfig.save();
CosmeticsConfig.reload();
trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
}
// Inspiration from https://github.com/iInvisibilities/spiraltrails/blob/main/SpiralFactory.java
// Not used right now, maybe in the future: this would allow for spirals and such
Projectile arrow = (Projectile) e.getProjectile();
// Not necessarily an arrow, could be a firework
int rotationSpeed = 30;
final double INCREMENT = (2 * Math.PI) / rotationSpeed;
new BukkitRunnable() {
double circlePointOffset = 0;
Location lastLocation = player.getEyeLocation();
@Override
public void run() {
if(arrow.isDead() || arrow.isOnGround()) { // hopefully this is most of em
this.cancel();
return;
}
String trail = CosmeticsConfig.get().getString("projectile_trail." + player.getName());
Location location = arrow.getLocation();
// System.out.println(trail);
switch(trail){
case "none":
return;
case "flame":
location.getWorld().spawnParticle(Particle.FLAME, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "sparkle":
location.getWorld().spawnParticle(Particle.END_ROD, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "water_drip":
location.getWorld().spawnParticle(Particle.DRIP_WATER, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "heart":
location.getWorld().spawnParticle(Particle.HEART, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "firework":
location.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "totem":
location.getWorld().spawnParticle(Particle.TOTEM, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
case "smoke":
location.getWorld().spawnParticle(Particle.CAMPFIRE_COSY_SMOKE, location, plugin.getConfig().getInt("projectile-trail-count"), 0.1, 0.1, 0.1, 0.001);
break;
default:
break;
}
}
}.runTaskTimer(plugin, 2, plugin.getConfig().getInt("projectile-trail-period"));
}
}
@@ -52,7 +52,7 @@ public class CreateKit extends Subcommand {
return true;
}
if (!(args.length >= 2)){
if (!(args.length >= 4)){
player.sendMessage(ChatColor.RED + "Please provide arguments!");
return false;
}
@@ -64,7 +64,7 @@ public class CreateKit extends Subcommand {
String kitName = args[1].toLowerCase();
kitName = kitName.substring(0, 1).toUpperCase() + kitName.substring(1);
String displayColor = args[2];
if (!(args.length >= 4)){
if (!(args.length >= 5)){
player.sendMessage("Provide arguments!");
return false;
@@ -129,7 +129,7 @@ public class CreateKit extends Subcommand {
player.sendMessage(ChatColor.translateAlternateColorCodes('&',
"Kit created with following properties: \nKitName: &a" + kitName +
"&r\n displayColor: &a" + displayColor + "&r\n kitIcon: &a"
"&r\n displayColor: &a" + displayColor + "■" + "&r\n kitIcon: &a"
+ kitIcon + "&r\n kitPermission: &a" + kitPermission + "&r\nkillItem: &a" + killItem));
player.sendMessage("You can change these in the kits.yml file, but remember to backup the file when manually editing.");
@@ -0,0 +1,133 @@
package me.lifelessnerd.purekitpvp.createKit;
import me.lifelessnerd.purekitpvp.Subcommand;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkLib;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
public class SetPerk extends Subcommand {
Plugin plugin;
public SetPerk(Plugin plugin) {
this.plugin = plugin;
}
@Override
public String getName() {
return "setperk";
}
@Override
public String[] getAliases() {
return null;
}
@Override
public String getDescription() {
return "Set perk values for this kit";
}
@Override
public String getSyntax() {
return "/purekitpvp setperk <kit> <perk> <true/false>";
}
@Override
public boolean perform(Player player, String[] args) {
if (!player.hasPermission("purekitpvp.admin.createkit")){
player.sendMessage(ChatColor.RED + "No permission!");
return true;
}
if (!(args.length >= 2)){
player.sendMessage(ChatColor.RED + "Please provide arguments!");
return false;
}
String kitNameArg = MyStringUtils.camelCaseWord(args[1]);
ArrayList<String> kitNames = new ArrayList<>();
ConfigurationSection kitsSection = KitConfig.get().getConfigurationSection("kits");
// This nesting is painful but it works okay
if (kitNameArg.equalsIgnoreCase("all")){
kitNames.addAll(kitsSection.getKeys(false));
} else {
if (!(KitConfig.get().isSet("kits." + kitNameArg))){
player.sendMessage(ChatColor.GRAY + "That kit does not exist.");
return true;
} else {
kitNames.add(kitNameArg);
}
}
String perkNameArg = args[2].toUpperCase();
PerkLib perkLib = new PerkLib();
ArrayList<String> perkNames = new ArrayList<>();
// This nesting is painful but it works okay
if (perkNameArg.equalsIgnoreCase("all")){
perkNames.addAll(perkLib.perks.keySet());
} else {
if (!(perkLib.perks.containsKey(perkNameArg))){
player.sendMessage(ChatColor.GRAY + "That perk does not exist. Choose from the following:");
for (String key : perkLib.perks.keySet()){
player.sendMessage(ChatColor.GREEN + key);
player.sendMessage(ChatColor.GRAY + perkLib.perks.get(key));
}
return true;
} else {
perkNames.add(perkNameArg);
}
}
String booleanArg = args[3].toLowerCase();
if (!(booleanArg.equalsIgnoreCase("true") || booleanArg.equalsIgnoreCase("false"))){
player.sendMessage(ChatColor.GRAY + "Provide either true or false.");
return true;
}
if (booleanArg.equalsIgnoreCase("true")) {
for(String kitName : kitNames){
for(String perkName : perkNames) {
KitConfig.get().set("kits." + kitName + ".perks." + perkName, true);
player.sendMessage(ChatColor.translateAlternateColorCodes('&',
"&7Perk &e" + perkName + " &7updated to &aTRUE&7 for kit &e" + kitName
));
}
}
} else { // i.e. false
for (String kitName : kitNames) {
for (String perkName : perkNames) {
KitConfig.get().set("kits." + kitName + ".perks." + perkName, null);
player.sendMessage(ChatColor.translateAlternateColorCodes('&',
"&7Perk &e" + perkName + " &7updated to &cFALSE&7 for kit &e" + kitName
));
}
}
}
KitConfig.save();
KitConfig.reload();
return true;
}
}
@@ -1,15 +1,22 @@
package me.lifelessnerd.purekitpvp.customitems;
import me.lifelessnerd.purekitpvp.PluginGetter;
import me.lifelessnerd.purekitpvp.Subcommand;
import me.lifelessnerd.purekitpvp.files.LootTablesConfig;
import me.lifelessnerd.purekitpvp.files.MobSpawnConfig;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,7 +40,7 @@ public class GetCustomItem extends Subcommand {
@Override
public String getSyntax() {
return "/purekitpvp getcustomitem <golden_head/random_chest>";
return "/purekitpvp getcustomitem <golden_head/random_chest/custom_mob_egg>";
}
@Override
@@ -43,8 +50,8 @@ public class GetCustomItem extends Subcommand {
ItemStack goldenHead = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) goldenHead.getItemMeta();
meta.displayName(Component.text("Golden Head"));
String[] loreList = {"Golden Head"};
meta.displayName(Component.text("Golden Head").decoration(TextDecoration.ITALIC, false));
String[] loreList = {"Healing Item"};
meta.setLore(Arrays.asList(loreList));
meta.setOwningPlayer(Bukkit.getOfflinePlayer("PhantomTupac"));
goldenHead.setItemMeta(meta);
@@ -75,6 +82,26 @@ public class GetCustomItem extends Subcommand {
return true;
} else if(args[1].equalsIgnoreCase("custom_mob_egg")){
if (!(MobSpawnConfig.get().isSet(args[2]))){
player.sendMessage("Such custom mob does not exist!");
return false;
}
// Try catch dit miss?
String type = MobSpawnConfig.get().getString(args[2] + ".type");
ItemStack egg = new ItemStack(Material.valueOf(type + "_SPAWN_EGG"));
ItemMeta eggMeta = egg.getItemMeta();
List<Component> lore = new ArrayList<>();
lore.add(Component.text("Custom Mob Spawner Egg"));
eggMeta.lore(lore);
PersistentDataContainer data = eggMeta.getPersistentDataContainer();
data.set(new NamespacedKey(PluginGetter.Plugin(), "custom_mob_id"), PersistentDataType.STRING, args[2]);
egg.setItemMeta(eggMeta);
player.getInventory().addItem(egg);
}
return false;
}
@@ -46,7 +46,7 @@ public class GoldenHeadEat implements Listener {
ItemStack heldItem = player.getInventory().getItemInMainHand();
String desiredLore = "Golden Head"; //TODO: Might make this customizable later
String desiredLore = "Healing Item";
if (!(heldItem.getItemMeta().hasLore())) {
@@ -57,10 +57,16 @@ public class GoldenHeadEat implements Listener {
return;
}
heldItem.setAmount(heldItem.getAmount() - 1);
int slot = player.getInventory().getHeldItemSlot();
player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 100, 2));
player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 400, 0));
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 200, 1));
player.getInventory().remove(heldItem);
player.getInventory().setItem(slot, heldItem);
// This is suboptimal, but apparently removing itemstack with amount 1 does not work
// Side effect is change in inventory slot possibly
// FIXED using SLOT
}
}
@@ -1,6 +1,7 @@
package me.lifelessnerd.purekitpvp.customitems;
import me.lifelessnerd.purekitpvp.files.LootTablesConfig;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@@ -64,9 +65,13 @@ public class OpenRandomChest implements Listener {
}
}
if (currentLootTable == null){
player.sendMessage("This loottable is not defined.");
plugin.getLogger().warning("Player " + player.getName() + " attempted to open a loottable with lore " + itemLore + ", but no loottable was found!");
plugin.getLogger().warning("Player " + player.getName() + " current kit is " + PlayerStatsConfig.get().getString(player.getName() + ".current_kit"));
return;
}
player.getInventory().remove(heldItem);
// Giving algorithm
if (LootTablesConfig.get().getBoolean(currentLootTable + ".guaranteed.enabled")){
//Guaranteed items algo
@@ -112,7 +117,7 @@ public class OpenRandomChest implements Listener {
}
player.playSound(player, Sound.BLOCK_NOTE_BLOCK_BELL, 1, 1);
player.getInventory().remove(heldItem);
if (heldItem.getAmount() > 1){
int itemsAdded = 0;
@@ -42,7 +42,7 @@
// }
//
// if (args.length < 1){
// player.sendMessage("Please specify what function to use."); //TODO: Add all options in a message
// player.sendMessage("Please specify what function to use.");
// return false;
// }
//
@@ -55,7 +55,7 @@
// }
//
//
// player.sendMessage(args[0] + " is not a valid sub-command."); //TODO: Add all options in a message same as above
// player.sendMessage(args[0] + " is not a valid sub-command.");
// return false;
//
// }
@@ -33,16 +33,16 @@ public class GetGoldenHead extends Subcommand {
@Override
public boolean perform(Player player, String[] args) {
ItemStack goldenHead = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) goldenHead.getItemMeta();
meta.displayName(Component.text("Golden Head"));
String[] loreList = {"Golden Head"};
meta.setLore(Arrays.asList(loreList));
meta.setOwningPlayer(Bukkit.getOfflinePlayer("PhantomTupac"));
goldenHead.setItemMeta(meta);
player.getInventory().addItem(goldenHead);
// System.out.println("dab");
// ItemStack goldenHead = new ItemStack(Material.PLAYER_HEAD);
// SkullMeta meta = (SkullMeta) goldenHead.getItemMeta();
// meta.displayName(Component.text("Golden Head"));
// String[] loreList = {"Healing Item"};
// meta.setLore(Arrays.asList(loreList));
// meta.setOwningPlayer(Bukkit.getOfflinePlayer("PhantomTupac"));
// goldenHead.setItemMeta(meta);
//
// player.getInventory().addItem(goldenHead);
return true;
}
@@ -105,7 +105,7 @@ public class CreateLootTable extends Subcommand {
player.sendMessage(
"Loot table created. \nTo specify chances per item, and add multi-word lore" +
"please use the loottables.yml config!");
" please use the loottables.yml config!");
player.sendMessage("When manually editing loottables.yml, remember to back it up if it contains a lot of information.");
LootTablesConfig.save();
@@ -0,0 +1,119 @@
package me.lifelessnerd.purekitpvp.custommobs;
import me.lifelessnerd.purekitpvp.Subcommand;
import me.lifelessnerd.purekitpvp.files.MobSpawnConfig;
import me.lifelessnerd.purekitpvp.utils.ComponentUtils;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
public class CustomMobCommand extends Subcommand {
@Override
public String getName() {
return "custommob";
}
@Override
public String[] getAliases() {
return null;
}
@Override
public String getDescription() {
return "Create custom mobs that can be used in kits as spawn eggs";
}
@Override
public String getSyntax() {
return "/purekitpvp custommob <create/delete/set> <identifier>";
}
@Override
public boolean perform(Player player, String[] args) {
if (args.length <= 1){
player.sendMessage("Please provide arguments!");
return true;
}
if (args[1].equalsIgnoreCase("create")){
if (args.length <= 3){
player.sendMessage("Please provide arguments!");
return true;
}
//String customMobName = args[2];
MobSpawnConfig.get().set(args[2], null);
MobSpawnConfig.get().set(args[2] + ".type", EntityType.valueOf(args[3].toUpperCase()).toString());
MobSpawnConfig.get().set(args[2] + ".child", false);
MobSpawnConfig.get().set(args[2] + ".helmet", null);
MobSpawnConfig.get().set(args[2] + ".chestplate", null);
MobSpawnConfig.get().set(args[2] + ".leggings", null);
MobSpawnConfig.get().set(args[2] + ".boots", null);
MobSpawnConfig.get().set(args[2] + ".mainhand", null);
MobSpawnConfig.get().set(args[2] + ".offhand", null);
player.sendMessage("Custom mob created with type " + args[3] + ", identifier " + args[2]);
player.sendMessage("You can now change its equipment using /purekitpvp custommob set");
MobSpawnConfig.save();
MobSpawnConfig.reload();
return true;
}
if (args[1].equalsIgnoreCase("set")){
if (args.length <= 3){
player.sendMessage("Please provide arguments!");
player.sendMessage("Usage: /purekitpvp custommob set <helmet/chestplate/leggings/boots/mainhand/offhand>");
return true;
}
// First the identifier as arg, check if there is such a key
if (!(MobSpawnConfig.get().isSet(args[2]))) {
player.sendMessage("That custom mob is not defined!");
}
//Possible args should be: helmet, chestplate, leggings, boots, mainhand, offhand
String[] possibleArgs = {"helmet", "chestplate", "leggings", "boots", "mainhand", "offhand"};
if (Arrays.asList(possibleArgs).contains(args[3])) {
setEquipment(player, args[2], args[3]);
player.sendMessage(args[2] + "'s " + args[3] + " was changed to the item you held.");
} else if(args[3].equalsIgnoreCase("child")){
if (args.length == 5 && (args[4].equalsIgnoreCase("true") || args[4].equalsIgnoreCase("false"))){
MobSpawnConfig.get().set(args[2] + ".child", Boolean.valueOf(args[4]));
MobSpawnConfig.save();
MobSpawnConfig.reload();
player.sendMessage("Custom mob " + args[2] + " property " + args[3] + " set to " + args[4]);
} else {
player.sendMessage("When using argument 'child', follow with either true or false.");
return true;
}
} else {
player.sendMessage("Possible arguments are: child (requires true/false argument), helmet, chestplate, leggings, boots, mainhand, offhand");
}
return true;
}
if (args[1].equalsIgnoreCase("delete")){
MobSpawnConfig.get().set(args[2], null);
player.sendMessage("Custom mob " + args[2] + " deleted.");
MobSpawnConfig.save();
MobSpawnConfig.reload();
return true;
}
else {
player.sendMessage("Invalid argument!");
}
return true;
}
public static void setEquipment(Player player, String mobName, String slot){
ItemStack heldItem = player.getInventory().getItemInMainHand();
MobSpawnConfig.get().set(mobName + "." + slot, heldItem);
MobSpawnConfig.save();
MobSpawnConfig.reload();
}
}
@@ -0,0 +1,45 @@
package me.lifelessnerd.purekitpvp.files;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class CosmeticsConfig {
private static File file;
private static FileConfiguration customFile;
public static void setup(){
file = new File(Bukkit.getServer().getPluginManager().getPlugin("PureKitPvP").getDataFolder(), "cosmetics.yml");
if (!(file.exists())){
try{
file.createNewFile();
} catch (IOException e){
//pain
}
}
customFile = YamlConfiguration.loadConfiguration(file);
}
public static FileConfiguration get(){
return customFile;
}
public static void save(){
try{
customFile.save(file);
} catch (IOException e){
System.out.println("Cannot save!");
}
}
public static void reload(){
customFile = YamlConfiguration.loadConfiguration(file);
}
}
@@ -0,0 +1,45 @@
package me.lifelessnerd.purekitpvp.files;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class MobSpawnConfig {
private static File file;
private static FileConfiguration customFile;
public static void setup(){
file = new File(Bukkit.getServer().getPluginManager().getPlugin("PureKitPvP").getDataFolder(), "mobsconfig.yml");
if (!(file.exists())){
try{
file.createNewFile();
} catch (IOException e){
//pain
}
}
customFile = YamlConfiguration.loadConfiguration(file);
}
public static FileConfiguration get(){
return customFile;
}
public static void save(){
try{
customFile.save(file);
} catch (IOException e){
System.out.println("Cannot save!");
}
}
public static void reload(){
customFile = YamlConfiguration.loadConfiguration(file);
}
}
@@ -0,0 +1,64 @@
package me.lifelessnerd.purekitpvp.files;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
public class PerkData {
private static File file;
private static FileConfiguration customFile;
public static void setup(){
file = new File(Bukkit.getServer().getPluginManager().getPlugin("PureKitPvP").getDataFolder(), "perkdata.yml");
if (!(file.exists())){
try{
file.createNewFile();
} catch (IOException e){
//pain
}
}
customFile = YamlConfiguration.loadConfiguration(file);
}
public static FileConfiguration get(){
return customFile;
}
public static void save(){
try{
customFile.save(file);
} catch (IOException e){
System.out.println("Cannot save!");
}
}
public static void reload(){
customFile = YamlConfiguration.loadConfiguration(file);
}
public static void setPerk(Player player, String perkName, int slot){
FileConfiguration perkData = PerkData.get();
if (!(perkData.isSet(player.getName()))){
createSection(player);
}
perkData.set(player.getName() + ".slot" + slot, perkName);
}
public static void createSection(Player player){
FileConfiguration perkData = PerkData.get();
perkData.set(player.getName() + ".slot1", null);
perkData.set(player.getName() + ".slot2", null);
perkData.set(player.getName() + ".slot3", null);
perkData.set(player.getName() + ".slot4", null);
perkData.set(player.getName() + ".slot5", null);
}
}
@@ -1,14 +1,30 @@
package me.lifelessnerd.purekitpvp.kitCommand;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkLib;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class GUIListener implements Listener {
@@ -25,14 +41,17 @@ public class GUIListener implements Listener {
if (player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world"))){
if (!(e.getCurrentItem() == null && e.getRawSlot() >= 53)){ //NPE, idk why
if (!(e.getCurrentItem() == null && e.getRawSlot() >= 53)){
ItemStack clickedItem = e.getCurrentItem();
InventoryView inv = e.getView();
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
if (inv.title().toString().contains("Kits")) { //I hate component
if (!(e.getRawSlot() == 53)){ // 53 is reset button
if (e.getRawSlot() < 45){
e.setCancelled(true);
if(clickedItem == null){ //
if(clickedItem == null){
return;
}
String displayName = clickedItem.getItemMeta().getDisplayName();
@@ -40,7 +59,8 @@ public class GUIListener implements Listener {
player.chat("/getkit " + displayName);
player.closeInventory();
}
else {
else if (e.getRawSlot() == 53){ // Reset button
e.setCancelled(true);
if (player.hasPermission("purekitpvp.admin.resetkit")){
player.chat("/purekitpvp resetkit");
@@ -48,6 +68,31 @@ public class GUIListener implements Listener {
else {
player.chat("/suicide");
}
} else if (e.getRawSlot() == 49){ // Perk help button
e.setCancelled(true);
player.chat("/perks");
} else if (e.getRawSlot() == 48){ // Prev page button
if (e.getCurrentItem().equals(new ItemStack(Material.AIR))){
return;
}
e.setCancelled(true);
String title = serializer.serialize(e.getView().title());
int prevPage = Integer.parseInt(title.split(" - ")[1]) - 1;
player.chat("/kit " + prevPage);
} else if (e.getRawSlot() == 50){ // Next page button
if (e.getCurrentItem().equals(new ItemStack(Material.AIR))){
return;
}
e.setCancelled(true);
String title = serializer.serialize(e.getView().title());
int nextPage = Integer.parseInt(title.split(" - ")[1]) + 1;
player.chat("/kit " + nextPage);
}
}
@@ -73,7 +73,7 @@ public class GetKit implements TabExecutor, Listener {
}
if(!KitConfig.get().isSet("kits." + kitNameArg + ".permission")){
player.sendMessage(ChatColor.GRAY + "That kit does not have a permission associated. Please report to your administrator.");
player.sendMessage(ChatColor.GRAY + "That kit does not have a permission associated. Please report this to your administrator.");
return true;
}
@@ -98,15 +98,16 @@ public class GetKit implements TabExecutor, Listener {
if (item == null) {
item = new ItemStack(Material.AIR);
}
// This code is from PureKits, idk why it works (.setHelmet is called for every armor piece?)
player.getInventory().setItem(index, item);
ItemStack helmet = fileConfiguration.getItemStack("kits." + kitNameArg + ".helmet");
player.getInventory().setHelmet(helmet);
ItemStack chestplate = fileConfiguration.getItemStack("kits." + kitNameArg + ".helmet");
player.getInventory().setChestplate(chestplate);
player.getInventory().setHelmet(chestplate);
ItemStack leggings = fileConfiguration.getItemStack("kits." + kitNameArg + ".helmet");
player.getInventory().setLeggings(leggings);
player.getInventory().setHelmet(leggings);
ItemStack boots = fileConfiguration.getItemStack("kits." + kitNameArg + ".helmet");
player.getInventory().setBoots(boots);
player.getInventory().setHelmet(boots);
}
hasKit.add(player.getName());
@@ -6,12 +6,14 @@ import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
@@ -23,8 +25,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.bukkit.util.NumberConversions.floor;
public class KitsGUI implements TabExecutor {
Plugin plugin;
@@ -50,29 +55,83 @@ public class KitsGUI implements TabExecutor {
player.sendMessage(ChatColor.RED + "You can only use this menu in " + ChatColor.GRAY + plugin.getConfig().getString("world"));
return true;
}
// Only argument is used for page, the plugin will run /kits 2 at some point for the second page of kits
int currentPage = 1;
if (args.length >= 1) {
currentPage = Integer.parseInt(args[0]);
}
//Create inventory GUI
TextComponent inventoryTitle = Component.text("Kits").color(TextColor.color(255, 150, 20));
TextComponent inventoryTitle = Component.text("Kits - ").
color(TextColor.color(255, 150, 20)).
append(Component.text(currentPage));
Inventory kits = Bukkit.createInventory(null, 54, inventoryTitle);
int amountOfKits = KitConfig.get().getConfigurationSection("kits").getKeys(false).size();
int lastPage = floor(((double) amountOfKits / 46)) + 1;
// Will a second page be necessary?
if (amountOfKits >= 45 && (currentPage != lastPage)){ // On last page? Don't show next item
// Create next page item
ItemStack nextPageButton = new ItemStack(Material.ARROW);
ItemMeta nextPageButtonMeta = nextPageButton.getItemMeta();
nextPageButtonMeta.displayName(Component.text("Next").decoration(TextDecoration.ITALIC, false));
List<Component> loreList = new ArrayList<>();
TextComponent txt = Component.text("Go to the next kit selection page.").
decoration(TextDecoration.ITALIC, false).
color(TextColor.color(100,100,100));
loreList.add(txt);
nextPageButtonMeta.lore(loreList);
nextPageButton.setItemMeta(nextPageButtonMeta);
kits.setItem(50, nextPageButton);
loreList.clear();
}
if (currentPage > 1){
// If this, we need a prev button too
ItemStack prevPageButton = new ItemStack(Material.ARROW);
ItemMeta prevPageButtonMeta = prevPageButton.getItemMeta();
prevPageButtonMeta.displayName(Component.text("Previous").decoration(TextDecoration.ITALIC, false));
List<Component> loreList = new ArrayList<>();
TextComponent txt = Component.text("Go to the previous kit selection page.").
decoration(TextDecoration.ITALIC, false).
color(TextColor.color(100,100,100));
loreList.add(txt);
prevPageButtonMeta.lore(loreList);
prevPageButton.setItemMeta(prevPageButtonMeta);
kits.setItem(48, prevPageButton);
loreList.clear();
}
int kitNumber = 1;
for (String key : KitConfig.get().getConfigurationSection("kits").getKeys(false)) {
// What page should this kit be put on?
int intendedPage = floor(((double) kitNumber / 46)) + 1;
kitNumber++;
if (intendedPage != currentPage){ // Not this page? Don't do anything
continue;
}
ItemStack itemStack = new ItemStack(Material.BARRIER);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
//NPE GALORE, TODO: idiot proof if these keys do not exist, instead of crashing entire plugin with an NPE
//TODO: Actually i have no idea what this is referring to, I get no NPE's in the GUI ever
//Set block
//Set gui item
itemStack.setType(Material.getMaterial(KitConfig.get().getString("kits." + key + ".guiitem")));
//Set lore
//Set lore
String loreText = KitConfig.get().getString("kits." + key + ".guilore");
loreText = ChatColor.translateAlternateColorCodes('&', loreText);
ArrayList<String> lore = new ArrayList<>();
lore.add(loreText);
// If no permission: set gui item to red stained glass pane and a bit of lore is added to explain the situation
if (!(player.hasPermission(KitConfig.get().getString("kits." + key + ".permission")))){
itemStack.setType(Material.RED_STAINED_GLASS_PANE);
lore.add(ChatColor.translateAlternateColorCodes('&', "&4&lNo permission for this kit!"));
}
// Item lore that consists of contents of kit
FileConfiguration fileConfiguration = KitConfig.get();
List<ItemStack> kitContent = (List<ItemStack>) fileConfiguration.get("kits." + key + ".contents");
@@ -102,6 +161,7 @@ public class KitsGUI implements TabExecutor {
if (item == null) {
item = new ItemStack(Material.AIR);
} else if (item.getType().toString().equalsIgnoreCase("DIAMOND")){
// Some old kits have a diamond for identification of that kit, that is legacy
//Diamond check; do nothing
} else if (item.getType().toString().equalsIgnoreCase("SPLASH_POTION")){
@@ -120,11 +180,12 @@ public class KitsGUI implements TabExecutor {
String amount = String.valueOf(item.getAmount());
lore.add(ChatColor.GRAY + amount + "x " + ChatColor.YELLOW + MyStringUtils.itemCamelCase("golden_head"));
lore.add(ChatColor.GRAY + " Healing Item");
lore.add(ChatColor.GRAY + " " + item.getItemMeta().getLore().get(0));
} else if (item.getType().toString().equalsIgnoreCase("CHEST")){
String amount = String.valueOf(item.getAmount());
lore.add(ChatColor.GRAY + amount + "x " + ChatColor.YELLOW + MyStringUtils.itemCamelCase("random_loot_chest"));
lore.add(ChatColor.GRAY + " " + item.getItemMeta().getLore().get(0));
} else {
String amount = String.valueOf(item.getAmount());
@@ -138,13 +199,18 @@ public class KitsGUI implements TabExecutor {
}
//Set KillItem as lore
ItemStack killItem = (ItemStack) KitConfig.get().get("kits." + key + ".killitem");
if (killItem.getType().toString().equalsIgnoreCase("PLAYER_HEAD")) {
lore.add(ChatColor.WHITE + "Item on Kill:");
lore.add(ChatColor.YELLOW + " Golden Head"); //I would just get the displayname to make this more dynamic but I cant because of fecking component
lore.add(ChatColor.GRAY + "1x " + ChatColor.YELLOW + "Golden Head"); //fixedI would just get the displayname to make this more dynamic but I cant because of fecking component
lore.add(ChatColor.GRAY + " " + killItem.getItemMeta().getLore().get(0));
} else if (killItem.getType().toString().equalsIgnoreCase("CHEST")){
lore.add(ChatColor.WHITE + "Item on Kill:");
int amount = killItem.getAmount();
lore.add(ChatColor.GRAY + "" + amount + "x " + ChatColor.YELLOW + "Kit Loot Chest");
lore.add(ChatColor.GRAY + "" + amount + "x " + ChatColor.YELLOW + "Random Loot Chest");
lore.add(ChatColor.GRAY + " " + killItem.getItemMeta().getLore().get(0));
//System.out.println(killItem.getItemMeta().getLore().get(0));
} else if (killItem.getType().toString().equalsIgnoreCase("AIR")){
lore.add(ChatColor.WHITE + "No Item on Kill");
@@ -155,7 +221,6 @@ public class KitsGUI implements TabExecutor {
}
itemMeta.setLore(lore); //Heck you Component
//Set meta
@@ -170,18 +235,31 @@ public class KitsGUI implements TabExecutor {
//Reset button
ItemStack resetButton = new ItemStack(Material.BARRIER);
ItemMeta resetButtonMeta = resetButton.getItemMeta();
resetButtonMeta.displayName(Component.text("Reset kit"));
resetButtonMeta.displayName(Component.text("Reset kit").decoration(TextDecoration.ITALIC, false));
List<Component> loreList = new ArrayList<>();
TextComponent txt = Component.text("If you do not have permission to reset your kit,").color(TextColor.color(0,100,255));
TextComponent txt2 = Component.text("this will run /suicide on your behalf.").color(TextColor.color(0,100,255));
TextComponent txt = Component.text("If you do not have permission to reset your kit,").decoration(TextDecoration.ITALIC, false).color(TextColor.color(100,100,100));
TextComponent txt2 = Component.text("this will run /suicide on your behalf.").decoration(TextDecoration.ITALIC, false).color(TextColor.color(100,100,100));
loreList.add(txt);
loreList.add(txt2);
resetButtonMeta.lore(loreList);
resetButton.setItemMeta(resetButtonMeta);
kits.setItem(53, resetButton);
// Perk Redirect Button
ItemStack perkHelpButton = new ItemStack(Material.BOOK);
ItemMeta perkHelpButtonMeta = perkHelpButton.getItemMeta();
perkHelpButtonMeta.displayName(Component.text("Perk Info").decoration(TextDecoration.ITALIC, false));
List<Component> loreList2 = new ArrayList<>();
TextComponent txt21 = Component.text("Click here to change your perks!").decoration(TextDecoration.ITALIC, false).color(TextColor.color(100,100,100));
loreList2.add(txt21);
perkHelpButtonMeta.lore(loreList2);
perkHelpButton.setItemMeta(perkHelpButtonMeta);
kits.setItem(49, perkHelpButton);
player.openInventory(kits);
}
@@ -10,6 +10,8 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class GetKitStats extends Subcommand {
Plugin plugin;
public GetKitStats(Plugin plugin) {
@@ -40,7 +42,31 @@ public class GetKitStats extends Subcommand {
@Override
public boolean perform(Player player, String[] args) {
FileConfiguration kitStats = KitStatsConfig.get();
for(String key : kitStats.getKeys(false)){
ArrayList<String> kitStatsKeys = new ArrayList<>(kitStats.getKeys(false));
HashMap<String, Integer> map = new HashMap<>();
LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<>();
ArrayList<Integer> list = new ArrayList<>();
for(String key : kitStatsKeys){
map.put(key, kitStats.getInt(key));
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
list.add(entry.getValue());
}
Collections.sort(list);
Collections.reverse(list);
for (Integer integer : list) {
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue().equals(integer)) {
sortedMap.put(entry.getKey(), integer);
}
}
}
for(String key : sortedMap.keySet()){
player.sendMessage(key + " - " + kitStats.getInt(key));
@@ -31,13 +31,13 @@ public class GetStats implements TabExecutor {
if (!(sender instanceof Player player)) {
return true;
}
if (!(args.length > 0)){
player.sendMessage("Provide a player!");
return false;
}
FileConfiguration playerStatsConfig = PlayerStatsConfig.get();
String argumentPlayer = args[0];
String argumentPlayer = player.getName();
if (args.length == 1){
argumentPlayer = args[0];
}
Set<String> allKeys = playerStatsConfig.getKeys(true);
if (!(allKeys.contains(argumentPlayer))){
player.sendMessage("That player does not have any stats attached to them.");
@@ -0,0 +1,126 @@
package me.lifelessnerd.purekitpvp.perks.perkCommand;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.files.PerkData;
import me.lifelessnerd.purekitpvp.kitCommand.GetKit;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkLib;
import me.lifelessnerd.purekitpvp.utils.ComponentUtils;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class PerkCommand implements CommandExecutor {
Plugin plugin;
public PerkCommand(Plugin plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)){
return false;
}
Player player = (Player) sender;
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))){
player.sendMessage(ChatColor.RED + "You can only use this menu in " + ChatColor.GRAY + plugin.getConfig().getString("world"));
return true;
}
if (GetKit.hasKit.contains(player.getName())){
player.sendMessage(ChatColor.RED + "You can only change perks when you have no kit selected!");
return true;
}
//Create inventory GUI
TextComponent invTitle = Component.text("Perks Menu").color(TextColor.color(255, 150, 20));
Inventory perksInventory = Bukkit.createInventory(null, 54, invTitle);
//Info item
ItemStack infoItem = new ItemStack(Material.BOOK);
TextComponent infoItemName = Component.text("Perks Info").color(TextColor.color(233, 67, 47)).decoration(TextDecoration.ITALIC, false);
ItemMeta infoMeta = infoItem.getItemMeta();
infoMeta.displayName(infoItemName);
infoMeta = ComponentUtils.setLore(infoMeta, "&aYou can equip a total of &e5 &aperks total.", 0);
infoMeta = ComponentUtils.setLore(infoMeta, "&7Click on a perk slot to choose a perk for that slot.", 1);
infoMeta = ComponentUtils.setLore(infoMeta, "&7It will replace any perk currently in that slot.", 2);
infoMeta = ComponentUtils.setLore(infoMeta, "&7Perks are abilities that are always active.", 3);
infoMeta = ComponentUtils.setLore(infoMeta, "&7Duplicate perks do not stack.", 4);
infoItem.setItemMeta(infoMeta);
perksInventory.setItem(13, infoItem);
//Back to kits item
ItemStack kitItem = new ItemStack(Material.ARROW);
TextComponent kitItemName = Component.text("Back to Kits").color(TextColor.color(0, 255, 47)).decoration(TextDecoration.ITALIC, false);
ItemMeta kitItemMeta = kitItem.getItemMeta();
kitItemMeta.displayName(kitItemName);
kitItem.setItemMeta(kitItemMeta);
perksInventory.setItem(49, kitItem);
//Fill perk slots with either empty or actual perk icon
for (int index = 20; index <= 24; index++){
int slot = index - 19;
String fileContent = PerkData.get().getString(player.getName() + ".slot" + slot);
//System.out.println(fileContent);
if (fileContent == null){
// No perk selected in this slot; show red stained-glass
ItemStack perkSlot = new ItemStack(Material.RED_STAINED_GLASS_PANE);
TextComponent perkSlotName = Component.text("Perk Slot " + slot).color(TextColor.color(233, 67, 47)).decoration(TextDecoration.ITALIC, false);
ItemMeta perkSlotMeta = perkSlot.getItemMeta();
perkSlotMeta.displayName(perkSlotName);
perkSlotMeta = ComponentUtils.setLore(perkSlotMeta, "&aClick to select a perk for this slot!", 0);
perkSlot.setItemMeta(perkSlotMeta);
perksInventory.setItem(index, perkSlot);
} else {
PerkLib perkLib = new PerkLib();
ItemStack perkSlot = new ItemStack(perkLib.perkIcons.get(fileContent));
TextComponent perkSlotName = Component.text("Perk Slot " + slot).color(TextColor.color(233, 67, 47)).decoration(TextDecoration.ITALIC, false);
ItemMeta perkSlotMeta = perkSlot.getItemMeta();
perkSlotMeta.displayName(perkSlotName);
//Component style - not my own class util (okay, only the decoder)
ArrayList<Component> loreTBA = new ArrayList<>();
TextComponent loreTitle = Component.text(fileContent).color(TextColor.color(0, 230, 0)).decoration(TextDecoration.ITALIC, false);
loreTBA.add(loreTitle);
if (perkLib.perks.get(fileContent).contains("\n")) {
String[] decodedLore = MyStringUtils.perkLoreDecoder(perkLib.perks.get(fileContent));
for (String line : decodedLore) {
loreTBA.add(Component.text(line).color(TextColor.color(150, 150, 150)).decoration(TextDecoration.ITALIC, false));
}
} else {
loreTBA.add(Component.text(perkLib.perks.get(fileContent)).color(TextColor.color(150, 150, 150)).decoration(TextDecoration.ITALIC, false));
}
perkSlotMeta.lore(loreTBA);
perkSlotMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
perkSlotMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
perkSlot.setItemMeta(perkSlotMeta);
perksInventory.setItem(index, perkSlot);
}
}
player.openInventory(perksInventory);
return true;
}
}
@@ -0,0 +1,149 @@
package me.lifelessnerd.purekitpvp.perks.perkCommand;
import me.lifelessnerd.purekitpvp.files.PerkData;
import me.lifelessnerd.purekitpvp.perks.perkfirehandler.PerkLib;
import me.lifelessnerd.purekitpvp.utils.MyStringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
public class PerkGUIListener implements Listener {
Plugin plugin;
public PerkGUIListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
Player player = (Player) e.getWhoClicked();
if (!(player.getWorld().getName().equalsIgnoreCase(plugin.getConfig().getString("world")))) {
return;
}
if (e.getCurrentItem() == null || e.getRawSlot() >= 53) {
return;
}
ItemStack clickedItem = e.getCurrentItem();
InventoryView inv = e.getView();
if (inv.title().toString().contains("Perks Menu")) { //I hate component
e.setCancelled(true);
Component itemDisplayName = clickedItem.displayName();
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
String itemName = serializer.serialize(itemDisplayName);
// This is when you click on a perk slot to modify it
if (itemName.contains("Perk Slot")) {
int slot = Integer.parseInt(String.valueOf(itemName.charAt(itemName.length() - 2)));
//Create inventory GUI
TextComponent invTitle = Component.text("Perk Slot " + slot).color(TextColor.color(255, 150, 20));
Inventory perkSlotInventory = Bukkit.createInventory(null, 54, invTitle);
//Fill inventory with interactive perk items
PerkLib perkLib = new PerkLib();
for (String perk : perkLib.perkIcons.keySet()) {
ItemStack icon = new ItemStack(perkLib.perkIcons.get(perk));
ItemMeta itemMeta = icon.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS);
itemMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
itemMeta.displayName(Component.text(perk).color(TextColor.color(200, 0, 0)).decoration(TextDecoration.ITALIC, false));
// Check if it is selected: if so add glint
for(String selectedPerkKey : PerkData.get().getConfigurationSection(player.getName()).getKeys(false)){
String selectedPerk = PerkData.get().getString(player.getName() + "." + selectedPerkKey);
if (perk.equals(selectedPerk)){
itemMeta.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
itemMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
itemMeta.displayName(Component.text(perk).color(TextColor.color(50, 200, 0)).decoration(TextDecoration.BOLD, true));
}
}
icon.setItemMeta(itemMeta);
ArrayList<Component> loreTBA = new ArrayList<>();
if (perkLib.perks.get(perk).contains("\n")) {
String[] decodedLore = MyStringUtils.perkLoreDecoder(perkLib.perks.get(perk));
for (String line : decodedLore) {
loreTBA.add(Component.text(line).color(TextColor.color(150, 150, 150)).decoration(TextDecoration.ITALIC, false));
}
} else {
loreTBA.add(Component.text(perkLib.perks.get(perk)).color(TextColor.color(150, 150, 150)).decoration(TextDecoration.ITALIC, false));
}
icon.lore(loreTBA);
perkSlotInventory.addItem(icon);
}
ItemStack backButton = new ItemStack(Material.ARROW);
ItemMeta backButtonMeta = backButton.getItemMeta();
backButtonMeta.displayName(Component.text("Go Back").color(TextColor.color(0, 250, 0)).decoration(TextDecoration.ITALIC, false));
backButtonMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
backButton.setItemMeta(backButtonMeta);
perkSlotInventory.setItem(49,backButton);
player.openInventory(perkSlotInventory);
}
else if (itemName.contains("Back to Kits")){
inv.close();
player.chat("/kit");
}
}
else if (inv.title().toString().contains("Perk Slot")){
e.setCancelled(true);
Component title = inv.title();
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
String itemName = serializer.serialize(title);
String clickedItemName = serializer.serialize(e.getCurrentItem().displayName());
if (clickedItemName.contains("Go Back")){
inv.close();
player.chat("/perks");
} else {
int slot = Integer.parseInt(String.valueOf(itemName.charAt(itemName.length() - 1)));
ItemStack clickedPerk = e.getCurrentItem();
String displayName = serializer.serialize(clickedPerk.displayName());
displayName = displayName.substring(1, displayName.length() - 1);
PerkData.setPerk(player, displayName, slot);
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1,0);
PerkData.save();
PerkData.reload();
inv.close();
player.chat("/perks");
}
}
}
}
@@ -0,0 +1,321 @@
package me.lifelessnerd.purekitpvp.perks.perkfirehandler;
import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent;
import me.lifelessnerd.purekitpvp.files.KitConfig;
import me.lifelessnerd.purekitpvp.files.PerkData;
import me.lifelessnerd.purekitpvp.files.PlayerStatsConfig;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class PerkFireHandler {
public static Plugin plugin;
public PerkFireHandler(Plugin plugin){
PerkFireHandler.plugin = plugin;
}
public static Set<String> getPerks(Player player) {
ConfigurationSection playerPerks = PerkData.get().getConfigurationSection(player.getName());
if (playerPerks == null){
return new HashSet<>(); // No perks? Return empty set; this way nothing happens
}
Set<String> perkSlots = playerPerks.getKeys(false);
Set<String> perks = new HashSet<>();
for (String perkSlot : perkSlots){
perks.add(playerPerks.getString(perkSlot));
}
return perks;
}
public static void fireKillPerks(Player player){
Set<String> perks = getPerks(player);
for(String perk : perks){
//System.out.println(perk);
switch(perk){
case "JUGGERNAUT":
player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 100, 1));
break;
case "BULLDOZER":
player.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 60, 1));
break;
case "KNOWLEDGE":
player.giveExpLevels(1);
break;
case "NOTORIETY":
if(Math.random() <= 0.15) {
ItemStack weapon = player.getInventory().getItemInMainHand();
ItemMeta weaponMeta = weapon.getItemMeta();
if (weaponMeta == null){continue;} // If weapon is hand
int sharpnessLevel = weaponMeta.getEnchantLevel(Enchantment.DAMAGE_ALL);
if (plugin.getConfig().getInt("notoriety-maximum") != -1){
// So if the boundary is set to SOME value
if (sharpnessLevel >= plugin.getConfig().getInt("notoriety-maximum")){
player.sendMessage(ChatColor.YELLOW + "You have reached the maximum Notoriety!");
player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1,0);
continue;
}
}
weaponMeta.removeEnchant(Enchantment.DAMAGE_ALL);
weaponMeta.addEnchant(Enchantment.DAMAGE_ALL, sharpnessLevel + 1, true);
weapon.setItemMeta(weaponMeta);
player.sendMessage(ChatColor.YELLOW + "Your sharpness level has increased!");
}
break;
case "ENDERMAGIC":
if(Math.random() <= 0.3) {
ItemStack pearl = new ItemStack(Material.ENDER_PEARL, 1);
player.getInventory().addItem(pearl);
player.sendMessage(ChatColor.YELLOW + "You gained an ender pearl!");
}
break;
case "SPEEDSTER":
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 200, 1));
break;
case "MARKSMAN":
if(Math.random() <= 0.5) {
ItemStack weapon = player.getInventory().getItemInMainHand();
ItemMeta weaponMeta = weapon.getItemMeta();
if (weapon.getType() != Material.BOW){continue;}
if (weaponMeta == null){continue;} // If weapon is hand
int powerLevel = weaponMeta.getEnchantLevel(Enchantment.ARROW_DAMAGE);
if (plugin.getConfig().getInt("marksman-maximum") != -1){
// So if the boundary is set to SOME value
if (powerLevel >= plugin.getConfig().getInt("marksman-maximum")){
player.sendMessage(ChatColor.YELLOW + "You have reached the maximum power level!");
player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_FALL, 1,0);
continue;
}
}
weaponMeta.removeEnchant(Enchantment.ARROW_DAMAGE);
weaponMeta.addEnchant(Enchantment.ARROW_DAMAGE, powerLevel + 1, true);
weapon.setItemMeta(weaponMeta);
player.sendMessage(ChatColor.YELLOW + "Your power level has increased!");
}
break;
}
}
}
public static void fireRangedPerks(EntityDamageByEntityEvent event, Player damager){
Set<String> perks = getPerks(damager);
for(String perk : perks){
//System.out.println(perk);
switch(perk){
case "APOLLO":
// Event is already Arrow on Player; damager has already been extracted out of the event
if (event.getDamager() instanceof SpectralArrow arrow){
ItemStack arrowItem = arrow.getItemStack();
arrowItem.setAmount(1);
damager.getInventory().addItem(arrowItem);
} else {
Arrow arrow = (Arrow) event.getDamager();
ItemStack arrowItem = arrow.getItemStack();
arrowItem.setAmount(1);
damager.getInventory().addItem(arrowItem);
}
damager.playSound(damager.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 1,0);
break;
}
}
}
public static void fireCombatPerks(Player damaged, Player damager){
Set<String> perks = getPerks(damager);
for(String perk : perks){
switch(perk){
case "ROBBERY":
if(damager.getInventory().getItemInMainHand().getType() != Material.AIR) { // if hit with hand
return;
}
if (Math.random() <= 0.3){
ItemStack item = damaged.getInventory().getItemInMainHand();
damaged.getInventory().setItemInMainHand(new ItemStack(Material.AIR));
//Check what slots in inventory (!= hotbar) are empty
ArrayList<Integer> airSlots = new ArrayList<Integer>();
for (int slot = 9; slot <= 35; slot++){
if(damaged.getInventory().getItem(slot) == null){
airSlots.add(slot);
}
}
Collections.shuffle(airSlots);
if (airSlots.size() != 0){ // this is exploitable, if a player has a full inv, stuff does not change. So else
damaged.getInventory().setItem(airSlots.get(0), item);
} else { //fixes above exploit
int randomNum = ThreadLocalRandom.current().nextInt(9, 35 + 1);
ItemStack toBeSwapped = damaged.getInventory().getItem(randomNum);
damaged.getInventory().setItem(randomNum, item);
damaged.getInventory().setItem(damaged.getInventory().getHeldItemSlot(), toBeSwapped);
}
// I could have just always swapped, sometimes swap with air
// oh well shite
damaged.sendMessage(ChatColor.YELLOW + "You were disarmed!");
}
break;
}
}
}
public static void fireVampirePerk(EntityDamageByEntityEvent event) {
Player player = (Player) event.getDamager();
Set<String> perks = getPerks(player);
for(String perk : perks){
if (perk.equalsIgnoreCase("VAMPIRE")){
if (event.isCritical()){
//Main logic
double damageDealt = event.getDamage();
double regen = damageDealt / 2;
if (player.getHealth() + regen <= 20){
player.setHealth(player.getHealth() + regen);
} else {
player.setHealth(20);
}
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_BURP, 1,0);
}
}
}
}
public static void fireSnowballPerks(ProjectileHitEvent event, Player damaged, Player shooter) {
Set<String> perks = getPerks(shooter);
for(String perk : perks){
switch(perk){
case "SNOWMAN":
if (event.getEntity() instanceof Snowball) {
damaged.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 60, 0));
}
break;
case "DISRUPTOR":
if (event.getEntity() instanceof Egg) {
damaged.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 80, 0));
}
break;
}
}
}
public static void fireEnderpearlPerks(Player player, PlayerLaunchProjectileEvent event) {
Set<String> perks = getPerks(player);
for(String perk : perks){
switch(perk){
case "ENDERMAN":
new BukkitRunnable() {
@Override
public void run() {
for (Entity en : event.getPlayer().getNearbyEntities(2, 2, 2)) {
//This has to be here; event.getProjectile does not work; idk why https://www.spigotmc.org/threads/ride-enderpearl.263710/
if (en.getType() == EntityType.ENDER_PEARL) {
en.addPassenger(event.getPlayer());
}
}
}
}.runTaskLater(plugin, 1);
break;
}
}
}
public static void fireHealthPerks(Player player){
Set<String> perks = getPerks(player);
for(String perk : perks) {
switch (perk) {
case "ADRENALINE":
if (player.getHealth() >= 6){
player.setWalkSpeed(0.2f);
break;
}
player.setWalkSpeed(0.3f);
}
}
}
public static void fireEnderpearlDamagePerks(Player player, EntityDamageByEntityEvent event){
Set<String> perks = getPerks(player);
for(String perk : perks) {
switch (perk) {
case "ENDERMAN":
event.setCancelled(true); // Negates not only the damage but also the tick
break;
}
}
}
}
@@ -0,0 +1,44 @@
package me.lifelessnerd.purekitpvp.perks.perkfirehandler;
import org.bukkit.Material;
import java.util.HashMap;
public class PerkLib {
public HashMap<String, String> perks = new HashMap<>();
public HashMap<String, Material> perkIcons = new HashMap<>();
public PerkLib(){
perks.put("JUGGERNAUT", "Gain regeneration 1 (5s) after every kill");
perks.put("BULLDOZER", "Gain strength 2 (3s) after every kill");
perks.put("KNOWLEDGE", "Gain 1 XP level on kill");
perks.put("NOTORIETY","15% chance of gaining a sharpness level on each kill\nSharpness will be added to the item held");
perks.put("ENDERMAGIC", "30% chance of gaining an ender pearl on kill");
perks.put("SPEEDSTER","Gain 10 seconds of speed 2 after every kill");
perks.put("ROBBERY","30% chance of disarming someone if hit with your fist\nThe weapon will be swapped with a slot in the inventory");
perks.put("SNOWMAN","Give slowness 1 (3s) when you hit someone with a snowball");
perks.put("DISRUPTOR","Give poison 1 (5s) when you hit someone with an egg");
perks.put("ENDERMAN", "You can now ride ender pearls; they do no damage");
perks.put("VAMPIRE", "On critical hits, gain 50% of the damage\nyou dealt, as instant health");
perks.put("MARKSMAN", "50% chance of gaining a power level on each bow kill\nPower is added to the item held, if it's a bow");
perks.put("APOLLO", "You get each arrow you hit on a player back\nA kill nets one extra arrow of that type");
perks.put("ADRENALINE", "When below 6 HP (3 hearts), you get a speed boost");
perkIcons.put("JUGGERNAUT" , Material.DIAMOND_CHESTPLATE);
perkIcons.put("BULLDOZER" , Material.ANVIL);
perkIcons.put("KNOWLEDGE" , Material.BOOK);
perkIcons.put("NOTORIETY", Material.DIAMOND_SWORD);
perkIcons.put("ENDERMAGIC", Material.ENDER_PEARL);
perkIcons.put("SPEEDSTER", Material.SUGAR);
perkIcons.put("ROBBERY", Material.IRON_BARS);
perkIcons.put("SNOWMAN", Material.SNOWBALL);
perkIcons.put("DISRUPTOR", Material.EGG);
perkIcons.put("ENDERMAN", Material.ENDER_EYE);
perkIcons.put("VAMPIRE", Material.REDSTONE);
perkIcons.put("MARKSMAN", Material.BOW);
perkIcons.put("APOLLO", Material.ARROW);
perkIcons.put("ADRENALINE", Material.GHAST_TEAR);
}
}
@@ -0,0 +1,114 @@
package me.lifelessnerd.purekitpvp.utils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
public class ComponentUtils {
public static ItemMeta setLore(ItemMeta itemMeta, String lore, int line){
List<Component> currentLore = null;
if (itemMeta.hasLore()){
currentLore = itemMeta.lore();
} else {
currentLore = new ArrayList<>();
}
TextComponent translated = stringDecoder(lore);
if (line >= currentLore.size()){
currentLore.add(translated);
} else {
currentLore.set(line, translated);
}
itemMeta.lore(currentLore);
return itemMeta;
}
static TextComponent stringDecoder(String lore) {
//String to TextComponent decoder
// "&aTesting &3string!"
TextComponent textComponent = Component.text("");
StringBuilder toBeAdded = new StringBuilder();
TextColor lastColor = NamedTextColor.WHITE;
for (int index = 0; index < lore.length(); index++) {
char character = lore.charAt(index);
if (character == '&') {
textComponent = textComponent.append(Component.text(
toBeAdded.toString()).color(lastColor));
toBeAdded = new StringBuilder();
switch (lore.charAt(index + 1)) {
case '0':
lastColor = NamedTextColor.BLACK;
break;
case '1':
lastColor = NamedTextColor.DARK_BLUE;
break;
case '2':
lastColor = NamedTextColor.DARK_GREEN;
break;
case '3':
lastColor = NamedTextColor.DARK_AQUA;
break;
case '4':
lastColor = NamedTextColor.DARK_RED;
break;
case '5':
lastColor = NamedTextColor.DARK_PURPLE;
break;
case '6':
lastColor = NamedTextColor.GOLD;
break;
case '7':
lastColor = NamedTextColor.GRAY;
break;
case '8':
lastColor = NamedTextColor.DARK_GRAY;
break;
case '9':
lastColor = NamedTextColor.BLUE;
break;
case 'a':
lastColor = NamedTextColor.GREEN;
break;
case 'b':
lastColor = NamedTextColor.AQUA;
break;
case 'c':
lastColor = NamedTextColor.RED;
break;
case 'd':
lastColor = NamedTextColor.LIGHT_PURPLE;
break;
case 'e':
lastColor = NamedTextColor.YELLOW;
break;
case 'f':
lastColor = NamedTextColor.WHITE;
break;
}
index = index + 1;
} else {
toBeAdded.append(character);
}
}
textComponent = textComponent.append(Component.text(
toBeAdded.toString()).color(lastColor)).decoration(TextDecoration.ITALIC, false);
return textComponent;
}
}
@@ -1,5 +1,8 @@
package me.lifelessnerd.purekitpvp.utils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
public class MyStringUtils {
public static String itemCamelCase(String string){
@@ -37,7 +40,8 @@ public class MyStringUtils {
String[] splitAgain = word.split(",");
String levelString = splitAgain[1];
int level = Integer.parseInt(String.valueOf(levelString.charAt(levelString.length() - 1)));
String[] isolateLevel = levelString.split("=");
int level = Integer.parseInt(isolateLevel[isolateLevel.length - 1]); //HERE
word = splitAgain[0];
word = MyStringUtils.itemCamelCase(word);
result.append(word).append(level).append(" ");
@@ -73,12 +77,17 @@ public class MyStringUtils {
time.deleteCharAt(splitOnceMore[0].length() - 1);
int timeSec = Integer.parseInt(time.toString()) / 20;
StringBuilder potency = new StringBuilder(splitOnceMore[1]);
potency.deleteCharAt(0);
int potencyInt = Integer.parseInt(potency.toString()) + 1;
StringBuilder lvlAndTime = new StringBuilder("");
lvlAndTime.append(potencyInt + " (" + timeSec + "s)");
if (timeSec > 100000000){
lvlAndTime.append(potencyInt + " (Infinite)");
} else {
lvlAndTime.append(potencyInt + " (" + timeSec + "s)");
}
result.append(lvlAndTime);
@@ -105,4 +114,29 @@ public class MyStringUtils {
return result.toString();
}
public static String[] perkLoreDecoder(String string){
String[] output = string.split("\n");
return output;
}
public static String itemNameToCosmeticId(String input){
String processed = input.toLowerCase();
processed = processed.replace(' ', '_');
return processed;
}
// Opposite of function above
public static String cosmeticIdToItemName(String input){
// Input: blood_explosion -> Blood Explosion
return itemCamelCase(input).trim();
}
public static String componentToString(Component singleLineComponent){
PlainTextComponentSerializer serializer = PlainTextComponentSerializer.plainText();
String processed = serializer.serialize(singleLineComponent);
processed = processed.substring(1, processed.length() - 1);
return processed;
}
}
+38 -5
View File
@@ -1,24 +1,57 @@
# PureKitPvP by LifelessNerd
# Made to work with PureKits kit files
# 2022
# 2022 - 2023
# World in which the plugin should be active: i.e. kits, deaths, stats and such
world: pvp
#Quick kill when falling in void, only works when suicide-command is enabled
quick-voidkill: true
#If above true, Y level at which you should die in pvp, please provide double
#If above true, Y level at which you should die in pvp, please provide double (something like 0.0 or -10.0)
voidY: 0.0
#respawn X, Y, Z in world
#respawn X, Y, Z in world, this is basically the spawn region
respawnX: 0.5
respawnY: 142.0
respawnZ: 0.5
#Whether people who get a killstreak will get glowing effect
# Spawn region radius; you won't get fall damage in this area (square area relative to respawnX and respawnZ)
spawn-radius: 6
#Whether people who get a kill streak will get glowing effect
killstreak-glowing: true
#If above true, the duration in seconds
killstreak-glowing-duration: 100
#Suicide command from PureKitPvP, ensures death recaps work correctly
suicide-command: true
suicide-command: true
# Whether the level of the player should be displayed in front of the message as prefix (only in the enabled world)
level-chat: true
#Notoriety perk boundary
#If the notoriety perk is too OP, restrict the maximum level of sharpness that can be gained
#Set to -1 if infinite
notoriety-maximum: -1
#Marksman perk boundary
#If the marksman perk is too OP, restrict the maximum level of power that can be gained
#Set to -1 if infinite
marksman-maximum: -1
#Default kill effect
default-kill-effect: "firework"
#Default projectile trail
default-projectile-trail: "none"
# Projectile trail period delay
# The amount of time between each particle, in ticks (20 ticks = 1 particle per second)
projectile-trail-period: 1
# Projectile trail count
# Amount of particles per spawn (also controlled by projectile-trail-period)
projectile-trail-count: 5
# Chicken prevention: kits with eggs might spawn chicken; when this is true they are prevented from spawning
chicken-prevention: true
+17 -3
View File
@@ -2,8 +2,8 @@ name: PureKitPvP
version: '${project.version}'
main: me.lifelessnerd.purekitpvp.PureKitPvP
api-version: 1.19
authors: [ LifelessNerd, PsionicPvP ]
description: KitPVP plugin, with kit functionality from PureKits (abandoned)
authors: [ LifelessNerd ]
description: KitPVP plugin, made to work with PureKits kits (abandoned)
commands:
getkit:
description: Gives you a kit.
@@ -22,10 +22,24 @@ commands:
- pvpstats
purekitpvp:
description: All admin commands. See documentation for help.
usage: /purekitpvp <createkit/deletekit/kitstats/setkillitem/getcustomitem/createloottable/reload>
usage: /purekitpvp <createkit/deletekit/kitstats/setkillitem/getcustomitem/createloottable/reload/help/info>
aliases:
- kitpvp
- pkpvp
purekitpvphelp:
description: Get PureKitPvP help, for the common folk
usage: /purekitpvphelp
aliases:
- pkpvphelp
- pvphelp
perks:
description: Perk menu
usage: /perk
aliases:
- perk
cosmetics:
description: Open cosmetics menu
usage: /cosmetics
+12 -4
View File
@@ -1,5 +1,6 @@
![\[Banner\]](https://i.imgur.com/tl2TQuw.png)
# PureKitPvP
# PureKitPvP (1.1)
PureKitPvP lets you create a kit pvp environment quickly, with your own custom kits. These kits work similar to the plugin PureKits, but since that plugin is abandoned, I decided to extend it with other features. A quick overview of all features:
- Death Recaps
@@ -18,6 +19,7 @@ PureKitPvP lets you create a kit pvp environment quickly, with your own custom k
- See Kit usage stats for balancing
- Mobs can be used in kits, they despawn when the player has died
- Quickly die when falling in the void
- 11 Perks, with GUI selection
## Commands
All commands can be seen in-game via _/purekitpvp help_.
@@ -57,7 +59,10 @@ All commands can be seen in-game via _/purekitpvp help_.
* **/kit**
* Show Kit GUI
![\[IMG\]](https://i.imgur.com/JLFvel3.png)
* **/perks**
* Show Perk GUI, click on a slot to change the perk in that slot (see img2)
![\[IMG\]](https://i.imgur.com/Yau99d1.png)
![\[IMG\]](https://i.imgur.com/DB81qVL.png)
* **/getkit <kitName>**
* Get a kit directly
@@ -80,11 +85,14 @@ For the loottables.yml, follow the format that is provided in the example in the
Have all the items you want to be in your kit in your inventory, and type the command. A kit will be created with the arguments and automatically added to the kit menu (/kit). You either provide a kill item in the base command, or, if you want the kill item to be a special item (i.e. a golden head or a random loot chest), use the /purekitpvp getcustomitem command to get that item, and run the command /purekitpvp setkillitem \<kitName> while holding that item.
The contents of the kit will be shown in a clean hoverbox when choosing the kit, which will categorize the first 3 items in your hotbar as weapons, the rest of the inventory as items, the armor as armor and the offhand as offhand. If the kit has no armor, it will tell you aswell. A piece of lore can be set in the kits.yml.
Basic potions that can be found in the inventory are translated as well, although they do not show their potency and lenght, due to how these items work in spigot. Custom potions created with commands however do work perfectly and show potency and lenght, so I recommend to create your own potions with commands when working with them.
## Perks
The perks menu can be brought up using /perks, or via the /kit command. These perks can be changed anytime (so also during combat. Any suggestions on how to forbid this are welcome), and these perks are active at any time. You can have a total of 5 perks active at any time. Perks are activated based on what they do, some active on kill, some during combat etc.
Some configuration is provided in the config, but these perks are not as customizable as the kits and loot tables, due to most perks being quite unlike each other.
There are currently around 11 perks to choose from. Suggestions can be made (see contact info below).
## How to create a loot table
*Also see the video that covers this topic below.*
Place a chest and put all items you want to be in your loottable in the chest. The chance of each item will be 0.1 by default. You can change this in the loottables.yml file, but if you want you can just put 2 identical items in the chest if you want the chance to be 0.2. When finished, run the command /purekitpvp createloottable \<name> \<lore> \<displayName>. The lore and displayname are important for the item this loot table with be attached to. Now you may change the chance values of each item in the loottables.yml file. You may also change the lore and displayname to get multi-line text. Check if your YAML is valid before reloading the plugin (or back it up), otherwise the file may reset (!). To get the item with the loot table, run the command /purekitpvp getcustomitem random_chest \<loottable>. With this item in your inventory you can use it in a kit, or as kill item.
Place a chest and put all items you want to be in your loottable in the chest. The chance of each item will be 0.1 by default. You can change this in the loottables.yml file, but if you want you can just put 2 identical items in the chest if you want the chance to be 0.2. When finished, run the command /purekitpvp createloottable \<name> \<lore> \<displayName>. The lore and displayname are important for the item this loot table with be attached to. Now you may change the chance values of each item in the loottables.yml file. You may also change the lore and displayname to get multi-line text. If guaranteed is set to a true, the plugin will keep cycling through all item of the lootchest until exactly that amount is given. Check if your YAML is valid before reloading the plugin (or back it up), otherwise the file may reset (!). To get the item with the loot table, run the command /purekitpvp getcustomitem random_chest \<loottable> (will auto-complete). With this item in your inventory you can use it in a kit, or set it as kill item.
## Video
https://youtu.be/wZcZ4DcRfgU