1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-30 05:07:46 +00:00

More friends list work; Get session from 64bits id;

This commit is contained in:
Maru 2018-03-17 21:43:24 -03:00
parent 5069bdd3e0
commit 86b7b62351
15 changed files with 679 additions and 583 deletions

View file

@ -47,3 +47,6 @@ ALTER TABLE `charainfo` CHANGE `Mounts` `Mounts` BINARY(15) NULL DEFAULT NULL;
ALTER TABLE `charainfo` CHANGE `Orchestrion` `Orchestrion` BINARY(40) NULL DEFAULT NULL; ALTER TABLE `charainfo` CHANGE `Orchestrion` `Orchestrion` BINARY(40) NULL DEFAULT NULL;
ALTER TABLE `charainfo` CHANGE `Minions` `Minions` BINARY(37) NULL DEFAULT NULL; ALTER TABLE `charainfo` CHANGE `Minions` `Minions` BINARY(37) NULL DEFAULT NULL;
ALTER TABLE `charainfo` CHANGE `QuestCompleteFlags` `QuestCompleteFlags` VARBINARY(396) NULL DEFAULT NULL; ALTER TABLE `charainfo` CHANGE `QuestCompleteFlags` `QuestCompleteFlags` VARBINARY(396) NULL DEFAULT NULL;
ALTER TABLE `charainfofriendlist` CHANGE `CharacterIdList` `CharacterIdList` VARBINARY(1600) NULL DEFAULT NULL;
ALTER TABLE `charainfofriendlist` CHANGE `InviteDataList` `InviteDataList` VARBINARY(1600) NULL DEFAULT NULL;

View file

@ -68,13 +68,13 @@ namespace Packets {
CFDutyInfo = 0x007A, CFDutyInfo = 0x007A,
CFPlayerInNeed = 0x007F, CFPlayerInNeed = 0x007F,
SocialRequestError = 0x00AD,
Playtime = 0x00DF, // updated 4.2 Playtime = 0x00DF, // updated 4.2
CFRegistered = 0x00B8, // updated 4.1 CFRegistered = 0x00B8, // updated 4.1
CancelAllianceForming = 0x00C6, // updated 4.2 CancelAllianceForming = 0x00C6, // updated 4.2
Chat = 0x00E1, // updated 4.2 Chat = 0x00E1, // updated 4.2
SocialRequestResponse = 0x00E5, // updated 4.1
SocialRequestError = 0x00E4, // updated 4.2
SocialRequestResponse = 0x00E5, // updated 4.2
SocialRequestReceive = 0x00E6, // updated 4.2 SocialRequestReceive = 0x00E6, // updated 4.2
SocialList = 0x00E7, // updated 4.2 SocialList = 0x00E7, // updated 4.2

View file

@ -101,6 +101,7 @@ struct PlayerEntry {
uint8_t one; uint8_t one;
char name[0x20]; char name[0x20];
char fcTag[5]; char fcTag[5];
uint32_t unknown_p1; // Added 4.2
}; };
struct FFXIVIpcSocialRequestReceive : FFXIVIpcBasePacket<SocialRequestReceive> struct FFXIVIpcSocialRequestReceive : FFXIVIpcBasePacket<SocialRequestReceive>
@ -123,6 +124,8 @@ struct FFXIVIpcSocialRequestReceive : FFXIVIpcBasePacket<SocialRequestReceive>
struct FFXIVIpcSocialRequestError : FFXIVIpcBasePacket<SocialRequestError> struct FFXIVIpcSocialRequestError : FFXIVIpcBasePacket<SocialRequestError>
{ {
uint32_t unknown_p1; // Added on 4.2, unknown. Possibly padding/crossworld related
uint32_t unknown_p2;
uint32_t messageId; // if 0 then type's message is used (type must 2/4/5 or it wont print) uint32_t messageId; // if 0 then type's message is used (type must 2/4/5 or it wont print)
Common::SocialCategory category; // 2 - friend request, 4 - fc petition, 5 - fc invitation, anything else and wont print Common::SocialCategory category; // 2 - friend request, 4 - fc petition, 5 - fc invitation, anything else and wont print
uint8_t unknown; // possibly padding uint8_t unknown; // possibly padding

View file

@ -2,19 +2,19 @@
#include "Aethernet.cpp" #include "Aethernet.cpp"
#include "Aetheryte.cpp" #include "Aetheryte.cpp"
#include "HouFurOrchestrion.cpp"
#include "CmnDefInnBed.cpp"
#include "CmnDefCutSceneReplay.cpp" #include "CmnDefCutSceneReplay.cpp"
#include "CmnDefInnBed.cpp"
#include "CmnDefLinkShell.cpp" #include "CmnDefLinkShell.cpp"
#include "HouFurOrchestrion.cpp"
const ScriptObject* ptrs[] = const ScriptObject* ptrs[] =
{ {
static_cast< ScriptObject* >( new Aethernet ), static_cast< ScriptObject* >( new Aethernet ),
static_cast< ScriptObject* >( new Aetheryte ), static_cast< ScriptObject* >( new Aetheryte ),
static_cast< ScriptObject* >( new HouFurOrchestrion ),
static_cast< ScriptObject* >( new CmnDefInnBed ),
static_cast< ScriptObject* >( new CmnDefCutSceneReplay ), static_cast< ScriptObject* >( new CmnDefCutSceneReplay ),
static_cast< ScriptObject* >( new CmnDefInnBed ),
static_cast< ScriptObject* >( new CmnDefLinkShell ), static_cast< ScriptObject* >( new CmnDefLinkShell ),
static_cast< ScriptObject* >( new HouFurOrchestrion ),
nullptr nullptr
}; };

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,13 @@
#include <Script/NativeScriptApi.h> #include <Script/NativeScriptApi.h>
#include "OpeningLimsa.cpp"
#include "OpeningGridania.cpp" #include "OpeningGridania.cpp"
#include "OpeningLimsa.cpp"
#include "OpeningUldah.cpp" #include "OpeningUldah.cpp"
const ScriptObject* ptrs[] = const ScriptObject* ptrs[] =
{ {
static_cast< ScriptObject* >( new OpeningLimsa ),
static_cast< ScriptObject* >( new OpeningGridania ), static_cast< ScriptObject* >( new OpeningGridania ),
static_cast< ScriptObject* >( new OpeningLimsa ),
static_cast< ScriptObject* >( new OpeningUldah ), static_cast< ScriptObject* >( new OpeningUldah ),
nullptr nullptr

View file

@ -1,32 +1,32 @@
#include <Script/NativeScriptApi.h> #include <Script/NativeScriptApi.h>
#include "ManFst004.cpp" #include "ManFst001.cpp"
#include "ManSea002.cpp"
#include "ManFst002.cpp" #include "ManFst002.cpp"
#include "ManFst003.cpp" #include "ManFst003.cpp"
#include "ManFst004.cpp"
#include "ManSea001.cpp"
#include "ManSea002.cpp"
#include "ManWil001.cpp" #include "ManWil001.cpp"
#include "ManWil002.cpp" #include "ManWil002.cpp"
#include "ManFst001.cpp"
#include "subquest/gridania/SubFst002.cpp"
#include "subquest/gridania/SubFst013.cpp"
#include "subquest/gridania/SubFst001.cpp" #include "subquest/gridania/SubFst001.cpp"
#include "subquest/gridania/SubFst002.cpp"
#include "subquest/gridania/SubFst010.cpp" #include "subquest/gridania/SubFst010.cpp"
#include "ManSea001.cpp" #include "subquest/gridania/SubFst013.cpp"
const ScriptObject* ptrs[] = const ScriptObject* ptrs[] =
{ {
static_cast< ScriptObject* >( new ManFst004 ), static_cast< ScriptObject* >( new ManFst001 ),
static_cast< ScriptObject* >( new ManSea002 ),
static_cast< ScriptObject* >( new ManFst002 ), static_cast< ScriptObject* >( new ManFst002 ),
static_cast< ScriptObject* >( new ManFst003 ), static_cast< ScriptObject* >( new ManFst003 ),
static_cast< ScriptObject* >( new ManFst004 ),
static_cast< ScriptObject* >( new ManSea001 ),
static_cast< ScriptObject* >( new ManSea002 ),
static_cast< ScriptObject* >( new ManWil001 ), static_cast< ScriptObject* >( new ManWil001 ),
static_cast< ScriptObject* >( new ManWil002 ), static_cast< ScriptObject* >( new ManWil002 ),
static_cast< ScriptObject* >( new ManFst001 ),
static_cast< ScriptObject* >( new SubFst002 ),
static_cast< ScriptObject* >( new SubFst013 ),
static_cast< ScriptObject* >( new SubFst001 ), static_cast< ScriptObject* >( new SubFst001 ),
static_cast< ScriptObject* >( new SubFst002 ),
static_cast< ScriptObject* >( new SubFst010 ), static_cast< ScriptObject* >( new SubFst010 ),
static_cast< ScriptObject* >( new ManSea001 ), static_cast< ScriptObject* >( new SubFst013 ),
nullptr nullptr
}; };

View file

@ -372,8 +372,8 @@ namespace Core {
void PlayerMinimal::createFriendsListContainer( uint32_t characterId ) const void PlayerMinimal::createFriendsListContainer( uint32_t characterId ) const
{ {
// todo: check if size is a-ok // todo: check if size is a-ok
std::vector< uint8_t > friendsList( 800 ); std::vector< uint8_t > friendsList( 1600 );
std::vector< uint8_t > inviteDateList( 800 ); std::vector< uint8_t > inviteDateList( 1600 );
auto stmtCreateFrnList = g_charaDb.getPreparedStatement( Db::CHARA_SOCIAL_FRIENDS_INS ); auto stmtCreateFrnList = g_charaDb.getPreparedStatement( Db::CHARA_SOCIAL_FRIENDS_INS );
stmtCreateFrnList->setInt( 1, characterId ); stmtCreateFrnList->setInt( 1, characterId );

View file

@ -501,6 +501,18 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket
i++; i++;
} }
for ( auto invite : playerFriendsList->getInvites() )
{
// more elegant way to break over list entries pls
if ( i == 10 )
break;
g_fw.get< Logger >()->debug( "aaa" + std::to_string( i ) );
// todo: replace this with call for generating the entire vector
listPacket.data().entries[i] = Core::Social::FriendList::generatePlayerEntry( invite, true );
i++;
}
queueOutPacket( listPacket ); queueOutPacket( listPacket );
} }
@ -571,18 +583,14 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
auto pSession = g_fw.get< ServerZone >()->getSession( name ); auto pSession = g_fw.get< ServerZone >()->getSession( name );
// only the requester needs the response // Variable for error logging and control
ZoneChannelPacket< FFXIVIpcSocialRequestError > response( player.getId() ); uint32_t logMessage = 0;
memcpy( &( response.data().name ), name.c_str(), 32 );
// todo: enumerate log messages // only the requester needs the response
response.data().messageId = 319; // That name does not exist. Please confirm the spelling.
response.data().category = category;
// todo: enumerate and move each of these cases into their classes? // todo: enumerate and move each of these cases into their classes?
if( pSession ) if( pSession )
{ {
bool successful = false;
Entity::PlayerPtr pRecipient = pSession->getPlayer(); Entity::PlayerPtr pRecipient = pSession->getPlayer();
std::array< std::string, 5 > typeVar{ "", "PartyInvite", "FriendInvite", "FreeCompanyPetition", "FreeCompanyInvite" }; std::array< std::string, 5 > typeVar{ "", "PartyInvite", "FriendInvite", "FreeCompanyPetition", "FreeCompanyInvite" };
@ -600,12 +608,13 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
} }
return; return;
}*/ }*/
/*
if( pRecipient->getId() == player.getId() ) if( pRecipient->getId() == player.getId() )
{ {
response.data().messageId = 321; // Unable to invite. response.data().messageId = 321; // Unable to invite.
} }
*/
switch( category ) switch( category )
{ {
// party invite // party invite
@ -626,19 +635,15 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
}*/ }*/
if( !pRecipient->isLoadingComplete() ) // || pRecipient->getDuty() ) if( !pRecipient->isLoadingComplete() ) // || pRecipient->getDuty() )
{ {
response.data().messageId = 331; // Unable to invite. That player is currently bound by duty or in a different area. logMessage = 331; // Unable to invite. That player is currently bound by duty or in a different area.
} }
else if( pRecipient->getOnlineStatus() == Common::OnlineStatus::Busy ) else if( pRecipient->getOnlineStatus() == Common::OnlineStatus::Busy )
{ {
response.data().messageId = 334; // Unable to send party invite. Player's online status is set to Busy. logMessage = 334; // Unable to send party invite. Player's online status is set to Busy.
} }
else if( pRecipient->getOnlineStatus() == Common::OnlineStatus::ViewingCutscene ) else if( pRecipient->getOnlineStatus() == Common::OnlineStatus::ViewingCutscene )
{ {
response.data().messageId = 336; // Unable to invite. That player is currently watching a cutscene. logMessage = 336; // Unable to invite. That player is currently watching a cutscene.
}
else
{
successful = true;
} }
// response.data().messageId = 62; // <name> declines the party invite. // response.data().messageId = 62; // <name> declines the party invite.
} }
@ -647,23 +652,36 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
case Common::SocialCategory::Friends: case Common::SocialCategory::Friends:
{ {
// todo: check if already on friends list or invite pending // todo: check if already on friends list or invite pending
/*
auto playerFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pPlayer->getgetFriendsListId() );
if( playerFriendsList ) auto recipientId = pRecipient->getId();
auto senderId = player.getId();
auto senderFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( player.getFriendsListId() );
auto recipientFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pRecipient->getFriendsListId() );
// If any of these are true, an error has occured.
if( senderFriendsList->hasInvite( recipientId ) || senderFriendsList->hasMember( recipientId ) )
{ {
response.data().messageId = 312; // That player is already a friend or has been sent a request. logMessage = 312; // That player is already a friend or has been sent a request.
} }
else if( pRecipient->getFriendList()->getSize() >= 200 ) else if( senderFriendsList->getTotalSize() >= senderFriendsList->getCapacity() )
{ {
response.data().messageId = 314; // Unable to send friend request. The other player's friend list is full. logMessage = 313; // Your friend list is full.
} }
else if( pPlayer->getFriendList()->getSize() >= 200 ) else if( recipientFriendsList->getTotalSize() >= recipientFriendsList->getCapacity() )
{ {
response.data().messageId = 313; // Your friend list is full. logMessage = 314; // Unable to send friend request. The other player's friend list is full.
} }
*/ else if( pRecipient->getOnlineStatus() == Common::OnlineStatus::Busy )
successful = true; {
logMessage = 316; // Unable to send friend request. Player's online status is set to Busy.
}
else
{
// Catch any other, unreported mess
logMessage = senderFriendsList->addInvite( recipientId );
}
} }
break; break;
@ -671,7 +689,8 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
break; break;
} }
if( successful ) // No errors reported
if( logMessage == 0 )
{ {
ZoneChannelPacket< FFXIVIpcSocialRequestReceive > packet( player.getId(), pRecipient->getId() ); ZoneChannelPacket< FFXIVIpcSocialRequestReceive > packet( player.getId(), pRecipient->getId() );
@ -703,8 +722,6 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
auto recipientFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pRecipient->getFriendsListId() ); auto recipientFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pRecipient->getFriendsListId() );
auto senderResultPacketResult = recipientFriendsList->addInvite( pRecipient->getId() );
recipientFriendsList->addInvite( player.getId() ); recipientFriendsList->addInvite( player.getId() );
auto senderResultPacket = GamePacketNew< Server::FFXIVIpcSocialRequestResponse, ServerZoneIpcType >( pRecipient->getId(), player.getId() ); auto senderResultPacket = GamePacketNew< Server::FFXIVIpcSocialRequestResponse, ServerZoneIpcType >( pRecipient->getId(), player.getId() );
@ -722,11 +739,23 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
g_fw.get< Logger >()->debug( "he HAA HAAA" ); g_fw.get< Logger >()->debug( "he HAA HAAA" );
} }
response.data().messageId = typeMessage[category]; //response.data().messageId = typeMessage[category];
}
else
{
ZoneChannelPacket< FFXIVIpcSocialRequestError > error( player.getId() );
memcpy( &( error.data().name ), name.c_str(), 32 );
// todo: enumerate log messages
error.data().messageId = logMessage; // That name does not exist. Please confirm the spelling.
error.data().category = category;
// Errors have happened. Send it back only to requester
player.queuePacket( error );
} }
} }
player.queuePacket( response ); //player.queuePacket( response );
// todo: handle party, friend request // todo: handle party, friend request
g_fw.get< Logger >()->debug( "sent to " + name ); g_fw.get< Logger >()->debug( "sent to " + name );
} }

View file

@ -338,6 +338,7 @@ bool Core::ServerZone::createSession( uint32_t sessionId )
} }
m_sessionMapByName[newSession->getPlayer()->getName()] = newSession; m_sessionMapByName[newSession->getPlayer()->getName()] = newSession;
m_sessionMapByContentId[newSession->getPlayer()->getContentId()] = newSession;
return true; return true;
@ -369,6 +370,18 @@ Core::SessionPtr Core::ServerZone::getSession( uint32_t id )
return nullptr; return nullptr;
} }
Core::SessionPtr Core::ServerZone::getSession( uint64_t contentId )
{
//std::lock_guard<std::mutex> lock( m_sessionMutex );
auto it = m_sessionMapById.find( contentId );
if( it != m_sessionMapById.end() )
return ( it->second );
return nullptr;
}
Core::SessionPtr Core::ServerZone::getSession( std::string playerName ) Core::SessionPtr Core::ServerZone::getSession( std::string playerName )
{ {
//std::lock_guard<std::mutex> lock( m_sessionMutex ); //std::lock_guard<std::mutex> lock( m_sessionMutex );

View file

@ -26,6 +26,7 @@ namespace Core {
bool loadSettings( int32_t argc, char* argv[] ); bool loadSettings( int32_t argc, char* argv[] );
SessionPtr getSession( uint32_t id ); SessionPtr getSession( uint32_t id );
SessionPtr getSession( uint64_t contentId );
SessionPtr getSession( std::string playerName ); SessionPtr getSession( std::string playerName );
void updateSession( uint32_t id ); void updateSession( uint32_t id );
void updateSession( std::string playerName ); void updateSession( std::string playerName );
@ -52,6 +53,7 @@ namespace Core {
std::mutex m_sessionMutex; std::mutex m_sessionMutex;
std::map< uint32_t, SessionPtr > m_sessionMapById; std::map< uint32_t, SessionPtr > m_sessionMapById;
std::map< uint64_t, SessionPtr > m_sessionMapByContentId;
std::map< std::string, SessionPtr > m_sessionMapByName; std::map< std::string, SessionPtr > m_sessionMapByName;
std::map< uint32_t, uint32_t > m_zones; std::map< uint32_t, uint32_t > m_zones;

View file

@ -24,6 +24,35 @@ using namespace Core::Network::Packets::Server;
using namespace Core::Social; using namespace Core::Social;
/*
uint32_t Group::addInvite( uint64_t characterId )
{
assert( characterId != 0 );
uint32_t logMessage = 0;
g_fw.get< Logger >()->debug( "here" );
if( m_groupMembers.find( characterId ) != m_groupMembers.end() || m_groupInvites.find( characterId ) != m_groupInvites.end() )
{
// That player is already a friend or has been sent a request.
logMessage = 312;
return logMessage;
}
if( getTotalSize() >= getCapacity() )
{
// Unable to send friend request. The other player's friend list is full.
logMessage = 314;
return logMessage;
}
m_groupInvites.insert( characterId );
return logMessage;
}
*/
std::vector< PlayerEntry > Core::Social::FriendList::getFriendListEntries( uint16_t entryAmount ) std::vector< PlayerEntry > Core::Social::FriendList::getFriendListEntries( uint16_t entryAmount )
{ {
std::vector< PlayerEntry > entryList = {}; std::vector< PlayerEntry > entryList = {};
@ -63,14 +92,15 @@ Core::Network::Packets::Server::PlayerEntry FriendList::generatePlayerEntry( uin
Core::Network::Packets::Server::PlayerEntry entry = {}; Core::Network::Packets::Server::PlayerEntry entry = {};
entry.contentId = characterId; entry.contentId = characterId;
entry.timestamp = 1512799339; entry.timestamp = 1517767262;
// todo: if invite change these // todo: if invite change these
entry.status = 2;
entry.status = 16;
entry.unknown = 0; entry.unknown = 0;
//entry.entryIcon = 0xf; //entry.entryIcon = 0xf;
entry.unavailable = 0; // unavailable (other world) entry.unavailable = 0; // unavailable (other world)
entry.one = 0; entry.one = 1;
if ( pSession ) if ( pSession )
{ {
@ -83,7 +113,7 @@ Core::Network::Packets::Server::PlayerEntry FriendList::generatePlayerEntry( uin
entry.classJob = pPlayer->getClass(); entry.classJob = pPlayer->getClass();
entry.level = pPlayer->getLevel(); entry.level = pPlayer->getLevel();
entry.zoneId = pPlayer->getCurrentZone()->getGuId(); entry.zoneId = pPlayer->getCurrentZone()->getTerritoryId();
entry.grandCompany = pPlayer->getGc(); entry.grandCompany = pPlayer->getGc();
memcpy( &entry.fcTag[0], "Meme", 4 ); memcpy( &entry.fcTag[0], "Meme", 4 );
entry.clientLanguage = 2; entry.clientLanguage = 2;

View file

@ -22,8 +22,6 @@ using namespace Core::Network;
// todo: invite map in g_serverZone.getGroupMgr(GroupType) and look up // todo: invite map in g_serverZone.getGroupMgr(GroupType) and look up
uint32_t Group::addMember( uint64_t characterId ) uint32_t Group::addMember( uint64_t characterId )
{ {
assert( characterId != 0 ); assert( characterId != 0 );
@ -32,7 +30,7 @@ uint32_t Group::addMember( uint64_t characterId )
m_groupMembers.insert( characterId ); m_groupMembers.insert( characterId );
return 0; return logMessage;
} }
uint32_t Group::addInvite( uint64_t characterId ) uint32_t Group::addInvite( uint64_t characterId )
@ -43,7 +41,17 @@ uint32_t Group::addInvite( uint64_t characterId )
m_groupInvites.insert( characterId ); m_groupInvites.insert( characterId );
return 0; return logMessage;
}
bool Group::hasMember( uint64_t memberId ) const
{
return m_groupMembers.find( memberId ) != m_groupMembers.end();
}
bool Group::hasInvite( uint64_t inviteId ) const
{
return m_groupInvites.find( inviteId ) != m_groupInvites.end();
} }
Core::Network::Packets::GamePacketPtr Group::processInvite( uint64_t recipientId, uint64_t senderId ) Core::Network::Packets::GamePacketPtr Group::processInvite( uint64_t recipientId, uint64_t senderId )

View file

@ -80,6 +80,10 @@ public:
/*! get total size of group (members + invites) */ /*! get total size of group (members + invites) */
uint32_t Group::getTotalSize() const; uint32_t Group::getTotalSize() const;
bool hasMember( uint64_t memberId ) const;
bool hasInvite( uint64_t inviteId ) const;
protected: protected:
GroupType m_type{ GroupType::None }; GroupType m_type{ GroupType::None };
uint64_t m_id{ 0 }; uint64_t m_id{ 0 };

View file

@ -131,7 +131,11 @@ uint64_t Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( u
if ( inData.size() ) if ( inData.size() )
{ {
std::vector< uint64_t > list( inData.size() / 8 ); std::vector< uint64_t > list( inData.size() / 8 );
outList.insert( list.begin(), list.end() ); // todo: fix this garbage. maybe get rid of lambda altogether
if( list.at( 0 ) != 0 )
{
outList.insert( list.begin(), list.end() );
}
} }
}; };