This commit is contained in:
RipleyTom 2023-04-01 21:52:07 +02:00 committed by Megamouse
parent d3298c422b
commit 03761c5dd4
16 changed files with 3865 additions and 1781 deletions

View File

@ -3085,18 +3085,7 @@ error_code sceNpManagerGetNetworkTime(vm::ptr<CellRtcTick> pTick)
return SCE_NP_ERROR_INVALID_STATE;
}
vm::var<s64> sec;
vm::var<s64> nsec;
error_code ret = sys_time_get_current_time(sec, nsec);
if (ret != CELL_OK)
{
return ret;
}
// Taken from cellRtc
pTick->tick = *nsec / 1000 + *sec * cellRtcGetTickResolution() + 62135596800000000ULL;
pTick->tick = nph.get_network_time();
return CELL_OK;
}
@ -3974,7 +3963,9 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout)
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (static_cast<u32>(ctxId) >= score_transaction_ctx::id_base)
const u32 idm_id = static_cast<u32>(ctxId);
if (idm_id >= score_transaction_ctx::id_base && idm_id < (score_transaction_ctx::id_base + score_transaction_ctx::id_count))
{
auto trans = idm::get<score_transaction_ctx>(ctxId);
if (!trans)
@ -3983,7 +3974,7 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout)
}
trans->timeout = timeout;
}
else
else if (idm_id >= score_ctx::id_base && idm_id < (score_ctx::id_base + score_ctx::id_count))
{
auto score = idm::get<score_ctx>(ctxId);
if (!ctxId)
@ -3992,6 +3983,10 @@ error_code sceNpScoreSetTimeout(s32 ctxId, usecond_t timeout)
}
score->timeout = timeout;
}
else
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ID;
}
return CELL_OK;
}
@ -4073,7 +4068,7 @@ error_code sceNpScorePollAsync(s32 transId, vm::ptr<s32> result)
return SCE_NP_COMMUNITY_ERROR_INVALID_ID;
}
auto res = trans->get_score_transaction_status();
auto res = trans->get_transaction_status();
if (!res)
{
@ -4790,7 +4785,7 @@ error_code sceNpScoreAbortTransaction(s32 transId)
return SCE_NP_COMMUNITY_ERROR_INVALID_ID;
}
trans->abort_score_transaction();
trans->abort_transaction();
return CELL_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -61,8 +61,8 @@ struct SceNpTusVariable
{
SceNpId ownerId;
be_t<s32> hasData;
u8 pad[4];
CellRtcTick lastChangedDate;
u8 pad[4];
SceNpId lastChangedAuthorId;
be_t<s64> variable;
be_t<s64> oldVariable;
@ -84,7 +84,7 @@ struct SceNpTusDataStatus
be_t<s32> hasData;
CellRtcTick lastChangedDate;
SceNpId lastChangedAuthorId;
be_t<u32> data;
vm::bptr<void> data;
be_t<u32> dataSize;
u8 pad[4];
SceNpTusDataInfo info;

View File

@ -181,7 +181,7 @@ public:
static constexpr auto thread_name = "Tcp Over Udp Timeout Manager Thread"sv;
private:
atomic_t<u32> wakey;
atomic_t<u32> wakey = 0;
shared_mutex data_mutex;
// List of outgoing messages
struct message

View File

@ -167,7 +167,7 @@ namespace np
get_resp->roomDataExternalNum = resp->rooms() ? resp->rooms()->size() : 0;
SceNpMatching2RoomDataExternal* prev_room = nullptr;
for (std::size_t i = 0; i < get_resp->roomDataExternalNum; i++)
for (flatbuffers::uoffset_t i = 0; i < get_resp->roomDataExternalNum; i++)
{
auto* fb_room = resp->rooms()->Get(i);
SceNpMatching2RoomDataExternal* cur_room;

View File

@ -1,282 +1,282 @@
table BinAttr {
id:uint16;
data:[uint8];
id:uint16;
data:[uint8];
}
table IntAttr {
id:uint16;
num:uint32;
id:uint16;
num:uint32;
}
table RoomMemberBinAttrInternal {
updateDate:uint64;
data:BinAttr;
updateDate:uint64;
data:BinAttr;
}
table BinAttrInternal {
updateDate:uint64;
updateMemberId:uint16;
data:BinAttr;
updateDate:uint64;
updateMemberId:uint16;
data:BinAttr;
}
table OptParam {
type:uint8;
flag:uint8;
hubMemberId:uint16 ;
type:uint8;
flag:uint8;
hubMemberId:uint16 ;
}
table GroupConfig {
slotNum:uint32;
withLabel:bool;
label:[uint8];
withPassword:bool;
slotNum:uint32;
withLabel:bool;
label:[uint8];
withPassword:bool;
}
table UserInfo2 {
npId:string;
onlineName:string;
avatarUrl:string;
npId:string;
onlineName:string;
avatarUrl:string;
}
table RoomMemberDataInternal {
userInfo:UserInfo2;
joinDate:uint64;
memberId:uint16;
teamId:uint8;
roomGroup:RoomGroup;
natType:uint8;
flagAttr:uint32;
roomMemberBinAttrInternal:[RoomMemberBinAttrInternal];
userInfo:UserInfo2;
joinDate:uint64;
memberId:uint16;
teamId:uint8;
roomGroup:RoomGroup;
natType:uint8;
flagAttr:uint32;
roomMemberBinAttrInternal:[RoomMemberBinAttrInternal];
}
table RoomGroup {
groupId:uint8;
withPassword:bool;
withLabel:bool;
label:[uint8];
slotNum:uint32;
curGroupMemberNum:uint32;
groupId:uint8;
withPassword:bool;
withLabel:bool;
label:[uint8];
slotNum:uint32;
curGroupMemberNum:uint32;
}
table RoomDataInternal {
serverId:uint16;
worldId:uint32;
lobbyId:uint64;
roomId:uint64;
passwordSlotMask:uint64;
maxSlot:uint32;
memberList:[RoomMemberDataInternal];
ownerId:uint16;
roomGroup:[RoomGroup];
flagAttr:uint32;
roomBinAttrInternal:[BinAttrInternal];
serverId:uint16;
worldId:uint32;
lobbyId:uint64;
roomId:uint64;
passwordSlotMask:uint64;
maxSlot:uint32;
memberList:[RoomMemberDataInternal];
ownerId:uint16;
roomGroup:[RoomGroup];
flagAttr:uint32;
roomBinAttrInternal:[BinAttrInternal];
}
table RoomDataExternal {
serverId:uint16;
worldId:uint32;
publicSlotNum:uint16;
privateSlotNum:uint16;
lobbyId:uint64;
roomId:uint64;
openPublicSlotNum:uint16;
maxSlot:uint16;
openPrivateSlotNum:uint16;
curMemberNum:uint16;
passwordSlotMask:uint64;
owner:UserInfo2;
roomGroup:[RoomGroup];
flagAttr:uint32;
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
serverId:uint16;
worldId:uint32;
publicSlotNum:uint16;
privateSlotNum:uint16;
lobbyId:uint64;
roomId:uint64;
openPublicSlotNum:uint16;
maxSlot:uint16;
openPrivateSlotNum:uint16;
curMemberNum:uint16;
passwordSlotMask:uint64;
owner:UserInfo2;
roomGroup:[RoomGroup];
flagAttr:uint32;
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
}
table IntSearchFilter {
searchOperator:uint8;
attr:IntAttr;
searchOperator:uint8;
attr:IntAttr;
}
table BinSearchFilter {
searchOperator:uint8;
attr:BinAttr;
searchOperator:uint8;
attr:BinAttr;
}
table PresenceOptionData {
data:[uint8];
len:uint32;
data:[uint8];
len:uint32;
}
table RoomGroupPasswordConfig {
groupId:[uint8];
withPassword:bool;
groupId:[uint8];
withPassword:bool;
}
table SearchRoomRequest {
option:int32;
worldId:uint32;
lobbyId:uint64;
rangeFilter_startIndex:uint32;
rangeFilter_max:uint32;
flagFilter:uint32;
flagAttr:uint32;
intFilter:[IntSearchFilter];
binFilter:[BinSearchFilter];
attrId:[uint16];
option:int32;
worldId:uint32;
lobbyId:uint64;
rangeFilter_startIndex:uint32;
rangeFilter_max:uint32;
flagFilter:uint32;
flagAttr:uint32;
intFilter:[IntSearchFilter];
binFilter:[BinSearchFilter];
attrId:[uint16];
}
table SearchRoomResponse {
startIndex:uint32;
total:uint32;
size:uint32;
rooms:[RoomDataExternal];
startIndex:uint32;
total:uint32;
size:uint32;
rooms:[RoomDataExternal];
}
table CreateJoinRoomRequest {
worldId:uint32;
lobbyId:uint64;
maxSlot:uint32;
flagAttr:uint32;
roomBinAttrInternal:[BinAttr];
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
roomPassword:[uint8];
groupConfig:[GroupConfig];
passwordSlotMask:uint64;
allowedUser:[string];
blockedUser:[string];
worldId:uint32;
lobbyId:uint64;
maxSlot:uint32;
flagAttr:uint32;
roomBinAttrInternal:[BinAttr];
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
roomPassword:[uint8];
groupConfig:[GroupConfig];
passwordSlotMask:uint64;
allowedUser:[string];
blockedUser:[string];
joinRoomGroupLabel:[uint8];
roomMemberBinAttrInternal:[BinAttr];
teamId:uint8;
sigOptParam:OptParam;
joinRoomGroupLabel:[uint8];
roomMemberBinAttrInternal:[BinAttr];
teamId:uint8;
sigOptParam:OptParam;
}
table JoinRoomRequest {
roomId:uint64;
roomPassword:[uint8];
joinRoomGroupLabel:[uint8];
roomMemberBinAttrInternal:[BinAttr];
optData:PresenceOptionData;
teamId:uint8;
roomId:uint64;
roomPassword:[uint8];
joinRoomGroupLabel:[uint8];
roomMemberBinAttrInternal:[BinAttr];
optData:PresenceOptionData;
teamId:uint8;
}
table LeaveRoomRequest {
roomId:uint64;
optData:PresenceOptionData;
roomId:uint64;
optData:PresenceOptionData;
}
table GetRoomDataExternalListRequest {
roomIds:[uint64];
attrIds:[uint16];
roomIds:[uint64];
attrIds:[uint16];
}
table GetRoomDataExternalListResponse {
rooms:[RoomDataExternal];
rooms:[RoomDataExternal];
}
table SetRoomDataExternalRequest {
roomId:uint64;
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
roomId:uint64;
roomSearchableIntAttrExternal:[IntAttr];
roomSearchableBinAttrExternal:[BinAttr];
roomBinAttrExternal:[BinAttr];
}
table SetRoomDataInternalRequest {
roomId:uint64;
flagFilter:uint32;
flagAttr:uint32;
roomBinAttrInternal:[BinAttr];
passwordConfig:[RoomGroupPasswordConfig];
passwordSlotMask:uint64;
ownerPrivilegeRank:[uint16];
roomId:uint64;
flagFilter:uint32;
flagAttr:uint32;
roomBinAttrInternal:[BinAttr];
passwordConfig:[RoomGroupPasswordConfig];
passwordSlotMask:uint64;
ownerPrivilegeRank:[uint16];
}
table SetRoomMemberDataInternalRequest {
roomId:uint64;
memberId:uint16;
teamId:uint8;
roomMemberBinAttrInternal:[BinAttr];
roomId:uint64;
memberId:uint16;
teamId:uint8;
roomMemberBinAttrInternal:[BinAttr];
}
table GetRoomDataInternalRequest {
roomId:uint64;
attrId:[uint16];
roomId:uint64;
attrId:[uint16];
}
table RoomMemberUpdateInfo {
roomMemberDataInternal:RoomMemberDataInternal;
eventCause:uint8;
optData:PresenceOptionData;
roomMemberDataInternal:RoomMemberDataInternal;
eventCause:uint8;
optData:PresenceOptionData;
}
table RoomUpdateInfo {
eventCause:uint8;
errorCode:int32;
optData:PresenceOptionData;
eventCause:uint8;
errorCode:int32;
optData:PresenceOptionData;
}
table RoomDataInternalUpdateInfo {
newRoomDataInternal:RoomDataInternal;
prevFlagAttr:uint32;
prevRoomPasswordSlotMask:uint64;
newRoomGroup:[uint8];
newRoomBinAttrInternal:[uint16];
newRoomDataInternal:RoomDataInternal;
prevFlagAttr:uint32;
prevRoomPasswordSlotMask:uint64;
newRoomGroup:[uint8];
newRoomBinAttrInternal:[uint16];
}
table RoomMemberDataInternalUpdateInfo {
newRoomMemberDataInternal:RoomMemberDataInternal;
prevFlagAttr:uint32;
prevTeamId:uint8;
newRoomMemberBinAttrInternal:[uint16];
newRoomMemberDataInternal:RoomMemberDataInternal;
prevFlagAttr:uint32;
prevTeamId:uint8;
newRoomMemberBinAttrInternal:[uint16];
}
table GetPingInfoResponse {
serverId:uint16;
worldId:uint32;
roomId:uint64;
rtt:uint32;
serverId:uint16;
worldId:uint32;
roomId:uint64;
rtt:uint32;
}
table SendRoomMessageRequest {
roomId:uint64;
castType:uint8;
dst:[uint16];
msg:[uint8];
option:uint8;
roomId:uint64;
castType:uint8;
dst:[uint16];
msg:[uint8];
option:uint8;
}
table RoomMessageInfo {
filtered:bool;
castType:uint8;
dst:[uint16];
srcMember:UserInfo2;
msg:[uint8];
filtered:bool;
castType:uint8;
dst:[uint16];
srcMember:UserInfo2;
msg:[uint8];
}
table MessageDetails {
communicationId:string;
msgId:uint64;
mainType:uint16;
subType:uint16;
msgFeatures:uint32;
subject:string;
body:string;
data:[uint8];
communicationId:string;
msgId:uint64;
mainType:uint16;
subType:uint16;
msgFeatures:uint32;
subject:string;
body:string;
data:[uint8];
}
table SendMessageRequest {
message:[uint8] (nested_flatbuffer: "MessageDetails");
npids:[string];
message:[uint8] (nested_flatbuffer: "MessageDetails");
npids:[string];
}
table BoardInfo {
rankLimit:uint32;
updateMode:uint32;
sortMode:uint32;
uploadNumLimit:uint32;
uploadSizeLimit:uint32;
rankLimit:uint32;
updateMode:uint32;
sortMode:uint32;
uploadNumLimit:uint32;
uploadSizeLimit:uint32;
}
table RecordScoreRequest {
@ -322,11 +322,11 @@ table ScoreRankData {
rank:uint32;
score:int64;
hasGameData:bool;
recordDate:uint64;
recordDate:uint64;
}
table ScoreInfo {
data: [uint8];
data:[uint8];
}
table GetScoreResponse {
@ -348,3 +348,121 @@ table GetScoreGameDataRequest {
npId:string;
pcId:int32;
}
table TusUser {
vuser:bool;
npid:string;
}
table TusVariable {
ownerId:string;
hasData:bool;
lastChangedDate:uint64;
lastChangedAuthorId:string;
variable:int64;
oldVariable:int64;
}
table TusVarResponse {
vars:[TusVariable];
}
table TusSetMultiSlotVariableRequest {
user:TusUser;
slotIdArray:[int32];
variableArray:[int64];
}
table TusGetMultiSlotVariableRequest {
user:TusUser;
slotIdArray:[int32];
}
table TusGetMultiUserVariableRequest {
users:[TusUser];
slotId:int32;
}
table TusGetFriendsVariableRequest {
slotId:int32;
includeSelf:bool;
sortType:int32;
arrayNum:uint32;
}
table TusAddAndGetVariableRequest {
user:TusUser;
slotId:int32;
inVariable:int64;
isLastChangedDate:[uint64];
isLastChangedAuthorId:string;
}
table TusTryAndSetVariableRequest {
user:TusUser;
slotId:int32;
opeType:int32;
variable:int64;
isLastChangedDate:[uint64];
isLastChangedAuthorId:string;
compareValue:[int64];
}
table TusDeleteMultiSlotVariableRequest {
user:TusUser;
slotIdArray:[int32];
}
table TusSetDataRequest {
user:TusUser;
slotId:int32;
data:[uint8];
info:[uint8];
isLastChangedDate:[uint64];
isLastChangedAuthorId:string;
}
table TusDataStatus {
ownerId:string;
hasData:bool;
lastChangedDate:uint64;
lastChangedAuthorId:string;
info:[uint8];
}
table TusData {
status: TusDataStatus;
data:[uint8];
}
table TusDataStatusResponse {
status: [TusDataStatus];
}
table TusGetDataRequest {
user:TusUser;
slotId:int32;
}
table TusGetMultiSlotDataStatusRequest {
user:TusUser;
slotIdArray:[int32];
}
table TusGetMultiUserDataStatusRequest {
users:[TusUser];
slotId:int32;
}
table TusGetFriendsDataStatusRequest {
slotId:int32;
includeSelf:bool;
sortType:int32;
arrayNum:uint32;
}
table TusDeleteMultiSlotDataRequest {
user:TusUser;
slotIdArray:[int32];
}

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,93 @@
LOG_CHANNEL(sceNp2);
generic_async_transaction_context::generic_async_transaction_context(const SceNpCommunicationId& communicationId, const SceNpCommunicationPassphrase& passphrase, u64 timeout)
: communicationId(communicationId), passphrase(passphrase), timeout(timeout)
{
}
generic_async_transaction_context::~generic_async_transaction_context()
{
if (thread.joinable())
thread.join();
}
std::optional<s32> generic_async_transaction_context::get_transaction_status()
{
std::lock_guard lock(mutex);
return result;
}
void generic_async_transaction_context::abort_transaction()
{
std::lock_guard lock(mutex);
result = SCE_NP_COMMUNITY_ERROR_ABORTED;
wake_cond.notify_one();
}
error_code generic_async_transaction_context::wait_for_completion()
{
std::unique_lock lock(mutex);
if (result)
{
return *result;
}
completion_cond.wait(lock);
return *result;
}
bool generic_async_transaction_context::set_result_and_wake(error_code err)
{
result = err;
wake_cond.notify_one();
return true;
}
tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
}
s32 create_tus_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
s32 tus_id = idm::make<tus_ctx>(communicationId, passphrase);
if (tus_id == id_manager::id_traits<tus_ctx>::invalid)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS;
}
return static_cast<s32>(tus_id);
}
bool destroy_tus_context(s32 ctx_id)
{
return idm::remove<tus_ctx>(static_cast<u32>(ctx_id));
}
tus_transaction_ctx::tus_transaction_ctx(const std::shared_ptr<tus_ctx>& tus)
: generic_async_transaction_context(tus->communicationId, tus->passphrase, tus->timeout)
{
}
s32 create_tus_transaction_context(const std::shared_ptr<tus_ctx>& tus)
{
s32 tus_id = idm::make<tus_transaction_ctx>(tus);
if (tus_id == id_manager::id_traits<tus_transaction_ctx>::invalid)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS;
}
return static_cast<s32>(tus_id);
}
bool destroy_tus_transaction_context(s32 ctx_id)
{
return idm::remove<tus_transaction_ctx>(static_cast<u32>(ctx_id));
}
score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
@ -28,16 +115,9 @@ bool destroy_score_context(s32 ctx_id)
}
score_transaction_ctx::score_transaction_ctx(const std::shared_ptr<score_ctx>& score)
: generic_async_transaction_context(score->communicationId, score->passphrase, score->timeout)
{
pcId = score->pcId;
communicationId = score->communicationId;
passphrase = score->passphrase;
timeout = score->timeout;
}
score_transaction_ctx::~score_transaction_ctx()
{
if (thread.joinable())
thread.join();
pcId = score->pcId;
}
s32 create_score_transaction_context(const std::shared_ptr<score_ctx>& score)
@ -55,39 +135,6 @@ bool destroy_score_transaction_context(s32 ctx_id)
{
return idm::remove<score_transaction_ctx>(static_cast<u32>(ctx_id));
}
std::optional<s32> score_transaction_ctx::get_score_transaction_status()
{
std::lock_guard lock(mutex);
return result;
}
void score_transaction_ctx::abort_score_transaction()
{
std::lock_guard lock(mutex);
result = SCE_NP_COMMUNITY_ERROR_ABORTED;
wake_cond.notify_one();
}
error_code score_transaction_ctx::wait_for_completion()
{
std::unique_lock lock(mutex);
if (result)
{
return *result;
}
completion_cond.wait(lock);
return *result;
}
bool score_transaction_ctx::set_result_and_wake(error_code err)
{
result = err;
wake_cond.notify_one();
return true;
}
match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
@ -97,7 +144,7 @@ match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<
}
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
{
sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast<const char *>(communicationId->data));
sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast<const char*>(communicationId->data));
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase));
}
bool destroy_match2_context(u16 ctx_id)
@ -144,7 +191,7 @@ commerce2_ctx::commerce2_ctx(u32 version, vm::cptr<SceNpId> npid, vm::ptr<SceNpC
{
this->version = version;
memcpy(&this->npid, npid.get_ptr(), sizeof(SceNpId));
this->context_callback = handler;
this->context_callback = handler;
this->context_callback_param = arg;
}
s32 create_commerce2_context(u32 version, vm::cptr<SceNpId> npid, vm::ptr<SceNpCommerce2Handler> handler, vm::ptr<void> arg)
@ -164,7 +211,7 @@ signaling_ctx::signaling_ctx(vm::ptr<SceNpId> npid, vm::ptr<SceNpSignalingHandle
{
memcpy(&this->npid, npid.get_ptr(), sizeof(SceNpId));
this->handler = handler;
this->arg = arg;
this->arg = arg;
}
s32 create_signaling_context(vm::ptr<SceNpId> npid, vm::ptr<SceNpSignalingHandler> handler, vm::ptr<void> arg)
{

View File

@ -11,32 +11,36 @@
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include "Emu/Cell/Modules/sceNpCommerce2.h"
#include "Emu/Cell/Modules/sceNpTus.h"
// Score related
struct score_ctx
// Used By Score and Tus
struct generic_async_transaction_context
{
score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
virtual ~generic_async_transaction_context();
static const u32 id_base = 0x2001;
static const u32 id_step = 1;
static const u32 id_count = 32;
SAVESTATE_INIT_POS(25);
generic_async_transaction_context(const SceNpCommunicationId& communicationId, const SceNpCommunicationPassphrase& passphrase, u64 timeout);
std::optional<s32> get_transaction_status();
void abort_transaction();
error_code wait_for_completion();
bool set_result_and_wake(error_code err);
shared_mutex mutex;
std::condition_variable_any wake_cond, completion_cond;
std::optional<error_code> result;
SceNpCommunicationId communicationId;
SceNpCommunicationPassphrase passphrase;
u64 timeout;
u64 timeout = 60'000'000; // 60 seconds
SceNpCommunicationId communicationId{};
SceNpCommunicationPassphrase passphrase{};
s32 pcId = 0;
std::thread thread;
};
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
bool destroy_score_context(s32 ctx_id);
struct tdata_invalid
{
};
// Score transaction data
struct tdata_get_board_infos
{
vm::ptr<SceNpScoreBoardInfo> boardInfo;
@ -74,33 +78,104 @@ struct tdata_get_score_generic
vm::ptr<SceNpScoreRankNumber> totalRecord;
};
struct score_transaction_ctx
{
score_transaction_ctx(const std::shared_ptr<score_ctx>& score);
~score_transaction_ctx();
std::optional<s32> get_score_transaction_status();
void abort_score_transaction();
error_code wait_for_completion();
bool set_result_and_wake(error_code err);
// TUS transaction data
static const u32 id_base = 0x1001;
static const u32 id_step = 1;
static const u32 id_count = 32;
SAVESTATE_INIT_POS(26);
struct tdata_tus_get_variables_generic
{
vm::ptr<SceNpTusVariable> variableArray;
s32 arrayNum;
};
struct tdata_tus_get_variable_generic
{
vm::ptr<SceNpTusVariable> outVariable;
};
struct tdata_tus_set_data
{
u32 tus_data_size;
std::vector<u8> tus_data;
};
struct tdata_tus_get_data
{
u32 recvSize = 0;
vm::ptr<SceNpTusDataStatus> dataStatus;
vm::ptr<void> data;
std::vector<u8> tus_data;
};
struct tdata_tus_get_datastatus_generic
{
vm::ptr<SceNpTusDataStatus> statusArray;
s32 arrayNum;
};
// TUS related
struct tus_ctx
{
tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
static const u32 id_base = 0x7001;
static const u32 id_step = 1;
static const u32 id_count = SCE_NP_TUS_MAX_CTX_NUM;
SAVESTATE_INIT_POS(50);
shared_mutex mutex;
std::condition_variable_any wake_cond, completion_cond;
u64 timeout = 60'000'000; // 60 seconds
SceNpCommunicationId communicationId{};
SceNpCommunicationPassphrase passphrase{};
};
s32 create_tus_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
bool destroy_tus_context(s32 ctx_id);
std::optional<error_code> result;
std::variant<tdata_invalid, tdata_get_board_infos, tdata_record_score, tdata_record_score_data, tdata_get_score_data, tdata_get_score_generic> tdata;
struct tus_transaction_ctx : public generic_async_transaction_context
{
tus_transaction_ctx(const std::shared_ptr<tus_ctx>& tus);
virtual ~tus_transaction_ctx() = default;
u64 timeout = 60'000'000; // 60 seconds;
static const u32 id_base = 0x8001;
static const u32 id_step = 1;
static const u32 id_count = SCE_NP_TUS_MAX_CTX_NUM;
SAVESTATE_INIT_POS(51);
std::variant<tdata_invalid, tdata_tus_get_variables_generic, tdata_tus_get_variable_generic, tdata_tus_set_data, tdata_tus_get_data, tdata_tus_get_datastatus_generic> tdata;
};
s32 create_tus_transaction_context(const std::shared_ptr<tus_ctx>& tus);
bool destroy_tus_transaction_context(s32 ctx_id);
// Score related
struct score_ctx
{
score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
static const u32 id_base = 0x2001;
static const u32 id_step = 1;
static const u32 id_count = SCE_NP_SCORE_MAX_CTX_NUM;
SAVESTATE_INIT_POS(25);
shared_mutex mutex;
u64 timeout = 60'000'000; // 60 seconds
SceNpCommunicationId communicationId{};
SceNpCommunicationPassphrase passphrase{};
s32 pcId = 0;
};
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
bool destroy_score_context(s32 ctx_id);
std::thread thread;
struct score_transaction_ctx : public generic_async_transaction_context
{
score_transaction_ctx(const std::shared_ptr<score_ctx>& score);
virtual ~score_transaction_ctx() = default;
static const u32 id_base = 0x1001;
static const u32 id_step = 1;
static const u32 id_count = SCE_NP_SCORE_MAX_CTX_NUM;
SAVESTATE_INIT_POS(26);
std::variant<tdata_invalid, tdata_get_board_infos, tdata_record_score, tdata_record_score_data, tdata_get_score_data, tdata_get_score_generic> tdata;
s32 pcId = 0;
};
s32 create_score_transaction_context(const std::shared_ptr<score_ctx>& score);
bool destroy_score_transaction_context(s32 ctx_id);
@ -112,7 +187,7 @@ struct match2_ctx
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 255;
static const u32 id_count = 255; // TODO: constant here?
SAVESTATE_INIT_POS(27);
SceNpCommunicationId communicationId{};
@ -134,7 +209,7 @@ struct lookup_title_ctx
static const u32 id_base = 0x3001;
static const u32 id_step = 1;
static const u32 id_count = 32;
static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM;
SAVESTATE_INIT_POS(28);
SceNpCommunicationId communicationId{};
@ -149,7 +224,7 @@ struct lookup_transaction_ctx
static const u32 id_base = 0x4001;
static const u32 id_step = 1;
static const u32 id_count = 32;
static const u32 id_count = SCE_NP_LOOKUP_MAX_CTX_NUM;
SAVESTATE_INIT_POS(29);
s32 lt_ctx = 0;
@ -163,7 +238,7 @@ struct commerce2_ctx
static const u32 id_base = 0x5001;
static const u32 id_step = 1;
static const u32 id_count = 32;
static const u32 id_count = SCE_NP_COMMERCE2_CTX_MAX;
SAVESTATE_INIT_POS(30);
u32 version{};
@ -181,7 +256,7 @@ struct signaling_ctx
static const u32 id_base = 0x6001;
static const u32 id_step = 1;
static const u32 id_count = 32;
static const u32 id_count = SCE_NP_SIGNALING_CTX_MAX;
SAVESTATE_INIT_POS(31);
SceNpId npid{};

View File

@ -436,16 +436,16 @@ namespace np
np_handler::~np_handler()
{
std::unordered_map<u32, std::shared_ptr<score_transaction_ctx>> moved_trans;
std::unordered_map<u32, std::shared_ptr<generic_async_transaction_context>> moved_trans;
{
std::lock_guard lock(mutex_score_transactions);
moved_trans = std::move(score_transactions);
score_transactions.clear();
std::lock_guard lock(mutex_async_transactions);
moved_trans = std::move(async_transactions);
async_transactions.clear();
}
for (auto& [trans_id, trans] : moved_trans)
{
trans->abort_score_transaction();
trans->abort_transaction();
}
for (auto& [trans_id, trans] : moved_trans)
@ -950,6 +950,19 @@ namespace np
case rpcn::CommandType::GetScoreRange: reply_get_score_range(req_id, data); break;
case rpcn::CommandType::GetScoreFriends: reply_get_score_friends(req_id, data); break;
case rpcn::CommandType::GetScoreNpid: reply_get_score_npid(req_id, data); break;
case rpcn::CommandType::TusSetMultiSlotVariable: reply_tus_set_multislot_variable(req_id, data); break;
case rpcn::CommandType::TusGetMultiSlotVariable: reply_tus_get_multislot_variable(req_id, data); break;
case rpcn::CommandType::TusGetMultiUserVariable: reply_tus_get_multiuser_variable(req_id, data); break;
case rpcn::CommandType::TusGetFriendsVariable: reply_tus_get_friends_variable(req_id, data); break;
case rpcn::CommandType::TusAddAndGetVariable: reply_tus_add_and_get_variable(req_id, data); break;
case rpcn::CommandType::TusTryAndSetVariable: reply_tus_try_and_set_variable(req_id, data); break;
case rpcn::CommandType::TusDeleteMultiSlotVariable: reply_tus_delete_multislot_variable(req_id, data); break;
case rpcn::CommandType::TusSetData: reply_tus_set_data(req_id, data); break;
case rpcn::CommandType::TusGetData: reply_tus_get_data(req_id, data); break;
case rpcn::CommandType::TusGetMultiSlotDataStatus: reply_tus_get_multislot_data_status(req_id, data); break;
case rpcn::CommandType::TusGetMultiUserDataStatus: reply_tus_get_multiuser_data_status(req_id, data); break;
case rpcn::CommandType::TusGetFriendsDataStatus: reply_tus_get_friends_data_status(req_id, data); break;
case rpcn::CommandType::TusDeleteMultiSlotData: reply_tus_delete_multislot_data(req_id, data); break;
default: rpcn_log.error("Unknown reply(%d) received!", command); break;
}
}
@ -1095,7 +1108,7 @@ namespace np
u32 np_handler::add_players_to_history(vm::cptr<SceNpId> /*npids*/, u32 /*count*/)
{
const u32 req_id = get_req_id(0);
const u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC);
if (basic_handler.handler_func)
{

View File

@ -20,6 +20,13 @@
namespace np
{
enum class REQUEST_ID_HIGH : u16
{
MISC = 0x3333,
SCORE = 0x3334,
TUS = 0x3335,
};
struct ticket_data
{
u16 id{}, len{};
@ -106,6 +113,7 @@ namespace np
atomic_t<bool> is_NP2_init = false;
atomic_t<bool> is_NP2_Match2_init = false;
atomic_t<bool> is_NP_Auth_init = false;
atomic_t<bool> is_NP_TUS_init = false;
// NP Handlers/Callbacks
// Seems to be global
@ -142,6 +150,7 @@ namespace np
// Synchronous requests
std::vector<SceNpMatching2ServerId> get_match2_server_list(SceNpMatching2ContextId);
u64 get_network_time();
// Asynchronous requests
u32 get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
u32 create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
@ -162,7 +171,7 @@ namespace np
u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size);
// Score requests
void score_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<score_transaction_ctx>& trans_ctx, u32 req_id, bool async);
void transaction_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<generic_async_transaction_context>& trans_ctx, u32 req_id, bool async);
void get_board_infos(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, vm::ptr<SceNpScoreBoardInfo> boardInfo, bool async);
void record_score(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr<SceNpScoreComment> scoreComment, const u8* data, u32 data_size, vm::ptr<SceNpScoreRankNumber> tmpRank, bool async);
void record_score_data(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, u32 totalSize, u32 sendSize, const u8* score_data, bool async);
@ -171,6 +180,21 @@ namespace np
void get_score_npid(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const std::vector<std::pair<SceNpId, s32>>& npid_vec, vm::ptr<SceNpScorePlayerRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async);
void get_score_friend(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr<SceNpScoreRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async);
// TUS requests
void tus_set_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multiuser_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_friends_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusVariable> variableArray,s32 arrayNum, bool async);
void tus_add_and_get_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusVariable> outVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser, bool async);
void tus_try_and_set_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusVariable> resultVariable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser, bool async);
void tus_delete_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async);
void tus_set_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr<void> data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser, bool async);
void tus_get_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> dataStatus, vm::ptr<void> data, u32 recvSize, bool vuser, bool async);
void tus_get_multislot_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multiuser_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async);
void tus_get_friends_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool async);
void tus_delete_multislot_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async);
// Local functions
std::pair<error_code, std::optional<SceNpId>> local_get_npid(u64 room_id, u16 member_id);
std::pair<error_code, std::optional<SceNpMatching2RoomSlotInfo>> local_get_room_slots(SceNpMatching2RoomId room_id);
@ -253,6 +277,19 @@ namespace np
bool reply_get_score_range(u32 req_id, std::vector<u8>& reply_data);
bool reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data);
bool reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_set_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_multiuser_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_friends_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_add_and_get_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_try_and_set_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_delete_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_set_data(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_data(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_multislot_data_status(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_multiuser_data_status(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_get_friends_data_status(u32 req_id, std::vector<u8>& reply_data);
bool reply_tus_delete_multislot_data(u32 req_id, std::vector<u8>& reply_data);
// Helper functions(fb=>np2)
void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info);
@ -274,6 +311,10 @@ namespace np
void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid);
void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info);
bool handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data);
bool handle_tus_no_data(u32 req_id, std::vector<u8>& reply_data);
bool handle_TusVarResponse(u32 req_id, std::vector<u8>& reply_data);
bool handle_TusVariable(u32 req_id, std::vector<u8>& reply_data);
bool handle_TusDataStatusResponse(u32 req_id, std::vector<u8>& reply_data);
struct callback_info
{
@ -338,6 +379,9 @@ namespace np
std::optional<u64> selected_invite_id{};
std::optional<u64> selected_message_id{};
// Misc
s64 network_time_offset = 0;
// Requests(reqEventKey : data)
shared_mutex mutex_match2_req_results;
std::unordered_map<u32, event_data> match2_req_results;
@ -347,15 +391,21 @@ namespace np
{
return ((app_req << 16) | match2_low_reqid_cnt.fetch_add(1));
}
u32 get_req_id(REQUEST_ID_HIGH int_req)
{
return ((static_cast<u16>(int_req) << 16) | match2_low_reqid_cnt.fetch_add(1));
}
u32 get_event_key()
{
return match2_event_cnt.fetch_add(1);
}
event_data& allocate_req_result(u32 event_key, u32 max_size, u32 initial_size);
// Async score threads
shared_mutex mutex_score_transactions;
std::unordered_map<u32, std::shared_ptr<score_transaction_ctx>> score_transactions; // (req_id, transaction_ctx)
// Async transaction threads
shared_mutex mutex_async_transactions;
std::unordered_map<u32, std::shared_ptr<generic_async_transaction_context>> async_transactions; // (req_id, transaction_ctx)
// RPCN
shared_mutex mutex_rpcn;

View File

@ -23,7 +23,7 @@ namespace np
return server_list;
}
if (!get_rpcn()->get_server_list(get_req_id(0), get_match2_context(ctx_id)->communicationId, server_list))
if (!get_rpcn()->get_server_list(get_req_id(REQUEST_ID_HIGH::MISC), get_match2_context(ctx_id)->communicationId, server_list))
{
rpcn_log.error("Disconnecting from RPCN!");
is_psn_active = false;
@ -32,6 +32,33 @@ namespace np
return server_list;
}
u64 np_handler::get_network_time()
{
// If network time hasn't been set we need to sync time with the rpcn server
auto get_local_timestamp = []() -> u64
{
return std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now().time_since_epoch()).count();
};
if (!network_time_offset)
{
// Could be improved with multiple requests to increase latency determination accuracy
const u64 req_timestamp = get_local_timestamp();
const u64 server_timestamp = get_rpcn()->get_network_time(get_req_id(REQUEST_ID_HIGH::MISC));
if (!server_timestamp)
{
rpcn_log.error("Disconnecting from RPCN!");
is_psn_active = false;
return 0;
}
const u64 reply_timestamp = get_local_timestamp();
const u64 latency = (reply_timestamp - req_timestamp) / 2;
network_time_offset = reply_timestamp - (server_timestamp + latency);
}
return get_local_timestamp() - network_time_offset;
}
u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id)
{
// TODO: actually implement interaction with server for this?
@ -550,7 +577,7 @@ namespace np
void np_handler::req_sign_infos(const std::string& npid, u32 conn_id)
{
u32 req_id = get_req_id(0x3333);
u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC);
{
std::lock_guard lock(mutex_pending_sign_infos_requests);
pending_sign_infos_requests[req_id] = conn_id;
@ -603,7 +630,7 @@ namespace np
void np_handler::req_ticket([[maybe_unused]] u32 version, [[maybe_unused]] const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, [[maybe_unused]] const char* entitlement_id, [[maybe_unused]] u32 consumed_count)
{
u32 req_id = get_req_id(0x3333);
u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC);
std::string service_id_str(service_id);
@ -650,14 +677,14 @@ namespace np
return true;
}
void np_handler::score_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<score_transaction_ctx>& trans_ctx, u32 req_id, bool async)
void np_handler::transaction_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<generic_async_transaction_context>& trans_ctx, u32 req_id, bool async)
{
auto worker_function = [trans_ctx = trans_ctx, req_id, this](std::unique_lock<shared_mutex> lock)
{
auto res = trans_ctx->wake_cond.wait_for(lock, std::chrono::microseconds(trans_ctx->timeout));
{
std::lock_guard lock_threads(this->mutex_score_transactions);
this->score_transactions.erase(req_id);
std::lock_guard lock_threads(this->mutex_async_transactions);
this->async_transactions.erase(req_id);
}
if (res == std::cv_status::timeout)
@ -673,8 +700,8 @@ namespace np
};
{
std::lock_guard lock_score(mutex_score_transactions);
ensure(score_transactions.insert({req_id, trans_ctx}).second);
std::lock_guard lock_score(mutex_async_transactions);
ensure(async_transactions.insert({req_id, trans_ctx}).second);
}
if (async)
@ -693,11 +720,11 @@ namespace np
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
trans_ctx->tdata = tdata_get_board_infos{.boardInfo = boardInfo};
get_rpcn()->get_board_infos(req_id, trans_ctx->communicationId, boardId);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_get_board_infos(u32 req_id, std::vector<u8>& reply_data)
@ -717,22 +744,24 @@ namespace np
board_info.uploadNumLimit = resp->uploadNumLimit();
board_info.uploadSizeLimit = resp->uploadSizeLimit();
std::lock_guard lock_trans(mutex_score_transactions);
if (!score_transactions.count(req_id))
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans = ::at32(score_transactions, req_id);
std::lock_guard lock(trans->mutex);
auto score_trans = std::dynamic_pointer_cast<score_transaction_ctx>(::at32(async_transactions, req_id));
ensure(score_trans);
const auto* tdata = std::get_if<tdata_get_board_infos>(&trans->tdata);
std::lock_guard lock(score_trans->mutex);
const auto* tdata = std::get_if<tdata_get_board_infos>(&score_trans->tdata);
ensure(tdata);
memcpy(reinterpret_cast<u8*>(tdata->boardInfo.get_ptr()), &board_info, sizeof(SceNpScoreBoardInfo));
trans->result = CELL_OK;
trans->wake_cond.notify_one();
score_trans->result = CELL_OK;
score_trans->wake_cond.notify_one();
return true;
}
@ -740,7 +769,7 @@ namespace np
void np_handler::record_score(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr<SceNpScoreComment> scoreComment, const u8* data, u32 data_size, vm::ptr<SceNpScoreRankNumber> tmpRank, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
std::optional<std::string> str_comment = scoreComment ? std::optional(std::string(reinterpret_cast<const char*>(scoreComment->data))) : std::nullopt;
std::optional<std::vector<u8>> vec_data;
@ -753,20 +782,22 @@ namespace np
get_rpcn()->record_score(req_id, trans_ctx->communicationId, boardId, trans_ctx->pcId, score, str_comment, vec_data);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_record_score(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_score_transactions);
if (!score_transactions.count(req_id))
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans = ::at32(score_transactions, req_id);
std::lock_guard lock(trans->mutex);
auto score_trans = std::dynamic_pointer_cast<score_transaction_ctx>(::at32(async_transactions, req_id));
ensure(score_trans);
std::lock_guard lock(score_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
@ -774,8 +805,8 @@ namespace np
{
case rpcn::ErrorType::ScoreNotBest:
{
trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE;
trans->wake_cond.notify_one();
score_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE;
score_trans->wake_cond.notify_one();
return true;
}
default: return false;
@ -791,7 +822,7 @@ namespace np
return false;
}
const auto* tdata = std::get_if<tdata_record_score>(&trans->tdata);
const auto* tdata = std::get_if<tdata_record_score>(&score_trans->tdata);
ensure(tdata);
if (tdata->tmpRank)
@ -799,8 +830,8 @@ namespace np
*tdata->tmpRank = tmp_rank;
}
trans->result = CELL_OK;
trans->wake_cond.notify_one();
score_trans->result = CELL_OK;
score_trans->wake_cond.notify_one();
return true;
}
@ -821,9 +852,9 @@ namespace np
if (tdata->game_data.size() == tdata->game_data_size)
{
trans_ctx->result = std::nullopt;
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
get_rpcn()->record_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, score, tdata->game_data);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
else
{
@ -833,14 +864,14 @@ namespace np
bool np_handler::reply_record_score_data(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_score_transactions);
if (!score_transactions.count(req_id))
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans = ::at32(score_transactions, req_id);
auto trans = ::at32(async_transactions, req_id);
std::lock_guard lock(trans->mutex);
auto set_result_and_wake = [&](error_code err) -> bool
@ -873,9 +904,9 @@ namespace np
{
trans_ctx->tdata = tdata_get_score_data{.totalSize = totalSize, .recvSize = recvSize, .score_data = score_data};
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
get_rpcn()->get_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, npId);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
return;
}
@ -898,28 +929,29 @@ namespace np
bool np_handler::reply_get_score_data(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_score_transactions);
if (!score_transactions.count(req_id))
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans = ::at32(score_transactions, req_id);
std::lock_guard lock(trans->mutex);
auto score_trans = std::dynamic_pointer_cast<score_transaction_ctx>(::at32(async_transactions, req_id));
ensure(score_trans);
std::lock_guard lock(score_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND);
case rpcn::ErrorType::NotFound: return score_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND);
default: return false;
}
}
vec_stream reply(reply_data, 1);
auto* tdata = std::get_if<tdata_get_score_data>(&trans->tdata);
auto* tdata = std::get_if<tdata_get_score_data>(&score_trans->tdata);
ensure(tdata);
tdata->game_data = reply.get_rawdata();
@ -937,13 +969,13 @@ namespace np
tdata->game_data.erase(tdata->game_data.begin(), tdata->game_data.begin() + to_copy);
*tdata->totalSize = tdata->game_data_size;
return trans->set_result_and_wake(not_an_error(to_copy));
return score_trans->set_result_and_wake(not_an_error(to_copy));
}
void np_handler::get_score_range(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr<SceNpScoreRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
trans_ctx->tdata = tdata_get_score_generic{
.rankArray = rankArray,
@ -961,20 +993,21 @@ namespace np
get_rpcn()->get_score_range(req_id, trans_ctx->communicationId, boardId, startSerialRank, arrayNum, with_comments, with_gameinfo);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_score_transactions);
if (!score_transactions.count(req_id))
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans_ctx = ::at32(score_transactions, req_id);
std::lock_guard lock(trans_ctx->mutex);
auto score_trans = std::dynamic_pointer_cast<score_transaction_ctx>(::at32(async_transactions, req_id));
ensure(score_trans);
std::lock_guard lock(score_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
@ -990,7 +1023,7 @@ namespace np
return false;
}
const auto* tdata = std::get_if<tdata_get_score_generic>(&trans_ctx->tdata);
const auto* tdata = std::get_if<tdata_get_score_generic>(&score_trans->tdata);
ensure(tdata);
ensure(resp->rankArray() && resp->rankArray()->size() <= tdata->arrayNum);
@ -1078,13 +1111,14 @@ namespace np
*tdata->totalRecord = resp->totalRecord();
if (fb_rankarray->size())
trans_ctx->result = not_an_error(fb_rankarray->size());
score_trans->result = not_an_error(fb_rankarray->size());
else
trans_ctx->result = SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND;
score_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND;
trans_ctx->wake_cond.notify_one();
score_trans->wake_cond.notify_one();
return true;
}
bool np_handler::reply_get_score_range(u32 req_id, std::vector<u8>& reply_data)
{
return handle_GetScoreResponse(req_id, reply_data);
@ -1093,7 +1127,7 @@ namespace np
void np_handler::get_score_friend(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr<SceNpScoreRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
trans_ctx->tdata = tdata_get_score_generic{
.rankArray = rankArray,
.rankArraySize = rankArraySize,
@ -1110,7 +1144,7 @@ namespace np
get_rpcn()->get_score_friend(req_id, trans_ctx->communicationId, boardId, include_self, with_comments, with_gameinfo, arrayNum);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data)
{
@ -1120,7 +1154,7 @@ namespace np
void np_handler::get_score_npid(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const std::vector<std::pair<SceNpId, s32>>& npid_vec, vm::ptr<SceNpScorePlayerRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(0x3334);
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
trans_ctx->tdata = tdata_get_score_generic{
.rankArray = rankArray,
.rankArraySize = rankArraySize,
@ -1137,11 +1171,583 @@ namespace np
get_rpcn()->get_score_npid(req_id, trans_ctx->communicationId, boardId, npid_vec, with_comments, with_gameinfo);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data)
{
return handle_GetScoreResponse(req_id, reply_data);
}
bool np_handler::handle_tus_no_data(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto trans = ::at32(async_transactions, req_id);
std::lock_guard lock(trans->mutex);
auto set_result_and_wake = [&](error_code err) -> bool
{
trans->result = err;
trans->wake_cond.notify_one();
return true;
};
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: return false;
}
}
return set_result_and_wake(CELL_OK);
}
bool np_handler::handle_TusVarResponse(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto tus_trans = std::dynamic_pointer_cast<tus_transaction_ctx>(::at32(async_transactions, req_id));
ensure(tus_trans);
std::lock_guard lock(tus_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: return false;
}
}
vec_stream reply(reply_data, 1);
auto* resp = reply.get_flatbuffer<TusVarResponse>();
if (reply.is_error())
{
rpcn_log.error("Error parsing response in handle_TusVarResponse");
return false;
}
const auto* tdata = std::get_if<tdata_tus_get_variables_generic>(&tus_trans->tdata);
ensure(tdata);
ensure(resp->vars() && resp->vars()->size() <= static_cast<usz>(tdata->arrayNum));
const auto* fb_vars = resp->vars();
memset(tdata->variableArray.get_ptr(), 0, sizeof(SceNpTusVariable) * tdata->arrayNum);
for (flatbuffers::uoffset_t i = 0; i < fb_vars->size(); i++)
{
auto* cur_var = &tdata->variableArray[i];
const auto* cur_fb_var = fb_vars->Get(i);
ensure(cur_fb_var->ownerId());
string_to_npid(cur_fb_var->ownerId()->string_view(), cur_var->ownerId);
if (!cur_fb_var->hasData())
{
continue;
}
ensure(cur_fb_var->lastChangedAuthorId());
cur_var->hasData = 1;
cur_var->lastChangedDate.tick = cur_fb_var->lastChangedDate();
string_to_npid(cur_fb_var->lastChangedAuthorId()->string_view(), cur_var->lastChangedAuthorId);
cur_var->variable = cur_fb_var->variable();
cur_var->oldVariable = cur_fb_var->oldVariable();
}
tus_trans->result = not_an_error(fb_vars->size());
tus_trans->wake_cond.notify_one();
return true;
}
bool np_handler::handle_TusVariable(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto tus_trans = std::dynamic_pointer_cast<tus_transaction_ctx>(::at32(async_transactions, req_id));
ensure(tus_trans);
std::lock_guard lock(tus_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: return false;
}
}
vec_stream reply(reply_data, 1);
const auto* fb_var = reply.get_flatbuffer<TusVariable>();
if (reply.is_error())
{
rpcn_log.error("Error parsing response in handle_TusVariable");
return false;
}
const auto* tdata = std::get_if<tdata_tus_get_variable_generic>(&tus_trans->tdata);
ensure(tdata);
auto* var = tdata->outVariable.get_ptr();
memset(var, 0, sizeof(SceNpTusVariable));
ensure(fb_var->ownerId());
string_to_npid(fb_var->ownerId()->string_view(), var->ownerId);
if (fb_var->hasData())
{
ensure(fb_var->lastChangedAuthorId());
var->hasData = 1;
var->lastChangedDate.tick = fb_var->lastChangedDate();
string_to_npid(fb_var->lastChangedAuthorId()->string_view(), var->lastChangedAuthorId);
var->variable = fb_var->variable();
var->oldVariable = fb_var->oldVariable();
}
tus_trans->result = CELL_OK;
tus_trans->wake_cond.notify_one();
return true;
}
bool np_handler::handle_TusDataStatusResponse(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto tus_trans = std::dynamic_pointer_cast<tus_transaction_ctx>(::at32(async_transactions, req_id));
ensure(tus_trans);
std::lock_guard lock(tus_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: return false;
}
}
vec_stream reply(reply_data, 1);
auto* resp = reply.get_flatbuffer<TusDataStatusResponse>();
if (reply.is_error())
{
rpcn_log.error("Error parsing response in handle_TusDataStatusReponse");
return false;
}
const auto* tdata = std::get_if<tdata_tus_get_datastatus_generic>(&tus_trans->tdata);
ensure(tdata);
ensure(resp->status() && resp->status()->size() <= static_cast<usz>(tdata->arrayNum));
const auto* fb_status = resp->status();
memset(tdata->statusArray.get_ptr(), 0, sizeof(SceNpTusDataStatus) * tdata->arrayNum);
for (flatbuffers::uoffset_t i = 0; i < fb_status->size(); i++)
{
auto* cur_status = &tdata->statusArray[i];
const auto* cur_fb_status = fb_status->Get(i);
ensure(cur_fb_status->ownerId());
string_to_npid(cur_fb_status->ownerId()->string_view(), cur_status->ownerId);
if (!cur_fb_status->hasData())
{
continue;
}
ensure(cur_fb_status->lastChangedAuthorId());
cur_status->hasData = 1;
cur_status->lastChangedDate.tick = cur_fb_status->lastChangedDate();
string_to_npid(cur_fb_status->lastChangedAuthorId()->string_view(), cur_status->lastChangedAuthorId);
cur_status->info.infoSize = cur_fb_status->info() ? cur_fb_status->info()->size() : 0;
for (usz i = 0; i < static_cast<usz>(cur_status->info.infoSize); i++)
{
cur_status->info.data[i] = cur_fb_status->info()->Get(i);
}
}
tus_trans->result = not_an_error(fb_status->size());
tus_trans->wake_cond.notify_one();
return true;
}
void np_handler::tus_set_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
get_rpcn()->tus_set_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, variableArray, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_set_multislot_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_tus_no_data(req_id, reply_data);
}
void np_handler::tus_get_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_variables_generic {
.variableArray = variableArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_multislot_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusVarResponse(req_id, reply_data);
}
void np_handler::tus_get_multiuser_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_variables_generic {
.variableArray = variableArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_multiuser_variable(req_id, trans_ctx->communicationId, targetNpIdArray, slotId, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_multiuser_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusVarResponse(req_id, reply_data);
}
void np_handler::tus_get_friends_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusVariable> variableArray,s32 arrayNum, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_variables_generic {
.variableArray = variableArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_friends_variable(req_id, trans_ctx->communicationId, slotId, !!includeSelf, sortType, arrayNum);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_friends_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusVarResponse(req_id, reply_data);
}
void np_handler::tus_add_and_get_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusVariable> outVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_variable_generic {
.outVariable = outVariable,
};
get_rpcn()->tus_add_and_get_variable(req_id, trans_ctx->communicationId, targetNpId, slotId, inVariable, option, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_add_and_get_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusVariable(req_id, reply_data);
}
void np_handler::tus_try_and_set_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusVariable> resultVariable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_variable_generic {
.outVariable = resultVariable,
};
get_rpcn()->tus_try_and_set_variable(req_id, trans_ctx->communicationId, targetNpId, slotId, opeType, variable, option, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_try_and_set_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusVariable(req_id, reply_data);
}
void np_handler::tus_delete_multislot_variable(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
get_rpcn()->tus_delete_multislot_variable(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_delete_multislot_variable(u32 req_id, std::vector<u8>& reply_data)
{
return handle_tus_no_data(req_id, reply_data);
}
void np_handler::tus_set_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr<void> data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
auto* tdata = std::get_if<tdata_tus_set_data>(&trans_ctx->tdata);
if (!tdata)
{
trans_ctx->tdata = tdata_tus_set_data{.tus_data_size = totalSize};
tdata = std::get_if<tdata_tus_set_data>(&trans_ctx->tdata);
tdata->tus_data.reserve(totalSize);
}
const u8* ptr = static_cast<const u8*>(data.get_ptr());
std::copy(ptr, ptr + sendSize, std::back_inserter(tdata->tus_data));
if (tdata->tus_data.size() == tdata->tus_data_size)
{
trans_ctx->result = std::nullopt;
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
get_rpcn()->tus_set_data(req_id, trans_ctx->communicationId, targetNpId, slotId, tdata->tus_data, info, option, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
else
{
trans_ctx->result = CELL_OK;
}
}
bool np_handler::reply_tus_set_data(u32 req_id, std::vector<u8>& reply_data)
{
return handle_tus_no_data(req_id, reply_data);
}
void np_handler::tus_get_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> dataStatus, vm::ptr<void> data, u32 recvSize, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
auto* tdata = std::get_if<tdata_tus_get_data>(&trans_ctx->tdata);
if (!tdata)
{
trans_ctx->tdata = tdata_tus_get_data{.recvSize = recvSize, .dataStatus = dataStatus, .data = data};
u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE);
get_rpcn()->tus_get_data(req_id, trans_ctx->communicationId, targetNpId, slotId, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
return;
}
// Check if the transaction has actually completed, otherwise adjust tdata parameters
if (!trans_ctx->result)
{
tdata->recvSize = recvSize;
tdata->dataStatus = dataStatus;
tdata->data = data;
return;
}
// If here the data has already been acquired and the client is just asking for part of it
usz to_copy = std::min(tdata->tus_data.size(), static_cast<usz>(recvSize));
std::memcpy(data.get_ptr(), tdata->tus_data.data(), to_copy);
tdata->tus_data.erase(tdata->tus_data.begin(), tdata->tus_data.begin() + to_copy);
trans_ctx->result = not_an_error(to_copy);
}
bool np_handler::reply_tus_get_data(u32 req_id, std::vector<u8>& reply_data)
{
std::lock_guard lock_trans(mutex_async_transactions);
if (!async_transactions.count(req_id))
{
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
return false;
}
auto tus_trans = std::dynamic_pointer_cast<tus_transaction_ctx>(::at32(async_transactions, req_id));
ensure(tus_trans);
std::lock_guard lock(tus_trans->mutex);
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
{
switch (reply_data[0])
{
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: return false;
}
}
vec_stream reply(reply_data, 1);
const auto* fb_data = reply.get_flatbuffer<TusData>();
if (reply.is_error())
{
rpcn_log.error("Error parsing response in reply_tus_get_data");
return false;
}
auto* tdata = std::get_if<tdata_tus_get_data>(&tus_trans->tdata);
ensure(tdata);
const auto* fb_status = fb_data->status();
ensure(fb_status && fb_status->ownerId());
auto* data_status = tdata->dataStatus.get_ptr();
auto* data = static_cast<u8 *>(tdata->data.get_ptr());
memset(data_status, 0, sizeof(SceNpTusDataStatus));
string_to_npid(fb_status->ownerId()->string_view(), data_status->ownerId);
usz to_copy = 0;
if (fb_status->hasData())
{
data_status->hasData = 1;
data_status->lastChangedDate.tick = fb_status->lastChangedDate();
string_to_npid(fb_status->lastChangedAuthorId()->string_view(), data_status->lastChangedAuthorId);
data_status->data = tdata->data;
data_status->dataSize = fb_data->data() ? fb_data->data()->size() : 0;
data_status->info.infoSize = fb_status->info() ? fb_status->info()->size() : 0;
to_copy = std::min(static_cast<usz>(data_status->dataSize), static_cast<usz>(tdata->recvSize));
for (usz i = 0; i < to_copy; i++)
{
data[i] = fb_data->data()->Get(i);
}
const usz bytes_left = data_status->dataSize - to_copy;
tdata->tus_data.reserve(bytes_left);
for (usz i = to_copy; i < bytes_left; i++)
{
tdata->tus_data.push_back(fb_data->data()->Get(i));
}
for (usz i = 0; i < data_status->info.infoSize; i++)
{
fb_status->info()->Get(i);
}
tus_trans->result = not_an_error(to_copy);
}
else
{
tus_trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_USER_STORAGE_DATA_NOT_FOUND;
}
tus_trans->wake_cond.notify_one();
return true;
}
void np_handler::tus_get_multislot_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_datastatus_generic {
.statusArray = statusArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_multislot_data_status(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_multislot_data_status(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusDataStatusResponse(req_id, reply_data);
}
void np_handler::tus_get_multiuser_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_datastatus_generic {
.statusArray = statusArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_multiuser_data_status(req_id, trans_ctx->communicationId, targetNpIdArray, slotId, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_multiuser_data_status(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusDataStatusResponse(req_id, reply_data);
}
void np_handler::tus_get_friends_data_status(std::shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
trans_ctx->tdata = tdata_tus_get_datastatus_generic {
.statusArray = statusArray,
.arrayNum = arrayNum,
};
get_rpcn()->tus_get_friends_data_status(req_id, trans_ctx->communicationId, slotId, !!includeSelf, sortType, arrayNum);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_get_friends_data_status(u32 req_id, std::vector<u8>& reply_data)
{
return handle_TusDataStatusResponse(req_id, reply_data);
}
void np_handler::tus_delete_multislot_data(std::shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
get_rpcn()->tus_delete_multislot_data(req_id, trans_ctx->communicationId, targetNpId, slotIdArray, arrayNum, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
}
bool np_handler::reply_tus_delete_multislot_data(u32 req_id, std::vector<u8>& reply_data)
{
return handle_tus_no_data(req_id, reply_data);
}
} // namespace np

View File

@ -25,6 +25,11 @@ namespace extra_nps
sceNp2.warning("hubMemberId: %d", opt->hubMemberId);
}
void print_int_attr(const SceNpMatching2IntAttr* attr)
{
sceNp2.warning("Id: 0x%x, num:%d(0x%x)", attr->id, attr->num, attr->num);
}
void print_bin_attr(const SceNpMatching2BinAttr* bin)
{
const auto ptr = +bin->ptr;
@ -68,6 +73,18 @@ namespace extra_nps
sceNp2.warning("max: %d", filt->max);
}
void print_int_search_filter(const SceNpMatching2IntSearchFilter* filt)
{
sceNp2.warning("searchOperator: %s", filt->searchOperator);
print_int_attr(&filt->attr);
}
void print_bin_search_filter(const SceNpMatching2BinSearchFilter* filt)
{
sceNp2.warning("searchOperator: %s", filt->searchOperator);
print_bin_attr(&filt->attr);
}
void print_createjoinroom(const SceNpMatching2CreateJoinRoomRequest* req)
{
sceNp2.warning("SceNpMatching2CreateJoinRoomRequest:");
@ -83,10 +100,22 @@ namespace extra_nps
sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", req->roomSearchableIntAttrExternal);
sceNp2.warning("roomSearchableIntAttrExternalNum: %d", req->roomSearchableIntAttrExternalNum);
for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++)
print_int_attr(&req->roomSearchableIntAttrExternal[i]);
sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", req->roomSearchableBinAttrExternal);
sceNp2.warning("roomSearchableBinAttrExternalNum: %d", req->roomSearchableBinAttrExternalNum);
for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++)
print_bin_attr(&req->roomSearchableBinAttrExternal[i]);
sceNp2.warning("roomBinAttrExternal: *0x%x", req->roomBinAttrExternal);
sceNp2.warning("roomBinAttrExternalNum: %d", req->roomBinAttrExternalNum);
for (u32 i = 0; i < req->roomBinAttrExternalNum; i++)
print_bin_attr(&req->roomBinAttrExternal[i]);
sceNp2.warning("roomPassword: *0x%x", req->roomPassword);
sceNp2.warning("groupConfig: *0x%x", req->groupConfig);
sceNp2.warning("groupConfigNum: %d", req->groupConfigNum);
@ -107,11 +136,6 @@ namespace extra_nps
if (req->sigOptParam)
print_sigoptparam(req->sigOptParam.get_ptr());
for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++)
{
sceNp2.warning("roomSearchableIntAttrExternal(%d) = %d", req->roomSearchableIntAttrExternal[i].id, req->roomSearchableIntAttrExternal[i].num);
}
}
void print_joinroom(const SceNpMatching2JoinRoomRequest* req)
@ -140,10 +164,16 @@ namespace extra_nps
sceNp2.warning("flagAttr: 0x%x", req->flagAttr);
sceNp2.warning("intFilter: *0x%x", req->intFilter);
sceNp2.warning("intFilterNum: %d", req->intFilterNum);
for (u32 i = 0; i < req->intFilterNum; i++)
print_int_search_filter(&req->intFilter[i]);
sceNp2.warning("binFilter: *0x%x", req->binFilter);
sceNp2.warning("binFilterNum: %d", req->binFilterNum);
for (u32 i = 0; i < req->binFilterNum; i++)
print_bin_search_filter(&req->binFilter[i]);
sceNp2.warning("attrId: *0x%x", req->attrId);
sceNp2.warning("attrIdNum: %d", req->attrIdNum);
for (u32 i = 0; i < req->attrIdNum; i++)
sceNp2.warning("attrId[%d] = 0x%x", i, req->attrId[i]);
}
void print_search_room_resp(const SceNpMatching2SearchRoomResponse* resp)
@ -235,13 +265,21 @@ namespace extra_nps
sceNp2.warning("flagAttr: 0x%x", room->flagAttr);
sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", room->roomSearchableIntAttrExternal);
sceNp2.warning("roomSearchableIntAttrExternalNum: %d", room->roomSearchableIntAttrExternalNum);
// TODO: print roomSearchableIntAttrExternal
for (u32 i = 0; i < room->roomSearchableIntAttrExternalNum; i++)
print_int_attr(&room->roomSearchableIntAttrExternal[i]);
sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", room->roomSearchableBinAttrExternal);
sceNp2.warning("roomSearchableBinAttrExternalNum: %d", room->roomSearchableBinAttrExternalNum);
// TODO: print roomSearchableBinAttrExternal
for (u32 i = 0; i < room->roomSearchableBinAttrExternalNum; i++)
print_bin_attr(&room->roomSearchableBinAttrExternal[i]);
sceNp2.warning("roomBinAttrExternal: *0x%x", room->roomBinAttrExternal);
sceNp2.warning("roomBinAttrExternalNum: %d", room->roomBinAttrExternalNum);
// TODO: print roomBinAttrExternal
for (u32 i = 0; i < room->roomBinAttrExternalNum; i++)
print_bin_attr(&room->roomBinAttrExternal[i]);
}
void print_create_room_resp(const SceNpMatching2CreateJoinRoomResponse* resp)
@ -258,10 +296,21 @@ namespace extra_nps
sceNp2.warning("roomId: %d", req->roomId);
sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", req->roomSearchableIntAttrExternal);
sceNp2.warning("roomSearchableIntAttrExternalNum: %d", req->roomSearchableIntAttrExternalNum);
for (u32 i = 0; i < req->roomSearchableIntAttrExternalNum; i++)
print_int_attr(&req->roomSearchableIntAttrExternal[i]);
sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", req->roomSearchableBinAttrExternal);
sceNp2.warning("roomSearchableBinAttrExternalNum: %d", req->roomSearchableBinAttrExternalNum);
for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++)
print_bin_attr(&req->roomSearchableBinAttrExternal[i]);
sceNp2.warning("roomBinAttrExternal: *0x%x", req->roomBinAttrExternal);
sceNp2.warning("roomBinAttrExternalNum: %d", req->roomBinAttrExternalNum);
for (u32 i = 0; i < req->roomBinAttrExternalNum; i++)
print_bin_attr(&req->roomBinAttrExternal[i]);
}
void print_set_roomdata_int_req(const SceNpMatching2SetRoomDataInternalRequest* req)
@ -272,6 +321,10 @@ namespace extra_nps
sceNp2.warning("flagAttr: 0x%x", req->flagAttr);
sceNp2.warning("roomBinAttrInternal: *0x%x", req->roomBinAttrInternal);
sceNp2.warning("roomBinAttrInternalNum: %d", req->roomBinAttrInternalNum);
for (u32 i = 0; i < req->roomBinAttrInternalNum; i++)
print_bin_attr(&req->roomBinAttrInternal[i]);
sceNp2.warning("passwordConfig: *0x%x", req->passwordConfig);
sceNp2.warning("passwordConfigNum: %d", req->passwordConfigNum);
sceNp2.warning("passwordSlotMask: *0x%x", req->passwordSlotMask);

View File

@ -74,7 +74,7 @@ namespace rpcn
return get_localized_string(rpcn_state_to_localized_string_id(state));
}
constexpr u32 RPCN_PROTOCOL_VERSION = 19;
constexpr u32 RPCN_PROTOCOL_VERSION = 20;
constexpr usz RPCN_HEADER_SIZE = 15;
constexpr usz COMMUNICATION_ID_SIZE = 9;
@ -114,6 +114,7 @@ namespace rpcn
case ScoreNotBest: rpcn_log.error("Attempted to register a score that is not better!"); break;
case ScoreInvalid: rpcn_log.error("Score for player was found but wasn't what was expected!"); break;
case ScoreHasData: rpcn_log.error("Score already has game data associated with it!"); break;
case CondFail: rpcn_log.error("Condition related to the query failed!"); break;
case Unsupported: rpcn_log.error("An unsupported operation was attempted!"); break;
default: rpcn_log.fatal("Unhandled ErrorType reached the switch?"); break;
}
@ -364,7 +365,7 @@ namespace rpcn
std::vector<u8> data;
if (packet_size > RPCN_HEADER_SIZE)
{
const u16 data_size = packet_size - RPCN_HEADER_SIZE;
const u32 data_size = packet_size - RPCN_HEADER_SIZE;
data.resize(data_size);
if (recvn(data.data(), data_size) != recvn_result::recvn_success)
return error_and_disconnect("Failed to receive a whole packet");
@ -383,7 +384,7 @@ namespace rpcn
command == CommandType::AddFriend || command == CommandType::RemoveFriend ||
command == CommandType::AddBlock || command == CommandType::RemoveBlock ||
command == CommandType::SendMessage || command == CommandType::SendToken ||
command == CommandType::SendResetToken || command == CommandType::ResetPassword)
command == CommandType::SendResetToken || command == CommandType::ResetPassword || command == CommandType::GetNetworkTime)
{
std::lock_guard lock(mutex_replies_sync);
replies_sync.insert(std::make_pair(packet_id, std::make_pair(command, std::move(data))));
@ -1261,6 +1262,34 @@ namespace rpcn
return true;
}
u64 rpcn_client::get_network_time(u32 req_id)
{
std::vector<u8> data, reply_data;
if (!forge_send_reply(CommandType::GetNetworkTime, req_id, data, reply_data))
{
return 0;
}
vec_stream reply(reply_data);
auto error = static_cast<ErrorType>(reply.get<u8>());
if (is_error(error))
{
return 0;
}
u64 network_time = reply.get<u64>();
if (reply.is_error())
{
error_and_disconnect("Malformed reply to GetNetworkTime command");
return 0;
}
return network_time;
}
bool rpcn_client::get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id)
{
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u16));
@ -1381,8 +1410,8 @@ namespace rpcn
final_memberbinattrinternal_vec, req->teamId, final_optparam);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1418,8 +1447,8 @@ namespace rpcn
auto req_finished = CreateJoinRoomRequest(builder, req->roomId, final_roompassword, final_grouplabel, final_memberbinattrinternal_vec, final_optdata, req->teamId);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1435,8 +1464,8 @@ namespace rpcn
flatbuffers::Offset<PresenceOptionData> final_optdata = CreatePresenceOptionData(builder, builder.CreateVector(req->optData.data, 16), req->optData.length);
auto req_finished = CreateLeaveRoomRequest(builder, req->roomId, final_optdata);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1502,8 +1531,8 @@ namespace rpcn
auto req_finished = s_req.Finish();
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1530,8 +1559,8 @@ namespace rpcn
auto req_finished = CreateGetRoomDataExternalListRequestDirect(builder, &roomIds, &attrIds);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1580,8 +1609,8 @@ namespace rpcn
auto req_finished = CreateSetRoomDataExternalRequest(builder, req->roomId, final_searchintattrexternal_vec, final_searchbinattrexternal_vec, final_binattrexternal_vec);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1609,8 +1638,8 @@ namespace rpcn
auto req_finished = CreateGetRoomDataInternalRequest(builder, req->roomId, final_attr_ids_vec);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1664,8 +1693,8 @@ namespace rpcn
CreateSetRoomDataInternalRequest(builder, req->roomId, req->flagFilter, req->flagAttr, final_binattrinternal_vec, final_grouppasswordconfig_vec, final_passwordSlotMask, final_ownerprivilege_vec);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1693,8 +1722,8 @@ namespace rpcn
auto req_finished = CreateSetRoomMemberDataInternalRequest(builder, req->roomId, req->memberId, req->teamId, final_binattrinternal_vec);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1743,8 +1772,8 @@ namespace rpcn
auto req_finished = CreateSendRoomMessageRequest(builder, req->roomId, req->castType, builder.CreateVector(dst.data(), dst.size()), builder.CreateVector(reinterpret_cast<const u8*>(req->msg.get_ptr()), req->msgLen), req->option);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1797,8 +1826,8 @@ namespace rpcn
auto fb_sendmessage = CreateSendMessageRequest(builder, nested_flatbuffer_vector, npids_vector);
builder.Finish(fb_sendmessage);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(bufsize + sizeof(u32));
reinterpret_cast<le_t<u32>&>(data[0]) = static_cast<u32>(bufsize);
@ -1825,8 +1854,8 @@ namespace rpcn
auto req_finished = CreateRecordScoreRequestDirect(builder, board_id, char_id, score, comment ? (*comment).c_str() : nullptr, score_data ? &*score_data : nullptr);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1842,8 +1871,8 @@ namespace rpcn
auto req_finished = CreateGetScoreRangeRequest(builder, board_id, start_rank, num_rank, with_comment, with_gameinfo);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1867,8 +1896,8 @@ namespace rpcn
auto req_finished = CreateGetScoreNpIdRequest(builder, board_id, builder.CreateVector(davec), with_comment, with_gameinfo);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1884,8 +1913,8 @@ namespace rpcn
auto req_finished = CreateGetScoreFriendsRequest(builder, board_id, include_self, max_entries, with_comment, with_gameinfo);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1901,8 +1930,8 @@ namespace rpcn
auto req_finished = CreateRecordScoreGameDataRequest(builder, board_id, pc_id, score);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize + sizeof(u32) + score_data.size());
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1920,8 +1949,8 @@ namespace rpcn
auto req_finished = CreateGetScoreGameDataRequest(builder, board_id, builder.CreateString(reinterpret_cast<const char*>(npid.handle.data)), pc_id);
builder.Finish(req_finished);
u8* buf = builder.GetBufferPointer();
usz bufsize = builder.GetSize();
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
@ -1931,6 +1960,324 @@ namespace rpcn
return forge_send(CommandType::GetScoreData, req_id, data);
}
bool rpcn_client::tus_set_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser)
{
const std::vector<s32> slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum);
const std::vector<s64> variable_array(variableArray.get_ptr(), variableArray.get_ptr() + arrayNum);
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusSetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array), builder.CreateVector(variable_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusSetMultiSlotVariable, req_id, data);
}
bool rpcn_client::tus_get_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
{
const std::vector<s32> slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum);
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusGetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiSlotVariable, req_id, data);
}
bool rpcn_client::tus_get_multiuser_variable(u32 req_id, const SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
std::vector<flatbuffers::Offset<TusUser>> davec;
for (s32 i = 0; i < arrayNum; i++)
{
davec.push_back(CreateTusUser(builder, vuser, builder.CreateString(targetNpIdArray[i].data)));
}
auto req_finished = CreateTusGetMultiUserVariableRequest(builder, builder.CreateVector(davec), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiUserVariable, req_id, data);
}
bool rpcn_client::tus_get_friends_variable(u32 req_id, const SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum)
{
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusGetFriendsVariableRequest(builder, slotId, includeSelf, sortType, arrayNum);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetFriendsVariable, req_id, data);
}
bool rpcn_client::tus_add_and_get_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
flatbuffers::Offset<flatbuffers::Vector<uint64_t>> isLastChangedDate;
flatbuffers::Offset<flatbuffers::String> isLastChangedAuthorId;
if (option)
{
if (option->isLastChangedDate)
{
std::vector<u64> is_last_changed_date_vec;
is_last_changed_date_vec.push_back(option->isLastChangedDate->tick);
isLastChangedDate = builder.CreateVector(is_last_changed_date_vec);
}
if (option->isLastChangedAuthorId)
{
isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data);
}
}
auto req_finished = CreateTusAddAndGetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, inVariable, isLastChangedDate, isLastChangedAuthorId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusAddAndGetVariable, req_id, data);
}
bool rpcn_client::tus_try_and_set_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
flatbuffers::Offset<flatbuffers::Vector<uint64_t>> isLastChangedDate;
flatbuffers::Offset<flatbuffers::String> isLastChangedAuthorId;
flatbuffers::Offset<flatbuffers::Vector<int64_t>> compareValue;
if (option)
{
if (option->isLastChangedDate)
{
std::vector<u64> is_last_changed_date_vec;
is_last_changed_date_vec.push_back(option->isLastChangedDate->tick);
isLastChangedDate = builder.CreateVector(is_last_changed_date_vec);
}
if (option->isLastChangedAuthorId)
{
isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data);
}
if (option->compareValue)
{
std::vector<s64> compare_value_vec;
compare_value_vec.push_back(*(option->compareValue));
compareValue = builder.CreateVector(compare_value_vec);
}
}
auto req_finished = CreateTusTryAndSetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, opeType, variable, isLastChangedDate, isLastChangedAuthorId, compareValue);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusTryAndSetVariable, req_id, data);
}
bool rpcn_client::tus_delete_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
{
const std::vector<s32> slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum);
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusDeleteMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusDeleteMultiSlotVariable, req_id, data);
}
bool rpcn_client::tus_set_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, const std::vector<u8>& tus_data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
flatbuffers::Offset<flatbuffers::Vector<uint64_t>> isLastChangedDate;
flatbuffers::Offset<flatbuffers::String> isLastChangedAuthorId;
if (option)
{
if (option->isLastChangedDate)
{
std::vector<u64> is_last_changed_date_vec;
is_last_changed_date_vec.push_back(option->isLastChangedDate->tick);
isLastChangedDate = builder.CreateVector(is_last_changed_date_vec);
}
if (option->isLastChangedAuthorId)
{
isLastChangedAuthorId = builder.CreateString(option->isLastChangedAuthorId->handle.data);
}
}
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> fb_info;
if (info)
{
fb_info = builder.CreateVector(info->data, static_cast<size_t>(info->infoSize));
}
auto req_finished = CreateTusSetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, builder.CreateVector(tus_data), fb_info, isLastChangedDate, isLastChangedAuthorId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusSetData, req_id, data);
}
bool rpcn_client::tus_get_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusGetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetData, req_id, data);
}
bool rpcn_client::tus_get_multislot_data_status(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
{
const std::vector<s32> slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum);
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusGetMultiSlotDataStatusRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiSlotDataStatus, req_id, data);
}
bool rpcn_client::tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser)
{
flatbuffers::FlatBufferBuilder builder(1024);
std::vector<flatbuffers::Offset<TusUser>> davec;
for (s32 i = 0; i < arrayNum; i++)
{
davec.push_back(CreateTusUser(builder, vuser, builder.CreateString(targetNpIdArray[i].data)));
}
auto req_finished = CreateTusGetMultiUserDataStatusRequest(builder, builder.CreateVector(davec), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiUserDataStatus, req_id, data);
}
bool rpcn_client::tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum)
{
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusGetFriendsDataStatusRequest(builder, slotId, includeSelf, sortType, arrayNum);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetFriendsDataStatus, req_id, data);
}
bool rpcn_client::tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
{
const std::vector<s32> slotid_array(slotIdArray.get_ptr(), slotIdArray.get_ptr() + arrayNum);
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateTusDeleteMultiSlotDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusDeleteMultiSlotData, req_id, data);
}
std::vector<u8> rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const
{
u32 packet_size = data.size() + RPCN_HEADER_SIZE;

View File

@ -26,6 +26,7 @@
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include "Emu/Cell/Modules/sceNpTus.h"
#include "generated/np2_structs_generated.h"
@ -182,6 +183,20 @@ namespace rpcn
GetScoreRange,
GetScoreFriends,
GetScoreNpid,
GetNetworkTime,
TusSetMultiSlotVariable,
TusGetMultiSlotVariable,
TusGetMultiUserVariable,
TusGetFriendsVariable,
TusAddAndGetVariable,
TusTryAndSetVariable,
TusDeleteMultiSlotVariable,
TusSetData,
TusGetData,
TusGetMultiSlotDataStatus,
TusGetMultiUserDataStatus,
TusGetFriendsDataStatus,
TusDeleteMultiSlotData,
};
enum NotificationType : u16
@ -253,6 +268,7 @@ namespace rpcn
ScoreNotBest, // A better score is already registered for that user/character_id
ScoreInvalid, // Score for player was found but wasn't what was expected
ScoreHasData, // Score already has data
CondFail, // Condition related to query failed
Unsupported,
__error_last
};
@ -386,6 +402,7 @@ namespace rpcn
// Synchronous requests
bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector<u16>& server_list);
u64 get_network_time(u32 req_id);
// Asynchronous requests
bool get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id);
bool createjoin_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req);
@ -409,6 +426,19 @@ namespace rpcn
bool get_score_friend(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, bool include_self, bool with_comment, bool with_gameinfo, u32 max_entries);
bool record_score_data(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScorePcId pc_id, SceNpScoreBoardId board_id, s64 score, const std::vector<u8>& score_data);
bool get_score_data(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScorePcId pc_id, SceNpScoreBoardId board_id, const SceNpId& npid);
bool tus_set_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser);
bool tus_get_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser);
bool tus_get_multiuser_variable(u32 req_id, const SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser);
bool tus_get_friends_variable(u32 req_id, const SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum);
bool tus_add_and_get_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser);
bool tus_try_and_set_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser);
bool tus_delete_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser);
bool tus_set_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, const std::vector<u8>& tus_data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser);
bool tus_get_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, bool vuser);
bool tus_get_multislot_data_status(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser);
bool tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser);
bool tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum);
bool tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser);
const std::string& get_online_name() const
{
@ -472,7 +502,7 @@ namespace rpcn
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync;
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies; // req id / (command / data)
std::unordered_map<u64, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(Login, Create, GetServerList)
std::unordered_map<u64, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(see handle_input())
// Messages
struct message_cb_t

View File

@ -73,7 +73,6 @@ public:
void start_sig(u32 conn_id, u32 addr, u16 port);
void stop_sig(u32 conn_id);
void start_sig2(u64 room_id, u16 member_id);
void disconnect_sig2_users(u64 room_id);
static constexpr auto thread_name = "Signaling Manager Thread"sv;
@ -120,7 +119,6 @@ private:
u32 get_always_conn_id(const SceNpId& npid);
static void update_si_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port);
static void update_si_mapped_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port);
static void update_room_info(std::shared_ptr<signaling_info>& si, u64 room_id, u16 member_id);
void update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status);
void update_ext_si_status(std::shared_ptr<signaling_info>& si, bool op_activated);
void signal_sig_callback(u32 conn_id, int event);
@ -134,7 +132,7 @@ private:
void stop_sig_nl(u32 conn_id);
shared_mutex data_mutex;
atomic_t<u32> wakey;
atomic_t<u32> wakey = 0;
signaling_packet sig_packet{};