mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-05-03 01:07:47 +00:00
Merge remote-tracking branch 'upstream/SQL_REWRITE_OWN' into SQL_REWRITE_OWN
This commit is contained in:
commit
70668727df
27 changed files with 330 additions and 794 deletions
63
CONTRIBUTING.md
Normal file
63
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Contributing
|
||||
|
||||
Thanks for contributing to Sapphire!
|
||||
|
||||
First, we'd like to mention that a lot of discussion regarding the project happens in our Discord server.
|
||||
We value research and discussion as to how we should tackle our issues as well as improving what is already in.
|
||||
Of course we also value testing - many things tend to break due to patches, or mistakes/edge cases.
|
||||
|
||||
Regardless of how you plan on contributing, your thoughts are appreciated and you're welcome to join our Discord (link in README.md).
|
||||
|
||||
## Research
|
||||
|
||||
Care in implementating features should be taken. It tends to be end up weird, and replicating the expected behavior
|
||||
is always preferred. Avoid assumptions and guesswork whenever possible.
|
||||
|
||||
As much research possible should be done before writing it out - on game data, testing with retail,
|
||||
and even common practices in server development (emulators or not).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
When making a PR, please make sure that it follows our style guidelines and good practices.
|
||||
|
||||
### Coding style
|
||||
|
||||
Indentations are Allman-style based, 4-space, no tabs.
|
||||
Space between arguments in function calls, as well as for types.
|
||||
|
||||
Example (shortened from ActionHandler.cpp):
|
||||
|
||||
```cpp
|
||||
switch( commandId )
|
||||
{
|
||||
case 0x01: // Toggle sheathe
|
||||
{
|
||||
if ( param11 == 1 )
|
||||
pPlayer->setStance( Entity::Actor::Stance::Active );
|
||||
else
|
||||
{
|
||||
pPlayer->setStance( Entity::Actor::Stance::Passive );
|
||||
pPlayer->setAutoattack( false );
|
||||
}
|
||||
|
||||
pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), 0, param11, 1 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x03: // Change target
|
||||
{
|
||||
uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 );
|
||||
pPlayer->changeTarget( targetId );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Feature implementation
|
||||
|
||||
Please make sure edge cases have been tested, behavior is aligned with retail and (if applicable) your queries make sense.
|
||||
Any changes to the SQL base should be noted (and reflected in the update.sql file in rootDirectory/sql).
|
|
@ -1,379 +0,0 @@
|
|||
#include "Database.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
#include "src/servers/Server_Common/Logging/Logger.h"
|
||||
|
||||
extern Core::Logger g_log;
|
||||
|
||||
namespace Core {
|
||||
namespace Db {
|
||||
|
||||
QueryResult::QueryResult( MYSQL_RES *res, uint32_t fields, uint32_t rows )
|
||||
: m_result( res ),
|
||||
m_fieldCount( fields ),
|
||||
m_rowCount( rows )
|
||||
{
|
||||
m_currentRow = new Field[fields];
|
||||
}
|
||||
|
||||
QueryResult::~QueryResult()
|
||||
{
|
||||
mysql_free_result( m_result );
|
||||
delete[] m_currentRow;
|
||||
}
|
||||
|
||||
bool QueryResult::nextRow()
|
||||
{
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row( m_result );
|
||||
auto length = mysql_fetch_lengths( m_result );
|
||||
if( row == nullptr )
|
||||
return false;
|
||||
|
||||
for( uint32_t i = 0; i < m_fieldCount; ++i )
|
||||
{
|
||||
m_currentRow[i].setValue( row[i] );
|
||||
m_currentRow[i].setLength( 0 );
|
||||
if( length )
|
||||
m_currentRow[i].setLength( length[i] );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Field *QueryResult::fetch()
|
||||
{
|
||||
return m_currentRow;
|
||||
}
|
||||
|
||||
uint32_t QueryResult::getFieldCount() const
|
||||
{
|
||||
return m_fieldCount;
|
||||
}
|
||||
|
||||
uint32_t QueryResult::getRowCount() const
|
||||
{
|
||||
return m_rowCount;
|
||||
}
|
||||
|
||||
Database::Database()
|
||||
{
|
||||
m_port = 0;
|
||||
m_counter = 0;
|
||||
m_pConnections = nullptr;
|
||||
m_connectionCount = -1; // Not connected.
|
||||
}
|
||||
|
||||
Database::~Database()
|
||||
{
|
||||
for( int32_t i = 0; i < m_connectionCount; ++i )
|
||||
{
|
||||
if( m_pConnections[i].conn != nullptr )
|
||||
mysql_close( m_pConnections[i].conn );
|
||||
}
|
||||
|
||||
delete[] m_pConnections;
|
||||
}
|
||||
|
||||
bool Database::initialize( const DatabaseParams& params )
|
||||
{
|
||||
uint32_t i;
|
||||
MYSQL * temp;
|
||||
MYSQL * temp2;
|
||||
my_bool my_true = true;
|
||||
|
||||
g_log.info( "Database: Connecting to " + params.hostname + ", database " + params.databaseName + "..." );
|
||||
|
||||
m_pConnections = new DatabaseConnection[params.connectionCount];
|
||||
for( i = 0; i < params.connectionCount; ++i )
|
||||
{
|
||||
temp = mysql_init( nullptr );
|
||||
if( mysql_options( temp, MYSQL_SET_CHARSET_NAME, "utf8" ) )
|
||||
g_log.error( "Database: Could not set utf8 character set." );
|
||||
|
||||
if( mysql_options( temp, MYSQL_OPT_RECONNECT, &my_true ) )
|
||||
g_log.error( "Database: MYSQL_OPT_RECONNECT could not be set, "
|
||||
"connection drops may occur but will be counteracted." );
|
||||
|
||||
temp2 = mysql_real_connect( temp,
|
||||
params.hostname.c_str(),
|
||||
params.username.c_str(),
|
||||
params.password.c_str(),
|
||||
params.databaseName.c_str(),
|
||||
params.port,
|
||||
nullptr,
|
||||
0 );
|
||||
if( temp2 == nullptr )
|
||||
{
|
||||
g_log.fatal( "Database: Connection failed due to: `%s`" + std::string( mysql_error( temp ) ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pConnections[i].conn = temp2;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t Database::getNextUId()
|
||||
{
|
||||
execute( std::string( "INSERT INTO uniqueiddata( IdName ) VALUES( 'NOT_SET' );" ) );
|
||||
auto res = query( "SELECT LAST_INSERT_ID();" );
|
||||
|
||||
if( !res )
|
||||
return 0;
|
||||
|
||||
Db::Field *field = res->fetch();
|
||||
|
||||
return field[0].get< uint64_t >();
|
||||
}
|
||||
|
||||
DatabaseConnection * Database::getFreeConnection()
|
||||
{
|
||||
uint32_t i = 0;
|
||||
while( true )
|
||||
{
|
||||
DatabaseConnection * con = &m_pConnections[( ( i++ ) % m_connectionCount )];
|
||||
if( con->lock.try_lock() )
|
||||
return con;
|
||||
|
||||
// sleep every 20 iterations, otherwise this can cause 100% cpu if the db link goes dead
|
||||
if( !( i % 20 ) )
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr< QueryResult > Database::query( const std::string& QueryString )
|
||||
{
|
||||
// Send the query
|
||||
boost::shared_ptr< QueryResult > qResult( nullptr );
|
||||
DatabaseConnection * con = getFreeConnection();
|
||||
|
||||
if( sendQuery( con, QueryString.c_str(), false ) )
|
||||
qResult = boost::shared_ptr< QueryResult >( storeQueryResult( con ) );
|
||||
|
||||
con->lock.unlock();
|
||||
return qResult;
|
||||
}
|
||||
|
||||
|
||||
bool Database::execute( const std::string& QueryString )
|
||||
{
|
||||
DatabaseConnection * con = getFreeConnection();
|
||||
bool Result = sendQuery( con, QueryString, false );
|
||||
con->lock.unlock();
|
||||
return Result;
|
||||
}
|
||||
|
||||
void Database::freeQueryResult( QueryResult * p )
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
std::string Database::escapeString( std::string Escape )
|
||||
{
|
||||
char a2[16384] = { 0 };
|
||||
|
||||
DatabaseConnection * con = getFreeConnection();
|
||||
const char * ret;
|
||||
if( mysql_real_escape_string( con->conn, a2, Escape.c_str(), ( uint32_t ) Escape.length() ) == 0 )
|
||||
ret = Escape.c_str();
|
||||
else
|
||||
ret = a2;
|
||||
|
||||
con->lock.unlock();
|
||||
return std::string( ret );
|
||||
}
|
||||
|
||||
void Database::escapeLongString( const char * str, uint32_t len, std::stringstream& out )
|
||||
{
|
||||
char a2[65536 * 3] = { 0 };
|
||||
|
||||
DatabaseConnection * con = getFreeConnection();
|
||||
mysql_real_escape_string( con->conn, a2, str, ( uint32_t ) len );
|
||||
|
||||
out.write( a2, ( std::streamsize )strlen( a2 ) );
|
||||
con->lock.unlock();
|
||||
}
|
||||
|
||||
std::string Database::escapeString( const char * esc, DatabaseConnection * con )
|
||||
{
|
||||
char a2[16384] = { 0 };
|
||||
const char * ret;
|
||||
if( mysql_real_escape_string( con->conn, a2, ( char* ) esc, ( uint32_t ) strlen( esc ) ) == 0 )
|
||||
ret = esc;
|
||||
else
|
||||
ret = a2;
|
||||
|
||||
return std::string( ret );
|
||||
}
|
||||
|
||||
bool Database::sendQuery( DatabaseConnection *con, const std::string &sql, bool Self )
|
||||
{
|
||||
int32_t result = mysql_query( con->conn, sql.c_str() );
|
||||
if( result > 0 )
|
||||
{
|
||||
if( Self == false && handleError( con, mysql_errno( con->conn ) ) )
|
||||
{
|
||||
// Re-send the query, the connection was successful.
|
||||
// The true on the end will prevent an endless loop here, as it will
|
||||
// stop after sending the query twice.
|
||||
result = sendQuery(con, sql, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log.error( "Database: query failed " + std::string( mysql_error( con->conn ) ) );
|
||||
g_log.error( "\t" + std::string( sql ) );
|
||||
}
|
||||
}
|
||||
|
||||
return ( result == 0 ? true : false );
|
||||
}
|
||||
|
||||
bool Database::handleError( DatabaseConnection *con, uint32_t ErrorNumber )
|
||||
{
|
||||
// Handle errors that should cause a reconnect to the CDatabase.
|
||||
switch( ErrorNumber ) {
|
||||
case 2006: // Mysql server has gone away
|
||||
case 2008: // Client ran out of memory
|
||||
case 2013: // Lost connection to sql server during query
|
||||
case 2055: // Lost connection to sql server - system error
|
||||
{
|
||||
// Let's instruct a reconnect to the db when we encounter these errors.
|
||||
return reconnect( con );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QueryResult * Database::storeQueryResult( DatabaseConnection * con )
|
||||
{
|
||||
QueryResult* res;
|
||||
MYSQL_RES* pRes = mysql_store_result( con->conn );
|
||||
auto uRows = mysql_affected_rows( con->conn );
|
||||
auto uFields = mysql_field_count( con->conn );
|
||||
|
||||
if( uRows == 0 || uFields == 0 || pRes == 0 )
|
||||
{
|
||||
if( pRes != nullptr )
|
||||
mysql_free_result( pRes );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
res = new QueryResult( pRes,
|
||||
static_cast< uint32_t >( uFields ),
|
||||
static_cast< uint32_t >( uRows ) );
|
||||
res->nextRow();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Database::reconnect( DatabaseConnection * conn )
|
||||
{
|
||||
MYSQL * temp;
|
||||
MYSQL * temp2;
|
||||
|
||||
temp = mysql_init( nullptr );
|
||||
|
||||
temp2 = mysql_real_connect( temp,
|
||||
m_hostname.c_str(),
|
||||
m_username.c_str(),
|
||||
m_password.c_str(),
|
||||
m_databaseName.c_str(),
|
||||
m_port,
|
||||
nullptr,
|
||||
0 );
|
||||
if( temp2 == nullptr )
|
||||
{
|
||||
g_log.error( "Database: Could not reconnect to database -> " + std::string( mysql_error( temp ) ) );
|
||||
mysql_close( temp );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( conn->conn != nullptr )
|
||||
mysql_close( conn->conn );
|
||||
|
||||
conn->conn = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Database::cleanupLibs()
|
||||
{
|
||||
mysql_library_end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Database::shutdown()
|
||||
{
|
||||
for( int32_t i = 0; i < m_connectionCount; ++i )
|
||||
{
|
||||
if( m_pConnections[i].conn != nullptr )
|
||||
{
|
||||
mysql_close( m_pConnections[i].conn );
|
||||
m_pConnections[i].conn = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &Database::getHostName()
|
||||
{
|
||||
return m_hostname;
|
||||
}
|
||||
|
||||
const std::string &Database::getDatabaseName()
|
||||
{
|
||||
return m_databaseName;
|
||||
}
|
||||
|
||||
void Field::setValue( char *value )
|
||||
{
|
||||
m_pValue = value;
|
||||
}
|
||||
|
||||
void Field::setLength( uint32_t value )
|
||||
{
|
||||
m_size = value;
|
||||
}
|
||||
|
||||
std::string Field::getString() const
|
||||
{
|
||||
if( !m_pValue )
|
||||
return "";
|
||||
return std::string( m_pValue );
|
||||
}
|
||||
|
||||
void Field::getBinary( char *dstBuf, uint16_t size ) const
|
||||
{
|
||||
if( m_pValue )
|
||||
memcpy( dstBuf, m_pValue, size );
|
||||
else
|
||||
dstBuf = nullptr;
|
||||
}
|
||||
|
||||
float Field::getFloat() const
|
||||
{
|
||||
return m_pValue ? static_cast< float >( atof( m_pValue ) ) : 0;
|
||||
}
|
||||
|
||||
bool Field::getBool() const
|
||||
{
|
||||
return m_pValue ? atoi( m_pValue ) > 0 : false;
|
||||
}
|
||||
|
||||
uint32_t Field::getLength() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
#ifndef _DATABASE_H
|
||||
#define _DATABASE_H
|
||||
|
||||
#include <mutex>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string.h>
|
||||
|
||||
namespace Core {
|
||||
namespace Db {
|
||||
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
|
||||
// set value
|
||||
void setValue( char* value );
|
||||
void setLength( uint32_t value );
|
||||
|
||||
std::string getString() const;
|
||||
void getBinary( char* dstBuf, uint16_t size ) const;
|
||||
float getFloat() const;
|
||||
bool getBool() const;
|
||||
|
||||
template< class T >
|
||||
__inline T get() const
|
||||
{
|
||||
if( !m_pValue )
|
||||
return 0;
|
||||
|
||||
return static_cast< T >( atol( m_pValue ) );
|
||||
}
|
||||
|
||||
uint64_t getUInt64()
|
||||
{
|
||||
if( m_pValue )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
uint64_t value;
|
||||
sscanf( m_pValue, "%I64d", &value );
|
||||
return value;
|
||||
#else
|
||||
uint64_t value;
|
||||
sscanf( m_pValue, "%Lu", &value );
|
||||
return value;
|
||||
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t getLength() const;
|
||||
|
||||
private:
|
||||
char *m_pValue;
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
|
||||
class QueryResult
|
||||
{
|
||||
public:
|
||||
QueryResult( MYSQL_RES *res, uint32_t fields, uint32_t rows );
|
||||
~QueryResult();
|
||||
|
||||
bool nextRow();
|
||||
|
||||
Field* fetch();
|
||||
uint32_t getFieldCount() const;
|
||||
uint32_t getRowCount() const;
|
||||
|
||||
protected:
|
||||
uint32_t m_fieldCount;
|
||||
uint32_t m_rowCount;
|
||||
Field *m_currentRow;
|
||||
MYSQL_RES *m_result;
|
||||
};
|
||||
|
||||
struct DatabaseConnection
|
||||
{
|
||||
std::mutex lock;
|
||||
MYSQL *conn;
|
||||
};
|
||||
|
||||
struct DatabaseParams
|
||||
{
|
||||
std::string hostname;
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string databaseName;
|
||||
uint16_t port;
|
||||
uint32_t bufferSize;
|
||||
uint32_t connectionCount;
|
||||
};
|
||||
|
||||
class Database
|
||||
{
|
||||
public:
|
||||
Database();
|
||||
virtual ~Database();
|
||||
|
||||
bool initialize( const DatabaseParams& params );
|
||||
|
||||
void shutdown();
|
||||
|
||||
boost::shared_ptr< QueryResult > query( const std::string& QueryString );
|
||||
bool waitExecuteNA( const char* QueryString );//Wait For Request Completion
|
||||
bool execute( const char* QueryString, ... );
|
||||
bool execute( const std::string& QueryString );
|
||||
|
||||
const std::string& getHostName();
|
||||
|
||||
const std::string& getDatabaseName();
|
||||
|
||||
std::string escapeString( std::string Escape );
|
||||
void escapeLongString( const char * str, uint32_t len, std::stringstream& out );
|
||||
std::string escapeString( const char * esc, DatabaseConnection *con );
|
||||
|
||||
void freeQueryResult( QueryResult * p );
|
||||
|
||||
DatabaseConnection *getFreeConnection();
|
||||
|
||||
void cleanupLibs();
|
||||
|
||||
/* database is killed off manually. */
|
||||
void onShutdown() {}
|
||||
|
||||
uint64_t getNextUId();
|
||||
|
||||
protected:
|
||||
|
||||
// actual query function
|
||||
bool sendQuery( DatabaseConnection *con, const std::string &sql, bool Self );
|
||||
QueryResult * storeQueryResult( DatabaseConnection * con );
|
||||
bool handleError( DatabaseConnection *conn, uint32_t ErrorNumber );
|
||||
bool reconnect( DatabaseConnection *conn );
|
||||
|
||||
DatabaseConnection *m_pConnections;
|
||||
|
||||
uint32_t m_counter;
|
||||
///////////////////////////////
|
||||
|
||||
int32_t m_connectionCount;
|
||||
|
||||
// For reconnecting a broken connection
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
std::string m_databaseName;
|
||||
uint32_t m_port;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -136,6 +136,7 @@ namespace Packets {
|
|||
IPCTYPE_UNK_320 = 0x0207, // updated 4.1
|
||||
IPCTYPE_UNK_322 = 0x0209, // updated 4.1
|
||||
|
||||
ActorGauge = 0x249
|
||||
PerformNote = 0x0252,
|
||||
};
|
||||
|
||||
|
|
|
@ -731,16 +731,16 @@ struct FFXIVIpcInitUI : FFXIVIpcBasePacket<InitUI>
|
|||
uint8_t preNamePadding;
|
||||
char name[32];
|
||||
uint8_t unknown_54[16];
|
||||
uint8_t unknown55;
|
||||
uint8_t unknown55[4];
|
||||
uint16_t levels[25];
|
||||
uint32_t exp[25];
|
||||
uint8_t unlockBitmask[64];
|
||||
uint8_t aetheryte[16];
|
||||
uint8_t discovery[420];
|
||||
uint8_t howto[33];
|
||||
uint8_t minions[33];
|
||||
uint8_t minions[35];
|
||||
uint8_t chocoboTaxiMask[8];
|
||||
uint8_t contentClearMask[104];
|
||||
uint8_t contentClearMask[105];
|
||||
uint8_t companionBardingMask[8];
|
||||
uint8_t companionEquippedHead;
|
||||
uint8_t companionEquippedBody;
|
||||
|
@ -1314,6 +1314,12 @@ struct FFXIVIpcMount : FFXIVIpcBasePacket<Mount>
|
|||
};
|
||||
|
||||
|
||||
struct FFXIVIpcActorGauge : FFXIVIpcBasePacket<ActorGauge>
|
||||
{
|
||||
uint8_t classJobId;
|
||||
uint8_t data[15]; // depends on classJobId
|
||||
};
|
||||
|
||||
struct FFXIVIpcPerformNote : FFXIVIpcBasePacket<PerformNote>
|
||||
{
|
||||
uint8_t data[32];
|
||||
|
|
|
@ -18,6 +18,7 @@ set_target_properties(server_lobby PROPERTIES
|
|||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
|
|
|
@ -139,7 +139,7 @@ void Core::Network::GameConnection::getCharList( FFXIVARR_PACKET_RAW& packet, ui
|
|||
serverListPacket.data().server[0].id = g_serverLobby.getConfig()->getValue<uint16_t>( "Settings.Parameters.WorldID", 1 );
|
||||
serverListPacket.data().server[0].index = 0;
|
||||
serverListPacket.data().final = 1;
|
||||
sprintf( serverListPacket.data().server[0].name, g_serverLobby.getConfig()->getValue< std::string >( "Settings.Parameters.WorldName", "Sapphire" ).c_str() );
|
||||
strcpy( serverListPacket.data().server[0].name, g_serverLobby.getConfig()->getValue< std::string >( "Settings.Parameters.WorldName", "Sapphire" ).c_str() );
|
||||
|
||||
pRP.addPacket( serverListPacket );
|
||||
|
||||
|
|
|
@ -17,12 +17,17 @@ set_target_properties(server_rest PROPERTIES
|
|||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries (server_rest Common xivdat pthread mysqlclient mysqlConnector dl z)
|
||||
else()
|
||||
# ignore unchecked iterators warnings from msvc
|
||||
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
||||
|
||||
target_link_libraries (server_rest Common xivdat libmysql mysqlConnector zlib1)
|
||||
|
||||
endif()
|
||||
|
||||
target_link_libraries( server_rest ${Boost_LIBRARIES} ${Boost_LIBRARIES} )
|
||||
|
|
|
@ -345,8 +345,8 @@ namespace Core {
|
|||
|
||||
void PlayerMinimal::insertDbGlobalItem( uint32_t weaponId, uint64_t uniqueId ) const
|
||||
{
|
||||
auto stmtItemGlobal = g_charaDb.getPreparedStatement(Db::CHARA_ITEMGLOBAL_INS );
|
||||
stmtItemGlobal->setInt(1, m_id);
|
||||
auto stmtItemGlobal = g_charaDb.getPreparedStatement( Db::CHARA_ITEMGLOBAL_INS );
|
||||
stmtItemGlobal->setInt( 1, m_id );
|
||||
stmtItemGlobal->setInt64( 2, uniqueId );
|
||||
stmtItemGlobal->setInt( 3, weaponId );
|
||||
g_charaDb.directExecute( stmtItemGlobal );
|
||||
|
@ -362,10 +362,10 @@ namespace Core {
|
|||
|
||||
uint64_t PlayerMinimal::getNextUId64() const
|
||||
{
|
||||
g_charaDb.execute( std::string( "INSERT INTO uniqueiddata( IdName ) VALUES( 'NOT_SET' );" ) );
|
||||
g_charaDb.directExecute( std::string( "INSERT INTO uniqueiddata( IdName ) VALUES( 'NOT_SET' );" ) );
|
||||
auto res = g_charaDb.query( "SELECT LAST_INSERT_ID();" );
|
||||
|
||||
if( !res )
|
||||
if( !res->next() )
|
||||
return 0;
|
||||
|
||||
return res->getUInt64( 1 );
|
||||
|
|
|
@ -88,7 +88,7 @@ bool Core::Network::SapphireAPI::createAccount( const std::string& username, con
|
|||
// get account from login name
|
||||
auto pQR = g_charaDb.query( "SELECT account_id FROM accounts WHERE account_name = '" + username + "';" );
|
||||
// found?
|
||||
if( !pQR->next() )
|
||||
if( pQR->next() )
|
||||
return false;
|
||||
|
||||
// we are clear and can create a new account
|
||||
|
@ -99,7 +99,7 @@ bool Core::Network::SapphireAPI::createAccount( const std::string& username, con
|
|||
uint32_t accountId = pQR->getUInt( 1 ) + 1;
|
||||
|
||||
// store the account to the db
|
||||
g_charaDb.execute( "INSERT INTO accounts (account_Id, account_name, account_pass, account_created) VALUE( " +
|
||||
g_charaDb.directExecute( "INSERT INTO accounts (account_Id, account_name, account_pass, account_created) VALUE( " +
|
||||
std::to_string( accountId ) + ", '" +
|
||||
username + "', '" +
|
||||
pass + "', " +
|
||||
|
|
|
@ -70,7 +70,8 @@ Core::Entity::Player::Player() :
|
|||
m_bLoadingComplete( false ),
|
||||
m_bMarkedForZoning( false ),
|
||||
m_zoningType( Common::ZoneingType::None ),
|
||||
m_bAutoattack( false )
|
||||
m_bAutoattack( false ),
|
||||
m_markedForRemoval( false )
|
||||
{
|
||||
m_id = 0;
|
||||
m_type = ActorType::Player;
|
||||
|
@ -90,7 +91,7 @@ Core::Entity::Player::Player() :
|
|||
|
||||
Core::Entity::Player::~Player()
|
||||
{
|
||||
|
||||
g_log.debug( "PlayerObj destroyed" );
|
||||
}
|
||||
|
||||
// TODO: add a proper calculation based on race / job / level / gear
|
||||
|
@ -134,6 +135,16 @@ uint8_t Core::Entity::Player::getStartTown() const
|
|||
return m_startTown;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::setMarkedForRemoval()
|
||||
{
|
||||
m_markedForRemoval = true;
|
||||
}
|
||||
|
||||
bool Core::Entity::Player::isMarkedForRemoval() const
|
||||
{
|
||||
return m_markedForRemoval;
|
||||
}
|
||||
|
||||
Core::Common::OnlineStatus Core::Entity::Player::getOnlineStatus()
|
||||
{
|
||||
uint64_t newMask = uint64_t( 1 ) << static_cast< uint32_t >( OnlineStatus::NewAdventurer );
|
||||
|
@ -899,7 +910,6 @@ uint32_t Core::Entity::Player::getLastPing() const
|
|||
return m_lastPing;
|
||||
}
|
||||
|
||||
|
||||
void Core::Entity::Player::setVoiceId( uint8_t voiceId )
|
||||
{
|
||||
m_voice = voiceId;
|
||||
|
@ -1396,7 +1406,7 @@ uint8_t * Core::Entity::Player::getTitleList()
|
|||
|
||||
uint16_t Core::Entity::Player::getTitle() const
|
||||
{
|
||||
return m_title;
|
||||
return m_activeTitle;
|
||||
}
|
||||
|
||||
void Core::Entity::Player::addTitle( uint16_t titleId )
|
||||
|
@ -1417,7 +1427,7 @@ void Core::Entity::Player::setTitle( uint16_t titleId )
|
|||
if ( ( m_titleList[index] & value ) == 0 ) // Player doesn't have title - bail
|
||||
return;
|
||||
|
||||
m_title = titleId;
|
||||
m_activeTitle = titleId;
|
||||
|
||||
sendToInRangeSet( ActorControlPacket142( getId(), SetTitle, titleId ), true );
|
||||
}
|
||||
|
|
|
@ -530,6 +530,9 @@ public:
|
|||
void updateDbSearchInfo() const;
|
||||
void updateDbClass() const;
|
||||
|
||||
void setMarkedForRemoval();
|
||||
bool isMarkedForRemoval() const;
|
||||
|
||||
private:
|
||||
uint32_t m_lastWrite;
|
||||
uint32_t m_lastPing;
|
||||
|
@ -540,6 +543,8 @@ private:
|
|||
|
||||
uint8_t m_mode;
|
||||
|
||||
bool m_markedForRemoval;
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_voice;
|
||||
|
@ -566,7 +571,7 @@ private:
|
|||
uint8_t status;
|
||||
} m_retainerInfo[8];
|
||||
|
||||
uint16_t m_title;
|
||||
uint16_t m_activeTitle;
|
||||
uint8_t m_titleList[48];
|
||||
uint8_t m_howTo[33];
|
||||
uint8_t m_minions[33];
|
||||
|
|
|
@ -81,15 +81,21 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|||
setRotation( 0.0f );
|
||||
}
|
||||
|
||||
// Stats
|
||||
|
||||
m_hp = res->getUInt( "Hp" );
|
||||
m_mp = res->getUInt( "Mp" );
|
||||
m_tp = 0;
|
||||
|
||||
// Position
|
||||
|
||||
m_pos.x = res->getFloat( "PosX" );
|
||||
m_pos.y = res->getFloat( "PosY" );
|
||||
m_pos.z = res->getFloat( "PosZ" );
|
||||
setRotation( res->getFloat( "PosR" ) );
|
||||
|
||||
// Model
|
||||
|
||||
auto custom = res->getBlobVector( "Customize" );
|
||||
memcpy( reinterpret_cast< char* >( m_customize ), custom.data(), custom.size() );
|
||||
|
||||
|
@ -98,6 +104,8 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|||
auto modelEq = res->getBlobVector( "ModelEquip" );
|
||||
memcpy( reinterpret_cast< char* >( m_modelEquip ), modelEq.data(), modelEq.size() );
|
||||
|
||||
// Minimal info
|
||||
|
||||
m_guardianDeity = res->getUInt8( "GuardianDeity" );
|
||||
m_birthDay = res->getUInt8( "BirthDay" );
|
||||
m_birthMonth = res->getUInt8( "BirthMonth" );
|
||||
|
@ -105,12 +113,27 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|||
m_class = static_cast< ClassJob >( res->getUInt( "Class" ) );
|
||||
m_homePoint = res->getUInt8( "Homepoint" );
|
||||
|
||||
auto howTo = res->getBlobVector( "HowTo" );
|
||||
memcpy( reinterpret_cast< char* >( m_howTo ), howTo.data(), howTo.size() );
|
||||
// Additional data
|
||||
|
||||
m_contentId = res->getUInt64( "ContentId" );
|
||||
|
||||
m_voice = res->getUInt8( "Voice" );
|
||||
m_startTown = res->getUInt8( "StartTown" );
|
||||
m_playTime = res->getUInt( "TotalPlayTime" );
|
||||
|
||||
m_bNewGame = res->getBoolean( "IsNewGame" );
|
||||
m_bNewAdventurer = res->getBoolean( "IsNewAdventurer" );
|
||||
m_openingSequence = res->getUInt8( "OpeningSequence" );
|
||||
|
||||
m_gc = res->getUInt8( "GrandCompany" );
|
||||
m_cfPenaltyUntil = res->getUInt( "CFPenaltyUntil" );
|
||||
m_activeTitle = res->getUInt16( "ActiveTitle" );
|
||||
|
||||
m_gmRank = res->getUInt8( "GMRank" );
|
||||
|
||||
// Blobs
|
||||
|
||||
auto howTo = res->getBlobVector( "HowTo" );
|
||||
memcpy( reinterpret_cast< char* >( m_howTo ), howTo.data(), howTo.size() );
|
||||
|
||||
auto questCompleteFlags = res->getBlobVector( "QuestCompleteFlags" );
|
||||
memcpy( reinterpret_cast< char* >( m_questCompleteFlags ), questCompleteFlags.data(), questCompleteFlags.size() );
|
||||
|
@ -118,8 +141,6 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|||
auto questTracking = res->getBlobVector( "QuestTracking" );
|
||||
memcpy( reinterpret_cast< char* >( m_questTracking ), questTracking.data(), questTracking.size() );
|
||||
|
||||
m_bNewGame = res->getBoolean( "IsNewGame" );
|
||||
|
||||
auto aetheryte = res->getBlobVector( "Aetheryte" );
|
||||
memcpy( reinterpret_cast< char* >( m_aetheryte ), aetheryte.data(), aetheryte.size() );
|
||||
|
||||
|
@ -129,21 +150,12 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
|
|||
auto discovery = res->getBlobVector( "Discovery" );
|
||||
memcpy( reinterpret_cast< char* >( m_discovery ), discovery.data(), discovery.size() );
|
||||
|
||||
m_startTown = res->getUInt8( "StartTown" );
|
||||
m_playTime = res->getUInt( "TotalPlayTime" );
|
||||
|
||||
m_bNewAdventurer = res->getBoolean( "IsNewAdventurer" );
|
||||
|
||||
m_gc = res->getUInt8( "GrandCompany" );
|
||||
auto titleList = res->getBlobVector( "TitleList" );
|
||||
memcpy( reinterpret_cast< char* >( m_titleList ), titleList.data(), titleList.size() );
|
||||
|
||||
auto gcRank = res->getBlobVector( "GrandCompanyRank" );
|
||||
memcpy( reinterpret_cast< char* >( m_gcRank ), gcRank.data(), gcRank.size() );
|
||||
|
||||
m_cfPenaltyUntil = res->getUInt( "CFPenaltyUntil" );
|
||||
|
||||
m_openingSequence = res->getUInt8( "OpeningSequence" );
|
||||
|
||||
m_gmRank = res->getUInt8( "GMRank" );
|
||||
|
||||
res->free();
|
||||
|
||||
m_pCell = nullptr;
|
||||
|
@ -338,7 +350,7 @@ void Core::Entity::Player::updateSql()
|
|||
stmt->setInt( 35, 0 ); // RestPoint
|
||||
stmt->setInt( 36, 0 ); // ActiveTitle
|
||||
|
||||
std::vector< uint8_t > titleListVec( 32 );
|
||||
std::vector< uint8_t > titleListVec( sizeof ( m_titleList ) );
|
||||
stmt->setBinary( 37, titleListVec );
|
||||
|
||||
std::vector< uint8_t > achievementVec( 16 );
|
||||
|
@ -402,6 +414,8 @@ void Core::Entity::Player::updateSql()
|
|||
////// Class
|
||||
updateDbClass();
|
||||
|
||||
memset( m_orchestrion, 0, sizeof( m_orchestrion ) );
|
||||
|
||||
}
|
||||
|
||||
void Core::Entity::Player::updateDbClass() const
|
||||
|
@ -484,6 +498,4 @@ void Core::Entity::Player::insertQuest( uint16_t questId, uint8_t index, uint8_t
|
|||
stmt->setInt( 11, 0 );
|
||||
stmt->setInt( 12, 0 );
|
||||
g_charaDb.execute( stmt );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -4,7 +4,21 @@ cmake_policy(SET CMP0014 OLD)
|
|||
|
||||
project(Sapphire_Zone)
|
||||
|
||||
file(GLOB SERVER_PUBLIC_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/* ${CMAKE_CURRENT_SOURCE_DIR}/Script/*)
|
||||
file(GLOB SERVER_PUBLIC_INCLUDE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
/*.h
|
||||
Actor/*.h
|
||||
Action/*.h
|
||||
DebugCommand/*.h
|
||||
Event/*.h
|
||||
Inventory/*.h
|
||||
Linkshell/*.h
|
||||
Network/*.h
|
||||
Network/Handlers/*.h
|
||||
Network/PacketWrappers/*.h
|
||||
Script/*.h
|
||||
StatusEffect/*.h
|
||||
Zone/*.h)
|
||||
|
||||
file(GLOB SERVER_SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.c*
|
||||
Actor/*.c*
|
||||
|
@ -33,6 +47,7 @@ set_target_properties(server_zone PROPERTIES
|
|||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../../bin/"
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
|
@ -41,4 +56,4 @@ else()
|
|||
target_link_libraries ( server_zone Common xivdat libmysql zlib1 mysqlConnector )
|
||||
endif()
|
||||
|
||||
target_link_libraries(server_zone ${Boost_LIBRARIES} ${Boost_LIBRARIES} )
|
||||
target_link_libraries(server_zone ${Boost_LIBRARIES} )
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include <Server_Common/Database/DatabaseDef.h>
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
extern Core::Scripting::ScriptManager g_scriptMgr;
|
||||
extern Core::Data::ExdData g_exdData;
|
||||
extern Core::Logger g_log;
|
||||
|
@ -256,7 +258,7 @@ void Core::DebugCommandHandler::set( char * data, Core::Entity::PlayerPtr pPlaye
|
|||
else if ( subCommand == "eorzeatime" )
|
||||
{
|
||||
uint64_t timestamp;
|
||||
sscanf( params.c_str(), "%llu", ×tamp );
|
||||
sscanf( params.c_str(), "%" SCNu64, ×tamp );
|
||||
|
||||
pPlayer->setEorzeaTimeOffset( timestamp );
|
||||
pPlayer->sendNotice( "Eorzea time offset: " + std::to_string( timestamp ) );
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#include "LinkshellMgr.h"
|
||||
#include <Server_Common/Database/Database.h>
|
||||
#include <Server_Common/Logging/Logger.h>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <servers/Server_Common/Database/DatabaseDef.h>
|
||||
|
||||
#include "Linkshell.h"
|
||||
|
||||
extern Core::Logger g_log;
|
||||
extern Core::Db::Database g_database;
|
||||
|
||||
Core::LinkshellMgr::LinkshellMgr()
|
||||
{
|
||||
|
@ -16,47 +15,47 @@ Core::LinkshellMgr::LinkshellMgr()
|
|||
bool Core::LinkshellMgr::loadLinkshells()
|
||||
{
|
||||
|
||||
auto res = g_database.query( "SELECT LinkshellId, MasterCharacterId, CharacterIdList, "
|
||||
"LinkshellName, LeaderIdList, InviteIdList "
|
||||
"FROM infolinkshell "
|
||||
"ORDER BY LinkshellId ASC;" );
|
||||
auto res = g_charaDb.query( "SELECT LinkshellId, MasterCharacterId, CharacterIdList, "
|
||||
"LinkshellName, LeaderIdList, InviteIdList "
|
||||
"FROM infolinkshell "
|
||||
"ORDER BY LinkshellId ASC;" );
|
||||
|
||||
// we do not really need linkshells to function...
|
||||
if( !res )
|
||||
return true;
|
||||
|
||||
Db::Field *field = res->fetch();
|
||||
|
||||
do
|
||||
while( res->next() )
|
||||
{
|
||||
uint64_t linkshellId = field[0].get< uint64_t >();
|
||||
uint32_t masterId = field[1].get< uint32_t >();
|
||||
std::string name = field[3].getString();
|
||||
uint64_t linkshellId = res->getUInt64( 1 );
|
||||
uint32_t masterId = res->getUInt( 2 );
|
||||
std::string name = res->getString( 4 );
|
||||
|
||||
auto func = []( std::set< uint64_t >& outList, Db::Field * pField )
|
||||
auto func = []( std::set< uint64_t >& outList, std::vector< char >& inData )
|
||||
{
|
||||
if( pField->getLength() )
|
||||
if( inData.size() )
|
||||
{
|
||||
std::vector< uint64_t > list( pField->getLength() / 8 );
|
||||
pField->getBinary( reinterpret_cast< char * >( &list[0] ), pField->getLength() );
|
||||
std::vector< uint64_t > list( inData.size() / 8 );
|
||||
outList.insert( list.begin(), list.end() );
|
||||
}
|
||||
};
|
||||
|
||||
std::set< uint64_t > members;
|
||||
func( members, &field[2] );
|
||||
std::vector< char > membersBin;
|
||||
membersBin = res->getBlobVector( 3 );
|
||||
func( members, membersBin );
|
||||
|
||||
std::set< uint64_t > leaders;
|
||||
func( members, &field[4] );
|
||||
std::vector< char > leadersBin;
|
||||
leadersBin = res->getBlobVector( 5 );
|
||||
func( members, leadersBin );
|
||||
|
||||
std::set< uint64_t > invites;
|
||||
func( members, &field[5] );
|
||||
std::vector< char > invitesBin;
|
||||
invitesBin = res->getBlobVector( 6 );
|
||||
func( members, invitesBin );
|
||||
|
||||
auto lsPtr = boost::make_shared< Linkshell >( linkshellId, name, masterId, members, leaders, invites );
|
||||
m_linkshellIdMap[linkshellId] = lsPtr;
|
||||
m_linkshellNameMap[name] = lsPtr;
|
||||
|
||||
} while( res->nextRow() );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -330,7 +330,11 @@ void Core::Network::GameConnection::injectPacket( const std::string& packetpath,
|
|||
fseek( fp, 0, SEEK_END );
|
||||
int32_t size = ftell( fp );
|
||||
rewind( fp );
|
||||
fread( packet, sizeof( char ), size, fp );
|
||||
if ( fread( packet, sizeof( char ), size, fp ) != size )
|
||||
{
|
||||
g_log.error( "Packet " + packetpath + " did not read full size: " + std::to_string( size ) );
|
||||
return;
|
||||
}
|
||||
fclose( fp );
|
||||
|
||||
// cycle through the packet entries and queue each one
|
||||
|
@ -389,8 +393,7 @@ void Core::Network::GameConnection::handlePackets( const Core::Network::Packets:
|
|||
}
|
||||
session = g_serverZone.getSession( playerId );
|
||||
}
|
||||
|
||||
if( !session->isValid() ) //TODO: Catch more things in lobby and send real errors
|
||||
else if( !session->isValid() || ( session->getPlayer() && session->getPlayer()->getLastPing() != 0 ) ) //TODO: Catch more things in lobby and send real errors
|
||||
{
|
||||
g_log.error( "[" + std::string(id) + "] Session INVALID, disconnecting" );
|
||||
Disconnect();
|
||||
|
|
|
@ -333,7 +333,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
|
|||
GamePacketNew< FFXIVIpcSetSearchInfo, ServerZoneIpcType > searchInfoPacket( targetPlayer->getId() );
|
||||
searchInfoPacket.data().onlineStatusFlags = param1;
|
||||
searchInfoPacket.data().selectRegion = targetPlayer->getSearchSelectRegion();
|
||||
sprintf( searchInfoPacket.data().searchMessage, targetPlayer->getSearchMessage() );
|
||||
strcpy( searchInfoPacket.data().searchMessage, targetPlayer->getSearchMessage() );
|
||||
targetPlayer->queuePacket( searchInfoPacket );
|
||||
|
||||
targetPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatusIcon,
|
||||
|
|
|
@ -84,7 +84,7 @@ void Core::Network::GameConnection::setSearchInfoHandler( const Packets::GamePac
|
|||
GamePacketNew< FFXIVIpcSetSearchInfo, ServerZoneIpcType > searchInfoPacket( pPlayer->getId() );
|
||||
searchInfoPacket.data().onlineStatusFlags = status;
|
||||
searchInfoPacket.data().selectRegion = pPlayer->getSearchSelectRegion();
|
||||
sprintf( searchInfoPacket.data().searchMessage, pPlayer->getSearchMessage() );
|
||||
strcpy( searchInfoPacket.data().searchMessage, pPlayer->getSearchMessage() );
|
||||
queueOutPacket( searchInfoPacket );
|
||||
|
||||
pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatusIcon,
|
||||
|
@ -98,7 +98,7 @@ void Core::Network::GameConnection::reqSearchInfoHandler( const Packets::GamePac
|
|||
GamePacketNew< FFXIVIpcInitSearchInfo, ServerZoneIpcType > searchInfoPacket( pPlayer->getId() );
|
||||
searchInfoPacket.data().onlineStatusFlags = pPlayer->getOnlineStatusMask();
|
||||
searchInfoPacket.data().selectRegion = pPlayer->getSearchSelectRegion();
|
||||
sprintf( searchInfoPacket.data().searchMessage, pPlayer->getSearchMessage() );
|
||||
strcpy( searchInfoPacket.data().searchMessage, pPlayer->getSearchMessage() );
|
||||
queueOutPacket( searchInfoPacket );
|
||||
}
|
||||
|
||||
|
@ -540,6 +540,8 @@ void Core::Network::GameConnection::logoutHandler( const Packets::GamePacket& in
|
|||
logoutPacket.data().flags1 = 0x02;
|
||||
logoutPacket.data().flags2 = 0x2000;
|
||||
queueOutPacket( logoutPacket );
|
||||
|
||||
pPlayer->setMarkedForRemoval();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ private:
|
|||
|
||||
memset( &m_data.name[0], 0, sizeof( m_data.name ) );
|
||||
|
||||
sprintf( &m_data.name[0], player->getName().c_str() );
|
||||
strcpy( &m_data.name[0], player->getName().c_str() );
|
||||
|
||||
memcpy( m_data.aetheryte, player->getAetheryteArray(), sizeof ( m_data.aetheryte ) );
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <src/servers/Server_Common/Logging/Logger.h>
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
|
||||
#include <src/servers/Server_Common/Script/ChaiscriptStdLib.h>
|
||||
#include <Server_Common/Logging/Logger.h>
|
||||
#include <Server_Common/Script/ChaiscriptStdLib.h>
|
||||
|
||||
#include "src/servers/Server_Zone/Script/ScriptManager.h"
|
||||
|
||||
|
@ -15,11 +15,6 @@
|
|||
#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
||||
extern Core::Logger g_log;
|
||||
|
||||
|
|
|
@ -1,35 +1,29 @@
|
|||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "ServerZone.h"
|
||||
|
||||
#include <src/servers/Server_Common/Version.h>
|
||||
#include <src/servers/Server_Common/Logging/Logger.h>
|
||||
#include <src/servers/Server_Common/Config/XMLConfig.h>
|
||||
#include <src/servers/Server_Common/Database/Database.h>
|
||||
#include <src/servers/Server_Common/Version.h>
|
||||
|
||||
#include <MySqlBase.h>
|
||||
#include <Connection.h>
|
||||
#include <Statement.h>
|
||||
#include <ResultSet.h>
|
||||
#include <PreparedStatement.h>
|
||||
#include <PreparedResultSet.h>
|
||||
|
||||
#include <src/servers/Server_Common/Network/Connection.h>
|
||||
#include <src/servers/Server_Common/Network/Hive.h>
|
||||
#include <src/servers/Server_Common/Network/Acceptor.h>
|
||||
#include <Server_Common/Network/Connection.h>
|
||||
#include <Server_Common/Network/Hive.h>
|
||||
|
||||
#include <src/servers/Server_Common/Exd/ExdData.h>
|
||||
#include <src/servers/Server_Common/Network/PacketContainer.h>
|
||||
#include <Server_Common/Exd/ExdData.h>
|
||||
#include <Server_Common/Network/PacketContainer.h>
|
||||
#include <Server_Common/Database/DbLoader.h>
|
||||
#include <Server_Common/Database/CharaDbConnection.h>
|
||||
#include <Server_Common/Database/DbWorkerPool.h>
|
||||
#include <Server_Common/Database/PreparedStatement.h>
|
||||
|
||||
#include "src/servers/Server_Zone/Network/GameConnection.h"
|
||||
#include "Network/GameConnection.h"
|
||||
#include "Session.h"
|
||||
|
||||
#include "src/servers/Server_Zone/Zone/ZoneMgr.h"
|
||||
#include "Zone/ZoneMgr.h"
|
||||
|
||||
#include "src/servers/Server_Zone/DebugCommand/DebugCommandHandler.h"
|
||||
#include "DebugCommand/DebugCommandHandler.h"
|
||||
|
||||
#include "Script/ScriptManager.h"
|
||||
#include "Linkshell/LinkshellMgr.h"
|
||||
|
@ -38,15 +32,9 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <Server_Common/Database/DbLoader.h>
|
||||
#include <Server_Common/Database/CharaDbConnection.h>
|
||||
#include <Server_Common/Database/DbWorkerPool.h>
|
||||
#include <Server_Common/Database/PreparedStatement.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
Core::Logger g_log;
|
||||
Core::Db::Database g_database;
|
||||
Core::DebugCommandHandler g_gameCommandMgr;
|
||||
Core::Scripting::ScriptManager g_scriptMgr;
|
||||
Core::Data::ExdData g_exdData;
|
||||
|
@ -54,7 +42,7 @@ Core::ZoneMgr g_zoneMgr;
|
|||
Core::LinkshellMgr g_linkshellMgr;
|
||||
Core::Db::DbWorkerPool< Core::Db::CharaDbConnection > g_charaDb;
|
||||
|
||||
Core::ServerZone::ServerZone( const std::string& configPath, uint16_t serverId )
|
||||
Core::ServerZone::ServerZone( const std::string& configPath )
|
||||
: m_configPath( configPath ),
|
||||
m_bRunning( true )
|
||||
{
|
||||
|
@ -95,7 +83,7 @@ bool Core::ServerZone::registerBnpcTemplate( std::string templateName, uint32_t
|
|||
|
||||
Core::Entity::BattleNpcTemplatePtr Core::ServerZone::getBnpcTemplate( std::string templateName )
|
||||
{
|
||||
auto it = m_bnpcTemplates.find(templateName);
|
||||
auto it = m_bnpcTemplates.find( templateName );
|
||||
|
||||
if (it != m_bnpcTemplates.end())
|
||||
return nullptr;
|
||||
|
@ -190,131 +178,8 @@ bool Core::ServerZone::loadSettings( int32_t argc, char* argv[] )
|
|||
if( !loader.initDbs() )
|
||||
return false;
|
||||
|
||||
// execute() runs asynchronous
|
||||
g_charaDb.execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" );
|
||||
g_charaDb.execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
|
||||
// query runs synchronous
|
||||
auto res = g_charaDb.query( "SELECT id,ip,port FROM zoneservers" );
|
||||
while( res->next() )
|
||||
{
|
||||
g_log.info( "id: " + std::to_string( res->getUInt( "id" ) ) );
|
||||
g_log.info( "ip: " + res->getString( "ip" ) );
|
||||
g_log.info( "port: " + std::to_string( res->getUInt( "port" ) ) );
|
||||
}
|
||||
|
||||
|
||||
//stmt->setUInt( 1, 245 );
|
||||
//stmt->setString( 2, "12.12.12.12" );
|
||||
//stmt->setUInt( 3, 3306 );
|
||||
//CharacterDatabase.execute( stmt );
|
||||
try
|
||||
{
|
||||
// // bunch of test cases for db wrapper
|
||||
boost::shared_ptr< Mysql::MySqlBase > base( new Mysql::MySqlBase() );
|
||||
g_log.info( base->getVersionInfo() );
|
||||
|
||||
Mysql::optionMap options;
|
||||
options[ MYSQL_OPT_RECONNECT ] = "1";
|
||||
|
||||
auto con = base->connect( "127.0.0.1", "root", "", options, 3306 );
|
||||
|
||||
// if( con->getAutoCommit() )
|
||||
// g_log.info( "autocommit active" );
|
||||
|
||||
// con->setAutoCommit( false );
|
||||
|
||||
// if( !con->getAutoCommit() )
|
||||
// g_log.info( "autocommit inactive" );
|
||||
|
||||
// con->setAutoCommit( true );
|
||||
|
||||
// if( con->getAutoCommit() )
|
||||
// g_log.info( "autocommit active" );
|
||||
|
||||
con->setSchema( "sapphire" );
|
||||
|
||||
// boost::scoped_ptr< Mysql::Statement > stmt( con->createStatement() );
|
||||
// bool t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
// t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" );
|
||||
// // t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" ); // throws duplicate entry
|
||||
// t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
// t1 = stmt->execute( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( 101, '127.0.0.1', 54555);" );
|
||||
// //t1 = stmt->execute( "DELETE FROM zoneservers WHERE id = 101" );
|
||||
|
||||
// //boost::scoped_ptr< Mysql::Statement > stmt1( con->createStatement() );
|
||||
// //bool t2 = stmt1->execute( "INSERT INTO BLARGH!" ); // throws error
|
||||
|
||||
// boost::scoped_ptr< Mysql::Statement > stmt2( con->createStatement() );
|
||||
// boost::scoped_ptr< Mysql::ResultSet > res( stmt2->executeQuery( "SELECT id,ip,port FROM zoneservers" ) );
|
||||
|
||||
// while( res->next() )
|
||||
// {
|
||||
// g_log.info( "id: " + std::to_string( res->getUInt( "id" ) ) );
|
||||
// g_log.info( "ip: " + res->getString( "ip" ) );
|
||||
// g_log.info( "port: " + std::to_string( res->getUInt( "port" ) ) );
|
||||
|
||||
// // alternatively ( slightly faster )
|
||||
// // g_log.info( "id: " + std::to_string( res->getUInt( 1 ) ) );
|
||||
// // g_log.info( "ip: " + res->getString( 2 ) );
|
||||
// // g_log.info( "port: " + std::to_string( res->getUInt( 3 ) ) );
|
||||
|
||||
// }
|
||||
|
||||
// // binary data test
|
||||
// boost::scoped_ptr< Mysql::Statement > stmt3( con->createStatement() );
|
||||
// boost::scoped_ptr< Mysql::ResultSet > res1( stmt3->executeQuery( "SELECT * FROM charabase" ) );
|
||||
|
||||
// while( res1->next() )
|
||||
// {
|
||||
// auto blob = res1->getBlobVector( "Customize" );
|
||||
// }
|
||||
|
||||
// pstmt2->setInt( 1, 1001 );
|
||||
// pstmt2->execute();
|
||||
|
||||
// boost::scoped_ptr< Mysql::PreparedStatement > pstmt( con->prepareStatement( "INSERT INTO zoneservers ( id, ip, port ) VALUES ( ?, ?, ?);" ) );
|
||||
// pstmt->setInt( 1, 1001 );
|
||||
// pstmt->setString( 2, "123.123.123.123" );
|
||||
// pstmt->setInt( 3, 5454 );
|
||||
// pstmt->execute();
|
||||
|
||||
// pstmt->setInt( 1, 1021 );
|
||||
// pstmt->setString( 2, "173.173.173.173" );
|
||||
// pstmt->setInt( 3, 5151 );
|
||||
// pstmt->execute();
|
||||
|
||||
// boost::scoped_ptr< Mysql::PreparedStatement > pstmt1( con->prepareStatement( "DELETE FROM zoneservers WHERE id = ?" ) );
|
||||
// pstmt->setInt( 1, 1021 );
|
||||
// pstmt->execute();
|
||||
|
||||
// pstmt->setInt( 1, 1001 );
|
||||
// pstmt->execute();
|
||||
|
||||
}
|
||||
catch( std::runtime_error e )
|
||||
{
|
||||
g_log.error( e.what() );
|
||||
}
|
||||
|
||||
|
||||
Db::DatabaseParams params;
|
||||
params.bufferSize = 16384;
|
||||
params.connectionCount = 3;
|
||||
params.databaseName = m_pConfig->getValue< std::string >( "Settings.General.Mysql.Database", "sapphire" );
|
||||
params.hostname = m_pConfig->getValue< std::string >( "Settings.General.Mysql.Host", "127.0.0.1" );
|
||||
params.password = m_pConfig->getValue< std::string >( "Settings.General.Mysql.Pass", "" );
|
||||
params.port = m_pConfig->getValue< uint16_t >( "Settings.General.Mysql.Port", 3306 );
|
||||
params.username = m_pConfig->getValue< std::string >( "Settings.General.Mysql.Username", "root" );
|
||||
|
||||
if( !g_database.initialize( params ) )
|
||||
{
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 5000 ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_port = m_pConfig->getValue< uint16_t >( "Settings.General.ListenPort", 54992 );
|
||||
m_ip = m_pConfig->getValue< std::string >( "Settings.General.ListenIp", "0.0.0.0" );;
|
||||
m_ip = m_pConfig->getValue< std::string >( "Settings.General.ListenIp", "0.0.0.0" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -398,10 +263,12 @@ void Core::ServerZone::mainLoop()
|
|||
auto session = sessionIt.second;
|
||||
if( session && session->getPlayer() )
|
||||
{
|
||||
|
||||
// if the player is in a zone, let the zone handler take care of his updates
|
||||
// else do it here.
|
||||
if( !session->getPlayer()->getCurrentZone() )
|
||||
session->update();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,6 +280,19 @@ void Core::ServerZone::mainLoop()
|
|||
|
||||
auto pPlayer = it->second->getPlayer();
|
||||
|
||||
// remove session of players marked for removel ( logoff / kick )
|
||||
if( pPlayer->isMarkedForRemoval() && diff > 1 )
|
||||
{
|
||||
it->second->close();
|
||||
// if( it->second.unique() )
|
||||
{
|
||||
g_log.info("[" + std::to_string(it->second->getId() ) + "] Session removal" );
|
||||
it = this->m_sessionMap.erase( it );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// remove sessions that simply timed out
|
||||
if( diff > 20 )
|
||||
{
|
||||
g_log.info("[" + std::to_string(it->second->getId() ) + "] Session time out" );
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Core {
|
|||
class ServerZone
|
||||
{
|
||||
public:
|
||||
ServerZone( const std::string& configPath, uint16_t serverId = 0 );
|
||||
ServerZone( const std::string& configPath );
|
||||
~ServerZone();
|
||||
|
||||
void run( int32_t argc, char* argv[] );
|
||||
|
|
|
@ -125,7 +125,7 @@ void Core::Session::update()
|
|||
m_pZoneConnection->processOutQueue();
|
||||
}
|
||||
|
||||
if( m_pZoneConnection )
|
||||
if( m_pChatConnection )
|
||||
{
|
||||
m_pChatConnection->processInQueue();
|
||||
m_pChatConnection->processOutQueue();
|
||||
|
|
24
src/tools/pcb_reader/README.md
Normal file
24
src/tools/pcb_reader/README.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
collision data exporter for sapphire
|
||||
|
||||
compile with STANDALONE defined to compile without boost and sapphire dependencies
|
||||
|
||||
usage:
|
||||
- regular
|
||||
- compile with root sapphire dir cmakelists
|
||||
- sapphire/src/tools/bin/pcb_reader2 "<path/to/game/sqpack/ffxiv>" <territory>
|
||||
- standalone
|
||||
- compile main.cpp with STANDALONE defined in build arg
|
||||
- download ffxivexplorer <http://ffxivexplorer.fragmenterworks.com/>
|
||||
- ffxivexplorer > path/to/ffxiv's/game/sqpack/ffxiv/020000.dat
|
||||
- ctrl click the following:
|
||||
- `bg/ffxiv/[REGION]/common/collision`
|
||||
- `bg/ffxiv/[REGION]/[dun|fld|twn|etc..]/common/collision/`
|
||||
- `bg/ffxiv/[REGION]/[dun|fld|twn|etc..]/collision/`
|
||||
- `bg/ffxiv/region/shared/[for_bg|for_hou]/`
|
||||
- `bg/ffxiv/[REGION]/[dun|fld|twn|etc..]/ZONE/level/`
|
||||
- `bg/ffxiv/[REGION]/[dun|fld|twn|etc..]/ZONE/collision/`
|
||||
- `bgcommon/world/sys/shared/for_bg/`
|
||||
and `File > Export Raw` to pcb_reader exe dir (common and shared files are optional but you will be missing a lot of objects if you skip them)
|
||||
- note: at this time ffxivexplorer is still missing some hashes, though any tool which can export the exds should work fine
|
||||
- main "" <territory>
|
||||
|
|
@ -1,21 +1,23 @@
|
|||
#include <stdio.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
|
||||
#include "pcb.h"
|
||||
#include "lgb.h"
|
||||
#include "sgb.h"
|
||||
|
||||
#ifndef STANDALONE
|
||||
#include <GameData.h>
|
||||
#include <File.h>
|
||||
#include <DatCat.h>
|
||||
#include <ExdData.h>
|
||||
#include <ExdCat.h>
|
||||
#include <Exd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <chrono>
|
||||
//#include <boost/algorithm/string.hpp>
|
||||
#endif
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
@ -86,7 +88,7 @@ std::string zoneNameToPath( const std::string& name )
|
|||
char region = name[1];
|
||||
char type = name[2];
|
||||
char zone = name[3];
|
||||
static std::map<char, std::string> teriMap
|
||||
static std::map< char, std::string > teriMap
|
||||
{
|
||||
{ 'r', "roc" },
|
||||
{ 'w', "wil" },
|
||||
|
@ -98,7 +100,7 @@ std::string zoneNameToPath( const std::string& name )
|
|||
{ 'z', "zon" }
|
||||
};
|
||||
|
||||
static std::map<char, std::string> typeMap
|
||||
static std::map< char, std::string > typeMap
|
||||
{
|
||||
{ 'f', "fld" },
|
||||
{ 't', "twn" },
|
||||
|
@ -117,6 +119,24 @@ std::string zoneNameToPath( const std::string& name )
|
|||
return ret;
|
||||
}
|
||||
|
||||
void readFileToBuffer( const std::string& path, std::vector< char >& buf )
|
||||
{
|
||||
auto inFile = std::ifstream( path, std::ios::binary );
|
||||
if( inFile.good() )
|
||||
{
|
||||
inFile.seekg( 0, inFile.end );
|
||||
int32_t fileSize = inFile.tellg();
|
||||
buf.resize( fileSize );
|
||||
inFile.seekg( 0, inFile.beg );
|
||||
inFile.read( &buf[0], fileSize );
|
||||
inFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error( "Unable to open " + path );
|
||||
}
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
|
@ -136,21 +156,35 @@ int main( int argc, char* argv[] )
|
|||
|
||||
try
|
||||
{
|
||||
std::string listPcbPath( "bg/ffxiv/" + zonePath + "/collision/list.pcb" );
|
||||
std::string bgLgbPath( "bg/ffxiv/" + zonePath + "/level/bg.lgb" );
|
||||
std::string collisionFilePath( "bg/ffxiv/" + zonePath + "/collision/" );
|
||||
std::vector< char > section;
|
||||
std::vector< char > section1;
|
||||
|
||||
#ifndef STANDALONE
|
||||
xiv::dat::GameData data1( gamePath );
|
||||
xiv::exd::ExdData eData( data1 );
|
||||
|
||||
const xiv::dat::Cat& test = data1.get_category( "bg" );
|
||||
|
||||
auto test_file = data1.get_file( "bg/ffxiv/" + zonePath + "/level/bg.lgb" );
|
||||
auto section = test_file->access_data_sections().at( 0 );
|
||||
int32_t list_offset = *(uint32_t*)§ion[0x18];
|
||||
int32_t size = *(uint32_t*)§ion[4];
|
||||
auto test_file = data1.get_file( bgLgbPath );
|
||||
section = test_file->access_data_sections().at( 0 );
|
||||
|
||||
std::vector<std::string> stringList;
|
||||
auto test_file1 = data1.get_file( listPcbPath );
|
||||
section1 = test_file1->access_data_sections().at( 0 );
|
||||
#else
|
||||
{
|
||||
readFileToBuffer( bgLgbPath, section );
|
||||
readFileToBuffer( listPcbPath, section1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t list_offset = *( uint32_t* )§ion[0x18];
|
||||
int32_t size = *( uint32_t* )§ion[4];
|
||||
|
||||
std::vector< std::string > stringList;
|
||||
|
||||
auto test_file1 = data1.get_file( "bg/ffxiv/" + zonePath + "/collision/list.pcb" );
|
||||
auto section1 = test_file1->access_data_sections().at( 0 );
|
||||
std::string path = "bg/ffxiv/" + zonePath + "/collision/";
|
||||
uint32_t offset1 = 0x20;
|
||||
for( ; ; )
|
||||
{
|
||||
|
@ -158,7 +192,7 @@ int main( int argc, char* argv[] )
|
|||
uint16_t trId = *(uint16_t*)§ion1[offset1];
|
||||
|
||||
char someString[200];
|
||||
sprintf( someString, "%str%04d.pcb", path.c_str(), trId );
|
||||
sprintf( someString, "%str%04d.pcb", collisionFilePath.c_str(), trId );
|
||||
stringList.push_back( std::string( someString ) );
|
||||
//std::cout << someString << "\n";
|
||||
offset1 += 0x20;
|
||||
|
@ -191,18 +225,24 @@ int main( int argc, char* argv[] )
|
|||
fp_out = fopen( ( zoneName + ".obj" ).c_str(), "ab+" );
|
||||
if( fp_out )
|
||||
{
|
||||
std::map<std::string, PCB_FILE> pcbFiles;
|
||||
std::map<std::string, SGB_FILE> sgbFiles;
|
||||
std::map<std::string, uint32_t> objCount;
|
||||
std::map< std::string, PCB_FILE > pcbFiles;
|
||||
std::map< std::string, SGB_FILE > sgbFiles;
|
||||
std::map< std::string, uint32_t > objCount;
|
||||
auto loadPcbFile = [&]( const std::string& fileName ) -> bool
|
||||
{
|
||||
try
|
||||
{
|
||||
char* dataSection = nullptr;
|
||||
//std::cout << fileName << " ";
|
||||
#ifndef STANDALONE
|
||||
auto file = data1.get_file( fileName );
|
||||
auto sections = file->get_data_sections();
|
||||
auto dataSection = §ions.at( 0 )[0];
|
||||
|
||||
dataSection = §ions.at( 0 )[0];
|
||||
#else
|
||||
std::vector< char > buf;
|
||||
readFileToBuffer( fileName, buf );
|
||||
dataSection = &buf[0];
|
||||
#endif
|
||||
//std::cout << sections.size() << "\n";
|
||||
|
||||
uint32_t offset = 0;
|
||||
|
@ -244,9 +284,17 @@ int main( int argc, char* argv[] )
|
|||
SGB_FILE sgbFile;
|
||||
try
|
||||
{
|
||||
char* dataSection = nullptr;
|
||||
//std::cout << fileName << " ";
|
||||
#ifndef STANDALONE
|
||||
auto file = data1.get_file( fileName );
|
||||
auto sections = file->get_data_sections();
|
||||
auto dataSection = §ions.at( 0 )[0];
|
||||
dataSection = §ions.at( 0 )[0];
|
||||
#else
|
||||
std::vector< char > buf;
|
||||
readFileToBuffer( fileName, buf );
|
||||
dataSection = &buf[0];
|
||||
#endif
|
||||
sgbFile = SGB_FILE( &dataSection[0] );
|
||||
sgbFiles.insert( std::make_pair( fileName, sgbFile ) );
|
||||
return true;
|
||||
|
@ -356,8 +404,8 @@ int main( int argc, char* argv[] )
|
|||
totalGroups++;
|
||||
for( const auto& pEntry : group.entries )
|
||||
{
|
||||
auto pGimmick = dynamic_cast<LGB_GIMMICK_ENTRY*>( pEntry.get() );
|
||||
auto pBgParts = dynamic_cast<LGB_BGPARTS_ENTRY*>( pEntry.get() );
|
||||
auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() );
|
||||
auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() );
|
||||
|
||||
std::string fileName( "" );
|
||||
fileName.resize( 256 );
|
||||
|
@ -410,7 +458,7 @@ int main( int argc, char* argv[] )
|
|||
{
|
||||
for( const auto& pEntry : group.entries )
|
||||
{
|
||||
auto pModel = dynamic_cast<SGB_MODEL_ENTRY*>( pEntry.get() );
|
||||
auto pModel = dynamic_cast< SGB_MODEL_ENTRY* >( pEntry.get() );
|
||||
fileName = pModel->collisionFileName;
|
||||
writeOutput( fileName, &pGimmick->header.scale, &pGimmick->header.rotation, &pGimmick->header.translation, pModel );
|
||||
}
|
||||
|
@ -423,7 +471,7 @@ int main( int argc, char* argv[] )
|
|||
std::cout << "Total Groups " << totalGroups << " Total entries " << totalGroupEntries << "\n";
|
||||
}
|
||||
std::cout << "Finished exporting " << zoneName << " in " <<
|
||||
std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now() - startTime ).count() << " seconds\n";
|
||||
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::system_clock::now() - startTime ).count() << " seconds\n";
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
|
|
|
@ -303,7 +303,11 @@ int main()
|
|||
outputFile1.write(§ion[0], section.size());
|
||||
outputFile1.close();
|
||||
std::string command= std::string("java -jar unluac_2015_06_13.jar ") + "generated/" + questInfo->name_intern + ".luab" + ">> " + "generated/" + questInfo->name_intern + ".lua";
|
||||
system(command.c_str());
|
||||
if ( system( command.c_str() ) == -1 )
|
||||
{
|
||||
g_log.error( "Error executing java command:\n" + command + "\nerrno: " + std::strerror( errno ) );
|
||||
return errno;
|
||||
}
|
||||
for( ; ; )
|
||||
{
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue