diff --git a/VC2010/MCServer.vcxproj b/VC2010/MCServer.vcxproj index 2c428a718..66ed07b48 100644 --- a/VC2010/MCServer.vcxproj +++ b/VC2010/MCServer.vcxproj @@ -234,6 +234,7 @@ + @@ -242,6 +243,7 @@ + @@ -358,6 +360,7 @@ + @@ -515,4 +518,4 @@ - + \ No newline at end of file diff --git a/VC2010/MCServer.vcxproj.filters b/VC2010/MCServer.vcxproj.filters index 55edac971..2e0ec8324 100644 --- a/VC2010/MCServer.vcxproj.filters +++ b/VC2010/MCServer.vcxproj.filters @@ -367,6 +367,9 @@ {e4620b72-4739-4233-b326-47d4b5ca23d2} + + {c9b053f2-89dd-475e-a889-5c25a20e6eec} + @@ -733,6 +736,12 @@ cEntity\cPawn\cMonster\cZombiepigman + + cFileFormatUpdater + + + cItem + @@ -1137,6 +1146,9 @@ cEntity\cPawn\cMonster\cZombiepigman + + cFileFormatUpdater + @@ -1147,4 +1159,4 @@ - + \ No newline at end of file diff --git a/makefile b/makefile index fb87b9081..1438549d1 100644 --- a/makefile +++ b/makefile @@ -127,188 +127,7 @@ MCServer : \ build/cPacket_DestroyEntity.o\ build/cPacket_Disconnect.o\ build/cPacket_EntityEquipment.o\ - build/cPacket_CreateInventoryAction.o\ - build/cPacket_EntityLook.o\ - build/cPacket_EntityStatus.o\ - build/cPacket_Flying.o\ - build/cPacket_Handshake.o\ - build/cPacket_InventoryProgressBar.o\ - build/cPacket_InventorySlot.o\ - build/cPacket_ItemSwitch.o\ - build/cPacket_KeepAlive.o\ - build/cPacket_Login.o\ - build/cPacket_MapChunk.o\ - build/cPacket_Metadata.o\ - build/cPacket_MultiBlock.o\ - build/cPacket_NamedEntitySpawn.o\ - build/cPacket_PickupSpawn.o\ - build/cPacket_PlayerLook.o\ - build/cPacket_PlayerMoveLook.o\ - build/cPacket_PlayerPosition.o\ - build/cPacket_PreChunk.o\ - build/cPacket_RelativeEntityMove.o\ - build/cPacket_RelativeEntityMoveLook.o\ - build/cPacket_Respawn.o\ - build/cPacket_SpawnMob.o\ - build/cPacket_TeleportEntity.o\ - build/cPacket_TimeUpdate.o\ - build/cPacket_UpdateHealth.o\ - build/cPacket_UpdateSign.o\ - build/cPacket_UseEntity.o\ - build/cPacket_WholeInventory.o\ - build/cPacket_WindowClick.o\ - build/cPacket_WindowClose.o\ - build/cPacket_WindowOpen.o\ - build/cPacket.o\ - build/base64.o\ - build/Socket.o\ - build/StdHelpers.o\ - build/UrlHelper.o\ - build/WebServer.o\ - build/tolua_event.o\ - build/tolua_is.o\ - build/tolua_map.o\ - build/tolua_push.o\ - build/tolua_to.o\ - build/lapi.o\ - build/lauxlib.o\ - build/lbaselib.o\ - build/lcode.o\ - build/ldblib.o\ - build/ldebug.o\ - build/ldo.o\ - build/ldump.o\ - build/lfunc.o\ - build/lgc.o\ - build/linit.o\ - build/liolib.o\ - build/llex.o\ - build/lmathlib.o\ - build/lmem.o\ - build/loadlib.o\ - build/lobject.o\ - build/lopcodes.o\ - build/loslib.o\ - build/lparser.o\ - build/lstate.o\ - build/lstring.o\ - build/lstrlib.o\ - build/ltable.o\ - build/ltablib.o\ - build/ltm.o\ - build/luac.o\ - build/lundump.o\ - build/lvm.o\ - build/lzio.o\ - build/print.o\ - build/adler32.o\ - build/compress.o\ - build/crc32.o\ - build/deflate.o\ - build/gzclose.o\ - build/gzlib.o\ - build/gzread.o\ - build/gzwrite.o\ - build/infback.o\ - build/inffast.o\ - build/inflate.o\ - build/inftrees.o\ - build/trees.o\ - build/uncompr.o\ - build/zutil.o\ - build/iniFile.o\ - build/cSocket.o\ - build/cWaterSimulator.o - $(CC) $(LNK_OPTIONS) \ - build/json_reader.o\ - build/json_value.o\ - build/json_writer.o\ - build/cMakeDir.o\ - build/cGenSettings.o\ - build/cCuboid.o\ - build/cNoise.o\ - build/cTimer.o\ - build/cSleep.o\ - build/cMonsterConfig.o\ - build/cSpider.o\ - build/cThread.o\ - build/cBlockingTCPLink.o\ - build/cAuthenticator.o\ - build/cLuaCommandBinder.o\ - build/cChicken.o\ - build/cCow.o\ - build/cPig.o\ - build/cSheep.o\ - build/cSquid.o\ - build/cWolf.o\ - build/cZombie.o\ - build/cEnderman.o\ - build/cCreeper.o\ - build/cGhast.o\ - build/cCavespider.o\ - build/cZombiepigman.o\ - build/cSkeleton.o\ - build/cSlime.o\ - build/cSilverfish.o\ - build/md5.o\ - build/cReferenceManager.o\ - build/Bindings.o\ - build/cBlockToPickup.o\ - build/cChatColor.o\ - build/cChestEntity.o\ - build/cChunk.o\ - build/cChunkMap.o\ - build/cClientHandle.o\ - build/cCraftingWindow.o\ - build/cCriticalSection.o\ - build/cEntity.o\ - build/cEvent.o\ - build/cFurnaceEntity.o\ - build/cFurnaceRecipe.o\ - build/cFurnaceWindow.o\ - build/cGroup.o\ - build/cGroupManager.o\ - build/cInventory.o\ - build/cLog.o\ - build/cMonster.o\ - build/cPawn.o\ - build/cPickup.o\ - build/cPlayer.o\ - build/cPlugin_Lua.o\ - build/cPlugin.o\ - build/cPluginManager.o\ - build/cRecipeChecker.o\ - build/cRoot.o\ - build/cSemaphore.o\ - build/cServer.o\ - build/cSignEntity.o\ - build/cStringMap.o\ - build/cWebAdmin.o\ - build/cWebPlugin.o\ - build/cWindow.o\ - build/cWorld.o\ - build/main.o\ - build/ManualBindings.o\ - build/Matrix4f.o\ - build/Vector3d.o\ - build/Vector3f.o\ - build/Vector3i.o\ - build/cHeartBeat.o\ - build/cTCPLink.o\ - build/cMCLogger.o\ - build/cTracer.o\ - build/cPacket_13.o\ - build/cPacket_AddToInventory.o\ - build/cPacket_ArmAnim.o\ - build/cPacket_BlockChange.o\ - build/cPacket_BlockDig.o\ - build/cPacket_BlockPlace.o\ - build/cPacket_Chat.o\ - build/cPacket_CollectItem.o\ - build/cPacket_DestroyEntity.o\ - build/cPacket_Disconnect.o\ - build/cPacket_EntityEquipment.o\ - build/cPacket_CreateInventoryAction.o\ + build/cPacket_CreateInventoryAction.o\ build/cPacket_EntityLook.o\ build/cPacket_EntityStatus.o\ build/cPacket_Flying.o\ @@ -400,6 +219,191 @@ MCServer : \ build/iniFile.o\ build/cSocket.o\ build/cWaterSimulator.o\ + build/cFileFormatUpdater.o\ + build/cItem.o + $(CC) $(LNK_OPTIONS) \ + build/json_reader.o\ + build/json_value.o\ + build/json_writer.o\ + build/cMakeDir.o\ + build/cGenSettings.o\ + build/cCuboid.o\ + build/cNoise.o\ + build/cTimer.o\ + build/cSleep.o\ + build/cMonsterConfig.o\ + build/cSpider.o\ + build/cThread.o\ + build/cBlockingTCPLink.o\ + build/cAuthenticator.o\ + build/cLuaCommandBinder.o\ + build/cChicken.o\ + build/cCow.o\ + build/cPig.o\ + build/cSheep.o\ + build/cSquid.o\ + build/cWolf.o\ + build/cZombie.o\ + build/cEnderman.o\ + build/cCreeper.o\ + build/cGhast.o\ + build/cCavespider.o\ + build/cZombiepigman.o\ + build/cSkeleton.o\ + build/cSlime.o\ + build/cSilverfish.o\ + build/md5.o\ + build/cReferenceManager.o\ + build/Bindings.o\ + build/cBlockToPickup.o\ + build/cChatColor.o\ + build/cChestEntity.o\ + build/cChunk.o\ + build/cChunkMap.o\ + build/cClientHandle.o\ + build/cCraftingWindow.o\ + build/cCriticalSection.o\ + build/cEntity.o\ + build/cEvent.o\ + build/cFurnaceEntity.o\ + build/cFurnaceRecipe.o\ + build/cFurnaceWindow.o\ + build/cGroup.o\ + build/cGroupManager.o\ + build/cInventory.o\ + build/cLog.o\ + build/cMonster.o\ + build/cPawn.o\ + build/cPickup.o\ + build/cPlayer.o\ + build/cPlugin_Lua.o\ + build/cPlugin.o\ + build/cPluginManager.o\ + build/cRecipeChecker.o\ + build/cRoot.o\ + build/cSemaphore.o\ + build/cServer.o\ + build/cSignEntity.o\ + build/cStringMap.o\ + build/cWebAdmin.o\ + build/cWebPlugin.o\ + build/cWindow.o\ + build/cWorld.o\ + build/main.o\ + build/ManualBindings.o\ + build/Matrix4f.o\ + build/Vector3d.o\ + build/Vector3f.o\ + build/Vector3i.o\ + build/cHeartBeat.o\ + build/cTCPLink.o\ + build/cMCLogger.o\ + build/cTracer.o\ + build/cPacket_13.o\ + build/cPacket_AddToInventory.o\ + build/cPacket_ArmAnim.o\ + build/cPacket_BlockChange.o\ + build/cPacket_BlockDig.o\ + build/cPacket_BlockPlace.o\ + build/cPacket_Chat.o\ + build/cPacket_CollectItem.o\ + build/cPacket_DestroyEntity.o\ + build/cPacket_Disconnect.o\ + build/cPacket_EntityEquipment.o\ + build/cPacket_CreateInventoryAction.o\ + build/cPacket_EntityLook.o\ + build/cPacket_EntityStatus.o\ + build/cPacket_Flying.o\ + build/cPacket_Handshake.o\ + build/cPacket_InventoryProgressBar.o\ + build/cPacket_InventorySlot.o\ + build/cPacket_ItemSwitch.o\ + build/cPacket_KeepAlive.o\ + build/cPacket_Login.o\ + build/cPacket_MapChunk.o\ + build/cPacket_Metadata.o\ + build/cPacket_MultiBlock.o\ + build/cPacket_NamedEntitySpawn.o\ + build/cPacket_PickupSpawn.o\ + build/cPacket_PlayerLook.o\ + build/cPacket_PlayerMoveLook.o\ + build/cPacket_PlayerPosition.o\ + build/cPacket_PreChunk.o\ + build/cPacket_RelativeEntityMove.o\ + build/cPacket_RelativeEntityMoveLook.o\ + build/cPacket_Respawn.o\ + build/cPacket_SpawnMob.o\ + build/cPacket_TeleportEntity.o\ + build/cPacket_TimeUpdate.o\ + build/cPacket_UpdateHealth.o\ + build/cPacket_UpdateSign.o\ + build/cPacket_UseEntity.o\ + build/cPacket_WholeInventory.o\ + build/cPacket_WindowClick.o\ + build/cPacket_WindowClose.o\ + build/cPacket_WindowOpen.o\ + build/cPacket.o\ + build/base64.o\ + build/Socket.o\ + build/StdHelpers.o\ + build/UrlHelper.o\ + build/WebServer.o\ + build/tolua_event.o\ + build/tolua_is.o\ + build/tolua_map.o\ + build/tolua_push.o\ + build/tolua_to.o\ + build/lapi.o\ + build/lauxlib.o\ + build/lbaselib.o\ + build/lcode.o\ + build/ldblib.o\ + build/ldebug.o\ + build/ldo.o\ + build/ldump.o\ + build/lfunc.o\ + build/lgc.o\ + build/linit.o\ + build/liolib.o\ + build/llex.o\ + build/lmathlib.o\ + build/lmem.o\ + build/loadlib.o\ + build/lobject.o\ + build/lopcodes.o\ + build/loslib.o\ + build/lparser.o\ + build/lstate.o\ + build/lstring.o\ + build/lstrlib.o\ + build/ltable.o\ + build/ltablib.o\ + build/ltm.o\ + build/luac.o\ + build/lundump.o\ + build/lvm.o\ + build/lzio.o\ + build/print.o\ + build/adler32.o\ + build/compress.o\ + build/crc32.o\ + build/deflate.o\ + build/gzclose.o\ + build/gzlib.o\ + build/gzread.o\ + build/gzwrite.o\ + build/infback.o\ + build/inffast.o\ + build/inflate.o\ + build/inftrees.o\ + build/trees.o\ + build/uncompr.o\ + build/zutil.o\ + build/iniFile.o\ + build/cSocket.o\ + build/cWaterSimulator.o\ + build/cFileFormatUpdater.o\ + build/cItem.o\ -o MCServer clean : @@ -492,7 +496,7 @@ clean : build/cPacket_DestroyEntity.o\ build/cPacket_Disconnect.o\ build/cPacket_EntityEquipment.o\ - build/cPacket_CreateInventoryAction.o\ + build/cPacket_CreateInventoryAction.o\ build/cPacket_EntityLook.o\ build/cPacket_EntityStatus.o\ build/cPacket_Flying.o\ @@ -584,6 +588,8 @@ clean : build/iniFile.o\ build/cSocket.o\ build/cWaterSimulator.o\ + build/cFileFormatUpdater.o\ + build/cItem.o\ MCServer install : MCServer @@ -1342,8 +1348,15 @@ build/cMakeDir.o : source/cMakeDir.cpp build/cSocket.o : source/cSocket.cpp $(CC) $(CC_OPTIONS) source/cSocket.cpp -c $(INCLUDE) -o build/cSocket.o - + build/cWaterSimulator.o : source/cWaterSimulator.cpp $(CC) $(CC_OPTIONS) source/cWaterSimulator.cpp -c $(INCLUDE) -o build/cWaterSimulator.o +build/cFileFormatUpdater.o : source/cFileFormatUpdater.cpp + $(CC) $(CC_OPTIONS) source/cFileFormatUpdater.cpp -c $(INCLUDE) -o build/cFileFormatUpdater.o + +build/cItem.o : source/cItem.cpp + $(CC) $(CC_OPTIONS) source/cItem.cpp -c $(INCLUDE) -o build/cItem.o + + ##### END RUN #### diff --git a/source/cChestEntity.cpp b/source/cChestEntity.cpp index 54a06fcb9..9ec46014d 100644 --- a/source/cChestEntity.cpp +++ b/source/cChestEntity.cpp @@ -111,14 +111,8 @@ bool cChestEntity::LoadFromJson( const Json::Value& a_Value ) int SlotIdx = 0; for( Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr ) { - Json::Value & Slot = *itr; cItem Item; - Item.m_ItemID = (ENUM_ITEM_ID)Slot.get("ID", -1 ).asInt(); - if( Item.m_ItemID > 0 ) - { - Item.m_ItemCount = (char)Slot.get("Count", -1 ).asInt(); - Item.m_ItemHealth = (short)Slot.get("Health", -1 ).asInt(); - } + Item.FromJson( *itr ); SetSlot( SlotIdx, Item ); SlotIdx++; } @@ -137,15 +131,7 @@ void cChestEntity::SaveToJson( Json::Value& a_Value ) { Json::Value Slot; cItem* Item = GetSlot( i ); - if( Item ) - { - Slot["ID"] = Item->m_ItemID; - if( Item->m_ItemID > 0 ) - { - Slot["Count"] = Item->m_ItemCount; - Slot["Health"] = Item->m_ItemHealth; - } - } + if( Item ) Item->GetJson( Slot ); AllSlots.append( Slot ); } a_Value["Slots"] = AllSlots; diff --git a/source/cFileFormatUpdater.cpp b/source/cFileFormatUpdater.cpp new file mode 100644 index 000000000..8516b5b40 --- /dev/null +++ b/source/cFileFormatUpdater.cpp @@ -0,0 +1,185 @@ +#include "cFileFormatUpdater.h" +#include "cMCLogger.h" +#include "Vector3d.h" +#include "Vector3f.h" +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include +#include +#include +#include +#include + +#include +#endif + +#include "cItem.h" +#include + +typedef std::list< std::string > StringList; +StringList GetDirectoryContents( const char* a_Directory ); + +void cFileFormatUpdater::UpdateFileFormat() +{ + UpdatePlayersOfWorld("world"); +} + +// Convert player .bin files to JSON +void cFileFormatUpdater::UpdatePlayersOfWorld( const char* a_WorldName ) +{ + std::string PlayerDir = std::string( a_WorldName ) + "/player/"; + + StringList AllFiles = GetDirectoryContents( PlayerDir.c_str() ); + for( StringList::iterator itr = AllFiles.begin(); itr != AllFiles.end(); ++itr ) + { + std::string & FileName = *itr; + if( FileName.rfind(".bin") != std::string::npos ) // Get only the files ending in .bin + { + PlayerBINtoJSON( (PlayerDir + FileName).c_str() ); + } + } +} + +// Converts player binary files to human readable JSON +void cFileFormatUpdater::PlayerBINtoJSON( const char* a_FileName ) +{ + Vector3d PlayerPos; + Vector3f PlayerRot; + short PlayerHealth; + + const unsigned int NumInventorySlots = 45; // At this time the player inventory has/had 45 slots + cItem IventoryItems[ NumInventorySlots ]; + + FILE* f; +#ifdef _WIN32 + if( fopen_s(&f, a_FileName, "rb" ) == 0 ) // no error +#else + if( (f = fopen(a_FileName, "rb" ) ) != 0 ) // no error +#endif + { + // First read player position, rotation and health + if( fread( &PlayerPos.x, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerPos.y, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerPos.z, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerRot.x, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerRot.y, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerRot.z, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + if( fread( &PlayerHealth, sizeof(short), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", a_FileName); fclose(f); return; } + + + for(unsigned int i = 0; i < NumInventorySlots; i++) + { + cItem & Item = IventoryItems[i]; + if( fread( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, f) != 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return; } + if( fread( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, f) != 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return; } + if( fread( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, f)!= 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return; } + } + + fclose(f); + } + + // Loaded all the data, now create the JSON data + Json::Value JSON_PlayerPosition; + JSON_PlayerPosition.append( Json::Value( PlayerPos.x ) ); + JSON_PlayerPosition.append( Json::Value( PlayerPos.y ) ); + JSON_PlayerPosition.append( Json::Value( PlayerPos.z ) ); + + Json::Value JSON_PlayerRotation; + JSON_PlayerRotation.append( Json::Value( PlayerRot.x ) ); + JSON_PlayerRotation.append( Json::Value( PlayerRot.y ) ); + JSON_PlayerRotation.append( Json::Value( PlayerRot.z ) ); + + Json::Value JSON_Inventory; + for(unsigned int i = 0; i < NumInventorySlots; i++) + { + Json::Value JSON_Item; + IventoryItems[i].GetJson( JSON_Item ); + JSON_Inventory.append( JSON_Item ); + } + + Json::Value root; + root["position"] = JSON_PlayerPosition; + root["rotation"] = JSON_PlayerRotation; + root["inventory"] = JSON_Inventory; + root["health"] = PlayerHealth; + + Json::StyledWriter writer; + std::string JsonData = writer.write( root ); + + // Get correct filename + std::string FileName = a_FileName; + std::string FileNameWithoutExt = FileName.substr(0, FileName.find_last_of(".") ); + std::string FileNameJson = FileNameWithoutExt + ".json"; + + // Write to file +#ifdef _WIN32 + if( fopen_s(&f, FileNameJson.c_str(), "wb" ) == 0 ) // no error +#else + if( (f = fopen(FileNameJson.c_str(), "wb" ) ) != 0 ) // no error +#endif + { + if( fwrite( JsonData.c_str(), JsonData.size(), 1, f ) != 1 ) { LOGERROR("ERROR WRITING PLAYER JSON TO FILE %s", FileNameJson.c_str() ); return; } + fclose( f ); + } + + // Delete old format file, only do this when conversion has succeeded + if( std::remove( a_FileName ) != 0 ) + { + LOGERROR("COULD NOT DELETE FILE %s", a_FileName ); + return; + } + + LOGINFO("Successfully converted binary to Json %s", FileNameJson.c_str() ); +} + + + + + + + + + +// Helper function +StringList GetDirectoryContents( const char* a_Directory ) +{ + StringList AllFiles; +#ifdef _WIN32 + std::string FileFilter = std::string( a_Directory ) + "*.*"; + HANDLE hFind; + WIN32_FIND_DATA FindFileData; + + if( ( hFind = FindFirstFile(FileFilter.c_str(), &FindFileData) ) != INVALID_HANDLE_VALUE) + { + do + { + AllFiles.push_back( FindFileData.cFileName ); + } while( FindNextFile(hFind, &FindFileData) ); + FindClose(hFind); + } +#else + DIR *dp; + struct dirent *dirp; + if( (dp = opendir( a_Directory ) ) == NULL) + { + LOGERROR("Error (%i) opening %s\n", errno, a_Directory ); + } + else + { + while ((dirp = readdir(dp)) != NULL) + { + AllFiles.push_back( dirp->d_name ); + } + closedir(dp); + } +#endif + + return AllFiles; +} \ No newline at end of file diff --git a/source/cFileFormatUpdater.h b/source/cFileFormatUpdater.h new file mode 100644 index 000000000..fc6beed6e --- /dev/null +++ b/source/cFileFormatUpdater.h @@ -0,0 +1,11 @@ +#pragma once + +class cFileFormatUpdater +{ +public: + static void UpdateFileFormat(); +private: + static void UpdatePlayersOfWorld( const char* a_WorldName ); + + static void PlayerBINtoJSON( const char* a_FileName ); +}; \ No newline at end of file diff --git a/source/cFurnaceEntity.cpp b/source/cFurnaceEntity.cpp index 95f5f566c..36524e3b7 100644 --- a/source/cFurnaceEntity.cpp +++ b/source/cFurnaceEntity.cpp @@ -288,14 +288,7 @@ bool cFurnaceEntity::LoadFromJson( const Json::Value& a_Value ) int SlotIdx = 0; for( Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr ) { - Json::Value & Slot = *itr; - cItem & Item = m_Items[ SlotIdx ]; - Item.m_ItemID = (ENUM_ITEM_ID)Slot.get("ID", -1 ).asInt(); - if( Item.m_ItemID > 0 ) - { - Item.m_ItemCount = (char)Slot.get("Count", -1 ).asInt(); - Item.m_ItemHealth = (short)Slot.get("Health", -1 ).asInt(); - } + m_Items[ SlotIdx ].FromJson( *itr ); SlotIdx++; } @@ -304,12 +297,7 @@ bool cFurnaceEntity::LoadFromJson( const Json::Value& a_Value ) if( !JsonItem.empty() ) { cItem Item; - Item.m_ItemID = (ENUM_ITEM_ID)JsonItem.get("ID", -1).asInt(); - if( Item.m_ItemID > 0 ) - { - Item.m_ItemCount = (char)JsonItem.get("Count", -1).asInt(); - Item.m_ItemHealth = (short)JsonItem.get("Health", -1).asInt(); - } + Item.FromJson( JsonItem ); if( !Item.IsEmpty() ) { m_CookingItem = new cItem( Item ); @@ -335,13 +323,7 @@ void cFurnaceEntity::SaveToJson( Json::Value& a_Value ) for(unsigned int i = 0; i < 3; i++) { Json::Value Slot; - cItem & Item = m_Items[ i ]; - Slot["ID"] = Item.m_ItemID; - if( Item.m_ItemID > 0 ) - { - Slot["Count"] = Item.m_ItemCount; - Slot["Health"] = Item.m_ItemHealth; - } + m_Items[ i ].GetJson( Slot ); AllSlots.append( Slot ); } a_Value["Slots"] = AllSlots; @@ -350,12 +332,7 @@ void cFurnaceEntity::SaveToJson( Json::Value& a_Value ) if( m_CookingItem ) { Json::Value JsonItem; - JsonItem["ID"] = m_CookingItem->m_ItemID; - if( m_CookingItem->m_ItemID > 0 ) - { - JsonItem["Count"] = m_CookingItem->m_ItemCount; - JsonItem["Health"] = m_CookingItem->m_ItemHealth; - } + m_CookingItem->GetJson( JsonItem ); a_Value["Cooking"] = JsonItem; } diff --git a/source/cInventory.cpp b/source/cInventory.cpp index e78ac226e..788d38eaa 100644 --- a/source/cInventory.cpp +++ b/source/cInventory.cpp @@ -8,6 +8,8 @@ #include "cRecipeChecker.h" #include "cRoot.h" +#include + #include "packets/cPacket_WindowClick.h" #include "packets/cPacket_WholeInventory.h" #include "packets/cPacket_InventorySlot.h" @@ -340,25 +342,23 @@ void cInventory::DrawInventory() } } -void cInventory::WriteToFile(FILE* a_File) +void cInventory::SaveToJson(Json::Value & a_Value) { for(unsigned int i = 0; i < c_NumSlots; i++) { - cItem & Item = m_Slots[i]; - fwrite( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File ); - fwrite( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File ); - fwrite( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File ); + Json::Value JSON_Item; + m_Slots[i].GetJson( JSON_Item ); + a_Value.append( JSON_Item ); } } -bool cInventory::LoadFromFile(FILE* a_File) +bool cInventory::LoadFromJson(Json::Value & a_Value) { - for(unsigned int i = 0; i < c_NumSlots; i++) + int SlotIdx = 0; + for( Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr ) { - cItem & Item = m_Slots[i]; - if( fread( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File) != 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return false; } - if( fread( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File) != 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return false; } - if( fread( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File)!= 1 ) { LOGERROR("ERROR READING INVENTORY FROM FILE"); return false; } + m_Slots[SlotIdx].FromJson( *itr ); + SlotIdx++; } return true; } diff --git a/source/cInventory.h b/source/cInventory.h index cebcf346b..7d98af853 100644 --- a/source/cInventory.h +++ b/source/cInventory.h @@ -4,6 +4,11 @@ #include "cWindowOwner.h" #include "FileDefine.h" +namespace Json +{ + class Value; +}; + class cItem; class cClientHandle; class cPlayer; @@ -25,8 +30,8 @@ public: bool RemoveItem( cItem & a_Item ); //tolua_export void DrawInventory(); - void WriteToFile(FILE* a_File); - bool LoadFromFile(FILE* a_File); + void SaveToJson(Json::Value & a_Value); + bool LoadFromJson(Json::Value & a_Value); void SendWholeInventory( cClientHandle* a_Client ); diff --git a/source/cItem.cpp b/source/cItem.cpp new file mode 100644 index 000000000..b91a7a316 --- /dev/null +++ b/source/cItem.cpp @@ -0,0 +1,22 @@ +#include "cItem.h" +#include + +void cItem::GetJson( Json::Value & a_OutValue ) +{ + a_OutValue["ID"] = m_ItemID; + if( m_ItemID > 0 ) + { + a_OutValue["Count"] = m_ItemCount; + a_OutValue["Health"] = m_ItemHealth; + } +} + +void cItem::FromJson( const Json::Value & a_Value ) +{ + m_ItemID = (ENUM_ITEM_ID)a_Value.get("ID", -1 ).asInt(); + if( m_ItemID > 0 ) + { + m_ItemCount = (char)a_Value.get("Count", -1 ).asInt(); + m_ItemHealth = (short)a_Value.get("Health", -1 ).asInt(); + } +} \ No newline at end of file diff --git a/source/cItem.h b/source/cItem.h index edf3468ac..dde0c649b 100644 --- a/source/cItem.h +++ b/source/cItem.h @@ -3,6 +3,11 @@ #include "Defines.h" #include "BlockID.h" +namespace Json +{ + class Value; +}; + class cItem //tolua_export { //tolua_export public: @@ -27,6 +32,10 @@ public: { //tolua_export return ( (m_ItemID == a_Item.m_ItemID) && (m_ItemHealth == a_Item.m_ItemHealth) ); } //tolua_export + + void GetJson( Json::Value & a_OutValue ); //tolua_export + void FromJson( const Json::Value & a_Value ); //tolua_export + ENUM_ITEM_ID m_ItemID; //tolua_export char m_ItemCount; //tolua_export short m_ItemHealth; //tolua_export diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp index 898bac54f..fee8df966 100644 --- a/source/cPlayer.cpp +++ b/source/cPlayer.cpp @@ -32,6 +32,7 @@ #include "Vector3f.h" #include "../iniFile/iniFile.h" +#include #ifndef _WIN32 // for mkdir #include @@ -636,7 +637,7 @@ bool cPlayer::LoadFromDisk() } char SourceFile[128]; - sprintf_s(SourceFile, 128, "world/player/%s.bin", m_pState->PlayerName.c_str() ); + sprintf_s(SourceFile, 128, "world/player/%s.json", m_pState->PlayerName.c_str() ); FILE* f; #ifdef _WIN32 @@ -645,15 +646,43 @@ bool cPlayer::LoadFromDisk() if( (f = fopen(SourceFile, "rb" ) ) != 0 ) // no error #endif { - if( fread( &m_Pos->x, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Pos->y, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Pos->z, sizeof(double), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Rot->x, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Rot->y, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Rot->z, sizeof(float), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( fread( &m_Health, sizeof(m_Health), 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } - if( !m_Inventory->LoadFromFile( f ) ) { LOGERROR("ERROR READING INVENTORY FROM FILE %s", SourceFile); fclose(f); return false; } + // Get file size + fseek (f , 0 , SEEK_END); + long FileSize = ftell (f); + rewind(f); + + char* buffer = new char[ FileSize ]; + if( fread( buffer, FileSize, 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } fclose(f); + + Json::Value root; + Json::Reader reader; + if( !reader.parse( buffer, root, false ) ) + { + LOGERROR("ERROR WHILE PARSING JSON FROM FILE %s", SourceFile); + } + + delete [] buffer; + + Json::Value & JSON_PlayerPosition = root["position"]; + if( JSON_PlayerPosition.size() == 3 ) + { + m_Pos->x = JSON_PlayerPosition[(unsigned int)0].asDouble(); + m_Pos->y = JSON_PlayerPosition[(unsigned int)1].asDouble(); + m_Pos->z = JSON_PlayerPosition[(unsigned int)2].asDouble(); + } + + Json::Value & JSON_PlayerRotation = root["rotation"]; + if( JSON_PlayerRotation.size() == 3 ) + { + m_Rot->x = (float)JSON_PlayerRotation[(unsigned int)0].asDouble(); + m_Rot->y = (float)JSON_PlayerRotation[(unsigned int)1].asDouble(); + m_Rot->z = (float)JSON_PlayerRotation[(unsigned int)2].asDouble(); + } + + m_Health = root.get("health", 0 ).asInt(); + m_Inventory->LoadFromJson(root["inventory"]); + return true; } return false; @@ -677,8 +706,31 @@ bool cPlayer::SaveToDisk() } #endif + // create the JSON data + Json::Value JSON_PlayerPosition; + JSON_PlayerPosition.append( Json::Value( m_Pos->x ) ); + JSON_PlayerPosition.append( Json::Value( m_Pos->y ) ); + JSON_PlayerPosition.append( Json::Value( m_Pos->z ) ); + + Json::Value JSON_PlayerRotation; + JSON_PlayerRotation.append( Json::Value( m_Rot->x ) ); + JSON_PlayerRotation.append( Json::Value( m_Rot->y ) ); + JSON_PlayerRotation.append( Json::Value( m_Rot->z ) ); + + Json::Value JSON_Inventory; + m_Inventory->SaveToJson( JSON_Inventory ); + + Json::Value root; + root["position"] = JSON_PlayerPosition; + root["rotation"] = JSON_PlayerRotation; + root["inventory"] = JSON_Inventory; + root["health"] = m_Health; + + Json::StyledWriter writer; + std::string JsonData = writer.write( root ); + char SourceFile[128]; - sprintf_s(SourceFile, 128, "world/player/%s.bin", m_pState->PlayerName.c_str() ); + sprintf_s(SourceFile, 128, "world/player/%s.json", m_pState->PlayerName.c_str() ); FILE* f; #ifdef _WIN32 @@ -687,14 +739,7 @@ bool cPlayer::SaveToDisk() if( (f = fopen(SourceFile, "wb" ) ) != 0 ) // no error #endif { - fwrite( &m_Pos->x, sizeof(double), 1, f ); - fwrite( &m_Pos->y, sizeof(double), 1, f ); - fwrite( &m_Pos->z, sizeof(double), 1, f ); - fwrite( &m_Rot->x, sizeof(float), 1, f ); - fwrite( &m_Rot->y, sizeof(float), 1, f ); - fwrite( &m_Rot->z, sizeof(float), 1, f ); - fwrite( &m_Health, sizeof(m_Health), 1, f ); - m_Inventory->WriteToFile( f ); + if( fwrite( JsonData.c_str(), JsonData.size(), 1, f ) != 1 ) { LOGERROR("ERROR WRITING PLAYER JSON TO FILE %s", SourceFile ); return false; } fclose(f); return true; } diff --git a/source/cRoot.cpp b/source/cRoot.cpp index 531d0c9f3..55ee28576 100644 --- a/source/cRoot.cpp +++ b/source/cRoot.cpp @@ -10,6 +10,7 @@ #include "cMonsterConfig.h" #include "cSleep.h" #include "cThread.h" +#include "cFileFormatUpdater.h" #include "../iniFile/iniFile.h" @@ -67,6 +68,8 @@ void cRoot::Start() { m_bRestart = false; + cFileFormatUpdater::UpdateFileFormat(); + m_Server = new cServer(); cIniFile IniFile("settings.ini"); IniFile.ReadFile();