[MD]
# ItemComponentExpansion - 物品组件扩展
## 介绍
给`/give`和`/replaceitem`指令的`components`参数添加更多的组件。
## 使用示例
- `/give @s chest 1 0 {"NBT": "{Items:[{Name:\"minecraft:diamond\",Count:1b,tag:{ench:[]}}]}"}`
- `/give @s diamond 1 0 {"ench": []}`
- `/give @s diamond_sword 1 0 {"CustomName": "qwq"}`
- `/give @s diamond_pickaxe 1 0 {"Unbreakable": true}`
- `/give @s leather_horse_armor 1 0 {"NBT": "{customColor:16761035}"}`
## 内置组件
- `CustomName` - 自定义名称(物品名称)
- 格式: `{"CustomName": "自定义名称"}`
- `Lore` - 物品描述
- 格式: `{"Lore": ["第一行描述", "第二行描述", "第三行描述"]}`
- `Unbreakable` - 无法破坏
- 格式: `{"Unbreakable": true}`
- `RepairCost` - 修复成本
- 格式: `{"RepairCost": 10}`
- `Damage` - 物品损坏值
- 格式: `{"Damage": 10}`
- `Enchantments`, `ench`, `enchant` - 附魔
- 格式: `{"Enchantments": [{"id": "minecraft:sharpness", "lvl": -32767}, {"id": 9, "lvl": 32767}, {"id": "锋利"}, {"id": "sharpness"}]}`
- `Sign` - 告示牌数据
- `FrontText` / `BackText` - 前面/后面的文字
- `HideGlowOutline` - 如果告示牌的这一面的文字在发光时不显示外框的轮廓,则为true
- `IgnoreLighting` - 如果告示牌的这一面的文字发光(或该面被使用了荧光墨囊),则为true
- `PersistFormatting` - 未知。默认为1
- `SignTextColor` - 告示牌文本使用的颜色,是32位的小端序整数编码。对于一个RGBA颜色,可以通过int((r<<16)|(g<<8)|b|(a<<24))来编码得到,其中r, g, b和a都是0到255的整数。黑色是该字段的默认值,通过编码(r=0, g=0, b=0, a=255)得到,即16777216
- `Text` - 告示牌上的文本信息。
- `TextOwner` - 写下告示牌文本的玩家的ID
- 格式: `{"Sign": {"FrontText": {"HideGlowOutline": true, "IgnoreLighting": true, "PersistFormatting": 1, "SignTextColor": 16777216, "Text": "Hello, world!", "TextOwner": ""}, "BackText": {}, "IsWaxed": false}}`
- `Furnace` - 熔炉数据
- `BurnTime` - 燃料在耗尽前的时间(刻)
- `CookTime` - 烹饪时间(刻)。在值达到200刻(10秒)时烹饪完成,且在BurnTime达到0时自动设置为0
- `BurnDuration` - 使用的燃料允许的总燃烧时间(刻)
- `StoredXPInt` - 储存的经验值数量
- `NBT` - NBT数据
- 格式: `{"NBT": "{Items:[{Name:\"minecraft:diamond\",Count:1b,tag:{ench:[]}}]}"}`
## 组件注册
### C++
```c++
#include "ComponentRegistry.h"
bool Entry::load() {
using namespace item_component_expansion;
auto& registry = ComponentRegistry::getInstance();
getLogger().warn(
"component: {0}",
fmt::join(registry.getComponents() | std::views::transform([](auto&& p) { return p.first; }), ", ")
);
registry.registerComponent(
{"test"},
[this](ItemStackBase& item, ComponentRegistry::JsonType const& data) -> ll::Expected<> {
getSelf().getLogger().warn("test: {}", data.dump());
return {};
}
);
registry.registerComponent<bool>(
{"test2"},
[this](ItemStackBase& item, bool data) -> ll::Expected<> {
getSelf().getLogger().warn("test2: {}", data);
return {};
}
);
return true;
}
bool Entry::unload() {
using namespace item_component_expansion;
auto& registry = ComponentRegistry::getInstance();
registry.unregisterComponent({"test"});
return true;
}
```
### JavaScript
```javascript
const ComponentRegistry = {
/**
* @param {Array<string>} path
* @param {function(Item, Record<string, any>): string | undefined} callback
* @returns {void}
*/
registerComponent(path, callback) {
const exportName = Math.random().toString(36).slice(2, 9);
ll.exports(callback, exportName, exportName);
const result = ll.imports("ItemComponentExpansion", "registerComponent")(path, exportName, exportName);
if (result) throw new Error(result);
},
/**
* @param {Array<string>} path
* @returns {void}
*/
unregisterComponent(path) {
const result = ll.imports("ItemComponentExpansion", "unregisterComponent")(path);
if (result) throw new Error(result);
},
/**
* @param {Item} item
* @param {Record<string, any>} data
* @return {void}
*/
applyComponent(item, data) {
const result = ll.imports("ItemComponentExpansion", "applyComponent")(item, data);
if (result) throw new Error(result);
},
/**
* @return {Array<Array<string>>}
*/
getComponents() {
return ll.imports("ItemComponentExpansion", "getComponents")();
},
/**
* @param {Array<string>} path
* @param {Array<string>} alisa
*/
registerComponentAlisa(path, alisa){
const result = ll.imports("ItemComponentExpansion", "registerComponentAlisa")(path, alisa);
if (result) throw new Error(result);
}
};
mc.listen("onServerStarted", () => {
logger.warn(JSON.stringify(ComponentRegistry.getComponents()));
ComponentRegistry.registerComponent(
["test"],
(item, data) => {
logger.warn(JSON.stringify(data));
}
);
ll.onUnload(() => {
ComponentRegistry.unregisterComponent(["test"]);
});
});
```
[/MD]