diff --git a/src/main/java/me/sashegdev/blackknife/AwakeningManager.java b/src/main/java/me/sashegdev/blackknife/AwakeningManager.java new file mode 100644 index 0000000..6fa5bde --- /dev/null +++ b/src/main/java/me/sashegdev/blackknife/AwakeningManager.java @@ -0,0 +1,98 @@ +package me.sashegdev.blackknife; + +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.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import java.util.HashMap; +import java.util.Map; + +public class AwakeningManager implements Listener { + private final BlackKnifePlugin plugin; + private final MagicManager mgr; + private final Map chances = new HashMap<>(); + + public AwakeningManager(BlackKnifePlugin plugin, MagicManager mgr) { + this.plugin = plugin; this.mgr = mgr; + reloadChances(); + } + + public void reloadChances() { + chances.clear(); + var cfg = plugin.getConfig(); + chances.put("mob", cfg.getDouble("awakening.chances.mob", 0.05)); + chances.put("kill", cfg.getDouble("awakening.chances.kill", 0.08)); + chances.put("fall", cfg.getDouble("awakening.chances.fall", 0.03)); + chances.put("lava", cfg.getDouble("awakening.chances.lava", 0.04)); + chances.put("void", cfg.getDouble("awakening.chances.void", 0.10)); + chances.put("generic", cfg.getDouble("awakening.chances.generic", 0.01)); + } + + private boolean tryAwaken(Player p, String cause) { + if (mgr.hasAwakened(p.getUniqueId())) return false; + if (BlackKnifeItem.is(p.getInventory().getItemInMainHand()) || BlackKnifeItem.is(p.getInventory().getItemInOffHand())) return false; + for (var it : p.getInventory().getContents()) if (BlackKnifeItem.is(it)) return false; + double chance = chances.getOrDefault(cause, chances.getOrDefault("generic", 0.01)); + if (Math.random() >= chance) return false; + MagicProfile prof = mgr.awaken(p, cause); + p.getInventory().addItem(MagicItem.create(prof)); + p.sendTitle("§dПробуждение!", "§7Магия пробудилась: " + cause, 10, 60, 10); + p.getWorld().playSound(p.getLocation(), org.bukkit.Sound.BLOCK_BEACON_ACTIVATE, 1f, 1.2f); + p.sendMessage("§d[Пробуждение] §7Твоя магия пробудилась! Причина: " + cause); + plugin.getLogger().info("Awakened " + p.getName() + " via " + cause); + return true; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDamage(EntityDamageEvent e) { + if (!(e.getEntity() instanceof Player p)) return; + if (e.isCancelled()) return; + String cause = e.getCause().name().toLowerCase(); + if (cause.equals("fall")) { + int minFall = plugin.getConfig().getInt("awakening.fall_min", 15); + if (p.getFallDistance() >= minFall) tryAwaken(p, "fall"); + else tryAwaken(p, "generic"); + } else if (cause.equals("lava") || cause.equals("fire") || cause.equals("fire_tick")) tryAwaken(p, "lava"); + else if (cause.equals("void")) tryAwaken(p, "void"); + else tryAwaken(p, "generic"); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDamageByEntity(EntityDamageByEntityEvent e) { + if (e.getEntity() instanceof Player victim) { + if (e.getDamager() instanceof LivingEntity le && !(le instanceof Player)) tryAwaken(victim, "mob"); + } + if (e.getDamager() instanceof Player killer && e.getEntity() instanceof Player) { + tryAwaken(killer, "kill"); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onDeath(PlayerDeathEvent e) { + Player victim = e.getEntity(); + Player killer = victim.getKiller(); + if (killer != null && killer != victim) tryAwaken(killer, "kill"); + var last = victim.getLastDamageCause(); + if (last != null && last.getCause() != null) { + String cause = last.getCause().name().toLowerCase(); + if (last instanceof EntityDamageByEntityEvent ev && ev.getDamager() instanceof LivingEntity le && !(le instanceof Player)) tryAwaken(victim, "mob"); + else if (cause.equals("fall")) { + int minFall = plugin.getConfig().getInt("awakening.fall_min", 15); + if (victim.getFallDistance() >= minFall) tryAwaken(victim, "fall"); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onMove(PlayerMoveEvent e) { + Player p = e.getPlayer(); + if (e.getFrom().getY() - e.getTo().getY() > 3) { + if (p.getFallDistance() > 10) tryAwaken(p, "fall"); + } + } +} diff --git a/src/main/java/me/sashegdev/blackknife/BlackKnifeCommand.java b/src/main/java/me/sashegdev/blackknife/BlackKnifeCommand.java index ec6ede8..1eb59ca 100644 --- a/src/main/java/me/sashegdev/blackknife/BlackKnifeCommand.java +++ b/src/main/java/me/sashegdev/blackknife/BlackKnifeCommand.java @@ -28,6 +28,7 @@ public class BlackKnifeCommand implements CommandExecutor { if (args.length >= 1 && args[0].equalsIgnoreCase("reload")) { if (chatConfig != null) chatConfig.load(); plugin.reloadConfig(); + plugin.reloadLang(); sender.sendMessage(Component.text("Chat+config reloaded lang=" + plugin.getLang()).color(NamedTextColor.GREEN)); return true; } diff --git a/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java b/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java index 684ba90..2505183 100644 --- a/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java +++ b/src/main/java/me/sashegdev/blackknife/BlackKnifePlugin.java @@ -3,15 +3,18 @@ package me.sashegdev.blackknife; import org.bukkit.plugin.java.JavaPlugin; public class BlackKnifePlugin extends JavaPlugin { + private static BlackKnifePlugin instance; private TensionManager tension; private MagicManager magicManager; private MagicListener magicListener; private ChatConfig chatConfig; private ChatHandler chatHandler; + private AwakeningManager awakeningManager; private String lang = "ru"; @Override public void onEnable() { + instance = this; saveDefaultConfig(); lang = getConfig().getString("lang", "ru"); tension = new TensionManager(); @@ -19,6 +22,7 @@ public class BlackKnifePlugin extends JavaPlugin { magicListener = new MagicListener(this, magicManager); chatConfig = new ChatConfig(this); chatHandler = new ChatHandler(this, chatConfig); + awakeningManager = new AwakeningManager(this, magicManager); getServer().getPluginManager().registerEvents(tension, this); getServer().getPluginManager().registerEvents(new BlackKnifeListener(this), this); getServer().getPluginManager().registerEvents(new SwoonHandler(this), this); @@ -27,6 +31,7 @@ public class BlackKnifePlugin extends JavaPlugin { getServer().getPluginManager().registerEvents(new ParryHandler(this), this); getServer().getPluginManager().registerEvents(magicListener, this); getServer().getPluginManager().registerEvents(chatHandler, this); + getServer().getPluginManager().registerEvents(awakeningManager, this); getServer().getPluginManager().registerEvents(new KillMessageHandler(this), this); getCommand("blackknife").setExecutor(new BlackKnifeCommand(this, chatConfig, chatHandler)); getCommand("magic").setExecutor(new MagicCommand(magicManager, this)); @@ -34,10 +39,12 @@ public class BlackKnifePlugin extends JavaPlugin { getLogger().info("BlackKnife 1.0.0 enabled - Paper 1.21.1 lang=" + lang); } + public static BlackKnifePlugin getInstance() { return instance; } public TensionManager getTension() { return tension; } public MagicManager getMagicManager() { return magicManager; } public MagicListener getMagicListener() { return magicListener; } public String getLang() { return lang; } + public void reloadLang() { lang = getConfig().getString("lang", "ru"); if (awakeningManager != null) awakeningManager.reloadChances(); } @Override public void onDisable() { diff --git a/src/main/java/me/sashegdev/blackknife/MagicListener.java b/src/main/java/me/sashegdev/blackknife/MagicListener.java index bf8664e..d3ee66b 100644 --- a/src/main/java/me/sashegdev/blackknife/MagicListener.java +++ b/src/main/java/me/sashegdev/blackknife/MagicListener.java @@ -34,11 +34,75 @@ public class MagicListener implements Listener { @EventHandler public void onJoin(PlayerJoinEvent e) { Player p = e.getPlayer(); - if (BlackKnifeItem.is(p.getInventory().getItemInMainHand()) || BlackKnifeItem.is(p.getInventory().getItemInOffHand())) return; + if (hasAnyBlackKnife(p)) return; MagicProfile prof = mgr.getOrCreate(p); + if (!prof.awakened) return; boolean hasMagic = false; for (ItemStack it : p.getInventory().getContents()) if (MagicItem.is(it)) { hasMagic = true; break; } - if (!hasMagic) p.getInventory().addItem(MagicItem.create(prof)); + if (!hasMagic) { + p.getInventory().addItem(MagicItem.create(prof)); + p.sendMessage("§d[Магия] §7Твой Magic Orb вернулся!"); + } + } + + private boolean hasAnyBlackKnife(Player p) { + for (ItemStack it : p.getInventory().getContents()) if (BlackKnifeItem.is(it)) return true; + return BlackKnifeItem.is(p.getInventory().getItemInMainHand()) || BlackKnifeItem.is(p.getInventory().getItemInOffHand()); + } + + @EventHandler + public void onDrop(org.bukkit.event.player.PlayerDropItemEvent e) { + if (!MagicItem.is(e.getItemDrop().getItemStack())) return; + } + + @EventHandler + public void onPickup(org.bukkit.event.entity.EntityPickupItemEvent e) { + if (!(e.getEntity() instanceof Player picker)) return; + ItemStack item = e.getItem().getItemStack(); + if (!MagicItem.is(item)) return; + String ownerStr = item.getItemMeta().getPersistentDataContainer().get(MagicItem.OWNER, PersistentDataType.STRING); + if (ownerStr == null) return; + if (ownerStr.equals(picker.getUniqueId().toString())) return; + e.setCancelled(true); + Player owner = plugin.getServer().getPlayer(UUID.fromString(ownerStr)); + if (owner != null && owner.isOnline()) { + owner.getInventory().addItem(MagicItem.create(mgr.getOrCreate(owner))); + owner.sendMessage("§d[Магия] §7Твой Orb пытались подобрать, он вернулся!"); + picker.sendMessage("§cЧужой Magic Orb вернулся владельцу!"); + } else { + e.getItem().remove(); + picker.sendMessage("§cЧужой Magic Orb исчез (владелец оффлайн)!"); + } + } + + @EventHandler + public void onDespawn(org.bukkit.event.entity.ItemDespawnEvent e) { + ItemStack item = e.getEntity().getItemStack(); + if (!MagicItem.is(item)) return; + String ownerStr = item.getItemMeta().getPersistentDataContainer().get(MagicItem.OWNER, PersistentDataType.STRING); + if (ownerStr == null) return; + try { + UUID ownerId = UUID.fromString(ownerStr); + MagicProfile prof = mgr.get(ownerId); + if (prof != null && prof.awakened) { + Player owner = plugin.getServer().getPlayer(ownerId); + if (owner != null && owner.isOnline()) { + plugin.getServer().getScheduler().runTask(plugin, () -> owner.getInventory().addItem(MagicItem.create(prof))); + } + } + } catch (Exception ignored) {} + } + + @EventHandler + public void onInventoryClick(org.bukkit.event.inventory.InventoryClickEvent e) { + if (!(e.getWhoClicked() instanceof Player p)) return; + ItemStack item = e.getCurrentItem(); + if (!MagicItem.is(item)) return; + String ownerStr = item.getItemMeta().getPersistentDataContainer().get(MagicItem.OWNER, PersistentDataType.STRING); + if (ownerStr != null && !ownerStr.equals(p.getUniqueId().toString())) { + e.setCancelled(true); + p.sendMessage("§cЧужой Magic Orb нельзя трогать!"); + } } @EventHandler diff --git a/src/main/java/me/sashegdev/blackknife/MagicManager.java b/src/main/java/me/sashegdev/blackknife/MagicManager.java index 6066f66..a90fba9 100644 --- a/src/main/java/me/sashegdev/blackknife/MagicManager.java +++ b/src/main/java/me/sashegdev/blackknife/MagicManager.java @@ -38,23 +38,43 @@ public class MagicManager { p.rare = y.getStringList("pack.rare"); p.story = y.getStringList("pack.story"); p.rareRolled = y.getBoolean("flags.rareRolled", false); + p.awakened = y.getBoolean("flags.awakened", false); + p.awakeningCause = y.getString("flags.cause", null); + p.awakenedAt = y.getLong("flags.at", 0); map.put(uuid, p); } catch (Exception e) { plugin.getLogger().warning("Failed load magic " + f.getName() + ": " + e.getMessage()); } } } + public boolean hasAwakened(UUID uuid) { + MagicProfile p = map.get(uuid); + return p != null && p.awakened; + } + + public MagicProfile awaken(Player p, String cause) { + MagicProfile prof = map.get(p.getUniqueId()); + if (prof == null) prof = new MagicProfile(p.getName(), p.getUniqueId()); + prof.nick = p.getName(); + prof.awakened = true; + prof.awakeningCause = cause; + prof.awakenedAt = System.currentTimeMillis(); + if (!prof.rareRolled) { + prof.rareRolled = true; + if (Math.random() < 0.05) { + String[] pool = {"DETERMORE","FROSHE","PRAYER","SHIELDO"}; + String pick = pool[(int)(Math.random()*pool.length)]; + if (!prof.common.contains(pick)) prof.rare.add(pick); + } + } + map.put(p.getUniqueId(), prof); + save(prof); + return prof; + } + public MagicProfile getOrCreate(Player p) { MagicProfile prof = map.get(p.getUniqueId()); if (prof == null) { prof = new MagicProfile(p.getName(), p.getUniqueId()); - if (!prof.rareRolled) { - prof.rareRolled = true; - if (Math.random() < 0.05) { - String[] pool = {"DETERMORE","FROSHE","PRAYER","SHIELDO"}; - String pick = pool[(int)(Math.random()*pool.length)]; - if (!prof.common.contains(pick)) prof.rare.add(pick); - } - } map.put(p.getUniqueId(), prof); save(prof); } else if (!prof.nick.equals(p.getName())) { @@ -81,6 +101,9 @@ public class MagicManager { y.set("pack.story", prof.story); y.set("pack.selected", prof.selectedIdx); y.set("flags.rareRolled", prof.rareRolled); + y.set("flags.awakened", prof.awakened); + y.set("flags.cause", prof.awakeningCause); + y.set("flags.at", prof.awakenedAt); y.save(f); } catch (Exception e) { plugin.getLogger().warning("Failed save magic " + prof.uuid + ": " + e.getMessage()); } } diff --git a/src/main/java/me/sashegdev/blackknife/MagicProfile.java b/src/main/java/me/sashegdev/blackknife/MagicProfile.java index d35a603..7d6c70c 100644 --- a/src/main/java/me/sashegdev/blackknife/MagicProfile.java +++ b/src/main/java/me/sashegdev/blackknife/MagicProfile.java @@ -16,6 +16,9 @@ public class MagicProfile { public List rare = new ArrayList<>(); public List story = new ArrayList<>(); public boolean rareRolled; + public boolean awakened; + public String awakeningCause; + public long awakenedAt; public MagicProfile(String nick, UUID uuid) { this.nick = nick; this.uuid = uuid; this.firstSeen = System.currentTimeMillis(); diff --git a/src/main/java/me/sashegdev/blackknife/TensionManager.java b/src/main/java/me/sashegdev/blackknife/TensionManager.java index 9dd4ba6..ac40ef8 100644 --- a/src/main/java/me/sashegdev/blackknife/TensionManager.java +++ b/src/main/java/me/sashegdev/blackknife/TensionManager.java @@ -30,6 +30,7 @@ public class TensionManager implements Listener { } public void addTP(Player p, float amount, String reason) { + if (!hasMagic(p)) return; float cur = Math.min(250, getTP(p) + amount); tp.put(p.getUniqueId(), cur); lastCombat.put(p.getUniqueId(), System.currentTimeMillis()); @@ -38,7 +39,18 @@ public class TensionManager implements Listener { } public boolean isOwner(Player p) { - return BlackKnifeItem.is(p.getInventory().getItemInMainHand()) || BlackKnifeItem.is(p.getInventory().getItemInOffHand()); + return BlackKnifeItem.is(p.getInventory().getItemInMainHand()) || BlackKnifeItem.is(p.getInventory().getItemInOffHand()) || hasAnyBlackKnife(p); + } + + private boolean hasAnyBlackKnife(Player p) { + for (var it : p.getInventory().getContents()) if (BlackKnifeItem.is(it)) return true; + return false; + } + + public boolean hasMagic(Player p) { + if (hasAnyBlackKnife(p)) return true; + var mgr = BlackKnifePlugin.getInstance() != null ? BlackKnifePlugin.getInstance().getMagicManager() : null; + return mgr != null && mgr.hasAwakened(p.getUniqueId()); } private void updateBar(Player p, float tpVal) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 17b850f..4097bbe 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1 +1,12 @@ lang: ru +awakening: + enabled: true + tp_requires_magic: true + fall_min: 15 + chances: + mob: 0.05 + kill: 0.08 + fall: 0.03 + lava: 0.04 + void: 0.10 + generic: 0.01