Merge pull request #568 from GHOST3118/improve-items

Improve items
This commit is contained in:
MihailRis 2025-07-26 18:43:37 +03:00 committed by GitHub
commit bde80af0d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 247 additions and 57 deletions

View File

@ -18,6 +18,14 @@ Name of the item model. The model will be loaded automatically.
Default value is `packid:itemname.model`. Default value is `packid:itemname.model`.
If the model is not specified, an automatic one will be generated. If the model is not specified, an automatic one will be generated.
### Caption and Description
`caption` - name of item in inventory
`description` - item description in inventory
this props allow to use `md`
*see [Text Styles](/doc/en/text-styles.md)*
## Behaviour ## Behaviour
### *placing-block* ### *placing-block*

View File

@ -97,6 +97,40 @@ inventory.set(...)
inventory.set_all_data(...) inventory.set_all_data(...)
``` ```
for moving is inefficient, use inventory.move or inventory.move_range. for moving is inefficient, use inventory.move or inventory.move_range.
```lua
-- Get item caption
inventory.get_caption(
-- id of inventory
invid: int,
-- slot id
slot: int
)
-- Set item caption
inventory.set_caption(
-- id of inventory
invid: int,
-- slot id
slot: int,
-- Item Caption
caption: string
)
-- Get item description
inventory.get_description(
-- id of inventory
invid: int,
-- slot id
slot: int
)
-- Set item description
inventory.set_description(
-- id of inventory
invid: int,
-- slot id
slot: int,
-- Item Description
description: string
)
```
```lua ```lua
-- Returns a copy of value of a local property of an item by name or nil. -- Returns a copy of value of a local property of an item by name or nil.

View File

@ -10,6 +10,9 @@ item.index(name: str) -> int
-- Returns the item display name. -- Returns the item display name.
block.caption(blockid: int) -> str block.caption(blockid: int) -> str
-- Returns the item display description.
item.description(itemid: int) -> str
-- Returns max stack size for the item -- Returns max stack size for the item
item.stack_size(itemid: int) -> int item.stack_size(itemid: int) -> int

View File

@ -17,6 +17,14 @@
Значение по-умолчанию - `packid:itemname.model`. Значение по-умолчанию - `packid:itemname.model`.
Если модель не указана, будет сгенерирована автоматическию Если модель не указана, будет сгенерирована автоматическию
### Имя и Описание
`caption` - имя предмета в инвентаре
`description` - описание предмета в инвентаре
Можно использовать `md`
*см. [Text Styles](/doc/en/text-styles.md)*
## Поведение ## Поведение
### Устанавливаемый блок - `placing-block` ### Устанавливаемый блок - `placing-block`

View File

@ -94,6 +94,40 @@ inventory.set(...)
inventory.set_all_data(...) inventory.set_all_data(...)
``` ```
для перемещения вляется неэффективным, используйте inventory.move или inventory.move_range. для перемещения вляется неэффективным, используйте inventory.move или inventory.move_range.
```lua
-- Получает имя предмета в слоте
inventory.get_caption(
-- id инвентаря
invid: int,
-- индекс слота
slot: int
)
-- Задает имя предмету в слоте
inventory.set_caption(
-- id инвентаря
invid: int,
-- индекс слота
slot: int,
-- Имя предмета
caption: string
)
-- Получает описание предмета в слоте
inventory.get_description(
-- id инвентаря
invid: int,
-- индекс слота
slot: int
)
-- Задает описание предмету в слоте
inventory.set_description(
-- id инвентаря
invid: int,
-- индекс слота
slot: int,
-- Описание предмета
description: string
)
```
```lua ```lua
-- Проверяет наличие локального свойства по имени без копирования его значения. -- Проверяет наличие локального свойства по имени без копирования его значения.

View File

@ -10,6 +10,9 @@ item.index(name: str) -> int
-- Возвращает название предмета, отображаемое в интерфейсе. -- Возвращает название предмета, отображаемое в интерфейсе.
item.caption(itemid: int) -> str item.caption(itemid: int) -> str
-- Возвращает описание предмета, отображаемое в интерфейсе.
item.description(itemid: int) -> str
-- Возвращает максимальный размер стопки для предмета. -- Возвращает максимальный размер стопки для предмета.
item.stack_size(itemid: int) -> int item.stack_size(itemid: int) -> int

View File

@ -131,6 +131,44 @@ function inventory.decrement(invid, slot, count)
end end
end end
function inventory.get_caption(invid, slot)
local item_id, count = inventory.get(invid, slot)
local caption = inventory.get_data(invid, slot, "caption")
if not caption then return item.caption(item_id) end
return caption
end
function inventory.set_caption(invid, slot, caption)
local itemid, itemcount = inventory.get(invid, slot)
if itemid == 0 then
return
end
if caption == nil or type(caption) ~= "string" then
caption = ""
end
inventory.set_data(invid, slot, "caption", caption)
end
function inventory.get_description(invid, slot)
local item_id, count = inventory.get(invid, slot)
local description = inventory.get_data(invid, slot, "description")
if not description then return item.description(item_id) end
return description
end
function inventory.set_description(invid, slot, description)
local itemid, itemcount = inventory.get(invid, slot)
if itemid == 0 then
return
end
if description == nil or type(description) ~= "string" then
description = ""
end
inventory.set_data(invid, slot, "description", description)
end
------------------------------------------------ ------------------------------------------------
------------------- Events --------------------- ------------------- Events ---------------------
------------------------------------------------ ------------------------------------------------

View File

@ -29,6 +29,7 @@ template<> void ContentUnitLoader<ItemDef>::loadUnit(
parentDef->cloneTo(def); parentDef->cloneTo(def);
} }
root.at("caption").get(def.caption); root.at("caption").get(def.caption);
root.at("description").get(def.description);
std::string iconTypeStr = ""; std::string iconTypeStr = "";
root.at("icon-type").get(iconTypeStr); root.at("icon-type").get(iconTypeStr);

View File

@ -57,6 +57,14 @@ static inline void draw_glyph(
const FontStyle& style const FontStyle& style
) { ) {
for (int i = 0; i <= style.bold; i++) { for (int i = 0; i <= style.bold; i++) {
glm::vec4 color;
if (style.color == glm::vec4(1, 1, 1, 1)) {
color = batch.getColor();
} else {
color = style.color;
}
batch.sprite( batch.sprite(
pos.x + (offset.x + i / (right.x/glyphInterval/2.0f)) * right.x, pos.x + (offset.x + i / (right.x/glyphInterval/2.0f)) * right.x,
pos.y + offset.y * right.y, pos.y + offset.y * right.y,
@ -65,7 +73,7 @@ static inline void draw_glyph(
-0.15f * style.italic, -0.15f * style.italic,
16, 16,
c, c,
batch.getColor() * style.color color
); );
} }
} }
@ -81,6 +89,15 @@ static inline void draw_glyph(
const FontStyle& style const FontStyle& style
) { ) {
for (int i = 0; i <= style.bold; i++) { for (int i = 0; i <= style.bold; i++) {
glm::vec4 color;
if (style.color == glm::vec4(1, 1, 1, 1)) {
color = batch.getColor();
} else {
color = style.color;
}
batch.sprite( batch.sprite(
pos + right * (offset.x + i) + up * offset.y, pos + right * (offset.x + i) + up * offset.y,
up, right / glyphInterval, up, right / glyphInterval,
@ -88,7 +105,7 @@ static inline void draw_glyph(
0.5f, 0.5f,
16, 16,
c, c,
batch.getColor() * style.color color
); );
} }
} }

View File

@ -50,7 +50,7 @@ GUI::GUI(Engine& engine)
tooltip = guiutil::create( tooltip = guiutil::create(
*this, *this,
"<container color='#000000A0' interactive='false' z-index='999'>" "<container color='#000000A0' interactive='false' z-index='999'>"
"<label id='tooltip.label' pos='2' autoresize='true' multiline='true' text-wrap='false'></label>" "<label id='tooltip.label' markup='md' pos='2' autoresize='true' multiline='true' text-wrap='false'></label>"
"</container>" "</container>"
); );
store("tooltip", tooltip); store("tooltip", tooltip);

View File

@ -1,10 +1,21 @@
#include "InventoryView.hpp" #include "InventoryView.hpp"
#include <glm/glm.hpp>
#include <utility>
#include "assets/Assets.hpp" #include "assets/Assets.hpp"
#include "assets/assets_util.hpp" #include "assets/assets_util.hpp"
#include "content/Content.hpp" #include "content/Content.hpp"
#include "frontend/LevelFrontend.hpp" #include "frontend/LevelFrontend.hpp"
#include "frontend/locale.hpp" #include "frontend/locale.hpp"
#include "graphics/core/Atlas.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Font.hpp"
#include "graphics/core/Shader.hpp"
#include "graphics/core/Texture.hpp"
#include "graphics/render/BlocksPreview.hpp"
#include "graphics/ui/GUI.hpp"
#include "items/Inventories.hpp" #include "items/Inventories.hpp"
#include "items/Inventory.hpp" #include "items/Inventory.hpp"
#include "items/ItemDef.hpp" #include "items/ItemDef.hpp"
@ -15,17 +26,6 @@
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "window/input.hpp" #include "window/input.hpp"
#include "world/Level.hpp" #include "world/Level.hpp"
#include "graphics/core/Atlas.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/Font.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Shader.hpp"
#include "graphics/core/Texture.hpp"
#include "graphics/render/BlocksPreview.hpp"
#include "graphics/ui/GUI.hpp"
#include <glm/glm.hpp>
#include <utility>
using namespace gui; using namespace gui;
@ -37,20 +37,23 @@ SlotLayout::SlotLayout(
slotcallback updateFunc, slotcallback updateFunc,
slotcallback shareFunc, slotcallback shareFunc,
slotcallback rightClick slotcallback rightClick
) : index(index), )
: index(index),
position(position), position(position),
background(background), background(background),
itemSource(itemSource), itemSource(itemSource),
updateFunc(std::move(updateFunc)), updateFunc(std::move(updateFunc)),
shareFunc(std::move(shareFunc)), shareFunc(std::move(shareFunc)),
rightClick(std::move(rightClick)) {} rightClick(std::move(rightClick)) {
}
InventoryBuilder::InventoryBuilder(GUI& gui) : gui(gui) { InventoryBuilder::InventoryBuilder(GUI& gui) : gui(gui) {
view = std::make_shared<InventoryView>(gui); view = std::make_shared<InventoryView>(gui);
} }
void InventoryBuilder::addGrid( void InventoryBuilder::addGrid(
int cols, int count, int cols,
int count,
glm::vec2 pos, glm::vec2 pos,
glm::vec4 padding, glm::vec4 padding,
bool addpanel, bool addpanel,
@ -61,8 +64,10 @@ void InventoryBuilder::addGrid(
int rows = ceildiv(count, cols); int rows = ceildiv(count, cols);
uint width = cols * (slotSize + interval) - interval + padding.x + padding.z; uint width =
uint height = rows * (slotSize + interval) - interval + padding.y + padding.w; cols * (slotSize + interval) - interval + padding.x + padding.z;
uint height =
rows * (slotSize + interval) - interval + padding.y + padding.w;
glm::vec2 vsize = view->getSize(); glm::vec2 vsize = view->getSize();
if (pos.x + width > vsize.x) { if (pos.x + width > vsize.x) {
@ -85,7 +90,7 @@ void InventoryBuilder::addGrid(
if (row * cols + col >= count) { if (row * cols + col >= count) {
break; break;
} }
glm::vec2 position ( glm::vec2 position(
col * (slotSize + interval) + padding.x, col * (slotSize + interval) + padding.x,
row * (slotSize + interval) + padding.y row * (slotSize + interval) + padding.y
); );
@ -105,11 +110,9 @@ std::shared_ptr<InventoryView> InventoryBuilder::build() {
return view; return view;
} }
SlotView::SlotView( SlotView::SlotView(GUI& gui, SlotLayout layout)
GUI& gui, SlotLayout layout : UINode(gui, glm::vec2(InventoryView::SLOT_SIZE)),
) : UINode(gui, glm::vec2(InventoryView::SLOT_SIZE)), layout(std::move(layout)) {
layout(std::move(layout))
{
setColor(glm::vec4(0, 0, 0, 0.2f)); setColor(glm::vec4(0, 0, 0, 0.2f));
setTooltipDelay(0.0f); setTooltipDelay(0.0f);
} }
@ -120,9 +123,24 @@ void SlotView::refreshTooltip(const ItemStack& stack, const ItemDef& item) {
return; return;
} }
if (itemid) { if (itemid) {
tooltip = util::pascal_case( dv::value* caption = stack.getField("caption");
langs::get(util::str2wstr_utf8(item.caption)) dv::value* description = stack.getField("description");
); std::wstring captionText;
std::wstring descriptionText;
if (description != nullptr) {
descriptionText = util::pascal_case( langs::get( util::str2wstr_utf8( description->asString() ) ) );
} else {
descriptionText = util::pascal_case( langs::get( util::str2wstr_utf8( item.description ) ) );
}
if (caption != nullptr) {
captionText = util::pascal_case( langs::get( util::str2wstr_utf8( caption->asString() ) ) );
} else {
captionText = util::pascal_case( langs::get( util::str2wstr_utf8( item.caption ) ) );
}
tooltip = captionText + L"\n" + descriptionText;
} else { } else {
tooltip.clear(); tooltip.clear();
} }
@ -148,8 +166,17 @@ void SlotView::drawItemIcon(
UVRegion region = previews.get(block.name); UVRegion region = previews.get(block.name);
batch.rect( batch.rect(
pos.x, pos.y, SLOT_SIZE, SLOT_SIZE, pos.x,
0, 0, 0, region, false, true, tint pos.y,
SLOT_SIZE,
SLOT_SIZE,
0,
0,
0,
region,
false,
true,
tint
); );
break; break;
} }
@ -159,8 +186,17 @@ void SlotView::drawItemIcon(
batch.texture(textureRegion.texture); batch.texture(textureRegion.texture);
batch.rect( batch.rect(
pos.x, pos.y, SLOT_SIZE, SLOT_SIZE, pos.x,
0, 0, 0, textureRegion.region, false, true, tint pos.y,
SLOT_SIZE,
SLOT_SIZE,
0,
0,
0,
textureRegion.region,
false,
true,
tint
); );
break; break;
} }
@ -317,8 +353,7 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
} }
return; return;
} }
if (layout.itemSource) if (layout.itemSource) return;
return;
if (grabbed.isEmpty()) { if (grabbed.isEmpty()) {
if (!stack.isEmpty() && layout.taking) { if (!stack.isEmpty() && layout.taking) {
grabbed.set(std::move(stack)); grabbed.set(std::move(stack));
@ -342,15 +377,15 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
} else { } else {
grabbed = ItemStack(stack.getItemId(), count - 1); grabbed = ItemStack(stack.getItemId(), count - 1);
} }
} else if (stack.accepts(grabbed) && stack.getCount() < stackDef.stackSize) { } else if (stack.accepts(grabbed) &&
stack.getCount() < stackDef.stackSize) {
stack.setCount(stack.getCount() + 1); stack.setCount(stack.getCount() + 1);
grabbed.setCount(grabbed.getCount() - 1); grabbed.setCount(grabbed.getCount() - 1);
} }
} }
void SlotView::clicked(Mousecode button) { void SlotView::clicked(Mousecode button) {
if (bound == nullptr) if (bound == nullptr) return;
return;
auto exchangeSlot = auto exchangeSlot =
std::dynamic_pointer_cast<SlotView>(gui.get(EXCHANGE_SLOT_NAME)); std::dynamic_pointer_cast<SlotView>(gui.get(EXCHANGE_SLOT_NAME));
if (exchangeSlot == nullptr) { if (exchangeSlot == nullptr) {
@ -382,9 +417,7 @@ const std::wstring& SlotView::getTooltip() const {
} }
void SlotView::bind( void SlotView::bind(
int64_t inventoryid, int64_t inventoryid, ItemStack& stack, const Content* content
ItemStack& stack,
const Content* content
) { ) {
this->inventoryid = inventoryid; this->inventoryid = inventoryid;
bound = &stack; bound = &stack;
@ -403,8 +436,8 @@ InventoryView::InventoryView(GUI& gui) : Container(gui, glm::vec2()) {
setColor(glm::vec4(0, 0, 0, 0.0f)); setColor(glm::vec4(0, 0, 0, 0.0f));
} }
InventoryView::~InventoryView() {} InventoryView::~InventoryView() {
}
std::shared_ptr<SlotView> InventoryView::addSlot(const SlotLayout& layout) { std::shared_ptr<SlotView> InventoryView::addSlot(const SlotLayout& layout) {
uint width = InventoryView::SLOT_SIZE + layout.padding; uint width = InventoryView::SLOT_SIZE + layout.padding;
@ -432,14 +465,12 @@ std::shared_ptr<Inventory> InventoryView::getInventory() const {
return inventory; return inventory;
} }
size_t InventoryView::getSlotsCount() const { size_t InventoryView::getSlotsCount() const {
return slots.size(); return slots.size();
} }
void InventoryView::bind( void InventoryView::bind(
const std::shared_ptr<Inventory>& inventory, const std::shared_ptr<Inventory>& inventory, const Content* content
const Content* content
) { ) {
this->inventory = inventory; this->inventory = inventory;
this->content = content; this->content = content;

View File

@ -4,9 +4,11 @@
ItemDef::ItemDef(const std::string& name) : name(name) { ItemDef::ItemDef(const std::string& name) : name(name) {
caption = util::id_to_caption(name); caption = util::id_to_caption(name);
description = "";
} }
void ItemDef::cloneTo(ItemDef& dst) { void ItemDef::cloneTo(ItemDef& dst) {
dst.caption = caption; dst.caption = caption;
dst.description = description;
dst.stackSize = stackSize; dst.stackSize = stackSize;
dst.generated = generated; dst.generated = generated;
std::copy(&emission[0], &emission[3], dst.emission); std::copy(&emission[0], &emission[3], dst.emission);

View File

@ -34,6 +34,9 @@ struct ItemDef {
/// @brief Item name will shown in inventory /// @brief Item name will shown in inventory
std::string caption; std::string caption;
/// @brief Item description will shown in inventory
std::string description;
dv::value properties = nullptr; dv::value properties = nullptr;
/// @brief Item max stack size /// @brief Item max stack size

View File

@ -57,6 +57,13 @@ static int l_caption(lua::State* L) {
return 0; return 0;
} }
static int l_description(lua::State* L) {
if (auto def = get_item_def(L, 1)) {
return lua::pushstring(L, def->description);
}
return 0;
}
static int l_placing_block(lua::State* L) { static int l_placing_block(lua::State* L) {
if (auto def = get_item_def(L, 1)) { if (auto def = get_item_def(L, 1)) {
return lua::pushinteger(L, def->rt.placingBlock); return lua::pushinteger(L, def->rt.placingBlock);
@ -108,6 +115,7 @@ const luaL_Reg itemlib[] = {
{"defs_count", lua::wrap<l_defs_count>}, {"defs_count", lua::wrap<l_defs_count>},
{"icon", lua::wrap<l_get_icon>}, {"icon", lua::wrap<l_get_icon>},
{"caption", lua::wrap<l_caption>}, {"caption", lua::wrap<l_caption>},
{"description", lua::wrap<l_description>},
{"placing_block", lua::wrap<l_placing_block>}, {"placing_block", lua::wrap<l_placing_block>},
{"model_name", lua::wrap<l_model_name>}, {"model_name", lua::wrap<l_model_name>},
{"emission", lua::wrap<l_emission>}, {"emission", lua::wrap<l_emission>},