1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 06:47:45 +00:00

Major rewrite of zonelines, aetherytes and discoveries

This commit is contained in:
Mordred 2019-10-21 23:24:26 +02:00
parent eb75b35e7d
commit b17af41e67
21 changed files with 738 additions and 4899 deletions

View file

@ -0,0 +1,198 @@
#ifndef SAPPHIRE_LGBTYPES_H
#define SAPPHIRE_LGBTYPES_H
#include "vec3.h"
enum class LgbEntryType : uint32_t
{
BgParts = 1,
Attribute = 2,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
RoutePath = 10,
Character = 11,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Player = 37,
Monster = 38,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
LVB = 42,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
DemiHuman = 46,
EnvLocation = 47,
ControlPoint = 48,
EventRange = 49,
RestBonusRange = 50,
QuestMarker = 51,
TimeLine = 52,
ObjectBehaviorSet = 53,
Movie = 54,
ScenarioEXD = 55,
ScenarioText = 56,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
SoundEnvSet = 60,
CutActionTimeline = 61,
CharaScene = 62,
CutAction = 63,
EquipPreset = 64,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
PartyMember = 73,
KeepRange = 74,
SphereCastRange = 75,
IndoorObject = 76,
OutdoorObject = 77,
EditGroup = 78,
StableChocobo = 79
};
enum PopType : uint32_t
{
PopTypePC = 0x1,
PopTypeNPC = 0x2,
PopTypeBNPC = 0x2,
PopTypeContent = 0x3,
};
struct Transformation
{
vec3 translation;
vec3 rotation;
vec3 scale;
};
struct InstanceObject
{
LgbEntryType type;
uint32_t instanceId;
uint32_t nameOffset;
Transformation transform;
};
struct BgPartsData : public InstanceObject
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
struct RelativePositions
{
int32_t Pos;
int32_t PosCount;
};
struct PopRangeData : InstanceObject
{
PopType popType;
RelativePositions relativePositions;
float innerRadiusRatio;
uint8_t index;
uint8_t padding00[3];
uint32_t reserved;
};
struct GimmickData : public InstanceObject
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
struct ENpcData : public InstanceObject
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
struct EObjData : public InstanceObject
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
enum TriggerBoxShape : uint32_t
{
TriggerBoxShapeBox = 0x1,
TriggerBoxShapeSphere = 0x2,
TriggerBoxShapeCylinder = 0x3,
TriggerBoxShapeBoard = 0x4,
TriggerBoxShapeMesh = 0x5,
TriggerBoxShapeBoardBothSides = 0x6,
};
struct TriggerBoxInstanceObject
{
TriggerBoxShape triggerBoxShape;
int16_t priority;
int8_t enabled;
uint8_t padding;
uint32_t reserved;
};
struct ExitRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t exitType;
uint16_t zoneId;
uint16_t destTerritoryType;
int index;
uint32_t destInstanceObjectId;
uint32_t returnInstanceObjectId;
float direction;
uint32_t reserved;
};
struct MapRangeData : public InstanceObject
{
TriggerBoxInstanceObject triggerBoxType;
uint32_t mapId;
uint32_t placeNameBlock;
uint32_t placeNameSpot;
uint32_t bGM;
uint32_t weather;
uint32_t reserved;
uint32_t reserved2;
uint16_t reserved3;
uint8_t housingBlockId;
int8_t restBonusEffective;
uint8_t discoveryIndex;
int8_t mapEnabled;
int8_t placeNameEnabled;
int8_t discoveryEnabled;
int8_t bGMEnabled;
int8_t weatherEnabled;
int8_t restBonusEnabled;
int8_t bGMPlayZoneInOnly;
int8_t liftEnabled;
int8_t housingEnabled;
uint16_t padding;
};
#endif //SAPPHIRE_LGBTYPES_H

View file

@ -12,87 +12,33 @@
#include "matrix4.h" #include "matrix4.h"
#include "vec3.h" #include "vec3.h"
#include "sgb.h" #include "sgb.h"
#include "LgbTypes.h"
// garbage to skip model loading // based on https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
extern bool ignoreModels;
// all credit to
// https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
// this is simply their work ported to c++ since we dont c#
struct LGB_FILE; struct LGB_FILE;
struct LGB_FILE_HEADER; struct LGB_FILE_HEADER;
struct LGB_GROUP; struct LGB_GROUP;
struct LGB_GROUP_HEADER; struct LGB_GROUP_HEADER;
enum class LgbEntryType : class LgbEntry
uint32_t
{
BgParts = 1,
Light = 3,
Vfx = 4,
PositionMarker = 5,
Gimmick = 6,
SharedGroup6 = 6,// secondary variable is set to 2
Sound = 7,
EventNpc = 8,
BattleNpc = 9,
Aetheryte = 12,
EnvSpace = 13,
Gathering = 14,
SharedGroup15 = 15,// secondary variable is set to 13
Treasure = 16,
Weapon = 39,
PopRange = 40,
ExitRange = 41,
MapRange = 43,
NaviMeshRange = 44,
EventObject = 45,
EnvLocation = 47,
EventRange = 49,
QuestMarker = 51,
CollisionBox = 57,
DoorRange = 58,
LineVfx = 59,
ClientPath = 65,
ServerPath = 66,
GimmickRange = 67,
TargetMarker = 68,
ChairMarker = 69,
ClickableRange = 70,
PrefetchRange = 71,
FateRange = 72,
SphereCastRange = 75,
};
struct LGB_ENTRY_HEADER
{
LgbEntryType type;
uint32_t unknown;
uint32_t nameOffset;
vec3 translation;
vec3 rotation;
vec3 scale;
};
class LGB_ENTRY
{ {
public: public:
char* m_buf; char* m_buf;
uint32_t m_offset; uint32_t m_offset;
LGB_ENTRY_HEADER header; InstanceObject header;
LGB_ENTRY() LgbEntry()
{ {
m_buf = nullptr; m_buf = nullptr;
m_offset = 0; m_offset = 0;
memset( &header, 0, sizeof( header ) ); memset( &header, 0, sizeof( header ) );
}; };
LGB_ENTRY( char* buf, uint32_t offset ) LgbEntry( char* buf, uint32_t offset )
{ {
m_buf = buf; m_buf = buf;
m_offset = offset; m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset ); header = *reinterpret_cast< InstanceObject* >( buf + offset );
}; };
const LgbEntryType getType() const const LgbEntryType getType() const
@ -100,30 +46,16 @@ public:
return header.type; return header.type;
}; };
virtual ~LGB_ENTRY() virtual ~LgbEntry()
{ {
}; };
}; };
struct LGB_BGPARTS_HEADER : class LGB_BGPARTS_ENTRY : public LgbEntry
public LGB_ENTRY_HEADER
{
uint32_t modelFileOffset;
uint32_t collisionFileOffset;
uint32_t unknown4;
uint32_t unknown5;
uint32_t unknown6;
uint32_t unknown7;
uint32_t unknown8;
uint32_t unknown9;
};
class LGB_BGPARTS_ENTRY :
public LGB_ENTRY
{ {
public: public:
LGB_BGPARTS_HEADER header; BgPartsData header;
std::string name; std::string name;
std::string modelFileName; std::string modelFileName;
std::string collisionFileName; std::string collisionFileName;
@ -132,124 +64,95 @@ public:
{ {
}; };
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
LGB_ENTRY( buf, offset )
{ {
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset ); header = *reinterpret_cast< BgPartsData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset ); modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset ); collisionFileName = std::string( buf + offset + header.collisionFileOffset );
}; };
}; };
struct LGB_GIMMICK_HEADER : class LGB_GIMMICK_ENTRY : public LgbEntry
public LGB_ENTRY_HEADER
{
uint32_t gimmickFileOffset;
char unknownBytes[100];
};
class LGB_GIMMICK_ENTRY :
public LGB_ENTRY
{ {
public: public:
LGB_GIMMICK_HEADER header; GimmickData header;
std::string name; std::string name;
std::string gimmickFileName; std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
LGB_ENTRY( buf, offset )
{ {
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset ); header = *reinterpret_cast< GimmickData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset ); gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
}; };
}; };
struct LGB_ENPC_HEADER : class LGB_ENPC_ENTRY : public LgbEntry
public LGB_ENTRY_HEADER
{
uint32_t enpcId;
uint8_t unknown1[0x24];
};
class LGB_ENPC_ENTRY :
public LGB_ENTRY
{ {
public: public:
LGB_ENPC_HEADER header; ENpcData header;
std::string name; std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) : LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset ); header = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
};
};
struct LGB_EOBJ_HEADER :
public LGB_ENTRY_HEADER
{
uint32_t eobjId;
uint32_t levelHierachyId;
uint8_t unknown1[0xC];
};
class LGB_EOBJ_ENTRY :
public LGB_ENTRY
{
public:
LGB_EOBJ_HEADER header;
std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset )
{
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_MAPRANGE_HEADER : class LGB_EOBJ_ENTRY : public LgbEntry
public LGB_ENTRY_HEADER
{
uint32_t type;
uint8_t unknown2;
uint8_t unknown2_1;
uint16_t unknown3;
uint32_t unknown5;
uint32_t mapId;
uint32_t offsetX;
uint32_t offsetY;
uint32_t unkInts[4];
uint16_t unkShort;
uint8_t unkFlag;
uint8_t unkFlag2;
uint8_t discoveryIndex;
uint8_t unkFlag3;
uint8_t unkFlag4;
uint8_t unknown4[0x09];
};
struct LGB_MAPRANGE_ENTRY :
public LGB_ENTRY
{ {
public: public:
LGB_MAPRANGE_HEADER header; EObjData header;
std::string name; std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) : LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
LGB_ENTRY( buf, offset )
{ {
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset ); header = *reinterpret_cast< EObjData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
{
public:
MapRangeData header;
std::string name;
LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_EXIT_RANGE_ENTRY : public LgbEntry
{
public:
ExitRangeData header;
std::string name;
LGB_EXIT_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< ExitRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset );
};
};
struct LGB_POP_RANGE_ENTRY : public LgbEntry
{
public:
PopRangeData header;
LGB_POP_RANGE_ENTRY( char* buf, uint32_t offset ) : LgbEntry( buf, offset )
{
header = *reinterpret_cast< PopRangeData* >( buf + offset );
};
};
struct LGB_GROUP_HEADER struct LGB_GROUP_HEADER
{ {
uint32_t id; uint32_t id;
@ -272,15 +175,13 @@ struct LGB_GROUP
LGB_FILE* parent; LGB_FILE* parent;
LGB_GROUP_HEADER header; LGB_GROUP_HEADER header;
std::string name; std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries; std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset ) LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{ {
parent = parentStruct; parent = parentStruct;
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset ); header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
name = std::string( buf + offset + header.groupNameOffset ); name = std::string( buf + offset + header.groupNameOffset );
//entries.resize( header.entryCount );
//std::cout << name << "\n\t unknown: " << header.unknown << "\n";
const auto entriesOffset = offset + header.entriesOffset; const auto entriesOffset = offset + header.entriesOffset;
for( auto i = 0; i < header.entryCount; ++i ) for( auto i = 0; i < header.entryCount; ++i )
{ {
@ -288,8 +189,7 @@ struct LGB_GROUP
try try
{ {
const auto type = *reinterpret_cast<LgbEntryType*>( buf + entryOffset ); const auto type = *reinterpret_cast< LgbEntryType* >( buf + entryOffset );
// garbage to skip model loading
if( type == LgbEntryType::BgParts ) if( type == LgbEntryType::BgParts )
{ {
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) ); entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
@ -306,16 +206,18 @@ struct LGB_GROUP
{ {
entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) ); entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) );
} }
else if( type == LgbEntryType::ExitRange )
{
entries.push_back( std::make_shared< LGB_EXIT_RANGE_ENTRY >( buf, entryOffset ) );
}
else if( type == LgbEntryType::MapRange ) else if( type == LgbEntryType::MapRange )
{ {
entries.push_back( std::make_shared< LGB_MAPRANGE_ENTRY >( buf, entryOffset ) ); entries.push_back( std::make_shared< LGB_MAP_RANGE_ENTRY >( buf, entryOffset ) );
} }
else else
{ {
entries.push_back( std::make_shared< LGB_ENTRY >( buf, entryOffset ) ); entries.push_back( std::make_shared< LgbEntry >( buf, entryOffset ) );
} }
} }
catch( std::exception& e ) catch( std::exception& e )
{ {
@ -344,8 +246,7 @@ struct LGB_FILE
std::vector< LGB_GROUP > groups; std::vector< LGB_GROUP > groups;
std::string m_name; std::string m_name;
LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( buf )
LGB_FILE( buf )
{ {
m_name = name; m_name = name;
} }
@ -356,8 +257,6 @@ struct LGB_FILE
if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 ) if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 )
throw std::runtime_error( "Invalid LGB file!" ); throw std::runtime_error( "Invalid LGB file!" );
//groups.resize(header.groupCount);
constexpr auto baseOffset = sizeof( header ); constexpr auto baseOffset = sizeof( header );
for( auto i = 0; i < header.groupCount; ++i ) for( auto i = 0; i < header.groupCount; ++i )
{ {

View file

@ -22,15 +22,13 @@ struct SGB_GROUP;
struct SGB_GROUP_HEADER; struct SGB_GROUP_HEADER;
enum SgbDataType : enum SgbDataType : uint32_t
uint32_t
{ {
Unknown0008 = 0x0008, Unknown0008 = 0x0008,
Group = 0x0100, Group = 0x0100,
}; };
enum SgbGroupEntryType : enum SgbGroupEntryType : uint32_t
uint32_t
{ {
Model = 0x01, Model = 0x01,
Gimmick = 0x06, Gimmick = 0x06,
@ -124,15 +122,13 @@ struct SGB_ENTRY_HEADER
vec3 scale; vec3 scale;
}; };
struct SGB_MODEL_HEADER : struct SGB_MODEL_HEADER : public SGB_ENTRY_HEADER
public SGB_ENTRY_HEADER
{ {
int32_t modelFileOffset; int32_t modelFileOffset;
int32_t collisionFileOffset; int32_t collisionFileOffset;
}; };
struct SGB_MODEL_ENTRY : struct SGB_MODEL_ENTRY : public SGB_GROUP_ENTRY
public SGB_GROUP_ENTRY
{ {
SGB_MODEL_HEADER header; SGB_MODEL_HEADER header;
SgbGroupEntryType type; SgbGroupEntryType type;

View file

@ -84,7 +84,7 @@ Index::Index(const std::experimental::filesystem::path& path) :
// The dat number is found in the offset, last four bits // The dat number is found in the offset, last four bits
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2; hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
// The offset in the dat file, needs to strip the dat number indicator // The offset in the dat file, needs to strip the dat number indicator
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset & 0xFFFFFFF0 ) * 0x08; hashTableEntry.datOffset = ( indexHashTableEntry.datOffset - ( indexHashTableEntry.datOffset & 0x000F ) ) * 0x08;
hashTableEntry.dirHash = indexHashTableEntry.dirHash; hashTableEntry.dirHash = indexHashTableEntry.dirHash;
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash; hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
} }

File diff suppressed because it is too large Load diff

View file

@ -400,13 +400,6 @@ CREATE TABLE `dbupdate` (
PRIMARY KEY(`name`) PRIMARY KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `discoveryinfo` (
`id` int(10) NOT NULL,
`map_id` int(3) NOT NULL,
`discover_id` int(3) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `house` ( CREATE TABLE `house` (
`HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `HouseId` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`LandSetId` int(10) UNSIGNED DEFAULT NULL, `LandSetId` int(10) UNSIGNED DEFAULT NULL,

View file

@ -5594,6 +5594,11 @@ struct ZoneSharedGroup
std::shared_ptr< xiv::dat::GameData > m_data; std::shared_ptr< xiv::dat::GameData > m_data;
std::shared_ptr< xiv::exd::ExdData > m_exd_data; std::shared_ptr< xiv::exd::ExdData > m_exd_data;
std::shared_ptr< xiv::dat::GameData > getGameData()
{
return m_data;
}
template< class T > template< class T >
std::shared_ptr< T > get( uint32_t id ) std::shared_ptr< T > get( uint32_t id )
{ {

View file

@ -1550,11 +1550,10 @@ namespace Sapphire::Network::Packets::Server
*/ */
struct FFXIVIpcDiscovery : FFXIVIpcBasePacket< Discovery > struct FFXIVIpcDiscovery : FFXIVIpcBasePacket< Discovery >
{ {
/* 0000 */ uint32_t map_part_id; /* 0000 */ uint32_t mapPartId;
/* 0004 */ uint32_t map_id; /* 0004 */ uint32_t mapId;
}; };
/** /**
* UNKOWN TYPE * UNKOWN TYPE
*/ */

View file

@ -36,10 +36,11 @@ struct ZoneInfo
uint16_t id; uint16_t id;
std::string name; std::string name;
std::string path; std::string path;
uint16_t mapId;
}; };
// parsing shit // parsing shit
std::string gamePath( "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" ); std::string gamePath( "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack" );
std::unordered_map< uint32_t, std::string > eobjNameMap; std::unordered_map< uint32_t, std::string > eobjNameMap;
std::unordered_map< uint16_t, ZoneInfo > zoneInfoMap; std::unordered_map< uint16_t, ZoneInfo > zoneInfoMap;
std::unordered_map< uint16_t, std::vector< std::pair< uint16_t, std::string > > > zoneInstanceMap; std::unordered_map< uint16_t, std::vector< std::pair< uint16_t, std::string > > > zoneInstanceMap;
@ -60,8 +61,7 @@ struct vec2
float x, y; float x, y;
}; };
struct DiscoveryMap : struct DiscoveryMap : std::enable_shared_from_this< DiscoveryMap >
std::enable_shared_from_this< DiscoveryMap >
{ {
std::string path; std::string path;
Image img; Image img;
@ -120,11 +120,11 @@ struct DiscoveryMap :
std::map< uint16_t, std::map< uint16_t, std::map< uint16_t, std::shared_ptr< DiscoveryMap > > > > discoveryMaps; std::map< uint16_t, std::map< uint16_t, std::map< uint16_t, std::shared_ptr< DiscoveryMap > > > > discoveryMaps;
enum class TerritoryTypeExdIndexes : enum class TerritoryTypeExdIndexes : size_t
size_t
{ {
TerritoryType = 0, TerritoryType = 0,
Path = 1 Path = 1,
Map = 6
}; };
using namespace std::chrono_literals; using namespace std::chrono_literals;
@ -165,6 +165,8 @@ std::string zoneNameToPath( const std::string& name )
info.id = row.first; info.id = row.first;
info.path = teriPath; info.path = teriPath;
info.name = teriName; info.name = teriName;
info.mapId = std::get< uint16_t >(
fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Map ) ) );
zoneInfoMap[ row.first ] = info; zoneInfoMap[ row.first ] = info;
if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) ) if( !found && ( Common::Util::toLowerCopy( name ) == Common::Util::toLowerCopy( teriName ) ) )
@ -217,69 +219,31 @@ void loadEobjNames()
} }
} }
void writeEobjEntry( std::ofstream& out, LGB_ENTRY* pObj ) void writeMapRangeEntry( std::ofstream& out, LgbEntry* pObj )
{ {
static std::string mapRangeStr( "\"MapRange\", " ); auto pMapRange = reinterpret_cast< LGB_MAP_RANGE_ENTRY* >( pObj );
std::ofstream discoverySql( zoneName + "_poprange.txt", std::ios::app ); if( !pMapRange->header.discoveryEnabled )
uint32_t id; return;
uint32_t unknown2 = 0, unknown2_1 = 0, unknown3 = 0;
std::string name;
std::string typeStr;
uint32_t eobjlevelHierachyId = 0;
static std::map< uint32_t, std::map< uint32_t, uint32_t > > exportedMapRange;
auto pMapRange = reinterpret_cast< LGB_MAPRANGE_ENTRY* >( pObj );
id = pMapRange->header.unknown;
unknown2 = pMapRange->header.unknown2;
unknown2_1 = pMapRange->header.unknown2_1;
unknown3 = pMapRange->header.unknown3;
typeStr = mapRangeStr;
// discovery shit
vec2 pos{ 0 };
auto subArea = 0; auto subArea = 0;
auto mapId = -1; auto mapId = -1;
auto discoveryIndex = pMapRange->header.discoveryIndex; auto discoveryIndex = pMapRange->header.discoveryIndex;
vec3 translation = pObj->header.translation; vec3 translation = pObj->header.transform.translation;
bool found = false; std::string outStr( pMapRange->name + " " + std::to_string( pMapRange->header.instanceId ) + " " +
float scale = 100.f; //pMapRange->header.unknown2 std::to_string( pMapRange->header.transform.translation.x ) + " " +
std::to_string( pMapRange->header.transform.translation.y ) + " " +
std::string outStr( pMapRange->name + " " + std::to_string( pMapRange->header.unknown ) + " " + std::to_string( pMapRange->header.transform.translation.z ) + " " +
std::to_string( pMapRange->header.translation.x ) + " " + std::to_string( pMapRange->header.transform.rotation.y ) + " " +
std::to_string( pMapRange->header.translation.y ) + " " + std::to_string( pMapRange->header.mapId ) + " " +
std::to_string( pMapRange->header.translation.z ) + " " + std::to_string( pMapRange->header.discoveryIndex ) + "\n"
std::to_string( pMapRange->header.rotation.y ) + "\n"
); );
//std::to_string( pObj->header.translation.x ) + ", " + std::to_string( pObj->header.translation.y ) + ", " + std::to_string( pObj->header.translation.z ) + out.write( outStr.c_str(), outStr.size() );
//", " + std::to_string( subArea ) + "" + "\n"
//);
discoverySql.write( outStr.c_str(), outStr.size() );
//out.write( outStr.c_str(), outStr.size() );
}
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 = ( int32_t ) 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 );
}
} }
bool isEx = false;
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
auto startTime = std::chrono::system_clock::now(); auto startTime = std::chrono::system_clock::now();
@ -288,10 +252,6 @@ int main( int argc, char* argv[] )
std::vector< std::string > argVec( argv + 1, argv + argc ); std::vector< std::string > argVec( argv + 1, argv + argc );
zoneName = "s1h1"; zoneName = "s1h1";
bool dumpAll = ignoreModels = std::remove_if( argVec.begin(), argVec.end(), []( auto arg )
{ return arg == "--dump-all"; } ) != argVec.end();
dumpAll = true;
ignoreModels = true;
if( argc > 1 ) if( argc > 1 )
{ {
zoneName = argv[ 1 ]; zoneName = argv[ 1 ];
@ -304,40 +264,23 @@ int main( int argc, char* argv[] )
} }
initExd( gamePath ); initExd( gamePath );
std::ofstream discoverySql( zoneName + "_poprange.txt", std::ios::trunc ); std::ofstream discoverySql( "maprange_export.txt", std::ios::trunc );
discoverySql.close();
if( dumpAll ) zoneNameToPath( "f1f1" );
zoneDumpList.emplace( "f1f1" );
zoneDumpList.emplace( "f1f2" );
for( const auto& zoneName : zoneDumpList )
{ {
zoneNameToPath( "s1h1" );
zoneDumpList.emplace( "s1h1" );
zoneDumpList.emplace( "f1h1" );
zoneDumpList.emplace( "w1h1" );
zoneDumpList.emplace( "e1h1" );
}
else
{
zoneDumpList.emplace( zoneName );
}
LABEL_DUMP:
entryStartTime = std::chrono::system_clock::now(); entryStartTime = std::chrono::system_clock::now();
zoneName = *zoneDumpList.begin(); discoverySql.write( ( zoneName + "\n" ).c_str(), zoneName.size() + 1 );
discoverySql.open( zoneName + "_poprange.txt", std::ios::trunc );
discoverySql.write( ( zoneName + "\n" ).c_str() , zoneName.size() + 1 );
try try
{ {
const auto zonePath = zoneNameToPath( zoneName ); const auto zonePath = zoneNameToPath( zoneName );
std::string listPcbPath( zonePath + "/collision/list.pcb" );
std::string bgLgbPath( zonePath + "/level/bg.lgb" ); std::string bgLgbPath( zonePath + "/level/bg.lgb" );
std::string planmapLgbPath( zonePath + "/level/planmap.lgb" ); std::string planmapLgbPath( zonePath + "/level/planmap.lgb" );
std::string collisionFilePath( zonePath + "/collision/" );
isEx = bgLgbPath.find( "ex1" ) != -1 || bgLgbPath.find( "ex2" ) != -1;
std::vector< char > section; std::vector< char > section;
std::vector< char > section1;
std::vector< char > section2; std::vector< char > section2;
auto test_file = gameData->getFile( bgLgbPath ); auto test_file = gameData->getFile( bgLgbPath );
@ -346,76 +289,17 @@ int main( int argc, char* argv[] )
auto planmap_file = gameData->getFile( planmapLgbPath ); auto planmap_file = gameData->getFile( planmapLgbPath );
section2 = planmap_file->access_data_sections().at( 0 ); section2 = planmap_file->access_data_sections().at( 0 );
auto test_file1 = gameData->getFile( listPcbPath );
section1 = test_file1->access_data_sections().at( 0 );
std::vector< std::string > stringList; std::vector< std::string > stringList;
uint32_t offset1 = 0x20; uint32_t offset1 = 0x20;
//loadEobjNames();
//getMapExdEntries( zoneId );
std::string eobjFileName( zoneName + "_eobj.csv" );
std::ofstream eobjOut( eobjFileName, std::ios::trunc );
if( !eobjOut.good() )
throw std::string( "Unable to create " + zoneName +
"_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str();
eobjOut.close();
eobjOut.open( eobjFileName, std::ios::app );
if( !eobjOut.good() )
throw std::string( "Unable to create " + zoneName +
"_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str();
if( 0 )
{
for( ;; )
{
uint16_t trId = *( uint16_t* ) &section1[ offset1 ];
char someString[200];
sprintf( someString, "%str%04d.pcb", collisionFilePath.c_str(), trId );
stringList.push_back( std::string( someString ) );
//std::cout << someString << "\n";
offset1 += 0x20;
if( offset1 >= section1.size() )
{
break;
}
}
}
LGB_FILE bgLgb( &section[ 0 ], "bg" ); LGB_FILE bgLgb( &section[ 0 ], "bg" );
LGB_FILE planmapLgb( &section2[ 0 ], "planmap" ); LGB_FILE planmapLgb( &section2[ 0 ], "planmap" );
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb }; std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
uint32_t max_index = 0; uint32_t max_index = 0;
// dont bother if we cant write to a file std::cout << "[Info] " << "Dumping MapRange and EObj" << "\n";
FILE* fp_out = nullptr;
//auto fp_out = ignoreModels ? ( FILE* )nullptr : fopen( ( zoneName + ".obj" ).c_str(), "w" );
if( fp_out )
{
fprintf( fp_out, "\n" );
fclose( fp_out );
}
else if( /*!ignoreModels*/ false )
{
std::string errorMessage( "Cannot create " + zoneName + ".obj\n" +
" Check no programs have a handle to file and run as admin.\n" );
std::cout << errorMessage;
throw std::runtime_error( errorMessage.c_str() );
return 0;
}
{
std::map< std::string, PCB_FILE > pcbFiles;
std::cout << "[Info] " << ( ignoreModels ? "Dumping MapRange and EObj" : "Writing obj file " ) << "\n";
uint32_t totalGroups = 0; uint32_t totalGroups = 0;
uint32_t totalGroupEntries = 0; uint32_t totalGroupEntries = 0;
@ -423,21 +307,24 @@ int main( int argc, char* argv[] )
{ {
for( const auto& group : lgb.groups ) for( const auto& group : lgb.groups )
{ {
//std::cout << "\t" << group.name << " Size " << group.header.entryCount << "\n";
totalGroups++; totalGroups++;
for( const auto& pEntry : group.entries ) for( const auto& pEntry : group.entries )
{ {
if( pEntry->getType() == LgbEntryType::PopRange ) if( pEntry->getType() == LgbEntryType::MapRange )
{ {
totalGroupEntries++; totalGroupEntries++;
writeEobjEntry( eobjOut, pEntry.get() ); writeMapRangeEntry( discoverySql, pEntry.get() );
}
else if( pEntry->getType() == LgbEntryType::ExitRange )
{
auto pExitRange = reinterpret_cast< LGB_EXIT_RANGE_ENTRY* >( pEntry.get() );
} }
} }
} }
} }
std::cout << "[Info] " << "Loaded " << pcbFiles.size() << " PCB Files \n";
std::cout << "[Info] " << "Total Groups " << totalGroups << " Total entries " << totalGroupEntries << "\n"; std::cout << "[Info] " << "Total Groups " << totalGroups << " Total entries " << totalGroupEntries << "\n";
}
std::cout << "[Success] " << "Exported " << zoneName << " in " << std::cout << "[Success] " << "Exported " << zoneName << " in " <<
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::duration_cast< std::chrono::seconds >(
std::chrono::system_clock::now() - entryStartTime ).count() << " seconds\n"; std::chrono::system_clock::now() - entryStartTime ).count() << " seconds\n";
@ -451,20 +338,15 @@ int main( int argc, char* argv[] )
std::cout << std::endl; std::cout << std::endl;
std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl; std::cout << "[Info] " << "Usage: pcb_reader2 territory \"path/to/game/sqpack/ffxiv\" " << std::endl;
} }
std::cout << "\n\n\n"; std::cout << "\n";
if( discoverySql.good() ) if( discoverySql.good() )
discoverySql.flush(); discoverySql.flush();
}
LABEL_NEXT_ZONE_ENTRY: std::cout << "\n[Success] Finished all tasks in " <<
zoneDumpList.erase( zoneName );
if( !zoneDumpList.empty() )
goto LABEL_DUMP;
std::cout << "\n\n\n[Success] Finished all tasks in " <<
std::chrono::duration_cast< std::chrono::seconds >( std::chrono::system_clock::now() - startTime ).count() std::chrono::duration_cast< std::chrono::seconds >( std::chrono::system_clock::now() - startTime ).count()
<< " seconds\n"; << " seconds\n";
std::cout << "Press any key to exit...";
getchar(); getchar();
if( eData ) if( eData )

View file

@ -285,7 +285,7 @@ int main( int argc, char* argv[] )
auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj ); auto pEobj = reinterpret_cast< LGB_EOBJ_ENTRY* >( pObj );
id = pEobj->header.eobjId; id = pEobj->header.eobjId;
unknown = pEobj->header.unknown; unknown = pEobj->header.instanceId;
eobjlevelHierachyId = pEobj->header.levelHierachyId; eobjlevelHierachyId = pEobj->header.levelHierachyId;
@ -295,7 +295,7 @@ int main( int argc, char* argv[] )
{ {
auto pGObj = pEntry1.get(); auto pGObj = pEntry1.get();
if( pGObj->getType() == LgbEntryType::Gimmick && if( pGObj->getType() == LgbEntryType::Gimmick &&
pGObj->header.unknown == pEobj->header.levelHierachyId ) pGObj->header.instanceId == pEobj->header.levelHierachyId )
{ {
auto pGObjR = reinterpret_cast< LGB_GIMMICK_ENTRY* >( pGObj ); auto pGObjR = reinterpret_cast< LGB_GIMMICK_ENTRY* >( pGObj );
char* dataSection = nullptr; char* dataSection = nullptr;
@ -361,13 +361,13 @@ int main( int argc, char* argv[] )
eobjects += " instance.registerEObj( \"" + name + "\", " + std::to_string( id ) + eobjects += " instance.registerEObj( \"" + name + "\", " + std::to_string( id ) +
", " + std::to_string( eobjlevelHierachyId ) + ", " + std::to_string( state ) + ", " + std::to_string( eobjlevelHierachyId ) + ", " + std::to_string( state ) +
", " + ", " +
"{ " + std::to_string( pObj->header.translation.x ) + "f, " "{ " + std::to_string( pObj->header.transform.translation.x ) + "f, "
+ std::to_string( pObj->header.translation.y ) + "f, " + std::to_string( pObj->header.transform.translation.y ) + "f, "
+ std::to_string( pObj->header.translation.z ) + "f }, " + + std::to_string( pObj->header.transform.translation.z ) + "f }, " +
std::to_string( pObj->header.scale.x ) + "f, " + std::to_string( pObj->header.transform.scale.x ) + "f, " +
// the rotation inside the sgbs is the inverse of what the game uses // the rotation inside the sgbs is the inverse of what the game uses
std::to_string( pObj->header.rotation.y * -1.f ) + "f ); \n" + states; std::to_string( pObj->header.transform.rotation.y * -1.f ) + "f ); \n" + states;
} }
} }
} }

View file

@ -43,6 +43,11 @@ STRUCTS
std::shared_ptr< xiv::dat::GameData > m_data; std::shared_ptr< xiv::dat::GameData > m_data;
std::shared_ptr< xiv::exd::ExdData > m_exd_data; std::shared_ptr< xiv::exd::ExdData > m_exd_data;
std::shared_ptr< xiv::dat::GameData > getGameData()
{
return m_data;
}
template< class T > template< class T >
std::shared_ptr< T > get( uint32_t id ) std::shared_ptr< T > get( uint32_t id )
{ {

View file

@ -68,7 +68,7 @@ enum class LgbEntryType :
SphereCastRange = 75, SphereCastRange = 75,
}; };
struct LGB_ENTRY_HEADER struct InstanceObject
{ {
LgbEntryType type; LgbEntryType type;
uint32_t unknown; uint32_t unknown;
@ -78,25 +78,25 @@ struct LGB_ENTRY_HEADER
vec3 scale; vec3 scale;
}; };
class LGB_ENTRY class LgbEntry
{ {
public: public:
char* m_buf; char* m_buf;
uint32_t m_offset; uint32_t m_offset;
LGB_ENTRY_HEADER header; InstanceObject header;
LGB_ENTRY() LgbEntry()
{ {
m_buf = nullptr; m_buf = nullptr;
m_offset = 0; m_offset = 0;
memset( &header, 0, sizeof( header ) ); memset( &header, 0, sizeof( header ) );
}; };
LGB_ENTRY( char* buf, uint32_t offset ) LgbEntry( char* buf, uint32_t offset )
{ {
m_buf = buf; m_buf = buf;
m_offset = offset; m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset ); header = *reinterpret_cast< InstanceObject* >( buf + offset );
}; };
const LgbEntryType getType() const const LgbEntryType getType() const
@ -104,14 +104,14 @@ public:
return header.type; return header.type;
}; };
virtual ~LGB_ENTRY() virtual ~LgbEntry()
{ {
}; };
}; };
struct LGB_BGPARTS_HEADER : struct BgPartsData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t modelFileOffset; uint32_t modelFileOffset;
uint32_t collisionFileOffset; uint32_t collisionFileOffset;
@ -124,10 +124,10 @@ struct LGB_BGPARTS_HEADER :
}; };
class LGB_BGPARTS_ENTRY : class LGB_BGPARTS_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_BGPARTS_HEADER header; BgPartsData header;
std::string name; std::string name;
std::string modelFileName; std::string modelFileName;
std::string collisionFileName; std::string collisionFileName;
@ -137,65 +137,65 @@ public:
}; };
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset ); header = *reinterpret_cast<BgPartsData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset ); modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset ); collisionFileName = std::string( buf + offset + header.collisionFileOffset );
}; };
}; };
struct LGB_GIMMICK_HEADER : struct GimmickData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t gimmickFileOffset; uint32_t gimmickFileOffset;
char unknownBytes[100]; char unknownBytes[100];
}; };
class LGB_GIMMICK_ENTRY : class LGB_GIMMICK_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_GIMMICK_HEADER header; GimmickData header;
std::string name; std::string name;
std::string gimmickFileName; std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset ); header = *reinterpret_cast<GimmickData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset ); gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n"; //std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
}; };
}; };
struct LGB_ENPC_HEADER : struct ENpcData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t enpcId; uint32_t enpcId;
uint8_t unknown1[0x24]; uint8_t unknown1[0x24];
}; };
class LGB_ENPC_ENTRY : class LGB_ENPC_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_ENPC_HEADER header; ENpcData header;
std::string name; std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) : LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset ); header = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n"; //std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
}; };
}; };
struct LGB_EOBJ_HEADER : struct EObjData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t eobjId; uint32_t eobjId;
uint32_t levelHierachyId; uint32_t levelHierachyId;
@ -203,23 +203,23 @@ struct LGB_EOBJ_HEADER :
}; };
class LGB_EOBJ_ENTRY : class LGB_EOBJ_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_EOBJ_HEADER header; EObjData header;
std::string name; std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset ); header = *reinterpret_cast< EObjData* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n"; //std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_MAPRANGE_HEADER : struct MapRangeData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t type; uint32_t type;
uint16_t unknown2; uint16_t unknown2;
@ -227,35 +227,35 @@ struct LGB_MAPRANGE_HEADER :
uint8_t unknown4[0x10]; uint8_t unknown4[0x10];
}; };
struct LGB_MAPRANGE_ENTRY : struct LGB_MAP_RANGE_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_MAPRANGE_HEADER header; MapRangeData header;
std::string name; std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) : LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset ); header = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_COLLISION_BOX_HEADER : struct LGB_COLLISION_BOX_HEADER :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint8_t unk[100]; uint8_t unk[100];
}; };
struct LGB_COLLISION_BOX_ENTRY : struct LGB_COLLISION_BOX_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
LGB_COLLISION_BOX_HEADER header; LGB_COLLISION_BOX_HEADER header;
std::string name; std::string name;
LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) : LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset ); header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset );
header.type = LgbEntryType::CollisionBox; header.type = LgbEntryType::CollisionBox;
@ -305,7 +305,7 @@ struct LGB_GROUP
LGB_FILE* parent; LGB_FILE* parent;
LGB_GROUP_HEADER header; LGB_GROUP_HEADER header;
std::string name; std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries; std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset ) LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{ {

View file

@ -257,7 +257,7 @@ bool pcbTransformModel( const std::string& fileName, const vec3* scale, const ve
return true; return true;
}; };
void exportSgbModel( const std::string& sgbFilePath, LGB_ENTRY* pGimmick, ExportedGroup& exportgroup, bool isEobj = false ) void exportSgbModel( const std::string& sgbFilePath, LgbEntry* pGimmick, ExportedGroup& exportgroup, bool isEobj = false )
{ {
if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) ) if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) )
{ {

View file

@ -68,7 +68,7 @@ enum class LgbEntryType :
SphereCastRange = 75, SphereCastRange = 75,
}; };
struct LGB_ENTRY_HEADER struct InstanceObject
{ {
LgbEntryType type; LgbEntryType type;
uint32_t unknown; uint32_t unknown;
@ -78,25 +78,25 @@ struct LGB_ENTRY_HEADER
vec3 scale; vec3 scale;
}; };
class LGB_ENTRY class LgbEntry
{ {
public: public:
char* m_buf; char* m_buf;
uint32_t m_offset; uint32_t m_offset;
LGB_ENTRY_HEADER header; InstanceObject header;
LGB_ENTRY() LgbEntry()
{ {
m_buf = nullptr; m_buf = nullptr;
m_offset = 0; m_offset = 0;
memset( &header, 0, sizeof( header ) ); memset( &header, 0, sizeof( header ) );
}; };
LGB_ENTRY( char* buf, uint32_t offset ) LgbEntry( char* buf, uint32_t offset )
{ {
m_buf = buf; m_buf = buf;
m_offset = offset; m_offset = offset;
header = *reinterpret_cast< LGB_ENTRY_HEADER* >( buf + offset ); header = *reinterpret_cast< InstanceObject* >( buf + offset );
}; };
const LgbEntryType getType() const const LgbEntryType getType() const
@ -104,14 +104,14 @@ public:
return header.type; return header.type;
}; };
virtual ~LGB_ENTRY() virtual ~LgbEntry()
{ {
}; };
}; };
struct LGB_BGPARTS_HEADER : struct BgPartsData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t modelFileOffset; uint32_t modelFileOffset;
uint32_t collisionFileOffset; uint32_t collisionFileOffset;
@ -124,10 +124,10 @@ struct LGB_BGPARTS_HEADER :
}; };
class LGB_BGPARTS_ENTRY : class LGB_BGPARTS_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_BGPARTS_HEADER header; BgPartsData header;
std::string name; std::string name;
std::string modelFileName; std::string modelFileName;
std::string collisionFileName; std::string collisionFileName;
@ -137,65 +137,65 @@ public:
}; };
LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) : LGB_BGPARTS_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>( buf + offset ); header = *reinterpret_cast<BgPartsData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string( buf + offset + header.modelFileOffset ); modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string( buf + offset + header.collisionFileOffset ); collisionFileName = std::string( buf + offset + header.collisionFileOffset );
}; };
}; };
struct LGB_GIMMICK_HEADER : struct GimmickData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t gimmickFileOffset; uint32_t gimmickFileOffset;
char unknownBytes[100]; char unknownBytes[100];
}; };
class LGB_GIMMICK_ENTRY : class LGB_GIMMICK_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_GIMMICK_HEADER header; GimmickData header;
std::string name; std::string name;
std::string gimmickFileName; std::string gimmickFileName;
LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) : LGB_GIMMICK_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>( buf + offset ); header = *reinterpret_cast<GimmickData*>( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
gimmickFileName = std::string( buf + offset + header.gimmickFileOffset ); gimmickFileName = std::string( buf + offset + header.gimmickFileOffset );
//std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n"; //std::cout << "\t " << gimmickFileName << " unknown: " << header.unknown << "\n";
}; };
}; };
struct LGB_ENPC_HEADER : struct ENpcData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t enpcId; uint32_t enpcId;
uint8_t unknown1[0x24]; uint8_t unknown1[0x24];
}; };
class LGB_ENPC_ENTRY : class LGB_ENPC_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_ENPC_HEADER header; ENpcData header;
std::string name; std::string name;
LGB_ENPC_ENTRY( char* buf, uint32_t offset ) : LGB_ENPC_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset ); header = *reinterpret_cast< ENpcData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
//std::cout << "\t ENpc " << header.enpcId << " " << name << "\n"; //std::cout << "\t ENpc " << header.enpcId << " " << name << "\n";
}; };
}; };
struct LGB_EOBJ_HEADER : struct EObjData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t eobjId; uint32_t eobjId;
uint32_t levelHierachyId; uint32_t levelHierachyId;
@ -203,23 +203,23 @@ struct LGB_EOBJ_HEADER :
}; };
class LGB_EOBJ_ENTRY : class LGB_EOBJ_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
public: public:
LGB_EOBJ_HEADER header; EObjData header;
std::string name; std::string name;
LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) : LGB_EOBJ_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset ); header = *reinterpret_cast< EObjData* >( buf + offset );
//std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n"; //std::cout << "\t " << header.eobjId << " " << name << " unknown: " << header.unknown << "\n";
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_MAPRANGE_HEADER : struct MapRangeData :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint32_t type; uint32_t type;
uint16_t unknown2; uint16_t unknown2;
@ -227,35 +227,34 @@ struct LGB_MAPRANGE_HEADER :
uint8_t unknown4[0x10]; uint8_t unknown4[0x10];
}; };
struct LGB_MAPRANGE_ENTRY : struct LGB_MAP_RANGE_ENTRY : public LgbEntry
public LGB_ENTRY
{ {
public: public:
LGB_MAPRANGE_HEADER header; MapRangeData header;
std::string name; std::string name;
LGB_MAPRANGE_ENTRY( char* buf, uint32_t offset ) : LGB_MAP_RANGE_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_MAPRANGE_HEADER* >( buf + offset ); header = *reinterpret_cast< MapRangeData* >( buf + offset );
name = std::string( buf + offset + header.nameOffset ); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
struct LGB_COLLISION_BOX_HEADER : struct LGB_COLLISION_BOX_HEADER :
public LGB_ENTRY_HEADER public InstanceObject
{ {
uint8_t unk[100]; uint8_t unk[100];
}; };
struct LGB_COLLISION_BOX_ENTRY : struct LGB_COLLISION_BOX_ENTRY :
public LGB_ENTRY public LgbEntry
{ {
LGB_COLLISION_BOX_HEADER header; LGB_COLLISION_BOX_HEADER header;
std::string name; std::string name;
LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) : LGB_COLLISION_BOX_ENTRY( char* buf, uint32_t offset ) :
LGB_ENTRY( buf, offset ) LgbEntry( buf, offset )
{ {
header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset ); header = *reinterpret_cast< LGB_COLLISION_BOX_HEADER* >( buf + offset );
header.type = LgbEntryType::CollisionBox; header.type = LgbEntryType::CollisionBox;
@ -305,7 +304,7 @@ struct LGB_GROUP
LGB_FILE* parent; LGB_FILE* parent;
LGB_GROUP_HEADER header; LGB_GROUP_HEADER header;
std::string name; std::string name;
std::vector< std::shared_ptr< LGB_ENTRY > > entries; std::vector< std::shared_ptr< LgbEntry > > entries;
LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset ) LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{ {

View file

@ -429,7 +429,7 @@ int main( int argc, char* argv[] )
} }
return true; return true;
}; };
auto exportSgbModel = [&]( const std::string& sgbFilePath, LGB_ENTRY* pGimmick, bool isEobj = false ) auto exportSgbModel = [&]( const std::string& sgbFilePath, LgbEntry* pGimmick, bool isEobj = false )
{ {
if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) ) if( auto pSgbFile = pCache->getSgbFile( sgbFilePath ) )
{ {

View file

@ -19,8 +19,10 @@
#include "Territory/Territory.h" #include "Territory/Territory.h"
#include "Territory/ZonePosition.h" #include "Territory/ZonePosition.h"
#include "Territory/InstanceContent.h" #include "Territory/InstanceContent.h"
#include "Territory/InstanceObjectCache.h"
#include "Territory/Land.h" #include "Territory/Land.h"
#include "Network/GameConnection.h" #include "Network/GameConnection.h"
#include "Network/PacketWrappers/ActorControlPacket.h" #include "Network/PacketWrappers/ActorControlPacket.h"
#include "Network/PacketWrappers/ActorControlSelfPacket.h" #include "Network/PacketWrappers/ActorControlSelfPacket.h"
@ -350,8 +352,27 @@ void Sapphire::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type )
} }
setStateFlag( PlayerStateFlag::BetweenAreas ); setStateFlag( PlayerStateFlag::BetweenAreas );
auto pInstanceObjectCache = m_pFw->get< InstanceObjectCache >();
auto targetPos = pTeriMgr->getTerritoryPosition( data->level.at( 0 ) ); auto targetPos = pTeriMgr->getTerritoryPosition( data->level.at( 0 ) );
auto pop = pInstanceObjectCache->getPopRange( data->territory, data->level[ 0 ] );
auto pop1 = pInstanceObjectCache->getPopRange( data->territory, data->level[ 1 ] );
if( pop )
{
sendDebug( "Teleport: popRange {0} found!", data->level.at( 0 ) );
}
else if( pop1 )
{
sendDebug( "Teleport: popRange {0} found!", data->level.at( 1 ) );
}
else
{
sendDebug( "Teleport: popRange not found!" );
}
Common::FFXIVARR_POSITION3 pos; Common::FFXIVARR_POSITION3 pos;
pos.x = 0; pos.x = 0;
pos.y = 0; pos.y = 0;

View file

@ -209,31 +209,10 @@ void Sapphire::World::Manager::DebugCommandMgr::set( char* data, Entity::Player&
sscanf( params.c_str(), "%i %i", &map_id, &discover_id ); sscanf( params.c_str(), "%i %i", &map_id, &discover_id );
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() ); auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().map_id = map_id; discoveryPacket->data().mapId = map_id;
discoveryPacket->data().map_part_id = discover_id; discoveryPacket->data().mapPartId = discover_id;
player.queuePacket( discoveryPacket ); player.queuePacket( discoveryPacket );
} }
else if( ( subCommand == "discovery_pos" ) && ( params != "" ) )
{
int32_t map_id;
int32_t discover_id;
int32_t pos_id;
sscanf( params.c_str(), "%i %i %i", &pos_id, &map_id, &discover_id );
std::string query2 = "UPDATE IGNORE `discoveryinfo` SET `discover_id` = '" + std::to_string( discover_id ) +
"' WHERE `discoveryinfo`.`id` = " + std::to_string( pos_id ) + ";";
std::string query1 =
"INSERT IGNORE INTO `discoveryinfo` (`id`, `map_id`, `discover_id`) VALUES ('" + std::to_string( pos_id ) +
"', '" + std::to_string( map_id ) +
"', '" + std::to_string( discover_id ) + "')";
pDb->execute( query1 );
pDb->execute( query2 );
}
else if( subCommand == "discovery_reset" ) else if( subCommand == "discovery_reset" )
{ {
player.resetDiscovery(); player.resetDiscovery();

View file

@ -9,6 +9,9 @@
#include <Database/DatabaseDef.h> #include <Database/DatabaseDef.h>
#include <Util/Util.h> #include <Util/Util.h>
#include <datReader/DatCategories/bg/LgbTypes.h>
#include <datReader/DatCategories/bg/Lgb.h>
#include <unordered_map> #include <unordered_map>
#include <Network/PacketDef/Zone/ClientZoneDef.h> #include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Logging/Logger.h> #include <Logging/Logger.h>
@ -20,6 +23,7 @@
#include "Territory/Land.h" #include "Territory/Land.h"
#include "Territory/ZonePosition.h" #include "Territory/ZonePosition.h"
#include "Territory/House.h" #include "Territory/House.h"
#include "Territory/InstanceObjectCache.h"
#include "Network/PacketWrappers/PlayerSetupPacket.h" #include "Network/PacketWrappers/PlayerSetupPacket.h"
#include "Network/PacketWrappers/PingPacket.h" #include "Network/PacketWrappers/PingPacket.h"
@ -274,22 +278,56 @@ void Sapphire::Network::GameConnection::zoneLineHandler( FrameworkPtr pFw,
const Packets::FFXIVARR_PACKET_RAW& inPacket, const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player ) Entity::Player& player )
{ {
auto pTeriMgr = pFw->get< TerritoryMgr >();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcZoneLineHandler >( inPacket ); const auto packet = ZoneChannelPacket< Client::FFXIVIpcZoneLineHandler >( inPacket );
const auto zoneLineId = packet.data().zoneLineId; const auto zoneLineId = packet.data().zoneLineId;
auto pTeriMgr = pFw->get< TerritoryMgr >();
auto pInstanceObjectCache = pFw->get< InstanceObjectCache >();
auto tInfo = player.getCurrentTerritory()->getTerritoryTypeInfo();
auto pExitRange = pInstanceObjectCache->getExitRange( player.getTerritoryTypeId(), zoneLineId );
Common::FFXIVARR_POSITION3 targetPos{};
uint32_t targetZone;
if( pExitRange )
{
player.sendDebug( "Found ExitRange#{0}", zoneLineId );
player.sendDebug( "destTerritoryType#{0}", pExitRange->header.destTerritoryType );
player.sendDebug( "destInstanceObjectId#{0}", pExitRange->header.destInstanceObjectId );
auto pPopRange = pInstanceObjectCache->getPopRange( pExitRange->header.destTerritoryType,
pExitRange->header.destInstanceObjectId );
if( pPopRange )
{
targetZone = pExitRange->header.destTerritoryType;
player.sendDebug( "\tFound PopRange#{0}", pExitRange->header.destInstanceObjectId );
player.sendDebug( "\t{0}", pPopRange->header.transform.translation.x );
player.sendDebug( "\t{0}", pPopRange->header.transform.translation.y );
player.sendDebug( "\t{0}", pPopRange->header.transform.translation.z );
targetPos = Common::FFXIVARR_POSITION3 { pPopRange->header.transform.translation.x,
pPopRange->header.transform.translation.y,
pPopRange->header.transform.translation.z };
player.sendDebug( "ZoneLine #{0} found.", zoneLineId );
auto preparePacket = makeZonePacket< FFXIVIpcPrepareZoning >( player.getId() );
preparePacket->data().targetZone = pExitRange->header.destTerritoryType;
//ActorControlSelfPacket controlPacket( pPlayer, ActorControlType::DespawnZoneScreenMsg,
// 0x03, player.getId(), 0x01, targetZone );
player.queuePacket( preparePacket );
}
}
player.sendDebug( "Walking ZoneLine#{0}", zoneLineId ); player.sendDebug( "Walking ZoneLine#{0}", zoneLineId );
auto pZone = player.getCurrentTerritory(); auto pZone = player.getCurrentTerritory();
auto pLine = pTeriMgr->getTerritoryPosition( zoneLineId );
Common::FFXIVARR_POSITION3 targetPos{};
uint32_t targetZone;
float rotation = 0.0f; float rotation = 0.0f;
if( pLine != nullptr ) /* if( pLine != nullptr )
{ {
player.sendDebug( "ZoneLine #{0} found.", zoneLineId ); player.sendDebug( "ZoneLine #{0} found.", zoneLineId );
targetPos = pLine->getTargetPosition(); targetPos = pLine->getTargetPosition();
@ -311,7 +349,7 @@ void Sapphire::Network::GameConnection::zoneLineHandler( FrameworkPtr pFw,
targetPos.y = 0; targetPos.y = 0;
targetPos.z = 0; targetPos.z = 0;
targetZone = pZone->getTerritoryTypeId(); targetZone = pZone->getTerritoryTypeId();
} }*/
player.performZoning( targetZone, targetPos, rotation ); player.performZoning( targetZone, targetPos, rotation );
} }
@ -321,29 +359,23 @@ void Sapphire::Network::GameConnection::discoveryHandler( FrameworkPtr pFw,
const Packets::FFXIVARR_PACKET_RAW& inPacket, const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player ) Entity::Player& player )
{ {
auto pInstanceObjectCache = pFw->get< InstanceObjectCache >();
auto tInfo = player.getCurrentTerritory()->getTerritoryTypeInfo();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcDiscoveryHandler >( inPacket ); const auto packet = ZoneChannelPacket< Client::FFXIVIpcDiscoveryHandler >( inPacket );
const auto positionRef = packet.data().positionRef; const auto positionRef = packet.data().positionRef;
auto pDb = pFw->get< Db::DbWorkerPool< Db::ZoneDbConnection > >(); auto pRefInfo = pInstanceObjectCache->getMapRange( player.getTerritoryTypeId(), positionRef );
auto pQR = pDb->query( "SELECT id, map_id, discover_id "
"FROM discoveryinfo "
"WHERE id = " + std::to_string( positionRef ) + ";" );
if( !pQR->next() )
{
player.sendDebug( "Discovery ref pos id#{0} not found!", positionRef );
return;
}
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().map_id = pQR->getUInt( 2 );
discoveryPacket->data().map_part_id = pQR->getUInt( 3 );
player.queuePacket( discoveryPacket );
player.sendDebug( "Discovery ref pos id#{0}", positionRef ); player.sendDebug( "Discovery ref pos id#{0}", positionRef );
player.discover( pQR->getUInt16( 2 ), pQR->getUInt16( 3 ) ); if( pRefInfo )
{
auto discoveryPacket = makeZonePacket< FFXIVIpcDiscovery >( player.getId() );
discoveryPacket->data().mapId = tInfo->map;
discoveryPacket->data().mapPartId = pRefInfo->header.discoveryIndex;
player.queuePacket( discoveryPacket );
player.discover( tInfo->map, pRefInfo->header.discoveryIndex );
}
} }

View file

@ -44,6 +44,8 @@
#include "Manager/NaviMgr.h" #include "Manager/NaviMgr.h"
#include "Manager/ActionMgr.h" #include "Manager/ActionMgr.h"
#include "Territory/InstanceObjectCache.h"
using namespace Sapphire::World::Manager; using namespace Sapphire::World::Manager;
Sapphire::World::ServerMgr::ServerMgr( const std::string& configName, FrameworkPtr pFw ) : Sapphire::World::ServerMgr::ServerMgr( const std::string& configName, FrameworkPtr pFw ) :
@ -171,6 +173,10 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] )
} }
framework()->set< Scripting::ScriptMgr >( pScript ); framework()->set< Scripting::ScriptMgr >( pScript );
Logger::info( "Setting up InstanceObjectCache" );
auto pInstanceObjCache = std::make_shared< Sapphire::InstanceObjectCache >( framework() );
framework()->set< Sapphire::InstanceObjectCache >( pInstanceObjCache );
auto pActionMgr = std::make_shared< Manager::ActionMgr >( framework() ); auto pActionMgr = std::make_shared< Manager::ActionMgr >( framework() );
framework()->set< Manager::ActionMgr >( pActionMgr ); framework()->set< Manager::ActionMgr >( pActionMgr );

View file

@ -0,0 +1,118 @@
#include "InstanceObjectCache.h"
#include "Exd/ExdDataGenerated.h"
#include <Framework.h>
#include <datReader/DatCategories/bg/pcb.h>
#include <datReader/DatCategories/bg/lgb.h>
#include <datReader/DatCategories/bg/sgb.h>
#include <GameData.h>
#include <File.h>
#include <DatCat.h>
#include <ExdData.h>
#include <ExdCat.h>
#include <Exd.h>
Sapphire::InstanceObjectCache::InstanceObjectCache( std::shared_ptr< Framework > pFramework ) :
m_pFramework( pFramework )
{
auto pExd = pFramework->get< Sapphire::Data::ExdDataGenerated >();
auto idList = pExd->getTerritoryTypeIdList();
size_t count = 0;
for( const auto& id : idList )
{
// show some loading indication...
if( count++ % 10 == 0 )
std::cout << ".";
auto territoryType = pExd->get< Sapphire::Data::TerritoryType >( id );
if( !territoryType )
continue;
auto path = territoryType->bg;
if( path.empty() )
continue;
// TODO: Horrible workaround... Fails if expansion is not installed
if( path.find( "ex3" ) != std::string::npos )
continue;
path = std::string( "bg/" ) + path.substr( 0, path.find( "/level/" ) );
// TODO: it does feel like this needs to be streamlined into the datReader instead of being done here...
std::string bgLgbPath( path + "/level/bg.lgb" );
std::string planmapLgbPath( path + "/level/planmap.lgb" );
std::vector< char > bgSection;
std::vector< char > planmapSection;
auto test_file = pExd->getGameData()->getFile( bgLgbPath );
bgSection = test_file->access_data_sections().at( 0 );
auto planmap_file = pExd->getGameData()->getFile( planmapLgbPath );
planmapSection = planmap_file->access_data_sections().at( 0 );
std::vector< std::string > stringList;
uint32_t offset1 = 0x20;
LGB_FILE bgLgb( &bgSection[ 0 ], "bg" );
LGB_FILE planmapLgb( &planmapSection[ 0 ], "planmap" );
std::vector< LGB_FILE > lgbList{ bgLgb, planmapLgb };
uint32_t max_index = 0;
for( const auto& lgb : lgbList )
{
for( const auto& group : lgb.groups )
{
for( const auto& pEntry : group.entries )
{
if( pEntry->getType() == LgbEntryType::MapRange )
{
auto pMapRange = reinterpret_cast< LGB_MAP_RANGE_ENTRY* >( pEntry.get() );
m_mapRangeCache.insert( id, *pMapRange );
}
else if( pEntry->getType() == LgbEntryType::ExitRange )
{
auto pExitRange = reinterpret_cast< LGB_EXIT_RANGE_ENTRY* >( pEntry.get() );
m_exitRangeCache.insert( id, *pExitRange);
}
else if( pEntry->getType() == LgbEntryType::PopRange )
{
if( pEntry->header.instanceId == 1359242 )
{
std::cout << ">>>" << id << "__" << static_cast< uint32_t >( pEntry->getType() ) << ">>>\n";
//break;
}
auto pPopRange = reinterpret_cast< LGB_POP_RANGE_ENTRY* >( pEntry.get() );
m_popRangeCache.insert( id, *pPopRange );
}
}
}
}
}
std::cout << "\n";
}
Sapphire::InstanceObjectCache::MapRangePtr
Sapphire::InstanceObjectCache::getMapRange( uint16_t zoneId, uint32_t mapRangeId )
{
return m_mapRangeCache.get( zoneId, mapRangeId );
}
Sapphire::InstanceObjectCache::ExitRangePtr
Sapphire::InstanceObjectCache::getExitRange( uint16_t zoneId, uint32_t exitRangeId )
{
return m_exitRangeCache.get( zoneId, exitRangeId );
}
Sapphire::InstanceObjectCache::PopRangePtr
Sapphire::InstanceObjectCache::getPopRange( uint16_t zoneId, uint32_t popRangeId )
{
return m_popRangeCache.get( zoneId, popRangeId );
}

View file

@ -0,0 +1,84 @@
#ifndef SAPPHIRE_INSTANCEOBJECTCACHE_H
#define SAPPHIRE_INSTANCEOBJECTCACHE_H
#include <memory>
#include <unordered_map>
struct LGB_MAP_RANGE_ENTRY;
struct LGB_EXIT_RANGE_ENTRY;
struct LGB_POP_RANGE_ENTRY;
namespace Sapphire
{
class Framework;
template< typename T >
class ObjectCache
{
using ObjectPtr = std::shared_ptr< T >;
using ObjectMap = std::unordered_map< uint32_t, ObjectPtr >;
using ZoneObjectCache = std::unordered_map< uint16_t, ObjectMap >;
ZoneObjectCache m_objectCache;
public:
ObjectPtr get( uint16_t zoneId, uint32_t id )
{
auto it = m_objectCache.find( zoneId );
if( it != m_objectCache.end() )
{
auto rangeIt = it->second.find( id );
if( rangeIt != it->second.end() )
{
return rangeIt->second;
}
}
return nullptr;
}
template< typename T >
void insert( uint16_t zoneId, T& entry )
{
auto pShared = std::make_shared< T >( entry );
if( m_objectCache.find( zoneId ) == m_objectCache.end() )
{
ObjectMap cache;
cache[ entry.header.instanceId ] = pShared;
m_objectCache[ zoneId ] = cache;
}
else
{
auto it = m_objectCache.find( zoneId );
it->second[ entry.header.instanceId ] = pShared;
}
}
};
class InstanceObjectCache
{
public:
using MapRangePtr = std::shared_ptr< LGB_MAP_RANGE_ENTRY >;
using ExitRangePtr = std::shared_ptr< LGB_EXIT_RANGE_ENTRY >;
using PopRangePtr = std::shared_ptr< LGB_POP_RANGE_ENTRY >;
InstanceObjectCache( std::shared_ptr< Framework > pFramework );
~InstanceObjectCache() = default;
MapRangePtr getMapRange( uint16_t zoneId, uint32_t mapRangeId );
ExitRangePtr getExitRange( uint16_t zoneId, uint32_t exitRangeId );
PopRangePtr getPopRange( uint16_t zoneId, uint32_t popRangeId );
private:
ObjectCache< LGB_MAP_RANGE_ENTRY > m_mapRangeCache;
ObjectCache< LGB_EXIT_RANGE_ENTRY > m_exitRangeCache;
ObjectCache< LGB_POP_RANGE_ENTRY > m_popRangeCache;
std::shared_ptr< Framework > m_pFramework;
};
}
#endif //SAPPHIRE_INSTANCEOBJECTCACHE_H