Skip to content

Commit f4b966d

Browse files
committed
Add meta item image override functions
1 parent 298a6c5 commit f4b966d

File tree

13 files changed

+343
-8
lines changed

13 files changed

+343
-8
lines changed

doc/lua_api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8252,6 +8252,13 @@ Can be obtained via `item:get_meta()`.
82528252
* Overrides the item's wear bar parameters (see "Wear Bar Color" section)
82538253
* A nil value will clear the override data and restore the original
82548254
behavior.
8255+
* `set_inventory_image(<Item image definition>)`
8256+
* `set_inventory_overlay(<Item image definition>)`
8257+
* `set_wield_image(<Item image definition>)`
8258+
* `set_wield_overlay(<Item image definition>)`
8259+
* Overrides the item image definitions
8260+
* Takes precedence over the overwritten image names from [Item Metadata](#item-metadata)
8261+
* A nil value will clear the override data and restore the original behavior.
82558262

82568263
`MetaDataRef`
82578264
-------------

games/devtest/mods/testitems/init.lua

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,85 @@ core.register_craftitem("testitems:wield_image_animation_overlay", {
226226
wield_overlay = animated_overlay,
227227
color = "#ff0000",
228228
})
229+
230+
local function animated_image_accelerated(speed)
231+
local image = table.copy(animated_image)
232+
image.animation.length = image.animation.length * speed
233+
return image
234+
end
235+
236+
local function animated_overlay_accelerated(speed)
237+
local image = table.copy(animated_overlay)
238+
image.animation.frame_length = image.animation.frame_length * speed
239+
return image
240+
end
241+
242+
local function update_animation(meta, mode, speed, name)
243+
local msg
244+
local speed_factor = 1/(speed+1)
245+
if mode == 0 then
246+
meta:set_wield_overlay()
247+
msg = S"Not animated"
248+
elseif mode == 1 then
249+
meta:set_inventory_image(animated_image_accelerated(speed_factor))
250+
msg = S"Inventory image animated"
251+
elseif mode == 2 then
252+
meta:set_inventory_image()
253+
meta:set_inventory_overlay(animated_overlay_accelerated(speed_factor))
254+
msg = S"Inventory overlay animated"
255+
elseif mode == 3 then
256+
meta:set_inventory_overlay()
257+
meta:set_wield_image(animated_image_accelerated(speed_factor))
258+
msg = S"Wield image animated"
259+
else
260+
meta:set_wield_image()
261+
meta:set_wield_overlay(animated_overlay_accelerated(speed_factor))
262+
msg = S"Wield overlay animated"
263+
end
264+
core.chat_send_player(name, msg .. S", speed " .. speed)
265+
end
266+
267+
local function toggle_red_string_meta_inventory_image(itemstack)
268+
local meta = itemstack:get_meta()
269+
local image = meta:get_string("inventory_image") == "" and
270+
"testnodes_anim.png^[invert:rgb^[verticalframe:4:0^[multiply:#ff0000" or ""
271+
local overlay = meta:get_string("inventory_overlay") == "" and
272+
"testitems_animation_overlay.png^[verticalframe:4:0^[multiply:#ff0000" or ""
273+
meta:set_string("inventory_image", image)
274+
meta:set_string("inventory_overlay", overlay)
275+
meta:set_string("wield_image", image)
276+
meta:set_string("wield_overlay", overlay)
277+
return itemstack
278+
end
279+
280+
core.register_craftitem("testitems:inventory_image_animation_meta", {
281+
description = S("Animated Meta Test Item").."\n"..
282+
S("Left click to cycle through modes").."\n"..
283+
S("Hold sneak and left click to change speed").."\n"..
284+
S("Right click to toggle red string meta inventory image fields"),
285+
inventory_image = "testnodes_anim.png^[invert:rgb^[verticalframe:4:0",
286+
inventory_overlay = "testitems_animation_overlay.png^[verticalframe:4:0",
287+
wield_image = "testnodes_anim.png^[invert:rgb^[verticalframe:4:0",
288+
wield_overlay = "testitems_animation_overlay.png^[verticalframe:4:0",
289+
on_use = function(itemstack, user, pointed_thing)
290+
if not core.is_player(user) then
291+
return
292+
end
293+
local name = user:get_player_name()
294+
local meta = itemstack:get_meta()
295+
local speed = meta:get_int("speed")
296+
local mode = meta:get_int("mode")
297+
298+
if user:get_player_control().sneak then
299+
speed = (speed + 1) % 4
300+
meta:set_int("speed", speed)
301+
else
302+
mode = (mode + 1) % 5
303+
meta:set_int("mode", mode)
304+
end
305+
update_animation(meta, mode, speed, name)
306+
return itemstack
307+
end,
308+
on_place = toggle_red_string_meta_inventory_image,
309+
on_secondary_use = toggle_red_string_meta_inventory_image,
310+
})

src/client/item_visuals_manager.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,16 @@ ItemVisualsManager::ItemVisuals *ItemVisualsManager::createItemVisuals( const It
4545
ItemImageDef inventory_image = item.getInventoryImage(idef);
4646
ItemImageDef inventory_overlay = item.getInventoryOverlay(idef);
4747

48-
// Key only consists of item name + image name,
49-
// because animation currently cannot be overridden by meta
5048
std::ostringstream os(def.name);
51-
if (!inventory_image.name.empty())
52-
os << "/" << inventory_image.name;
53-
if (!inventory_overlay.name.empty())
54-
os << ":" << inventory_overlay.name;
49+
if (!inventory_image.name.empty()) {
50+
os << "/";
51+
inventory_image.serializeJson(os);
52+
}
53+
if (!inventory_overlay.name.empty()) {
54+
os << ":";
55+
inventory_overlay.serializeJson(os);
56+
}
57+
5558
std::string cache_key = os.str();
5659

5760

src/inventory.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ std::string ItemStack::getShortDescription(const IItemDefManager *itemdef) const
258258

259259
ItemImageDef ItemStack::getInventoryImage(const IItemDefManager *itemdef) const
260260
{
261+
const auto &override_image = metadata.getInventoryImageOverride();
262+
if (override_image)
263+
return override_image.value();
264+
261265
ItemImageDef image = getDefinition(itemdef).inventory_image;
262266
std::string meta_image = metadata.getString("inventory_image");
263267
if (!meta_image.empty())
@@ -268,6 +272,10 @@ ItemImageDef ItemStack::getInventoryImage(const IItemDefManager *itemdef) const
268272

269273
ItemImageDef ItemStack::getInventoryOverlay(const IItemDefManager *itemdef) const
270274
{
275+
const auto &override_image = metadata.getInventoryOverlayOverride();
276+
if (override_image)
277+
return override_image.value();
278+
271279
ItemImageDef image = getDefinition(itemdef).inventory_overlay;
272280
std::string meta_image = metadata.getString("inventory_overlay");
273281
if (!meta_image.empty())
@@ -278,6 +286,10 @@ ItemImageDef ItemStack::getInventoryOverlay(const IItemDefManager *itemdef) cons
278286

279287
ItemImageDef ItemStack::getWieldImage(const IItemDefManager *itemdef) const
280288
{
289+
const auto &override_image = metadata.getWieldImageOverride();
290+
if (override_image)
291+
return override_image.value();
292+
281293
ItemImageDef image = getDefinition(itemdef).wield_image;
282294
std::string meta_image = metadata.getString("wield_image");
283295
if (!meta_image.empty())
@@ -288,6 +300,10 @@ ItemImageDef ItemStack::getWieldImage(const IItemDefManager *itemdef) const
288300

289301
ItemImageDef ItemStack::getWieldOverlay(const IItemDefManager *itemdef) const
290302
{
303+
const auto &override_image = metadata.getWieldOverlayOverride();
304+
if (override_image)
305+
return override_image.value();
306+
291307
ItemImageDef image = getDefinition(itemdef).wield_overlay;
292308
std::string meta_image = metadata.getString("wield_overlay");
293309
if (!meta_image.empty())

src/inventory.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ struct ItemStack
4141
ItemImageDef getWieldImage(const IItemDefManager *itemdef) const;
4242
ItemImageDef getWieldOverlay(const IItemDefManager *itemdef) const;
4343
v3f getWieldScale(const IItemDefManager *itemdef) const;
44+
const TileAnimationParams getInventoryImageAnimation(const IItemDefManager *itemdef) const;
45+
const TileAnimationParams getInventoryOverlayAnimation(const IItemDefManager *itemdef) const;
46+
const TileAnimationParams getWieldImageAnimation(const IItemDefManager *itemdef) const;
47+
const TileAnimationParams getWieldOverlayAnimation(const IItemDefManager *itemdef) const;
4448

4549
/*
4650
Quantity methods

src/itemdef.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "util/pointedthing.h"
1616
#include <map>
1717
#include <set>
18+
#include "convert_json.h"
19+
#include <json/json.h>
1820

1921
TouchInteraction::TouchInteraction()
2022
{
@@ -103,6 +105,29 @@ void ItemImageDef::deSerialize(std::istream &is, u16 protocol_version)
103105
animation.deSerialize(is, protocol_version);
104106
}
105107

108+
void ItemImageDef::serializeJson(std::ostream &os) const
109+
{
110+
Json::Value root;
111+
root["name"] = name;
112+
root["animation"] = animation.serializeJson();
113+
114+
fastWriteJson(root, os);
115+
}
116+
117+
std::optional<ItemImageDef> ItemImageDef::deserializeJson(std::istream &is)
118+
{
119+
Json::Value root;
120+
is >> root;
121+
if (!root.isObject() || !root["name"].isString()) {
122+
return std::nullopt;
123+
}
124+
125+
ItemImageDef def;
126+
def.name = root["name"].asString();
127+
def.animation.deserializeJson(root["animation"]);
128+
return def;
129+
}
130+
106131
/*
107132
ItemDefinition
108133
*/

src/itemdef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ struct ItemImageDef
7777

7878
void serialize(std::ostream &os, u16 protocol_version) const;
7979
void deSerialize(std::istream &is, u16 protocol_version);
80+
81+
void serializeJson(std::ostream &os) const;
82+
static std::optional<ItemImageDef> deserializeJson(std::istream &is);
8083
};
8184

8285
struct ItemDefinition

src/itemstackmetadata.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,25 @@
1919

2020
#define TOOLCAP_KEY "tool_capabilities"
2121
#define WEAR_BAR_KEY "wear_color"
22+
#define INVENTORY_IMAGE_KEY "inventory_image_def"
23+
#define INVENTORY_OVERLAY_KEY "inventory_overlay_def"
24+
#define WIELD_IMAGE_KEY "wield_image_def"
25+
#define WIELD_OVERLAY_KEY "wield_overlay_def"
2226

2327
void ItemStackMetadata::clear()
2428
{
2529
SimpleMetadata::clear();
30+
updateAll();
31+
}
32+
33+
void ItemStackMetadata::updateAll()
34+
{
2635
updateToolCapabilities();
2736
updateWearBarParams();
37+
updateInventoryImage();
38+
updateOverlayImage();
39+
updateWieldImage();
40+
updateWieldOverlay();
2841
}
2942

3043
static void sanitize_string(std::string &str)
@@ -46,6 +59,14 @@ bool ItemStackMetadata::setString(const std::string &name, std::string_view var)
4659
updateToolCapabilities();
4760
else if (clean_name == WEAR_BAR_KEY)
4861
updateWearBarParams();
62+
else if (clean_name == INVENTORY_IMAGE_KEY)
63+
updateInventoryImage();
64+
else if (clean_name == INVENTORY_OVERLAY_KEY)
65+
updateOverlayImage();
66+
else if (clean_name == WIELD_IMAGE_KEY)
67+
updateWieldImage();
68+
else if (clean_name == WIELD_OVERLAY_KEY)
69+
updateWieldOverlay();
4970
return result;
5071
}
5172

@@ -81,8 +102,7 @@ void ItemStackMetadata::deSerialize(std::istream &is)
81102
m_stringvars[""] = std::move(in);
82103
}
83104
}
84-
updateToolCapabilities();
85-
updateWearBarParams();
105+
updateAll();
86106
}
87107

88108
void ItemStackMetadata::updateToolCapabilities()
@@ -129,3 +149,32 @@ void ItemStackMetadata::clearWearBarParams()
129149
{
130150
setString(WEAR_BAR_KEY, "");
131151
}
152+
153+
// Item image overrides
154+
155+
#define ITEM_IMAGE_FUNCTIONS(NAME, FIELD, KEY) \
156+
void ItemStackMetadata::set##NAME(const ItemImageDef &def) \
157+
{ \
158+
std::ostringstream os; \
159+
def.serializeJson(os); \
160+
setString(KEY, os.str()); \
161+
} \
162+
void ItemStackMetadata::clear##NAME() \
163+
{ \
164+
setString(KEY, ""); \
165+
} \
166+
void ItemStackMetadata::update##NAME() \
167+
{ \
168+
if (contains(KEY)) { \
169+
std::istringstream is(getString(KEY)); \
170+
FIELD = ItemImageDef::deserializeJson(is); \
171+
} else { \
172+
FIELD.reset(); \
173+
} \
174+
}
175+
176+
ITEM_IMAGE_FUNCTIONS(InventoryImage, inventory_image_override, INVENTORY_IMAGE_KEY)
177+
ITEM_IMAGE_FUNCTIONS(OverlayImage, inventory_overlay_override, INVENTORY_OVERLAY_KEY)
178+
ITEM_IMAGE_FUNCTIONS(WieldImage, wield_image_override, WIELD_IMAGE_KEY)
179+
ITEM_IMAGE_FUNCTIONS(WieldOverlay, wield_overlay_override, WIELD_OVERLAY_KEY)
180+
#undef ITEM_IMAGE_FUNCTIONS

src/itemstackmetadata.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "metadata.h"
88
#include "tool.h"
9+
#include "itemdef.h"
910

1011
#include <optional>
1112

@@ -39,10 +40,50 @@ class ItemStackMetadata : public SimpleMetadata
3940
void setWearBarParams(const WearBarParams &params);
4041
void clearWearBarParams();
4142

43+
// Item image overrides
44+
45+
const std::optional<ItemImageDef> &getInventoryImageOverride() const
46+
{
47+
return inventory_image_override;
48+
}
49+
void setInventoryImage(const ItemImageDef &params);
50+
void clearInventoryImage();
51+
52+
const std::optional<ItemImageDef> &getInventoryOverlayOverride() const
53+
{
54+
return inventory_overlay_override;
55+
}
56+
void setOverlayImage(const ItemImageDef &params);
57+
void clearOverlayImage();
58+
59+
const std::optional<ItemImageDef> &getWieldImageOverride() const
60+
{
61+
return wield_image_override;
62+
}
63+
void setWieldImage(const ItemImageDef &params);
64+
void clearWieldImage();
65+
66+
const std::optional<ItemImageDef> &getWieldOverlayOverride() const
67+
{
68+
return wield_overlay_override;
69+
}
70+
void setWieldOverlay(const ItemImageDef &params);
71+
void clearWieldOverlay();
72+
4273
private:
4374
void updateToolCapabilities();
4475
void updateWearBarParams();
76+
void updateInventoryImage();
77+
void updateOverlayImage();
78+
void updateWieldImage();
79+
void updateWieldOverlay();
80+
81+
void updateAll();
4582

4683
std::optional<ToolCapabilities> toolcaps_override;
4784
std::optional<WearBarParams> wear_bar_override;
85+
std::optional<ItemImageDef> inventory_image_override;
86+
std::optional<ItemImageDef> inventory_overlay_override;
87+
std::optional<ItemImageDef> wield_image_override;
88+
std::optional<ItemImageDef> wield_overlay_override;
4889
};

0 commit comments

Comments
 (0)