summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua1
-rw-r--r--VC2008/MCServer.vcproj8
-rw-r--r--source/AllToLua.pkg1
-rw-r--r--source/Bindings.cpp527
-rw-r--r--source/Bindings.h2
-rw-r--r--source/Enchantments.cpp231
-rw-r--r--source/Enchantments.h105
-rw-r--r--source/Item.h35
-rw-r--r--source/Protocol/Protocol132.cpp73
-rw-r--r--source/Protocol/Protocol132.h3
-rw-r--r--source/StringCompression.cpp129
-rw-r--r--source/StringCompression.h12
-rw-r--r--source/WorldStorage/NBTChunkSerializer.cpp10
13 files changed, 1082 insertions, 55 deletions
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index f35e2d2de..fb2601470 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -595,6 +595,7 @@ function HandleTestWndCmd(a_Split, a_Player)
local Window = cLuaWindow(WindowType, WindowSizeX, WindowSizeY, "TestWnd");
Window:SetSlot(a_Player, 0, cItem(E_ITEM_DIAMOND, 64));
+ Window:SetSlot(a_Player, 1, cItem(E_ITEM_DIAMOND_SWORD, 1, 0, "1=1"));
Window:SetOnClosing(OnClosing);
Window:SetOnSlotChanged(OnSlotChanged);
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index 2d0e9d94e..c44356545 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -383,6 +383,14 @@
>
</File>
<File
+ RelativePath="..\source\Enchantments.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\Enchantments.h"
+ >
+ </File>
+ <File
RelativePath="..\source\Endianness.h"
>
</File>
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index 1cb57ebd0..ee098e63e 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -37,6 +37,7 @@ $cfile "Plugin_NewLua.h"
$cfile "Server.h"
$cfile "World.h"
$cfile "Inventory.h"
+$cfile "Enchantments.h"
$cfile "Item.h"
$cfile "ItemGrid.h"
$cfile "BlockEntities/BlockEntity.h"
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index 28d691085..50f417cc1 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 06/01/13 09:50:23.
+** Generated automatically by tolua++-1.0.92 on 06/02/13 12:36:50.
*/
#ifndef __cplusplus
@@ -36,6 +36,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
#include "Server.h"
#include "World.h"
#include "Inventory.h"
+#include "Enchantments.h"
#include "Item.h"
#include "ItemGrid.h"
#include "BlockEntities/BlockEntity.h"
@@ -64,86 +65,93 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S);
/* function to release collected object via destructor */
#ifdef __cplusplus
-static int tolua_collect_cIniFile (lua_State* tolua_S)
+static int tolua_collect_cItem (lua_State* tolua_S)
{
- cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
+ cItem* self = (cItem*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cCraftingGrid (lua_State* tolua_S)
+static int tolua_collect_Vector3f (lua_State* tolua_S)
{
- cCraftingGrid* self = (cCraftingGrid*) tolua_tousertype(tolua_S,1,0);
+ Vector3f* self = (Vector3f*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cItem (lua_State* tolua_S)
+static int tolua_collect_cChestEntity (lua_State* tolua_S)
{
- cItem* self = (cItem*) tolua_tousertype(tolua_S,1,0);
+ cChestEntity* self = (cChestEntity*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_Vector3f (lua_State* tolua_S)
+static int tolua_collect_cDispenserEntity (lua_State* tolua_S)
{
- Vector3f* self = (Vector3f*) tolua_tousertype(tolua_S,1,0);
+ cDispenserEntity* self = (cDispenserEntity*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cDropperEntity (lua_State* tolua_S)
+static int tolua_collect_cCuboid (lua_State* tolua_S)
{
- cDropperEntity* self = (cDropperEntity*) tolua_tousertype(tolua_S,1,0);
+ cCuboid* self = (cCuboid*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cPickup (lua_State* tolua_S)
+static int tolua_collect_cBlockEntity (lua_State* tolua_S)
{
- cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
+ cBlockEntity* self = (cBlockEntity*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cItems (lua_State* tolua_S)
+static int tolua_collect_cBlockArea (lua_State* tolua_S)
{
- cItems* self = (cItems*) tolua_tousertype(tolua_S,1,0);
+ cBlockArea* self = (cBlockArea*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cBlockArea (lua_State* tolua_S)
+static int tolua_collect_cEnchantments (lua_State* tolua_S)
{
- cBlockArea* self = (cBlockArea*) tolua_tousertype(tolua_S,1,0);
+ cEnchantments* self = (cEnchantments*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cChestEntity (lua_State* tolua_S)
+static int tolua_collect_cLuaWindow (lua_State* tolua_S)
{
- cChestEntity* self = (cChestEntity*) tolua_tousertype(tolua_S,1,0);
+ cLuaWindow* self = (cLuaWindow*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cDispenserEntity (lua_State* tolua_S)
+static int tolua_collect_cDropperEntity (lua_State* tolua_S)
{
- cDispenserEntity* self = (cDispenserEntity*) tolua_tousertype(tolua_S,1,0);
+ cDropperEntity* self = (cDropperEntity*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cCuboid (lua_State* tolua_S)
+static int tolua_collect_cPickup (lua_State* tolua_S)
{
- cCuboid* self = (cCuboid*) tolua_tousertype(tolua_S,1,0);
+ cPickup* self = (cPickup*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cBlockEntity (lua_State* tolua_S)
+static int tolua_collect_cItems (lua_State* tolua_S)
{
- cBlockEntity* self = (cBlockEntity*) tolua_tousertype(tolua_S,1,0);
+ cItems* self = (cItems*) tolua_tousertype(tolua_S,1,0);
+ Mtolua_delete(self);
+ return 0;
+}
+
+static int tolua_collect_cCraftingGrid (lua_State* tolua_S)
+{
+ cCraftingGrid* self = (cCraftingGrid*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
@@ -155,16 +163,16 @@ static int tolua_collect_Vector3i (lua_State* tolua_S)
return 0;
}
-static int tolua_collect_cTracer (lua_State* tolua_S)
+static int tolua_collect_cIniFile (lua_State* tolua_S)
{
- cTracer* self = (cTracer*) tolua_tousertype(tolua_S,1,0);
+ cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
-static int tolua_collect_cLuaWindow (lua_State* tolua_S)
+static int tolua_collect_cTracer (lua_State* tolua_S)
{
- cLuaWindow* self = (cLuaWindow*) tolua_tousertype(tolua_S,1,0);
+ cTracer* self = (cTracer*) tolua_tousertype(tolua_S,1,0);
Mtolua_delete(self);
return 0;
}
@@ -182,13 +190,14 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"TakeDamageInfo");
- tolua_usertype(tolua_S,"cCraftingRecipe");
- tolua_usertype(tolua_S,"cPlugin_NewLua");
tolua_usertype(tolua_S,"cCraftingGrid");
+ tolua_usertype(tolua_S,"cCraftingRecipe");
+ tolua_usertype(tolua_S,"cPlugin");
+ tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cStringMap");
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cBlockArea");
- tolua_usertype(tolua_S,"cWindow");
+ tolua_usertype(tolua_S,"cEnchantments");
tolua_usertype(tolua_S,"cLuaWindow");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
@@ -221,12 +230,12 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cItemGrid::cListener");
tolua_usertype(tolua_S,"cDropperEntity");
- tolua_usertype(tolua_S,"cPlugin");
+ tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cLadder");
- tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cCriticalSection");
+ tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cIniFile");
tolua_usertype(tolua_S,"cListeners");
tolua_usertype(tolua_S,"AStringVector");
@@ -234,8 +243,8 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cPlayer");
tolua_usertype(tolua_S,"cTorch");
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
- tolua_usertype(tolua_S,"cServer");
tolua_usertype(tolua_S,"cWorld");
+ tolua_usertype(tolua_S,"cPlugin_NewLua");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"Lua__cEntity");
tolua_usertype(tolua_S,"Vector3d");
@@ -13828,6 +13837,314 @@ static int tolua_AllToLua_cInventory_GetEquippedBoots00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: new of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_new00
+static int tolua_AllToLua_cEnchantments_new00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ {
+ cEnchantments* tolua_ret = (cEnchantments*) Mtolua_new((cEnchantments)());
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cEnchantments");
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_new00_local
+static int tolua_AllToLua_cEnchantments_new00_local(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ {
+ cEnchantments* tolua_ret = (cEnchantments*) Mtolua_new((cEnchantments)());
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cEnchantments");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'new'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_new01
+static int tolua_AllToLua_cEnchantments_new01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const AString a_StringSpec = ((const AString) tolua_tocppstring(tolua_S,2,0));
+ {
+ cEnchantments* tolua_ret = (cEnchantments*) Mtolua_new((cEnchantments)(a_StringSpec));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cEnchantments");
+ tolua_pushcppstring(tolua_S,(const char*)a_StringSpec);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cEnchantments_new00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_new01_local
+static int tolua_AllToLua_cEnchantments_new01_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const AString a_StringSpec = ((const AString) tolua_tocppstring(tolua_S,2,0));
+ {
+ cEnchantments* tolua_ret = (cEnchantments*) Mtolua_new((cEnchantments)(a_StringSpec));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cEnchantments");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ tolua_pushcppstring(tolua_S,(const char*)a_StringSpec);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cEnchantments_new00_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: AddFromString of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_AddFromString00
+static int tolua_AllToLua_cEnchantments_AddFromString00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEnchantments* self = (cEnchantments*) tolua_tousertype(tolua_S,1,0);
+ const AString a_StringSpec = ((const AString) tolua_tocppstring(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddFromString'", NULL);
+#endif
+ {
+ self->AddFromString(a_StringSpec);
+ tolua_pushcppstring(tolua_S,(const char*)a_StringSpec);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'AddFromString'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: ToString of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_ToString00
+static int tolua_AllToLua_cEnchantments_ToString00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cEnchantments",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cEnchantments* self = (const cEnchantments*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ToString'", NULL);
+#endif
+ {
+ AString tolua_ret = (AString) self->ToString();
+ tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'ToString'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: GetLevel of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_GetLevel00
+static int tolua_AllToLua_cEnchantments_GetLevel00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cEnchantments",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cEnchantments* self = (const cEnchantments*) tolua_tousertype(tolua_S,1,0);
+ int a_EnchantmentID = ((int) tolua_tonumber(tolua_S,2,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'GetLevel'", NULL);
+#endif
+ {
+ int tolua_ret = (int) self->GetLevel(a_EnchantmentID);
+ tolua_pushnumber(tolua_S,(lua_Number)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'GetLevel'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: SetLevel of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_SetLevel00
+static int tolua_AllToLua_cEnchantments_SetLevel00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,4,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEnchantments* self = (cEnchantments*) tolua_tousertype(tolua_S,1,0);
+ int a_EnchantmentID = ((int) tolua_tonumber(tolua_S,2,0));
+ int a_Level = ((int) tolua_tonumber(tolua_S,3,0));
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'SetLevel'", NULL);
+#endif
+ {
+ self->SetLevel(a_EnchantmentID,a_Level);
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'SetLevel'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: Clear of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_Clear00
+static int tolua_AllToLua_cEnchantments_Clear00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"cEnchantments",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ cEnchantments* self = (cEnchantments*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Clear'", NULL);
+#endif
+ {
+ self->Clear();
+ }
+ }
+ return 0;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'Clear'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: IsEmpty of class cEnchantments */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cEnchantments_IsEmpty00
+static int tolua_AllToLua_cEnchantments_IsEmpty00(lua_State* tolua_S)
+{
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertype(tolua_S,1,"const cEnchantments",0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+#endif
+ {
+ const cEnchantments* self = (const cEnchantments*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsEmpty'", NULL);
+#endif
+ {
+ bool tolua_ret = (bool) self->IsEmpty();
+ tolua_pushboolean(tolua_S,(bool)tolua_ret);
+ }
+ }
+ return 1;
+#ifndef TOLUA_RELEASE
+ tolua_lerror:
+ tolua_error(tolua_S,"#ferror in function 'IsEmpty'.",&tolua_err);
+ return 0;
+#endif
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: new of class cItem */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_new00
static int tolua_AllToLua_cItem_new00(lua_State* tolua_S)
@@ -13944,6 +14261,71 @@ tolua_lerror:
}
#endif //#ifndef TOLUA_DISABLE
+/* method: new of class cItem */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_new02
+static int tolua_AllToLua_cItem_new02(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cItem",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,5,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,6,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ short a_ItemType = ((short) tolua_tonumber(tolua_S,2,0));
+ char a_ItemCount = ((char) tolua_tonumber(tolua_S,3,0));
+ short a_ItemDamage = ((short) tolua_tonumber(tolua_S,4,0));
+ const AString a_Enchantments = ((const AString) tolua_tocppstring(tolua_S,5,0));
+ {
+ cItem* tolua_ret = (cItem*) Mtolua_new((cItem)(a_ItemType,a_ItemCount,a_ItemDamage,a_Enchantments));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cItem");
+ tolua_pushcppstring(tolua_S,(const char*)a_Enchantments);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cItem_new01(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cItem */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_new02_local
+static int tolua_AllToLua_cItem_new02_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cItem",0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,3,0,&tolua_err) ||
+ !tolua_isnumber(tolua_S,4,0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,5,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,6,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ short a_ItemType = ((short) tolua_tonumber(tolua_S,2,0));
+ char a_ItemCount = ((char) tolua_tonumber(tolua_S,3,0));
+ short a_ItemDamage = ((short) tolua_tonumber(tolua_S,4,0));
+ const AString a_Enchantments = ((const AString) tolua_tocppstring(tolua_S,5,0));
+ {
+ cItem* tolua_ret = (cItem*) Mtolua_new((cItem)(a_ItemType,a_ItemCount,a_ItemDamage,a_Enchantments));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cItem");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ tolua_pushcppstring(tolua_S,(const char*)a_Enchantments);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cItem_new01_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: Empty of class cItem */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cItem_Empty00
static int tolua_AllToLua_cItem_Empty00(lua_State* tolua_S)
@@ -14400,6 +14782,36 @@ static int tolua_set_cItem_m_ItemDamage(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* get function: m_Enchantments of class cItem */
+#ifndef TOLUA_DISABLE_tolua_get_cItem_m_Enchantments
+static int tolua_get_cItem_m_Enchantments(lua_State* tolua_S)
+{
+ cItem* self = (cItem*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'm_Enchantments'",NULL);
+#endif
+ tolua_pushusertype(tolua_S,(void*)&self->m_Enchantments,"cEnchantments");
+ return 1;
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* set function: m_Enchantments of class cItem */
+#ifndef TOLUA_DISABLE_tolua_set_cItem_m_Enchantments
+static int tolua_set_cItem_m_Enchantments(lua_State* tolua_S)
+{
+ cItem* self = (cItem*) tolua_tousertype(tolua_S,1,0);
+#ifndef TOLUA_RELEASE
+ tolua_Error tolua_err;
+ if (!self) tolua_error(tolua_S,"invalid 'self' in accessing variable 'm_Enchantments'",NULL);
+ if ((tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"cEnchantments",0,&tolua_err)))
+ tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);
+#endif
+ self->m_Enchantments = *((cEnchantments*) tolua_tousertype(tolua_S,2,0))
+;
+ return 0;
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: new of class cItems */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cItems_new00
static int tolua_AllToLua_cItems_new00(lua_State* tolua_S)
@@ -27250,6 +27662,47 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetEquippedBoots",tolua_AllToLua_cInventory_GetEquippedBoots00);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
+ tolua_cclass(tolua_S,"cEnchantments","cEnchantments","",tolua_collect_cEnchantments);
+ #else
+ tolua_cclass(tolua_S,"cEnchantments","cEnchantments","",NULL);
+ #endif
+ tolua_beginmodule(tolua_S,"cEnchantments");
+ tolua_constant(tolua_S,"enchProtection",cEnchantments::enchProtection);
+ tolua_constant(tolua_S,"enchFireProtection",cEnchantments::enchFireProtection);
+ tolua_constant(tolua_S,"enchFeatherFalling",cEnchantments::enchFeatherFalling);
+ tolua_constant(tolua_S,"enchBlastProtection",cEnchantments::enchBlastProtection);
+ tolua_constant(tolua_S,"enchProjectileProtection",cEnchantments::enchProjectileProtection);
+ tolua_constant(tolua_S,"enchRespiration",cEnchantments::enchRespiration);
+ tolua_constant(tolua_S,"enchAquaAffinity",cEnchantments::enchAquaAffinity);
+ tolua_constant(tolua_S,"enchThorns",cEnchantments::enchThorns);
+ tolua_constant(tolua_S,"enchSharpness",cEnchantments::enchSharpness);
+ tolua_constant(tolua_S,"enchSmite",cEnchantments::enchSmite);
+ tolua_constant(tolua_S,"enchBaneOfArthropods",cEnchantments::enchBaneOfArthropods);
+ tolua_constant(tolua_S,"enchKnockback",cEnchantments::enchKnockback);
+ tolua_constant(tolua_S,"enchFireAspect",cEnchantments::enchFireAspect);
+ tolua_constant(tolua_S,"enchLooting",cEnchantments::enchLooting);
+ tolua_constant(tolua_S,"enchEfficiency",cEnchantments::enchEfficiency);
+ tolua_constant(tolua_S,"enchSilkTouch",cEnchantments::enchSilkTouch);
+ tolua_constant(tolua_S,"enchUnbreaking",cEnchantments::enchUnbreaking);
+ tolua_constant(tolua_S,"enchFortune",cEnchantments::enchFortune);
+ tolua_constant(tolua_S,"enchPower",cEnchantments::enchPower);
+ tolua_constant(tolua_S,"enchPunch",cEnchantments::enchPunch);
+ tolua_constant(tolua_S,"enchFlame",cEnchantments::enchFlame);
+ tolua_constant(tolua_S,"enchInfinity",cEnchantments::enchInfinity);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cEnchantments_new00);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cEnchantments_new00_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cEnchantments_new00_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cEnchantments_new01);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cEnchantments_new01_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cEnchantments_new01_local);
+ tolua_function(tolua_S,"AddFromString",tolua_AllToLua_cEnchantments_AddFromString00);
+ tolua_function(tolua_S,"ToString",tolua_AllToLua_cEnchantments_ToString00);
+ tolua_function(tolua_S,"GetLevel",tolua_AllToLua_cEnchantments_GetLevel00);
+ tolua_function(tolua_S,"SetLevel",tolua_AllToLua_cEnchantments_SetLevel00);
+ tolua_function(tolua_S,"Clear",tolua_AllToLua_cEnchantments_Clear00);
+ tolua_function(tolua_S,"IsEmpty",tolua_AllToLua_cEnchantments_IsEmpty00);
+ tolua_endmodule(tolua_S);
+ #ifdef __cplusplus
tolua_cclass(tolua_S,"cItem","cItem","",tolua_collect_cItem);
#else
tolua_cclass(tolua_S,"cItem","cItem","",NULL);
@@ -27261,6 +27714,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"new",tolua_AllToLua_cItem_new01);
tolua_function(tolua_S,"new_local",tolua_AllToLua_cItem_new01_local);
tolua_function(tolua_S,".call",tolua_AllToLua_cItem_new01_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cItem_new02);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cItem_new02_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cItem_new02_local);
tolua_function(tolua_S,"Empty",tolua_AllToLua_cItem_Empty00);
tolua_function(tolua_S,"Clear",tolua_AllToLua_cItem_Clear00);
tolua_function(tolua_S,"IsEmpty",tolua_AllToLua_cItem_IsEmpty00);
@@ -27275,6 +27731,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_variable(tolua_S,"m_ItemType",tolua_get_cItem_m_ItemType,tolua_set_cItem_m_ItemType);
tolua_variable(tolua_S,"m_ItemCount",tolua_get_cItem_m_ItemCount,tolua_set_cItem_m_ItemCount);
tolua_variable(tolua_S,"m_ItemDamage",tolua_get_cItem_m_ItemDamage,tolua_set_cItem_m_ItemDamage);
+ tolua_variable(tolua_S,"m_Enchantments",tolua_get_cItem_m_Enchantments,tolua_set_cItem_m_Enchantments);
tolua_endmodule(tolua_S);
#ifdef __cplusplus
tolua_cclass(tolua_S,"cItems","cItems","",tolua_collect_cItems);
diff --git a/source/Bindings.h b/source/Bindings.h
index 6ec76cc1c..1c7aa7261 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 06/01/13 09:50:24.
+** Generated automatically by tolua++-1.0.92 on 06/02/13 12:36:50.
*/
/* Exported function */
diff --git a/source/Enchantments.cpp b/source/Enchantments.cpp
new file mode 100644
index 000000000..69bf8f7eb
--- /dev/null
+++ b/source/Enchantments.cpp
@@ -0,0 +1,231 @@
+
+// Enchantments.cpp
+
+// Implements the cEnchantments class representing a storage for item enchantments and stored-enchantments
+
+#include "Globals.h"
+#include "Enchantments.h"
+#include "WorldStorage/FastNBT.h"
+
+
+
+
+
+cEnchantments::cEnchantments(void)
+{
+ // Nothing needed yet, but the constructor needs to be declared and impemented in order to be usable
+}
+
+
+
+
+
+cEnchantments::cEnchantments(const AString & a_StringSpec)
+{
+ AddFromString(a_StringSpec);
+}
+
+
+
+
+
+void cEnchantments::AddFromString(const AString & a_StringSpec)
+{
+ // Add enchantments in the stringspec; if a specified enchantment already exists, overwrites it
+
+ // Split the StringSpec into separate declarations, each in the form "id=lvl":
+ AStringVector Decls = StringSplit(a_StringSpec, ";");
+ for (AStringVector::const_iterator itr = Decls.begin(), end = Decls.end(); itr != end; ++itr)
+ {
+ // Split each declaration into the id and lvl part:
+ if (itr->empty())
+ {
+ // The decl is empty (may happen if there's an extra semicolon at the end), ignore silently
+ continue;
+ }
+ AStringVector Split = StringSplitAndTrim(*itr, "=");
+ if (Split.size() != 2)
+ {
+ // Malformed decl
+ LOG("%s: Malformed enchantment decl: \"%s\", skipping.", __FUNCTION__, itr->c_str());
+ continue;
+ }
+ int id = atoi(Split[0].c_str());
+ int lvl = atoi(Split[1].c_str());
+ if (
+ ((id == 0) && (Split[0] != "0")) ||
+ ((lvl == 0) && (Split[1] != "0"))
+ )
+ {
+ // Numbers failed to parse
+ LOG("%s: Failed to parse enchantment declaration for numbers: \"%s\" and \"%s\", skipping.",
+ __FUNCTION__, Split[0].c_str(), Split[1].c_str()
+ );
+ continue;
+ }
+ SetLevel(id, lvl);
+ } // for itr - Decls[]
+}
+
+
+
+
+
+AString cEnchantments::ToString(void) const
+{
+ // Serialize all the enchantments into a string
+ AString res;
+ for (cEnchantments::cMap::const_iterator itr = m_Enchantments.begin(), end = m_Enchantments.end(); itr != end; ++itr)
+ {
+ AppendPrintf(res, "%d=%d;", itr->first, itr->second);
+ } // for itr - m_Enchantments[]
+ return res;
+}
+
+
+
+
+
+int cEnchantments::GetLevel(int a_EnchantmentID) const
+{
+ // Return the level for the specified enchantment; 0 if not stored
+ cMap::const_iterator itr = m_Enchantments.find(a_EnchantmentID);
+ if (itr != m_Enchantments.end())
+ {
+ return itr->second;
+ }
+
+ // Not stored, return zero
+ return 0;
+}
+
+
+
+
+
+void cEnchantments::SetLevel(int a_EnchantmentID, int a_Level)
+{
+ // Sets the level for the specified enchantment, adding it if not stored before or removing it if level <= 0
+ if (a_Level == 0)
+ {
+ // Delete enchantment, if present:
+ cMap::iterator itr = m_Enchantments.find(a_EnchantmentID);
+ if (itr != m_Enchantments.end())
+ {
+ m_Enchantments.erase(itr);
+ }
+ }
+ else
+ {
+ // Add / overwrite enchantment
+ m_Enchantments[a_EnchantmentID] = a_Level;
+ }
+}
+
+
+
+
+
+
+void cEnchantments::Clear(void)
+{
+ m_Enchantments.clear();
+}
+
+
+
+
+
+bool cEnchantments::IsEmpty(void) const
+{
+ return m_Enchantments.empty();
+}
+
+
+
+
+
+void cEnchantments::WriteToNBTCompound(cFastNBTWriter & a_Writer, const AString & a_ListTagName) const
+{
+ // Write the enchantments into the specified NBT writer
+ // begin with the LIST tag of the specified name ("ench" or "StoredEnchantments")
+
+ a_Writer.BeginList(a_ListTagName, TAG_Compound);
+ for (cMap::const_iterator itr = m_Enchantments.begin(), end = m_Enchantments.end(); itr != end; ++itr)
+ {
+ a_Writer.BeginCompound("");
+ a_Writer.AddShort("id", itr->first);
+ a_Writer.AddShort("lvl", itr->second);
+ a_Writer.EndCompound();
+ } // for itr - m_Enchantments[]
+ a_Writer.EndList();
+}
+
+
+
+
+
+void cEnchantments::ParseFromNBT(cParsedNBT & a_NBT, int a_EnchListTagIdx)
+{
+ // Read the enchantments from the specified NBT list tag (ench or StoredEnchantments)
+
+ // Verify that the tag is a list:
+ if (a_NBT.GetType(a_EnchListTagIdx) != TAG_List)
+ {
+ LOGWARNING("%s: Invalid EnchListTag type: exp %d, got %d. Enchantments not parsed",
+ __FUNCTION__, TAG_List, a_NBT.GetType(a_EnchListTagIdx)
+ );
+ ASSERT(!"Bad EnchListTag type");
+ return;
+ }
+
+ // Verify that the list is of Compounds:
+ if (a_NBT.GetChildrenType(a_EnchListTagIdx) != TAG_Compound)
+ {
+ LOGWARNING("%s: Invalid NBT list children type: exp %d, got %d. Enchantments not parsed",
+ __FUNCTION__, TAG_Compound, a_NBT.GetChildrenType(a_EnchListTagIdx)
+ );
+ ASSERT(!"Bad EnchListTag children type");
+ return;
+ }
+
+ Clear();
+
+ // Iterate over all the compound children, parse an enchantment from each:
+ for (int tag = a_NBT.GetFirstChild(a_EnchListTagIdx); tag >= 0; tag = a_NBT.GetNextSibling(tag))
+ {
+ // tag is the compound inside the "ench" list tag
+ ASSERT(a_NBT.GetType(tag) == TAG_Compound);
+
+ // Search for the id and lvl tags' values:
+ int id = -1, lvl = -1;
+ for (int ch = a_NBT.GetFirstChild(tag); ch >= 0; ch = a_NBT.GetNextSibling(ch))
+ {
+ if (a_NBT.GetType(ch) != TAG_Short)
+ {
+ continue;
+ }
+ if (a_NBT.GetName(ch) == "id")
+ {
+ id = a_NBT.GetShort(ch);
+ }
+ else if (a_NBT.GetName(ch) == "lvl")
+ {
+ lvl = a_NBT.GetShort(ch);
+ }
+ } // for ch - children of the compound tag
+
+ if ((id == -1) || (lvl <= 0))
+ {
+ // Failed to parse either the id or the lvl, skip this compound
+ continue;
+ }
+
+ // Store the enchantment:
+ m_Enchantments[id] = lvl;
+ } // for tag - children of the ench list tag
+}
+
+
+
+
diff --git a/source/Enchantments.h b/source/Enchantments.h
new file mode 100644
index 000000000..6b3b4679b
--- /dev/null
+++ b/source/Enchantments.h
@@ -0,0 +1,105 @@
+
+// Enchantments.h
+
+// Declares the cEnchantments class representing a storage for item enchantments and stored-enchantments
+
+
+
+
+
+#pragma once
+
+
+
+
+
+// fwd: WorldStorage/FastNBT.h
+class cFastNBTWriter;
+class cParsedNBT;
+
+
+
+
+
+// tolua_begin
+
+/** Class that stores item enchantments or stored-enchantments
+The enchantments may be serialized to a stringspec and read back from such stringspec.
+The format for the stringspec is "id=lvl;id=lvl;id=lvl...", with an optional semicolon at the end,
+mapping each enchantment's id onto its level.
+Level value of 0 means no such enchantment, and it will not be stored in the m_Enchantments.
+Serialization will never put zero-level enchantments into the stringspec.
+*/
+class cEnchantments
+{
+public:
+ /// Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs )
+ enum
+ {
+ enchProtection = 0,
+ enchFireProtection = 1,
+ enchFeatherFalling = 2,
+ enchBlastProtection = 3,
+ enchProjectileProtection = 4,
+ enchRespiration = 5,
+ enchAquaAffinity = 6,
+ enchThorns = 7,
+ enchSharpness = 16,
+ enchSmite = 17,
+ enchBaneOfArthropods = 18,
+ enchKnockback = 19,
+ enchFireAspect = 20,
+ enchLooting = 21,
+ enchEfficiency = 32,
+ enchSilkTouch = 33,
+ enchUnbreaking = 34,
+ enchFortune = 35,
+ enchPower = 48,
+ enchPunch = 49,
+ enchFlame = 50,
+ enchInfinity = 51,
+ } ;
+
+ /// Creates an empty enchantments container
+ cEnchantments(void);
+
+ /// Creates an enchantments container filled with enchantments parsed from stringspec
+ cEnchantments(const AString & a_StringSpec);
+
+ /// Adds enchantments in the stringspec; if a specified enchantment already exists, overwrites it
+ void AddFromString(const AString & a_StringSpec);
+
+ /// Serializes all the enchantments into a string
+ AString ToString(void) const;
+
+ /// Returns the level for the specified enchantment; 0 if not stored
+ int GetLevel(int a_EnchantmentID) const;
+
+ /// Sets the level for the specified enchantment, adding it if not stored before or removing it if level <= 0
+ void SetLevel(int a_EnchantmentID, int a_Level);
+
+ /// Removes all enchantments
+ void Clear(void);
+
+ /// Returns true if there are no enchantments
+ bool IsEmpty(void) const;
+
+ // tolua_end
+
+ /// Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments")
+ void WriteToNBTCompound(cFastNBTWriter & a_Writer, const AString & a_ListTagName) const;
+
+ /// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments)
+ void ParseFromNBT(cParsedNBT & a_NBT, int a_EnchListTagIdx);
+
+protected:
+ /// Maps enchantment ID -> enchantment level
+ typedef std::map<int, int> cMap;
+
+ /// Currently stored enchantments
+ cMap m_Enchantments;
+} ; // tolua_export
+
+
+
+
diff --git a/source/Item.h b/source/Item.h
index 45b124e67..fee549a2c 100644
--- a/source/Item.h
+++ b/source/Item.h
@@ -1,7 +1,20 @@
+
+// Item.h
+
+// Declares the cItem class representing an item (in the inventory sense)
+
+
+
+
+
#pragma once
#include "Defines.h"
-#include "BlockID.h"
+#include "Enchantments.h"
+
+
+
+
namespace Json
{
@@ -25,15 +38,17 @@ public:
}
- /// Creates an item of the specified type, by default 1 piece with no damage
+ /// Creates an item of the specified type, by default 1 piece with no damage and no enchantments
cItem(
short a_ItemType,
char a_ItemCount = 1,
- short a_ItemDamage = 0
+ short a_ItemDamage = 0,
+ const AString & a_Enchantments = ""
) :
- m_ItemType (a_ItemType),
- m_ItemCount (a_ItemCount),
- m_ItemDamage(a_ItemDamage)
+ m_ItemType (a_ItemType),
+ m_ItemCount (a_ItemCount),
+ m_ItemDamage (a_ItemDamage),
+ m_Enchantments(a_Enchantments)
{
if (!IsValidItem(m_ItemType))
{
@@ -48,6 +63,7 @@ public:
m_ItemType = E_ITEM_EMPTY;
m_ItemCount = 0;
m_ItemDamage = 0;
+ m_Enchantments.Clear();
}
@@ -98,9 +114,10 @@ public:
static bool IsEnchantable(short a_ItemType);
- short m_ItemType;
- char m_ItemCount;
- short m_ItemDamage;
+ short m_ItemType;
+ char m_ItemCount;
+ short m_ItemDamage;
+ cEnchantments m_Enchantments;
};
// tolua_end
diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp
index 50c335180..f34401b55 100644
--- a/source/Protocol/Protocol132.cpp
+++ b/source/Protocol/Protocol132.cpp
@@ -15,6 +15,8 @@
#include "../Mobs/Monster.h"
#include "../UI/Window.h"
#include "../Pickup.h"
+#include "../WorldStorage/FastNBT.h"
+#include "../StringCompression.h"
@@ -693,8 +695,21 @@ void cProtocol132::WriteItem(const cItem & a_Item)
WriteByte (a_Item.m_ItemCount);
WriteShort(a_Item.m_ItemDamage);
- // TODO: Implement enchantments
- WriteShort(-1);
+ if (a_Item.m_Enchantments.IsEmpty())
+ {
+ WriteShort(-1);
+ return;
+ }
+
+ // Send the enchantments:
+ cFastNBTWriter Writer;
+ const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
+ a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName);
+ Writer.Finish();
+ AString Compressed;
+ CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
+ WriteShort(Compressed.size());
+ SendData(Compressed.data(), Compressed.size());
}
@@ -721,18 +736,64 @@ int cProtocol132::ParseItem(cItem & a_Item)
a_Item.Empty();
}
- HANDLE_PACKET_READ(ReadBEShort, short, EnchantNumBytes);
- if (EnchantNumBytes <= 0)
+ HANDLE_PACKET_READ(ReadBEShort, short, MetadataLength);
+ if (MetadataLength <= 0)
{
return PARSE_OK;
}
- // TODO: Enchantment not implemented yet!
- if (!m_ReceivedData.SkipRead(EnchantNumBytes))
+ // Read the metadata
+ AString Metadata;
+ Metadata.resize(MetadataLength);
+ if (!m_ReceivedData.ReadBuf((void *)Metadata.data(), MetadataLength))
{
return PARSE_INCOMPLETE;
}
+ return ParseItemMetadata(a_Item, Metadata);
+}
+
+
+
+
+
+int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
+{
+ // Uncompress the GZIPped data:
+ AString Uncompressed;
+ if (UncompressStringGZIP(a_Metadata.data(), a_Metadata.size(), Uncompressed) != Z_OK)
+ {
+ AString HexDump;
+ CreateHexDump(HexDump, a_Metadata.data(), a_Metadata.size(), 16);
+ LOG("Cannot unGZIP item metadata:\n%s", HexDump.c_str());
+ return PARSE_ERROR;
+ }
+
+ // Parse into NBT:
+ cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
+ if (!NBT.IsValid())
+ {
+ AString HexDump;
+ CreateHexDump(HexDump, Uncompressed.data(), Uncompressed.size(), 16);
+ LOG("Cannot parse NBT item metadata:\n%s", HexDump.c_str());
+ return PARSE_ERROR;
+ }
+
+ // Load enchantments from the NBT:
+ for (int tag = NBT.GetFirstChild(NBT.GetRoot()); tag >= 0; tag = NBT.GetNextSibling(tag))
+ {
+ if (
+ (NBT.GetType(tag) == TAG_List) &&
+ (
+ (NBT.GetName(tag) == "ench") ||
+ (NBT.GetName(tag) == "StoredEnchantments")
+ )
+ )
+ {
+ a_Item.m_Enchantments.ParseFromNBT(NBT, tag);
+ }
+ }
+
return PARSE_OK;
}
diff --git a/source/Protocol/Protocol132.h b/source/Protocol/Protocol132.h
index a481f7162..cf559f1ca 100644
--- a/source/Protocol/Protocol132.h
+++ b/source/Protocol/Protocol132.h
@@ -82,6 +82,9 @@ protected:
virtual void WriteItem(const cItem & a_Item) override;
virtual int ParseItem(cItem & a_Item) override;
+ /// Parses the metadata that may come with the item.
+ int ParseItemMetadata(cItem & a_Item, const AString & a_Metadata);
+
virtual void SendCompass(const cWorld & a_World);
virtual void SendEncryptionKeyRequest(void);
diff --git a/source/StringCompression.cpp b/source/StringCompression.cpp
index b7e08cb11..36946b282 100644
--- a/source/StringCompression.cpp
+++ b/source/StringCompression.cpp
@@ -5,13 +5,12 @@
#include "Globals.h"
#include "StringCompression.h"
-#include "zlib.h"
-/// Compresses a_Data into a_Compressed; return Z_XXX error constants same as zlib's compress2()
+/// Compresses a_Data into a_Compressed; returns Z_XXX error constants same as zlib's compress2()
int CompressString(const char * a_Data, int a_Length, AString & a_Compressed)
{
uLongf CompressedSize = compressBound(a_Length);
@@ -53,3 +52,129 @@ int UncompressString(const char * a_Data, int a_Length, AString & a_Uncompressed
+
+int CompressStringGZIP(const char * a_Data, int a_Length, AString & a_Compressed)
+{
+ // Compress a_Data into a_Compressed using GZIP; return Z_XXX error constants same as zlib's compress2()
+
+ a_Compressed.reserve(a_Length);
+
+ char Buffer[64 KiB];
+ z_stream strm;
+ memset(&strm, 0, sizeof(strm));
+ strm.next_in = (Bytef *)a_Data;
+ strm.avail_in = a_Length;
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+
+ int res = deflateInit2(&strm, 9, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY);
+ if (res != Z_OK)
+ {
+ LOG("%s: compression initialization failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ return res;
+ }
+
+ while (true)
+ {
+ res = deflate(&strm, Z_FINISH);
+ switch (res)
+ {
+ case Z_OK:
+ {
+ // Some data has been compressed. Consume the buffer and continue compressing
+ a_Compressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ strm.avail_out = sizeof(Buffer);
+ if (strm.avail_in == 0)
+ {
+ // All data has been compressed
+ deflateEnd(&strm);
+ return Z_OK;
+ }
+ break;
+ }
+
+ case Z_STREAM_END:
+ {
+ // Finished compressing. Consume the rest of the buffer and return
+ a_Compressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ deflateEnd(&strm);
+ return Z_OK;
+ }
+
+ default:
+ {
+ // An error has occurred, log it and return the error value
+ LOG("%s: compression failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ deflateEnd(&strm);
+ return res;
+ }
+ } // switch (res)
+ } // while (true)
+}
+
+
+
+
+
+extern int UncompressStringGZIP(const char * a_Data, int a_Length, AString & a_Uncompressed)
+{
+ // Uncompresses a_Data into a_Uncompressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib
+
+ a_Uncompressed.reserve(a_Length);
+
+ char Buffer[64 KiB];
+ z_stream strm;
+ memset(&strm, 0, sizeof(strm));
+ strm.next_in = (Bytef *)a_Data;
+ strm.avail_in = a_Length;
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+
+ int res = inflateInit2(&strm, 31); // Force GZIP decoding
+ if (res != Z_OK)
+ {
+ LOG("%s: uncompression initialization failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ return res;
+ }
+
+ while (true)
+ {
+ res = inflate(&strm, Z_FINISH);
+ switch (res)
+ {
+ case Z_OK:
+ {
+ // Some data has been uncompressed. Consume the buffer and continue uncompressing
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ strm.avail_out = sizeof(Buffer);
+ if (strm.avail_in == 0)
+ {
+ // All data has been uncompressed
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+ break;
+ }
+
+ case Z_STREAM_END:
+ {
+ // Finished uncompressing. Consume the rest of the buffer and return
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+
+ default:
+ {
+ // An error has occurred, log it and return the error value
+ LOG("%s: uncompression failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ inflateEnd(&strm);
+ return res;
+ }
+ } // switch (res)
+ } // while (true)
+}
+
+
+
+
diff --git a/source/StringCompression.h b/source/StringCompression.h
index 5afd4c37f..8afdf59e0 100644
--- a/source/StringCompression.h
+++ b/source/StringCompression.h
@@ -3,15 +3,23 @@
// Interfaces to the wrapping functions for compression and decompression using AString as their data
+#include "zlib.h" // Needed for the Z_XXX return values
-/// Compresses a_Data into a_Compressed; return Z_XXX error constants same as zlib's compress2()
+
+
+/// Compresses a_Data into a_Compressed using ZLIB; returns Z_XXX error constants same as zlib's compress2()
extern int CompressString(const char * a_Data, int a_Length, AString & a_Compressed);
-/// Uncompresses a_Data into a_Decompressed; returns Z_XXX error constants same as zlib's decompress()
+/// Uncompresses a_Data into a_Uncompressed; returns Z_XXX error constants same as zlib's decompress()
extern int UncompressString(const char * a_Data, int a_Length, AString & a_Uncompressed, int a_UncompressedSize);
+/// Compresses a_Data into a_Compressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib
+extern int CompressStringGZIP(const char * a_Data, int a_Length, AString & a_Compressed);
+
+/// Uncompresses a_Data into a_Uncompressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib
+extern int UncompressStringGZIP(const char * a_Data, int a_Length, AString & a_Uncompressed);
diff --git a/source/WorldStorage/NBTChunkSerializer.cpp b/source/WorldStorage/NBTChunkSerializer.cpp
index 65153c4d8..2cf34a24f 100644
--- a/source/WorldStorage/NBTChunkSerializer.cpp
+++ b/source/WorldStorage/NBTChunkSerializer.cpp
@@ -68,6 +68,16 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin
{
m_Writer.AddByte ("Slot", (unsigned char)a_Slot);
}
+
+ // Write the enchantments:
+ if (!a_Item.m_Enchantments.IsEmpty())
+ {
+ const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
+ m_Writer.BeginCompound("tag");
+ a_Item.m_Enchantments.WriteToNBTCompound(m_Writer, TagName);
+ m_Writer.EndCompound();
+ }
+
m_Writer.EndCompound();
}