Skip to content

Commit

Permalink
Merge pull request #2798 from moreal/backmerge-1.17.3
Browse files Browse the repository at this point in the history
Backmerge 1.17.3
  • Loading branch information
U-lis authored Aug 29, 2024
2 parents e92330b + 1404a36 commit 776c911
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 16 deletions.
59 changes: 59 additions & 0 deletions .Lib9c.Tests/Action/HackAndSlashSweepTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -705,5 +705,64 @@ public void ExecuteDuplicatedException(int slotIndex, int runeId, int slotIndex2
throw new SheetRowNotFoundException(nameof(StageSheet), stageId);
}
}

[Theory]
[InlineData(0, -1)]
[InlineData(0, int.MinValue + 1)]
[InlineData(-1, 0)]
[InlineData(int.MinValue + 1, 0)]
public void Execute_ArgumentOutOfRangeException(int ap, int apPotion)
{
var avatarState = new AvatarState(
_avatarAddress,
_agentAddress,
0,
_initialState.GetAvatarSheets(),
_rankingMapAddress)
{
worldInformation =
new WorldInformation(0, _initialState.GetSheet<WorldSheet>(), 25),
level = 400,
};

IWorld state = _initialState.SetAvatarState(_avatarAddress, avatarState)
.SetActionPoint(_avatarAddress, 0);
var actionPoint = _initialState.GetActionPoint(_avatarAddress);

var stageSheet = _initialState.GetSheet<StageSheet>();
var (expectedLevel, expectedExp) = (0, 0L);
if (stageSheet.TryGetValue(2, out var stageRow))
{
var itemPlayCount =
DailyReward.ActionPointMax / stageRow.CostAP * 1;
var apPlayCount = actionPoint / stageRow.CostAP;
var playCount = apPlayCount + itemPlayCount;
(expectedLevel, expectedExp) = avatarState.GetLevelAndExp(
_tableSheets.CharacterLevelSheet,
2,
(int)playCount);

var (equipments, costumes) = GetDummyItems(avatarState);
var action = new HackAndSlashSweep
{
runeInfos = new List<RuneSlotInfo>(),
costumes = costumes,
equipments = equipments,
avatarAddress = _avatarAddress,
actionPoint = ap,
apStoneCount = apPotion,
worldId = 1,
stageId = 2,
};

Assert.Throws<ArgumentOutOfRangeException>(() =>
action.Execute(new ActionContext()
{
PreviousState = state,
Signer = _agentAddress,
RandomSeed = 0,
}));
}
}
}
}
34 changes: 34 additions & 0 deletions .Lib9c.Tests/Action/RegisterProductTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,40 @@ public void Execute_Throw_ArgumentOutOfRangeException()
Assert.Throws<ArgumentOutOfRangeException>(() => action.Execute(new ActionContext()));
}

[Fact]
public void Execute_Throw_DuplicateOrderIdException()
{
var asset = 3 * RuneHelper.DailyRewardRune;
var context = new ActionContext();
var random = new TestRandom();
var productId = random.GenerateRandomGuid();
_initialState = _initialState
.SetAvatarState(AvatarAddress, _avatarState)
.SetLegacyState(Product.DeriveAddress(productId), List.Empty)
.MintAsset(context, AvatarAddress, asset);
var action = new RegisterProduct
{
AvatarAddress = AvatarAddress,
RegisterInfos = new List<IRegisterInfo>
{
new AssetInfo
{
AvatarAddress = AvatarAddress,
Asset = asset,
Price = 1 * Gold,
Type = ProductType.FungibleAssetValue,
},
},
};
Assert.Throws<DuplicateOrderIdException>(() => action.Execute(new ActionContext
{
BlockIndex = 1L,
PreviousState = _initialState,
RandomSeed = 0,
Signer = _agentAddress,
}));
}

public class ValidateMember
{
public IEnumerable<IRegisterInfo> RegisterInfos { get; set; }
Expand Down
47 changes: 33 additions & 14 deletions Lib9c/Action/HackAndSlashSweep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
using Nekoyume.TableData;
using Nekoyume.TableData.Rune;
using Serilog;
using static Lib9c.SerializeKeys;

namespace Nekoyume.Action
{
Expand All @@ -42,8 +41,10 @@ public class HackAndSlashSweep : GameAction, IHackAndSlashSweepV3

IEnumerable<Guid> IHackAndSlashSweepV3.Costumes => costumes;
IEnumerable<Guid> IHackAndSlashSweepV3.Equipments => equipments;

IEnumerable<IValue> IHackAndSlashSweepV3.RuneSlotInfos =>
runeInfos.Select(x => x.Serialize());

Address IHackAndSlashSweepV3.AvatarAddress => avatarAddress;
int IHackAndSlashSweepV3.ApStoneCount => apStoneCount;
int IHackAndSlashSweepV3.ActionPoint => actionPoint;
Expand All @@ -55,7 +56,8 @@ public class HackAndSlashSweep : GameAction, IHackAndSlashSweepV3
{
["costumes"] = new List(costumes.OrderBy(i => i).Select(e => e.Serialize())),
["equipments"] = new List(equipments.OrderBy(i => i).Select(e => e.Serialize())),
["runeInfos"] = runeInfos.OrderBy(x => x.SlotIndex).Select(x=> x.Serialize()).Serialize(),
["runeInfos"] = runeInfos.OrderBy(x => x.SlotIndex)
.Select(x => x.Serialize()).Serialize(),
["avatarAddress"] = avatarAddress.Serialize(),
["apStoneCount"] = apStoneCount.Serialize(),
["actionPoint"] = actionPoint.Serialize(),
Expand Down Expand Up @@ -91,6 +93,13 @@ public override IWorld Execute(IActionContext context)
$"apStoneCount : {apStoneCount} > UsableApStoneCount : {UsableApStoneCount}");
}

if (apStoneCount < 0 || actionPoint < 0)
{
throw new ArgumentOutOfRangeException(
$"{addressesHex} Aborted as the player give negative value ({actionPoint} AP & {apStoneCount} potions)"
);
}

states.ValidateWorldId(avatarAddress, worldId);

if (!states.TryGetAvatarState(
Expand All @@ -102,7 +111,9 @@ public override IWorld Execute(IActionContext context)
$"{addressesHex}Aborted as the avatar state of the signer was failed to load.");
}

var collectionExist = states.TryGetCollectionState(avatarAddress, out var collectionState) && collectionState.Ids.Any();
var collectionExist =
states.TryGetCollectionState(avatarAddress, out var collectionState) &&
collectionState.Ids.Any();
var sheetTypes = new List<Type>
{
typeof(WorldSheet),
Expand All @@ -126,6 +137,7 @@ public override IWorld Execute(IActionContext context)
{
sheetTypes.Add(typeof(CollectionSheet));
}

var sheets = states.GetSheets(
sheetTypes: sheetTypes);

Expand Down Expand Up @@ -206,19 +218,23 @@ public override IWorld Execute(IActionContext context)
}

// update rune slot
var runeSlotStateAddress = RuneSlotState.DeriveAddress(avatarAddress, BattleType.Adventure);
var runeSlotState = states.TryGetLegacyState(runeSlotStateAddress, out List rawRuneSlotState)
? new RuneSlotState(rawRuneSlotState)
: new RuneSlotState(BattleType.Adventure);
var runeSlotStateAddress =
RuneSlotState.DeriveAddress(avatarAddress, BattleType.Adventure);
var runeSlotState =
states.TryGetLegacyState(runeSlotStateAddress, out List rawRuneSlotState)
? new RuneSlotState(rawRuneSlotState)
: new RuneSlotState(BattleType.Adventure);
var runeListSheet = sheets.GetSheet<RuneListSheet>();
runeSlotState.UpdateSlot(runeInfos, runeListSheet);
states = states.SetLegacyState(runeSlotStateAddress, runeSlotState.Serialize());

// update item slot
var itemSlotStateAddress = ItemSlotState.DeriveAddress(avatarAddress, BattleType.Adventure);
var itemSlotState = states.TryGetLegacyState(itemSlotStateAddress, out List rawItemSlotState)
? new ItemSlotState(rawItemSlotState)
: new ItemSlotState(BattleType.Adventure);
var itemSlotStateAddress =
ItemSlotState.DeriveAddress(avatarAddress, BattleType.Adventure);
var itemSlotState =
states.TryGetLegacyState(itemSlotStateAddress, out List rawItemSlotState)
? new ItemSlotState(rawItemSlotState)
: new ItemSlotState(BattleType.Adventure);
itemSlotState.UpdateEquipment(equipments);
itemSlotState.UpdateCostumes(costumes);
states = states.SetLegacyState(itemSlotStateAddress, itemSlotState.Serialize());
Expand All @@ -238,6 +254,7 @@ public override IWorld Execute(IActionContext context)
equippedRune.Add(runeState);
}
}

var runeOptionSheet = sheets.GetSheet<RuneOptionSheet>();
var runeOptions = new List<RuneOptionSheet.Row.RuneOptionInfo>();
foreach (var runeState in equippedRune)
Expand Down Expand Up @@ -354,9 +371,11 @@ public override IWorld Execute(IActionContext context)
avatarState.UpdateExp(level, exp);

var ended = DateTimeOffset.UtcNow;
Log.Debug("{AddressesHex}HackAndSlashSweep Total Executed Time: {Elapsed}", addressesHex, ended - started);
return states
.SetAvatarState(avatarAddress, avatarState);
Log.Debug(
"{AddressesHex}HackAndSlashSweep Total Executed Time: {Elapsed}",
addressesHex, ended - started
);
return states.SetAvatarState(avatarAddress, avatarState);
}

public static List<ItemBase> GetRewardItems(IRandom random,
Expand Down
17 changes: 15 additions & 2 deletions Lib9c/Action/RegisterProduct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ public static IWorld Register(IActionContext context, IRegisterInfo info, Avatar
}

Guid productId = random.GenerateRandomGuid();
var productAddress = Product.DeriveAddress(productId);
// 중복된 ProductId가 발급되면 상태를 덮어씌우는 현상을 방지하기위해 예외발생
if (states.TryGetLegacyState(productAddress, out IValue v) && v is not Null)
{
// FIXME 클라이언트 배포를 회피하기위해 기존 오류를 사용했으나 정규배포때 별도 예외로 구분ㅐ
throw new DuplicateOrderIdException("already registered id.");
}
var product = new ItemProduct
{
ProductId = productId,
Expand All @@ -218,8 +225,7 @@ public static IWorld Register(IActionContext context, IRegisterInfo info, Avatar
SellerAvatarAddress = registerInfo.AvatarAddress,
};
productsState.ProductIds.Add(productId);
states = states.SetLegacyState(Product.DeriveAddress(productId),
product.Serialize());
states = states.SetLegacyState(productAddress, product.Serialize());
break;
}
}
Expand All @@ -229,6 +235,13 @@ public static IWorld Register(IActionContext context, IRegisterInfo info, Avatar
{
Guid productId = random.GenerateRandomGuid();
Address productAddress = Product.DeriveAddress(productId);
// 중복된 ProductId가 발급되면 상태를 덮어씌우는 현상을 방지하기위해 예외발생
if (states.TryGetLegacyState(productAddress, out IValue v) && v is not Null)
{
// FIXME 클라이언트 배포를 회피하기위해 기존 오류를 사용했으나 정규배포때 별도 예외로 구분ㅐ
throw new DuplicateOrderIdException("already registered id.");
}

FungibleAssetValue asset = assetInfo.Asset;
var product = new FavProduct
{
Expand Down

0 comments on commit 776c911

Please sign in to comment.