commit
1584b07706
@ -1,4 +1,5 @@
|
||||
{
|
||||
"icon-type": "sprite",
|
||||
"icon": "items:bazalt_breaker"
|
||||
"icon": "items:bazalt_breaker",
|
||||
"uses": 100
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
local util = {}
|
||||
|
||||
function util.drop(ppos, itemid, count, pickup_delay)
|
||||
function util.drop(ppos, itemid, count, data, pickup_delay)
|
||||
if itemid == 0 or not itemid then
|
||||
return nil
|
||||
end
|
||||
return entities.spawn("base:drop", ppos, {base__drop={
|
||||
id=itemid,
|
||||
count=count,
|
||||
data=data,
|
||||
pickup_delay=pickup_delay
|
||||
}})
|
||||
end
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
function on_block_break_by(x, y, z, p)
|
||||
function on_block_break_by(x, y, z, pid)
|
||||
block.set(x, y, z, 0, 0)
|
||||
if not player.is_infinite_items(pid) then
|
||||
inventory.use(player.get_inventory(pid))
|
||||
end
|
||||
end
|
||||
|
||||
@ -14,6 +14,7 @@ end
|
||||
if SAVED_DATA.item then
|
||||
dropitem.id = item.index(SAVED_DATA.item)
|
||||
dropitem.count = SAVED_DATA.count
|
||||
dropitem.data = SAVED_DATA.data
|
||||
end
|
||||
|
||||
local DROP_SCALE = 0.3
|
||||
@ -25,6 +26,7 @@ local rotation = mat4.rotate({
|
||||
function on_save()
|
||||
SAVED_DATA.item = item.name(dropitem.id)
|
||||
SAVED_DATA.count = dropitem.count
|
||||
SAVED_DATA.data = dropitem.data
|
||||
end
|
||||
|
||||
do -- setup visuals
|
||||
@ -59,11 +61,10 @@ function on_sensor_enter(index, oid)
|
||||
if pid == -1 then
|
||||
-- other is base:drop too
|
||||
if index == 0 and other:def_index() == def_index then
|
||||
local odrop = other:get_component("base:drop")
|
||||
if odrop.dropitem.id == dropitem.id then
|
||||
-- // TODO: replace combination logic with item.* function
|
||||
local odrop = other:get_component("base:drop").dropitem
|
||||
if odrop.id == dropitem.id and not odrop.data then
|
||||
local stack = item.stack_size(dropitem.id)
|
||||
local sum = dropitem.count + odrop.dropitem.count
|
||||
local sum = dropitem.count + odrop.count
|
||||
if sum <= stack then
|
||||
dropitem.count = sum
|
||||
other:despawn()
|
||||
@ -75,7 +76,7 @@ function on_sensor_enter(index, oid)
|
||||
|
||||
if timer < 0.0 and index == 0 then
|
||||
entity:despawn()
|
||||
inventory.add(player.get_inventory(pid), dropitem.id, dropitem.count)
|
||||
inventory.add(player.get_inventory(pid), dropitem.id, dropitem.count, dropitem.data)
|
||||
audio.play_sound_2d("events/pickup", 0.5, 0.8 + math.random() * 0.4, "regular")
|
||||
end
|
||||
if index == 1 then
|
||||
|
||||
@ -14,12 +14,13 @@ function on_hud_open()
|
||||
if itemid == 0 then
|
||||
return
|
||||
end
|
||||
local data = inventory.get_all_data(invid, slot)
|
||||
inventory.set(invid, slot, itemid, itemcount-1)
|
||||
|
||||
local pvel = {player.get_vel(pid)}
|
||||
local ppos = vec3.add({player.get_pos(pid)}, {0, 0.7, 0})
|
||||
local throw_force = vec3.mul(player.get_dir(pid), DROP_FORCE)
|
||||
local drop = base_util.drop(ppos, itemid, 1, 1.5)
|
||||
local drop = base_util.drop(ppos, itemid, 1, data, 1.5)
|
||||
local velocity = vec3.add(throw_force, vec3.add(pvel, DROP_INIT_VEL))
|
||||
drop.rigidbody:set_vel(velocity)
|
||||
end)
|
||||
|
||||
@ -94,6 +94,31 @@ elseif __vc_app then
|
||||
complete_app_lib(__vc_app)
|
||||
end
|
||||
|
||||
function inventory.get_uses(invid, slot)
|
||||
local uses = inventory.get_data(invid, slot, "uses")
|
||||
if uses == nil then
|
||||
return item.uses(inventory.get(invid, slot))
|
||||
end
|
||||
return uses
|
||||
end
|
||||
|
||||
|
||||
function inventory.use(invid, slot)
|
||||
local itemid, count = inventory.get(invid, slot)
|
||||
if itemid == nil then
|
||||
return
|
||||
end
|
||||
local item_uses = inventory.get_uses(invid, slot)
|
||||
if item_uses == nil then
|
||||
return
|
||||
end
|
||||
if item_uses == 1 then
|
||||
inventory.set(invid, slot, itemid, count - 1)
|
||||
elseif item_uses > 1 then
|
||||
inventory.set_data(invid, slot, "uses", item_uses - 1)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------
|
||||
------------------- Events ---------------------
|
||||
------------------------------------------------
|
||||
|
||||
@ -429,15 +429,29 @@ void ContentLoader::loadItem(
|
||||
} else if (iconTypeStr == "sprite") {
|
||||
def.iconType = ItemIconType::SPRITE;
|
||||
} else if (iconTypeStr.length()) {
|
||||
logger.error() << name << ": unknown icon type" << iconTypeStr;
|
||||
logger.error() << name << ": unknown icon type - " << iconTypeStr;
|
||||
}
|
||||
root.at("icon").get(def.icon);
|
||||
root.at("placing-block").get(def.placingBlock);
|
||||
root.at("script-name").get(def.scriptName);
|
||||
root.at("model-name").get(def.modelName);
|
||||
root.at("stack-size").get(def.stackSize);
|
||||
root.at("uses").get(def.uses);
|
||||
|
||||
std::string usesDisplayStr = "";
|
||||
root.at("uses-display").get(usesDisplayStr);
|
||||
if (usesDisplayStr == "none") {
|
||||
def.usesDisplay = ItemUsesDisplay::NONE;
|
||||
} else if (usesDisplayStr == "number") {
|
||||
def.usesDisplay = ItemUsesDisplay::NUMBER;
|
||||
} else if (usesDisplayStr == "relation") {
|
||||
def.usesDisplay = ItemUsesDisplay::RELATION;
|
||||
} else if (usesDisplayStr == "vbar") {
|
||||
def.usesDisplay = ItemUsesDisplay::VBAR;
|
||||
} else if (usesDisplayStr.length()) {
|
||||
logger.error() << name << ": unknown uses display mode - " << usesDisplayStr;
|
||||
}
|
||||
|
||||
// item light emission [r, g, b] where r,g,b in range [0..15]
|
||||
if (auto found = root.at("emission")) {
|
||||
const auto& emissionarr = *found;
|
||||
def.emission[0] = emissionarr[0].asNumber();
|
||||
|
||||
@ -70,7 +70,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
);
|
||||
|
||||
HudElement::HudElement(
|
||||
hud_element_mode mode,
|
||||
HudElementMode mode,
|
||||
UiDocument* document,
|
||||
std::shared_ptr<UINode> node,
|
||||
bool debug
|
||||
@ -83,16 +83,16 @@ void HudElement::update(bool pause, bool inventoryOpen, bool debugMode) {
|
||||
return;
|
||||
}
|
||||
switch (mode) {
|
||||
case hud_element_mode::permanent:
|
||||
case HudElementMode::PERMANENT:
|
||||
node->setVisible(true);
|
||||
break;
|
||||
case hud_element_mode::ingame:
|
||||
case HudElementMode::INGAME:
|
||||
node->setVisible(!pause && !inventoryOpen);
|
||||
break;
|
||||
case hud_element_mode::inventory_any:
|
||||
case HudElementMode::INVENTORY_ANY:
|
||||
node->setVisible(inventoryOpen);
|
||||
break;
|
||||
case hud_element_mode::inventory_bound:
|
||||
case HudElementMode::INVENTORY:
|
||||
removed = !inventoryOpen;
|
||||
break;
|
||||
}
|
||||
@ -108,21 +108,21 @@ std::shared_ptr<UINode> HudElement::getNode() const {
|
||||
|
||||
std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
||||
auto& content = frontend.getLevel().content;
|
||||
auto indices = content.getIndices();
|
||||
auto& indices = *content.getIndices();
|
||||
auto inventory = player.getInventory();
|
||||
|
||||
size_t itemsCount = indices->items.count();
|
||||
size_t itemsCount = indices.items.count();
|
||||
auto accessInventory = std::make_shared<Inventory>(0, itemsCount);
|
||||
for (size_t id = 1; id < itemsCount; id++) {
|
||||
accessInventory->getSlot(id-1).set(ItemStack(id, 1));
|
||||
}
|
||||
|
||||
SlotLayout slotLayout(-1, glm::vec2(), false, true, nullptr,
|
||||
[=](uint, ItemStack& item) {
|
||||
[inventory, &indices](uint, ItemStack& item) {
|
||||
auto copy = ItemStack(item);
|
||||
inventory->move(copy, indices);
|
||||
},
|
||||
[=](uint, ItemStack& item) {
|
||||
[this, inventory](uint, ItemStack& item) {
|
||||
inventory->getSlot(player.getChosenSlot()).set(item);
|
||||
});
|
||||
|
||||
@ -192,7 +192,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
||||
auto dplotter = std::make_shared<Plotter>(350, 250, 2000, 16);
|
||||
dplotter->setGravity(Gravity::bottom_right);
|
||||
dplotter->setInteractive(false);
|
||||
add(HudElement(hud_element_mode::permanent, nullptr, dplotter, true));
|
||||
add(HudElement(HudElementMode::PERMANENT, nullptr, dplotter, true));
|
||||
|
||||
assets.store(Texture::from(debugImgWorldGen.get()), DEBUG_WORLDGEN_IMAGE);
|
||||
|
||||
@ -200,7 +200,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
||||
"<image src='"+DEBUG_WORLDGEN_IMAGE+
|
||||
"' pos='0' size='256' gravity='top-right' margin='0,20,0,0'/>"
|
||||
);
|
||||
add(HudElement(hud_element_mode::permanent, nullptr, debugMinimap, true));
|
||||
add(HudElement(HudElementMode::PERMANENT, nullptr, debugMinimap, true));
|
||||
}
|
||||
|
||||
Hud::~Hud() {
|
||||
@ -372,8 +372,8 @@ void Hud::openInventory() {
|
||||
auto inventoryDocument = assets.get<UiDocument>("core:inventory");
|
||||
inventoryView = std::dynamic_pointer_cast<InventoryView>(inventoryDocument->getRoot());
|
||||
inventoryView->bind(inventory, &content);
|
||||
add(HudElement(hud_element_mode::inventory_bound, inventoryDocument, inventoryView, false));
|
||||
add(HudElement(hud_element_mode::inventory_bound, nullptr, exchangeSlot, false));
|
||||
add(HudElement(HudElementMode::INVENTORY, inventoryDocument, inventoryView, false));
|
||||
add(HudElement(HudElementMode::INVENTORY, nullptr, exchangeSlot, false));
|
||||
}
|
||||
|
||||
std::shared_ptr<Inventory> Hud::openInventory(
|
||||
@ -401,7 +401,7 @@ std::shared_ptr<Inventory> Hud::openInventory(
|
||||
inv = level.inventories->createVirtual(secondInvView->getSlotsCount());
|
||||
}
|
||||
secondInvView->bind(inv, &content);
|
||||
add(HudElement(hud_element_mode::inventory_bound, doc, secondUI, false));
|
||||
add(HudElement(HudElementMode::INVENTORY, doc, secondUI, false));
|
||||
scripting::on_inventory_open(&player, *inv);
|
||||
return inv;
|
||||
}
|
||||
@ -436,7 +436,7 @@ void Hud::openInventory(
|
||||
blockUI->bind(blockinv, &content);
|
||||
blockPos = block;
|
||||
currentblockid = chunks.require(block.x, block.y, block.z).id;
|
||||
add(HudElement(hud_element_mode::inventory_bound, doc, blockUI, false));
|
||||
add(HudElement(HudElementMode::INVENTORY, doc, blockUI, false));
|
||||
|
||||
scripting::on_inventory_open(&player, *blockinv);
|
||||
}
|
||||
@ -468,8 +468,7 @@ void Hud::showOverlay(
|
||||
showExchangeSlot();
|
||||
inventoryOpen = true;
|
||||
}
|
||||
add(HudElement(hud_element_mode::inventory_bound, doc, secondUI, false),
|
||||
args);
|
||||
add(HudElement(HudElementMode::INVENTORY, doc, secondUI, false), args);
|
||||
}
|
||||
|
||||
void Hud::openPermanent(UiDocument* doc) {
|
||||
@ -480,7 +479,7 @@ void Hud::openPermanent(UiDocument* doc) {
|
||||
if (invview) {
|
||||
invview->bind(player.getInventory(), &frontend.getLevel().content);
|
||||
}
|
||||
add(HudElement(hud_element_mode::permanent, doc, doc->getRoot(), false));
|
||||
add(HudElement(HudElementMode::PERMANENT, doc, doc->getRoot(), false));
|
||||
}
|
||||
|
||||
void Hud::dropExchangeSlot() {
|
||||
@ -494,12 +493,12 @@ void Hud::dropExchangeSlot() {
|
||||
|
||||
auto indices = frontend.getLevel().content.getIndices();
|
||||
if (auto invView = std::dynamic_pointer_cast<InventoryView>(blockUI)) {
|
||||
invView->getInventory()->move(stack, indices);
|
||||
invView->getInventory()->move(stack, *indices);
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
player.getInventory()->move(stack, indices);
|
||||
player.getInventory()->move(stack, *indices);
|
||||
if (!stack.isEmpty()) {
|
||||
logger.warning() << "discard item [" << stack.getItemId() << ":"
|
||||
<< stack.getCount();
|
||||
|
||||
@ -30,26 +30,26 @@ namespace gui {
|
||||
class SlotView;
|
||||
}
|
||||
|
||||
enum class hud_element_mode {
|
||||
enum class HudElementMode {
|
||||
// element is hidden if menu or inventory open
|
||||
ingame,
|
||||
INGAME,
|
||||
// element is visible if hud is visible
|
||||
permanent,
|
||||
PERMANENT,
|
||||
// element is visible in inventory mode
|
||||
inventory_any,
|
||||
INVENTORY_ANY,
|
||||
// element will be removed on inventory close
|
||||
inventory_bound
|
||||
INVENTORY
|
||||
};
|
||||
|
||||
class HudElement {
|
||||
hud_element_mode mode;
|
||||
HudElementMode mode;
|
||||
UiDocument* document;
|
||||
std::shared_ptr<gui::UINode> node;
|
||||
|
||||
bool debug;
|
||||
bool removed = false;
|
||||
public:
|
||||
HudElement(hud_element_mode mode, UiDocument* document, std::shared_ptr<gui::UINode> node, bool debug);
|
||||
HudElement(HudElementMode mode, UiDocument* document, std::shared_ptr<gui::UINode> node, bool debug);
|
||||
|
||||
void update(bool pause, bool inventoryOpen, bool debug);
|
||||
|
||||
@ -57,7 +57,7 @@ public:
|
||||
std::shared_ptr<gui::UINode> getNode() const;
|
||||
|
||||
bool isInventoryBound() const {
|
||||
return mode == hud_element_mode::inventory_bound;
|
||||
return mode == HudElementMode::INVENTORY;
|
||||
}
|
||||
|
||||
void setRemoved() {
|
||||
|
||||
@ -48,10 +48,15 @@ public:
|
||||
void sprite(float x, float y, float w, float h, float skew, int atlasRes, int index, glm::vec4 tint);
|
||||
void point(float x, float y, float r, float g, float b, float a);
|
||||
|
||||
inline void setColor(glm::vec4 color) {
|
||||
void setColor(glm::vec4 color) {
|
||||
this->color = color;
|
||||
}
|
||||
inline glm::vec4 getColor() const {
|
||||
|
||||
void resetColor() {
|
||||
this->color = glm::vec4(1.0f);
|
||||
}
|
||||
|
||||
glm::vec4 getColor() const {
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#include "items/Inventories.hpp"
|
||||
#include "items/Inventory.hpp"
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "items/ItemStack.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "maths/voxmaths.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
@ -115,26 +114,73 @@ SlotView::SlotView(
|
||||
setTooltipDelay(0.0f);
|
||||
}
|
||||
|
||||
void SlotView::refreshTooltip(const ItemStack& stack, const ItemDef& item) {
|
||||
itemid_t itemid = stack.getItemId();
|
||||
if (itemid == cache.stack.getItemId()) {
|
||||
return;
|
||||
}
|
||||
if (itemid) {
|
||||
tooltip = util::pascal_case(
|
||||
langs::get(util::str2wstr_utf8(item.caption))
|
||||
);
|
||||
} else {
|
||||
tooltip.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SlotView::drawItemIcon(
|
||||
Batch2D& batch,
|
||||
const ItemStack& stack,
|
||||
const ItemDef& item,
|
||||
const Assets& assets,
|
||||
const glm::vec4& tint,
|
||||
const glm::vec2& pos
|
||||
) {
|
||||
const int SLOT_SIZE = InventoryView::SLOT_SIZE;
|
||||
const auto& previews = assets.require<Atlas>("block-previews");
|
||||
batch.setColor(glm::vec4(1.0f));
|
||||
switch (item.iconType) {
|
||||
case ItemIconType::NONE:
|
||||
break;
|
||||
case ItemIconType::BLOCK: {
|
||||
const Block& block = content->blocks.require(item.icon);
|
||||
batch.texture(previews.getTexture());
|
||||
|
||||
UVRegion region = previews.get(block.name);
|
||||
batch.rect(
|
||||
pos.x, pos.y, SLOT_SIZE, SLOT_SIZE,
|
||||
0, 0, 0, region, false, true, tint
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ItemIconType::SPRITE: {
|
||||
auto textureRegion =
|
||||
util::get_texture_region(assets, item.icon, "blocks:notfound");
|
||||
|
||||
batch.texture(textureRegion.texture);
|
||||
batch.rect(
|
||||
pos.x, pos.y, SLOT_SIZE, SLOT_SIZE,
|
||||
0, 0, 0, textureRegion.region, false, true, tint
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SlotView::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
if (bound == nullptr) {
|
||||
return;
|
||||
}
|
||||
itemid_t itemid = bound->getItemId();
|
||||
if (itemid != prevItem) {
|
||||
if (itemid) {
|
||||
auto& def = content->getIndices()->items.require(itemid);
|
||||
tooltip = util::pascal_case(
|
||||
langs::get(util::str2wstr_utf8(def.caption))
|
||||
);
|
||||
} else {
|
||||
tooltip.clear();
|
||||
}
|
||||
}
|
||||
prevItem = itemid;
|
||||
|
||||
const int slotSize = InventoryView::SLOT_SIZE;
|
||||
|
||||
const auto& indices = *content->getIndices();
|
||||
const ItemStack& stack = *bound;
|
||||
const ItemDef& item = indices.items.require(stack.getItemId());
|
||||
|
||||
if (cache.stack.getCount() != stack.getCount()) {
|
||||
cache.countStr = std::to_wstring(stack.getCount());
|
||||
}
|
||||
refreshTooltip(stack, item);
|
||||
cache.stack.set(ItemStack(stack.getItemId(), stack.getCount()));
|
||||
|
||||
glm::vec4 tint(1, 1, 1, isEnabled() ? 1 : 0.5f);
|
||||
glm::vec2 pos = calcPos();
|
||||
glm::vec4 color = getColor();
|
||||
@ -144,59 +190,84 @@ void SlotView::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
color = glm::vec4(1, 1, 1, 0.2f);
|
||||
}
|
||||
|
||||
auto batch = pctx.getBatch2D();
|
||||
batch->setColor(color);
|
||||
auto& batch = *pctx.getBatch2D();
|
||||
|
||||
if (color.a > 0.0) {
|
||||
batch->texture(nullptr);
|
||||
batch.setColor(color);
|
||||
batch.texture(nullptr);
|
||||
|
||||
const int size = InventoryView::SLOT_SIZE;
|
||||
if (highlighted) {
|
||||
batch->rect(pos.x-4, pos.y-4, slotSize+8, slotSize+8);
|
||||
batch.rect(pos.x - 4, pos.y - 4, size + 8, size + 8);
|
||||
} else {
|
||||
batch->rect(pos.x, pos.y, slotSize, slotSize);
|
||||
}
|
||||
}
|
||||
|
||||
batch->setColor(glm::vec4(1.0f));
|
||||
|
||||
auto previews = assets.get<Atlas>("block-previews");
|
||||
auto indices = content->getIndices();
|
||||
|
||||
auto& item = indices->items.require(stack.getItemId());
|
||||
switch (item.iconType) {
|
||||
case ItemIconType::NONE:
|
||||
break;
|
||||
case ItemIconType::BLOCK: {
|
||||
const Block& cblock = content->blocks.require(item.icon);
|
||||
batch->texture(previews->getTexture());
|
||||
|
||||
UVRegion region = previews->get(cblock.name);
|
||||
batch->rect(
|
||||
pos.x, pos.y, slotSize, slotSize,
|
||||
0, 0, 0, region, false, true, tint);
|
||||
break;
|
||||
}
|
||||
case ItemIconType::SPRITE: {
|
||||
auto textureRegion =
|
||||
util::get_texture_region(assets, item.icon, "blocks:notfound");
|
||||
|
||||
batch->texture(textureRegion.texture);
|
||||
batch->rect(
|
||||
pos.x, pos.y, slotSize, slotSize,
|
||||
0, 0, 0, textureRegion.region, false, true, tint);
|
||||
break;
|
||||
batch.rect(pos.x, pos.y, size, size);
|
||||
}
|
||||
}
|
||||
|
||||
drawItemIcon(batch, stack, item, assets, tint, pos);
|
||||
|
||||
if (stack.getCount() > 1 || stack.getFields() != nullptr) {
|
||||
const auto& font = assets.require<Font>("normal");
|
||||
drawItemInfo(batch, stack, item, font, pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_shaded_text(
|
||||
Batch2D& batch, const Font& font, const std::wstring& text, int x, int y
|
||||
) {
|
||||
batch.setColor({0, 0, 0, 1.0f});
|
||||
font.draw(batch, text, x + 1, y + 1, nullptr, 0);
|
||||
batch.resetColor();
|
||||
font.draw(batch, text, x, y, nullptr, 0);
|
||||
}
|
||||
|
||||
void SlotView::drawItemInfo(
|
||||
Batch2D& batch,
|
||||
const ItemStack& stack,
|
||||
const ItemDef& item,
|
||||
const Font& font,
|
||||
const glm::vec2& pos
|
||||
) {
|
||||
const int SLOT_SIZE = InventoryView::SLOT_SIZE;
|
||||
if (stack.getCount() > 1) {
|
||||
auto font = assets.get<Font>("normal");
|
||||
std::wstring text = std::to_wstring(stack.getCount());
|
||||
const auto& countStr = cache.countStr;
|
||||
int x = pos.x + SLOT_SIZE - countStr.length() * 8;
|
||||
int y = pos.y + SLOT_SIZE - 16;
|
||||
draw_shaded_text(batch, font, countStr, x, y);
|
||||
}
|
||||
|
||||
int x = pos.x+slotSize-text.length()*8;
|
||||
int y = pos.y+slotSize-16;
|
||||
|
||||
batch->setColor({0, 0, 0, 1.0f});
|
||||
font->draw(*batch, text, x+1, y+1, nullptr, 0);
|
||||
batch->setColor(glm::vec4(1.0f));
|
||||
font->draw(*batch, text, x, y, nullptr, 0);
|
||||
auto usesPtr = stack.getField("uses");
|
||||
if (usesPtr == nullptr || !usesPtr->isInteger()) {
|
||||
return;
|
||||
}
|
||||
int16_t uses = usesPtr->asInteger();
|
||||
if (uses < 0) {
|
||||
return;
|
||||
}
|
||||
switch (item.usesDisplay) {
|
||||
case ItemUsesDisplay::NONE:
|
||||
break;
|
||||
case ItemUsesDisplay::RELATION:
|
||||
draw_shaded_text(
|
||||
batch, font, std::to_wstring(item.uses), pos.x - 3, pos.y + 9
|
||||
);
|
||||
[[fallthrough]];
|
||||
case ItemUsesDisplay::NUMBER:
|
||||
draw_shaded_text(
|
||||
batch, font, std::to_wstring(uses), pos.x - 3, pos.y - 3
|
||||
);
|
||||
break;
|
||||
case ItemUsesDisplay::VBAR: {
|
||||
batch.untexture();
|
||||
batch.setColor({0, 0, 0, 0.75f});
|
||||
batch.rect(pos.x - 2, pos.y - 2, 6, SLOT_SIZE + 4);
|
||||
float t = static_cast<float>(uses) / item.uses;
|
||||
|
||||
int height = SLOT_SIZE * t;
|
||||
batch.setColor({(1.0f - t * 0.8f), 0.4f, t * 0.8f + 0.2f, 1.0f});
|
||||
batch.rect(pos.x, pos.y + SLOT_SIZE - height, 2, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +290,7 @@ void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) {
|
||||
return;
|
||||
}
|
||||
if (!layout.itemSource && stack.accepts(grabbed) && layout.placing) {
|
||||
stack.move(grabbed, content->getIndices());
|
||||
stack.move(grabbed, *content->getIndices());
|
||||
} else {
|
||||
if (layout.itemSource) {
|
||||
if (grabbed.isEmpty()) {
|
||||
@ -249,10 +320,11 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
|
||||
return;
|
||||
if (grabbed.isEmpty()) {
|
||||
if (!stack.isEmpty() && layout.taking) {
|
||||
grabbed.set(stack);
|
||||
grabbed.set(std::move(stack));
|
||||
int halfremain = stack.getCount() / 2;
|
||||
grabbed.setCount(stack.getCount() - halfremain);
|
||||
stack.setCount(halfremain);
|
||||
// reset all data in the origin slot
|
||||
stack = ItemStack(stack.getItemId(), halfremain);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -261,9 +333,14 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
|
||||
return;
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
stack.set(grabbed);
|
||||
itemcount_t count = grabbed.getCount();
|
||||
stack.set(std::move(grabbed));
|
||||
stack.setCount(1);
|
||||
grabbed.setCount(grabbed.getCount() - 1);
|
||||
if (count == 1) {
|
||||
grabbed = {};
|
||||
} else {
|
||||
grabbed = ItemStack(stack.getItemId(), count - 1);
|
||||
}
|
||||
} else if (stack.accepts(grabbed) && stack.getCount() < stackDef.stackSize) {
|
||||
stack.setCount(stack.getCount() + 1);
|
||||
grabbed.setCount(grabbed.getCount() - 1);
|
||||
|
||||
@ -4,15 +4,18 @@
|
||||
#include "Container.hpp"
|
||||
#include "typedefs.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "items/ItemStack.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Font;
|
||||
class Assets;
|
||||
class ItemDef;
|
||||
class Batch2D;
|
||||
class DrawContext;
|
||||
class Content;
|
||||
class ItemStack;
|
||||
class ContentIndices;
|
||||
class LevelFrontend;
|
||||
class Inventory;
|
||||
@ -49,6 +52,11 @@ namespace gui {
|
||||
};
|
||||
|
||||
class SlotView : public gui::UINode {
|
||||
struct {
|
||||
ItemStack stack {};
|
||||
std::wstring countStr;
|
||||
} cache;
|
||||
|
||||
const Content* content = nullptr;
|
||||
SlotLayout layout;
|
||||
bool highlighted = false;
|
||||
@ -56,11 +64,27 @@ namespace gui {
|
||||
int64_t inventoryid = 0;
|
||||
ItemStack* bound = nullptr;
|
||||
|
||||
std::wstring tooltip;
|
||||
itemid_t prevItem = 0;
|
||||
|
||||
void performLeftClick(ItemStack& stack, ItemStack& grabbed);
|
||||
void performRightClick(ItemStack& stack, ItemStack& grabbed);
|
||||
|
||||
void drawItemIcon(
|
||||
Batch2D& batch,
|
||||
const ItemStack& stack,
|
||||
const ItemDef& item,
|
||||
const Assets& assets,
|
||||
const glm::vec4& tint,
|
||||
const glm::vec2& pos
|
||||
);
|
||||
|
||||
void drawItemInfo(
|
||||
Batch2D& batch,
|
||||
const ItemStack& stack,
|
||||
const ItemDef& item,
|
||||
const Font& font,
|
||||
const glm::vec2& pos
|
||||
);
|
||||
|
||||
void refreshTooltip(const ItemStack& stack, const ItemDef& item);
|
||||
public:
|
||||
SlotView(SlotLayout layout);
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ size_t Inventory::findSlotByItem(
|
||||
}
|
||||
|
||||
void Inventory::move(
|
||||
ItemStack& item, const ContentIndices* indices, size_t begin, size_t end
|
||||
ItemStack& item, const ContentIndices& indices, size_t begin, size_t end
|
||||
) {
|
||||
end = std::min(slots.size(), end);
|
||||
for (size_t i = begin; i < end && !item.isEmpty(); i++) {
|
||||
@ -72,8 +72,12 @@ void Inventory::deserialize(const dv::value& src) {
|
||||
if (item.has("count")){
|
||||
count = item["count"].asInteger();
|
||||
}
|
||||
dv::value fields = nullptr;
|
||||
if (item.has("fields")) {
|
||||
fields = item["fields"];
|
||||
}
|
||||
auto& slot = slots[i];
|
||||
slot.set(ItemStack(id, count));
|
||||
slot.set(ItemStack(id, count, fields));
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,6 +96,10 @@ dv::value Inventory::serialize() const {
|
||||
if (count) {
|
||||
slotmap["count"] = count;
|
||||
}
|
||||
const auto& fields = item.getFields();
|
||||
if (fields != nullptr) {
|
||||
slotmap["fields"] = fields;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@ -110,5 +118,3 @@ void Inventory::convert(dv::value& data, const ContentReport* report) {
|
||||
inventory.convert(report);
|
||||
data = inventory.serialize();
|
||||
}
|
||||
|
||||
const size_t Inventory::npos = -1;
|
||||
|
||||
@ -26,13 +26,9 @@ public:
|
||||
itemid_t id, size_t begin = 0, size_t end = -1, size_t minCount = 1
|
||||
);
|
||||
|
||||
inline size_t size() const {
|
||||
return slots.size();
|
||||
}
|
||||
|
||||
void move(
|
||||
ItemStack& item,
|
||||
const ContentIndices* indices,
|
||||
const ContentIndices& indices,
|
||||
size_t begin = 0,
|
||||
size_t end = -1
|
||||
);
|
||||
@ -46,17 +42,21 @@ public:
|
||||
void convert(const ContentReport* report);
|
||||
static void convert(dv::value& data, const ContentReport* report);
|
||||
|
||||
inline void setId(int64_t id) {
|
||||
size_t size() const {
|
||||
return slots.size();
|
||||
}
|
||||
|
||||
void setId(int64_t id) {
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
inline int64_t getId() const {
|
||||
int64_t getId() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
inline bool isVirtual() const {
|
||||
bool isVirtual() const {
|
||||
return id < 0;
|
||||
}
|
||||
|
||||
static const size_t npos;
|
||||
static constexpr size_t npos = -1;
|
||||
};
|
||||
|
||||
@ -15,4 +15,6 @@ void ItemDef::cloneTo(ItemDef& dst) {
|
||||
dst.placingBlock = placingBlock;
|
||||
dst.scriptName = scriptName;
|
||||
dst.modelName = modelName;
|
||||
dst.uses = uses;
|
||||
dst.usesDisplay = usesDisplay;
|
||||
}
|
||||
|
||||
@ -19,6 +19,14 @@ enum class ItemIconType {
|
||||
BLOCK, // block preview: icon is string block id
|
||||
};
|
||||
|
||||
enum class ItemUsesDisplay {
|
||||
NONE, // uses count is not displayed
|
||||
NUMBER, // uses count is displayed as number
|
||||
RELATION, // uses count is displayed as `remain/default` relation
|
||||
VBAR, // uses count is displayed as vertical bar without counter
|
||||
DEFAULT = VBAR,
|
||||
};
|
||||
|
||||
struct ItemDef {
|
||||
/// @brief Item string id (with prefix included)
|
||||
std::string const name;
|
||||
@ -28,10 +36,21 @@ struct ItemDef {
|
||||
|
||||
dv::value properties = nullptr;
|
||||
|
||||
/// @brief Item max stack size
|
||||
itemcount_t stackSize = 64;
|
||||
|
||||
/// @brief Item is generated for other content unit (like block)
|
||||
bool generated = false;
|
||||
|
||||
/// @brief Item light emission [r, g, b] where r,g,b in range [0..15]
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
/// @brief Default item uses count
|
||||
int16_t uses = -1;
|
||||
|
||||
/// @brief Item uses count display mode
|
||||
ItemUsesDisplay usesDisplay = ItemUsesDisplay::DEFAULT;
|
||||
|
||||
ItemIconType iconType = ItemIconType::SPRITE;
|
||||
std::string icon = "blocks:notfound";
|
||||
|
||||
|
||||
@ -3,16 +3,18 @@
|
||||
#include "content/Content.hpp"
|
||||
#include "ItemDef.hpp"
|
||||
|
||||
ItemStack::ItemStack() : item(ITEM_EMPTY), count(0) {
|
||||
}
|
||||
|
||||
ItemStack::ItemStack(itemid_t item, itemcount_t count)
|
||||
: item(item), count(count) {
|
||||
ItemStack::ItemStack(itemid_t item, itemcount_t count, dv::value data)
|
||||
: item(item), count(count), fields(std::move(data)) {
|
||||
}
|
||||
|
||||
void ItemStack::set(const ItemStack& item) {
|
||||
set(ItemStack(item));
|
||||
}
|
||||
|
||||
void ItemStack::set(ItemStack&& item) {
|
||||
this->item = item.item;
|
||||
this->count = item.count;
|
||||
this->fields = std::move(item.fields);
|
||||
if (count == 0) {
|
||||
this->item = 0;
|
||||
}
|
||||
@ -25,14 +27,14 @@ bool ItemStack::accepts(const ItemStack& other) const {
|
||||
if (isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return item == other.getItemId();
|
||||
return item == other.getItemId() && other.fields == nullptr;
|
||||
}
|
||||
|
||||
void ItemStack::move(ItemStack& item, const ContentIndices* indices) {
|
||||
auto& def = indices->items.require(item.getItemId());
|
||||
int count = std::min(item.count, def.stackSize - this->count);
|
||||
void ItemStack::move(ItemStack& item, const ContentIndices& indices) {
|
||||
auto& def = indices.items.require(item.getItemId());
|
||||
itemcount_t count = std::min(item.count, def.stackSize - this->count);
|
||||
if (isEmpty()) {
|
||||
set(ItemStack(item.getItemId(), count));
|
||||
set(ItemStack(item.getItemId(), count, std::move(item.fields)));
|
||||
} else {
|
||||
setCount(this->count + count);
|
||||
}
|
||||
@ -42,6 +44,30 @@ void ItemStack::move(ItemStack& item, const ContentIndices* indices) {
|
||||
void ItemStack::setCount(itemcount_t count) {
|
||||
this->count = count;
|
||||
if (count == 0) {
|
||||
item = 0;
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStack::setField(std::string_view name, dv::value value) {
|
||||
if (fields == nullptr) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
fields = dv::object();
|
||||
}
|
||||
if (value == nullptr) {
|
||||
fields.erase(std::string(name));
|
||||
if (fields.empty()) {
|
||||
fields = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
fields[std::string(name)] = std::move(value);
|
||||
}
|
||||
|
||||
dv::value* ItemStack::getField(const std::string& name) const {
|
||||
if (fields == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return fields.at(name).ptr;
|
||||
}
|
||||
|
||||
@ -2,36 +2,60 @@
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "typedefs.hpp"
|
||||
#include "data/dv.hpp"
|
||||
|
||||
class ContentIndices;
|
||||
|
||||
class ItemStack {
|
||||
itemid_t item;
|
||||
itemcount_t count;
|
||||
itemid_t item = ITEM_EMPTY;
|
||||
itemcount_t count = 0;
|
||||
dv::value fields = nullptr;
|
||||
public:
|
||||
ItemStack();
|
||||
ItemStack() = default;
|
||||
|
||||
ItemStack(itemid_t item, itemcount_t count);
|
||||
ItemStack(itemid_t item, itemcount_t count, dv::value data=nullptr);
|
||||
|
||||
void set(const ItemStack& item);
|
||||
void set(ItemStack&& item);
|
||||
void setCount(itemcount_t count);
|
||||
|
||||
bool accepts(const ItemStack& item) const;
|
||||
void move(ItemStack& item, const ContentIndices* indices);
|
||||
/// @brief Set a field in the item stack data.
|
||||
void setField(std::string_view name, dv::value value);
|
||||
|
||||
inline void clear() {
|
||||
/// @brief Get a field from the item stack data.
|
||||
/// @param name field name
|
||||
/// @return value pointer or nullptr if the field does not exist.
|
||||
dv::value* getField(const std::string& name) const;
|
||||
|
||||
bool accepts(const ItemStack& item) const;
|
||||
|
||||
/// @brief Move items from one stack to another.
|
||||
/// If the target stack is completely filled, the source stack will be reduced.
|
||||
/// @param item source stack
|
||||
/// @param indices content indices
|
||||
void move(ItemStack& item, const ContentIndices& indices);
|
||||
|
||||
void clear() {
|
||||
set(ItemStack(0, 0));
|
||||
}
|
||||
|
||||
inline bool isEmpty() const {
|
||||
bool isEmpty() const {
|
||||
return item == ITEM_EMPTY;
|
||||
}
|
||||
|
||||
inline itemid_t getItemId() const {
|
||||
itemid_t getItemId() const {
|
||||
return item;
|
||||
}
|
||||
|
||||
inline itemcount_t getCount() const {
|
||||
itemcount_t getCount() const {
|
||||
return count;
|
||||
}
|
||||
|
||||
const dv::value& getFields() const {
|
||||
return fields;
|
||||
}
|
||||
|
||||
bool hasFields() const {
|
||||
return fields != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@ -7,68 +7,73 @@
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static void validate_itemid(itemid_t id) {
|
||||
if (id >= indices->items.count()) {
|
||||
throw std::runtime_error("invalid item id");
|
||||
namespace {
|
||||
void validate_itemid(itemid_t id) {
|
||||
if (id >= indices->items.count()) {
|
||||
throw std::runtime_error("invalid item id");
|
||||
}
|
||||
}
|
||||
|
||||
Inventory& get_inventory(int64_t id) {
|
||||
auto inv = level->inventories->get(id);
|
||||
if (inv == nullptr) {
|
||||
throw std::runtime_error("inventory not found: " + std::to_string(id));
|
||||
}
|
||||
return *inv;
|
||||
}
|
||||
|
||||
Inventory& get_inventory(int64_t id, int arg) {
|
||||
auto inv = level->inventories->get(id);
|
||||
if (inv == nullptr) {
|
||||
throw std::runtime_error(
|
||||
"inventory not found: " + std::to_string(id) + " argument " +
|
||||
std::to_string(arg)
|
||||
);
|
||||
}
|
||||
return *inv;
|
||||
}
|
||||
|
||||
void validate_slotid(int slotid, const Inventory& inv) {
|
||||
if (static_cast<size_t>(slotid) >= inv.size()) {
|
||||
throw std::runtime_error(
|
||||
"slot index is out of range [0..inventory.size(invid)]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
using SlotFunc = int(lua::State*, ItemStack&);
|
||||
|
||||
template <SlotFunc func>
|
||||
int wrap_slot(lua::State* L) {
|
||||
auto invid = lua::tointeger(L, 1);
|
||||
auto slotid = lua::tointeger(L, 2);
|
||||
auto& inv = get_inventory(invid);
|
||||
validate_slotid(slotid, inv);
|
||||
auto& item = inv.getSlot(slotid);
|
||||
return func(L, item);
|
||||
}
|
||||
}
|
||||
|
||||
static Inventory& get_inventory(int64_t id) {
|
||||
auto inv = level->inventories->get(id);
|
||||
if (inv == nullptr) {
|
||||
throw std::runtime_error("inventory not found: " + std::to_string(id));
|
||||
}
|
||||
return *inv;
|
||||
}
|
||||
|
||||
static Inventory& get_inventory(int64_t id, int arg) {
|
||||
auto inv = level->inventories->get(id);
|
||||
if (inv == nullptr) {
|
||||
throw std::runtime_error(
|
||||
"inventory not found: " + std::to_string(id) + " argument " +
|
||||
std::to_string(arg)
|
||||
);
|
||||
}
|
||||
return *inv;
|
||||
}
|
||||
|
||||
static void validate_slotid(int slotid, const Inventory& inv) {
|
||||
if (static_cast<size_t>(slotid) >= inv.size()) {
|
||||
throw std::runtime_error(
|
||||
"slot index is out of range [0..inventory.size(invid)]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static int l_get(lua::State* L) {
|
||||
auto invid = lua::tointeger(L, 1);
|
||||
auto slotid = lua::tointeger(L, 2);
|
||||
auto inv = get_inventory(invid);
|
||||
validate_slotid(slotid, inv);
|
||||
const ItemStack& item = inv.getSlot(slotid);
|
||||
static int l_get(lua::State* L, ItemStack& item) {
|
||||
lua::pushinteger(L, item.getItemId());
|
||||
lua::pushinteger(L, item.getCount());
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_set(lua::State* L) {
|
||||
auto invid = lua::tointeger(L, 1);
|
||||
auto slotid = lua::tointeger(L, 2);
|
||||
static int l_set(lua::State* L, ItemStack& item) {
|
||||
auto itemid = lua::tointeger(L, 3);
|
||||
auto count = lua::tointeger(L, 4);
|
||||
validate_itemid(itemid);
|
||||
|
||||
auto& inv = get_inventory(invid);
|
||||
|
||||
validate_slotid(slotid, inv);
|
||||
ItemStack& item = inv.getSlot(slotid);
|
||||
item.set(ItemStack(itemid, count));
|
||||
auto data = lua::tovalue(L, 5);
|
||||
if (!data.isObject() && data != nullptr) {
|
||||
throw std::runtime_error("invalid data argument type (table expected)");
|
||||
}
|
||||
item.set(ItemStack(itemid, count, std::move(data)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_size(lua::State* L) {
|
||||
auto invid = lua::tointeger(L, 1);
|
||||
auto& inv = get_inventory(invid);
|
||||
const auto& inv = get_inventory(invid);
|
||||
return lua::pushinteger(L, inv.size());
|
||||
}
|
||||
|
||||
@ -76,11 +81,16 @@ static int l_add(lua::State* L) {
|
||||
auto invid = lua::tointeger(L, 1);
|
||||
auto itemid = lua::tointeger(L, 2);
|
||||
auto count = lua::tointeger(L, 3);
|
||||
auto data = lua::tovalue(L, 4);
|
||||
|
||||
validate_itemid(itemid);
|
||||
if (!data.isObject() && data != nullptr) {
|
||||
throw std::runtime_error("invalid data argument type (table expected)");
|
||||
}
|
||||
|
||||
auto& inv = get_inventory(invid);
|
||||
ItemStack item(itemid, count);
|
||||
inv.move(item, indices);
|
||||
ItemStack item(itemid, count, std::move(data));
|
||||
inv.move(item, *indices);
|
||||
return lua::pushinteger(L, item.getCount());
|
||||
}
|
||||
|
||||
@ -144,9 +154,9 @@ static int l_move(lua::State* L) {
|
||||
auto& invB = get_inventory(invBid, 3);
|
||||
auto& slot = invA.getSlot(slotAid);
|
||||
if (slotBid == -1) {
|
||||
invB.move(slot, content->getIndices());
|
||||
invB.move(slot, *content->getIndices());
|
||||
} else {
|
||||
invB.move(slot, content->getIndices(), slotBid, slotBid + 1);
|
||||
invB.move(slot, *content->getIndices(), slotBid, slotBid + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -163,9 +173,9 @@ static int l_move_range(lua::State* L) {
|
||||
auto invB = get_inventory(invBid, 3);
|
||||
auto& slot = invA.getSlot(slotAid);
|
||||
if (slotBegin == -1) {
|
||||
invB.move(slot, content->getIndices());
|
||||
invB.move(slot, *content->getIndices());
|
||||
} else {
|
||||
invB.move(slot, content->getIndices(), slotBegin, slotEnd);
|
||||
invB.move(slot, *content->getIndices(), slotBegin, slotEnd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -184,9 +194,38 @@ static int l_find_by_item(lua::State* L) {
|
||||
return lua::pushinteger(L, index);
|
||||
}
|
||||
|
||||
static int l_get_data(lua::State* L, ItemStack& stack) {
|
||||
auto key = lua::require_string(L, 3);
|
||||
auto value = stack.getField(key);
|
||||
if (value == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return lua::pushvalue(L, *value);
|
||||
}
|
||||
|
||||
static int l_get_all_data(lua::State* L, ItemStack& stack) {
|
||||
return lua::pushvalue(L, stack.getFields());
|
||||
}
|
||||
|
||||
static int l_has_data(lua::State* L, ItemStack& stack) {
|
||||
auto key = lua::tostring(L, 3);
|
||||
if (key == nullptr) {
|
||||
return lua::pushboolean(L, stack.hasFields());
|
||||
}
|
||||
return lua::pushboolean(L, stack.getField(key) != nullptr);
|
||||
}
|
||||
|
||||
static int l_set_data(lua::State* L, ItemStack& stack) {
|
||||
auto key = lua::require_string(L, 3);
|
||||
auto value = lua::tovalue(L, 4);
|
||||
auto& fields = stack.getFields();
|
||||
stack.setField(key, std::move(value));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg inventorylib[] = {
|
||||
{"get", lua::wrap<l_get>},
|
||||
{"set", lua::wrap<l_set>},
|
||||
{"get", wrap_slot<l_get>},
|
||||
{"set", wrap_slot<l_set>},
|
||||
{"size", lua::wrap<l_size>},
|
||||
{"add", lua::wrap<l_add>},
|
||||
{"move", lua::wrap<l_move>},
|
||||
@ -195,7 +234,12 @@ const luaL_Reg inventorylib[] = {
|
||||
{"get_block", lua::wrap<l_get_block>},
|
||||
{"bind_block", lua::wrap<l_bind_block>},
|
||||
{"unbind_block", lua::wrap<l_unbind_block>},
|
||||
{"get_data", wrap_slot<l_get_data>},
|
||||
{"set_data", wrap_slot<l_set_data>},
|
||||
{"get_all_data", wrap_slot<l_get_all_data>},
|
||||
{"has_data", wrap_slot<l_has_data>},
|
||||
{"create", lua::wrap<l_create>},
|
||||
{"remove", lua::wrap<l_remove>},
|
||||
{"clone", lua::wrap<l_clone>},
|
||||
{NULL, NULL}};
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -80,6 +80,13 @@ static int l_emission(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_uses(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
return lua::pushinteger(L, def->uses);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg itemlib[] = {
|
||||
{"index", lua::wrap<l_index>},
|
||||
{"name", lua::wrap<l_name>},
|
||||
@ -90,4 +97,6 @@ const luaL_Reg itemlib[] = {
|
||||
{"placing_block", lua::wrap<l_placing_block>},
|
||||
{"model_name", lua::wrap<l_model_name>},
|
||||
{"emission", lua::wrap<l_emission>},
|
||||
{NULL, NULL}};
|
||||
{"uses", lua::wrap<l_uses>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user