summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Pioch <lukas@zgow.de>2017-08-23 18:09:47 +0200
committerLukas Pioch <lukas@zgow.de>2017-08-27 17:49:08 +0200
commita5bae9f2f37921bfcf6203282155a8779c818120 (patch)
treeb51bcc42cdc65fd7d0d76fd312216ec0720c706a
parentAdded a new param to OnPlayerEditingBook and changed the names (diff)
downloadcuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar.gz
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar.bz2
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar.lz
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar.xz
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.tar.zst
cuberite-a5bae9f2f37921bfcf6203282155a8779c818120.zip
Diffstat (limited to '')
-rw-r--r--Server/Plugins/APIDump/APIDesc.lua125
-rw-r--r--src/Bindings/CMakeLists.txt2
-rw-r--r--src/Bindings/ManualBindings.cpp184
-rw-r--r--src/Bindings/PluginManager.h2
-rw-r--r--src/BookContent.cpp12
-rw-r--r--src/BookContent.h30
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Item.cpp4
-rw-r--r--src/Protocol/Protocol_1_9.cpp32
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp4
10 files changed, 330 insertions, 67 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua
index 73443aa41..5768e89f6 100644
--- a/Server/Plugins/APIDump/APIDesc.lua
+++ b/Server/Plugins/APIDump/APIDesc.lua
@@ -7022,10 +7022,37 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
cBookContent =
{
Desc = [[
-This class contains the information for a signed or writeable book: The author, title and the pages. A page of the writeable book is a simple string. For a signed book it can be a json string. For the json string use {{cCompositeChat}} to create a page and then the function {{cCompositeChat#CreateJsonString_1|CreateJsonString}} to get the json string.
+This class contains the information for a signed or writeable book: The author, title and the pages. A page of the writeable book is a simple string. For a signed book it can be a json string. Use {{cCompositeChat}} to create a more complex page with formatting.
]],
Functions =
{
+ AddPage =
+ {
+ {
+ Params =
+ {
+ {
+ Name = "Page",
+ Type = "string",
+ },
+ },
+ Notes = "Add a page to the end of the book",
+ },
+ {
+ Params =
+ {
+ {
+ Name = "Page",
+ Type = "cCompositeChat",
+ },
+ },
+ Notes = "Add a page to the end of the book. For signed book saves it as json string, otherwise as simple string",
+ }
+ },
+ Clear =
+ {
+ Notes = "Clears the whole book",
+ },
constructor =
{
Returns =
@@ -7036,18 +7063,17 @@ This class contains the information for a signed or writeable book: The author,
},
Notes = "Creates a empty book",
},
- SetAuthor =
+ GetAuthor =
{
- Params =
+ Returns =
{
{
- Name = "Author",
Type = "string",
},
},
- Notes = "Set the author of the book",
+ Notes = "Returns the author of the book",
},
- GetAuthor =
+ GetTitle =
{
Returns =
{
@@ -7055,74 +7081,109 @@ This class contains the information for a signed or writeable book: The author,
Type = "string",
},
},
- Notes = "Get the author of the book",
+ Notes = "Returns the title of the book",
},
- SetTitle =
+ GetPage =
{
Params =
{
{
- Name = "Title",
+ Type = "number",
+ },
+ },
+ Returns =
+ {
+ {
Type = "string",
},
},
- Notes = "Set the title of the book",
+ Notes = "Returns the page at the given index, can be a json string or a simple string. Note: one-based",
},
- GetTitle =
+ GetPages =
{
Returns =
{
{
- Type = "string",
+ Type = "table",
},
},
- Notes = "Returns the title of the book",
+ Notes = "Returns the pages of the book as a table",
},
- AddPage =
+ IsEmpty =
+ {
+ Returns =
+ {
+ {
+ Type = "boolean",
+ },
+ },
+ Notes = "Returns true if the book has no author, title and no pages",
+ },
+ SetAuthor =
{
Params =
{
{
- Name = "Page",
+ Name = "Author",
Type = "string",
},
},
- Notes = "Add a page to the end of the book. Note: If it's a written book, the page can be a json string",
+ Notes = "Set the author of the book",
},
- GetPages =
+ SetPage =
{
- Returns =
{
+ Params =
{
- Type = "table",
+ {
+ Name = "Index",
+ Type = "number",
+ },
+ {
+ Name = "Page",
+ Type = "string",
+ },
},
+ Notes = "Set's the page at the given index. Note: one-based",
+ },
+ {
+ Params =
+ {
+ {
+ Name = "Index",
+ Type = "number",
+ },
+ {
+ Name = "Page",
+ Type = "cCompositeChat",
+ },
+ },
+ Notes = "Set's the page at the given index. For signed book saves it as json string, otherwise as simple string. Note: one-based",
},
- Notes = "Returns the pages of the book as a table",
},
SetPages =
{
- Params =
{
+ Params =
{
- Name = "Pages",
- Type = "table",
+ {
+ Name = "Pages",
+ Type = "table",
+ },
},
+ Notes = "Sets all pages of the book. A entry can be a string or a {{cCompositeChat}}",
},
- Notes = "Set the pages of the book",
},
- Clear =
- {
- Notes = "Clears the whole book",
- },
- IsEmpty =
+ SetTitle =
{
- Returns =
+ Params =
{
{
- Type = "boolean",
+ Name = "Title",
+ Type = "string",
},
},
- Notes = "Returns true if the book has no author, title and no pages",
+ Notes = "Set the title of the book",
},
},
},
diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt
index 7b1635a4a..15d629117 100644
--- a/src/Bindings/CMakeLists.txt
+++ b/src/Bindings/CMakeLists.txt
@@ -85,6 +85,7 @@ set(BINDING_DEPENDENCIES
../BlockEntities/FlowerPotEntity.h
../BlockID.h
../BlockInfo.h
+ ../BookContent.h
../BoundingBox.h
../ChatColor.h
../ChunkDef.h
@@ -143,7 +144,6 @@ set(BINDING_DEPENDENCIES
../Vector3.h
../WebAdmin.h
../World.h
- ../BookContent.h
)
if (NOT MSVC)
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index 2a08e3e56..32711223d 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -3967,6 +3967,93 @@ static int tolua_cEntity_GetSpeed(lua_State * tolua_S)
+static int tolua_cBookContent_AddPage(lua_State * tolua_S)
+{
+ // cBookContent:AddPage(string)
+ // cBookContent:AddPage(cCompositeChat)
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamSelf("cBookContent") ||
+ lua_isnil(L, 2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ cBookContent * BookContent = nullptr;
+ L.GetStackValue(1, BookContent);
+
+ // Check type of second param
+ if (L.GetTypeText(2) == "string")
+ {
+ AString Page;
+ L.GetStackValue(2, Page);
+ BookContent->AddPage(Page);
+ }
+ else if (L.CheckParamUserType(2, "cCompositeChat"))
+ {
+ cCompositeChat * CompositeChat = nullptr;
+ L.GetStackValue(2, CompositeChat);
+ if (BookContent->IsSigned())
+ {
+ BookContent->AddPage(CompositeChat->CreateJsonString());
+ }
+ else
+ {
+ BookContent->AddPage(CompositeChat->ExtractText());
+ }
+ }
+ else
+ {
+ return L.ApiParamError("Expected a string or a cCompositeChat.");
+ }
+ return 0;
+}
+
+
+
+
+
+static int tolua_cBookContent_GetPage(lua_State * tolua_S)
+{
+ // cBookContent::GetPage(Index) -> string
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamSelf("cBookContent") ||
+ !L.CheckParamNumber(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+
+ cBookContent * BookContent = nullptr;
+ size_t Index;
+ L.GetStackValues(1, BookContent, Index);
+
+ if (BookContent->GetPages().empty())
+ {
+ return L.ApiParamError("Getting the page at the index is not possbile. The book has no pages.");
+ }
+
+ // Check if the index is valid
+ if ((Index <= 0) || (Index > BookContent->GetPages().size()))
+ {
+ return L.ApiParamError("Index %d out of range. The valid range is %d - %d.", Index, 1, BookContent->GetPages().size());
+ }
+
+ L.Push(BookContent->GetPage(Index - 1));
+ return 1;
+
+}
+
+
+
+
+
static int tolua_cBookContent_GetPages(lua_State * tolua_S)
{
// cBookContent::GetPages() -> table of strings
@@ -3990,6 +4077,68 @@ static int tolua_cBookContent_GetPages(lua_State * tolua_S)
+static int tolua_cBookContent_SetPage(lua_State * tolua_S)
+{
+ // cBookContent::SetPage(index, string)
+ // cBookContent::SetPage(index, cCompositeChat)
+
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamSelf("cBookContent") ||
+ !L.CheckParamNumber(2) ||
+ lua_isnil(L, 3) ||
+ !L.CheckParamEnd(4)
+ )
+ {
+ return 0;
+ }
+
+ cBookContent * BookContent = nullptr;
+ size_t Index;
+ L.GetStackValues(1, BookContent, Index);
+
+ if (BookContent->GetPages().empty())
+ {
+ return L.ApiParamError("Changing the page at the index is not possbile. The book has no pages.");
+ }
+
+ // Check if the index is valid
+ if ((Index <= 0) || (Index > BookContent->GetPages().size()))
+ {
+ return L.ApiParamError("The index %d is out of range. The valid range is %d to %d.", Index, 1, BookContent->GetPages().size());
+ }
+
+ // Check type of third param
+ if (L.GetTypeText(3) == "string")
+ {
+ AString Page;
+ L.GetStackValue(3, Page);
+ BookContent->SetPage(Index - 1, Page);
+ }
+ else if (L.CheckParamUserType(3, "cCompositeChat"))
+ {
+ cCompositeChat * CompositeChat = nullptr;
+ L.GetStackValue(3, CompositeChat);
+ if (BookContent->IsSigned())
+ {
+ BookContent->SetPage(Index - 1, CompositeChat->CreateJsonString());
+ }
+ else
+ {
+ BookContent->SetPage(Index - 1, CompositeChat->ExtractText());
+ }
+ }
+ else
+ {
+ return L.ApiParamError("Expected a string or a cCompositeChat.");
+ }
+ return 0;
+}
+
+
+
+
+
static int tolua_cBookContent_SetPages(lua_State * tolua_S)
{
// cBookContent::SetPages(table)
@@ -4010,9 +4159,25 @@ static int tolua_cBookContent_SetPages(lua_State * tolua_S)
BookContent->ClearPages();
Pages->ForEachArrayElement([=](cLuaState & a_LuaState, int a_Index) -> bool
{
- AString Page;
- a_LuaState.GetStackValue(-1, Page);
- BookContent->AddPage(Page);
+ if (a_LuaState.GetTypeText(-1) == "string")
+ {
+ AString Page;
+ a_LuaState.GetStackValue(-1, Page);
+ BookContent->AddPage(Page);
+ }
+ else if (a_LuaState.CheckParamUserType(-1, "cCompositeChat"))
+ {
+ cCompositeChat * CompositeChat = nullptr;
+ a_LuaState.GetStackValue(-1, CompositeChat);
+ if (BookContent->IsSigned())
+ {
+ BookContent->AddPage(CompositeChat->CreateJsonString());
+ }
+ else
+ {
+ BookContent->AddPage(CompositeChat->ExtractText());
+ }
+ }
return false;
}
);
@@ -4051,6 +4216,14 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode);
tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead
+ tolua_beginmodule(tolua_S, "cBookContent");
+ tolua_function(tolua_S, "AddPage", tolua_cBookContent_AddPage);
+ tolua_function(tolua_S, "GetPage", tolua_cBookContent_GetPage);
+ tolua_function(tolua_S, "GetPages", tolua_cBookContent_GetPages);
+ tolua_function(tolua_S, "SetPage", tolua_cBookContent_SetPage);
+ tolua_function(tolua_S, "SetPages", tolua_cBookContent_SetPages);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cBoundingBox");
tolua_function(tolua_S, "CalcLineIntersection", tolua_cBoundingBox_CalcLineIntersection);
tolua_function(tolua_S, "Intersect", tolua_cBoundingBox_Intersect);
@@ -4250,11 +4423,6 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, nullptr);
tolua_endmodule(tolua_S);
- tolua_beginmodule(tolua_S, "cBookContent");
- tolua_function(tolua_S, "GetPages", tolua_cBookContent_GetPages);
- tolua_function(tolua_S, "SetPages", tolua_cBookContent_SetPages);
- tolua_endmodule(tolua_S);
-
BindNetwork(tolua_S);
BindRankManager(tolua_S);
BindWorld(tolua_S);
diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h
index d7bbf62c2..0c02404d2 100644
--- a/src/Bindings/PluginManager.h
+++ b/src/Bindings/PluginManager.h
@@ -248,7 +248,7 @@ public:
bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username);
bool CallHookHopperPullingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_DstSlotNum, cBlockEntityWithItems & a_SrcEntity, int a_SrcSlotNum);
bool CallHookHopperPushingItem (cWorld & a_World, cHopperEntity & a_Hopper, int a_SrcSlotNum, cBlockEntityWithItems & a_DstEntity, int a_DstSlotNum);
- bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage);
+ bool CallHookKilled (cEntity & a_Victim, TakeDamageInfo & a_TDI, AString & a_DeathMessage);
bool CallHookKilling (cEntity & a_Victim, cEntity * a_Killer, TakeDamageInfo & a_TDI);
bool CallHookLogin (cClientHandle & a_Client, UInt32 a_ProtocolVersion, const AString & a_Username);
bool CallHookPlayerAnimation (cPlayer & a_Player, int a_Animation);
diff --git a/src/BookContent.cpp b/src/BookContent.cpp
index 4163d77d1..40819316b 100644
--- a/src/BookContent.cpp
+++ b/src/BookContent.cpp
@@ -80,8 +80,16 @@ void cBookContent::WriteToNBTCompound(const cBookContent & a_BookContent, cFastN
return;
}
- a_Writer.AddString("author", a_BookContent.GetAuthor());
- a_Writer.AddString("title", a_BookContent.GetTitle());
+ if (!a_BookContent.GetAuthor().empty())
+ {
+ a_Writer.AddString("author", a_BookContent.GetAuthor());
+
+ }
+ if (!a_BookContent.GetTitle().empty())
+ {
+ a_Writer.AddString("title", a_BookContent.GetTitle());
+
+ }
a_Writer.BeginList("pages", TAG_String);
for (const auto & Page : a_BookContent.GetPages())
{
diff --git a/src/BookContent.h b/src/BookContent.h
index 43fd93742..f8a6b6a38 100644
--- a/src/BookContent.h
+++ b/src/BookContent.h
@@ -14,7 +14,9 @@ class cBookContent
{
public:
/** Creates a empty book */
- cBookContent() {}
+ cBookContent():
+ m_IsSigned(false)
+ {}
/** Set the author of the book */
void SetAuthor(const AString & a_Author) { m_Author = a_Author; }
@@ -28,9 +30,6 @@ public:
/** Returns the title of the book */
const AString & GetTitle(void) const { return m_Title; }
- /** Add a page to the end of the book */
- void AddPage(const AString & a_Page) { m_Pages.emplace_back(a_Page); }
-
/** Clears the whole book */
void Clear();
@@ -39,13 +38,29 @@ public:
// tolua_end
+ /** Required in ManualBindings to save the page as simple string or json string */
+ void SetIsSigned(bool a_IsSigned) { m_IsSigned = a_IsSigned; }
+
+ /** Returns true if the book is signed */
+ bool IsSigned(void) const { return m_IsSigned; }
+
+ /** Add a page to the end of the book */
+ void AddPage(const AString & a_Page) { m_Pages.emplace_back(a_Page); }
+
+ /** Returns the page at the index */
+ const AString & GetPage(size_t a_Index) { return m_Pages[a_Index]; }
+
+ /** Changes the page at the index */
+ void SetPage(size_t a_Index, const AString & a_Page) { m_Pages[a_Index] = a_Page; }
+
+ /** Removes all pages */
void ClearPages(void)
{
m_Pages.clear();
}
- /** Returns a AStringVector ref to the pages. Used in ManualBindings and for saving the book */
- const AStringVector & GetPages(void) const { return m_Pages; }
+ /** Returns a ref to the vector. Used in ManualBindings and for saving the book */
+ const std::vector<AString> & GetPages(void) const { return m_Pages; }
/** Read the book content from nbt. The boolean a_SaveAsJson is optional. If the book is signed, the text should be in a json string */
static void ParseFromNBT(int TagTag, cBookContent & a_BookContent, const cParsedNBT & a_NBT, bool a_SaveAsJson = false);
@@ -63,4 +78,7 @@ private:
/** Contains the pages */
AStringVector m_Pages;
+ /** If true the book is written */
+ bool m_IsSigned;
+
}; // tolua_export
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a71da1363..548fa746c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -85,6 +85,7 @@ SET (HDRS
BlockInServerPluginInterface.h
BlockInfo.h
BlockTracer.h
+ BookContent.h
BrewingRecipes.h
Broadcaster.h
BoundingBox.h
@@ -154,7 +155,6 @@ SET (HDRS
VoronoiMap.h
WebAdmin.h
World.h
- BookContent.h
XMLParser.h
)
diff --git a/src/Item.cpp b/src/Item.cpp
index 412c66ec3..09f8f39d7 100644
--- a/src/Item.cpp
+++ b/src/Item.cpp
@@ -258,6 +258,10 @@ void cItem::FromJson(const Json::Value & a_Value)
{
m_BookContent.SetAuthor(a_Value.get("author", "").asString());
m_BookContent.SetTitle(a_Value.get("title", "").asString());
+ if (m_ItemType == E_ITEM_WRITTEN_BOOK)
+ {
+ m_BookContent.SetIsSigned(true);
+ }
if (a_Value.isMember("pages"))
{
for (Json::Value::ArrayIndex i = 0; i != a_Value["pages"].size(); i++)
diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp
index 712658329..8e43fd2cc 100644
--- a/src/Protocol/Protocol_1_9.cpp
+++ b/src/Protocol/Protocol_1_9.cpp
@@ -2966,20 +2966,24 @@ void cProtocol_1_9_0::HandleVanillaPluginMessage(cByteBuffer & a_ByteBuffer, con
BookItem = cItem(E_ITEM_BOOK_AND_QUILL);
cBookContent::ParseFromNBT(0, BookItem.m_BookContent, NBT);
}
+ BookItem.m_BookContent.SetIsSigned(IsSigned);
// The equipped item contains the old book content
if (cRoot::Get()->GetPluginManager()->CallHookPlayerEditingBook(Player, Player.GetEquippedItem().m_BookContent, BookItem.m_BookContent, IsSigned))
{
- // Plugin denied the editing of the book
+ // Plugin denied the player to edit the book
+ cInventory & inv = Player.GetInventory();
+ inv.SetHotbarSlot(inv.GetEquippedSlotNum(), BookItem);
+ Player.GetInventory().SendEquippedSlot();
return;
}
- // Book has been edited, inform plugins
- cRoot::Get()->GetPluginManager()->CallHookPlayerEditedBook(Player, BookItem.m_BookContent, IsSigned);
-
cInventory & inv = Player.GetInventory();
inv.SetHotbarSlot(inv.GetEquippedSlotNum(), BookItem);
Player.GetInventory().SendEquippedSlot();
+
+ // Book has been edited by player, inform plugins
+ cRoot::Get()->GetPluginManager()->CallHookPlayerEditedBook(Player, BookItem.m_BookContent, IsSigned);
return;
}
LOG("Unhandled vanilla plugin channel: \"%s\".", a_Channel.c_str());
@@ -3418,9 +3422,9 @@ void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
return;
}
- if ((ItemType == E_ITEM_BOOK_AND_QUILL) && (a_Item.m_BookContent.GetPages().size() == 0))
+ if ((ItemType == E_ITEM_BOOK_AND_QUILL) && a_Item.m_BookContent.GetPages().empty())
{
- // Don't send any nbt tag if the book is writeable and has no pages
+ // Don't send any nbt tag if the book is not signed and has no pages
// If a tag with a empty pages list is send, the player can't enter anything
a_Pkt.WriteBEInt8(0);
return;
@@ -3539,24 +3543,24 @@ void cProtocol_1_9_0::WriteItem(cPacketizer & a_Pkt, const cItem & a_Item)
{
if (a_Item.m_ItemType == E_ITEM_WRITTEN_BOOK)
{
- // Only send author and title for a signed book
+ // Only send author and title if the book is signed
Writer.AddString("author", a_Item.m_BookContent.GetAuthor());
Writer.AddString("title", a_Item.m_BookContent.GetTitle());
}
- if (a_Item.m_BookContent.GetPages().size() > 0)
+ if (a_Item.m_BookContent.GetPages().empty())
{
+ // A signed book, has a empty page
Writer.BeginList("pages", TAG_String);
- for (auto & Page : a_Item.m_BookContent.GetPages())
- {
- Writer.AddString("", Page);
- }
+ Writer.AddString("", "");
Writer.EndList();
}
else
{
- // A signed book, has a empty page
Writer.BeginList("pages", TAG_String);
- Writer.AddString("", "");
+ for (const auto & Page : a_Item.m_BookContent.GetPages())
+ {
+ Writer.AddString("", Page);
+ }
Writer.EndList();
}
}
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index 702439133..df627006c 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -106,8 +106,8 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin
// Write the tag compound (for enchantment, firework, custom name and repair cost):
if (
(!a_Item.m_Enchantments.IsEmpty()) ||
- ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ||
- (a_Item.m_ItemType == E_ITEM_WRITTEN_BOOK)) || (a_Item.m_ItemType == E_ITEM_BOOK_AND_QUILL) ||
+ (a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ||
+ (a_Item.m_ItemType == E_ITEM_WRITTEN_BOOK) || (a_Item.m_ItemType == E_ITEM_BOOK_AND_QUILL) ||
(a_Item.m_RepairCost > 0) ||
(a_Item.m_CustomName != "") ||
(!a_Item.m_LoreTable.empty())