summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Color.cpp76
-rw-r--r--src/Color.h58
-rw-r--r--src/CraftingRecipes.cpp192
-rw-r--r--src/CraftingRecipes.h3
-rw-r--r--src/Item.cpp19
-rw-r--r--src/Item.h11
-rw-r--r--src/Protocol/Protocol17x.cpp14
-rw-r--r--src/Protocol/Protocol18x.cpp14
9 files changed, 382 insertions, 6 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6c8fe7d0c..d941b7d4c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -28,6 +28,7 @@ SET (SRCS
ChunkSender.cpp
ChunkStay.cpp
ClientHandle.cpp
+ Color.cpp
CommandOutput.cpp
CompositeChat.cpp
CraftingRecipes.cpp
diff --git a/src/Color.cpp b/src/Color.cpp
new file mode 100644
index 000000000..f2180e2d9
--- /dev/null
+++ b/src/Color.cpp
@@ -0,0 +1,76 @@
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Color.h"
+
+
+
+
+
+#define COLOR_RED_BITS 0x00FF0000
+#define COLOR_GREEN_BITS 0x0000FF00
+#define COLOR_BLUE_BITS 0x000000FF
+#define COLOR_RED_OFFSET 16
+#define COLOR_GREEN_OFFSET 8
+
+
+
+
+
+void cColor::SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue)
+{
+ m_Color = (static_cast<unsigned int>(a_Red) << COLOR_RED_OFFSET) + (static_cast<unsigned int>(a_Green) << COLOR_GREEN_OFFSET) + (static_cast<unsigned int>(a_Blue));
+}
+
+
+
+
+
+void cColor::SetRed(unsigned char a_Red)
+{
+ m_Color = (static_cast<unsigned int>(a_Red) << COLOR_RED_OFFSET) + ((COLOR_GREEN_BITS | COLOR_BLUE_BITS) & m_Color);
+}
+
+
+
+
+
+void cColor::SetGreen(unsigned char a_Green)
+{
+ m_Color = (static_cast<unsigned int>(a_Green) << COLOR_GREEN_OFFSET) + ((COLOR_RED_BITS | COLOR_BLUE_BITS) & m_Color);
+}
+
+
+
+
+
+void cColor::SetBlue(unsigned char a_Blue)
+{
+ m_Color = static_cast<unsigned int>(a_Blue) + ((COLOR_RED_BITS | COLOR_GREEN_BITS) & m_Color);
+}
+
+
+
+
+
+unsigned char cColor::GetRed() const
+{
+ return (m_Color & COLOR_RED_BITS) >> COLOR_RED_OFFSET;
+}
+
+
+
+
+
+unsigned char cColor::GetGreen() const
+{
+ return (m_Color & COLOR_GREEN_BITS) >> COLOR_GREEN_OFFSET;
+}
+
+
+
+
+
+unsigned char cColor::GetBlue() const
+{
+ return m_Color & COLOR_BLUE_BITS;
+}
diff --git a/src/Color.h b/src/Color.h
new file mode 100644
index 000000000..a90e8372b
--- /dev/null
+++ b/src/Color.h
@@ -0,0 +1,58 @@
+
+// Color.h
+
+// Declares a class to handle item color related code
+
+
+
+
+
+#pragma once
+
+ // tolua_begin
+
+class cColor
+{
+public:
+
+ enum
+ {
+ COLOR_MIN = 0,
+ COLOR_MAX = 255,
+ COLOR_LIMIT = 256,
+ COLOR_NONE = 0xFFFFFFFF,
+ };
+ cColor() { m_Color = COLOR_NONE;}
+ cColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue) { SetColor(a_Red, a_Green, a_Blue); }
+
+ /// Returns whether the color is a valid color
+ bool IsValid() const { return m_Color != COLOR_NONE; }
+
+ /// Changes the color
+ void SetColor(unsigned char a_Red, unsigned char a_Green, unsigned char a_Blue);
+
+ /// Alters the red value of the color
+ void SetRed(unsigned char a_Red);
+
+ /// Alters the green value of the color
+ void SetGreen(unsigned char a_Red);
+
+ /// Alters the blue value of the color
+ void SetBlue(unsigned char a_Red);
+
+ /// Returns the red value of the color
+ unsigned char GetRed() const;
+
+ /// Returns the green value of the color
+ unsigned char GetGreen() const;
+
+ /// Returns the blue value of the color
+ unsigned char GetBlue() const;
+
+ /// Resets the color
+ void Clear() { m_Color = COLOR_NONE; }
+ // tolua_end
+
+ unsigned int m_Color;
+
+};
diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp
index 0bb77d341..d3a28292a 100644
--- a/src/CraftingRecipes.cpp
+++ b/src/CraftingRecipes.cpp
@@ -787,6 +787,9 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
// We use Recipe instead of a_Recipe because we want the wildcard ingredients' slot numbers as well, which was just added previously
HandleFireworks(a_CraftingGrid, Recipe.get(), a_GridStride, a_OffsetX, a_OffsetY);
+ // Handle Dyed Leather
+ HandleDyedLeather(a_CraftingGrid, Recipe.get(), a_GridStride, a_GridWidth, a_GridHeight);
+
return Recipe.release();
}
@@ -874,3 +877,192 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
+
+void cCraftingRecipes::HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight)
+{
+ short result_type = a_Recipe->m_Result.m_ItemType;
+ if ((result_type == E_ITEM_LEATHER_CAP) || (result_type == E_ITEM_LEATHER_TUNIC) || (result_type == E_ITEM_LEATHER_PANTS) || (result_type == E_ITEM_LEATHER_BOOTS))
+ {
+ bool found = false;
+ cItem temp;
+
+ float red = 0;
+ float green = 0;
+ float blue = 0;
+ float dye_count = 0;
+
+ for (int x = 0; x < a_GridWidth; ++x)
+ {
+ for (int y = 0; y < a_GridHeight; ++y)
+ {
+ int GridIdx = x + a_GridStride * y;
+ if ((a_CraftingGrid[GridIdx].m_ItemType == result_type) && (found == false))
+ {
+ found = true;
+ temp = a_CraftingGrid[GridIdx].CopyOne();
+ // The original color of the item affects the result
+ if (temp.m_ItemColor.IsValid())
+ {
+ red += temp.m_ItemColor.GetRed();
+ green += temp.m_ItemColor.GetGreen();
+ blue += temp.m_ItemColor.GetBlue();
+ ++dye_count;
+ }
+ }
+ else if (a_CraftingGrid[GridIdx].m_ItemType == E_ITEM_DYE)
+ {
+ switch (a_CraftingGrid[GridIdx].m_ItemDamage)
+ {
+ case E_META_DYE_BLACK:
+ {
+ red += 23;
+ green += 23;
+ blue += 23;
+ break;
+ }
+ case E_META_DYE_RED:
+ {
+ red += 142;
+ green += 47;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_GREEN:
+ {
+ red += 95;
+ green += 118;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_BROWN:
+ {
+ red += 95;
+ green += 71;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_BLUE:
+ {
+ red += 47;
+ green += 71;
+ blue += 165;
+ break;
+ }
+ case E_META_DYE_PURPLE:
+ {
+ red += 118;
+ green += 59;
+ blue += 165;
+ break;
+ }
+ case E_META_DYE_CYAN:
+ {
+ red += 71;
+ green += 118;
+ blue += 142;
+ break;
+ }
+ case E_META_DYE_LIGHTGRAY:
+ {
+ red += 142;
+ green += 142;
+ blue += 142;
+ break;
+ }
+ case E_META_DYE_GRAY:
+ {
+ red += 71;
+ green += 71;
+ blue += 71;
+ break;
+ }
+ case E_META_DYE_PINK:
+ {
+ red += 225;
+ green += 118;
+ blue += 153;
+ break;
+ }
+ case E_META_DYE_LIGHTGREEN:
+ {
+ red += 118;
+ green += 190;
+ blue += 23;
+ break;
+ }
+ case E_META_DYE_YELLOW:
+ {
+ red += 213;
+ green += 213;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_LIGHTBLUE:
+ {
+ red += 95;
+ green += 142;
+ blue += 201;
+ break;
+ }
+ case E_META_DYE_MAGENTA:
+ {
+ red += 165;
+ green += 71;
+ blue += 201;
+ break;
+ }
+ case E_META_DYE_ORANGE:
+ {
+ red += 201;
+ green += 118;
+ blue += 47;
+ break;
+ }
+ case E_META_DYE_WHITE:
+ {
+ red += 237;
+ green += 237;
+ blue += 237;
+ break;
+ }
+ }
+ ++dye_count;
+ }
+ else if (a_CraftingGrid[GridIdx].m_ItemType != E_ITEM_EMPTY)
+ {
+ return;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return;
+ }
+
+ // Calculate the rgb values
+ double maximum = static_cast<double>(std::max({red, green, blue}));
+
+ double average_red = red / dye_count;
+ double average_green = green / dye_count;
+ double average_blue = blue / dye_count;
+ double average_max = maximum / dye_count;
+
+ double max_average = std::max({average_red, average_green, average_blue});
+
+ double gain_factor = average_max / max_average;
+
+
+ unsigned char result_red = static_cast<unsigned char>(average_red * gain_factor);
+ unsigned char result_green = static_cast<unsigned char>(average_green * gain_factor);
+ unsigned char result_blue = static_cast<unsigned char>(average_blue * gain_factor);
+
+ // Set the results values
+ a_Recipe->m_Result = temp;
+ a_Recipe->m_Result.m_ItemColor.SetColor(result_red, result_green, result_blue);
+ }
+}
+
+
+
+
diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h
index 44444d42e..778dd495a 100644
--- a/src/CraftingRecipes.h
+++ b/src/CraftingRecipes.h
@@ -168,6 +168,9 @@ protected:
/** Searches for anything firework related, and does the data setting if appropriate */
void HandleFireworks(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_OffsetX, int a_OffsetY);
+
+ /// Searches for anything dye related for leather, calculates the appropriate color value, and sets the resulting value.
+ void HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight);
} ;
diff --git a/src/Item.cpp b/src/Item.cpp
index 36c444328..7bd344ae8 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -142,6 +142,13 @@ void cItem::GetJson(Json::Value & a_OutValue) const
a_OutValue["Lore"] = m_Lore;
}
+ if (m_ItemColor.IsValid())
+ {
+ a_OutValue["Color_Red"] = m_ItemColor.GetRed();
+ a_OutValue["Color_Green"] = m_ItemColor.GetGreen();
+ a_OutValue["Color_Blue"] = m_ItemColor.GetBlue();
+ }
+
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
{
a_OutValue["Flicker"] = m_FireworkItem.m_HasFlicker;
@@ -172,6 +179,18 @@ void cItem::FromJson(const Json::Value & a_Value)
m_CustomName = a_Value.get("Name", "").asString();
m_Lore = a_Value.get("Lore", "").asString();
+ int red = a_Value.get("Color_Red", -1).asInt();
+ int green = a_Value.get("Color_Green", -1).asInt();
+ int blue = a_Value.get("Color_Blue", -1).asInt();
+ if ((red > -1) && (red < static_cast<int>(cColor::COLOR_LIMIT)) && (green > -1) && (green < static_cast<int>(cColor::COLOR_LIMIT)) && (blue > -1) && (blue < static_cast<int>(cColor::COLOR_LIMIT)))
+ {
+ m_ItemColor.SetColor(static_cast<unsigned char>(red), static_cast<unsigned char>(green), static_cast<unsigned char>(blue));
+ }
+ else if ((red != -1) || (blue != -1) || (green != -1))
+ {
+ LOGWARNING("Item with invalid red, green, and blue values read in from json file.");
+ }
+
if ((m_ItemType == E_ITEM_FIREWORK_ROCKET) || (m_ItemType == E_ITEM_FIREWORK_STAR))
{
m_FireworkItem.m_HasFlicker = a_Value.get("Flicker", false).asBool();
diff --git a/src/Item.h b/src/Item.h
index 056b5eb8a..8f47c4177 100644
--- a/src/Item.h
+++ b/src/Item.h
@@ -12,6 +12,7 @@
#include "Defines.h"
#include "Enchantments.h"
#include "WorldStorage/FireworksSerializer.h"
+#include "Color.h"
@@ -19,6 +20,7 @@
// fwd:
class cItemHandler;
+class cColor;
namespace Json
{
@@ -41,7 +43,8 @@ public:
m_CustomName(""),
m_Lore(""),
m_RepairCost(0),
- m_FireworkItem()
+ m_FireworkItem(),
+ m_ItemColor()
{
}
@@ -62,7 +65,8 @@ public:
m_CustomName (a_CustomName),
m_Lore (a_Lore),
m_RepairCost (0),
- m_FireworkItem()
+ m_FireworkItem(),
+ m_ItemColor()
{
if (!IsValidItem(m_ItemType))
{
@@ -105,6 +109,7 @@ public:
m_Lore = "";
m_RepairCost = 0;
m_FireworkItem.EmptyData();
+ m_ItemColor.Clear();
}
@@ -114,6 +119,7 @@ public:
m_ItemCount = 0;
m_ItemDamage = 0;
m_RepairCost = 0;
+ m_ItemColor.Clear();
}
@@ -206,6 +212,7 @@ public:
int m_RepairCost;
cFireworkItem m_FireworkItem;
+ cColor m_ItemColor;
};
// tolua_end
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index c5c0f4a03..ff134c754 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -2646,6 +2646,10 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
a_Item.m_Lore = Lore;
}
+ else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color"))
+ {
+ a_Item.m_ItemColor.m_Color = static_cast<unsigned int>(NBT.GetInt(displaytag));
+ }
}
}
else if ((TagName == "Fireworks") || (TagName == "Explosion"))
@@ -2732,7 +2736,7 @@ void cProtocol172::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
a_Pkt.WriteBEInt8(a_Item.m_ItemCount);
a_Pkt.WriteBEInt16(a_Item.m_ItemDamage);
- if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
+ if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid())
{
a_Pkt.WriteBEInt16(-1);
return;
@@ -2749,9 +2753,15 @@ void cProtocol172::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
}
- if (!a_Item.IsBothNameAndLoreEmpty())
+ if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid())
{
Writer.BeginCompound("display");
+
+ if (a_Item.m_ItemColor.IsValid())
+ {
+ Writer.AddInt("color", static_cast<int>(a_Item.m_ItemColor.m_Color));
+ }
+
if (!a_Item.IsCustomNameEmpty())
{
Writer.AddString("Name", a_Item.m_CustomName.c_str());
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index 99bba63e3..c435f6e40 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -2898,6 +2898,10 @@ void cProtocol180::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
a_Item.m_Lore = Lore;
}
+ else if ((NBT.GetType(displaytag) == TAG_Int) && (NBT.GetName(displaytag) == "color"))
+ {
+ a_Item.m_ItemColor.m_Color = static_cast<unsigned int>(NBT.GetInt(displaytag));
+ }
}
}
else if ((TagName == "Fireworks") || (TagName == "Explosion"))
@@ -3047,12 +3051,13 @@ void cProtocol180::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
a_Pkt.WriteBEInt8(a_Item.m_ItemCount);
a_Pkt.WriteBEInt16(a_Item.m_ItemDamage);
- if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR))
+ if (a_Item.m_Enchantments.IsEmpty() && a_Item.IsBothNameAndLoreEmpty() && (a_Item.m_ItemType != E_ITEM_FIREWORK_ROCKET) && (a_Item.m_ItemType != E_ITEM_FIREWORK_STAR) && !a_Item.m_ItemColor.IsValid())
{
a_Pkt.WriteBEInt8(0);
return;
}
+
// Send the enchantments and custom names:
cFastNBTWriter Writer;
if (a_Item.m_RepairCost != 0)
@@ -3064,9 +3069,14 @@ void cProtocol180::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName);
}
- if (!a_Item.IsBothNameAndLoreEmpty())
+ if (!a_Item.IsBothNameAndLoreEmpty() || a_Item.m_ItemColor.IsValid())
{
Writer.BeginCompound("display");
+ if (a_Item.m_ItemColor.IsValid())
+ {
+ Writer.AddInt("color", static_cast<int>(a_Item.m_ItemColor.m_Color));
+ }
+
if (!a_Item.IsCustomNameEmpty())
{
Writer.AddString("Name", a_Item.m_CustomName.c_str());