diff --git a/make/XCode/uox3.xcodeproj/project.pbxproj b/make/XCode/uox3.xcodeproj/project.pbxproj index cc8952325..56b55edc8 100644 --- a/make/XCode/uox3.xcodeproj/project.pbxproj +++ b/make/XCode/uox3.xcodeproj/project.pbxproj @@ -121,6 +121,13 @@ /* Begin PBXFileReference section */ 56BA2FB52A95BDF70064EB36 /* jscript.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = jscript.xcodeproj; path = ../../spidermonkey/make/XCode/jscript/jscript.xcodeproj; sourceTree = ""; }; + 56C9E3D52A9C8FF0004D9F38 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = CMakeLists.txt; path = ../cmake/CMakeLists.txt; sourceTree = ""; }; + 56C9E3D82A9C9022004D9F38 /* uox3.sln */ = {isa = PBXFileReference; lastKnownFileType = text; name = uox3.sln; path = ../VS2022/uox3.sln; sourceTree = ""; }; + 56C9E3D92A9C9022004D9F38 /* uox3.vcxproj */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = uox3.vcxproj; path = ../VS2022/uox3.vcxproj; sourceTree = ""; }; + 56C9E3DA2A9C9022004D9F38 /* uox3.vcxproj.filters */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = uox3.vcxproj.filters; path = ../VS2022/uox3.vcxproj.filters; sourceTree = ""; }; + 56C9E3DB2A9C9035004D9F38 /* uox3.vcxproj */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = uox3.vcxproj; path = ../VS2017/uox3.vcxproj; sourceTree = ""; }; + 56C9E3DC2A9C9035004D9F38 /* uox3.vcxproj.filters */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = uox3.vcxproj.filters; path = ../VS2017/uox3.vcxproj.filters; sourceTree = ""; }; + 56C9E3DD2A9C9035004D9F38 /* uox3.sln */ = {isa = PBXFileReference; lastKnownFileType = text; name = uox3.sln; path = ../VS2017/uox3.sln; sourceTree = ""; }; 648153C929466EF400784170 /* libjscript.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libjscript.a; sourceTree = BUILT_PRODUCTS_DIR; }; 64A9006A293E3DA3009B54DA /* uox3 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = uox3; sourceTree = BUILT_PRODUCTS_DIR; }; 64A90075293E3DD4009B54DA /* ai.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ai.cpp; sourceTree = ""; }; @@ -305,9 +312,40 @@ name = Products; sourceTree = ""; }; + 56C9E3D22A9C8FD5004D9F38 /* makestuff */ = { + isa = PBXGroup; + children = ( + 56C9E3D52A9C8FF0004D9F38 /* CMakeLists.txt */, + 56C9E3D72A9C9004004D9F38 /* vs2017 */, + 56C9E3D62A9C8FF7004D9F38 /* vs2022 */, + ); + name = makestuff; + sourceTree = ""; + }; + 56C9E3D62A9C8FF7004D9F38 /* vs2022 */ = { + isa = PBXGroup; + children = ( + 56C9E3D82A9C9022004D9F38 /* uox3.sln */, + 56C9E3D92A9C9022004D9F38 /* uox3.vcxproj */, + 56C9E3DA2A9C9022004D9F38 /* uox3.vcxproj.filters */, + ); + name = vs2022; + sourceTree = ""; + }; + 56C9E3D72A9C9004004D9F38 /* vs2017 */ = { + isa = PBXGroup; + children = ( + 56C9E3DD2A9C9035004D9F38 /* uox3.sln */, + 56C9E3DB2A9C9035004D9F38 /* uox3.vcxproj */, + 56C9E3DC2A9C9035004D9F38 /* uox3.vcxproj.filters */, + ); + name = vs2017; + sourceTree = ""; + }; 64A90061293E3DA3009B54DA = { isa = PBXGroup; children = ( + 56C9E3D22A9C8FD5004D9F38 /* makestuff */, 64A90074293E3DD4009B54DA /* source */, 64A9006B293E3DA3009B54DA /* Products */, 64A9016B293E3EED009B54DA /* Frameworks */, diff --git a/make/XCode/uox3.xcodeproj/xcshareddata/xcschemes/uox3.xcscheme b/make/XCode/uox3.xcodeproj/xcshareddata/xcschemes/uox3.xcscheme index 0e5f58993..355157f58 100644 --- a/make/XCode/uox3.xcodeproj/xcshareddata/xcschemes/uox3.xcscheme +++ b/make/XCode/uox3.xcodeproj/xcshareddata/xcschemes/uox3.xcscheme @@ -36,7 +36,7 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "YES" - customWorkingDirectory = "/Users/charleskerr/Documents/projects/official/data" + customWorkingDirectory = "/Users/charles/Development/projects/official/test/data" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" diff --git a/source/Changelog.txt b/source/Changelog.txt index 13b15602c..eb6f2e40e 100644 --- a/source/Changelog.txt +++ b/source/Changelog.txt @@ -1,3 +1,7 @@ +28/08/2023 - punt + Replaced all routine calls with a specific type of stream ifstream/ofstream to the generic istream/ostream for flexibility + Modernized region resource loading/saving code + 24/08/2023 - punt Fixed a memory leak with regions.cpp, related to worldsaves diff --git a/source/MultiMul.hpp b/source/MultiMul.hpp index 2cc8df443..db7c23200 100644 --- a/source/MultiMul.hpp +++ b/source/MultiMul.hpp @@ -14,6 +14,7 @@ #include "UOPData.hpp" #include "mapclasses.h" class TileInfo; +class CTile; //================================================================================================== // MultiItem_st //================================================================================================== diff --git a/source/regions.cpp b/source/regions.cpp index 1fe7875ac..20ba9d8e2 100644 --- a/source/regions.cpp +++ b/source/regions.cpp @@ -1,10 +1,16 @@ +#include "regions.h" + +#include +#include +#include + #include "uox3.h" #include "classes.h" -#include "regions.h" #include "StringUtility.hpp" #include "ObjectFactory.h" -#include -#include + +using namespace std::string_literals; + #define DEBUG_REGIONS 0 CMapHandler *MapRegion; @@ -323,30 +329,27 @@ MapResource_st& CMapWorld::GetResource( SI16 x, SI16 y ) //o------------------------------------------------------------------------------------------------o void CMapWorld::SaveResources( UI08 worldNum ) { - char wBuffer[2]; - const std::string resourceFile = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "resource[" + std::to_string( worldNum ) + "].bin"; - std::ofstream toWrite( resourceFile.c_str(), std::ios::out | std::ios::trunc | std::ios::binary ); - - if( toWrite ) + auto resourceFile = std::filesystem::path( cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "resource["s + std::to_string( worldNum ) + "].bin"s ); + auto output = std::ofstream( resourceFile.string(), std::ios::binary ); + auto buffer = std::vector( 3, 0 ); + + if( output.is_open() ) { - for( std::vector::const_iterator mIter = mapResources.begin(); mIter != mapResources.end(); ++mIter ) + for( auto iter = mapResources.begin(); iter != mapResources.end(); iter++ ) { - wBuffer[0] = static_cast(( *mIter ).oreAmt >> 8 ); - wBuffer[1] = static_cast(( *mIter ).oreAmt % 256 ); - toWrite.write(( const char * )&wBuffer, 2 ); - - wBuffer[0] = static_cast(( *mIter ).logAmt >> 8 ); - wBuffer[1] = static_cast(( *mIter ).logAmt % 256 ); - toWrite.write(( const char * )&wBuffer, 2 ); - - wBuffer[0] = static_cast(( *mIter ).fishAmt >> 8 ); - wBuffer[1] = static_cast(( *mIter ).fishAmt % 256 ); - toWrite.write(( const char * )&wBuffer, 2 ); - } - toWrite.close(); - } - else // Can't save resources + buffer[0] = iter->oreAmt; + std::reverse( reinterpret_cast( buffer.data()), reinterpret_cast( buffer.data()) + 2 ); // Make it big endian + buffer[1] = iter->logAmt; + std::reverse( reinterpret_cast( buffer.data()) + 2, reinterpret_cast( buffer.data()) + 4 ); + buffer[2] = iter->fishAmt; + std::reverse( reinterpret_cast( buffer.data()) + 4, reinterpret_cast( buffer.data()) + 6 ); + // Now write it + output.write( reinterpret_cast( buffer.data()), buffer.size() * 2 ); + } + } + else { + // Can't save resources Console.Error( "Failed to open resource.bin for writing" ); } } @@ -359,54 +362,42 @@ void CMapWorld::SaveResources( UI08 worldNum ) //o------------------------------------------------------------------------------------------------o void CMapWorld::LoadResources( UI08 worldNum ) { - const SI16 resOre = cwmWorldState->ServerData()->ResOre(); - const SI16 resLog = cwmWorldState->ServerData()->ResLogs(); - const SI16 resFish = cwmWorldState->ServerData()->ResFish(); - const UI32 oreTime = BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResOreTime() )); - const UI32 logTime = BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResLogTime() )); - const UI32 fishTime = BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResFishTime() )); - const std::string resourceFile = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + std::string("resource[") + oldstrutil::number( worldNum ) + std::string("].bin"); - - char rBuffer[2]; - std::ifstream toRead ( resourceFile.c_str(), std::ios::in | std::ios::binary ); - - bool fileExists = ( toRead.is_open() ); - - if( fileExists ) - { - toRead.seekg( 0, std::ios::beg ); - } - - for( std::vector::iterator mIter = mapResources.begin(); mIter != mapResources.end(); ++mIter ) + mapResources = std::vector( mapResources.size(), + MapResource_st( cwmWorldState->ServerData()->ResOre(), cwmWorldState->ServerData()->ResLogs(), + cwmWorldState->ServerData()->ResFish(), BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResOreTime() )), + BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResLogTime() )), BuildTimeValue( static_cast( cwmWorldState->ServerData()->ResFishTime() )))); + + auto resourceFile = std::filesystem::path( cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "resource["s + oldstrutil::number( worldNum ) + "].bin"s ); + + // The data is grouped as three shorts (for each resource), so we read in that format + auto buffer = std::vector( 3, 0 ); + auto input = std::ifstream( resourceFile.string(), std::ios::binary ); + + // We want to get the iteratro for the first mapResources ; + auto iter = mapResources.begin(); + if( input.is_open() ) { - if( fileExists ) - { - toRead.read( rBuffer, 2 ); - ( *mIter ).oreAmt = (( rBuffer[0] << 8 ) + rBuffer[1] ); - - toRead.read( rBuffer, 2 ); - ( *mIter ).logAmt = (( rBuffer[0] << 8 ) + rBuffer[1] ); - - toRead.read( rBuffer, 2 ); - ( *mIter ).fishAmt = (( rBuffer[0] << 8 ) + rBuffer[1] ); - - fileExists = toRead.eof(); - } - else + while( input.good() && !input.eof() && iter != mapResources.end() ) { - ( *mIter ).oreAmt = resOre; - ( *mIter ).logAmt = resLog; - ( *mIter ).fishAmt = resFish; - } - // No need to preserve time. Do a refresh automatically - ( *mIter ).oreTime = oreTime; - ( *mIter ).logTime = logTime; - ( *mIter ).fishTime = fishTime; - } - if( fileExists ) - { - toRead.close(); - } + input.read( reinterpret_cast( buffer.data() ), buffer.size() * 2 ); + if( input.gcount() != buffer.size() * 2 ) + { + // We had issues reading the full amount, break out of this + break; + } + + // For whatever reason the resources are stored in big endidan, which on int/arm machines , we need little endian, so reverse them + std::for_each( buffer.begin(), buffer.end(), []( SI16 &value ) { + std::reverse( reinterpret_cast( &value ), reinterpret_cast( &value ) + 2 ); + }); + + // Now set the values + ( *iter ).oreAmt = buffer[0]; + ( *iter ).logAmt = buffer[1]; + ( *iter ).fishAmt = buffer[2]; + iter++; + } + } } //o------------------------------------------------------------------------------------------------o diff --git a/source/regions.h b/source/regions.h index 9c304871f..87de396e9 100644 --- a/source/regions.h +++ b/source/regions.h @@ -28,7 +28,8 @@ struct MapResource_st SI16 fishAmt; UI32 fishTime; - MapResource_st() : oreAmt( 0 ), oreTime( 0 ), logAmt( 0 ), logTime( 0 ), fishAmt( 0 ), fishTime( 0 ) + MapResource_st( SI16 defOre = 0, SI16 defLog = 0, SI16 defFish = 0, UI32 defOreTime = 0, UI32 defLogTIme = 0, UI32 defFishTIme = 0 ) : + oreAmt( defOre ), oreTime( defOreTime ), logAmt( defLog ), logTime( defLogTIme ), fishAmt( defFish ), fishTime( defFishTIme ) { } };