Пример #1
0
bool CGrayInstall::ReadMulData(CGFile &file, const CUOIndexRec &Index, void * pData)
{
	if ( file.Seek(Index.GetFileOffset(), SEEK_SET) != Index.GetFileOffset() )
		return false;

	DWORD dwLength = Index.GetBlockLength();
	if ( file.Read(pData, dwLength) != dwLength )
		return false;

	return true;
}
Пример #2
0
bool CGrayInstall::ReadMulIndex(CGFile &file, DWORD id, CUOIndexRec &Index)
{
	LONG lOffset = id * sizeof(CUOIndexRec);

	if ( file.Seek(lOffset, SEEK_SET) != lOffset )
		return false;

	if ( file.Read((void *)&Index, sizeof(CUOIndexRec)) != sizeof(CUOIndexRec) )
		return false;

	return Index.HasData();
}
Пример #3
0
bool CGrayInstall::OpenFile( CGFile & file, LPCTSTR pszName, WORD wFlags )
{
	ASSERT(pszName);
	if ( !m_sPreferPath.IsEmpty() )
	{
		if ( file.Open(GetPreferPath(pszName), wFlags) )
			return true;
	}
	else
	{
		if ( file.Open(GetFullExePath(pszName), wFlags) )
			return true;
		if ( file.Open(GetFullCDPath(pszName), wFlags) )
			return true;
	}
	return false;
}
Пример #4
0
bool CGrayInstall::OpenFile( VERFILE_TYPE i )
{
	CGFile	*pFile = GetMulFile(i);
	if ( !pFile )
		return false;
	if ( pFile->IsFileOpen())
		return true;

	if ( !pFile->GetFilePath().IsEmpty() )
	{
		if ( pFile->Open(pFile->GetFilePath(), OF_READ|OF_SHARE_DENY_WRITE) )
			return true;
	}

	LPCTSTR pszTitle = GetBaseFileName((VERFILE_TYPE)i);
	if ( !pszTitle ) return false;

	return OpenFile(m_File[i], pszTitle, OF_READ|OF_SHARE_DENY_WRITE);
}
Пример #5
0
bool CGFile::CopyFileTo( LPCTSTR pszDstFileName )
{
	if ( ! IsFileOpen())
	{
		if ( ! Open())
			return( false );
	}
	else
	{
		SeekToBegin();
	}

	CGFile sDst;
	if ( ! sDst.Open( pszDstFileName, OF_WRITE|OF_CREATE|OF_BINARY ))
	{
		return( false );
	}

	BYTE * pData = new BYTE [ 32 * 1024 ];	// temporary buffer.
	ASSERT(pData);
	bool fSuccess = true;

	while ( true )
	{
		size_t iSize = Read( pData, 32 * 1024 );
		if ( iSize < 0 )
		{
			fSuccess = false;
			break;
		}
		if ( iSize == 0 )
			break;
		sDst.Write( pData, iSize );
		if ( iSize < 32 * 1024 )
			break;
	}

	delete [] pData;
	return( fSuccess );
}
Пример #6
0
void defragSphere(char *path)
{
	ASSERT(path != NULL);

	CFileText inf;
	CGFile ouf;
	char z[256], z1[256], buf[1024];
	size_t i;
	DWORD uid = UID_CLEAR;
	char *p = NULL, *p1 = NULL;
	DWORD dBytesRead;
	DWORD dTotalMb;
	DWORD mb10 = 10 * 1024 * 1024;
	DWORD mb5 = 5 * 1024 * 1024;
	bool bSpecial;
	DWORD dTotalUIDs;

	char	c,c1,c2;
	DWORD	d;

	// NOTE: Sure I could use CVarDefArray, but it is extremely slow with memory allocation, takes hours
	// to read and save the data. Moreover, it takes less memory in this case and does less convertations.

	g_Log.Event(LOGM_INIT, "Defragmentation (UID alteration) of " SPHERE_TITLE " saves.\n"
		"Use it at your own risk and if you know what you are doing, since it can possibly harm your server.\n"
		"The process can take up to several hours depending on the CPU you have.\n"
		"After finished, you will have your '" SPHERE_FILE "*.scp' save files converted to '" SPHERE_FILE "*.scp.new'.\n");

	DWORD *uids = static_cast<DWORD *>(calloc((SIZE_MAX / 2) / sizeof(DWORD), sizeof(DWORD)));
	for ( i = 0; i < 3; i++ )
	{
		strncpy(z, path, sizeof(z) - 1);
		if ( i == 0 )
			strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT);
		else if ( i == 1 )
			strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT);
		else
			strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT);

		g_Log.Event(LOGM_INIT, "Reading %s\n", z);
		if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for reading. Skipped!\n", z);
			continue;
		}
		dBytesRead = dTotalMb = 0;
		while ( !feof(inf.m_pStream) )
		{
			fgets(buf, sizeof(buf), inf.m_pStream);
			dBytesRead += strlen(buf);
			if ( dBytesRead > mb10 )
			{
				dBytesRead -= mb10;
				dTotalMb += 10;
				g_Log.Event(LOGM_INIT, "Total read %lu Mb\n", dTotalMb);
			}
			if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=") == buf ))
			{
				p = buf + 7;
				p1 = p;
				while ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' ))
					p1++;
				*p1 = 0;

				//	prepare new uid
				*(p-1) = '0';
				*p = 'x';
				p--;
				uids[uid++] = strtoul(p, &p1, 16);
			}
		}
		inf.Close();
	}

	dTotalUIDs = uid;
	if ( dTotalUIDs <= 0 )
	{
		g_Log.Event(LOGM_INIT, "Save files are empty, defragmentation is not needed\n");
		return;
	}

	g_Log.Event(LOGM_INIT, "Found %lu UIDs (latest: 0%lx)\n", uid, uids[dTotalUIDs - 1]);
	g_Log.Event(LOGM_INIT, "Quick-sorting UIDs array...\n");
	dword_q_sort(uids, 0, dTotalUIDs - 1);

	for ( i = 0; i < 5; i++ )
	{
		strncpy(z, path, sizeof(z) - 1);
		if ( i == 0 )
			strcat(z, SPHERE_FILE "accu.scp");
		else if ( i == 1 )
			strcat(z, SPHERE_FILE "chars" SPHERE_SCRIPT);
		else if ( i == 2 )
			strcat(z, SPHERE_FILE "data" SPHERE_SCRIPT);
		else if ( i == 3 )
			strcat(z, SPHERE_FILE "world" SPHERE_SCRIPT);
		else if ( i == 4 )
			strcat(z, SPHERE_FILE "statics" SPHERE_SCRIPT);

		g_Log.Event(LOGM_INIT, "Updating UIDs in '%s' to '%s.new'\n", z, z);
		if ( !inf.Open(z, OF_READ|OF_TEXT|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for reading. Skipped!\n", z);
			continue;
		}
		strcat(z, ".new");
		if ( !ouf.Open(z, OF_WRITE|OF_CREATE|OF_DEFAULTMODE) )
		{
			g_Log.Event(LOGM_INIT, "Can't open file '%s' for writing. Skipped!\n", z);
			continue;
		}
		dBytesRead = dTotalMb = 0;
		while ( inf.ReadString(buf, sizeof(buf)) )
		{
			uid = strlen(buf);
			if (uid > (COUNTOF(buf) - 3))
				uid = COUNTOF(buf) - 3;

			buf[uid] = buf[uid+1] = buf[uid+2] = 0;	// just to be sure to be in line always
							// NOTE: it is much faster than to use memcpy to clear before reading
			bSpecial = false;
			dBytesRead += uid;
			if ( dBytesRead > mb5 )
			{
				dBytesRead -= mb5;
				dTotalMb += 5;
				g_Log.Event(LOGM_INIT, "Total processed %lu Mb\n", dTotalMb);
			}
			p = buf;

			//	Note 28-Jun-2004
			//	mounts seems having ACTARG1 > 0x30000000. The actual UID is ACTARG1-0x30000000. The
			//	new also should be new+0x30000000. need investigation if this can help making mounts
			//	not to disappear after the defrag
			if (( buf[0] == 'A' ) && ( strstr(buf, "ACTARG1=0") == buf ))		// ACTARG1=
				p += 8;
			else if (( buf[0] == 'C' ) && ( strstr(buf, "CONT=0") == buf ))			// CONT=
				p += 5;
			else if (( buf[0] == 'C' ) && ( strstr(buf, "CHARUID=0") == buf ))		// CHARUID=
				p += 8;
			else if (( buf[0] == 'L' ) && ( strstr(buf, "LASTCHARUID=0") == buf ))	// LASTCHARUID=
				p += 12;
			else if (( buf[0] == 'L' ) && ( strstr(buf, "LINK=0") == buf ))			// LINK=
				p += 5;
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MEMBER=0") == buf ))		// MEMBER=
			{
				p += 7;
				bSpecial = true;
			}
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE1=0") == buf ))		// MORE1=
				p += 6;
			else if (( buf[0] == 'M' ) && ( strstr(buf, "MORE2=0") == buf ))		// MORE2=
				p += 6;
			else if (( buf[0] == 'S' ) && ( strstr(buf, "SERIAL=0") == buf ))		// SERIAL=
				p += 7;
			else if ((( buf[0] == 'T' ) && ( strstr(buf, "TAG.") == buf )) ||		// TAG.=
					 (( buf[0] == 'R' ) && ( strstr(buf, "REGION.TAG") == buf )))
			{
				while ( *p && ( *p != '=' )) p++;
				p++;
			}
			else if (( i == 2 ) && strchr(buf, '='))	// spheredata.scp - plain VARs
			{
				while ( *p && ( *p != '=' )) p++;
				p++;
			}
			else p = NULL;

			//	UIDs are always hex, so prefixed by 0
			if ( p && ( *p != '0' )) p = NULL;

			//	here we got potentialy UID-contained variable
			//	check if it really is only UID-like var containing
			if ( p )
			{
				p1 = p;
				while ( *p1 &&
					((( *p1 >= '0' ) && ( *p1 <= '9' )) ||
					 (( *p1 >= 'a' ) && ( *p1 <= 'f' )))) p1++;
				if ( !bSpecial )
				{
					if ( *p1 && ( *p1 != '\r' ) && ( *p1 != '\n' )) // some more text in line
						p = NULL;
				}
			}

			//	here we definitely know that this is very uid-like
			if ( p )
			{
				c = *p1;

				*p1 = 0;
				//	here in p we have the current value of the line.
				//	check if it is a valid UID

				//	prepare converting 0.. to 0x..
				c1 = *(p-1);
				c2 = *p;
				*(p-1) = '0';
				*p = 'x';
				p--;
				uid = strtoul(p, &p1, 16);
				p++;
				*(p-1) = c1;
				*p = c2;
				//	Note 28-Jun-2004
				//	The search algourytm is very simple and fast. But maybe integrate some other, at least /2 algorythm
				//	since has amount/2 tryes at worst chance to get the item and never scans the whole array
				//	It should improve speed since defragmenting 150Mb saves takes ~2:30 on 2.0Mhz CPU
				{
					DWORD	dStep = dTotalUIDs/2;
					d = dStep;
					for (;;)
					{
						dStep /= 2;

						if ( uids[d] == uid )
						{
							uid = d | (uids[d]&0xF0000000);	// do not forget attach item and special flags like 04..
							break;
						}
						else if ( uids[d] < uid ) d += dStep;
						else d -= dStep;

						if ( dStep == 1 )
						{
							uid = ULONG_MAX;
							break; // did not find the UID
						}
					}
				}

				//	Search for this uid in the table
/*				for ( d = 0; d < dTotalUIDs; d++ )
				{
					if ( !uids[d] )	// end of array
					{
						uid = ULONG_MAX;
						break;
					}
					else if ( uids[d] == uid )
					{
						uid = d | (uids[d]&0xF0000000);	// do not forget attach item and special flags like 04..
						break;
					}
				}*/

				//	replace UID by the new one since it has been found
				*p1 = c;
				if ( uid != ULONG_MAX )
				{
					*p = 0;
					strncpy(z, p1, sizeof(z) - 1);
					sprintf(z1, "0%lx", uid);
					strcat(buf, z1);
					strcat(buf, z);
				}
			}
			//	output the resulting line
			ouf.Write(buf, strlen(buf));
		}
		inf.Close();
		ouf.Close();
	}
	free(uids);
	g_Log.Event(LOGM_INIT,	"Defragmentation complete.\n");
}
Пример #7
0
int CWebPageDef::ServPageRequest( CClient * pClient, LPCTSTR pszURLArgs, CGTime * pdateIfModifiedSince )
{
	ADDTOCALLSTACK("CWebPageDef::ServPageRequest");
	UNREFERENCED_PARAMETER(pszURLArgs);
	// Got a web page request from the client.
	// ARGS:
	//  pszURLArgs = args on the URL line ex. http://www.hostname.com/dir?args
	// RETURN:
	//  HTTP error code = 0=200 page was served.

	ASSERT(pClient);

	if ( HasTrigger(WTRIG_Load))
	{
		CResourceLock s;
		if ( ResourceLock(s))
		{
			if (CScriptObj::OnTriggerScript( s, sm_szTrigName[WTRIG_Load], pClient, NULL ) == TRIGRET_RET_TRUE)
				return( 0 );	// Block further action.
		}
	}

	if ( m_privlevel )
	{
		if ( !pClient->m_pAccount )
			return 401;	// Authorization required
		if ( pClient->GetPrivLevel() < m_privlevel )
			return 403;	// Forbidden
	}

	CGTime datetime = CGTime::GetCurrentTime();

	LPCTSTR pszName;
	bool fGenerate = false;

	if ( m_type == WEBPAGE_TEMPLATE ) // my version of cgi
	{
		pszName = GetDstName();
		if ( pszName[0] == '\0' )
		{
			pszName = "temppage.htm";
			fGenerate = true;
		}
		else
		{
			fGenerate = ! m_iUpdatePeriod;
		}

		// The page must be generated on demand.
		if ( ! WebPageUpdate( fGenerate, pszName, pClient ))
			return 500;
	}
	else
	{
		pszName = GetName();
	}

	// Get proper Last-Modified: time.
	time_t dateChange;
	DWORD dwSize;
	if ( ! CFileList::ReadFileInfo( pszName, dateChange, dwSize ))
	{
		return 500;
	}

	const char *sDate = datetime.FormatGmt(NULL);	// current date.

	if ( !fGenerate && !pdateIfModifiedSince && (pdateIfModifiedSince->IsTimeValid() && pdateIfModifiedSince->GetTime() > dateChange) )
	{
		TCHAR *pszTemp = Str_GetTemp();
		sprintf(pszTemp, "HTTP/1.1 304 Not Modified\r\nDate: %s\r\nServer: " GRAY_TITLE " V " GRAY_VERSION "\r\nContent-Length: 0\r\n\r\n", sDate);
		new PacketWeb(pClient, (BYTE*)pszTemp, strlen(pszTemp));
		return 0;
	}

	// Now serve up the page.
	CGFile FileRead;
	if ( ! FileRead.Open( pszName, OF_READ|OF_BINARY ))
		return 500;

	// Send the header first.
	TCHAR szTmp[8*1024];
	size_t iLen = sprintf(szTmp,
		"HTTP/1.1 200 OK\r\n" // 100 Continue
		"Date: %s\r\n"
		"Server: " GRAY_TITLE " V " GRAY_VERSION "\r\n"
		"Accept-Ranges: bytes\r\n"
		"Content-Type: %s\r\n",
		static_cast<LPCTSTR>(sDate),
		static_cast<LPCTSTR>(sm_szPageType[m_type]) // type of the file. image/gif, image/x-xbitmap, image/jpeg
		);

	if ( m_type == WEBPAGE_TEMPLATE )
		iLen += sprintf(szTmp + iLen, "Expires: 0\r\n");
	else
		iLen += sprintf(szTmp + iLen, "Last-Modified: %s\r\n",  CGTime(dateChange).FormatGmt(NULL));

	iLen += sprintf( szTmp + iLen,
		"Content-Length: %lu\r\n"
		"\r\n",
		dwSize
		);

	PacketWeb packet;
	packet.setData((BYTE*)szTmp, iLen);
	packet.send(pClient);

	for (;;)
	{
		iLen = FileRead.Read( szTmp, sizeof( szTmp ) );
		if ( iLen <= 0 )
			break;
		packet.setData((BYTE*)szTmp, iLen);
		packet.send(pClient);
		//dwSize -= iLen;
		if ( iLen < sizeof( szTmp ) )
		{
			// memset( szTmp+iLen, 0, sizeof(szTmp)-iLen );
			break;
		}
	}
	return 0;
}
Пример #8
0
bool CClient::OnRxAxis( const BYTE * pData, size_t iLen )
{
	ADDTOCALLSTACK("CClient::OnRxAxis");
	if ( !iLen || ( GetConnectType() != CONNECT_AXIS ))
		return false;

	while ( iLen -- )
	{
		int iRet = OnConsoleKey( m_Targ_Text, *pData++, GetAccount() != NULL );
		if ( ! iRet )
			return( false );
		if ( iRet == 2 )
		{
			if ( GetAccount() == NULL )
			{
				if ( !m_zLogin[0] )
				{
					if ( static_cast<unsigned int>(m_Targ_Text.GetLength()) <= (COUNTOF(m_zLogin) - 1) )
						strcpy(m_zLogin, m_Targ_Text);
					m_Targ_Text.Empty();
				}
				else
				{
					CGString sMsg;

					CAccountRef pAccount = g_Accounts.Account_Find(m_zLogin);
					if (( pAccount == NULL ) || ( pAccount->GetPrivLevel() < PLEVEL_Counsel ))
					{
						SysMessagef("\"MSG:%s\"", g_Cfg.GetDefaultMsg(DEFMSG_AXIS_NOT_PRIV));
						m_Targ_Text.Empty();
						return false;
					}
					if ( LogIn(m_zLogin, m_Targ_Text, sMsg ) == PacketLoginError::Success )
					{
						m_Targ_Text.Empty();
						if ( GetPrivLevel() < PLEVEL_Counsel )
						{
							SysMessagef("\"MSG:%s\"", g_Cfg.GetDefaultMsg(DEFMSG_AXIS_NOT_PRIV));
							return false;
						}
						if (GetPeer().IsValidAddr())
						{
							CScriptTriggerArgs Args;
							Args.m_VarsLocal.SetStrNew("Account",GetName());
							Args.m_VarsLocal.SetStrNew("IP",GetPeer().GetAddrStr());
							TRIGRET_TYPE tRet = TRIGRET_RET_DEFAULT;
							r_Call("f_axis_preload", this, &Args, NULL, &tRet);
							if ( tRet == TRIGRET_RET_FALSE )
								return false;
							if ( tRet == TRIGRET_RET_TRUE )
							{
								SysMessagef("\"MSG:%s\"", g_Cfg.GetDefaultMsg(DEFMSG_AXIS_DENIED));
								return false;
							}

							time_t dateChange;
							DWORD dwSize;
							if ( ! CFileList::ReadFileInfo( "Axis.db", dateChange, dwSize ))
							{
								SysMessagef("\"MSG:%s\"", g_Cfg.GetDefaultMsg(DEFMSG_AXIS_INFO_ERROR));
								return false;
							}

							CGFile FileRead;
							if ( ! FileRead.Open( "Axis.db", OF_READ|OF_BINARY ))
							{
								SysMessagef("\"MSG:%s\"", g_Cfg.GetDefaultMsg(DEFMSG_AXIS_FILE_ERROR));
								return false;
							}

							TCHAR szTmp[8*1024];
							PacketWeb packet;
							for (;;)
							{
								size_t iLength = FileRead.Read( szTmp, sizeof( szTmp ) );
								if ( iLength <= 0 )
									break;
								packet.setData((BYTE*)szTmp, iLength);
								packet.send(this);
								dwSize -= iLength;
								if ( dwSize <= 0 )
									break;
							}
							return true;
						}
						return false;
					}
					else if ( ! sMsg.IsEmpty())
					{
						SysMessagef("\"MSG:%s\"", (LPCTSTR)sMsg);
						return false;
					}
					m_Targ_Text.Empty();
				}
				return true;
			}
		}
	}
	return true;
}
Пример #9
0
void CMapDiffCollection::LoadMapDiffs()
{
	// Load mapdif* and stadif* Files
	ADDTOCALLSTACK("CMapDiffCollection::LoadMapDiffs");
	if ( m_bLoaded ) // already loaded
		return;

	DWORD dwLength = 0, dwBlockId = 0;
	DWORD dwOffset = 0, dwRead = 0;
	CMapDiffBlock * pMapDiffBlock = NULL;

	for ( int m = 0; m < 256; ++m )
	{
		if ( !g_MapList.IsMapSupported( m ) )
			continue;

		int map = g_MapList.m_mapid[m];

		// Load Mapdif Files
		{
			CGFile * pFileMapdif	= &(g_Install.m_Mapdif[map]);
			CGFile * pFileMapdifl	= &(g_Install.m_Mapdifl[map]);

			// Check that the relevant dif files are available
			if ( pFileMapdif->IsFileOpen() && pFileMapdifl->IsFileOpen() )
			{
				// Make sure that we're at the beginning of the files
				pFileMapdif->SeekToBegin();
				pFileMapdifl->SeekToBegin();

				dwLength = pFileMapdifl->GetLength();
				dwRead = dwOffset = 0;

				for ( ; dwRead < dwLength; dwOffset += sizeof(CUOMapBlock) )
				{
					dwRead += pFileMapdifl->Read( &dwBlockId, sizeof(dwBlockId) );
					pMapDiffBlock = GetNewBlock( dwBlockId, map );

					if ( pMapDiffBlock->m_pTerrainBlock )
						delete pMapDiffBlock->m_pTerrainBlock;

					CUOMapBlock * pTerrain = new CUOMapBlock();
					if ( pFileMapdif->Seek( dwOffset ) != dwOffset )
					{
						g_Log.EventError("Reading mapdif%d.mul FAILED.\n", map);
						delete pTerrain;
						break;
					}
					else if ( pFileMapdif->Read( pTerrain, sizeof(CUOMapBlock) ) != sizeof(CUOMapBlock) )
					{
						g_Log.EventError("Reading mapdif%d.mul FAILED. [index=%lu offset=%lu]\n", map, dwBlockId, dwOffset);
						delete pTerrain;
						break;
					}

					pMapDiffBlock->m_pTerrainBlock = pTerrain;
				}
			}
		} // Mapdif

		// Load Stadif Files
		{
			CGFile * pFileStadif	= &(g_Install.m_Stadif[map]);
			CGFile * pFileStadifl	= &(g_Install.m_Stadifl[map]);
			CGFile * pFileStadifi	= &(g_Install.m_Stadifi[map]);

			// Check that the relevant dif files are available
			if ( !pFileStadif->IsFileOpen() || !pFileStadifl->IsFileOpen() || !pFileStadifi->IsFileOpen() )
				continue;

			// Make sure that we're at the beginning of the files
			pFileStadif->SeekToBegin();
			pFileStadifl->SeekToBegin();
			pFileStadifi->SeekToBegin();

			dwLength = pFileStadifl->GetLength();
			dwRead = dwOffset = 0;
	
			for ( ; dwRead < dwLength; dwOffset += sizeof(CUOIndexRec) )
			{
				dwRead += pFileStadifl->Read( &dwBlockId, sizeof(dwBlockId) );
				
				pMapDiffBlock = GetNewBlock( dwBlockId, map );
				if ( pMapDiffBlock->m_pStaticsBlock )
					delete[] pMapDiffBlock->m_pStaticsBlock;

				pMapDiffBlock->m_iStaticsCount = 0;
				pMapDiffBlock->m_pStaticsBlock = NULL;

				if ( pFileStadifi->Seek( dwOffset ) != dwOffset )
				{
					g_Log.EventError("Reading stadifi%d.mul FAILED.\n", map);
					break;
				}

				CUOIndexRec index;
				if ( pFileStadifi->Read( &index, sizeof(CUOIndexRec)) != sizeof(CUOIndexRec) )
				{
					g_Log.EventError("Reading stadifi%d.mul FAILED. [index=%lu offset=%lu]\n", map, dwBlockId, dwOffset);
					break;
				}
				else if ( !index.HasData() ) // This happens if the block has been intentionally patched to remove statics
				{
					continue;
				}
				else if ((index.GetBlockLength() % sizeof(CUOStaticItemRec)) != 0) // Make sure that the statics block length is valid
				{
					g_Log.EventError("Reading stadifi%d.mul FAILED. [index=%lu offset=%lu length=%lu]\n", map, dwBlockId, dwOffset, index.GetBlockLength());
					break;
				}

				pMapDiffBlock->m_iStaticsCount = index.GetBlockLength()/sizeof(CUOStaticItemRec);
				pMapDiffBlock->m_pStaticsBlock = new CUOStaticItemRec[pMapDiffBlock->m_iStaticsCount];
				if ( !g_Install.ReadMulData(*pFileStadif, index, pMapDiffBlock->m_pStaticsBlock) )
				{
					// This shouldn't happen, if this fails then the block will
					// be left with no statics
					pMapDiffBlock->m_iStaticsCount = 0;
					delete[] pMapDiffBlock->m_pStaticsBlock;
					pMapDiffBlock->m_pStaticsBlock = NULL;
					g_Log.EventError("Reading stadif%d.mul FAILED. [index=%lu offset=%lu]\n", map, dwBlockId, dwOffset);
					break;
				}
			}
		} // Stadif
	}

	m_bLoaded = true;
}
Пример #10
0
void CGrayMapBlock::Load( int bx, int by )
{
	ADDTOCALLSTACK("CGrayMapBlock::Load");
	// Read in all the statics data for this block.
	m_CacheTime.InitCacheTime();		// This is invalid !

	ASSERT( bx < (g_MapList.GetX(m_map)/UO_BLOCK_SIZE) );
	ASSERT( by < (g_MapList.GetY(m_map)/UO_BLOCK_SIZE) );

	if (( m_map < 0 ) || ( m_map >= 255 ))
	{
		g_Log.EventError("Unsupported map #%d specified. Auto-fixing that to 0.\n", m_map);
		m_map = 0;
	}

	unsigned long ulBlockIndex = (bx*(g_MapList.GetY(m_map)/UO_BLOCK_SIZE) + by);

	if ( !g_MapList.m_maps[m_map] )
	{
		memset( &m_Terrain, 0, sizeof( m_Terrain ));
		throw CGrayError(LOGL_CRIT, 0, "CGrayMapBlock: Map is not supported since MUL files for it not available.");
	}

	bool bPatchedTerrain = false, bPatchedStatics = false;

	if ( g_Cfg.m_fUseMapDiffs && g_MapList.m_pMapDiffCollection )
	{
		// Check to see if the terrain or statics in this block is patched
		CMapDiffBlock * pDiffBlock = g_MapList.m_pMapDiffCollection->GetAtBlock( ulBlockIndex, g_MapList.m_mapid[m_map] );
		if ( pDiffBlock )
		{
			if ( pDiffBlock->m_pTerrainBlock )
			{
				memcpy( &m_Terrain, pDiffBlock->m_pTerrainBlock, sizeof(CUOMapBlock) );
				bPatchedTerrain = true;
			}

			if ( pDiffBlock->m_iStaticsCount >= 0 )
			{
				m_Statics.LoadStatics( pDiffBlock->m_iStaticsCount, pDiffBlock->m_pStaticsBlock );
				bPatchedStatics = true;
			}
		}
	}

	// Only load terrain if it wasn't patched
	if ( ! bPatchedTerrain )
	{
		int mapNumber = g_MapList.m_mapnum[m_map];
		CGFile * pFile = &(g_Install.m_Maps[mapNumber]);
		ASSERT(pFile != NULL);
		ASSERT(pFile->IsFileOpen());
		
		// determine the location in the file where the data needs to be read from
		CUOIndexRec index;
		index.SetupIndex( ulBlockIndex * sizeof(CUOMapBlock), sizeof(CUOMapBlock));

		unsigned long fileOffset = index.GetFileOffset();
		if (g_Install.m_IsMapUopFormat[mapNumber])
		{
			for ( int i = 0; i < 256; i++ )
			{
				MapAddress pMapAddress = g_Install.m_UopMapAddress[mapNumber][i];
				if (( ulBlockIndex <= pMapAddress.dwLastBlock ) && ( ulBlockIndex >= pMapAddress.dwFirstBlock ))
				{
					fileOffset = static_cast<unsigned long>(pMapAddress.qwAdress + ((ulBlockIndex - pMapAddress.dwFirstBlock)*196));
					break;
				}
			}


		/*	// when the map is in a UOP container we need to modify the file offset to account for the block header
			// data. the uop file format splits the map data into smaller 'blocks', each of which has its on header (as
			// well as an overall file header)
			//
			// we must therefore determine which block of data contains the map information we need, and then add
			// the extra number of bytes to our file offset
			const unsigned long fileHeaderLength = 40; // length of overall file header
			const unsigned long blockHeaderLength = 12; // length of the block header
			const unsigned long firstDataEntryOffset = 3412; // offset of first actual data byte within a block
			const unsigned long firstBlockDataEntryOffset = fileHeaderLength + blockHeaderLength + firstDataEntryOffset; // offset of first actual data byte for the first entry in the file
			const unsigned long mapBlockLength = 802816; // maximum size of a block

			// note: to avoid writing code that parse the UOP format properly we are calculating a new offset based on the
			// sizes of the blocks as-of client 7.0.24.0. the nature of the UOP format allows the block lengths to differ
			// and for the data to be compressed, so we should watch out for this in the future (and if this happens we'll
			// have to handle UOP data properly)

			unsigned long block = fileOffset / mapBlockLength;
			fileOffset += firstBlockDataEntryOffset + ((firstDataEntryOffset) * (block / 100)) + (blockHeaderLength * block);*/
		}

		// seek to position in file
		if ( pFile->Seek( fileOffset, SEEK_SET ) != fileOffset )
		{
			memset( &m_Terrain, 0, sizeof(m_Terrain));
			throw CGrayError(LOGL_CRIT, CGFile::GetLastError(), "CGrayMapBlock: Seek Ver");
		}

		// read terrain data
		if ( pFile->Read( &m_Terrain, sizeof(CUOMapBlock)) <= 0 )
		{
			memset( &m_Terrain, 0, sizeof( m_Terrain ));
			throw CGrayError(LOGL_CRIT, CGFile::GetLastError(), "CGrayMapBlock: Read");
		}
	}

	// Only load statics if they weren't patched
	if ( ! bPatchedStatics )
	{
		m_Statics.LoadStatics( ulBlockIndex, m_map );
	}

	m_CacheTime.HitCacheTime();		// validate.
}