完善并添加README.md
This commit is contained in:
@@ -16,6 +16,7 @@ import com.yaohun.petsystem.manage.PetManager;
|
||||
import com.yaohun.petsystem.manage.PlayerManager;
|
||||
import com.yaohun.petsystem.model.PetNbt;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import com.yaohun.petsystem.util.InventoryUtil;
|
||||
import com.yaohun.petsystem.util.PetUtil;
|
||||
import de.tr7zw.nbtapi.NBTItem;
|
||||
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||
@@ -65,7 +66,9 @@ public class PetMain extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getPlayerManager().closeSaveAllData();
|
||||
if (getPlayerManager() != null) {
|
||||
getPlayerManager().closeSaveAllData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,6 +206,10 @@ public class PetMain extends JavaPlugin {
|
||||
return true;
|
||||
}
|
||||
PetNbt petNbt = PetExpAPI.addExp(playerName, stack, exp);
|
||||
if (petNbt == null) {
|
||||
sender.sendMessage(prefix + "执行失败,未找到宠物配置.");
|
||||
return true;
|
||||
}
|
||||
ItemStack petStack = PetUtil.refreshPetStackData(petNbt);
|
||||
player.getInventory().setItemInMainHand(petNbt.saveIoItem(petStack));
|
||||
sender.sendMessage(prefix + "给予 §6手持灵宠 §a经验: §d+" + exp);
|
||||
@@ -234,7 +241,7 @@ public class PetMain extends JavaPlugin {
|
||||
}
|
||||
PetNbt petNbt = new PetNbt(petData);
|
||||
ItemStack petStack = PetUtil.getPetStackDefault(petNbt);
|
||||
player.getInventory().addItem(petNbt.saveIoItem(petStack));
|
||||
InventoryUtil.giveOrDrop(player, petNbt.saveIoItem(petStack));
|
||||
DemonAPI.sendMessage(sender, "玩家: §e" + playerName + " §a宠物: §6" + petKey + " §r[背包]");
|
||||
return true;
|
||||
}
|
||||
@@ -262,4 +269,4 @@ public class PetMain extends JavaPlugin {
|
||||
return playerManager;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,49 +29,24 @@ public class PetExpAPI {
|
||||
return;
|
||||
}
|
||||
int petLevel = petNbt.level;
|
||||
if (petLevel >= petData.getMaxLevel()) {
|
||||
int levelCap = getLevelCap(petData, petNbt.evolution);
|
||||
if (petLevel >= levelCap) {
|
||||
return;
|
||||
}
|
||||
// 进化阶段判断
|
||||
int evolution = petNbt.evolution;
|
||||
if (evolution == 1) {
|
||||
if (petLevel >= 20) {
|
||||
return;
|
||||
}
|
||||
} else if (evolution == 2) {
|
||||
if (petLevel >= 40) {
|
||||
return;
|
||||
}
|
||||
} else if (evolution == 3) {
|
||||
if (petLevel >= 60) {
|
||||
return;
|
||||
}
|
||||
} else if (evolution == 4) {
|
||||
if (petLevel >= 70) {
|
||||
return;
|
||||
}
|
||||
} else if (evolution == 5) {
|
||||
if (petLevel >= 75) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int needExp = LevelExpManager.getNeedExpValue(petLevel);
|
||||
petNbt.setTotalExp(petNbt.totalExp + addExp);
|
||||
|
||||
int nowExp = petNbt.exp;
|
||||
addExp = nowExp + addExp;
|
||||
while (addExp >= needExp) {
|
||||
if (petLevel < 0) {
|
||||
break;
|
||||
}
|
||||
while (needExp > 0 && petLevel < levelCap && addExp >= needExp) {
|
||||
addExp -= needExp;
|
||||
petLevel++;
|
||||
needExp = LevelExpManager.getNeedExpValue(petLevel);
|
||||
bcmupLevelEvant(playerName, petLevel);
|
||||
playerData.refreshPetStack();
|
||||
}
|
||||
petNbt.setExp(addExp);
|
||||
petNbt.setLevel(petLevel);
|
||||
playerData.refreshPetStack();
|
||||
playerData.savePlayerData();
|
||||
}
|
||||
|
||||
@@ -86,7 +61,8 @@ public class PetExpAPI {
|
||||
PetNbt petNbt = new PetNbt();
|
||||
petNbt.loadNbtData(nbtItem);
|
||||
int petLevel = petNbt.level;
|
||||
if (petLevel >= petData.getMaxLevel()) {
|
||||
int levelCap = getLevelCap(petData, petNbt.evolution);
|
||||
if (petLevel >= levelCap) {
|
||||
return petNbt;
|
||||
}
|
||||
int needExp = LevelExpManager.getNeedExpValue(petLevel);
|
||||
@@ -94,10 +70,7 @@ public class PetExpAPI {
|
||||
|
||||
int nowExp = petNbt.exp;
|
||||
addExp = nowExp + addExp;
|
||||
while (addExp >= needExp) {
|
||||
if (petLevel < 0) {
|
||||
break;
|
||||
}
|
||||
while (needExp > 0 && petLevel < levelCap && addExp >= needExp) {
|
||||
addExp -= needExp;
|
||||
petLevel++;
|
||||
needExp = LevelExpManager.getNeedExpValue(petLevel);
|
||||
@@ -108,6 +81,22 @@ public class PetExpAPI {
|
||||
return petNbt;
|
||||
}
|
||||
|
||||
private static int getLevelCap(PetData petData, int evolution) {
|
||||
int maxLevel = petData.getMaxLevel();
|
||||
int evolutionLimit = switch (evolution) {
|
||||
case 1 -> 20;
|
||||
case 2 -> 40;
|
||||
case 3 -> 60;
|
||||
case 4 -> 70;
|
||||
case 5 -> 75;
|
||||
default -> maxLevel;
|
||||
};
|
||||
if (maxLevel <= 0) {
|
||||
return evolutionLimit;
|
||||
}
|
||||
return Math.min(maxLevel, evolutionLimit);
|
||||
}
|
||||
|
||||
public static void bcmupLevelEvant(String playerName, int level) {
|
||||
boolean butt = false;
|
||||
if (level == 10 || level == 20 || level == 30 || level == 40 || level == 50 ||
|
||||
@@ -119,4 +108,4 @@ public class PetExpAPI {
|
||||
// Bukkit.broadcastMessage("§f[§c§l公告§f] §a玩家§e"+playName+"§a本月器师手礼达到了 §7[§e§lLv."+level+"§7]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,14 +44,21 @@ public class Config {
|
||||
}
|
||||
|
||||
private static void loadQualityShowMap(FileConfiguration config) {
|
||||
qualityShowMap.clear();
|
||||
qualityShowMap.put(0, "§f普通");
|
||||
ConfigurationSection section = config.getConfigurationSection("QualityShow");
|
||||
if (section == null) {
|
||||
Bukkit.getConsoleSender().sendMessage("- 资质稀有度: §f" + qualityShowMap.size() + "个");
|
||||
return;
|
||||
}
|
||||
for (String levelKey : section.getKeys(false)) {
|
||||
int level = Integer.parseInt(levelKey);
|
||||
String show = section.getString(levelKey).replace("&", "§");
|
||||
qualityShowMap.put(level, show);
|
||||
try {
|
||||
int level = Integer.parseInt(levelKey);
|
||||
String show = section.getString(levelKey, "§f普通").replace("&", "§");
|
||||
qualityShowMap.put(level, show);
|
||||
} catch (NumberFormatException e) {
|
||||
Bukkit.getConsoleSender().sendMessage("§c[宠物系统] 资质显示配置无效: " + levelKey);
|
||||
}
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("- 资质稀有度: §f" + qualityShowMap.size() + "个");
|
||||
}
|
||||
@@ -62,8 +69,8 @@ public class Config {
|
||||
try {
|
||||
material = Material.valueOf(stackType.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Bukkit.getConsoleSender().sendMessage("- 宠物模板载入: §c失败");
|
||||
return;
|
||||
material = Material.DIAMOND;
|
||||
Bukkit.getConsoleSender().sendMessage("- 宠物模板载入: §c材质无效,已使用默认材质");
|
||||
}
|
||||
String stackName = config.getString("Pet_Stack_Template.name", "§f宠物");
|
||||
List<String> stringList = config.getStringList("Pet_Stack_Template.lore");
|
||||
@@ -80,6 +87,9 @@ public class Config {
|
||||
}
|
||||
|
||||
public static ItemStack getPetStackTemplate() {
|
||||
if (petStackTemplate == null) {
|
||||
petStackTemplate = new ItemStack(Material.DIAMOND);
|
||||
}
|
||||
return petStackTemplate.clone();
|
||||
}
|
||||
|
||||
@@ -119,7 +129,7 @@ public class Config {
|
||||
|
||||
public static String getQualityShow(int value) {
|
||||
Map.Entry<Integer, String> entry = qualityShowMap.floorEntry(value);
|
||||
return entry != null ? entry.getValue() : qualityShowMap.get(0);
|
||||
return entry != null ? entry.getValue() : "§f普通";
|
||||
}
|
||||
|
||||
public static String getHealthChar(int percent) {
|
||||
@@ -138,4 +148,4 @@ public class Config {
|
||||
return "§f<image:default:level_tag_" + level + ">";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.yaohun.petsystem.config.Config;
|
||||
import com.yaohun.petsystem.data.PlayerData;
|
||||
import com.yaohun.petsystem.gui.holder.CarryGuiHolder;
|
||||
import com.yaohun.petsystem.manage.PlayerManager;
|
||||
import com.yaohun.petsystem.util.InventoryUtil;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import de.tr7zw.nbtapi.NBTItem;
|
||||
import me.Demon.DemonPlugin.DemonAPI;
|
||||
@@ -54,7 +55,7 @@ public class CarryGui implements Listener {
|
||||
playerManager.removePetCall(playerName);
|
||||
playerData.refreshPetStack();
|
||||
ItemStack petStack = playerData.getPetStack();
|
||||
player.getInventory().addItem(petStack);
|
||||
InventoryUtil.giveOrDrop(player, petStack);
|
||||
playerData.setPetStack(DemonAPI.getErrItems());
|
||||
playerData.savePlayerData();
|
||||
inv.setItem(PET_SLOT, Config.getItemStack("carry_gui"));
|
||||
@@ -78,7 +79,7 @@ public class CarryGui implements Listener {
|
||||
playerManager.removePetCall(playerName);
|
||||
playerData.refreshPetStack();
|
||||
ItemStack petStack = playerData.getPetStack();
|
||||
player.getInventory().addItem(petStack);
|
||||
InventoryUtil.giveOrDrop(player, petStack);
|
||||
playerData.setPetStack(DemonAPI.getErrItems());
|
||||
playerData.savePlayerData();
|
||||
MessageUtil.sendMessageKey(player, "pet_stack_carry_takeOut", Sound.ENTITY_PLAYER_LEVELUP);
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.yaohun.petsystem.gui.holder.FeedingGuiHolder;
|
||||
import com.yaohun.petsystem.manage.LevelExpManager;
|
||||
import com.yaohun.petsystem.manage.PlayerManager;
|
||||
import com.yaohun.petsystem.model.PetNbt;
|
||||
import com.yaohun.petsystem.util.InventoryUtil;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import com.yaohun.petsystem.util.PetUtil;
|
||||
import de.tr7zw.nbtapi.NBTItem;
|
||||
@@ -96,7 +97,7 @@ public class FeedingGui implements Listener {
|
||||
// 判断槽位内是否已存在物品
|
||||
ItemStack foodStack = getFooedStack(inv);
|
||||
if (foodStack != null) {
|
||||
player.getInventory().addItem(foodStack);
|
||||
InventoryUtil.giveOrDrop(player, foodStack);
|
||||
}
|
||||
e.setCurrentItem(null);
|
||||
inv.setItem(FOOD_SLOT, clickStack);
|
||||
@@ -110,7 +111,7 @@ public class FeedingGui implements Listener {
|
||||
// 判断槽位内是否已存在物品
|
||||
ItemStack foodStack = getFooedStack(inv);
|
||||
if (foodStack != null) {
|
||||
player.getInventory().addItem(foodStack);
|
||||
InventoryUtil.giveOrDrop(player, foodStack);
|
||||
inv.setItem(FOOD_SLOT, DemonAPI.getPaperAirItems());
|
||||
}
|
||||
player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 1, 1);
|
||||
@@ -199,8 +200,8 @@ public class FeedingGui implements Listener {
|
||||
ItemStack stack = getFooedStack(inv);
|
||||
if (stack != null) {
|
||||
inv.setItem(FOOD_SLOT, DemonAPI.getPaperAirItems());
|
||||
player.getInventory().addItem(stack);
|
||||
InventoryUtil.giveOrDrop(player, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.yaohun.petsystem.gui.holder.MainGuiHolder;
|
||||
import com.yaohun.petsystem.listener.RePetNameListener;
|
||||
import com.yaohun.petsystem.manage.PlayerManager;
|
||||
import com.yaohun.petsystem.model.PetNbt;
|
||||
import com.yaohun.petsystem.util.InventoryUtil;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import com.yaohun.petsystem.util.PetUtil;
|
||||
import me.Demon.DemonPlugin.DemonAPI;
|
||||
@@ -150,7 +151,7 @@ public class MainGui implements Listener {
|
||||
playerManager.removePetCall(playerName);
|
||||
playerData.refreshPetStack();
|
||||
ItemStack petStack = playerData.getPetStack();
|
||||
player.getInventory().addItem(petStack);
|
||||
InventoryUtil.giveOrDrop(player, petStack);
|
||||
playerData.setPetStack(DemonAPI.getErrItems());
|
||||
playerData.savePlayerData();
|
||||
player.closeInventory();
|
||||
@@ -182,4 +183,4 @@ public class MainGui implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ public class PlayerListener implements Listener {
|
||||
if (petUUID == null) {
|
||||
return;
|
||||
}
|
||||
if (petUUID.equals(e.getEntity().getUniqueId())) {
|
||||
e.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
Entity entity = Bukkit.getEntity(petUUID);
|
||||
if (entity instanceof Wolf wolf) {
|
||||
wolf.setTarget(target);
|
||||
@@ -74,6 +78,6 @@ public class PlayerListener implements Listener {
|
||||
Player player = e.getPlayer();
|
||||
String playerName = player.getName();
|
||||
PlayerManager playerManager = PetMain.getPlayerManager();
|
||||
playerManager.removePetCall(playerName);
|
||||
playerManager.closeSaveData(playerName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,38 +5,39 @@ import com.yaohun.petsystem.config.Config;
|
||||
import com.yaohun.petsystem.data.PlayerData;
|
||||
import com.yaohun.petsystem.manage.PlayerManager;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class RePetNameListener implements Listener {
|
||||
|
||||
private static List<UUID> reNameList = new ArrayList<>();
|
||||
private static final Set<UUID> reNameList = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
public static void addReNameUUID(UUID uuid) {
|
||||
if (!reNameList.contains(uuid)) {
|
||||
reNameList.add(uuid);
|
||||
}
|
||||
reNameList.add(uuid);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChat(AsyncPlayerChatEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
UUID uuid = player.getUniqueId();
|
||||
if (reNameList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!reNameList.contains(uuid)) {
|
||||
if (!reNameList.remove(uuid)) {
|
||||
return;
|
||||
}
|
||||
e.setCancelled(true);
|
||||
reNameList.remove(uuid);
|
||||
String reName = e.getMessage();
|
||||
Bukkit.getScheduler().runTask(PetMain.inst(), () -> handleRename(player, reName));
|
||||
}
|
||||
|
||||
private void handleRename(Player player, String reName) {
|
||||
String playerName = player.getName();
|
||||
PlayerManager playerManager = PetMain.getPlayerManager();
|
||||
PlayerData playerData = playerManager.getPlayerData(playerName);
|
||||
@@ -44,7 +45,6 @@ public class RePetNameListener implements Listener {
|
||||
MessageUtil.sendMessageKey(player, "pet_rename_no_pets", Sound.ENTITY_VILLAGER_NO);
|
||||
return;
|
||||
}
|
||||
String reName = e.getMessage();
|
||||
if (reName.isEmpty()) {
|
||||
MessageUtil.sendMessageKey(player, "pet_rename_empty", Sound.ENTITY_VILLAGER_NO);
|
||||
return;
|
||||
@@ -59,4 +59,4 @@ public class RePetNameListener implements Listener {
|
||||
String message = Config.getLanguage("pet_rename_success");
|
||||
MessageUtil.sendMessage(player, message.replace("{petName}", newName), Sound.ENTITY_PLAYER_LEVELUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.yaohun.petsystem.manage;
|
||||
|
||||
import com.yaohun.petsystem.PetMain;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
@@ -13,17 +14,43 @@ public class LevelExpManager {
|
||||
private static HashMap<Integer, Integer> needExpMap = new HashMap<>();
|
||||
|
||||
public static void reloadLevelManager(PetMain plugin) {
|
||||
needExpMap.clear();
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection("NeedExpSettings");
|
||||
if (section != null) {
|
||||
loadNeedExpSection(section);
|
||||
} else {
|
||||
loadLegacyNeedExpFile(plugin);
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("§7- 等级经验配置: §f" + needExpMap.size() + "条");
|
||||
}
|
||||
|
||||
private static void loadNeedExpSection(ConfigurationSection section) {
|
||||
for (String levelKey : section.getKeys(false)) {
|
||||
try {
|
||||
int level = Integer.parseInt(levelKey);
|
||||
int needExp = section.getInt(levelKey);
|
||||
needExpMap.put(level, needExp);
|
||||
} catch (NumberFormatException e) {
|
||||
Bukkit.getConsoleSender().sendMessage("§c[宠物系统] 等级经验配置无效: " + levelKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadLegacyNeedExpFile(PetMain plugin) {
|
||||
File file = new File(plugin.getDataFolder() + "/Settings", "needExp.yml");
|
||||
if (file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||
for (String levelKey : config.getKeys(false)) {
|
||||
int level = Integer.parseInt(levelKey);
|
||||
int needExp = config.getInt(levelKey);
|
||||
needExpMap.put(level, needExp);
|
||||
try {
|
||||
int level = Integer.parseInt(levelKey);
|
||||
int needExp = config.getInt(levelKey);
|
||||
needExpMap.put(level, needExp);
|
||||
} catch (NumberFormatException e) {
|
||||
Bukkit.getConsoleSender().sendMessage("§c[宠物系统] 旧等级经验配置无效: " + levelKey);
|
||||
}
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("§7- 等级经验配置: §f" + needExpMap.size() + "条");
|
||||
}
|
||||
|
||||
public static int getNeedExpValue(int level) {
|
||||
@@ -32,4 +59,4 @@ public class LevelExpManager {
|
||||
}
|
||||
return 1000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.yaohun.petsystem.data.PetData;
|
||||
import com.yaohun.petsystem.data.PetSQL;
|
||||
import com.yaohun.petsystem.data.PlayerData;
|
||||
import com.yaohun.petsystem.event.PetCallEvent;
|
||||
import com.yaohun.petsystem.util.InventoryUtil;
|
||||
import com.yaohun.petsystem.util.MessageUtil;
|
||||
import com.yaohun.petsystem.util.model.BetterModelUtil;
|
||||
import com.yaohun.petsystem.util.wolf.CustomWolf;
|
||||
@@ -43,10 +44,10 @@ public class PlayerManager {
|
||||
}
|
||||
|
||||
public void closeSaveData(String playerName) {
|
||||
PlayerData playerData = getPlayerData(playerName);
|
||||
playerData.savePlayerData();
|
||||
playerDataMap.remove(playerName);
|
||||
|
||||
PlayerData playerData = playerDataMap.remove(playerName);
|
||||
if (playerData != null) {
|
||||
playerData.savePlayerData();
|
||||
}
|
||||
removePetCall(playerName);
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ public class PlayerManager {
|
||||
if (!nbtItem.hasKey("petKey")) {
|
||||
Bukkit.getConsoleSender().sendMessage("[日志 - 宠物] 未检测到宠物petKey的Nbt标识.");
|
||||
}
|
||||
player.getInventory().addItem(petStack);
|
||||
InventoryUtil.giveOrDrop(player, petStack);
|
||||
playerData.setPetStack(DemonAPI.getErrItems());
|
||||
playerData.savePlayerData();
|
||||
MessageUtil.sendMessageKey(player, "pet_stack_carry_takeOut", Sound.ENTITY_PLAYER_LEVELUP);
|
||||
|
||||
24
src/main/java/com/yaohun/petsystem/util/InventoryUtil.java
Normal file
24
src/main/java/com/yaohun/petsystem/util/InventoryUtil.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.yaohun.petsystem.util;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class InventoryUtil {
|
||||
|
||||
public static void giveOrDrop(Player player, ItemStack itemStack) {
|
||||
if (player == null || itemStack == null) {
|
||||
return;
|
||||
}
|
||||
HashMap<Integer, ItemStack> leftoverMap = player.getInventory().addItem(itemStack);
|
||||
if (leftoverMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (ItemStack leftover : leftoverMap.values()) {
|
||||
player.getWorld().dropItemNaturally(player.getLocation(), leftover);
|
||||
}
|
||||
MessageUtil.sendMessage(player, "§e背包空间不足,剩余物品已掉落在当前位置。", Sound.ENTITY_ITEM_PICKUP);
|
||||
}
|
||||
}
|
||||
@@ -1,130 +1,110 @@
|
||||
package com.yaohun.petsystem.util.wolf;
|
||||
|
||||
import com.yaohun.petsystem.PetMain;
|
||||
import com.yaohun.petsystem.model.PetNbt;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.animal.wolf.Wolf;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 自定义的狼实体类,用于实现“跟随玩家”的宠物功能。
|
||||
* 继承原版 NMS Wolf 实体,通过 tick() 方法控制移动与传送。
|
||||
*/
|
||||
public class CustomWolf extends Wolf {
|
||||
public class CustomWolf {
|
||||
|
||||
private static final double STOP_DISTANCE_SQ = 9.0D;
|
||||
private static final double TELEPORT_DISTANCE_SQ = 144.0D;
|
||||
private static final double LOOK_DISTANCE_SQ = 256.0D;
|
||||
private static final double FOLLOW_SPEED = 1.2D;
|
||||
private static final double DEFAULT_MOVEMENT_SPEED = 0.4D;
|
||||
private static final int PATH_RECALC_TICKS = 10;
|
||||
private static final long FOLLOW_INTERVAL_TICKS = 10L;
|
||||
|
||||
private final UUID ownerUuid;
|
||||
private final Wolf wolf;
|
||||
|
||||
private int timeToRecalcPath = 0;
|
||||
|
||||
/**
|
||||
* 构造方法:初始化宠物实体
|
||||
*
|
||||
* @param world NMS 世界对象
|
||||
* @param owner 宠物主人(Bukkit Player)
|
||||
*/
|
||||
public CustomWolf(Level world, Player owner) {
|
||||
super(EntityType.WOLF, world);
|
||||
this.ownerUuid = owner.getUniqueId();
|
||||
private CustomWolf(UUID ownerUuid, Wolf wolf) {
|
||||
this.ownerUuid = ownerUuid;
|
||||
this.wolf = wolf;
|
||||
startFollowTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每 tick 执行的逻辑,控制宠物的移动与状态
|
||||
*/
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
public Wolf getBukkitEntity() {
|
||||
return wolf;
|
||||
}
|
||||
|
||||
Player owner = Bukkit.getPlayer(ownerUuid);
|
||||
if (owner == null || !owner.isOnline()) {
|
||||
this.discard();
|
||||
return;
|
||||
}
|
||||
if (owner.isDead()) {
|
||||
this.getNavigation().stop();
|
||||
return;
|
||||
}
|
||||
if (!owner.getWorld().equals(this.getBukkitEntity().getWorld())) {
|
||||
this.getNavigation().stop();
|
||||
teleportToOwnerLocation(owner);
|
||||
return;
|
||||
}
|
||||
public LivingEntity getBukkitLivingEntity() {
|
||||
return wolf;
|
||||
}
|
||||
|
||||
net.minecraft.world.entity.player.Player nmsOwner = ((CraftPlayer) owner).getHandle();
|
||||
public UUID getUUID() {
|
||||
return wolf.getUniqueId();
|
||||
}
|
||||
|
||||
double distanceSq = this.distanceToSqr(nmsOwner);
|
||||
public boolean isRemoved() {
|
||||
return !wolf.isValid();
|
||||
}
|
||||
|
||||
if (distanceSq < STOP_DISTANCE_SQ) {
|
||||
this.getNavigation().stop();
|
||||
return;
|
||||
}
|
||||
public static CustomWolf spawnCustomWolf(Player owner, PetNbt petNbt) {
|
||||
Wolf wolf = owner.getWorld().spawn(owner.getLocation(), Wolf.class, entity -> {
|
||||
entity.setSilent(true);
|
||||
entity.setTamed(true);
|
||||
entity.setOwner(owner);
|
||||
entity.setSitting(false);
|
||||
entity.setRemoveWhenFarAway(false);
|
||||
|
||||
boolean shouldTeleport = distanceSq > TELEPORT_DISTANCE_SQ;
|
||||
double maxHealth = Math.max(1.0D, petNbt.maxHealth);
|
||||
double health = Math.max(1.0D, Math.min(petNbt.health, maxHealth));
|
||||
double damage = Math.max(0.0D, petNbt.damage);
|
||||
|
||||
if (!shouldTeleport && distanceSq <= LOOK_DISTANCE_SQ) {
|
||||
this.getLookControl().setLookAt(nmsOwner, 10.0F, this.getMaxHeadXRot());
|
||||
}
|
||||
setAttribute(entity, Attribute.MAX_HEALTH, maxHealth);
|
||||
setAttribute(entity, Attribute.MOVEMENT_SPEED, DEFAULT_MOVEMENT_SPEED);
|
||||
setAttribute(entity, Attribute.ATTACK_DAMAGE, damage);
|
||||
entity.setHealth(health);
|
||||
});
|
||||
return new CustomWolf(owner.getUniqueId(), wolf);
|
||||
}
|
||||
|
||||
if (--this.timeToRecalcPath <= 0) {
|
||||
this.timeToRecalcPath = PATH_RECALC_TICKS;
|
||||
|
||||
if (shouldTeleport) {
|
||||
if (!tryTeleportNearOwner(nmsOwner)) {
|
||||
this.getNavigation().moveTo(nmsOwner, FOLLOW_SPEED);
|
||||
private void startFollowTask() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!wolf.isValid() || wolf.isDead()) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
Player owner = Bukkit.getPlayer(ownerUuid);
|
||||
if (owner == null || !owner.isOnline()) {
|
||||
wolf.remove();
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
if (owner.isDead()) {
|
||||
wolf.setTarget(null);
|
||||
return;
|
||||
}
|
||||
if (!owner.getWorld().equals(wolf.getWorld())) {
|
||||
teleportToOwner(owner);
|
||||
return;
|
||||
}
|
||||
double distanceSq = wolf.getLocation().distanceSquared(owner.getLocation());
|
||||
if (distanceSq < STOP_DISTANCE_SQ) {
|
||||
wolf.setTarget(null);
|
||||
return;
|
||||
}
|
||||
if (distanceSq > TELEPORT_DISTANCE_SQ) {
|
||||
teleportToOwner(owner);
|
||||
}
|
||||
} else {
|
||||
this.getNavigation().moveTo(nmsOwner, FOLLOW_SPEED);
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(PetMain.inst(), FOLLOW_INTERVAL_TICKS, FOLLOW_INTERVAL_TICKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当宠物距离主人太远时,尝试在主人周围随机传送
|
||||
*
|
||||
* @param nmsOwner 主人 NMS 实体
|
||||
*/
|
||||
private boolean tryTeleportNearOwner(Entity nmsOwner) {
|
||||
Vec3 pos = nmsOwner.position();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int x = (int) Math.floor(pos.x) + (random.nextInt(7) - 3);
|
||||
int y = (int) Math.floor(pos.y);
|
||||
int z = (int) Math.floor(pos.z) + (random.nextInt(7) - 3);
|
||||
|
||||
Location location = new Location(getBukkitEntity().getWorld(), x + 0.5D, y, z + 0.5D);
|
||||
if (isSafeTeleportLocation(location)) {
|
||||
this.teleportTo(location.getX(), location.getY(), location.getZ());
|
||||
this.getNavigation().stop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void teleportToOwnerLocation(Player owner) {
|
||||
private void teleportToOwner(Player owner) {
|
||||
Location location = owner.getLocation();
|
||||
if (isSafeTeleportLocation(location)) {
|
||||
this.getBukkitEntity().teleport(location);
|
||||
wolf.teleport(location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,65 +112,7 @@ public class CustomWolf extends Wolf {
|
||||
Block feet = location.getBlock();
|
||||
Block head = feet.getRelative(0, 1, 0);
|
||||
Block ground = feet.getRelative(0, -1, 0);
|
||||
if (!feet.isPassable() || !head.isPassable() || !ground.getType().isSolid()) {
|
||||
return false;
|
||||
}
|
||||
if (!location.getWorld().equals(getBukkitEntity().getWorld())) {
|
||||
return true;
|
||||
}
|
||||
return this.level().noCollision(this, this.getBoundingBox().move(
|
||||
location.getX() - this.getX(),
|
||||
location.getY() - this.getY(),
|
||||
location.getZ() - this.getZ()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写受伤方法,防止主人伤害到自己的宠物
|
||||
*
|
||||
* @param source 伤害来源
|
||||
* @param amount 伤害数值
|
||||
* @return 是否成功造成伤害
|
||||
*/
|
||||
@Override
|
||||
public boolean hurtServer(ServerLevel level, DamageSource source, float amount) {
|
||||
Entity entity = source.getEntity();
|
||||
|
||||
if (entity != null && entity.getUUID().equals(ownerUuid)) {
|
||||
return false;
|
||||
}
|
||||
return super.hurtServer(level, source, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:用于在 Bukkit 世界中生成并注册一只 CustomWolf
|
||||
*
|
||||
* @param owner 宠物主人
|
||||
* @return 新生成的 CustomWolf 实例
|
||||
*/
|
||||
public static CustomWolf spawnCustomWolf(Player owner, PetNbt petNbt) {
|
||||
CraftWorld world = (CraftWorld) owner.getWorld();
|
||||
Level nmsWorld = world.getHandle();
|
||||
|
||||
CustomWolf wolf = new CustomWolf(nmsWorld, owner);
|
||||
|
||||
wolf.setSilent(true);
|
||||
wolf.setOrderedToSit(false);
|
||||
wolf.setPos(owner.getLocation().getX(), owner.getLocation().getY(), owner.getLocation().getZ());
|
||||
|
||||
LivingEntity livingEntity = wolf.getBukkitLivingEntity();
|
||||
double maxHealth = Math.max(1.0D, petNbt.maxHealth);
|
||||
double health = Math.max(1.0D, Math.min(petNbt.health, maxHealth));
|
||||
double damage = Math.max(0.0D, petNbt.damage);
|
||||
|
||||
setAttribute(livingEntity, Attribute.MAX_HEALTH, maxHealth);
|
||||
setAttribute(livingEntity, Attribute.MOVEMENT_SPEED, DEFAULT_MOVEMENT_SPEED);
|
||||
setAttribute(livingEntity, Attribute.ATTACK_DAMAGE, damage);
|
||||
livingEntity.setHealth(health);
|
||||
|
||||
nmsWorld.addFreshEntity(wolf);
|
||||
|
||||
return wolf;
|
||||
return feet.isPassable() && head.isPassable() && ground.getType().isSolid();
|
||||
}
|
||||
|
||||
private static void setAttribute(LivingEntity entity, Attribute attribute, double value) {
|
||||
|
||||
Reference in New Issue
Block a user