Loading...   


 CMakeLists.txt        |   6 ++
 zone/map.cpp          |  93 ++++++++++++++++++++-
 zone/map.h            |   7 +-
 zone/net.cpp          |  24 ++++++
 zone/raycast_mesh.cpp | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++
 zone/raycast_mesh.h   |   9 ++-
 6 files changed, 356 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 494959c..f24b13f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,6 +30,7 @@
 #EQEMU_BUILD_LUA
 #EQEMU_SANITIZE_LUA_LIBS
 #EQEMU_BUILD_CLIENT_FILES
+#EQEMU_USE_MAP_MMFS
 #EQEMU_MAP_DIR
 
 #We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
@@ -275,6 +276,11 @@ IF(EQEMU_BUILD_LUA)
 	ADD_DEFINITIONS(-DLUA_EQEMU)
 ENDIF(EQEMU_BUILD_LUA)
 
+OPTION(EQEMU_USE_MAP_MMFS "Create and use Map MMF files." OFF)
+IF(EQEMU_USE_MAP_MMFS)
+	ADD_DEFINITIONS(-DUSE_MAP_MMFS)
+ENDIF(EQEMU_USE_MAP_MMFS)
+
 SET(EQEMU_MAP_DIR "./Maps" CACHE STRING "The dir that maps, water maps, and paths are located in.")
 
 ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})
diff --git a/zone/map.cpp b/zone/map.cpp
index f06c590..ff00a58 100644
--- a/zone/map.cpp
+++ b/zone/map.cpp
@@ -242,7 +242,13 @@ Map *Map::LoadMapFile(std::string file) {
 	return nullptr;
 }
 
-bool Map::Load(std::string filename) {
+bool Map::Load(std::string filename, bool force_mmf_overwrite)
+{
+#ifdef USE_MAP_MMFS
+	if (!force_mmf_overwrite && LoadMMF(filename, force_mmf_overwrite))
+		return true;
+#endif /*USE_MAP_MMFS*/
+
 	FILE *f = fopen(filename.c_str(), "rb");
 	if(f) {
 		uint32 version;
@@ -254,10 +260,22 @@ bool Map::Load(std::string filename) {
 		if(version == 0x01000000) {
 			bool v = LoadV1(f);
 			fclose(f);
+
+#ifdef USE_MAP_MMFS
+			if (v)
+				SaveMMF(filename, force_mmf_overwrite);
+#endif /*USE_MAP_MMFS*/
+			
 			return v;
 		} else if(version == 0x02000000) {
 			bool v = LoadV2(f);
 			fclose(f);
+
+#ifdef USE_MAP_MMFS
+			if (v)
+				SaveMMF(filename, force_mmf_overwrite);
+#endif /*USE_MAP_MMFS*/
+			
 			return v;
 		} else {
 			fclose(f);
@@ -898,3 +916,76 @@ void Map::TranslateVertex(glm::vec3 &v, float tx, float ty, float tz) {
 	v.y = v.y + ty;
 	v.z = v.z + tz;
 }
+
+#ifdef USE_MAP_MMFS
+inline void strip_map_extension(std::string& file)
+{
+	auto ext_off = file.find(".map");
+	if (ext_off != std::string::npos)
+		file.erase(ext_off, strlen(".map"));
+}
+
+inline bool add_mmf_extension(std::string& file)
+{
+	if (file.empty())
+		return false;
+
+	file.append(".mmf");
+	size_t dot_check = std::count(file.begin(), file.end(), '.');
+
+	return (dot_check == 1);
+}
+
+bool Map::LoadMMF(std::string parentfile, bool force_mmf_overwrite)
+{
+	strip_map_extension(parentfile);
+	if (!add_mmf_extension(parentfile))
+		goto load_mmf_fail;
+	
+	if (imp) {
+		imp->rm->release();
+		imp->rm = nullptr;
+	}
+	else {
+		imp = new impl;
+	}
+
+	bool load_success = false;
+	imp->rm = loadRaycastMesh(parentfile, load_success, force_mmf_overwrite);
+	if (imp->rm && !load_success) {
+		imp->rm->release();
+		imp->rm = nullptr;
+	}
+
+	if (!imp->rm) {
+		delete imp;
+		imp = nullptr;
+		goto load_mmf_fail;
+	}
+
+	return true;
+
+load_mmf_fail:
+	Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s'", parentfile.c_str());
+	return false;
+}
+
+void Map::SaveMMF(std::string parentfile, bool force_mmf_overwrite)
+{
+	if (!imp || !imp->rm)
+		goto save_mmf_fail;
+	
+	strip_map_extension(parentfile);
+	if (!add_mmf_extension(parentfile))
+		goto save_mmf_fail;
+
+	if (!saveRaycastMesh(imp->rm, parentfile, force_mmf_overwrite))
+		goto save_mmf_fail;
+
+	return;
+
+save_mmf_fail:
+	Log.Out(Logs::General, Logs::Error, "Failed to save Map MMF file: '%s'", parentfile.c_str());
+}
+
+#endif
diff --git a/zone/map.h b/zone/map.h
index 5d1b086..2143427 100644
--- a/zone/map.h
+++ b/zone/map.h
@@ -42,7 +42,7 @@ public:
 	bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
 	bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
 	bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
-	bool Load(std::string filename);
+	bool Load(std::string filename, bool force_mmf_overwrite = false);
 	static Map *LoadMapFile(std::string file);
 private:
 	void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
@@ -51,6 +51,11 @@ private:
 	bool LoadV1(FILE *f);
 	bool LoadV2(FILE *f);
 
+#ifdef USE_MAP_MMFS
+	bool LoadMMF(std::string parentfile, bool force_mmf_overwrite);
+	void SaveMMF(std::string parentfile, bool force_mmf_overwrite);
+#endif
+
 	struct impl;
 	impl *imp;
 };
diff --git a/zone/net.cpp b/zone/net.cpp
index 0f6ad0b..2e13cba 100644
--- a/zone/net.cpp
+++ b/zone/net.cpp
@@ -116,6 +116,30 @@ int main(int argc, char** argv) {
 	Log.LoadLogSettingsDefaults();
 
 	set_exception_handler(); 
+
+#ifdef USE_MAP_MMFS
+	if (argc >= 3) {
+		if (strcasecmp(argv[1], "preload_map") == 0) {
+			if (!ZoneConfig::LoadConfig())
+				return 1;
+			Config = ZoneConfig::get();
+
+			std::string mapfile = argv[2];
+			std::string filename = Config->MapDir;
+			filename += "/";
+			std::transform(mapfile.begin(), mapfile.end(), mapfile.begin(), ::tolower);
+			filename += mapfile;
+
+			auto m = new Map();
+			auto force_mmf_overwrite = true;
+			auto success = m->Load(filename, force_mmf_overwrite);
+			delete m;
+			std::cout << "'" << mapfile.c_str() << "' conversion state: " << (success ? "pass" : "fail") << std::endl;
+			return 0;
+		}
+	}
+#endif
+
 	QServ = new QueryServ;
 
 	Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration..");
diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp
index e2e88b1..2f2399c 100644
--- a/zone/raycast_mesh.cpp
+++ b/zone/raycast_mesh.cpp
@@ -914,6 +914,11 @@ public:
 	RmUint32		mMaxNodeCount;
 	NodeAABB		*mNodes;
 	TriVector		mLeafTriangles;
+
+#ifdef USE_MAP_MMFS
+	MyRaycastMesh(std::string& filename, bool force_mmf_overwrite);
+	bool save(std::string& filename, bool force_mmf_overwrite);
+#endif
 };
 
 };
@@ -937,3 +942,218 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount,		// The number of vertices in t
 }
 
 
+#ifdef USE_MAP_MMFS
+
+RaycastMesh* loadRaycastMesh(std::string& filename, bool& load_success, bool force_mmf_overwrite)
+{
+	if (filename.empty())
+		return nullptr;
+
+	auto m = new MyRaycastMesh(filename, force_mmf_overwrite);
+	load_success = (m->mNodes != nullptr);
+
+	return static_cast<RaycastMesh*>(m);
+}
+
+bool saveRaycastMesh(RaycastMesh* rm, std::string& filename, bool force_mmf_overwrite)
+{
+	if (!rm || filename.empty())
+		return false;
+
+	return static_cast<MyRaycastMesh*>(rm)->save(filename, force_mmf_overwrite);
+}
+
+MyRaycastMesh::MyRaycastMesh(std::string& filename, bool force_mmf_overwrite)
+{
+	mVcount = 0;
+	mVertices = nullptr;
+	mTcount = 0;
+	mIndices = nullptr;
+	mRaycastTriangles = nullptr;
+	mFaceNormals = nullptr;
+	mRaycastFrame = 0;
+	mMaxNodeCount = 0;
+	mNodeCount = 0;
+	mNodes = nullptr;
+	mRoot = nullptr;
+
+	if (force_mmf_overwrite)
+		goto myrm_ctor_fail;
+
+	FILE *f = fopen(filename.c_str(), "rb");
+	if (!f)
+		return;
+
+	if (fread(&mVcount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_ctor_fail;
+
+	mVertices = (RmReal *)::malloc(sizeof(RmReal) * (3 * mVcount));
+	if (!mVertices || fread(mVertices, sizeof(RmReal), (3 * mVcount), f) != (3 * mVcount))
+		goto myrm_ctor_fail;
+
+	if (fread(&mTcount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_ctor_fail;
+
+	mIndices = (RmUint32 *)::malloc(sizeof(RmUint32) * (3 * mTcount));
+	if (!mIndices || fread(mIndices, sizeof(RmUint32), (3 * mTcount), f) != (3 * mTcount))
+		goto myrm_ctor_fail;
+
+	mRaycastTriangles = (RmUint32 *)::malloc(sizeof(RmUint32) * mTcount);
+	if (fread(mRaycastTriangles, sizeof(RmUint32), mTcount, f) != mTcount)
+		goto myrm_ctor_fail;
+
+	mFaceNormals = (RmReal *)::malloc(sizeof(RmReal) * (3 * mTcount));
+	if (!mFaceNormals || fread(mFaceNormals, sizeof(RmReal), (3 * mTcount), f) != (3 * mTcount))
+		goto myrm_ctor_fail;
+
+	if (fread(&mRaycastFrame, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_ctor_fail;
+
+	RmUint32 lt_size = 0;
+	if (fread(&lt_size, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_ctor_fail;
+
+	if (lt_size)
+		mLeafTriangles.resize(lt_size);
+	if (lt_size && fread(&mLeafTriangles[0], sizeof(RmUint32), lt_size, f) != lt_size)
+		goto myrm_ctor_fail;
+	if (mTcount > lt_size)
+		mLeafTriangles.reserve(mTcount);
+
+	if (fread(&mNodeCount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_ctor_fail;
+
+	mMaxNodeCount = mNodeCount;
+
+	mNodes = new NodeAABB[mMaxNodeCount];
+	mRoot = &mNodes[0];
+
+	for (RmUint32 index = 0; index < mNodeCount; ++index) {
+		if (fread(mNodes[index].mBounds.mMin, sizeof(RmReal), 3, f) != 3)
+			goto myrm_ctor_fail;
+		if (fread(mNodes[index].mBounds.mMax, sizeof(RmReal), 3, f) != 3)
+			goto myrm_ctor_fail;
+		if (fread(&mNodes[index].mLeafTriangleIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_ctor_fail;
+
+		RmUint32 lNodeIndex = TRI_EOF;
+		if (fread(&lNodeIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_ctor_fail;
+		if (lNodeIndex != TRI_EOF)
+			mNodes[index].mLeft = &mNodes[lNodeIndex];
+
+		RmUint32 rNodeIndex = TRI_EOF;
+		if (fread(&rNodeIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_ctor_fail;
+		if (rNodeIndex != TRI_EOF)
+			mNodes[index].mRight = &mNodes[rNodeIndex];
+	}
+
+	fclose(f);
+
+	return;
+
+myrm_ctor_fail:
+	fclose(f);
+
+	delete[]mNodes;
+	::free(mVertices);
+	::free(mIndices);
+	::free(mFaceNormals);
+	::free(mRaycastTriangles);
+
+	mVcount = 0;
+	mVertices = nullptr;
+	mTcount = 0;
+	mIndices = nullptr;
+	mRaycastTriangles = nullptr;
+	mFaceNormals = nullptr;
+	mRaycastFrame = 0;
+	mLeafTriangles.clear();
+	mMaxNodeCount = 0;
+	mNodeCount = 0;
+	mNodes = nullptr;
+	mRoot = nullptr;
+	
+	return;
+}
+
+bool MyRaycastMesh::save(std::string& filename, bool force_mmf_overwrite)
+{
+	FILE *f = fopen(filename.c_str(), "rb");
+	if (f) {
+		fclose(f);
+		if (!force_mmf_overwrite)
+			return true;
+	}
+
+	f = fopen(filename.c_str(), "wb");
+
+	if (fwrite(&mVcount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_abort_save;
+	
+	if (fwrite(mVertices, sizeof(RmReal), (3 * mVcount), f) != (3 * mVcount))
+		goto myrm_abort_save;
+	
+	if (fwrite(&mTcount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_abort_save;
+	
+	if (fwrite(mIndices, sizeof(RmUint32), (3 * mTcount), f) != (3 * mTcount))
+		goto myrm_abort_save;
+	
+	if (fwrite(mRaycastTriangles, sizeof(RmUint32), mTcount, f) != mTcount)
+		goto myrm_abort_save;
+
+	if (!mFaceNormals) {
+		RmReal save_face[3];
+		getFaceNormal(0, &save_face[0]);
+	}
+	if (!mFaceNormals || fwrite(mFaceNormals, sizeof(RmReal), (3 * mTcount), f) != (3 * mTcount))
+		goto myrm_abort_save;
+	
+	if (fwrite(&mRaycastFrame, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_abort_save;
+
+	RmUint32 lt_size = (RmUint32)mLeafTriangles.size();
+	if (fwrite(&lt_size, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_abort_save;
+
+	if (lt_size && fwrite(&mLeafTriangles[0], sizeof(RmUint32), lt_size, f) != lt_size)
+		goto myrm_abort_save;
+
+	if (fwrite(&mNodeCount, sizeof(RmUint32), 1, f) != 1)
+		goto myrm_abort_save;
+
+	for (RmUint32 index = 0; index < mNodeCount; ++index) {
+		if (fwrite(mNodes[index].mBounds.mMin, sizeof(RmReal), 3, f) != 3)
+			goto myrm_abort_save;
+		if (fwrite(mNodes[index].mBounds.mMax, sizeof(RmReal), 3, f) != 3)
+			goto myrm_abort_save;
+		if (fwrite(&mNodes[index].mLeafTriangleIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_abort_save;
+
+		RmUint32 lNodeIndex = TRI_EOF;
+		if (mNodes[index].mLeft)
+			lNodeIndex = ((RmUint32)mNodes[index].mLeft - (RmUint32)mNodes) / sizeof(NodeAABB);
+		if (fwrite(&lNodeIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_abort_save;
+
+		RmUint32 rNodeIndex = TRI_EOF;
+		if (mNodes[index].mRight)
+			rNodeIndex = ((RmUint32)mNodes[index].mRight - (RmUint32)mNodes) / sizeof(NodeAABB);
+		if (fwrite(&rNodeIndex, sizeof(RmUint32), 1, f) != 1)
+			goto myrm_abort_save;
+	}
+
+	fclose(f);
+
+	return true;
+
+myrm_abort_save:
+	fclose(f);
+	std::remove(filename.c_str());
+
+	return false;
+}
+
+#endif /*USE_MAP_MMFS*/
diff --git a/zone/raycast_mesh.h b/zone/raycast_mesh.h
index eec2e0b..a60c531 100644
--- a/zone/raycast_mesh.h
+++ b/zone/raycast_mesh.h
@@ -57,4 +57,11 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount,		// The number of vertices in t
 								);
 
 
-#endif
\ No newline at end of file
+#ifdef USE_MAP_MMFS
+#include <string>
+
+RaycastMesh* loadRaycastMesh(std::string& filename, bool& load_success, bool force_mmf_overwrite);
+bool saveRaycastMesh(RaycastMesh* rm, std::string& filename, bool force_mmf_overwrite);
+#endif /*USE_MAP_MMFS*/
+
+#endif

Raw Paste Data