From a19a0701211e0a5563dc77845e11a3f3308e2b32 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 2 Jun 2013 10:40:20 +0000 Subject: Enchantments: API and sending to client git-svn-id: http://mc-server.googlecode.com/svn/trunk@1539 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/AllToLua.pkg | 1 + source/Bindings.cpp | 527 +++++++++++++++++++++++++++-- source/Bindings.h | 2 +- source/Enchantments.cpp | 231 +++++++++++++ source/Enchantments.h | 105 ++++++ source/Item.h | 35 +- source/Protocol/Protocol132.cpp | 73 +++- source/Protocol/Protocol132.h | 3 + source/StringCompression.cpp | 129 ++++++- source/StringCompression.h | 12 +- source/WorldStorage/NBTChunkSerializer.cpp | 10 + 11 files changed, 1073 insertions(+), 55 deletions(-) create mode 100644 source/Enchantments.cpp create mode 100644 source/Enchantments.h (limited to 'source') 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 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(); } -- cgit v1.2.3