aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDániel Juhász <juhdanad@gmail.com>2017-06-20 09:19:56 +0000
committerLoïc Blot <nerzhul@users.noreply.github.com>2017-06-20 11:19:56 +0200
commit0fcaf9fb1b61caaf8ed78a5d3005b1d9d1c43b57 (patch)
tree39b19a3fa61dc29b921739a26d7598222cdbd5f3 /src
parent7c07cb4ec23ebb0f3d5f3d913bea205660515836 (diff)
downloadminetest-0fcaf9fb1b61caaf8ed78a5d3005b1d9d1c43b57.tar.gz
minetest-0fcaf9fb1b61caaf8ed78a5d3005b1d9d1c43b57.tar.bz2
minetest-0fcaf9fb1b61caaf8ed78a5d3005b1d9d1c43b57.zip
Automatic item and node colorization (#5640)
* Automatic item and node colorization Now nodes with a palette yield colored item stacks, and colored items place colored nodes by default. The client predicts the colorization. * Backwards compatibility * Use nil * Style fixes * Fix code style * Document changes
Diffstat (limited to 'src')
-rw-r--r--src/game.cpp57
-rw-r--r--src/inventory.cpp8
-rw-r--r--src/inventory.h5
-rw-r--r--src/script/lua_api/l_inventory.cpp11
-rw-r--r--src/script/lua_api/l_inventory.h2
5 files changed, 57 insertions, 26 deletions
diff --git a/src/game.cpp b/src/game.cpp
index 325557723..b81efc33f 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -774,8 +774,8 @@ public:
};
-bool nodePlacementPrediction(Client &client,
- const ItemDefinition &playeritem_def, v3s16 nodepos, v3s16 neighbourpos)
+bool nodePlacementPrediction(Client &client, const ItemDefinition &playeritem_def,
+ const ItemStack &playeritem, v3s16 nodepos, v3s16 neighbourpos)
{
std::string prediction = playeritem_def.node_placement_prediction;
INodeDefManager *nodedef = client.ndef();
@@ -818,11 +818,13 @@ bool nodePlacementPrediction(Client &client,
return false;
}
+ const ContentFeatures &predicted_f = nodedef->get(id);
+
// Predict param2 for facedir and wallmounted nodes
u8 param2 = 0;
- if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED ||
- nodedef->get(id).param_type_2 == CPT2_COLORED_WALLMOUNTED) {
+ if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
v3s16 dir = nodepos - neighbourpos;
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
@@ -834,8 +836,8 @@ bool nodePlacementPrediction(Client &client,
}
}
- if (nodedef->get(id).param_type_2 == CPT2_FACEDIR ||
- nodedef->get(id).param_type_2 == CPT2_COLORED_FACEDIR) {
+ if (predicted_f.param_type_2 == CPT2_FACEDIR ||
+ predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
v3s16 dir = nodepos - floatToInt(client.getEnv().getLocalPlayer()->getPosition(), BS);
if (abs(dir.X) > abs(dir.Z)) {
@@ -848,7 +850,7 @@ bool nodePlacementPrediction(Client &client,
assert(param2 <= 5);
//Check attachment if node is in group attached_node
- if (((ItemGroupList) nodedef->get(id).groups)["attached_node"] != 0) {
+ if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
static v3s16 wallmounted_dirs[8] = {
v3s16(0, 1, 0),
v3s16(0, -1, 0),
@@ -859,8 +861,8 @@ bool nodePlacementPrediction(Client &client,
};
v3s16 pp;
- if (nodedef->get(id).param_type_2 == CPT2_WALLMOUNTED ||
- nodedef->get(id).param_type_2 == CPT2_COLORED_WALLMOUNTED)
+ if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
pp = p + wallmounted_dirs[param2];
else
pp = p + v3s16(0, -1, 0);
@@ -869,6 +871,28 @@ bool nodePlacementPrediction(Client &client,
return false;
}
+ // Apply color
+ if ((predicted_f.param_type_2 == CPT2_COLOR
+ || predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
+ || predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
+ const std::string &indexstr = playeritem.metadata.getString(
+ "palette_index", 0);
+ if (!indexstr.empty()) {
+ s32 index = mystoi(indexstr);
+ if (predicted_f.param_type_2 == CPT2_COLOR) {
+ param2 = index;
+ } else if (predicted_f.param_type_2
+ == CPT2_COLORED_WALLMOUNTED) {
+ // param2 = pure palette index + other
+ param2 = (index & 0xf8) | (param2 & 0x07);
+ } else if (predicted_f.param_type_2
+ == CPT2_COLORED_FACEDIR) {
+ // param2 = pure palette index + other
+ param2 = (index & 0xe0) | (param2 & 0x1f);
+ }
+ }
+ }
+
// Add node to client map
MapNode n(id, 0, param2);
@@ -1277,8 +1301,9 @@ protected:
const core::line3d<f32> &shootline, bool liquids_pointable,
bool look_for_object, const v3s16 &camera_offset);
void handlePointingAtNothing(const ItemStack &playerItem);
- void handlePointingAtNode(const PointedThing &pointed, const ItemDefinition &playeritem_def,
- const ToolCapabilities &playeritem_toolcap, f32 dtime);
+ void handlePointingAtNode(const PointedThing &pointed,
+ const ItemDefinition &playeritem_def, const ItemStack &playeritem,
+ const ToolCapabilities &playeritem_toolcap, f32 dtime);
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
const v3f &player_position, bool show_debug);
void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
@@ -3599,7 +3624,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
if (playeritem.name.empty() && hand_def.tool_capabilities != NULL) {
playeritem_toolcap = *hand_def.tool_capabilities;
}
- handlePointingAtNode(pointed, playeritem_def, playeritem_toolcap, dtime);
+ handlePointingAtNode(pointed, playeritem_def, playeritem,
+ playeritem_toolcap, dtime);
} else if (pointed.type == POINTEDTHING_OBJECT) {
handlePointingAtObject(pointed, playeritem, player_position, show_debug);
} else if (isLeftPressed()) {
@@ -3734,8 +3760,9 @@ void Game::handlePointingAtNothing(const ItemStack &playerItem)
}
-void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinition &playeritem_def,
- const ToolCapabilities &playeritem_toolcap, f32 dtime)
+void Game::handlePointingAtNode(const PointedThing &pointed,
+ const ItemDefinition &playeritem_def, const ItemStack &playeritem,
+ const ToolCapabilities &playeritem_toolcap, f32 dtime)
{
v3s16 nodepos = pointed.node_undersurface;
v3s16 neighbourpos = pointed.node_abovesurface;
@@ -3795,7 +3822,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed, const ItemDefinitio
// If the wielded item has node placement prediction,
// make that happen
bool placed = nodePlacementPrediction(*client,
- playeritem_def,
+ playeritem_def, playeritem,
nodepos, neighbourpos);
if (placed) {
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 25f524150..5ce82737a 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -658,7 +658,7 @@ bool InventoryList::roomForItem(const ItemStack &item_) const
return false;
}
-bool InventoryList::containsItem(const ItemStack &item) const
+bool InventoryList::containsItem(const ItemStack &item, bool match_meta) const
{
u32 count = item.count;
if(count == 0)
@@ -669,9 +669,9 @@ bool InventoryList::containsItem(const ItemStack &item) const
{
if(count == 0)
break;
- if(i->name == item.name)
- {
- if(i->count >= count)
+ if (i->name == item.name
+ && (!match_meta || (i->metadata == item.metadata))) {
+ if (i->count >= count)
return true;
else
count -= i->count;
diff --git a/src/inventory.h b/src/inventory.h
index e3e818708..04c8156c8 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -223,9 +223,10 @@ public:
// Checks whether there is room for a given item
bool roomForItem(const ItemStack &item) const;
- // Checks whether the given count of the given item name
+ // Checks whether the given count of the given item
// exists in this inventory list.
- bool containsItem(const ItemStack &item) const;
+ // If match_meta is false, only the items' names are compared.
+ bool containsItem(const ItemStack &item, bool match_meta) const;
// Removes the given count of the given item name from
// this inventory list. Walks the list in reverse order.
diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp
index f5e76a7b6..e92197c14 100644
--- a/src/script/lua_api/l_inventory.cpp
+++ b/src/script/lua_api/l_inventory.cpp
@@ -325,8 +325,8 @@ int InvRef::l_room_for_item(lua_State *L)
return 1;
}
-// contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false
-// Returns true if the list contains the given count of the given item name
+// contains_item(self, listname, itemstack or itemstring or table or nil, [match_meta]) -> true/false
+// Returns true if the list contains the given count of the given item
int InvRef::l_contains_item(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -334,8 +334,11 @@ int InvRef::l_contains_item(lua_State *L)
const char *listname = luaL_checkstring(L, 2);
ItemStack item = read_item(L, 3, getServer(L)->idef());
InventoryList *list = getlist(L, ref, listname);
- if(list){
- lua_pushboolean(L, list->containsItem(item));
+ bool match_meta = false;
+ if (lua_isboolean(L, 4))
+ match_meta = lua_toboolean(L, 4);
+ if (list) {
+ lua_pushboolean(L, list->containsItem(item, match_meta));
} else {
lua_pushboolean(L, false);
}
diff --git a/src/script/lua_api/l_inventory.h b/src/script/lua_api/l_inventory.h
index 91d41c0d0..502827a11 100644
--- a/src/script/lua_api/l_inventory.h
+++ b/src/script/lua_api/l_inventory.h
@@ -93,7 +93,7 @@ private:
// Returns true if the item completely fits into the list
static int l_room_for_item(lua_State *L);
- // contains_item(self, listname, itemstack or itemstring or table or nil) -> true/false
+ // contains_item(self, listname, itemstack or itemstring or table or nil, [match_meta]) -> true/false
// Returns true if the list contains the given count of the given item name
static int l_contains_item(lua_State *L);