Skip to content

Commit

Permalink
Merge pull request #262 from pacampbell/gp_course_support
Browse files Browse the repository at this point in the history
feat: Add support for GP course effects
  • Loading branch information
alborrajo authored Apr 21, 2024
2 parents d3b4d7e + 8dfe5c9 commit aea24ea
Show file tree
Hide file tree
Showing 21 changed files with 1,432 additions and 32 deletions.
17 changes: 9 additions & 8 deletions Arrowgene.Ddon.GameServer/DdonGameServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public DdonGameServer(GameServerSetting setting, IDatabase database, AssetReposi
public List<CDataStageInfo> StageList { get; }

public override GameClientLookup ClientLookup { get; }

// TODO: Maybe place somewhere else
public readonly Dictionary<uint, DateTime> LastRevivalPowerRechargeTime = new Dictionary<uint, DateTime>();

Expand Down Expand Up @@ -164,7 +164,7 @@ private void LoadPacketHandler()
AddHandler(new BazaarGetItemInfoHandler(this));
AddHandler(new BazaarGetItemListHandler(this));
AddHandler(new BazaarProceedsHandler(this));

AddHandler(new BinarySaveSetCharacterBinSavedataHandler(this));
AddHandler(new BlackListGetBlackListHandler(this));

Expand Down Expand Up @@ -216,7 +216,7 @@ private void LoadPacketHandler()
AddHandler(new CraftGetCraftSettingHandler(this));
AddHandler(new CraftRecipeGetCraftRecipeHandler(this));
AddHandler(new CraftStartCraftHandler(this));

AddHandler(new DailyMissionListGetHandler(this));

AddHandler(new EquipChangeCharacterEquipHandler(this));
Expand All @@ -239,8 +239,9 @@ private void LoadPacketHandler()
AddHandler(new Gp_28_2_1_Handler(this));
AddHandler(new GpGetUpdateAppCourseBonusFlagHandler(this));
AddHandler(new GpGetValidChatComGroupHandler(this));
AddHandler(new GpGpEditGetVoiceListHandler(this));
AddHandler(new GpGetGpHandler(this));
AddHandler(new GpGpEditGetVoiceListHandler(this));
AddHandler(new GpGetGpHandler(this));
AddHandler(new GpGpCourseGetAvailableListHandler(this));

AddHandler(new GroupChatGroupChatGetMemberListHandler(this));

Expand Down Expand Up @@ -333,10 +334,10 @@ private void LoadPacketHandler()
AddHandler(new PawnJoinPartyMypawnHandler(this));
AddHandler(new PawnPawnLostHandler(this));
AddHandler(new PawnTrainingGetPreparetionInfoToAdviceHandler(this));

AddHandler(new ProfileGetCharacterProfileHandler(this));
AddHandler(new ProfileGetMyCharacterProfileHandler(this));

AddHandler(new QuestEndDistributionQuestCancelHandler(this));
AddHandler(new QuestGetAdventureGuideQuestListHandler(this));
AddHandler(new QuestGetAdventureGuideQuestNoticeHandler(this));
Expand All @@ -363,7 +364,7 @@ private void LoadPacketHandler()
AddHandler(new QuestSendLeaderQuestOrderConditionInfoHandler(this));
AddHandler(new QuestSendLeaderWaitOrderQuestListHandler(this));
AddHandler(new QuestSetPriorityQuestHandler(this));

AddHandler(new EntryBoardEntryBoardList(this));
AddHandler(new EntryBoardEntryBoardItemCreate(this));
AddHandler(new EntryBoardEntryBoardItemForceStart(this));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Arrowgene.Ddon.GameServer.Dump;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared;
using Arrowgene.Ddon.Shared.Entity;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.Structure;
Expand All @@ -13,9 +14,11 @@ public class CharacterDecideCharacterIdHandler : PacketHandler<GameClient>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(CharacterDecideCharacterIdHandler));

private AssetRepository _AssetRepo;

public CharacterDecideCharacterIdHandler(DdonGameServer server) : base(server)
{
_AssetRepo = server.AssetRepository;
}

public override PacketId Id => PacketId.C2S_CHARACTER_DECIDE_CHARACTER_ID_REQ;
Expand All @@ -27,12 +30,21 @@ public override void Handle(GameClient client, IPacket packet)
res.CharacterId = client.Character.CharacterId;
res.CharacterInfo = new CDataCharacterInfo(client.Character);
res.Unk0 = pcap.Unk0; // Removing this makes tons of tutorials pop up

client.Send(res);

// Unlocks menu options such as inventory, warping, etc.
S2CCharacterContentsReleaseElementNtc contentsReleaseElementNotice = EntitySerializer.Get<S2CCharacterContentsReleaseElementNtc>().Read(GameFull.data_Dump_20);
client.Send(contentsReleaseElementNotice);

foreach (var ValidCourse in _AssetRepo.GPCourseInfoAsset.ValidCourses)
{
client.Send(new S2CGPCourseStartNtc()
{
CourseID = ValidCourse.Value.Id,
ExpiryTimestamp = ValidCourse.Value.EndTime
});
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.GameServer.Dump;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;

namespace Arrowgene.Ddon.GameServer.Handler
{
public class GpGpCourseGetAvailableListHandler : PacketHandler<GameClient>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(GpGpCourseGetAvailableListHandler));

private AssetRepository _AssetRepo;

public GpGpCourseGetAvailableListHandler(DdonGameServer server) : base(server)
{
_AssetRepo = server.AssetRepository;
}

public override PacketId Id => PacketId.C2S_GP_GP_COURSE_GET_AVAILABLE_LIST_REQ;

public override void Handle(GameClient client, IPacket packet)
{
S2CGpGpCourseGetAvailableListRes Response = new S2CGpGpCourseGetAvailableListRes();

// foreach (var Course in _AssetRepo.GPCourseInfoAsset.ValidCourses)
// {
//
// }

// TODO: Send back real data based on JSON contents?
// TODO: PCAP doesn't have sample packet contents to see what is in it.
client.Send(Response);
}
}
}
30 changes: 28 additions & 2 deletions Arrowgene.Ddon.LoginServer/Handler/GetCharacterListHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using Arrowgene.Buffers;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared;
using Arrowgene.Ddon.Shared.Entity;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Ddon.Shared.Network;
Expand All @@ -14,10 +16,13 @@ namespace Arrowgene.Ddon.LoginServer.Handler
public class GetCharacterListHandler : PacketHandler<LoginClient>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(GetCharacterListHandler));
private AssetRepository _AssetRepo;



public GetCharacterListHandler(DdonLoginServer server) : base(server)
{
_AssetRepo = server.AssetRepository;
}

public override PacketId Id => PacketId.C2L_GET_CHARACTER_LIST_REQ;
Expand All @@ -39,6 +44,27 @@ public override void Handle(LoginClient client, IPacket packet)
cResponse.CharacterListElement.CommunityCharacterBaseInfo.CharacterName.LastName = c.LastName;
cResponse.CharacterListElement.CurrentJobBaseInfo.Job = c.Job;
cResponse.CharacterListElement.CurrentJobBaseInfo.Level = (byte) c.ActiveCharacterJobData.Lv;

List<CDataGPCourseValid> ValidCourses = new List<CDataGPCourseValid>();

foreach (var ValidCourse in _AssetRepo.GPCourseInfoAsset.ValidCourses)
{
CDataGPCourseValid cDataGPCourseValid = new CDataGPCourseValid()
{
Id = c.CharacterId,
CourseId = ValidCourse.Value.Id,
NameA = _AssetRepo.GPCourseInfoAsset.Courses[ValidCourse.Value.Id].Name, // Course Name
NameB = _AssetRepo.GPCourseInfoAsset.Courses[ValidCourse.Value.Id].IconPath, // Link to a icon
StartTime = ValidCourse.Value.StartTime,
EndTime = ValidCourse.Value.EndTime,
};

ValidCourses.Add(cDataGPCourseValid);
}

cResponse.GpCourseValidList = ValidCourses;
cResponse.NextFlowType = 1;
cResponse.IsClanMemberNotice = 1; // REMOVE
// maybe?
//cResponse.CharacterListElement.CurrentJobBaseInfo.Job = c.CharacterInfo.MatchingProfile.CurrentJob;
//cResponse.CharacterListElement.CurrentJobBaseInfo.Level = (byte) c.CharacterInfo.MatchingProfile.CurrentJobLevel;
Expand All @@ -48,11 +74,11 @@ public override void Handle(LoginClient client, IPacket packet)
cResponse.MatchingProfile = c.MatchingProfile;
cResponse.EquipItemInfo = c.Equipment.getEquipmentAsCDataEquipItemInfo(c.Job, EquipType.Performance)
.Union(c.Equipment.getEquipmentAsCDataEquipItemInfo(c.Job, EquipType.Visual))
.ToList();
.ToList();

characterListResponse.Add(cResponse);
}

EntitySerializer.Get<CDataCharacterListInfo>().WriteList(buffer, characterListResponse);
Packet response = new Packet(PacketId.L2C_GET_CHARACTER_LIST_RES, buffer.GetAllBytes());
client.Send(response);
Expand Down
43 changes: 41 additions & 2 deletions Arrowgene.Ddon.LoginServer/Handler/GpCourseGetInfoHandler.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,64 @@
using Arrowgene.Ddon.LoginServer.Dump;
using Arrowgene.Ddon.LoginServer.Dump;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Logging;
using System;
using System.Linq;

namespace Arrowgene.Ddon.LoginServer.Handler
{
public class GpCourseGetInfoHandler : PacketHandler<LoginClient>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(GpCourseGetInfoHandler));

private AssetRepository _AssetRepo;

public GpCourseGetInfoHandler(DdonLoginServer server) : base(server)
{
_AssetRepo = server.AssetRepository;
}

public override PacketId Id => PacketId.C2L_GP_COURSE_GET_INFO_REQ;

public override void Handle(LoginClient client, IPacket packet)
{
client.Send(LoginDump.Dump_22);
L2CGpCourseGetInfoRes Response = new L2CGpCourseGetInfoRes();

foreach (var Course in _AssetRepo.GPCourseInfoAsset.Courses)
{
CDataGPCourseInfo cDataGPCourseInfo = new CDataGPCourseInfo()
{
CourseId = Course.Value.Id,
CourseName = Course.Value.Name,
DoubleCourseTarget = Course.Value.Target,
PrioGroup = (byte)Course.Value.PriorityGroup,
PrioSameTime = (byte)Course.Value.PrioritySameTime,
AnnounceType = (byte)Course.Value.AnnounceType,
EffectUIDs = Course.Value.Effects
};

Response.CourseInfo.Add(cDataGPCourseInfo);
}

foreach (var Effect in _AssetRepo.GPCourseInfoAsset.Effects)
{
CDataGPCourseEffectParam cDataGPCourseEffectParam = new CDataGPCourseEffectParam()
{
EffectUID = Effect.Value.Uid,
EffectID = Effect.Value.Id,
Param0 = Effect.Value.Param0,
Param1 = Effect.Value.Param1
};

Response.Effects.Add(cDataGPCourseEffectParam);
}

// client.Send(LoginDump.Dump_22);
client.Send(Response);
}
}
}
18 changes: 18 additions & 0 deletions Arrowgene.Ddon.Shared/Asset/GPCourseInfoAsset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;
using Arrowgene.Ddon.Shared.Model;

namespace Arrowgene.Ddon.Shared.Asset
{
public class GPCourseInfoAsset
{
public GPCourseInfoAsset()
{
Courses = new Dictionary<uint, GPCourse>();
Effects = new Dictionary<uint, GpCourseEffect>();
ValidCourses = new Dictionary<uint, GPValidCourse>();
}
public Dictionary<uint, GPCourse> Courses { get; set; }
public Dictionary<uint, GpCourseEffect> Effects { get; set; }
public Dictionary<uint, GPValidCourse> ValidCourses { get; set; }
}
}
76 changes: 76 additions & 0 deletions Arrowgene.Ddon.Shared/AssetReader/GPCourseInfoDeserializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Arrowgene.Ddon.Shared.Model;
using Arrowgene.Logging;
using Arrowgene.Ddon.Shared.Asset;

namespace Arrowgene.Ddon.Shared.Csv
{
public class GPCourseInfoDeserializer : IAssetDeserializer<GPCourseInfoAsset>
{
private static readonly ILogger Logger = LogProvider.Logger(typeof(GPCourseInfoDeserializer));

public GPCourseInfoAsset ReadPath(string path)
{
Logger.Info($"Reading {path}");

GPCourseInfoAsset asset = new GPCourseInfoAsset();

string json = File.ReadAllText(path);
JsonDocument document = JsonDocument.Parse(json);

var ValidCourses = document.RootElement.GetProperty("valid_courses").EnumerateArray().ToList();
foreach (var ValidCourse in ValidCourses)
{
GPValidCourse obj = new GPValidCourse();
obj.Id = ValidCourse.GetProperty("course_id").GetUInt32();
obj.StartTime = ValidCourse.GetProperty("start_time").GetUInt64();
obj.EndTime = ValidCourse.GetProperty("end_time").GetUInt64();
obj.Comment = ValidCourse.GetProperty("comment").GetString();

asset.ValidCourses.Add(obj.Id, obj);
}

var Courses = document.RootElement.GetProperty("courses").EnumerateArray().ToList();
foreach (var Course in Courses)
{
GPCourse obj = new GPCourse();
obj.Id = Course.GetProperty("id").GetUInt32();
obj.Name = Course.GetProperty("name").GetString();
obj.Target = Course.GetProperty("target").GetUInt32() == 1;
obj.PriorityGroup = Course.GetProperty("priority_grp").GetUInt32();
obj.PrioritySameTime = Course.GetProperty("priority_same_time").GetUInt32();
obj.AnnounceType = Course.GetProperty("announce_type").GetUInt32();
obj.Comment = Course.GetProperty("comment").GetString();
obj.Url = Course.GetProperty("url").GetString();
obj.IconPath = Course.GetProperty("icon_path").GetString();
obj.Description = Course.GetProperty("description").GetString();

var EffectUIDs = Course.GetProperty("effects").EnumerateArray().ToList();
foreach (var EffectUID in EffectUIDs)
{
obj.Effects.Add(EffectUID.GetUInt32());
}

asset.Courses.Add(obj.Id, obj);
}

var Effects = document.RootElement.GetProperty("effects").EnumerateArray().ToList();
foreach (var Effect in Effects)
{
GpCourseEffect obj = new GpCourseEffect();
obj.Uid = Effect.GetProperty("uid").GetUInt32();
obj.Id = Effect.GetProperty("id").GetUInt32();
obj.Param0 = Effect.GetProperty("param0").GetUInt32();
obj.Param1 = Effect.GetProperty("param1").GetUInt32();
obj.Comment = Effect.GetProperty("comment").GetString();

asset.Effects.Add(obj.Uid, obj);
}

return asset;
}
}
}
Loading

0 comments on commit aea24ea

Please sign in to comment.