Skip to content

Commit

Permalink
Merge pull request #587 from RyanYappert/feat/box-full-error-codes
Browse files Browse the repository at this point in the history
Feat: Actual errors when doing things with a full storage chest.
  • Loading branch information
RyanYappert authored Oct 3, 2024
2 parents ff1b2a2 + 348b186 commit eda86d4
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 16 deletions.
42 changes: 41 additions & 1 deletion Arrowgene.Ddon.GameServer/Characters/JobManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,21 @@ public JobManager(DdonGameServer server)
_Server = server;
}

public (IPacketStructure jobRes, IPacketStructure itemNtc, IPacketStructure jobNtc) SetJob(GameClient client, CharacterCommon common, JobId jobId, DbConnection? connectionIn = null)
public (IPacketStructure jobRes, IPacketStructure? itemNtc, IPacketStructure? jobNtc) SetJob(GameClient client, CharacterCommon common, JobId jobId, DbConnection? connectionIn = null)
{
// TODO: Reject job change if there's no primary and secondary weapon for the new job in storage
// (or give a lvl 1 weapon for free?)

if (!HasEmptySlotsForTemplateSwap(client, common, common.Job, jobId))
{
return (new S2CJobChangeJobRes()
{
Error = (uint)ErrorCode.ERROR_CODE_JOBCHANGE_ITEM_CAPACITY_OVER
},
null,
null);
}

JobId oldJobId = common.Job;
common.Job = jobId;

Expand Down Expand Up @@ -278,6 +288,36 @@ private List<CDataItemUpdateResult> SwapEquipmentAndStorage(GameClient client, C
return itemUpdateResultList;
}

private static bool HasEmptySlotsForTemplateSwap(GameClient client, CharacterCommon common, JobId oldJobId, JobId newJobId)
{
var availableSlots = client.Character.Storage.GetStorage(StorageType.StorageBoxNormal).EmptySlots();

var neededSlots = common.Equipment.GetItems(EquipType.Performance)
.Concat(common.Equipment.GetItems(EquipType.Visual))
.Where(x => x != null)
.ToList()
.Count;

// If the item isn't moving, it doesn't need a space in the box.
foreach (var equipType in new List<EquipType>(){ EquipType.Performance, EquipType.Visual })
{
List<Item?> oldEquipment = common.Equipment.GetItems(equipType);
List<Item?> newEquipmentTemplate = common.EquipmentTemplate.GetEquipment(newJobId, equipType);

for (int i = 0; i < oldEquipment.Count; i++)
{
if (oldEquipment[i] != null && newEquipmentTemplate[i] != null && oldEquipment[i] == newEquipmentTemplate[i])
{
neededSlots--;
}
}
}

// TODO: Account for one-to-one swaps, as well as jewelry shuffling order.

return neededSlots <= availableSlots;
}

public void UnlockSkill(IDatabase database, GameClient client, CharacterCommon character, JobId job, uint skillId, byte skillLv)
{
// Check if there is a learned skill of the same ID (This unlock is a level upgrade)
Expand Down
28 changes: 16 additions & 12 deletions Arrowgene.Ddon.GameServer/Handler/JobChangeJobHandler.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.Server;
using Arrowgene.Ddon.Server.Network;
using Arrowgene.Ddon.Shared.Entity.PacketStructure;
using Arrowgene.Logging;
using Arrowgene.Ddon.Shared.Network;
using Arrowgene.Ddon.GameServer.Characters;
using Arrowgene.Ddon.Shared.Entity.Structure;
using Arrowgene.Ddon.Shared.Entity;

namespace Arrowgene.Ddon.GameServer.Handler
{
public class JobChangeJobHandler : StructurePacketHandler<GameClient, C2SJobChangeJobReq>
public class JobChangeJobHandler : GameRequestPacketHandler<C2SJobChangeJobReq, S2CJobChangeJobRes>
{
private static readonly ServerLogger Logger = LogProvider.Logger<ServerLogger>(typeof(JobChangeJobHandler));

Expand All @@ -20,22 +16,30 @@ public JobChangeJobHandler(DdonGameServer server) : base(server)
jobManager = server.JobManager;
}

public override void Handle(GameClient client, StructurePacket<C2SJobChangeJobReq> packet)
public override S2CJobChangeJobRes Handle(GameClient client, C2SJobChangeJobReq request)
{
(S2CJobChangeJobRes jobRes, S2CItemUpdateCharacterItemNtc itemNtc, S2CJobChangeJobNtc jobNtc) jobResult = (null, null, null);

Server.Database.ExecuteInTransaction(connection =>
{
jobResult = ((S2CJobChangeJobRes, S2CItemUpdateCharacterItemNtc, S2CJobChangeJobNtc))
jobManager.SetJob(client, client.Character, packet.Structure.JobId, connection);
jobManager.SetJob(client, client.Character, request.JobId, connection);
});

foreach (GameClient otherClient in Server.ClientLookup.GetAll())
if (jobResult.jobNtc != null)
{
otherClient.Send(jobResult.jobNtc);
foreach (GameClient otherClient in Server.ClientLookup.GetAll())
{
otherClient.Send(jobResult.jobNtc);
}
}
client.Send(jobResult.itemNtc);
client.Send(jobResult.jobRes);

if (jobResult.itemNtc != null)
{
client.Send(jobResult.itemNtc);
}

return jobResult.jobRes;
}
}
}
14 changes: 11 additions & 3 deletions Arrowgene.Ddon.GameServer/Handler/JobChangePawnJobHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ public override void Handle(GameClient client, StructurePacket<C2SJobChangePawnJ
jobManager.SetJob(client, pawn, packet.Structure.JobId, connection);
});

foreach (GameClient otherClient in Server.ClientLookup.GetAll())
if (jobResult.jobNtc != null)
{
otherClient.Send(jobResult.jobNtc);
foreach (GameClient otherClient in Server.ClientLookup.GetAll())
{
otherClient.Send(jobResult.jobNtc);
}
}
client.Send(jobResult.itemNtc);

if (jobResult.itemNtc != null)
{
client.Send(jobResult.itemNtc);
}

client.Send(jobResult.jobRes);
}
}
Expand Down
17 changes: 17 additions & 0 deletions Arrowgene.Ddon.GameServer/Handler/PawnCreatePawnHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public PawnCreatePawnHandler(DdonGameServer server) : base(server)

public override S2CPawnCreatePawnRes Handle(GameClient client, C2SPawnCreatePawnReq request)
{
// I hate hardcoding this but people legitimately keep finding ways to break this.
if (request.SlotNo > 3)
{
throw new ResponseErrorException(ErrorCode.ERROR_CODE_PAWN_CREATE_NUM_OVER);
}

if (request.SlotNo == 1)
{
const byte myPawnSlotNum = 2;
Expand Down Expand Up @@ -62,6 +68,17 @@ public override S2CPawnCreatePawnRes Handle(GameClient client, C2SPawnCreatePawn
Error = (uint)ErrorCode.ERROR_CODE_CHARACTER_ITEM_NOT_FOUND
};
}
else
{
client.Send(new S2CItemUpdateCharacterItemNtc()
{
UpdateType = ItemNoticeType.CreatePawn,
UpdateItemList = new()
{
result
}
});
}
}

Pawn pawn = new Pawn(client.Character.CharacterId)
Expand Down
10 changes: 10 additions & 0 deletions Arrowgene.Ddon.GameServer/Handler/QuestGetRewardBoxItemHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ public override S2CQuestGetRewardBoxItemRes Handle(GameClient client, C2SQuestGe
}
}

var slotCount = coalescedRewards
.Where(x => !Server.ItemManager.IsItemWalletPoint(x.Value.ItemId) && x.Value.Num > 0)
.ToList()
.Count;

if (slotCount > client.Character.Storage.GetStorage(StorageType.StorageBoxNormal).EmptySlots())
{
throw new ResponseErrorException(ErrorCode.ERROR_CODE_ITEM_STORAGE_OVERFLOW);
}

foreach (var rewardUID in packet.GetRewardBoxItemList.Select(x => x.UID).Distinct().ToList())
{
var reward = coalescedRewards[rewardUID];
Expand Down

0 comments on commit eda86d4

Please sign in to comment.