forked from Mirrorlandia_minetest/minetest
Add ability to override item images using meta (#12614)
This commit is contained in:
parent
8c2c7fadbf
commit
4158b72971
@ -2271,6 +2271,11 @@ Some of the values in the key-value store are handled specially:
|
|||||||
See also: `get_description` in [`ItemStack`]
|
See also: `get_description` in [`ItemStack`]
|
||||||
* `short_description`: Set the item stack's short description.
|
* `short_description`: Set the item stack's short description.
|
||||||
See also: `get_short_description` in [`ItemStack`]
|
See also: `get_short_description` in [`ItemStack`]
|
||||||
|
* `inventory_image`: Override inventory_image
|
||||||
|
* `inventory_overlay`: Override inventory_overlay
|
||||||
|
* `wield_image`: Override wield_image
|
||||||
|
* `wield_overlay`: Override wield_overlay
|
||||||
|
* `wield_scale`: Override wield_scale, use vector.to_string
|
||||||
* `color`: A `ColorString`, which sets the stack's color.
|
* `color`: A `ColorString`, which sets the stack's color.
|
||||||
* `palette_index`: If the item has a palette, this is used to get the
|
* `palette_index`: If the item has a palette, this is used to get the
|
||||||
current color from the palette.
|
current color from the palette.
|
||||||
|
@ -40,6 +40,7 @@ minetest.register_craftitem("testitems:overlay_meta", {
|
|||||||
on_place = overlay_on_place,
|
on_place = overlay_on_place,
|
||||||
on_secondary_use = overlay_on_place,
|
on_secondary_use = overlay_on_place,
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_craftitem("testitems:overlay_global", {
|
minetest.register_craftitem("testitems:overlay_global", {
|
||||||
description = S("Texture Overlay Test Item, Global Color") .. "\n" ..
|
description = S("Texture Overlay Test Item, Global Color") .. "\n" ..
|
||||||
S("Image must be an orange square with rainbow cross (inventory and wield)"),
|
S("Image must be an orange square with rainbow cross (inventory and wield)"),
|
||||||
@ -51,3 +52,41 @@ minetest.register_craftitem("testitems:overlay_global", {
|
|||||||
wield_overlay = "testitems_overlay_overlay.png",
|
wield_overlay = "testitems_overlay_overlay.png",
|
||||||
color = GLOBAL_COLOR_ARG,
|
color = GLOBAL_COLOR_ARG,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("testitems:image_meta", {
|
||||||
|
description = S("Image Override Meta Test Item"),
|
||||||
|
inventory_image = "default_apple.png",
|
||||||
|
wield_image = "basetools_icesword.png",
|
||||||
|
|
||||||
|
on_use = function(itemstack, player)
|
||||||
|
local meta = itemstack:get_meta()
|
||||||
|
local state = meta:get_int("state")
|
||||||
|
state = (state + 1) % 5
|
||||||
|
meta:set_int("state", state)
|
||||||
|
minetest.chat_send_player(player:get_player_name(), "State " .. state)
|
||||||
|
|
||||||
|
if state == 0 then
|
||||||
|
meta:set_string("inventory_image", "")
|
||||||
|
meta:set_string("wield_image", "")
|
||||||
|
meta:set_string("inventory_overlay", "")
|
||||||
|
meta:set_string("wield_overlay", "")
|
||||||
|
meta:set_string("wield_scale", "")
|
||||||
|
elseif state == 1 then
|
||||||
|
meta:set_string("inventory_image", "default_tree.png")
|
||||||
|
meta:set_string("wield_image", "basetools_firesword.png")
|
||||||
|
elseif state == 2 then
|
||||||
|
meta:set_string("inventory_image", "default_apple.png^testitems_overridden.png")
|
||||||
|
meta:set_string("wield_image", "basetools_icesword.png^testitems_overridden.png")
|
||||||
|
elseif state == 3 then
|
||||||
|
meta:set_string("inventory_image", "default_tree.png")
|
||||||
|
meta:set_string("wield_image", "basetools_firesword.png")
|
||||||
|
meta:set_string("inventory_overlay", "default_apple.png")
|
||||||
|
meta:set_string("wield_overlay", "default_apple.png")
|
||||||
|
elseif state == 4 then
|
||||||
|
local scale = vector.new(0.5, 0.5, 0.5)
|
||||||
|
meta:set_string("wield_scale", scale:to_string())
|
||||||
|
end
|
||||||
|
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
BIN
games/devtest/mods/testitems/textures/testitems_overridden.png
Normal file
BIN
games/devtest/mods/testitems/textures/testitems_overridden.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 B |
@ -1840,7 +1840,6 @@ inline bool Game::handleCallbacks()
|
|||||||
void Game::processQueues()
|
void Game::processQueues()
|
||||||
{
|
{
|
||||||
texture_src->processQueue();
|
texture_src->processQueue();
|
||||||
itemdef_manager->processQueue(client);
|
|
||||||
shader_src->processQueue();
|
shader_src->processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,10 +1008,14 @@ void drawItemStack(
|
|||||||
const static thread_local bool enable_animations =
|
const static thread_local bool enable_animations =
|
||||||
g_settings->getBool("inventory_items_animations");
|
g_settings->getBool("inventory_items_animations");
|
||||||
|
|
||||||
const ItemDefinition &def = item.getDefinition(client->idef());
|
auto *idef = client->idef();
|
||||||
|
const ItemDefinition &def = item.getDefinition(idef);
|
||||||
|
|
||||||
bool draw_overlay = false;
|
bool draw_overlay = false;
|
||||||
|
|
||||||
|
const std::string inventory_image = item.getInventoryImage(idef);
|
||||||
|
const std::string inventory_overlay = item.getInventoryOverlay(idef);
|
||||||
|
|
||||||
bool has_mesh = false;
|
bool has_mesh = false;
|
||||||
ItemMesh *imesh;
|
ItemMesh *imesh;
|
||||||
|
|
||||||
@ -1020,8 +1024,8 @@ void drawItemStack(
|
|||||||
viewrect.clipAgainst(*clip);
|
viewrect.clipAgainst(*clip);
|
||||||
|
|
||||||
// Render as mesh if animated or no inventory image
|
// Render as mesh if animated or no inventory image
|
||||||
if ((enable_animations && rotation_kind < IT_ROT_NONE) || def.inventory_image.empty()) {
|
if ((enable_animations && rotation_kind < IT_ROT_NONE) || inventory_image.empty()) {
|
||||||
imesh = client->idef()->getWieldMesh(def.name, client);
|
imesh = idef->getWieldMesh(item, client);
|
||||||
has_mesh = imesh && imesh->mesh;
|
has_mesh = imesh && imesh->mesh;
|
||||||
}
|
}
|
||||||
if (has_mesh) {
|
if (has_mesh) {
|
||||||
@ -1110,9 +1114,9 @@ void drawItemStack(
|
|||||||
driver->setTransform(video::ETS_PROJECTION, oldProjMat);
|
driver->setTransform(video::ETS_PROJECTION, oldProjMat);
|
||||||
driver->setViewPort(oldViewPort);
|
driver->setViewPort(oldViewPort);
|
||||||
|
|
||||||
draw_overlay = def.type == ITEM_NODE && def.inventory_image.empty();
|
draw_overlay = def.type == ITEM_NODE && inventory_image.empty();
|
||||||
} else { // Otherwise just draw as 2D
|
} else { // Otherwise just draw as 2D
|
||||||
video::ITexture *texture = client->idef()->getInventoryTexture(def.name, client);
|
video::ITexture *texture = client->idef()->getInventoryTexture(item, client);
|
||||||
video::SColor color;
|
video::SColor color;
|
||||||
if (texture) {
|
if (texture) {
|
||||||
color = client->idef()->getItemstackColor(item, client);
|
color = client->idef()->getItemstackColor(item, client);
|
||||||
@ -1134,9 +1138,9 @@ void drawItemStack(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw the inventory_overlay
|
// draw the inventory_overlay
|
||||||
if (!def.inventory_overlay.empty() && draw_overlay) {
|
if (!inventory_overlay.empty() && draw_overlay) {
|
||||||
ITextureSource *tsrc = client->getTextureSource();
|
ITextureSource *tsrc = client->getTextureSource();
|
||||||
video::ITexture *overlay_texture = tsrc->getTexture(def.inventory_overlay);
|
video::ITexture *overlay_texture = tsrc->getTexture(inventory_overlay);
|
||||||
core::dimension2d<u32> dimens = overlay_texture->getOriginalSize();
|
core::dimension2d<u32> dimens = overlay_texture->getOriginalSize();
|
||||||
core::rect<s32> srcrect(0, 0, dimens.Width, dimens.Height);
|
core::rect<s32> srcrect(0, 0, dimens.Width, dimens.Height);
|
||||||
draw2DImageFilterScaled(driver, overlay_texture, rect, srcrect, clip, 0, true);
|
draw2DImageFilterScaled(driver, overlay_texture, rect, srcrect, clip, 0, true);
|
||||||
|
@ -384,9 +384,13 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
m_colors.clear();
|
m_colors.clear();
|
||||||
m_base_color = idef->getItemstackColor(item, client);
|
m_base_color = idef->getItemstackColor(item, client);
|
||||||
|
|
||||||
|
const std::string wield_image = item.getWieldImage(idef);
|
||||||
|
const std::string wield_overlay = item.getWieldOverlay(idef);
|
||||||
|
const v3f wield_scale = item.getWieldScale(idef);
|
||||||
|
|
||||||
// If wield_image needs to be checked and is defined, it overrides everything else
|
// If wield_image needs to be checked and is defined, it overrides everything else
|
||||||
if (!def.wield_image.empty() && check_wield_image) {
|
if (!wield_image.empty() && check_wield_image) {
|
||||||
setExtruded(def.wield_image, def.wield_overlay, def.wield_scale, tsrc,
|
setExtruded(wield_image, wield_overlay, wield_scale, tsrc,
|
||||||
1);
|
1);
|
||||||
m_colors.emplace_back();
|
m_colors.emplace_back();
|
||||||
// overlay is white, if present
|
// overlay is white, if present
|
||||||
@ -413,7 +417,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
case NDT_RAILLIKE:
|
case NDT_RAILLIKE:
|
||||||
case NDT_PLANTLIKE:
|
case NDT_PLANTLIKE:
|
||||||
case NDT_FLOWINGLIQUID: {
|
case NDT_FLOWINGLIQUID: {
|
||||||
v3f wscale = def.wield_scale;
|
v3f wscale = wield_scale;
|
||||||
if (f.drawtype == NDT_FLOWINGLIQUID)
|
if (f.drawtype == NDT_FLOWINGLIQUID)
|
||||||
wscale.Z *= 0.1f;
|
wscale.Z *= 0.1f;
|
||||||
setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
|
setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
|
||||||
@ -429,7 +433,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
}
|
}
|
||||||
case NDT_PLANTLIKE_ROOTED: {
|
case NDT_PLANTLIKE_ROOTED: {
|
||||||
setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id),
|
setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id),
|
||||||
"", def.wield_scale, tsrc,
|
"", wield_scale, tsrc,
|
||||||
f.special_tiles[0].layers[0].animation_frame_count);
|
f.special_tiles[0].layers[0].animation_frame_count);
|
||||||
// Add color
|
// Add color
|
||||||
const TileLayer &l0 = f.special_tiles[0].layers[0];
|
const TileLayer &l0 = f.special_tiles[0].layers[0];
|
||||||
@ -439,7 +443,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
case NDT_NORMAL:
|
case NDT_NORMAL:
|
||||||
case NDT_ALLFACES:
|
case NDT_ALLFACES:
|
||||||
case NDT_LIQUID:
|
case NDT_LIQUID:
|
||||||
setCube(f, def.wield_scale);
|
setCube(f, wield_scale);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
// Render non-trivial drawtypes like the actual node
|
// Render non-trivial drawtypes like the actual node
|
||||||
@ -450,7 +454,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
changeToMesh(mesh);
|
changeToMesh(mesh);
|
||||||
mesh->drop();
|
mesh->drop();
|
||||||
m_meshnode->setScale(
|
m_meshnode->setScale(
|
||||||
def.wield_scale * WIELD_SCALE_FACTOR
|
wield_scale * WIELD_SCALE_FACTOR
|
||||||
/ (BS * f.visual_scale));
|
/ (BS * f.visual_scale));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -471,9 +475,10 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
setColor(video::SColor(0xFFFFFFFF));
|
setColor(video::SColor(0xFFFFFFFF));
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!def.inventory_image.empty()) {
|
const std::string inventory_image = item.getInventoryImage(idef);
|
||||||
setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale,
|
if (!inventory_image.empty()) {
|
||||||
tsrc, 1);
|
const std::string inventory_overlay = item.getInventoryOverlay(idef);
|
||||||
|
setExtruded(inventory_image, inventory_overlay, def.wield_scale, tsrc, 1);
|
||||||
} else {
|
} else {
|
||||||
setExtruded("no_texture.png", "", def.wield_scale, tsrc, 1);
|
setExtruded("no_texture.png", "", def.wield_scale, tsrc, 1);
|
||||||
}
|
}
|
||||||
@ -578,9 +583,10 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
bool cull_backface = f.needsBackfaceCulling();
|
bool cull_backface = f.needsBackfaceCulling();
|
||||||
|
|
||||||
// If inventory_image is defined, it overrides everything else
|
// If inventory_image is defined, it overrides everything else
|
||||||
if (!def.inventory_image.empty()) {
|
const std::string inventory_image = item.getInventoryImage(idef);
|
||||||
mesh = getExtrudedMesh(tsrc, def.inventory_image,
|
const std::string inventory_overlay = item.getInventoryOverlay(idef);
|
||||||
def.inventory_overlay);
|
if (!inventory_image.empty()) {
|
||||||
|
mesh = getExtrudedMesh(tsrc, inventory_image, inventory_overlay);
|
||||||
result->buffer_colors.emplace_back();
|
result->buffer_colors.emplace_back();
|
||||||
// overlay is white, if present
|
// overlay is white, if present
|
||||||
result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
|
result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
|
||||||
@ -588,8 +594,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
result->needs_shading = false;
|
result->needs_shading = false;
|
||||||
} else if (def.type == ITEM_NODE && f.drawtype == NDT_AIRLIKE) {
|
} else if (def.type == ITEM_NODE && f.drawtype == NDT_AIRLIKE) {
|
||||||
// Fallback image for airlike node
|
// Fallback image for airlike node
|
||||||
mesh = getExtrudedMesh(tsrc, "no_texture_airlike.png",
|
mesh = getExtrudedMesh(tsrc, "no_texture_airlike.png", inventory_overlay);
|
||||||
def.inventory_overlay);
|
|
||||||
result->needs_shading = false;
|
result->needs_shading = false;
|
||||||
} else if (def.type == ITEM_NODE) {
|
} else if (def.type == ITEM_NODE) {
|
||||||
switch (f.drawtype) {
|
switch (f.drawtype) {
|
||||||
|
@ -272,6 +272,50 @@ std::string ItemStack::getShortDescription(const IItemDefManager *itemdef) const
|
|||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ItemStack::getInventoryImage(const IItemDefManager *itemdef) const
|
||||||
|
{
|
||||||
|
std::string texture = metadata.getString("inventory_image");
|
||||||
|
if (texture.empty())
|
||||||
|
texture = getDefinition(itemdef).inventory_image;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemStack::getInventoryOverlay(const IItemDefManager *itemdef) const
|
||||||
|
{
|
||||||
|
std::string texture = metadata.getString("inventory_overlay");
|
||||||
|
if (texture.empty())
|
||||||
|
texture = getDefinition(itemdef).inventory_overlay;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemStack::getWieldImage(const IItemDefManager *itemdef) const
|
||||||
|
{
|
||||||
|
std::string texture = metadata.getString("wield_image");
|
||||||
|
if (texture.empty())
|
||||||
|
texture = getDefinition(itemdef).wield_image;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ItemStack::getWieldOverlay(const IItemDefManager *itemdef) const
|
||||||
|
{
|
||||||
|
std::string texture = metadata.getString("wield_overlay");
|
||||||
|
if (texture.empty())
|
||||||
|
texture = getDefinition(itemdef).wield_overlay;
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3f ItemStack::getWieldScale(const IItemDefManager *itemdef) const
|
||||||
|
{
|
||||||
|
std::string scale = metadata.getString("wield_scale");
|
||||||
|
if (scale.empty())
|
||||||
|
return getDefinition(itemdef).wield_scale;
|
||||||
|
|
||||||
|
return str_to_v3f(scale);
|
||||||
|
}
|
||||||
|
|
||||||
ItemStack ItemStack::addItem(ItemStack newitem, IItemDefManager *itemdef)
|
ItemStack ItemStack::addItem(ItemStack newitem, IItemDefManager *itemdef)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,12 @@ struct ItemStack
|
|||||||
std::string getDescription(const IItemDefManager *itemdef) const;
|
std::string getDescription(const IItemDefManager *itemdef) const;
|
||||||
std::string getShortDescription(const IItemDefManager *itemdef) const;
|
std::string getShortDescription(const IItemDefManager *itemdef) const;
|
||||||
|
|
||||||
|
std::string getInventoryImage(const IItemDefManager *itemdef) const;
|
||||||
|
std::string getInventoryOverlay(const IItemDefManager *itemdef) const;
|
||||||
|
std::string getWieldImage(const IItemDefManager *itemdef) const;
|
||||||
|
std::string getWieldOverlay(const IItemDefManager *itemdef) const;
|
||||||
|
v3f getWieldScale(const IItemDefManager *itemdef) const;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Quantity methods
|
Quantity methods
|
||||||
*/
|
*/
|
||||||
|
133
src/itemdef.cpp
133
src/itemdef.cpp
@ -253,6 +253,13 @@ class CItemDefManager: public IWritableItemDefManager
|
|||||||
inventory_texture(NULL),
|
inventory_texture(NULL),
|
||||||
palette(NULL)
|
palette(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
~ClientCached() {
|
||||||
|
if (wield_mesh.mesh)
|
||||||
|
wield_mesh.mesh->drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
DISABLE_CLASS_COPY(ClientCached);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -265,17 +272,9 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CItemDefManager()
|
virtual ~CItemDefManager()
|
||||||
{
|
{
|
||||||
#ifndef SERVER
|
|
||||||
const std::vector<ClientCached*> &values = m_clientcached.getValues();
|
|
||||||
for (ClientCached *cc : values) {
|
|
||||||
if (cc->wield_mesh.mesh)
|
|
||||||
cc->wield_mesh.mesh->drop();
|
|
||||||
delete cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
for (auto &item_definition : m_item_definitions) {
|
for (auto &item_definition : m_item_definitions) {
|
||||||
delete item_definition.second;
|
delete item_definition.second;
|
||||||
}
|
}
|
||||||
@ -319,103 +318,72 @@ public:
|
|||||||
}
|
}
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
public:
|
public:
|
||||||
ClientCached* createClientCachedDirect(const std::string &name,
|
ClientCached* createClientCachedDirect(const ItemStack &item, Client *client) const
|
||||||
Client *client) const
|
|
||||||
{
|
{
|
||||||
infostream<<"Lazily creating item texture and mesh for \""
|
|
||||||
<<name<<"\""<<std::endl;
|
|
||||||
|
|
||||||
// This is not thread-safe
|
// This is not thread-safe
|
||||||
sanity_check(std::this_thread::get_id() == m_main_thread);
|
sanity_check(std::this_thread::get_id() == m_main_thread);
|
||||||
|
|
||||||
|
const ItemDefinition &def = item.getDefinition(this);
|
||||||
|
std::string inventory_image = item.getInventoryImage(this);
|
||||||
|
std::string inventory_overlay = item.getInventoryOverlay(this);
|
||||||
|
std::string cache_key = def.name;
|
||||||
|
if (!inventory_image.empty())
|
||||||
|
cache_key += "/" + inventory_image;
|
||||||
|
if (!inventory_overlay.empty())
|
||||||
|
cache_key += ":" + inventory_overlay;
|
||||||
|
|
||||||
|
infostream << "Lazily creating item texture and mesh for \""
|
||||||
|
<< cache_key << "\""<<std::endl;
|
||||||
|
|
||||||
// Skip if already in cache
|
// Skip if already in cache
|
||||||
ClientCached *cc = NULL;
|
auto it = m_clientcached.find(cache_key);
|
||||||
m_clientcached.get(name, &cc);
|
if (it != m_clientcached.end())
|
||||||
if(cc)
|
return it->second.get();
|
||||||
return cc;
|
|
||||||
|
|
||||||
ITextureSource *tsrc = client->getTextureSource();
|
ITextureSource *tsrc = client->getTextureSource();
|
||||||
const ItemDefinition &def = get(name);
|
|
||||||
|
|
||||||
// Create new ClientCached
|
// Create new ClientCached
|
||||||
cc = new ClientCached();
|
auto cc = std::make_unique<ClientCached>();
|
||||||
|
|
||||||
// Create an inventory texture
|
// Create an inventory texture
|
||||||
cc->inventory_texture = NULL;
|
cc->inventory_texture = NULL;
|
||||||
if (!def.inventory_image.empty())
|
if (!inventory_image.empty())
|
||||||
cc->inventory_texture = tsrc->getTexture(def.inventory_image);
|
cc->inventory_texture = tsrc->getTexture(inventory_image);
|
||||||
|
|
||||||
ItemStack item = ItemStack();
|
|
||||||
item.name = def.name;
|
|
||||||
|
|
||||||
getItemMesh(client, item, &(cc->wield_mesh));
|
getItemMesh(client, item, &(cc->wield_mesh));
|
||||||
|
|
||||||
cc->palette = tsrc->getPalette(def.palette_image);
|
cc->palette = tsrc->getPalette(def.palette_image);
|
||||||
|
|
||||||
// Put in cache
|
// Put in cache
|
||||||
m_clientcached.set(name, cc);
|
ClientCached *ptr = cc.get();
|
||||||
|
m_clientcached[cache_key] = std::move(cc);
|
||||||
return cc;
|
return ptr;
|
||||||
}
|
|
||||||
ClientCached* getClientCached(const std::string &name,
|
|
||||||
Client *client) const
|
|
||||||
{
|
|
||||||
ClientCached *cc = NULL;
|
|
||||||
m_clientcached.get(name, &cc);
|
|
||||||
if (cc)
|
|
||||||
return cc;
|
|
||||||
|
|
||||||
if (std::this_thread::get_id() == m_main_thread) {
|
|
||||||
return createClientCachedDirect(name, client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're gonna ask the result to be put into here
|
|
||||||
static ResultQueue<std::string, ClientCached*, u8, u8> result_queue;
|
|
||||||
|
|
||||||
// Throw a request in
|
|
||||||
m_get_clientcached_queue.add(name, 0, 0, &result_queue);
|
|
||||||
try {
|
|
||||||
while(true) {
|
|
||||||
// Wait result for a second
|
|
||||||
GetResult<std::string, ClientCached*, u8, u8>
|
|
||||||
result = result_queue.pop_front(1000);
|
|
||||||
|
|
||||||
if (result.key == name) {
|
|
||||||
return result.item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(ItemNotFoundException &e) {
|
|
||||||
errorstream << "Waiting for clientcached " << name
|
|
||||||
<< " timed out." << std::endl;
|
|
||||||
return &m_dummy_clientcached;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get item inventory texture
|
// Get item inventory texture
|
||||||
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
virtual video::ITexture* getInventoryTexture(const ItemStack &item,
|
||||||
Client *client) const
|
Client *client) const
|
||||||
{
|
{
|
||||||
ClientCached *cc = getClientCached(name, client);
|
ClientCached *cc = createClientCachedDirect(item, client);
|
||||||
if (!cc)
|
if (!cc)
|
||||||
return NULL;
|
return nullptr;
|
||||||
return cc->inventory_texture;
|
return cc->inventory_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get item wield mesh
|
// Get item wield mesh
|
||||||
virtual ItemMesh* getWieldMesh(const std::string &name,
|
virtual ItemMesh* getWieldMesh(const ItemStack &item, Client *client) const
|
||||||
Client *client) const
|
|
||||||
{
|
{
|
||||||
ClientCached *cc = getClientCached(name, client);
|
ClientCached *cc = createClientCachedDirect(item, client);
|
||||||
if (!cc)
|
if (!cc)
|
||||||
return NULL;
|
return nullptr;
|
||||||
return &(cc->wield_mesh);
|
return &(cc->wield_mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get item palette
|
// Get item palette
|
||||||
virtual Palette* getPalette(const std::string &name,
|
virtual Palette* getPalette(const ItemStack &item, Client *client) const
|
||||||
Client *client) const
|
|
||||||
{
|
{
|
||||||
ClientCached *cc = getClientCached(name, client);
|
ClientCached *cc = createClientCachedDirect(item, client);
|
||||||
if (!cc)
|
if (!cc)
|
||||||
return NULL;
|
return nullptr;
|
||||||
return cc->palette;
|
return cc->palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +396,7 @@ public:
|
|||||||
if (!colorstring.empty() && parseColorString(colorstring, directcolor, true))
|
if (!colorstring.empty() && parseColorString(colorstring, directcolor, true))
|
||||||
return directcolor;
|
return directcolor;
|
||||||
// See if there is a palette
|
// See if there is a palette
|
||||||
Palette *palette = getPalette(stack.name, client);
|
Palette *palette = getPalette(stack, client);
|
||||||
const std::string &index = stack.metadata.getString("palette_index", 0);
|
const std::string &index = stack.metadata.getString("palette_index", 0);
|
||||||
if (palette && !index.empty())
|
if (palette && !index.empty())
|
||||||
return (*palette)[mystoi(index, 0, 255)];
|
return (*palette)[mystoi(index, 0, 255)];
|
||||||
@ -573,20 +541,7 @@ public:
|
|||||||
registerAlias(name, convert_to);
|
registerAlias(name, convert_to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void processQueue(IGameDef *gamedef)
|
|
||||||
{
|
|
||||||
#ifndef SERVER
|
|
||||||
//NOTE this is only thread safe for ONE consumer thread!
|
|
||||||
while(!m_get_clientcached_queue.empty())
|
|
||||||
{
|
|
||||||
GetRequest<std::string, ClientCached*, u8, u8>
|
|
||||||
request = m_get_clientcached_queue.pop();
|
|
||||||
|
|
||||||
m_get_clientcached_queue.pushResult(request,
|
|
||||||
createClientCachedDirect(request.key, (Client *)gamedef));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
// Key is name
|
// Key is name
|
||||||
std::map<std::string, ItemDefinition*> m_item_definitions;
|
std::map<std::string, ItemDefinition*> m_item_definitions;
|
||||||
@ -595,12 +550,8 @@ private:
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
// The id of the thread that is allowed to use irrlicht directly
|
// The id of the thread that is allowed to use irrlicht directly
|
||||||
std::thread::id m_main_thread;
|
std::thread::id m_main_thread;
|
||||||
// A reference to this can be returned when nothing is found, to avoid NULLs
|
|
||||||
mutable ClientCached m_dummy_clientcached;
|
|
||||||
// Cached textures and meshes
|
// Cached textures and meshes
|
||||||
mutable MutexedMap<std::string, ClientCached*> m_clientcached;
|
mutable std::unordered_map<std::string, std::unique_ptr<ClientCached>> m_clientcached;
|
||||||
// Queued clientcached fetches (to be processed by the main thread)
|
|
||||||
mutable RequestQueue<std::string, ClientCached*, u8, u8> m_get_clientcached_queue;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,14 +120,16 @@ public:
|
|||||||
virtual bool isKnown(const std::string &name) const=0;
|
virtual bool isKnown(const std::string &name) const=0;
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
// Get item inventory texture
|
// Get item inventory texture
|
||||||
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
virtual video::ITexture* getInventoryTexture(const ItemStack &item, Client *client) const=0;
|
||||||
Client *client) const=0;
|
|
||||||
// Get item wield mesh
|
/**
|
||||||
virtual ItemMesh* getWieldMesh(const std::string &name,
|
* Get wield mesh
|
||||||
Client *client) const=0;
|
*
|
||||||
|
* Returns nullptr if there is an inventory image
|
||||||
|
*/
|
||||||
|
virtual ItemMesh* getWieldMesh(const ItemStack &item, Client *client) const = 0;
|
||||||
// Get item palette
|
// Get item palette
|
||||||
virtual Palette* getPalette(const std::string &name,
|
virtual Palette* getPalette(const ItemStack &item, Client *client) const = 0;
|
||||||
Client *client) const = 0;
|
|
||||||
// Returns the base color of an item stack: the color of all
|
// Returns the base color of an item stack: the color of all
|
||||||
// tiles that do not define their own color.
|
// tiles that do not define their own color.
|
||||||
virtual video::SColor getItemstackColor(const ItemStack &stack,
|
virtual video::SColor getItemstackColor(const ItemStack &stack,
|
||||||
@ -144,23 +146,6 @@ public:
|
|||||||
|
|
||||||
virtual ~IWritableItemDefManager() = default;
|
virtual ~IWritableItemDefManager() = default;
|
||||||
|
|
||||||
// Get item definition
|
|
||||||
virtual const ItemDefinition& get(const std::string &name) const=0;
|
|
||||||
// Get alias definition
|
|
||||||
virtual const std::string &getAlias(const std::string &name) const=0;
|
|
||||||
// Get set of all defined item names and aliases
|
|
||||||
virtual void getAll(std::set<std::string> &result) const=0;
|
|
||||||
// Check if item is known
|
|
||||||
virtual bool isKnown(const std::string &name) const=0;
|
|
||||||
#ifndef SERVER
|
|
||||||
// Get item inventory texture
|
|
||||||
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
|
||||||
Client *client) const=0;
|
|
||||||
// Get item wield mesh
|
|
||||||
virtual ItemMesh* getWieldMesh(const std::string &name,
|
|
||||||
Client *client) const=0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Replace the textures of registered nodes with the ones specified in
|
// Replace the textures of registered nodes with the ones specified in
|
||||||
// the texture pack's override.txt files
|
// the texture pack's override.txt files
|
||||||
virtual void applyTextureOverrides(const std::vector<TextureOverride> &overrides)=0;
|
virtual void applyTextureOverrides(const std::vector<TextureOverride> &overrides)=0;
|
||||||
@ -177,11 +162,7 @@ public:
|
|||||||
virtual void registerAlias(const std::string &name,
|
virtual void registerAlias(const std::string &name,
|
||||||
const std::string &convert_to)=0;
|
const std::string &convert_to)=0;
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
|
||||||
virtual void deSerialize(std::istream &is, u16 protocol_version)=0;
|
virtual void deSerialize(std::istream &is, u16 protocol_version)=0;
|
||||||
|
|
||||||
// Do stuff asked by threads that can only be done in the main thread
|
|
||||||
virtual void processQueue(IGameDef *gamedef)=0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IWritableItemDefManager* createItemDefManager();
|
IWritableItemDefManager* createItemDefManager();
|
||||||
|
@ -562,13 +562,7 @@ v2f Settings::getV2F(const std::string &name) const
|
|||||||
|
|
||||||
v3f Settings::getV3F(const std::string &name) const
|
v3f Settings::getV3F(const std::string &name) const
|
||||||
{
|
{
|
||||||
v3f value;
|
return str_to_v3f(get(name));
|
||||||
Strfnd f(get(name));
|
|
||||||
f.next("(");
|
|
||||||
value.X = stof(f.next(","));
|
|
||||||
value.Y = stof(f.next(","));
|
|
||||||
value.Z = stof(f.next(")"));
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
|
#include "strfnd.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -897,3 +898,15 @@ void safe_print_string(std::ostream &os, const std::string &str)
|
|||||||
}
|
}
|
||||||
os.setf(flags);
|
os.setf(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
v3f str_to_v3f(const std::string &str)
|
||||||
|
{
|
||||||
|
v3f value;
|
||||||
|
Strfnd f(str);
|
||||||
|
f.next("(");
|
||||||
|
value.X = stof(f.next(","));
|
||||||
|
value.Y = stof(f.next(","));
|
||||||
|
value.Z = stof(f.next(")"));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
@ -765,3 +765,11 @@ std::string sanitizeDirName(const std::string &str, const std::string &optional_
|
|||||||
* brackets (e.g. "a\x1eb" -> "a<1e>b").
|
* brackets (e.g. "a\x1eb" -> "a<1e>b").
|
||||||
*/
|
*/
|
||||||
void safe_print_string(std::ostream &os, const std::string &str);
|
void safe_print_string(std::ostream &os, const std::string &str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string of form `(1, 2, 3)` to a v3f
|
||||||
|
*
|
||||||
|
* @param str String
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
v3f str_to_v3f(const std::string &str);
|
||||||
|
Loading…
Reference in New Issue
Block a user