mirror of
https://github.com/KoopaCode/LifeSteal-Core.git
synced 2025-03-31 13:57:33 +00:00
Release 1.0.0
This commit is contained in:
parent
a3ced2007b
commit
725274453e
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
35
README.md
35
README.md
@ -1,2 +1,33 @@
|
||||
# LifeSteal-Core
|
||||
Minecraft Spigot Native 1.20 Plugin for a advanced standalone Lifesteal plugin
|
||||
# LifeSteal Core ❤
|
||||
|
||||
A dramatic and feature-rich LifeSteal plugin for Minecraft servers. Take hearts from your victims, craft revival beacons, and experience epic death announcements!
|
||||
|
||||

|
||||
|
||||
## ✦ Features
|
||||
- **Heart Stealing System**: Take hearts from players you kill
|
||||
- **Dramatic Effects**: Server-wide announcements with sound effects
|
||||
- **Revival Beacons**: Custom crafting system to revive banned players
|
||||
- **Advanced Configuration**: In-game GUI for all settings
|
||||
- **Multiple Difficulties**: Easy, Medium, Hard, and Custom recipes
|
||||
- **Permission Based**: Full control over all features
|
||||
|
||||
## ✦ Downloads
|
||||
Pre-compiled builds are available at:
|
||||
- [SpigotMC](https://www.spigotmc.org/resources/lifesteal-core.xxxxx/)
|
||||
- [GitHub Releases](https://github.com/KoopaCode/LifeSteal-Core/releases)
|
||||
|
||||
## ✦ Requirements
|
||||
- Server Version: 1.13 - 1.20.4
|
||||
- Java: 17 or newer
|
||||
- Dependencies: None
|
||||
|
||||
## ✦ Installation
|
||||
1. Download the plugin
|
||||
2. Place in your plugins folder
|
||||
3. Start/Restart your server
|
||||
4. Configure using `/lifesteal config`
|
||||
|
||||
## ✦ Building from Source
|
||||
If you want to build the plugin yourself:
|
||||
- ` mvn clean package`
|
||||
|
74
pom.xml
Normal file
74
pom.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.koopa</groupId>
|
||||
<artifactId>lifestealcore</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>LifeStealCore</name>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>sonatype</id>
|
||||
<url>https://oss.sonatype.org/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
15
src/main/java/com/example/testplugin/Main.java
Normal file
15
src/main/java/com/example/testplugin/Main.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.example.testplugin;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class Main extends JavaPlugin {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
getLogger().info("TestPlugin has been enabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("TestPlugin has been disabled!");
|
||||
}
|
||||
}
|
28
src/main/java/com/example/testplugin/TestPlugin.java
Normal file
28
src/main/java/com/example/testplugin/TestPlugin.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.example.testplugin;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class TestPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
getLogger().info("TestPlugin has been enabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("TestPlugin has been disabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (command.getName().equalsIgnoreCase("test")) {
|
||||
sender.sendMessage(ChatColor.GREEN + "Test command executed successfully!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
77
src/main/java/com/koopa/lifestealcore/LifeStealCore.java
Normal file
77
src/main/java/com/koopa/lifestealcore/LifeStealCore.java
Normal file
@ -0,0 +1,77 @@
|
||||
package com.koopa.lifestealcore;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import com.koopa.lifestealcore.commands.LifeStealCommand;
|
||||
import com.koopa.lifestealcore.listeners.PlayerListener;
|
||||
import com.koopa.lifestealcore.managers.HeartManager;
|
||||
import com.koopa.lifestealcore.listeners.GUIListener;
|
||||
import com.koopa.lifestealcore.managers.BanManager;
|
||||
import com.koopa.lifestealcore.utils.RecipeManager;
|
||||
import com.koopa.lifestealcore.listeners.BeaconListener;
|
||||
import com.koopa.lifestealcore.utils.VersionChecker;
|
||||
import com.koopa.lifestealcore.utils.VersionSupport;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class LifeStealCore extends JavaPlugin {
|
||||
private HeartManager heartManager;
|
||||
private BanManager banManager;
|
||||
private static LifeStealCore instance;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
// Check version compatibility
|
||||
if (!VersionSupport.isSupported()) {
|
||||
getLogger().severe("§8§l[§c§lLifeSteal§8§l] §cThis plugin requires Minecraft 1.13 or newer!");
|
||||
getLogger().severe("§8§l[§c§lLifeSteal§8§l] §cDisabling plugin...");
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log server version info
|
||||
getLogger().info("§8§l[§c§lLifeSteal§8§l] §aDetected server version: " + VersionSupport.getServerVersion());
|
||||
|
||||
// Save default config
|
||||
saveDefaultConfig();
|
||||
|
||||
// Initialize managers
|
||||
heartManager = new HeartManager(this);
|
||||
banManager = new BanManager(this);
|
||||
|
||||
// Register recipes
|
||||
new RecipeManager(this).registerRecipes();
|
||||
|
||||
// Register commands
|
||||
getCommand("lifesteal").setExecutor(new LifeStealCommand(this));
|
||||
|
||||
// Register listeners
|
||||
getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new GUIListener(this), this);
|
||||
getServer().getPluginManager().registerEvents(new BeaconListener(this), this);
|
||||
|
||||
// Add version checker
|
||||
new VersionChecker(this).checkVersion();
|
||||
|
||||
getLogger().info("LifeStealCore has been enabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Save all player data
|
||||
heartManager.saveAllData();
|
||||
getLogger().info("LifeStealCore has been disabled!");
|
||||
}
|
||||
|
||||
public HeartManager getHeartManager() {
|
||||
return heartManager;
|
||||
}
|
||||
|
||||
public BanManager getBanManager() {
|
||||
return banManager;
|
||||
}
|
||||
|
||||
public static LifeStealCore getInstance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
package com.koopa.lifestealcore.commands;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.utils.ItemManager;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import com.koopa.lifestealcore.gui.ConfigGUI;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LifeStealCommand implements CommandExecutor {
|
||||
private final LifeStealCore plugin;
|
||||
private final HashMap<UUID, Boolean> resetConfirmMap = new HashMap<>();
|
||||
|
||||
public LifeStealCommand(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("This command can only be used by players!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
showHelp(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "help" -> showHelp(player);
|
||||
case "withdraw" -> handleWithdraw(player, args);
|
||||
case "deposit" -> handleDeposit(player);
|
||||
case "reset" -> handleReset(player);
|
||||
case "giveheart" -> handleGiveHeart(player, args);
|
||||
case "recipe" -> handleRecipe(player);
|
||||
case "config" -> handleConfig(player);
|
||||
case "debug" -> handleDebugCommand(player, args);
|
||||
default -> player.sendMessage(MessageUtils.color("&cUnknown command! Use /lifesteal help"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showHelp(Player player) {
|
||||
player.sendMessage(MessageUtils.color("&8&l=== &c&lLifeSteal Commands &8&l==="));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal help &8- &7Show this help menu"));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal withdraw <amount> &8- &7Convert hearts to items"));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal deposit &8- &7Deposit heart items"));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal reset &8- &7Reset all players' hearts"));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal giveheart <amount> &8- &7Give yourself heart items"));
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal recipe &8- &7View the revival beacon recipe"));
|
||||
if (player.hasPermission("lifesteal.admin.config")) {
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal config &8- &7Open configuration GUI"));
|
||||
}
|
||||
if (player.hasPermission("lifesteal.admin.debug")) {
|
||||
player.sendMessage(MessageUtils.color("&c/lifesteal debug <ban|unban> <player> &8- &7Test ban/unban messages"));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWithdraw(Player player, String[] args) {
|
||||
if (!player.hasPermission("lifesteal.withdraw")) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.no-permission")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(MessageUtils.color("&cUsage: /lifesteal withdraw <amount>"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int amount = Integer.parseInt(args[1]);
|
||||
int currentHearts = plugin.getHeartManager().getPlayerHearts(player);
|
||||
int minHearts = plugin.getConfig().getInt("settings.min-hearts");
|
||||
|
||||
if (currentHearts - amount < minHearts) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.minimum-hearts-reached")
|
||||
.replace("%min%", String.valueOf(minHearts))));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getHeartManager().setPlayerHearts(player, currentHearts - amount);
|
||||
ItemStack heartItem = ItemManager.createHeartItem(amount);
|
||||
player.getInventory().addItem(heartItem);
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.hearts-withdrawn")
|
||||
.replace("%amount%", String.valueOf(amount))));
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
player.sendMessage(MessageUtils.color("&cPlease enter a valid number!"));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeposit(Player player) {
|
||||
if (!player.hasPermission("lifesteal.deposit")) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.no-permission")));
|
||||
return;
|
||||
}
|
||||
|
||||
int deposited = 0;
|
||||
int maxHearts = plugin.getConfig().getInt("settings.max-hearts");
|
||||
int currentHearts = plugin.getHeartManager().getPlayerHearts(player);
|
||||
|
||||
for (ItemStack item : player.getInventory().getContents()) {
|
||||
if (item != null && ItemManager.isHeartItem(item)) {
|
||||
if (currentHearts + deposited + item.getAmount() <= maxHearts) {
|
||||
deposited += item.getAmount();
|
||||
item.setAmount(0);
|
||||
} else {
|
||||
int canDeposit = maxHearts - (currentHearts + deposited);
|
||||
if (canDeposit > 0) {
|
||||
deposited += canDeposit;
|
||||
item.setAmount(item.getAmount() - canDeposit);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deposited > 0) {
|
||||
plugin.getHeartManager().setPlayerHearts(player, currentHearts + deposited);
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.hearts-deposited")
|
||||
.replace("%amount%", String.valueOf(deposited))));
|
||||
} else {
|
||||
player.sendMessage(MessageUtils.color("&cNo hearts found in your inventory!"));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleReset(Player player) {
|
||||
if (!player.hasPermission("lifesteal.admin.reset")) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.no-permission")));
|
||||
return;
|
||||
}
|
||||
|
||||
int defaultHearts = plugin.getConfig().getInt("settings.default-hearts");
|
||||
for (Player onlinePlayer : plugin.getServer().getOnlinePlayers()) {
|
||||
plugin.getHeartManager().setPlayerHearts(onlinePlayer, defaultHearts);
|
||||
}
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.hearts-reset")));
|
||||
}
|
||||
|
||||
private void handleGiveHeart(Player player, String[] args) {
|
||||
if (!player.hasPermission("lifesteal.admin.give")) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.no-permission")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length != 2) {
|
||||
player.sendMessage(MessageUtils.color("&cUsage: /lifesteal giveheart <amount>"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int amount = Integer.parseInt(args[1]);
|
||||
ItemStack heartItem = ItemManager.createHeartItem(amount);
|
||||
player.getInventory().addItem(heartItem);
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.hearts-given")
|
||||
.replace("%amount%", String.valueOf(amount))
|
||||
.replace("%player%", player.getName())));
|
||||
} catch (NumberFormatException e) {
|
||||
player.sendMessage(MessageUtils.color("&cPlease enter a valid number!"));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRecipe(Player player) {
|
||||
new ConfigGUI(plugin).openRecipeGUI(player, plugin.getConfig().getString("settings.difficulty", "MEDIUM"));
|
||||
}
|
||||
|
||||
private void handleConfig(Player player) {
|
||||
if (!player.hasPermission("lifesteal.admin.config")) {
|
||||
player.sendMessage(MessageUtils.color("&cYou don't have permission to use this command!"));
|
||||
return;
|
||||
}
|
||||
new ConfigGUI(plugin).openConfigGUI(player);
|
||||
}
|
||||
|
||||
private void handleDebugCommand(Player player, String[] args) {
|
||||
if (!player.hasPermission("lifesteal.admin.debug")) {
|
||||
player.sendMessage(MessageUtils.color("&cYou don't have permission to use debug commands!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
player.sendMessage(MessageUtils.color("&cUsage: /lifesteal debug <ban|unban> <player>"));
|
||||
return;
|
||||
}
|
||||
|
||||
String action = args[1].toLowerCase();
|
||||
String targetName = args[2];
|
||||
Player target = Bukkit.getPlayer(targetName);
|
||||
|
||||
switch (action) {
|
||||
case "ban" -> {
|
||||
if (target == null) {
|
||||
player.sendMessage(MessageUtils.color("&cPlayer not found!"));
|
||||
return;
|
||||
}
|
||||
// Test ban message with both killer and victim
|
||||
plugin.getBanManager().banPlayer(target, player);
|
||||
player.sendMessage(MessageUtils.color("&aDebug: Tested ban message for " + target.getName() +
|
||||
" (killed by " + player.getName() + ")"));
|
||||
}
|
||||
case "unban" -> {
|
||||
// Test unban/revival message
|
||||
plugin.getBanManager().unbanPlayer(player, targetName);
|
||||
player.sendMessage(MessageUtils.color("&aDebug: Tested unban message for " + targetName +
|
||||
" (revived by " + player.getName() + ")"));
|
||||
}
|
||||
default -> player.sendMessage(MessageUtils.color("&cInvalid debug action! Use 'ban' or 'unban'"));
|
||||
}
|
||||
}
|
||||
}
|
188
src/main/java/com/koopa/lifestealcore/gui/ConfigGUI.java
Normal file
188
src/main/java/com/koopa/lifestealcore/gui/ConfigGUI.java
Normal file
@ -0,0 +1,188 @@
|
||||
package com.koopa.lifestealcore.gui;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigGUI {
|
||||
private final LifeStealCore plugin;
|
||||
private static final String GUI_TITLE = "§8LifeSteal Configuration";
|
||||
private static final String RECIPE_GUI_TITLE = "§8Revival Beacon Recipe";
|
||||
|
||||
public ConfigGUI(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void openConfigGUI(Player player) {
|
||||
Inventory gui = Bukkit.createInventory(null, 36, GUI_TITLE);
|
||||
|
||||
// Fill with gray stained glass panes
|
||||
for (int i = 0; i < gui.getSize(); i++) {
|
||||
gui.setItem(i, createConfigItem(Material.GRAY_STAINED_GLASS_PANE, " "));
|
||||
}
|
||||
|
||||
// Default Hearts Setting (Heart of the Sea)
|
||||
gui.setItem(11, createConfigItem(Material.HEART_OF_THE_SEA,
|
||||
"&c&lDefault Hearts",
|
||||
"&7Current value: &f" + plugin.getConfig().getInt("settings.default-hearts"),
|
||||
"&7",
|
||||
"&7Click to change the default",
|
||||
"&7hearts for new players"));
|
||||
|
||||
// Min Hearts Setting (Redstone)
|
||||
gui.setItem(13, createConfigItem(Material.REDSTONE,
|
||||
"&c&lMinimum Hearts",
|
||||
"&7Current value: &f" + plugin.getConfig().getInt("settings.min-hearts"),
|
||||
"&7",
|
||||
"&7Click to change the minimum",
|
||||
"&7hearts a player can have"));
|
||||
|
||||
// Max Hearts Setting (Diamond)
|
||||
gui.setItem(15, createConfigItem(Material.DIAMOND,
|
||||
"&c&lMaximum Hearts",
|
||||
"&7Current value: &f" + plugin.getConfig().getInt("settings.max-hearts"),
|
||||
"&7",
|
||||
"&7Click to change the maximum",
|
||||
"&7hearts a player can have"));
|
||||
|
||||
// Heart Item Preview (Nether Star)
|
||||
gui.setItem(21, createConfigItem(Material.NETHER_STAR,
|
||||
plugin.getConfig().getString("settings.heart-item-name"),
|
||||
"&7",
|
||||
"&7Current heart item settings:",
|
||||
"&7" + String.join("&7", plugin.getConfig().getStringList("settings.heart-item-lore"))));
|
||||
|
||||
// Difficulty Selector (Netherite Ingot)
|
||||
ItemStack difficultyItem = new ItemStack(Material.CRAFTING_TABLE);
|
||||
ItemMeta diffMeta = difficultyItem.getItemMeta();
|
||||
String currentDifficulty = plugin.getConfig().getString("settings.difficulty", "MEDIUM");
|
||||
diffMeta.setDisplayName(MessageUtils.color("&c&lCrafting Difficulty"));
|
||||
diffMeta.setLore(Arrays.asList(
|
||||
MessageUtils.color("&7Current: &f" + currentDifficulty),
|
||||
MessageUtils.color("&7"),
|
||||
MessageUtils.color("&7Left-Click to change"),
|
||||
MessageUtils.color("&7Right-Click to view recipe")
|
||||
));
|
||||
difficultyItem.setItemMeta(diffMeta);
|
||||
gui.setItem(23, difficultyItem);
|
||||
|
||||
// Save & Reload button (Emerald)
|
||||
gui.setItem(31, createConfigItem(Material.EMERALD,
|
||||
"&a&lSave & Reload",
|
||||
"&7",
|
||||
"&7Click to save changes",
|
||||
"&7and reload the config"));
|
||||
|
||||
player.openInventory(gui);
|
||||
}
|
||||
|
||||
public void openRecipeGUI(Player player, String difficulty) {
|
||||
Inventory gui = Bukkit.createInventory(null, 27, RECIPE_GUI_TITLE);
|
||||
String configPath = "settings.recipe-materials." + difficulty;
|
||||
|
||||
// Fill with gray stained glass panes first
|
||||
for (int i = 0; i < gui.getSize(); i++) {
|
||||
gui.setItem(i, createConfigItem(Material.GRAY_STAINED_GLASS_PANE, " "));
|
||||
}
|
||||
|
||||
// Get recipe materials
|
||||
Material cornerMaterial = difficulty.equals("EASY") ?
|
||||
Material.NETHER_STAR : // Hearts for EASY mode
|
||||
Material.valueOf(plugin.getConfig().getString(configPath + ".top_corners"));
|
||||
Material centerMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".center_row"));
|
||||
Material skullMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".skull"));
|
||||
Material bottomMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".bottom"));
|
||||
|
||||
// Set recipe items
|
||||
ItemStack corner = difficulty.equals("EASY") ?
|
||||
createConfigItem(Material.NETHER_STAR, "&c❤ Heart", "&7Required: 2") :
|
||||
createConfigItem(cornerMaterial, "&f" + cornerMaterial.name(), "&7Required: 2");
|
||||
ItemStack center = createConfigItem(centerMaterial, "&f" + centerMaterial.name(), "&7Required: 3");
|
||||
ItemStack skull = createConfigItem(skullMaterial, "&f" + skullMaterial.name(), "&7Required: 1");
|
||||
ItemStack bottom = createConfigItem(bottomMaterial, "&f" + bottomMaterial.name(), "&7Required: 3");
|
||||
|
||||
// Place items in crafting grid pattern (original layout)
|
||||
gui.setItem(3, corner); // Top left
|
||||
gui.setItem(4, center); // Top middle
|
||||
gui.setItem(5, corner); // Top right
|
||||
gui.setItem(12, center); // Middle left
|
||||
gui.setItem(13, skull); // Center
|
||||
gui.setItem(14, center); // Middle right
|
||||
gui.setItem(21, bottom); // Bottom left
|
||||
gui.setItem(22, bottom); // Bottom middle
|
||||
gui.setItem(23, bottom); // Bottom right
|
||||
|
||||
// Result item
|
||||
ItemStack result = createConfigItem(Material.BEACON, "&c&lRevival Beacon",
|
||||
"&7The result of the recipe",
|
||||
"&7in " + difficulty + " mode");
|
||||
gui.setItem(16, result);
|
||||
|
||||
// Back button
|
||||
gui.setItem(18, createConfigItem(Material.ARROW, "&c&lBack to Settings",
|
||||
"&7Click to return to the settings menu"));
|
||||
|
||||
player.openInventory(gui);
|
||||
}
|
||||
|
||||
public void openCustomRecipeGUI(Player player) {
|
||||
Inventory gui = Bukkit.createInventory(null, 54, "§8Custom Recipe Editor");
|
||||
|
||||
// Fill with gray stained glass panes
|
||||
for (int i = 0; i < gui.getSize(); i++) {
|
||||
gui.setItem(i, createConfigItem(Material.GRAY_STAINED_GLASS_PANE, " "));
|
||||
}
|
||||
|
||||
// Create empty crafting grid
|
||||
int[] craftingSlots = {11, 12, 13, 20, 21, 22, 29, 30, 31};
|
||||
for (int slot : craftingSlots) {
|
||||
gui.setItem(slot, null); // Empty slots for items
|
||||
}
|
||||
|
||||
// Result item (Beacon)
|
||||
gui.setItem(24, createConfigItem(Material.BEACON, "&c&lRevival Beacon",
|
||||
"&7The crafting result"));
|
||||
|
||||
// Save button
|
||||
gui.setItem(49, createConfigItem(Material.EMERALD, "&a&lSave Recipe",
|
||||
"&7Click to save your custom recipe"));
|
||||
|
||||
// Back button
|
||||
gui.setItem(45, createConfigItem(Material.ARROW, "&c&lBack",
|
||||
"&7Return to settings"));
|
||||
|
||||
player.openInventory(gui);
|
||||
}
|
||||
|
||||
private boolean isInCraftingGrid(int slot) {
|
||||
int[] craftingSlots = {11, 12, 13, 20, 21, 22, 29, 30, 31};
|
||||
for (int craftingSlot : craftingSlots) {
|
||||
if (slot == craftingSlot) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ItemStack createConfigItem(Material material, String name, String... lore) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color(name));
|
||||
|
||||
List<String> loreList = new ArrayList<>();
|
||||
for (String line : lore) {
|
||||
loreList.add(MessageUtils.color(line));
|
||||
}
|
||||
meta.setLore(loreList);
|
||||
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
}
|
60
src/main/java/com/koopa/lifestealcore/gui/RevivalGUI.java
Normal file
60
src/main/java/com/koopa/lifestealcore/gui/RevivalGUI.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.koopa.lifestealcore.gui;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class RevivalGUI {
|
||||
private static final String GUI_TITLE = "§c§lRevive Banned Player";
|
||||
private final Location beaconLocation;
|
||||
|
||||
public RevivalGUI(Location beaconLocation) {
|
||||
this.beaconLocation = beaconLocation;
|
||||
}
|
||||
|
||||
public void openGUI(Player player) {
|
||||
List<String> bannedPlayers = LifeStealCore.getInstance().getBanManager().getBannedPlayers();
|
||||
|
||||
// Always create at least a 9-slot inventory
|
||||
int size = bannedPlayers.isEmpty() ? 9 : Math.min(((bannedPlayers.size() + 8) / 9) * 9, 54);
|
||||
Inventory gui = Bukkit.createInventory(null, size, GUI_TITLE);
|
||||
|
||||
if (bannedPlayers.isEmpty()) {
|
||||
// Add an item to show there are no banned players
|
||||
ItemStack noPlayers = new ItemStack(Material.BARRIER);
|
||||
ItemMeta meta = noPlayers.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color("&cNo banned players!"));
|
||||
meta.setLore(Arrays.asList(
|
||||
MessageUtils.color("&7There are currently no"),
|
||||
MessageUtils.color("&7banned players to revive.")
|
||||
));
|
||||
noPlayers.setItemMeta(meta);
|
||||
gui.setItem(4, noPlayers);
|
||||
} else {
|
||||
// Add banned player heads
|
||||
for (String playerName : bannedPlayers) {
|
||||
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
|
||||
SkullMeta meta = (SkullMeta) skull.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color("&c" + playerName));
|
||||
meta.setLore(Arrays.asList(
|
||||
MessageUtils.color("&7Click to revive this player"),
|
||||
MessageUtils.color("&7They will spawn at this beacon")
|
||||
));
|
||||
meta.setOwner(playerName);
|
||||
skull.setItemMeta(meta);
|
||||
gui.addItem(skull);
|
||||
}
|
||||
}
|
||||
|
||||
player.openInventory(gui);
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.koopa.lifestealcore.listeners;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.gui.RevivalGUI;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class BeaconListener implements Listener {
|
||||
private final LifeStealCore plugin;
|
||||
private Location lastBeaconLocation;
|
||||
|
||||
public BeaconListener(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBeaconPlace(BlockPlaceEvent event) {
|
||||
ItemStack item = event.getItemInHand();
|
||||
if (item.getType() != Material.BEACON || !item.hasItemMeta() ||
|
||||
!item.getItemMeta().getDisplayName().equals(MessageUtils.color("&c&lRevival Beacon"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastBeaconLocation = event.getBlock().getLocation();
|
||||
new RevivalGUI(lastBeaconLocation).openGUI(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onGUIClick(InventoryClickEvent event) {
|
||||
if (!event.getView().getTitle().equals("§c§lRevive Banned Player")) return;
|
||||
event.setCancelled(true);
|
||||
|
||||
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||
|
||||
ItemStack clicked = event.getCurrentItem();
|
||||
if (clicked == null) return;
|
||||
|
||||
// If it's the "no players" barrier, just return
|
||||
if (clicked.getType() == Material.BARRIER) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle player head clicks
|
||||
if (clicked.getType() == Material.PLAYER_HEAD) {
|
||||
String playerName = clicked.getItemMeta().getDisplayName().substring(2); // Remove color code
|
||||
|
||||
// Remove the beacon block
|
||||
if (lastBeaconLocation != null) {
|
||||
Block beacon = lastBeaconLocation.getBlock();
|
||||
if (beacon.getType() == Material.BEACON) {
|
||||
beacon.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getBanManager().revivePlayer(playerName, lastBeaconLocation);
|
||||
player.sendMessage(MessageUtils.color("&aPlayer has been revived!"));
|
||||
player.closeInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Location revivalLoc = plugin.getBanManager().getRevivalLocation(player.getUniqueId());
|
||||
|
||||
if (revivalLoc != null) {
|
||||
player.teleport(revivalLoc);
|
||||
plugin.getHeartManager().setPlayerHearts(player, 5);
|
||||
player.sendMessage(MessageUtils.color("&aYou have been revived! You have 5 hearts."));
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel right-clicking the beacon to prevent the vanilla beacon GUI
|
||||
@EventHandler
|
||||
public void onBeaconInteract(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.BEACON) return;
|
||||
|
||||
// Check if it's our revival beacon by location
|
||||
if (lastBeaconLocation != null && lastBeaconLocation.equals(event.getClickedBlock().getLocation())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
245
src/main/java/com/koopa/lifestealcore/listeners/GUIListener.java
Normal file
245
src/main/java/com/koopa/lifestealcore/listeners/GUIListener.java
Normal file
@ -0,0 +1,245 @@
|
||||
package com.koopa.lifestealcore.listeners;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.gui.ConfigGUI;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GUIListener implements Listener {
|
||||
private final LifeStealCore plugin;
|
||||
private static final String GUI_TITLE = "§8LifeSteal Configuration";
|
||||
private final HashMap<UUID, String> editingPlayers = new HashMap<>();
|
||||
private final HashMap<UUID, String> materialEditing = new HashMap<>();
|
||||
|
||||
public GUIListener(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
String title = event.getView().getTitle();
|
||||
|
||||
// Handle Config GUI
|
||||
if (title.equals("§8LifeSteal Configuration")) {
|
||||
event.setCancelled(true);
|
||||
handleConfigGUI(event);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Recipe View GUI
|
||||
if (title.equals("§8Revival Beacon Recipe")) {
|
||||
event.setCancelled(true);
|
||||
if (event.getSlot() == 18) { // Back button
|
||||
new ConfigGUI(plugin).openConfigGUI((Player) event.getWhoClicked());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Custom Recipe Editor
|
||||
if (title.equals("§8Custom Recipe Editor")) {
|
||||
handleCustomRecipeEditor(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCustomRecipeEditor(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||
if (!player.hasPermission("lifesteal.admin.config")) return;
|
||||
|
||||
int slot = event.getSlot();
|
||||
int[] craftingSlots = {11, 12, 13, 20, 21, 22, 29, 30, 31};
|
||||
|
||||
// Allow clicking in crafting grid
|
||||
if (isInArray(slot, craftingSlots)) {
|
||||
event.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle save button
|
||||
if (slot == 49) {
|
||||
event.setCancelled(true);
|
||||
saveCustomRecipe(event.getInventory());
|
||||
player.sendMessage(MessageUtils.color("&aCustom recipe saved!"));
|
||||
new ConfigGUI(plugin).openConfigGUI(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle back button
|
||||
if (slot == 45) {
|
||||
event.setCancelled(true);
|
||||
new ConfigGUI(plugin).openConfigGUI(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel all other clicks in the GUI
|
||||
if (event.getClickedInventory() != null &&
|
||||
event.getView().getTitle().equals("§8Custom Recipe Editor")) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInArray(int value, int[] array) {
|
||||
for (int i : array) {
|
||||
if (i == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ItemStack createEmptySlot() {
|
||||
ItemStack item = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color("&7Click to set item"));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
private void handleConfigGUI(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||
if (!player.hasPermission("lifesteal.admin.config")) return;
|
||||
|
||||
switch (event.getSlot()) {
|
||||
case 11 -> promptForValue(player, "default-hearts", "Enter new default hearts value:");
|
||||
case 13 -> promptForValue(player, "min-hearts", "Enter new minimum hearts value:");
|
||||
case 15 -> promptForValue(player, "max-hearts", "Enter new maximum hearts value:");
|
||||
case 23 -> handleDifficultyClick(event);
|
||||
case 31 -> {
|
||||
plugin.reloadConfig();
|
||||
player.sendMessage(MessageUtils.color("&aConfiguration reloaded!"));
|
||||
player.closeInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDifficultyClick(InventoryClickEvent event) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (event.isRightClick()) {
|
||||
if (plugin.getConfig().getString("settings.difficulty").equals("CUSTOM")) {
|
||||
new ConfigGUI(plugin).openCustomRecipeGUI(player);
|
||||
} else {
|
||||
String currentDiff = plugin.getConfig().getString("settings.difficulty", "MEDIUM");
|
||||
new ConfigGUI(plugin).openRecipeGUI(player, currentDiff);
|
||||
}
|
||||
} else if (event.isLeftClick()) {
|
||||
String currentDiff = plugin.getConfig().getString("settings.difficulty", "MEDIUM");
|
||||
String newDiff = switch (currentDiff) {
|
||||
case "EASY" -> "MEDIUM";
|
||||
case "MEDIUM" -> "HARD";
|
||||
case "HARD" -> "CUSTOM";
|
||||
case "CUSTOM" -> "EASY";
|
||||
default -> "MEDIUM";
|
||||
};
|
||||
plugin.getConfig().set("settings.difficulty", newDiff);
|
||||
plugin.saveConfig();
|
||||
new ConfigGUI(plugin).openConfigGUI(player);
|
||||
player.sendMessage(MessageUtils.color("&aSet crafting difficulty to: " + newDiff));
|
||||
}
|
||||
}
|
||||
|
||||
private void saveCustomRecipe(Inventory gui) {
|
||||
String configPath = "settings.recipe-materials.CUSTOM";
|
||||
|
||||
// Get materials from crafting grid
|
||||
ItemStack cornerItem = gui.getItem(11);
|
||||
ItemStack centerItem = gui.getItem(12);
|
||||
ItemStack skullItem = gui.getItem(21);
|
||||
ItemStack bottomItem = gui.getItem(29);
|
||||
|
||||
// Save to config (checking for null items)
|
||||
plugin.getConfig().set(configPath + ".top_corners",
|
||||
cornerItem != null ? cornerItem.getType().name() : "GLASS");
|
||||
plugin.getConfig().set(configPath + ".center_row",
|
||||
centerItem != null ? centerItem.getType().name() : "DIAMOND");
|
||||
plugin.getConfig().set(configPath + ".skull",
|
||||
skullItem != null ? skullItem.getType().name() : "WITHER_SKELETON_SKULL");
|
||||
plugin.getConfig().set(configPath + ".bottom",
|
||||
bottomItem != null ? bottomItem.getType().name() : "OBSIDIAN");
|
||||
plugin.saveConfig();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (event.getView().getTitle().equals("§8Custom Recipe Editor")) {
|
||||
event.getPlayer().setItemOnCursor(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void promptForValue(Player player, String setting, String prompt) {
|
||||
player.closeInventory();
|
||||
player.sendMessage(MessageUtils.color(prompt));
|
||||
editingPlayers.put(player.getUniqueId(), "settings." + setting);
|
||||
}
|
||||
|
||||
private void promptForMaterial(Player player, String part, String prompt) {
|
||||
player.closeInventory();
|
||||
player.sendMessage(MessageUtils.color(prompt));
|
||||
materialEditing.put(player.getUniqueId(), "settings.recipe-materials.CUSTOM." + part);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String settingValue = editingPlayers.get(player.getUniqueId());
|
||||
String settingMaterial = materialEditing.get(player.getUniqueId());
|
||||
|
||||
if (settingValue != null) {
|
||||
event.setCancelled(true);
|
||||
try {
|
||||
int value = Integer.parseInt(event.getMessage());
|
||||
plugin.getConfig().set(settingValue, value);
|
||||
plugin.saveConfig();
|
||||
player.sendMessage(MessageUtils.color("&aValue updated!"));
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
new ConfigGUI(plugin).openConfigGUI(player);
|
||||
});
|
||||
} catch (NumberFormatException e) {
|
||||
player.sendMessage(MessageUtils.color("&cPlease enter a valid number!"));
|
||||
}
|
||||
editingPlayers.remove(player.getUniqueId());
|
||||
}
|
||||
else if (settingMaterial != null) {
|
||||
event.setCancelled(true);
|
||||
if (event.getMessage().equalsIgnoreCase("cancel")) {
|
||||
player.sendMessage(MessageUtils.color("&cCancelled material selection."));
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
new ConfigGUI(plugin).openCustomRecipeGUI(player);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
Material material = Material.valueOf(event.getMessage().toUpperCase());
|
||||
plugin.getConfig().set(settingMaterial, material.name());
|
||||
plugin.saveConfig();
|
||||
player.sendMessage(MessageUtils.color("&aMaterial updated!"));
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
new ConfigGUI(plugin).openCustomRecipeGUI(player);
|
||||
});
|
||||
} catch (IllegalArgumentException e) {
|
||||
player.sendMessage(MessageUtils.color("&cInvalid material! Try again or type 'cancel'"));
|
||||
}
|
||||
}
|
||||
materialEditing.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
private ItemStack createConfigItem(Material material, String name) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color(name));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package com.koopa.lifestealcore.listeners;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import com.koopa.lifestealcore.utils.ItemManager;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
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.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
public class PlayerListener implements Listener {
|
||||
private final LifeStealCore plugin;
|
||||
|
||||
public PlayerListener(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
plugin.getHeartManager().updatePlayerMaxHealth(player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
Player victim = event.getEntity();
|
||||
Player killer = victim.getKiller();
|
||||
|
||||
if (killer != null && killer != victim) {
|
||||
int victimHearts = plugin.getHeartManager().getPlayerHearts(victim);
|
||||
int killerHearts = plugin.getHeartManager().getPlayerHearts(killer);
|
||||
|
||||
if (victimHearts > plugin.getConfig().getInt("settings.min-hearts")) {
|
||||
plugin.getHeartManager().setPlayerHearts(victim, victimHearts - 1);
|
||||
plugin.getHeartManager().setPlayerHearts(killer, killerHearts + 1);
|
||||
killer.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 100, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Ban the player
|
||||
plugin.getBanManager().banPlayer(victim);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = event.getItem();
|
||||
|
||||
// Check if right-clicking with a heart item
|
||||
if ((event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)
|
||||
&& ItemManager.isHeartItem(item)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
int currentHearts = plugin.getHeartManager().getPlayerHearts(player);
|
||||
int maxHearts = plugin.getConfig().getInt("settings.max-hearts");
|
||||
|
||||
if (currentHearts >= maxHearts) {
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.maximum-hearts-reached")
|
||||
.replace("%max%", String.valueOf(maxHearts))));
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove one heart item and add to player's health
|
||||
item.setAmount(item.getAmount() - 1);
|
||||
plugin.getHeartManager().setPlayerHearts(player, currentHearts + 1);
|
||||
player.sendMessage(MessageUtils.color(plugin.getConfig().getString("messages.hearts-deposited")
|
||||
.replace("%amount%", "1")));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHeartChange(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
// Give regeneration effect when hearts change
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 100, 1)); // 5 seconds of Regen II
|
||||
}
|
||||
}
|
179
src/main/java/com/koopa/lifestealcore/managers/BanManager.java
Normal file
179
src/main/java/com/koopa/lifestealcore/managers/BanManager.java
Normal file
@ -0,0 +1,179 @@
|
||||
package com.koopa.lifestealcore.managers;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import org.bukkit.BanList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import org.bukkit.Sound;
|
||||
import com.koopa.lifestealcore.utils.MessageUtils;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class BanManager {
|
||||
private final LifeStealCore plugin;
|
||||
private final Map<UUID, Boolean> bannedPlayers = new HashMap<>();
|
||||
private final Map<UUID, Location> revivalLocations = new HashMap<>();
|
||||
private final File banFile;
|
||||
private YamlConfiguration banData;
|
||||
|
||||
public BanManager(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
this.banFile = new File(plugin.getDataFolder(), "bans.yml");
|
||||
loadBanData();
|
||||
}
|
||||
|
||||
private void loadBanData() {
|
||||
if (!banFile.exists()) {
|
||||
try {
|
||||
banFile.createNewFile();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
banData = YamlConfiguration.loadConfiguration(banFile);
|
||||
}
|
||||
|
||||
public void saveBanData() {
|
||||
try {
|
||||
banData.save(banFile);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void banPlayer(Player player) {
|
||||
banPlayer(player, false);
|
||||
}
|
||||
|
||||
public void banPlayer(Player player, boolean debugMode) {
|
||||
bannedPlayers.put(player.getUniqueId(), true);
|
||||
|
||||
// Save to ban data
|
||||
banData.set(player.getUniqueId().toString() + ".name", player.getName());
|
||||
banData.set(player.getUniqueId().toString() + ".banTime", System.currentTimeMillis());
|
||||
saveBanData();
|
||||
|
||||
if (!debugMode) {
|
||||
// Ban the player
|
||||
Bukkit.getBanList(BanList.Type.NAME).addBan(
|
||||
player.getName(),
|
||||
"§c§lYou died! §7Get someone to revive you with a Revival Beacon!",
|
||||
null,
|
||||
"LifeSteal System"
|
||||
);
|
||||
player.kickPlayer("§c§lYou died! §7Get someone to revive you with a Revival Beacon!");
|
||||
}
|
||||
}
|
||||
|
||||
public void revivePlayer(String playerName, Location beaconLoc) {
|
||||
UUID uuid = null;
|
||||
for (String key : banData.getKeys(false)) {
|
||||
if (banData.getString(key + ".name").equalsIgnoreCase(playerName)) {
|
||||
uuid = UUID.fromString(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
bannedPlayers.remove(uuid);
|
||||
revivalLocations.put(uuid, beaconLoc);
|
||||
banData.set(uuid.toString(), null);
|
||||
saveBanData();
|
||||
}
|
||||
|
||||
Bukkit.getBanList(BanList.Type.NAME).pardon(playerName);
|
||||
}
|
||||
|
||||
public void revivePlayer(String playerName) {
|
||||
revivePlayer(playerName, null);
|
||||
}
|
||||
|
||||
public List<String> getBannedPlayers() {
|
||||
List<String> players = new ArrayList<>();
|
||||
for (String key : banData.getKeys(false)) {
|
||||
players.add(banData.getString(key + ".name"));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public Location getRevivalLocation(UUID uuid) {
|
||||
Location loc = revivalLocations.get(uuid);
|
||||
revivalLocations.remove(uuid);
|
||||
return loc;
|
||||
}
|
||||
|
||||
public boolean isPlayerBanned(UUID uuid) {
|
||||
return bannedPlayers.getOrDefault(uuid, false);
|
||||
}
|
||||
|
||||
public void banPlayer(Player player, Player killer) {
|
||||
// Play dramatic sound to all players
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_ENDER_DRAGON_GROWL, 1.0f, 0.5f);
|
||||
}
|
||||
|
||||
// Dramatic ban message
|
||||
Bukkit.broadcastMessage("");
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&8&l[&c&l!!!&8&l] &c&lA PLAYER HAS FALLEN &8&l[&c&l!!!&8&l]"));
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&7" + player.getName() + " &8has lost their final heart..."));
|
||||
if (killer != null) {
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&7Slain by the hands of &c" + killer.getName()));
|
||||
}
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&c&lBANISHED TO THE SHADOW REALM"));
|
||||
Bukkit.broadcastMessage("");
|
||||
|
||||
// Ban the player
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
player.kickPlayer(MessageUtils.color(
|
||||
"&c&lYOU HAVE BEEN BANISHED!\n\n" +
|
||||
"&7You have lost all your hearts...\n" +
|
||||
"&7Find a Revival Beacon to return!"
|
||||
));
|
||||
plugin.getConfig().set("banned-players." + player.getUniqueId(), true);
|
||||
plugin.saveConfig();
|
||||
}, 2L); // Small delay for dramatic effect
|
||||
}
|
||||
|
||||
public void unbanPlayer(Player revivedBy, String playerName) {
|
||||
// Get the banned player's UUID
|
||||
UUID bannedUUID = null;
|
||||
String bannedName = playerName;
|
||||
|
||||
for (String uuidStr : plugin.getConfig().getConfigurationSection("banned-players").getKeys(false)) {
|
||||
UUID uuid = UUID.fromString(uuidStr);
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
if (offlinePlayer.getName().equalsIgnoreCase(playerName)) {
|
||||
bannedUUID = uuid;
|
||||
bannedName = offlinePlayer.getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bannedUUID != null) {
|
||||
// Play dramatic revival sound
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
p.playSound(p.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.0f, 1.0f);
|
||||
p.playSound(p.getLocation(), Sound.BLOCK_BEACON_ACTIVATE, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Dramatic revival message
|
||||
Bukkit.broadcastMessage("");
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&8&l[&e&l!!!&8&l] &e&lA SOUL HAS BEEN REVIVED &8&l[&e&l!!!&8&l]"));
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&7Through the power of the Revival Beacon..."));
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&e" + bannedName + " &7has been given another chance!"));
|
||||
Bukkit.broadcastMessage(MessageUtils.color("&7Restored to life by &e" + revivedBy.getName()));
|
||||
Bukkit.broadcastMessage("");
|
||||
|
||||
// Unban the player
|
||||
plugin.getConfig().set("banned-players." + bannedUUID, null);
|
||||
plugin.saveConfig();
|
||||
|
||||
// Reset their hearts to default
|
||||
plugin.getHeartManager().setHearts(bannedUUID,
|
||||
plugin.getConfig().getInt("settings.default-hearts", 10));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.koopa.lifestealcore.managers;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class HeartManager {
|
||||
private final LifeStealCore plugin;
|
||||
private final Map<UUID, Integer> playerHearts;
|
||||
private final File dataFile;
|
||||
private FileConfiguration data;
|
||||
|
||||
public HeartManager(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
this.playerHearts = new HashMap<>();
|
||||
this.dataFile = new File(plugin.getDataFolder(), "hearts.yml");
|
||||
loadData();
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
if (!dataFile.exists()) {
|
||||
try {
|
||||
dataFile.getParentFile().mkdirs();
|
||||
dataFile.createNewFile();
|
||||
data = new YamlConfiguration();
|
||||
data.save(dataFile);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Could not create hearts.yml!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
data = YamlConfiguration.loadConfiguration(dataFile);
|
||||
}
|
||||
|
||||
public void saveAllData() {
|
||||
if (data == null) return;
|
||||
|
||||
for (Map.Entry<UUID, Integer> entry : playerHearts.entrySet()) {
|
||||
data.set(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
|
||||
try {
|
||||
data.save(dataFile);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().severe("Could not save hearts data!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getPlayerHearts(Player player) {
|
||||
return playerHearts.getOrDefault(player.getUniqueId(),
|
||||
plugin.getConfig().getInt("settings.default-hearts"));
|
||||
}
|
||||
|
||||
public void setPlayerHearts(Player player, int hearts) {
|
||||
playerHearts.put(player.getUniqueId(), hearts);
|
||||
updatePlayerMaxHealth(player);
|
||||
}
|
||||
|
||||
public void updatePlayerMaxHealth(Player player) {
|
||||
int hearts = getPlayerHearts(player);
|
||||
player.setMaxHealth(hearts * 2);
|
||||
}
|
||||
|
||||
public void setHearts(UUID uuid, int hearts) {
|
||||
// Ensure hearts are within configured limits
|
||||
int minHearts = plugin.getConfig().getInt("settings.min-hearts", 1);
|
||||
int maxHearts = plugin.getConfig().getInt("settings.max-hearts", 20);
|
||||
|
||||
hearts = Math.max(minHearts, Math.min(maxHearts, hearts));
|
||||
|
||||
// Update hearts in memory and config
|
||||
playerHearts.put(uuid, hearts);
|
||||
plugin.getConfig().set("player-hearts." + uuid, hearts);
|
||||
plugin.saveConfig();
|
||||
|
||||
// Update player's max health if they're online
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null && player.isOnline()) {
|
||||
player.setMaxHealth(hearts * 2);
|
||||
player.setHealth(player.getMaxHealth());
|
||||
}
|
||||
}
|
||||
}
|
36
src/main/java/com/koopa/lifestealcore/utils/ItemManager.java
Normal file
36
src/main/java/com/koopa/lifestealcore/utils/ItemManager.java
Normal file
@ -0,0 +1,36 @@
|
||||
package com.koopa.lifestealcore.utils;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemManager {
|
||||
private static final NamespacedKey HEART_KEY = new NamespacedKey(LifeStealCore.getInstance(), "lifesteal_heart");
|
||||
|
||||
public static ItemStack createHeartItem(int amount) {
|
||||
ItemStack item = new ItemStack(Material.NETHER_STAR, amount);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color("&c❤ Heart"));
|
||||
meta.setLore(Arrays.asList(
|
||||
MessageUtils.color("&7Right-click to consume"),
|
||||
MessageUtils.color("&7and gain an extra heart")
|
||||
));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static boolean isHeartItem(ItemStack item) {
|
||||
if (item == null || item.getType() != Material.NETHER_STAR) return false;
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta == null) return false;
|
||||
return meta.hasDisplayName() &&
|
||||
meta.getDisplayName().equals(MessageUtils.color("&c❤ Heart"));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.koopa.lifestealcore.utils;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MessageUtils {
|
||||
public static String color(String message) {
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
|
||||
public static void sendHelpMenu(CommandSender sender, ConfigurationSection config) {
|
||||
// Send header
|
||||
sender.sendMessage(color(config.getString("messages.help.header")));
|
||||
|
||||
// Send command list
|
||||
String format = config.getString("messages.help.format");
|
||||
List<Map<?, ?>> commands = config.getMapList("messages.help.commands");
|
||||
|
||||
for (Map<?, ?> cmdMap : commands) {
|
||||
String command = (String) cmdMap.get("command");
|
||||
String description = (String) cmdMap.get("description");
|
||||
String permission = (String) cmdMap.get("permission");
|
||||
|
||||
// Only show commands the player has permission for
|
||||
if (permission == null || sender.hasPermission(permission)) {
|
||||
String helpLine = format
|
||||
.replace("%command%", command)
|
||||
.replace("%description%", description);
|
||||
sender.sendMessage(color(helpLine));
|
||||
}
|
||||
}
|
||||
|
||||
// Send footer
|
||||
sender.sendMessage(color(config.getString("messages.help.footer")));
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.koopa.lifestealcore.utils;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.RecipeChoice;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RecipeManager {
|
||||
private final LifeStealCore plugin;
|
||||
private static final NamespacedKey REVIVAL_BEACON_KEY = new NamespacedKey(LifeStealCore.getInstance(), "revival_beacon");
|
||||
|
||||
public RecipeManager(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void registerRecipes() {
|
||||
String difficulty = plugin.getConfig().getString("settings.difficulty", "MEDIUM");
|
||||
String configPath = "settings.recipe-materials." + difficulty;
|
||||
|
||||
ShapedRecipe recipe = new ShapedRecipe(new NamespacedKey(plugin, "revival_beacon"), new ItemStack(Material.BEACON));
|
||||
recipe.shape("CCC", "CSC", "BBB");
|
||||
|
||||
Material cornerMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".top_corners"));
|
||||
Material centerMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".center_row"));
|
||||
Material skullMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".skull"));
|
||||
Material bottomMaterial = Material.valueOf(plugin.getConfig().getString(configPath + ".bottom"));
|
||||
|
||||
recipe.setIngredient('C', cornerMaterial);
|
||||
recipe.setIngredient('S', skullMaterial);
|
||||
recipe.setIngredient('B', bottomMaterial);
|
||||
|
||||
Bukkit.addRecipe(recipe);
|
||||
}
|
||||
|
||||
public static ItemStack createRevivalBeacon() {
|
||||
ItemStack beacon = new ItemStack(Material.BEACON);
|
||||
ItemMeta meta = beacon.getItemMeta();
|
||||
meta.setDisplayName(MessageUtils.color("&c&lRevival Beacon"));
|
||||
meta.setLore(Arrays.asList(
|
||||
MessageUtils.color("&7Use this beacon to revive"),
|
||||
MessageUtils.color("&7a banned player!")
|
||||
));
|
||||
beacon.setItemMeta(meta);
|
||||
return beacon;
|
||||
}
|
||||
}
|
116
src/main/java/com/koopa/lifestealcore/utils/VersionChecker.java
Normal file
116
src/main/java/com/koopa/lifestealcore/utils/VersionChecker.java
Normal file
@ -0,0 +1,116 @@
|
||||
package com.koopa.lifestealcore.utils;
|
||||
|
||||
import com.koopa.lifestealcore.LifeStealCore;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
public class VersionChecker {
|
||||
private final LifeStealCore plugin;
|
||||
private static final String VERSION_URL = "https://raw.githubusercontent.com/KoopaCode/LifeSteal-Core/refs/heads/main/version/versioncheck";
|
||||
private static final String SPIGOT_URL_FILE = "https://raw.githubusercontent.com/KoopaCode/LifeSteal-Core/refs/heads/main/spigot/url";
|
||||
private static final String GITHUB_URL = "https://github.com/KoopaCode/LifeSteal-Core/releases";
|
||||
private String spigotUrl = null;
|
||||
|
||||
public VersionChecker(LifeStealCore plugin) {
|
||||
this.plugin = plugin;
|
||||
fetchSpigotUrl();
|
||||
}
|
||||
|
||||
private void fetchSpigotUrl() {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
try {
|
||||
URL url = new URL(SPIGOT_URL_FILE);
|
||||
java.net.URLConnection conn = url.openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.addRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
spigotUrl = reader.readLine().trim();
|
||||
reader.close();
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §cFailed to fetch Spigot URL: " + e.getMessage());
|
||||
spigotUrl = "https://www.spigotmc.org/resources/lifesteal-core.xxxxx/";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void checkVersion() {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
try {
|
||||
URL url = new URL(VERSION_URL);
|
||||
java.net.URLConnection conn = url.openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.addRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
conn.addRequestProperty("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
conn.addRequestProperty("Pragma", "no-cache");
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String latestVersion = reader.readLine().trim();
|
||||
reader.close();
|
||||
|
||||
String currentVersion = plugin.getDescription().getVersion();
|
||||
int comparison = compareVersions(currentVersion, latestVersion);
|
||||
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
if (comparison > 0) {
|
||||
// Running beta/development version (current > latest)
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §e§lYou are running a beta version!");
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §eCurrent version: §f" + currentVersion);
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §eLatest stable: §f" + latestVersion);
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §c⚠ Bugs may occur in this development build!");
|
||||
} else if (comparison < 0) {
|
||||
// Running outdated version (current < latest)
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §c§lA new version is available!");
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §cCurrent version: §f" + currentVersion);
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §cLatest version: §f" + latestVersion);
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §eDownload from:");
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §bSpigot: §f" + spigotUrl);
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §bGitHub: §f" + GITHUB_URL);
|
||||
} else {
|
||||
// Versions are equal - running latest stable
|
||||
plugin.getLogger().info("§8§l[§c§lLifeSteal§8§l] §a§lYou are running the latest stable version!");
|
||||
plugin.getLogger().info("§8§l[§c§lLifeSteal§8§l] §aCurrent version: §f" + currentVersion);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §cFailed to check for updates: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int compareVersions(String version1, String version2) {
|
||||
try {
|
||||
String[] v1Parts = version1.split("\\.");
|
||||
String[] v2Parts = version2.split("\\.");
|
||||
|
||||
// Convert to integers for proper comparison
|
||||
int major1 = Integer.parseInt(v1Parts[0]);
|
||||
int minor1 = v1Parts.length > 1 ? Integer.parseInt(v1Parts[1]) : 0;
|
||||
int patch1 = v1Parts.length > 2 ? Integer.parseInt(v1Parts[2]) : 0;
|
||||
|
||||
int major2 = Integer.parseInt(v2Parts[0]);
|
||||
int minor2 = v2Parts.length > 1 ? Integer.parseInt(v2Parts[1]) : 0;
|
||||
int patch2 = v2Parts.length > 2 ? Integer.parseInt(v2Parts[2]) : 0;
|
||||
|
||||
// Compare major version first
|
||||
if (major1 != major2) {
|
||||
return major1 - major2;
|
||||
}
|
||||
|
||||
// If major versions are equal, compare minor versions
|
||||
if (minor1 != minor2) {
|
||||
return minor1 - minor2;
|
||||
}
|
||||
|
||||
// If minor versions are equal, compare patch versions
|
||||
return patch1 - patch2;
|
||||
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().warning("§8§l[§c§lLifeSteal§8§l] §cError parsing version numbers!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.koopa.lifestealcore.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class VersionSupport {
|
||||
private static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
private static final int MAJOR_VERSION = Integer.parseInt(VERSION.split("_")[1]);
|
||||
|
||||
public static boolean isLegacy() {
|
||||
return MAJOR_VERSION < 13;
|
||||
}
|
||||
|
||||
public static boolean hasHexColors() {
|
||||
return MAJOR_VERSION >= 16;
|
||||
}
|
||||
|
||||
public static boolean hasOffhand() {
|
||||
return MAJOR_VERSION >= 9;
|
||||
}
|
||||
|
||||
public static boolean hasNewMaterials() {
|
||||
return MAJOR_VERSION >= 13;
|
||||
}
|
||||
|
||||
public static String getServerVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
public static int getMajorVersion() {
|
||||
return MAJOR_VERSION;
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return MAJOR_VERSION >= 13; // Plugin supports 1.13+
|
||||
}
|
||||
}
|
61
src/main/resources/config.yml
Normal file
61
src/main/resources/config.yml
Normal file
@ -0,0 +1,61 @@
|
||||
settings:
|
||||
default-hearts: 10
|
||||
min-hearts: 1
|
||||
max-hearts: 20
|
||||
heart-item-name: "&c❤ Heart"
|
||||
heart-item-lore:
|
||||
- "&7Right-click to consume this heart"
|
||||
- "&7and increase your max health"
|
||||
difficulty: "MEDIUM"
|
||||
recipe-materials:
|
||||
EASY:
|
||||
top_corners: "NETHER_STAR"
|
||||
center_row: "IRON_INGOT"
|
||||
skull: "SKELETON_SKULL"
|
||||
bottom: "OBSIDIAN"
|
||||
MEDIUM:
|
||||
top_corners: "GLASS"
|
||||
center_row: "DIAMOND"
|
||||
skull: "WITHER_SKELETON_SKULL"
|
||||
bottom: "OBSIDIAN"
|
||||
HARD:
|
||||
top_corners: "GLASS"
|
||||
center_row: "NETHERITE_INGOT"
|
||||
skull: "WITHER_SKELETON_SKULL"
|
||||
bottom: "CRYING_OBSIDIAN"
|
||||
CUSTOM:
|
||||
top_corners: "GLASS"
|
||||
center_row: "DIAMOND"
|
||||
skull: "WITHER_SKELETON_SKULL"
|
||||
bottom: "OBSIDIAN"
|
||||
messages:
|
||||
prefix: "&8[&cLifeSteal&8] "
|
||||
no-permission: "&cYou don't have permission to do this!"
|
||||
hearts-withdrawn: "&aYou have withdrawn &c%amount% &ahearts!"
|
||||
hearts-deposited: "&aYou have deposited &c%amount% &ahearts!"
|
||||
hearts-reset: "&aAll players' hearts have been reset to default!"
|
||||
hearts-reset-confirm: "&cAre you sure you want to reset all hearts? Type /lifesteal reset confirm"
|
||||
hearts-given: "&aGave &c%amount% &ahearts to &e%player%"
|
||||
not-enough-hearts: "&cYou don't have enough hearts to withdraw!"
|
||||
minimum-hearts-reached: "&cYou can't have less than %min% hearts!"
|
||||
maximum-hearts-reached: "&cYou can't have more than %max% hearts!"
|
||||
help:
|
||||
header: "&8&l&m-----&r &c&lLifeSteal Help &8&l&m-----"
|
||||
format: "&c/%command% &8- &7%description%"
|
||||
footer: "&8&l&m-------------------------"
|
||||
commands:
|
||||
- command: "lifesteal help"
|
||||
description: "Shows this help menu"
|
||||
permission: "lifesteal.use"
|
||||
- command: "lifesteal withdraw <amount>"
|
||||
description: "Withdraw hearts into physical items"
|
||||
permission: "lifesteal.withdraw"
|
||||
- command: "lifesteal deposit"
|
||||
description: "Deposit all heart items in your inventory"
|
||||
permission: "lifesteal.deposit"
|
||||
- command: "lifesteal reset"
|
||||
description: "Reset all players' hearts to default"
|
||||
permission: "lifesteal.admin.reset"
|
||||
- command: "lifesteal giveheart <amount>"
|
||||
description: "Give yourself heart items"
|
||||
permission: "lifesteal.admin.give"
|
2
src/main/resources/hearts.yml
Normal file
2
src/main/resources/hearts.yml
Normal file
@ -0,0 +1,2 @@
|
||||
# LifeStealCore hearts data storage
|
||||
# Do not edit this file manually!
|
36
src/main/resources/plugin.yml
Normal file
36
src/main/resources/plugin.yml
Normal file
@ -0,0 +1,36 @@
|
||||
name: LifeStealCore
|
||||
version: '1.0.0'
|
||||
main: com.koopa.lifestealcore.LifeStealCore
|
||||
api-version: '1.13'
|
||||
author: Koopa
|
||||
description: A LifeSteal plugin where players can steal hearts from others
|
||||
|
||||
commands:
|
||||
lifesteal:
|
||||
description: Main command for LifeSteal plugin
|
||||
usage: /<command> <help|withdraw|deposit|reset|giveheart|recipe|config>
|
||||
permission: lifesteal.use
|
||||
aliases: [ls]
|
||||
|
||||
permissions:
|
||||
lifesteal.use:
|
||||
description: Allows use of basic LifeSteal commands
|
||||
default: true
|
||||
lifesteal.withdraw:
|
||||
description: Allows withdrawing hearts
|
||||
default: true
|
||||
lifesteal.deposit:
|
||||
description: Allows depositing hearts
|
||||
default: true
|
||||
lifesteal.admin.config:
|
||||
description: Allows access to the configuration GUI
|
||||
default: op
|
||||
lifesteal.admin.reset:
|
||||
description: Allows resetting all players' hearts
|
||||
default: op
|
||||
lifesteal.admin.give:
|
||||
description: Allows giving heart items
|
||||
default: op
|
||||
lifesteal.admin.debug:
|
||||
description: Allows access to debug commands
|
||||
default: op
|
Loading…
x
Reference in New Issue
Block a user