Jump to content

[C++] Bug fixed Recoded & Optimalized TextFileLoader to c++17 based on Martysama source


Recommended Posts

  • Active+ Member

Hello due to i was working on optimalization and my new pack system with xxh3 hash and LRU cache system (after first files load i can use this files directly from RAM so its far faster than getting every 1 file who was small from disc) on 1 pserver i decided to recode a lot of c++98 code in Metin2 but when i looked at TextFileLoader i got terrified so... i decided to fix all bugs and do recode there was a lot of "possible" bugs in TextFileLoader 

from my test that seems to be 5-8x times faster and far more stable 
my limitations was to dont change structure (if i will change structure ofc it will be far better but i want to dont recode whole game) so its ready to copy and paste 🙂

in c++20 u can do more but its not needed with that version (only if u want +5-10% faster)

if you finds any bugs post it here i will try to fix it and send here 


TextFileLoader.h

#pragma once

#include "../eterBase/FileLoader.h"
#include "../eterBase/MappedFile.h"
#include "../eterLib/Util.h"
#include "../eterLib/Pool.h"

class CTextFileLoader {
public:
    typedef struct SGroupNode {
    static DWORD GenNameKey(const char* c_szGroupName, size_t uGroupNameLen);
    static DWORD GenNameKey(std::string_view sv);

    void SetGroupName(const std::string& c_rstGroupName);
    bool IsGroupNameKey(DWORD dwGroupNameKey);

    const std::string& GetGroupName();

    CTokenVector* GetTokenVector(DWORD dwGroupNameKey);
    CTokenVector* GetTokenVector(const std::string& c_rstGroupName);

    bool IsExistTokenVector(DWORD dwGroupNameKey);
    bool IsExistTokenVector(const std::string& c_rstGroupName);

    void InsertTokenVector(const std::string& c_rstGroupName,
        const CTokenVector& c_rkVct_stToken);

    DWORD m_dwGroupNameKey;
    std::string m_strGroupName;

    std::map < DWORD, CTokenVector > m_kMap_dwKey_kVct_stToken;

    SGroupNode* pParentNode;
    std::vector < SGroupNode* > ChildNodeVector;

    static SGroupNode* New();
    static void Delete(SGroupNode* pkNode);

    static void DestroySystem();
    static CDynamicPool < SGroupNode > ms_kPool;
}
      TGroupNode;

      typedef std::vector < TGroupNode* > TGroupNodeVector;

      class CGotoChild {
      public: CGotoChild(CTextFileLoader* pOwner,
          const char* c_szKey) : m_pOwner(pOwner) {
          m_pOwner->SetChildNode(c_szKey);
      }

            CGotoChild(CTextFileLoader* pOwner, DWORD dwIndex) : m_pOwner(pOwner) {
                m_pOwner->SetChildNode(dwIndex);
            }

            ~CGotoChild() {
                m_pOwner->SetParentNode();
            }

            CTextFileLoader* m_pOwner;
      };

public:
      static void DestroySystem();
      static void SetCacheMode();
      static CTextFileLoader* Cache(const char* c_szFileName);

public: 
      CTextFileLoader();
      virtual~CTextFileLoader();

      void Destroy();

      bool Load(const char* c_szFileName);
      const char* GetFileName();
      bool IsEmpty();

      void SetTop() {
          m_pcurNode = &m_GlobalNode;
      }

      DWORD GetChildNodeCount() {
          if (!m_pcurNode)
              return 0;

          return (DWORD)m_pcurNode->ChildNodeVector.size();
      }

      BOOL SetChildNode(const char* c_szKey) {
          if (!m_pcurNode)
              return FALSE;

          DWORD dwKey = SGroupNode::GenNameKey(c_szKey, strlen(c_szKey));

          for (TGroupNode* node : m_pcurNode->ChildNodeVector) {
              if (node->IsGroupNameKey(dwKey)) {
                  m_pcurNode = node;
                  return TRUE;
              }
          }

          return FALSE;
      }

      BOOL SetChildNode(DWORD dwIndex) {
          if (!m_pcurNode)
              return FALSE;

          if (dwIndex >= m_pcurNode->ChildNodeVector.size())
              return FALSE;

          m_pcurNode = m_pcurNode->ChildNodeVector[dwIndex];
          return TRUE;
      }

      BOOL SetChildNode(const std::string& c_rstrKeyHead, DWORD dwIndex);

      BOOL SetParentNode() {
          if (!m_pcurNode || !m_pcurNode->pParentNode)
              return FALSE;

          m_pcurNode = m_pcurNode->pParentNode;
          return TRUE;
      }

      BOOL GetCurrentNodeName(std::string* pstrName) {
          if (!m_pcurNode)
              return FALSE;

          *pstrName = m_pcurNode->GetGroupName();
          return TRUE;
      }

      BOOL IsToken(const char* c_szKey) {
          if (!m_pcurNode)
              return FALSE;

          return m_pcurNode->IsExistTokenVector(SGroupNode::GenNameKey(c_szKey, strlen(c_szKey)));
      }

      BOOL IsToken(const std::string& c_rstrKey) {
          if (!m_pcurNode)
              return FALSE;

          return m_pcurNode->IsExistTokenVector(c_rstrKey);
      }

      BOOL GetTokenVector(const char* c_szKey, CTokenVector** ppTokenVector) {
          if (!m_pcurNode)
              return FALSE;

          CTokenVector* pkRet = m_pcurNode->GetTokenVector(SGroupNode::GenNameKey(c_szKey, strlen(c_szKey)));

          if (!pkRet)
              return FALSE;

          *ppTokenVector = pkRet;
          return TRUE;
      }

      BOOL GetTokenVector(const std::string& c_rstrKey, CTokenVector** ppTokenVector) {
          if (!m_pcurNode)
              return FALSE;

          CTokenVector* pkRet = m_pcurNode->GetTokenVector(c_rstrKey);

          if (!pkRet)
              return FALSE;

          *ppTokenVector = pkRet;
          return TRUE;
      }

      BOOL GetTokenBoolean(const char* c_szKey, BOOL* pData);
      BOOL GetTokenByte(const char* c_szKey, BYTE* pData);
      BOOL GetTokenWord(const char* c_szKey, WORD* pData);
      BOOL GetTokenInteger(const char* c_szKey, int* pData);
      BOOL GetTokenDoubleWord(const char* c_szKey, DWORD* pData);
      BOOL GetTokenFloat(const char* c_szKey, float* pData);

      BOOL GetTokenBoolean(const std::string& c_rstrKey, BOOL* pData);
      BOOL GetTokenByte(const std::string& c_rstrKey, BYTE* pData);
      BOOL GetTokenWord(const std::string& c_rstrKey, WORD* pData);
      BOOL GetTokenInteger(const std::string& c_rstrKey, int* pData);
      BOOL GetTokenDoubleWord(const std::string& c_rstrKey, DWORD* pData);
      BOOL GetTokenFloat(const std::string& c_rstrKey, float* pData);

      BOOL GetTokenVector2(const char* c_szKey, D3DXVECTOR2* pVector2);
      BOOL GetTokenVector3(const char* c_szKey, D3DXVECTOR3* pVector3);
      BOOL GetTokenVector4(const char* c_szKey, D3DXVECTOR4* pVector4);
      BOOL GetTokenPosition(const char* c_szKey, D3DXVECTOR3* pVector);
      BOOL GetTokenQuaternion(const char* c_szKey, D3DXQUATERNION* pQ);
      BOOL GetTokenDirection(const char* c_szKey, D3DVECTOR* pVector);
      BOOL GetTokenColor(const char* c_szKey, D3DXCOLOR* pColor);
      BOOL GetTokenColor(const char* c_szKey, D3DCOLORVALUE* pColor);
      BOOL GetTokenString(const char* c_szKey, std::string* pString);

      BOOL GetTokenVector2(const std::string& k, D3DXVECTOR2* v) {
          return GetTokenVector2(k.c_str(), v);
      }
      BOOL GetTokenVector3(const std::string& k, D3DXVECTOR3* v) {
          return GetTokenVector3(k.c_str(), v);
      }
      BOOL GetTokenVector4(const std::string& k, D3DXVECTOR4* v) {
          return GetTokenVector4(k.c_str(), v);
      }
      BOOL GetTokenPosition(const std::string& k, D3DXVECTOR3* v) {
          return GetTokenPosition(k.c_str(), v);
      }
      BOOL GetTokenQuaternion(const std::string& k, D3DXQUATERNION* q) {
          return GetTokenQuaternion(k.c_str(), q);
      }
      BOOL GetTokenDirection(const std::string& k, D3DVECTOR* v) {
          return GetTokenDirection(k.c_str(), v);
      }
      BOOL GetTokenColor(const std::string& k, D3DXCOLOR* c) {
          return GetTokenColor(k.c_str(), c);
      }
      BOOL GetTokenColor(const std::string& k, D3DCOLORVALUE* c) {
          return GetTokenColor(k.c_str(), c);
      }
      BOOL GetTokenString(const std::string& k, std::string* s) {
          return GetTokenString(k.c_str(), s);
      }

protected: 
         void __DestroyGroupNodeVector();
         bool LoadGroup(TGroupNode* pGroupNode);

protected: 
         std::string m_strFileName;

         std::unique_ptr < char[] > m_acBufData;
         DWORD m_dwBufSize;
         DWORD m_dwBufCapacity;

         DWORD m_dwcurLineIndex;

         CMemoryTextFileLoader m_textFileLoader;

         TGroupNode m_GlobalNode;
         TGroupNode* m_pcurNode;

         std::vector < SGroupNode* > m_kVct_pkNode;

protected: 
         static std::map < DWORD,
         CTextFileLoader* > ms_kMap_dwNameKey_pkTextFileLoader;
         static bool ms_isCacheMode;
};
// KoMaR1911 Recode contact: discord komar1911


TextFileLoader.cpp

 

#include "StdAfx.h"
#include "../eterBase/CRC32.h"
#include "../EterPack/EterPackManager.h"
#include "Pool.h"
#include "TextFileLoader.h"

#include <string>
#include <algorithm>
#include <memory>
#include <vector>
#include <string_view>
#include <cerrno>
#include <cctype>
#include <cstdlib>

std::map< DWORD, CTextFileLoader* > CTextFileLoader::ms_kMap_dwNameKey_pkTextFileLoader;
bool CTextFileLoader::ms_isCacheMode = false;
CDynamicPool< CTextFileLoader::SGroupNode > CTextFileLoader::SGroupNode::ms_kPool;

static bool SafeParseFloat( const std::string& str, float* outVal )
{
	if ( str.empty( ) )
		return false;

	char* end;
	errno = 0;
	*outVal = std::strtof( str.c_str( ), &end );

	return ( end == str.c_str( ) + str.size( ) && errno == 0 );
}

static bool SafeParseInt( const std::string& str, int* outVal )
{
	if ( str.empty( ) )
		return false;

	char* end;
	errno = 0;
	*outVal = std::strtol( str.c_str( ), &end, 10 );

	return ( end == str.c_str( ) + str.size( ) && errno == 0 );
}

static void FastSplitLine( const char* line, size_t len, std::vector< std::string_view >& outTokens )
{
	outTokens.clear( );

	if ( !line || len == 0 )
		return;

	const char* ptr = line;
	const char* end = line + len;

	while ( ptr < end )
	{
		while ( ptr < end && ( unsigned char )*ptr <= ' ' )
			++ptr;

		if ( ptr >= end )
			break;

		if ( *ptr == '"' )
		{
			++ptr;
			const char* startToken = ptr;

			while ( ptr < end && *ptr != '"' )
				++ptr;

			outTokens.emplace_back( startToken, ptr - startToken );

			if ( ptr < end )
				++ptr;
		}
		else
		{
			const char* startToken = ptr;

			while ( ptr < end && ( unsigned char )*ptr > ' ' )
				++ptr;

			outTokens.emplace_back( startToken, ptr - startToken );
		}
	}
}

template< size_t N >
static bool IsEqualLower( std::string_view sv, const char ( &literal )[N] )
{
	constexpr size_t len = N - 1;

	if ( sv.length( ) != len )
		return false;

	for ( size_t i = 0; i < len; ++i )
	{
		if ( std::tolower( ( unsigned char )sv[i] ) != literal[i] )
			return false;
	}

	return true;
}

DWORD CTextFileLoader::SGroupNode::GenNameKey( const char* c_szGroupName, size_t uGroupNameLen )
{
	return GetCRC32( c_szGroupName, uGroupNameLen );
}

DWORD CTextFileLoader::SGroupNode::GenNameKey( std::string_view sv )
{
	return GetCRC32( sv.data( ), sv.length( ) );
}

CTokenVector* CTextFileLoader::SGroupNode::GetTokenVector( const std::string& c_rstGroupName )
{
	return GetTokenVector( GenNameKey( c_rstGroupName.c_str( ), c_rstGroupName.length( ) ) );
}

CTokenVector* CTextFileLoader::SGroupNode::GetTokenVector( DWORD dwGroupNameKey )
{
	auto it = m_kMap_dwKey_kVct_stToken.find( dwGroupNameKey );

	if ( it != m_kMap_dwKey_kVct_stToken.end( ) )
		return &it->second;

	return nullptr;
}

bool CTextFileLoader::SGroupNode::IsExistTokenVector( const std::string& c_rstGroupName )
{
	return IsExistTokenVector( GenNameKey( c_rstGroupName.c_str( ), c_rstGroupName.length( ) ) );
}

bool CTextFileLoader::SGroupNode::IsExistTokenVector( DWORD dwGroupNameKey )
{
	return m_kMap_dwKey_kVct_stToken.find( dwGroupNameKey ) != m_kMap_dwKey_kVct_stToken.end( );
}

void CTextFileLoader::SGroupNode::InsertTokenVector( const std::string& c_rstGroupName, const CTokenVector& c_rkVct_stToken )
{
	DWORD dwGroupNameKey = GenNameKey( c_rstGroupName.c_str( ), c_rstGroupName.length( ) );
	m_kMap_dwKey_kVct_stToken.emplace( dwGroupNameKey, c_rkVct_stToken );
}

const std::string& CTextFileLoader::SGroupNode::GetGroupName( )
{
	return m_strGroupName;
}

bool CTextFileLoader::SGroupNode::IsGroupNameKey( DWORD dwGroupNameKey )
{
	return dwGroupNameKey == m_dwGroupNameKey;
}

void CTextFileLoader::SGroupNode::SetGroupName( const std::string& c_rstGroupName )
{
	m_strGroupName = c_rstGroupName;
	stl_lowers( m_strGroupName );
	m_dwGroupNameKey = GenNameKey( m_strGroupName.c_str( ), m_strGroupName.length( ) );
}

CTextFileLoader::SGroupNode* CTextFileLoader::SGroupNode::New( )
{
	return ms_kPool.Alloc( );
}

void CTextFileLoader::SGroupNode::Delete( SGroupNode* pkNode )
{
	pkNode->m_kMap_dwKey_kVct_stToken.clear( );
	pkNode->ChildNodeVector.clear( );
	pkNode->m_strGroupName.clear( );
	pkNode->m_dwGroupNameKey = 0;
	ms_kPool.Free( pkNode );
}

void CTextFileLoader::SGroupNode::DestroySystem( )
{
	ms_kPool.Destroy( );
}

CTextFileLoader* CTextFileLoader::Cache( const char* c_szFileName )
{
	DWORD dwNameKey = GetCRC32( c_szFileName, strlen( c_szFileName ) );

	if ( auto f = ms_kMap_dwNameKey_pkTextFileLoader.find( dwNameKey ); f != ms_kMap_dwNameKey_pkTextFileLoader.end( ) )
	{
		if ( !ms_isCacheMode )
		{
			CTextFileLoader* pkNewTextFileLoader = new CTextFileLoader;

			if ( !pkNewTextFileLoader->Load( c_szFileName ) )
			{
				delete pkNewTextFileLoader;
				f->second->SetTop( );
				return f->second;
			}

			delete f->second;
			f->second = pkNewTextFileLoader;
		}

		f->second->SetTop( );
		return f->second;
	}

	CTextFileLoader* pkNewTextFileLoader = new CTextFileLoader;

	if ( !pkNewTextFileLoader->Load( c_szFileName ) )
	{
		delete pkNewTextFileLoader;
		return nullptr;
	}

	ms_kMap_dwNameKey_pkTextFileLoader.emplace( dwNameKey, pkNewTextFileLoader );
	return pkNewTextFileLoader;
}

void CTextFileLoader::SetCacheMode( )
{
	ms_isCacheMode = true;
}

void CTextFileLoader::DestroySystem( )
{
	for ( auto& pair : ms_kMap_dwNameKey_pkTextFileLoader )
		delete pair.second;

	ms_kMap_dwNameKey_pkTextFileLoader.clear( );
	SGroupNode::DestroySystem( );
}

void CTextFileLoader::Destroy( )
{
	__DestroyGroupNodeVector( );
	m_GlobalNode.m_kMap_dwKey_kVct_stToken.clear( );
	m_GlobalNode.ChildNodeVector.clear( );
}

CTextFileLoader::CTextFileLoader( )
{
	m_GlobalNode.m_strGroupName = "global";
	m_GlobalNode.pParentNode = nullptr;

	SetTop( );

	m_dwBufSize = 0;
	m_dwBufCapacity = 0;

	m_kVct_pkNode.reserve( 128 );
}

CTextFileLoader::~CTextFileLoader( )
{
	Destroy( );
}

void CTextFileLoader::__DestroyGroupNodeVector( )
{
	for ( auto* node : m_kVct_pkNode )
		SGroupNode::Delete( node );

	m_kVct_pkNode.clear( );
}

const char* CTextFileLoader::GetFileName( )
{
	return m_strFileName.c_str( );
}

bool CTextFileLoader::IsEmpty( )
{
	return m_strFileName.empty( );
}

bool CTextFileLoader::Load( const char* c_szFileName )
{
	__DestroyGroupNodeVector( );
	m_GlobalNode.m_kMap_dwKey_kVct_stToken.clear( );
	m_GlobalNode.ChildNodeVector.clear( );
	m_strFileName.clear( );

	CMappedFile kFile;
	LPCVOID pData = nullptr;

	if ( !CEterPackManager::Instance( ).Get( kFile, c_szFileName, &pData ) )
		return false;

	m_dwBufSize = kFile.Size( );

	if ( m_dwBufCapacity < m_dwBufSize )
	{
		m_dwBufCapacity = m_dwBufSize;
		m_acBufData = std::make_unique< char[] >( m_dwBufCapacity );
	}

	if ( m_dwBufSize > 0 && pData != nullptr )
	{
		memcpy( m_acBufData.get( ), pData, m_dwBufSize );
	}
	else
	{
		TraceError( "CTextFileLoader::Load: File %s found but empty", c_szFileName );
		return false;
	}

	m_strFileName = c_szFileName;
	m_dwcurLineIndex = 0;

	m_textFileLoader.Bind( m_dwBufSize, m_acBufData.get( ) );
	return LoadGroup( &m_GlobalNode );
}

bool CTextFileLoader::LoadGroup( TGroupNode* pGroupNode )
{
	std::vector< std::string_view > tokens;
	tokens.reserve( 32 );

	CTokenVector stTempValues;
	stTempValues.reserve( 32 );

	int nLocalGroupDepth = 0;
	DWORD lineCount = m_textFileLoader.GetLineCount( );

	for ( ; m_dwcurLineIndex < lineCount; ++m_dwcurLineIndex )
	{
		const std::string& lineStr = m_textFileLoader.GetLineString( m_dwcurLineIndex );

		if ( lineStr.empty( ) )
			continue;

		FastSplitLine( lineStr.c_str( ), lineStr.length( ), tokens );

		if ( tokens.empty( ) )
			continue;

		std::string_view keyToken = tokens[0];

		if ( keyToken.empty( ) )
			continue;

		if ( keyToken[0] == '{' )
		{
			nLocalGroupDepth++;
			continue;
		}

		if ( keyToken[0] == '}' )
		{
			nLocalGroupDepth--;
			break;
		}

		if ( IsEqualLower( keyToken, "group" ) )
		{
			if ( tokens.size( ) < 2 )
			{
				TraceError( "CTextFileLoader::LoadGroup: Missing group name in %s:%u", m_strFileName.c_str( ), m_dwcurLineIndex );
				continue;
			}

			TGroupNode* pNewNode = TGroupNode::New( );
			pNewNode->pParentNode = pGroupNode;
			pNewNode->SetGroupName( std::string( tokens[1] ) );

			++m_dwcurLineIndex;

			if ( !LoadGroup( pNewNode ) )
			{
				TGroupNode::Delete( pNewNode );
				return false;
			}

			m_kVct_pkNode.push_back( pNewNode );
			pGroupNode->ChildNodeVector.push_back( pNewNode );
		}
		else if ( IsEqualLower( keyToken, "list" ) )
		{
			if ( tokens.size( ) < 2 )
			{
				TraceError( "CTextFileLoader::LoadGroup: Missing list name in %s:%u", m_strFileName.c_str( ), m_dwcurLineIndex );
				continue;
			}

			std::string listKey( tokens[1] );
			stl_lowers( listKey );

			stTempValues.clear( );

			++m_dwcurLineIndex;

			for ( ; m_dwcurLineIndex < lineCount; ++m_dwcurLineIndex )
			{
				const std::string& subLineStr = m_textFileLoader.GetLineString( m_dwcurLineIndex );
				FastSplitLine( subLineStr.c_str( ), subLineStr.length( ), tokens );

				if ( tokens.empty( ) )
					continue;

				char firstChar = tokens[0][0];

				if ( firstChar == '{' )
					continue;

				if ( firstChar == '}' )
					break;

				for ( auto& sv : tokens )
					stTempValues.emplace_back( sv );
			}

			pGroupNode->InsertTokenVector( listKey, stTempValues );
		}
		else
		{
			if ( tokens.size( ) < 2 )
				continue;

			stTempValues.clear( );

			for ( size_t i = 1; i < tokens.size( ); ++i )
				stTempValues.emplace_back( tokens[i] );

			std::string keyStr( keyToken );
			stl_lowers( keyStr );

			pGroupNode->InsertTokenVector( keyStr, stTempValues );
		}
	}

	return ( nLocalGroupDepth == 0 );
}

BOOL CTextFileLoader::SetChildNode( const std::string& c_rstrKeyHead, DWORD dwIndex )
{
	char szKey[64];
	_snprintf( szKey, sizeof( szKey ), "%s%02u", c_rstrKeyHead.c_str( ), dwIndex );

	return SetChildNode( szKey );
}

BOOL CTextFileLoader::GetTokenBoolean( const char* c_szKey, BOOL* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	int val;

	if ( SafeParseInt( pTokenVector->at( 0 ), &val ) )
	{
		*pData = ( val != 0 );
		return TRUE;
	}

	return FALSE;
}

BOOL CTextFileLoader::GetTokenByte( const char* c_szKey, BYTE* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	int val;

	if ( SafeParseInt( pTokenVector->at( 0 ), &val ) )
	{
		*pData = ( BYTE )val;
		return TRUE;
	}

	return FALSE;
}

BOOL CTextFileLoader::GetTokenWord( const char* c_szKey, WORD* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	int val;

	if ( SafeParseInt( pTokenVector->at( 0 ), &val ) )
	{
		*pData = ( WORD )val;
		return TRUE;
	}

	return FALSE;
}

BOOL CTextFileLoader::GetTokenInteger( const char* c_szKey, int* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	return SafeParseInt( pTokenVector->at( 0 ), pData );
}

BOOL CTextFileLoader::GetTokenDoubleWord( const char* c_szKey, DWORD* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	int val;

	if ( SafeParseInt( pTokenVector->at( 0 ), &val ) )
	{
		*pData = ( DWORD )val;
		return TRUE;
	}

	return FALSE;
}

BOOL CTextFileLoader::GetTokenFloat( const char* c_szKey, float* pData )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	return SafeParseFloat( pTokenVector->at( 0 ), pData );
}

BOOL CTextFileLoader::GetTokenBoolean( const std::string& c_rstrKey, BOOL* pData )
{
	return GetTokenBoolean( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenByte( const std::string& c_rstrKey, BYTE* pData )
{
	return GetTokenByte( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenWord( const std::string& c_rstrKey, WORD* pData )
{
	return GetTokenWord( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenInteger( const std::string& c_rstrKey, int* pData )
{
	return GetTokenInteger( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenDoubleWord( const std::string& c_rstrKey, DWORD* pData )
{
	return GetTokenDoubleWord( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenFloat( const std::string& c_rstrKey, float* pData )
{
	return GetTokenFloat( c_rstrKey.c_str( ), pData );
}

BOOL CTextFileLoader::GetTokenVector2( const char* c_szKey, D3DXVECTOR2* pVector2 )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 2 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pVector2->x ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pVector2->y ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenVector3( const char* c_szKey, D3DXVECTOR3* pVector3 )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 3 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pVector3->x ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pVector3->y ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pVector3->z ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenVector4( const char* c_szKey, D3DXVECTOR4* pVector4 )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 4 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pVector4->x ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pVector4->y ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pVector4->z ) ||
	        !SafeParseFloat( pTokenVector->at( 3 ), &pVector4->w ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenPosition( const char* c_szKey, D3DXVECTOR3* pVector )
{
	return GetTokenVector3( c_szKey, pVector );
}

BOOL CTextFileLoader::GetTokenQuaternion( const char* c_szKey, D3DXQUATERNION* pQ )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 4 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pQ->x ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pQ->y ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pQ->z ) ||
	        !SafeParseFloat( pTokenVector->at( 3 ), &pQ->w ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenDirection( const char* c_szKey, D3DVECTOR* pVector )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 3 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pVector->x ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pVector->y ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pVector->z ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenColor( const char* c_szKey, D3DXCOLOR* pColor )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 4 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pColor->r ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pColor->g ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pColor->b ) ||
	        !SafeParseFloat( pTokenVector->at( 3 ), &pColor->a ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenColor( const char* c_szKey, D3DCOLORVALUE* pColor )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->size( ) != 4 )
		return FALSE;

	if ( !SafeParseFloat( pTokenVector->at( 0 ), &pColor->r ) ||
	        !SafeParseFloat( pTokenVector->at( 1 ), &pColor->g ) ||
	        !SafeParseFloat( pTokenVector->at( 2 ), &pColor->b ) ||
	        !SafeParseFloat( pTokenVector->at( 3 ), &pColor->a ) )
		return FALSE;

	return TRUE;
}

BOOL CTextFileLoader::GetTokenString( const char* c_szKey, std::string* pString )
{
	CTokenVector* pTokenVector;

	if ( !GetTokenVector( c_szKey, &pTokenVector ) )
		return FALSE;

	if ( pTokenVector->empty( ) )
		return FALSE;

	*pString = pTokenVector->at( 0 );
	return TRUE;
}
// KoMaR1911 Recode contact: discord komar1911



//credits  @ martysama0134 - based on his source

  • Metin2 Dev 5
  • Scream 1
  • Good 5
  • muscle 1

spacer.png

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.