init
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package dev.sillyangel.more_spear_enchantments;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CompatibilityCheck {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CompatibilityCheck.class);
|
||||
|
||||
private static Platform platform;
|
||||
private static boolean runsAsync = false;
|
||||
|
||||
public enum Platform {
|
||||
BUKKIT,
|
||||
SPIGOT,
|
||||
PAPER,
|
||||
FOLIA,
|
||||
PURPUR
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the detected platform, performing detection on first call
|
||||
*/
|
||||
public static Platform getPlatform() {
|
||||
if (platform == null) {
|
||||
platform = checkPlatform();
|
||||
LOGGER.info("Detected platform: {}", platform);
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
public static boolean isRunsAsync() {
|
||||
return runsAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which platform the plugin is running on by attempting to load
|
||||
* platform-specific classes. Order matters - checks from most specific to least specific.
|
||||
*/
|
||||
private static Platform checkPlatform() {
|
||||
// Check for Folia (Paper fork with regionized threading)
|
||||
if (classExists("io.papermc.paper.threadedregions.RegionizedServer")) {
|
||||
return Platform.FOLIA;
|
||||
}
|
||||
|
||||
// Check for Purpur (Paper fork with extra features)
|
||||
if (classExists("org.purpurmc.purpur.event.player.PlayerBookTooLargeEvent")) {
|
||||
return Platform.PURPUR;
|
||||
}
|
||||
|
||||
// Check for Paper (Spigot fork)
|
||||
if (classExists("io.papermc.paper.event.player.AbstractChatEvent")) {
|
||||
return Platform.PAPER;
|
||||
}
|
||||
|
||||
// Check for Spigot (Bukkit fork)
|
||||
if (classExists("org.spigotmc.CustomTimingsHandler")) {
|
||||
return Platform.SPIGOT;
|
||||
}
|
||||
|
||||
// Check for vanilla Bukkit
|
||||
if (classExists("org.bukkit.Bukkit")) {
|
||||
return Platform.BUKKIT;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unknown server platform - no recognized classes found!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to safely check if a class exists
|
||||
*/
|
||||
private static boolean classExists(String className) {
|
||||
try {
|
||||
Class. forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the plugin should continue loading based on platform compatibility.
|
||||
* @return true if compatible, false if the plugin should disable itself
|
||||
*/
|
||||
public static boolean isCompatible() {
|
||||
Platform currentPlatform = getPlatform();
|
||||
|
||||
switch (currentPlatform) {
|
||||
case BUKKIT:
|
||||
case SPIGOT:
|
||||
LOGGER. error("MoreSpearEnchantments has been loaded on an installation of {}!", currentPlatform);
|
||||
LOGGER.error("MoreSpearEnchantments does not support anything other than Paper and derivatives!");
|
||||
LOGGER.error("Spigot is considered legacy, and you should definitely consider upgrading!");
|
||||
LOGGER.error("For further information, see https://docs.papermc.io/paper/migration");
|
||||
LOGGER.error("MoreSpearEnchantments will shut down now...");
|
||||
return false;
|
||||
|
||||
case PAPER:
|
||||
case PURPUR:
|
||||
return true;
|
||||
|
||||
case FOLIA:
|
||||
LOGGER.info("MoreSpearEnchantments running in Folia-compatible mode, please report any issues!");
|
||||
runsAsync = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sillyangel.more_spear_enchantments;
|
||||
|
||||
import dev.sillyangel.more_spear_enchantments.listeners.EnchantmentListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit. event.Listener;
|
||||
import org.bukkit.plugin.java. JavaPlugin;
|
||||
import org.slf4j.Logger;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
public class MoreSpearEnchantments extends JavaPlugin implements Listener {
|
||||
public static final String PLUGIN_ID = "more_spear_enchantments";
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
private boolean shouldDisable = false;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Check platform compatibility
|
||||
if (!CompatibilityCheck.isCompatible()) {
|
||||
shouldDisable = true;
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Platform check passed! Loading plugin...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Safeguard: Don't enable if we flagged for disable
|
||||
if (shouldDisable) {
|
||||
LOGGER.warn("Plugin was marked for disable - skipping enable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Register listeners
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
Bukkit.getPluginManager().registerEvents(new EnchantmentListener(), this);
|
||||
|
||||
LOGGER.info("More Spear Enchantments enabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Safeguard: Don't run shutdown logic if we never fully enabled
|
||||
if (shouldDisable) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("More Spear Enchantments disabled!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sillyangel.more_spear_enchantments;
|
||||
|
||||
import dev.sillyangel.more_spear_enchantments.enchantment.SpearEnchantments;
|
||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
||||
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
|
||||
import io.papermc.paper.registry.event.RegistryEvents;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class SpearEnchantmentsBootstrap implements PluginBootstrap {
|
||||
|
||||
@Override
|
||||
public void bootstrap(@NotNull BootstrapContext context) {
|
||||
context.getLogger().info("MoreSpearEnchantments bootstrap starting...");
|
||||
LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
|
||||
|
||||
// Register enchantments during the registry compose event
|
||||
manager.registerEventHandler(RegistryEvents.ENCHANTMENT.compose().newHandler(event -> {
|
||||
context.getLogger().info("Registering custom enchantments...");
|
||||
SpearEnchantments.registerEnchantments(event.registry());
|
||||
}));
|
||||
|
||||
context.getLogger().info("MoreSpearEnchantments bootstrap complete!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package dev.sillyangel.more_spear_enchantments.enchantment;
|
||||
|
||||
import dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import io.papermc.paper.registry.TypedKey;
|
||||
import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
|
||||
import io.papermc.paper.registry.set.RegistryKeySet;
|
||||
import io.papermc.paper.registry.set.RegistrySet;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.EquipmentSlotGroup;
|
||||
import org.bukkit.inventory.ItemType;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class SpearEnchantments {
|
||||
|
||||
// Define enchantment keys
|
||||
|
||||
public static final TypedKey<Enchantment> VAMPIRIC = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "vampiric")
|
||||
);
|
||||
|
||||
public static final TypedKey<Enchantment> EXPLOSIVE = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "explosive")
|
||||
);
|
||||
|
||||
public static final TypedKey<Enchantment> LIGHTNING = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "lightning")
|
||||
);
|
||||
|
||||
public static final TypedKey<Enchantment> CRIPPLING = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "crippling")
|
||||
);
|
||||
|
||||
public static final TypedKey<Enchantment> POISON = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "poison")
|
||||
);
|
||||
|
||||
public static final TypedKey<Enchantment> WITHERING = TypedKey.create(
|
||||
RegistryKey.ENCHANTMENT,
|
||||
Key.key(MoreSpearEnchantments.PLUGIN_ID, "withering")
|
||||
);
|
||||
|
||||
public static void registerEnchantments(io.papermc.paper.registry.event.WritableRegistry<Enchantment, EnchantmentRegistryEntry.Builder> registry) {
|
||||
|
||||
// Create spear item key set with all spear types
|
||||
RegistryKeySet<ItemType> spearItems = RegistrySet.keySet(
|
||||
RegistryKey.ITEM,
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "wooden_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "stone_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "copper_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "iron_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "golden_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "diamond_spear")),
|
||||
TypedKey.create(RegistryKey.ITEM, Key.key("minecraft", "netherite_spear"))
|
||||
);
|
||||
|
||||
// Vampiric - Heals on hit
|
||||
registry.register(
|
||||
VAMPIRIC,
|
||||
builder -> builder
|
||||
.description(Component.text("Vampiric"))
|
||||
.maxLevel(3)
|
||||
.weight(2)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(10, 8))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(50, 8))
|
||||
.anvilCost(4)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
|
||||
// Explosive - Creates explosion on hit
|
||||
registry.register(
|
||||
EXPLOSIVE,
|
||||
builder -> builder
|
||||
.description(Component.text("Explosive"))
|
||||
.maxLevel(3)
|
||||
.weight(1)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(20, 10))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(70, 10))
|
||||
.anvilCost(8)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
|
||||
// Lightning - Strikes lightning on hit
|
||||
registry.register(
|
||||
LIGHTNING,
|
||||
builder -> builder
|
||||
.description(Component.text("Lightning"))
|
||||
.maxLevel(3)
|
||||
.weight(2)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(15, 9))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(65, 9))
|
||||
.anvilCost(4)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
|
||||
// Crippling - Applies slowness and weakness
|
||||
registry.register(
|
||||
CRIPPLING,
|
||||
builder -> builder
|
||||
.description(Component.text("Crippling"))
|
||||
.maxLevel(3)
|
||||
.weight(2)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(10, 8))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(50, 8))
|
||||
.anvilCost(4)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
|
||||
// Poison - Applies poison effect
|
||||
registry.register(
|
||||
POISON,
|
||||
builder -> builder
|
||||
.description(Component.text("Poison"))
|
||||
.maxLevel(3)
|
||||
.weight(2)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(10, 8))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(50, 8))
|
||||
.anvilCost(4)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
|
||||
// Withering - Applies wither effect
|
||||
registry.register(
|
||||
WITHERING,
|
||||
builder -> builder
|
||||
.description(Component.text("Withering"))
|
||||
.maxLevel(3)
|
||||
.weight(1)
|
||||
.minimumCost(EnchantmentRegistryEntry.EnchantmentCost.of(15, 9))
|
||||
.maximumCost(EnchantmentRegistryEntry.EnchantmentCost.of(65, 9))
|
||||
.anvilCost(6)
|
||||
.supportedItems(spearItems)
|
||||
.primaryItems(spearItems)
|
||||
.activeSlots(EquipmentSlotGroup.MAINHAND)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package dev.sillyangel.more_spear_enchantments.listeners;
|
||||
|
||||
import dev.sillyangel.more_spear_enchantments.enchantment.SpearEnchantments;
|
||||
import io.papermc.paper.registry.RegistryAccess;
|
||||
import io.papermc.paper.registry.RegistryKey;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
public class EnchantmentListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onEntityDamage(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(event.getEntity() instanceof LivingEntity target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack weapon = player.getInventory().getItemInMainHand();
|
||||
if (weapon.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get enchantments from registry
|
||||
var registry = RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT);
|
||||
|
||||
// Vampiric enchantment
|
||||
Enchantment vampiric = registry.get(SpearEnchantments.VAMPIRIC);
|
||||
if (vampiric != null) {
|
||||
int level = weapon.getEnchantmentLevel(vampiric);
|
||||
if (level > 0) {
|
||||
handleVampiric(player, event.getFinalDamage(), level);
|
||||
}
|
||||
}
|
||||
|
||||
// Explosive enchantment
|
||||
Enchantment explosive = registry.get(SpearEnchantments.EXPLOSIVE);
|
||||
if (explosive != null) {
|
||||
int level = weapon.getEnchantmentLevel(explosive);
|
||||
if (level > 0) {
|
||||
handleExplosive(target.getLocation(), level);
|
||||
}
|
||||
}
|
||||
|
||||
// Lightning enchantment
|
||||
Enchantment lightning = registry.get(SpearEnchantments.LIGHTNING);
|
||||
if (lightning != null) {
|
||||
int level = weapon.getEnchantmentLevel(lightning);
|
||||
if (level > 0) {
|
||||
handleLightning(target, level);
|
||||
}
|
||||
}
|
||||
|
||||
// Crippling enchantment
|
||||
Enchantment crippling = registry.get(SpearEnchantments.CRIPPLING);
|
||||
if (crippling != null) {
|
||||
int level = weapon.getEnchantmentLevel(crippling);
|
||||
if (level > 0) {
|
||||
handleCrippling(target, level);
|
||||
}
|
||||
}
|
||||
|
||||
// Poison enchantment
|
||||
Enchantment poison = registry.get(SpearEnchantments.POISON);
|
||||
if (poison != null) {
|
||||
int level = weapon.getEnchantmentLevel(poison);
|
||||
if (level > 0) {
|
||||
handlePoison(target, level);
|
||||
}
|
||||
}
|
||||
|
||||
// Withering enchantment
|
||||
Enchantment withering = registry.get(SpearEnchantments.WITHERING);
|
||||
if (withering != null) {
|
||||
int level = weapon.getEnchantmentLevel(withering);
|
||||
if (level > 0) {
|
||||
handleWithering(target, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVampiric(Player player, double damage, int level) {
|
||||
// Heal based on damage dealt and level
|
||||
double healAmount = damage * (0.1 * level); // 10%, 20%, 30% of damage at levels 1, 2, 3
|
||||
AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH);
|
||||
if (maxHealthAttr == null) return;
|
||||
double maxHealth = maxHealthAttr.getValue();
|
||||
double newHealth = Math.min(player.getHealth() + healAmount, maxHealth);
|
||||
player.setHealth(newHealth);
|
||||
}
|
||||
|
||||
private void handleExplosive(Location location, int level) {
|
||||
// Higher levels = higher chance and bigger explosion
|
||||
double chance = 0.1 * level; // 10%, 20%, 30% chance at levels 1, 2, 3
|
||||
if (Math.random() < chance) {
|
||||
float power = 1.0f + (0.5f * level); // 1.5, 2.0, 2.5 power at levels 1, 2, 3
|
||||
location.getWorld().createExplosion(location, power, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLightning(LivingEntity target, int level) {
|
||||
// Strikes lightning based on level
|
||||
for (int i = 0; i < level; i++) {
|
||||
target.getWorld().strikeLightning(target.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCrippling(LivingEntity target, int level) {
|
||||
// Apply slowness and weakness
|
||||
int duration = level * 50; // 2.5s, 5s, 7.5s at levels 1, 2, 3
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.SLOWNESS, duration, level - 1, false, true));
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS, duration, level - 1, false, true));
|
||||
}
|
||||
|
||||
private void handlePoison(LivingEntity target, int level) {
|
||||
// Apply poison effect
|
||||
int duration = level * 50; // 2.5s, 5s, 7.5s at levels 1, 2, 3
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.POISON, duration, level - 1, false, true));
|
||||
}
|
||||
|
||||
private void handleWithering(LivingEntity target, int level) {
|
||||
// Apply wither effect
|
||||
int duration = level * 50; // 2s, 4s, 6s at levels 1, 2, 3
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, duration, level - 1, false, true));
|
||||
}
|
||||
}
|
||||
|
||||
9
src/main/resources/paper-plugin.yml
Normal file
9
src/main/resources/paper-plugin.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
name: MoreSpearEnchantments
|
||||
version: 1.1.0
|
||||
main: dev.sillyangel.more_spear_enchantments.MoreSpearEnchantments
|
||||
bootstrapper: dev.sillyangel.more_spear_enchantments.SpearEnchantmentsBootstrap
|
||||
description: more enchantments for the newly added spear from the Mounts of Mayhem update
|
||||
author: sillyangel
|
||||
website: https://modrinth.com/mod/more-spear-enchantments
|
||||
api-version: '1.21.11'
|
||||
|
||||
Reference in New Issue
Block a user