Skip to content

Commit

Permalink
feat: 实现锻造功能 (#10)
Browse files Browse the repository at this point in the history
* feat: 实现 FootageAttr#toNBT 方法,初步实现锻造结果处理

* patch: 实现锻造物品的属性计算

* patch: 实现锻造物品attrLore更新

* patch: 修复吞素材的问题
  • Loading branch information
Mcayear authored Sep 24, 2024
1 parent c5f535a commit ae632c3
Show file tree
Hide file tree
Showing 18 changed files with 557 additions and 189 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>RcRPG.RcRPGMain</groupId>
<artifactId>RcRPG</artifactId>
<version>1.1.6-MOT</version>
<version>1.1.7-MOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/RcRPG/AttrManager/FootageAttr.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package RcRPG.AttrManager;

import RcRPG.RcRPGMain;
import cn.nukkit.nbt.tag.CompoundTag;
import cn.nukkit.nbt.tag.FloatTag;
import cn.nukkit.nbt.tag.ListTag;
import cn.nukkit.nbt.tag.Tag;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FootageAttr extends Manager {

public FootageAttr() {
myAttr.put("Main", new HashMap<>());
}
/**
* 属性结构
* {
Expand All @@ -18,6 +25,10 @@ public class FootageAttr extends Manager {
*/
public Map<String, Map<String, float[]>> myAttr = new HashMap<>();

public Map<String, float[]> getMainAttr() {
return myAttr.get("Main");
}

public void setItemAttrConfig(String id, Map<String, Object> newAttr) {
Map<String, float[]> attrMap = new HashMap<>();
for (Map.Entry<String, Object> entry : newAttr.entrySet()) {
Expand Down Expand Up @@ -80,4 +91,62 @@ public void setItemAttrConfig(String id, Map<String, Object> newAttr) {
}
}
}

/**
* 将属性转换为 NBT 格式
* 此方法用于序列化对象的属性,以便可以将其保存至物品
*
* @return 返回包含所有属性的 CompoundTag,用于保存至物品
*/
public CompoundTag toNBT() {
// 创建一个根CompoundTag来存储主属性
CompoundTag nbt = new CompoundTag();

// 获取主属性
Map<String, float[]> mainAttr = getMainAttr();

// 如果主属性不为空,遍历它并将其转换为NBT格式
if (mainAttr != null) {
for (Map.Entry<String, float[]> attrEntry : mainAttr.entrySet()) {
// 获取属性键和值
String attrKey = attrEntry.getKey();
float[] values = attrEntry.getValue();

// 创建一个ListTag来存储属性值
ListTag<FloatTag> valueList = new ListTag<>();
valueList.add(new FloatTag("", values[0]));
valueList.add(new FloatTag("", values[1]));

// 将ListTag添加到根CompoundTag中
nbt.putList(attrKey, valueList);
}
}

// 返回包含主属性的CompoundTag
return nbt;
}

public static Map<String, float[]> fromNBT(CompoundTag compoundTag) {
// 创建一个Map来存储反序列化后的主属性
Map<String, float[]> mainAttr = new HashMap<>();

// 遍历CompoundTag中的每个Tag
for (Tag tag : compoundTag.getAllTags()) {
if (tag instanceof ListTag<?> valueList && tag.getName() != null) {
String attrKey = tag.getName(); // 获取属性的键

// 提取ListTag中的两个值并存储到一个float数组中
float[] values = new float[2];
values[0] = ((FloatTag) valueList.get(0)).getData(); // 确保是FloatTag
values[1] = ((FloatTag) valueList.get(1)).getData();

// 将该属性键和值添加到主属性Map中
mainAttr.put(attrKey, values);
}
}

// 返回反序列化后的主属性Map
return mainAttr;
}

}
16 changes: 13 additions & 3 deletions src/main/java/RcRPG/AttrManager/ItemAttr.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package RcRPG.AttrManager;

import RcRPG.RcRPGMain;
import cn.nukkit.lang.LangCode;

import java.util.HashMap;
import java.util.List;
Expand All @@ -14,9 +15,7 @@ public class ItemAttr extends Manager {

/** 属性结构
* {
* "Main": {
* "攻击力": [1,3]
* }
* "攻击力": [1,3]
* }
* */
protected Map<String, float[]> mainAttr;
Expand Down Expand Up @@ -121,6 +120,17 @@ public String replaceAttrTemplate(String str) {
return sb.toString();
}

public String attrInfo(LangCode langCode) {
StringBuilder sb = new StringBuilder();
for (String attrName : getMainAttr().keySet()) {
float[] value = mainAttr.get(attrName);
sb.append(RcRPGMain.getInstance().attrTemplateConfig.getAttributeText(langCode, attrName, value[0], value[1]));
sb.append('\n');
}
sb.deleteCharAt(sb.length() - 1);// Remove the trailing "\n"
return sb.toString();
}

//激进向 (9)

@Override
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/RcRPG/AttrManager/PlayerAttr.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public void update() {
});
}

setItemAttrConfig(weapon.getLabel(), weapon.getMainAttr());
setItemAttrConfig(weapon.getLabel(), ForgingItem.isForgingItem(rcItem) ? ForgingItem.fromNBT(rcItem.getNamedTag().getCompound("attr")) : weapon.getMainAttr());
checkItemStoneAttr(weapon.getLabel(), Weapon.getStones(rcItem), beforeLabel, labelList);

beforeLabel.remove(weapon.getLabel());
Expand All @@ -153,7 +153,7 @@ public void update() {
if (rcItem.getNamedTag() == null) continue;
Armour armour = RcRPGMain.loadArmour.get(rcItem.getNamedTag().getString("name"));
if (armour == null) continue;
setItemAttrConfig(armour.getLabel(), armour.getMainAttr());
setItemAttrConfig(armour.getLabel(), ForgingItem.isForgingItem(rcItem) ? ForgingItem.fromNBT(rcItem.getNamedTag().getCompound("attr")) : armour.getMainAttr());
checkItemStoneAttr(armour.getLabel(), Armour.getStones(rcItem), beforeLabel, labelList);

if (!armour.getSuit().isEmpty()) {// 套装
Expand Down Expand Up @@ -426,7 +426,6 @@ protected static String lessZero(float value) {
* 将数据可视化,输入data,属性输出min-max或x%
*/
public static String valueToString(float[] data, String attribute) {
List<String> attrDisplayPercent = MainConfig.getAttrDisplayPercent();
String back = "";
if (data.length == 2) {
if (data[0] == data[1]) {
Expand All @@ -435,7 +434,7 @@ public static String valueToString(float[] data, String attribute) {
return lessZero(data[0]) + " - " + lessZero(data[1]);
}
}
if (attrDisplayPercent.contains(attribute)) {
if (MainConfig.getAttrDisplayPercent().contains(attribute)) {
// 百分比的值
DecimalFormat decimalFormat = new DecimalFormat("#.00");
decimalFormat.setMinimumIntegerDigits(1); // 确保整数部分至少有一位数字
Expand Down
113 changes: 69 additions & 44 deletions src/main/java/RcRPG/RPG/Armour.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

@Getter
@Setter
public class Armour extends ItemAttr {
public class Armour extends ItemAttr implements Cloneable {

private Config config;

Expand Down Expand Up @@ -88,45 +88,53 @@ public Armour(String name, Config config) {
this.config = config;
}

public static Armour loadArmour(String name, Config config) {
try {
Armour armour = new Armour(name, config);
public Armour initArmour() {
this.setLabel(config.getString("标签"));
this.setShowName(config.getString("显示名称"));
this.setItem(Item.fromString(config.getString("物品ID")));
if (config.exists("属性")) {
this.setAttr((Map<String, Object>) config.get("属性"));
}
this.setMessage(config.getString("介绍", ""));

armour.setLabel(config.getString("标签"));
armour.setShowName(config.getString("显示名称"));
armour.setItem(Item.fromString(config.getString("物品ID")));
if (config.exists("属性")) {
armour.setAttr((Map<String, Object>) config.get("属性"));
this.setColor(loadColorFromConfig(config));

this.setDismantle(config.getString("分解", ""));

if (config.exists("套装")) {
List<String> suitList;
if (config.isList("套装")) {
suitList = config.getStringList("套装");
} else {
suitList = new ArrayList<>(Arrays.asList(config.getString("套装", "").split(",")));
}
armour.setMessage(config.getString("介绍", ""));
this.setSuit(suitList);
}

armour.setColor(loadColorFromConfig(config));
this.setTipText(config.getString("底部显示"));
this.setMyMessage(config.getString("个人通知"));
this.setServerMessage(config.getString("全服通知"));
this.setStone(config.getInt("宝石孔数"));

armour.setDismantle(config.getString("分解", ""));
this.setEffects(loadEffectsFromConfig(config));

if (config.exists("套装")) {
List<String> suitList;
if (config.isList("套装")) {
suitList = config.getStringList("套装");
} else {
suitList = new ArrayList<>(Arrays.asList(config.getString("套装", "").split(",")));
}
armour.setSuit(suitList);
}
ArrayList<String> loreList = new ArrayList<>(config.getStringList("显示"));
this.setLoreList(loreList);
ArrayList<String> stoneList = new ArrayList<>(config.getStringList("宝石槽"));
this.setStoneList(stoneList);

armour.setTipText(config.getString("底部显示"));
armour.setMyMessage(config.getString("个人通知"));
armour.setServerMessage(config.getString("全服通知"));
armour.setStone(config.getInt("宝石孔数"));
return this;
}

armour.setEffects(loadEffectsFromConfig(config));
@Override
public Armour clone() {
return new Armour(this.name, this.config).initArmour();
}

ArrayList<String> loreList = new ArrayList<>(config.getStringList("显示"));
armour.setLoreList(loreList);
ArrayList<String> stoneList = new ArrayList<>(config.getStringList("宝石槽"));
armour.setStoneList(stoneList);
public static Armour loadArmour(String name, Config config) {
try {

return armour;
return new Armour(name, config).initArmour();
} catch (Exception e) {
e.printStackTrace();
RcRPGMain.getInstance().getLogger().error("加载盔甲" + name + "配置文件失败");
Expand Down Expand Up @@ -195,7 +203,7 @@ public static boolean delArmourConfig(String name) {

public static Item getItem(String name, int count, LangCode langCode) {
Armour armour = RcRPGMain.loadArmour.get(name);
Item item = armour.getItem();
Item item = armour.getItem().clone();
item.setCount(count);
CompoundTag tag = item.hasCompoundTag() ? item.getNamedTag() : new CompoundTag();
tag.putString("type", "armour");
Expand Down Expand Up @@ -341,21 +349,38 @@ public static int getStoneReDamage(Item item) {

public static Item setArmourLore(Item item, LangCode langCode) {
if (Armour.isArmour(item)) {
Armour armour = RcRPGMain.loadArmour.get(item.getNamedTag().getString("name"));
Armour armour;

boolean isForgingItem = ForgingItem.isForgingItem(item);
if (isForgingItem) {
// 锻造物品属性处理
armour = RcRPGMain.loadArmour.get(item.getNamedTag().getString("name")).clone();
armour.mainAttr = new HashMap<>();

for (Map.Entry<String, float[]> entry : ForgingItem.fromNBT(item.getNamedTag().getCompound("attr")).entrySet()) {
armour.mainAttr.put(entry.getKey(), entry.getValue());
}
} else {
// 非锻造物品不使用深拷贝
armour = RcRPGMain.loadArmour.get(item.getNamedTag().getString("name"));
}

ArrayList<String> lore = (ArrayList<String>) armour.getLoreList().clone();
for (int i = 0; i < lore.size(); i++) {
String s = lore.get(i);
if (s.contains("@message")) s = s.replace("@message", armour.getMessage());
if (s.contains("@stoneHealth"))
s = s.replace("@stoneHealth", String.valueOf(Armour.getStoneHealth(item)));
if (s.contains("@stoneDamage"))
s = s.replace("@stoneDamage", String.valueOf(Armour.getStoneDamage(item)));
if (s.contains("@stoneReDamage"))
s = s.replace("@stoneReDamage", String.valueOf(Armour.getStoneReDamage(item)));
if (s.contains("@gemLore"))
s = s.replace("@gemLore", RcRPGMain.getInstance().getGemTemplateConfig().getTemplateText(langCode, item.getNamedTag(), armour.getStone(), armour.getStoneList()));

s = armour.replaceAttrTemplate(s);// 替换属性的值
s = s.replace("@message", armour.getMessage());
s = s.replace("@stoneHealth", String.valueOf(Armour.getStoneHealth(item)));
s = s.replace("@stoneDamage", String.valueOf(Armour.getStoneDamage(item)));
s = s.replace("@stoneReDamage", String.valueOf(Armour.getStoneReDamage(item)));
s = s.replace("@gemLore", RcRPGMain.getInstance().getGemTemplateConfig().getTemplateText(langCode, item.getNamedTag(), armour.getStone(), armour.getStoneList()));

// 替换属性的值
if (isForgingItem) {
s = s.replace("@attrLore", armour.attrInfo(langCode));
} else {
s = armour.replaceAttrTemplate(s);
}

lore.set(i, s);
}
item.setLore(lore.toArray(new String[0]));
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/RcRPG/RPG/ForgingItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package RcRPG.RPG;

import RcRPG.AttrManager.FootageAttr;
import cn.nukkit.item.Item;
import cn.nukkit.nbt.tag.CompoundTag;

import java.util.Map;

public class ForgingItem {
public static boolean isForgingItem(Item item) {
if (item.getNamedTag() == null) {
return false;
}
return item.getNamedTag().containsCompound("attr");
}

public static Map<String, float[]> fromNBT(CompoundTag compoundTag) {
return FootageAttr.fromNBT(compoundTag);
}
}
Loading

0 comments on commit ae632c3

Please sign in to comment.