Skip to content

Commit

Permalink
Overhaul contacts/friends list stuff.
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanYappert committed Nov 1, 2024
1 parent 721c397 commit fff8860
Show file tree
Hide file tree
Showing 16 changed files with 241 additions and 226 deletions.
1 change: 1 addition & 0 deletions Arrowgene.Ddon.Database/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ bool requestedFavorite
List<ContactListEntity> SelectContactsByCharacterId(uint characterId);
ContactListEntity SelectContactsByCharacterId(uint characterId1, uint characterId2);
ContactListEntity SelectContactListById(uint id);
List<(ContactListEntity, CDataCharacterListElement)> SelectFullContactListByCharacterId(uint characterId, DbConnection? connectionIn = null);

// Dragon Force Augmentation
bool InsertIfNotExistsDragonForceAugmentation(
Expand Down
64 changes: 63 additions & 1 deletion Arrowgene.Ddon.Database/Sql/Core/DdonSqlDbContactList.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data.Common;
using System.Security.Claims;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Model.Clan;

namespace Arrowgene.Ddon.Database.Sql.Core
{
Expand Down Expand Up @@ -31,6 +34,22 @@ public abstract partial class DdonSqlDb<TCon, TCom, TReader> : SqlDb<TCon, TCom,

private static readonly string SqlUpdateContactByCharIds = $"UPDATE \"{ContactListTableName}\" SET \"status\"=@status, \"type\"=@type, \"requester_favorite\"=@requester_favorite, \"requested_favorite\"=@requested_favorite WHERE \"requester_character_id\"=@requester_character_id and \"requested_character_id\"=@requested_character_id;";

private static readonly string SqlSelectFullContactsByCharacterId = "SELECT \"ddon_contact_list\".*, " +
"\"ddon_character\".\"first_name\", \"ddon_character\".\"last_name\", " +
"\"ddon_character_job_data\".\"job\", \"ddon_character_job_data\".\"lv\"," +
"\"ddon_character_matching_profile\".\"comment\"," +
"CASE WHEN CASE WHEN \"ddon_contact_list\".\"requester_character_id\" = @character_id THEN \"ddon_contact_list\".\"requested_character_id\" ELSE \"ddon_contact_list\".\"requester_character_id\" END NOT IN (SELECT \"character_id\" FROM \"ddon_clan_membership\") THEN \"\"" +
"ELSE (SELECT \"ddon_clan_param\".\"name\" as \"clan_name\" FROM \"ddon_clan_param\" INNER JOIN \"ddon_clan_membership\" ON \"ddon_clan_membership\".\"clan_id\" = \"ddon_clan_param\".\"clan_id\" WHERE \"ddon_clan_membership\".\"character_id\" = CASE WHEN \"ddon_contact_list\".\"requester_character_id\" = 4 THEN \"ddon_contact_list\".\"requested_character_id\" ELSE \"ddon_contact_list\".\"requester_character_id\" END)" +
"END AS \"clan_name\"," +
"CASE WHEN \"ddon_contact_list\".\"requester_character_id\" = @character_id THEN \"ddon_contact_list\".\"requested_character_id\"" +
"ELSE \"ddon_contact_list\".\"requester_character_id\"" +
"END AS \"other_id\"" +
"FROM \"ddon_contact_list\" " +
"INNER JOIN \"ddon_character\" ON \"ddon_character\".\"character_id\" = \"other_id\"" +
"INNER JOIN \"ddon_character_common\" ON \"ddon_character_common\".\"character_common_id\" = \"ddon_character\".\"character_common_id\"" +
"INNER JOIN \"ddon_character_job_data\" ON \"ddon_character_job_data\".\"character_common_id\" = \"ddon_character\".\"character_common_id\" AND \"ddon_character_job_data\".\"job\" = \"ddon_character_common\".\"job\"" +
"INNER JOIN \"ddon_character_matching_profile\" ON \"ddon_character_matching_profile\".\"character_id\" = \"other_id\";";


public int InsertContact(uint requestingCharacterId, uint requestedCharacterId, ContactListStatus status, ContactListType type, bool requesterFavorite, bool requestedFavorite)
{
Expand Down Expand Up @@ -139,6 +158,49 @@ public ContactListEntity SelectContactListById(uint id)
return entity;
}

public List<(ContactListEntity, CDataCharacterListElement)> SelectFullContactListByCharacterId(uint characterId, DbConnection? connectionIn = null)
{
List<(ContactListEntity, CDataCharacterListElement)> list = new();

bool isTransaction = connectionIn is not null;
TCon connection = (TCon)(connectionIn ?? OpenNewConnection());
try
{
ExecuteReader(
connection,
SqlSelectFullContactsByCharacterId,
command =>
{
AddParameter(command, "@character_id", characterId);
},
reader =>
{
while (reader.Read())
{
var contactListEntity = ReadContactListEntity(reader);
var characterListElement = new CDataCharacterListElement();

characterListElement.CommunityCharacterBaseInfo.CharacterId = GetUInt32(reader, "other_id");
characterListElement.CommunityCharacterBaseInfo.CharacterName.FirstName = GetString(reader, "first_name");
characterListElement.CommunityCharacterBaseInfo.CharacterName.LastName = GetString(reader, "last_name");
characterListElement.CommunityCharacterBaseInfo.ClanName = GetStringNullable(reader, "clan_name") ?? string.Empty;
characterListElement.CurrentJobBaseInfo.Job = (JobId)GetByte(reader, "job");
characterListElement.CurrentJobBaseInfo.Level = GetByte(reader, "lv");
characterListElement.EntryJobBaseInfo = characterListElement.CurrentJobBaseInfo;
characterListElement.MatchingProfile = GetString(reader, "comment");

list.Add((contactListEntity, characterListElement));
}
});
}
finally
{
if (!isTransaction) connection.Dispose();
}

return list;
}

private ContactListEntity ReadContactListEntity(TReader reader)
{
ContactListEntity e = new ContactListEntity();
Expand Down
2 changes: 1 addition & 1 deletion Arrowgene.Ddon.GameServer/Characters/ContactListManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static CDataFriendInfo CharacterToFriend(Character c, uint unFriendNo, bo
{
IsFavorite = isFavorite,
PendingStatus = 0x00, // TODO
UnFriendNo = unFriendNo,
FriendNo = unFriendNo,
CharacterListElement = CharacterToListEml(c)

};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,59 @@
using System.Collections.Generic;
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;
using System.Collections.Generic;

namespace Arrowgene.Ddon.GameServer.Handler
{
public class CharacterCommunityCharacterStatusGetHandler : GameStructurePacketHandler<C2SCharacterCommunityCharacterStatusGetReq>
public class CharacterCommunityCharacterStatusGetHandler : GameRequestPacketHandler<C2SCharacterCommunityCharacterStatusGetReq, S2CCharacterCommunityCharacterStatusGetRes>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(CharacterCommunityCharacterStatusGetHandler));


public CharacterCommunityCharacterStatusGetHandler(DdonGameServer server) : base(server)
{
}

// public override PacketId Id => PacketId.C2S_CHARACTER_COMMUNITY_CHARACTER_STATUS_GET_REQ;

public override void Handle(GameClient client, StructurePacket<C2SCharacterCommunityCharacterStatusGetReq> packet)
public override S2CCharacterCommunityCharacterStatusGetRes Handle(GameClient client, C2SCharacterCommunityCharacterStatusGetReq request)
{
// client.Send(InGameDump.Dump_65);

List<CDataCharacterListElement> updateCharacterList = new List<CDataCharacterListElement>();
List<CDataUpdateMatchingProfileInfo> updateMatchingProfileList = new List<CDataUpdateMatchingProfileInfo>();
List<ContactListEntity> friends = Database.SelectContactsByCharacterId(client.Character.CharacterId);
foreach (var f in friends)

List<(ContactListEntity, CDataCharacterListElement)> friends = Database.SelectFullContactListByCharacterId(client.Character.CharacterId);

foreach ((ContactListEntity contact, CDataCharacterListElement character) in friends)
{
if (f.Type != ContactListType.FriendList || f.Status != ContactListStatus.Accepted)
if (contact.Type != ContactListType.FriendList || contact.Status != ContactListStatus.Accepted)
{
continue;
}
Character otherCharacter =
ContactListManager.getCharWithOnlineStatus(Server,Database, f.GetOtherCharacterId(client.Character.CharacterId));
updateCharacterList.Add(ContactListManager.CharacterToListEml(otherCharacter));

var matchClient = Server.ClientLookup.GetClientByCharacterId(character.CommunityCharacterBaseInfo.CharacterId);
if (matchClient != null)
{
character.OnlineStatus = matchClient.Character?.OnlineStatus ?? OnlineStatus.Offline;
character.ServerId = (ushort)Server.Id;
}

updateCharacterList.Add(character);
updateMatchingProfileList.Add(new CDataUpdateMatchingProfileInfo()
{
CharacterId = otherCharacter.CharacterId,
Comment = otherCharacter.MatchingProfile.Comment
CharacterId = character.CommunityCharacterBaseInfo.CharacterId,
Comment = character.MatchingProfile,
});
}

client.Send(new S2CCharacterCommunityCharacterStatusUpdateNtc()
{
UpdateCharacterList = updateCharacterList,
UpdateMatchingProfileList = updateMatchingProfileList
});
client.Send(new S2CCharacterCommunityCharacterStatusGetRes()

return new S2CCharacterCommunityCharacterStatusGetRes()
{
Result = updateCharacterList.Count + 1
});
Result = (uint)(updateCharacterList.Count + 1) // ???
};
}
}
}
73 changes: 24 additions & 49 deletions Arrowgene.Ddon.GameServer/Handler/FriendApplyFriendListHandler.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;

namespace Arrowgene.Ddon.GameServer.Handler
{
public class FriendApplyFriendListHandler : GameStructurePacketHandler<C2SFriendApplyFriendReq>
public class FriendApplyFriendListHandler : GameRequestPacketHandler<C2SFriendApplyFriendReq, S2CFriendApplyFriendRes>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(FriendApplyFriendListHandler));

Expand All @@ -17,70 +16,52 @@ public FriendApplyFriendListHandler(DdonGameServer server) : base(server)
{
}

public override void Handle(GameClient client, StructurePacket<C2SFriendApplyFriendReq> packet)
public override S2CFriendApplyFriendRes Handle(GameClient client, C2SFriendApplyFriendReq request)
{
ContactListEntity existingFriend = Server.Database.SelectContactsByCharacterId(packet.Structure.CharacterId, client.Character.CharacterId);

ContactListEntity existingFriend = Server.Database.SelectContactsByCharacterId(request.CharacterId, client.Character.CharacterId);
if (existingFriend != null)
{
uint errorCode = (uint)ErrorCode.ERROR_CODE_FAIL;
ErrorCode errorCode = ErrorCode.ERROR_CODE_FAIL;

if (existingFriend.Type == ContactListType.BlackList && client.Character.CharacterId == existingFriend.RequesterCharacterId)
{
errorCode = (uint)ErrorCode.ERROR_CODE_FRIEND_TARGET_IN_BLACK_LIST;
errorCode = ErrorCode.ERROR_CODE_FRIEND_TARGET_IN_BLACK_LIST;
}
else if (existingFriend.Status == ContactListStatus.Accepted)
{
errorCode = (uint)ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_FRIEND;
errorCode = ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_FRIEND;
}
else if (existingFriend.Status == ContactListStatus.PendingApproval && client.Character.CharacterId == existingFriend.RequesterCharacterId)
{
errorCode = (uint)ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_APPLYING;
errorCode = ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_APPLYING;
}
else if (existingFriend.Status == ContactListStatus.PendingApproval && client.Character.CharacterId == existingFriend.RequestedCharacterId)
{
errorCode = (uint)ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_APPROVING;
errorCode = ErrorCode.ERROR_CODE_FRIEND_TARGET_ALREADY_APPROVING;
}
var res = new S2CFriendApplyFriendRes()
{
FriendInfo = new CDataFriendInfo(),
Error = errorCode
};
Logger.Error(client, $"already in contact list: {packet.Structure.CharacterId} - friend invitation");
client.Send(res);
return;
}

Character requestedChar = ContactListManager.getCharWithOnlineStatus(Server, Database, packet.Structure.CharacterId);
if (requestedChar == null)
{
var res = new S2CFriendApplyFriendRes();
Logger.Error(client, $"not found CharacterId:{packet.Structure.CharacterId} for friend invitation");
res.Error = (uint)ErrorCode.ERROR_CODE_FRIEND_TARGET_PARAM_NOT_FOUND;
client.Send(res);
return;

throw new ResponseErrorException(errorCode, $"already in contact list: {request.CharacterId} - friend invitation.");
}

Character requestedChar = Server.ClientLookup.GetClientByCharacterId(request.CharacterId)?.Character
?? ContactListManager.getCharWithOnlineStatus(Server, Database, request.CharacterId)
?? throw new ResponseErrorException(ErrorCode.ERROR_CODE_FRIEND_TARGET_PARAM_NOT_FOUND, $"not found CharacterId:{request.CharacterId} for friend invitation.");

int id = Database.InsertContact(client.Character.CharacterId, requestedChar.CharacterId,
ContactListStatus.PendingApproval, ContactListType.FriendList, false, false);

if (id < 1)
{
var res = new S2CFriendApplyFriendRes()
{
FriendInfo = new CDataFriendInfo()
};
Logger.Error(client, $"Problem saving friend request");
res.Error = (uint)ErrorCode.ERROR_CODE_FAIL;
client.Send(res);
return;
throw new ResponseErrorException(ErrorCode.ERROR_CODE_FAIL, $"Problem saving friend request.");
}

CDataFriendInfo requester = ContactListManager.CharacterToFriend(client.Character, (uint)id, false);
CDataFriendInfo requested = ContactListManager.CharacterToFriend(requestedChar, (uint)id, false);
requester.UnFriendNo = (uint)id;
requested.UnFriendNo = (uint)id;
requester.FriendNo = (uint)id;
requested.FriendNo = (uint)id;

GameClient requestedClient = Server.ClientLookup.GetClientByCharacterId(packet.Structure.CharacterId);
GameClient requestedClient = Server.ClientLookup.GetClientByCharacterId(request.CharacterId);
if (requestedClient != null)
{
var ntc = new S2CFriendApplyFriendNtc()
Expand All @@ -90,16 +71,10 @@ public override void Handle(GameClient client, StructurePacket<C2SFriendApplyFri
requestedClient.Send(ntc);
}


var Result = new S2CFriendApplyFriendRes()
return new S2CFriendApplyFriendRes()
{
FriendInfo = requested,
Result = 0,
Error = 0,

FriendInfo = requested
};

client.Send(Result);
}
}
}
Loading

0 comments on commit fff8860

Please sign in to comment.