private static void AddItemsForTest( AvatarState avatarState, IRandom random, CostumeItemSheet costumeItemSheet, MaterialItemSheet materialItemSheet, EquipmentItemSheet equipmentItemSheet ) { foreach (var row in costumeItemSheet.OrderedList) { avatarState.inventory.AddItem2(ItemFactory.CreateCostume(row, random.GenerateRandomGuid())); } foreach (var row in materialItemSheet.OrderedList) { avatarState.inventory.AddItem2(ItemFactory.CreateMaterial(row), 10); if (row.ItemSubType == ItemSubType.Hourglass || row.ItemSubType == ItemSubType.ApStone) { avatarState.inventory.AddItem2(ItemFactory.CreateTradableMaterial(row), 100); } } foreach (var row in equipmentItemSheet.OrderedList.Where(row => row.Id > GameConfig.DefaultAvatarWeaponId)) { var itemId = random.GenerateRandomGuid(); avatarState.inventory.AddItem2(ItemFactory.CreateItemUsable(row, itemId, default)); } }
public StageSimulatorSheets( MaterialItemSheet materialItemSheet, SkillSheet skillSheet, SkillBuffSheet skillBuffSheet, BuffSheet buffSheet, CharacterSheet characterSheet, CharacterLevelSheet characterLevelSheet, EquipmentItemSetEffectSheet equipmentItemSetEffectSheet, StageSheet stageSheet, StageWaveSheet stageWaveSheet, EnemySkillSheet enemySkillSheet ) : base( materialItemSheet, skillSheet, skillBuffSheet, buffSheet, characterSheet, characterLevelSheet, equipmentItemSetEffectSheet ) { StageSheet = stageSheet; StageWaveSheet = stageWaveSheet; EnemySkillSheet = enemySkillSheet; }
public static AvatarState CreateAvatarState(string name, Address avatarAddress, IActionContext ctx, MaterialItemSheet materialItemSheet, Address rankingMapAddress) { var state = ctx.PreviousStates; var gameConfigState = state.GetGameConfigState(); var avatarState = new AvatarState( avatarAddress, ctx.Signer, ctx.BlockIndex, state.GetAvatarSheets(), gameConfigState, rankingMapAddress, name ); if (GameConfig.IsEditor) { var costumeItemSheet = ctx.PreviousStates.GetSheet <CostumeItemSheet>(); var equipmentItemSheet = ctx.PreviousStates.GetSheet <EquipmentItemSheet>(); AddItemsForTest(avatarState, ctx.Random, costumeItemSheet, materialItemSheet, equipmentItemSheet); } return(avatarState); }
public static AvatarState CreateAvatarState(string name, Address avatarAddress, IActionContext ctx, MaterialItemSheet materialItemSheet, Address rankingMapAddress) { var state = ctx.PreviousStates; var gameConfigState = state.GetGameConfigState(); var avatarState = new AvatarState( avatarAddress, ctx.Signer, ctx.BlockIndex, state.GetAvatarSheets(), gameConfigState, rankingMapAddress, name ); #if LIB9C_DEV_EXTENSIONS || UNITY_EDITOR var data = TestbedHelper.LoadData <TestbedCreateAvatar>("TestbedCreateAvatar"); var costumeItemSheet = ctx.PreviousStates.GetSheet <CostumeItemSheet>(); var equipmentItemSheet = ctx.PreviousStates.GetSheet <EquipmentItemSheet>(); AddItemsForTest( avatarState: avatarState, random: ctx.Random, costumeItemSheet: costumeItemSheet, materialItemSheet: materialItemSheet, equipmentItemSheet: equipmentItemSheet, data.MaterialCount, data.TradableMaterialCount); var skillSheet = ctx.PreviousStates.GetSheet <SkillSheet>(); var optionSheet = ctx.PreviousStates.GetSheet <EquipmentItemOptionSheet>(); var items = data.CustomEquipmentItems; foreach (var item in items) { AddCustomEquipment( avatarState: avatarState, random: ctx.Random, skillSheet: skillSheet, equipmentItemSheet: equipmentItemSheet, equipmentItemOptionSheet: optionSheet, // Set level of equipment here. level: item.Level, // Set recipeId of target equipment here. recipeId: item.ID, // Add optionIds here. item.OptionIds); } #endif return(avatarState); }
/// <summary> /// 완료된 퀘스트의 보상 처리를 한다. /// </summary> public void UpdateQuestRewards(MaterialItemSheet materialItemSheet) { var completedQuests = questList.Where(quest => quest.Complete && !quest.IsPaidInAction); // 완료되었지만 보상을 받지 않은 퀘스트를 return 문에서 Select 하지 않고 미리 저장하는 이유는 // 지연된 실행에 의해, return 시점에서 이미 모든 퀘스트의 보상 처리가 완료된 상태에서 // completed를 호출 시 where문의 predicate가 평가되어 컬렉션이 텅 비기 때문이다. var completedQuestIds = completedQuests.Select(quest => quest.Id).ToList(); foreach (var quest in completedQuests) { UpdateFromQuestReward(quest, materialItemSheet); } questList.completedQuestIds = completedQuestIds; }
public static AvatarState CreateAvatarState(string name, Address avatarAddress, IActionContext ctx, MaterialItemSheet materialItemSheet, Address rankingMapAddress) { var state = ctx.PreviousStates; var gameConfigState = state.GetGameConfigState(); var avatarState = new AvatarState( avatarAddress, ctx.Signer, ctx.BlockIndex, state.GetAvatarSheets(), gameConfigState, rankingMapAddress, name ); if (GameConfig.IsEditor) { var costumeItemSheet = ctx.PreviousStates.GetSheet <CostumeItemSheet>(); var equipmentItemSheet = ctx.PreviousStates.GetSheet <EquipmentItemSheet>(); AddItemsForTest( avatarState: avatarState, random: ctx.Random, costumeItemSheet: costumeItemSheet, materialItemSheet: materialItemSheet, equipmentItemSheet: equipmentItemSheet); var skillSheet = ctx.PreviousStates.GetSheet <SkillSheet>(); var optionSheet = ctx.PreviousStates.GetSheet <EquipmentItemOptionSheet>(); AddCustomEquipment( avatarState: avatarState, random: ctx.Random, skillSheet: skillSheet, equipmentItemSheet: equipmentItemSheet, equipmentItemOptionSheet: optionSheet, // Set level of equipment here. level: 2, // Set recipeId of target equipment here. recipeId: 10110000, // Add optionIds here. 7, 9, 11); } return(avatarState); }
public void UpdateFromQuestReward(Quest.Quest quest, MaterialItemSheet materialItemSheet) { var items = new List <Material>(); foreach (var pair in quest.Reward.ItemMap.OrderBy(kv => kv.Key)) { var row = materialItemSheet.OrderedList.First(itemRow => itemRow.Id == pair.Key); var item = ItemFactory.CreateMaterial(row); var map = inventory.AddItem(item, pair.Value); itemMap.Add(map); items.Add(item); } quest.IsPaidInAction = true; questList.UpdateCollectQuest(itemMap); questList.UpdateItemTypeCollectQuest(items); UpdateCompletedQuest(); }
protected SimulatorSheets( MaterialItemSheet materialItemSheet, SkillSheet skillSheet, SkillBuffSheet skillBuffSheet, BuffSheet buffSheet, CharacterSheet characterSheet, CharacterLevelSheet characterLevelSheet, EquipmentItemSetEffectSheet equipmentItemSetEffectSheet ) { MaterialItemSheet = materialItemSheet; SkillSheet = skillSheet; SkillBuffSheet = skillBuffSheet; BuffSheet = buffSheet; CharacterSheet = characterSheet; CharacterLevelSheet = characterLevelSheet; EquipmentItemSetEffectSheet = equipmentItemSetEffectSheet; }
protected Simulator( IRandom random, AvatarState avatarState, List <Guid> foods, SimulatorSheets simulatorSheets ) { Random = random; MaterialItemSheet = simulatorSheets.MaterialItemSheet; SkillSheet = simulatorSheets.SkillSheet; SkillBuffSheet = simulatorSheets.SkillBuffSheet; BuffSheet = simulatorSheets.BuffSheet; CharacterSheet = simulatorSheets.CharacterSheet; CharacterLevelSheet = simulatorSheets.CharacterLevelSheet; EquipmentItemSetEffectSheet = simulatorSheets.EquipmentItemSetEffectSheet; Log = new BattleLog(); Player = new Player(avatarState, this); Player.Use(foods); Player.Stats.EqualizeCurrentHPWithHP(); }
public RankingSimulatorSheets( MaterialItemSheet materialItemSheet, SkillSheet skillSheet, SkillBuffSheet skillBuffSheet, BuffSheet buffSheet, CharacterSheet characterSheet, CharacterLevelSheet characterLevelSheet, EquipmentItemSetEffectSheet equipmentItemSetEffectSheet, WeeklyArenaRewardSheet weeklyArenaRewardSheet ) : base( materialItemSheet, skillSheet, skillBuffSheet, buffSheet, characterSheet, characterLevelSheet, equipmentItemSetEffectSheet ) { WeeklyArenaRewardSheet = weeklyArenaRewardSheet; }
public static List <ItemBase> SetReward( WeightedSelector <StageSheet.RewardData> itemSelector, int maxCount, IRandom random, MaterialItemSheet materialItemSheet ) { var reward = new List <ItemBase>(); while (reward.Count < maxCount) { try { var data = itemSelector.Select(1).First(); if (materialItemSheet.TryGetValue(data.ItemId, out var itemData)) { var count = random.Next(data.Min, data.Max + 1); for (var i = 0; i < count; i++) { var item = ItemFactory.CreateMaterial(itemData); if (reward.Count < maxCount) { reward.Add(item); } else { break; } } } } catch (ListEmptyException) { break; } } reward = reward.OrderBy(r => r.Id).ToList(); return(reward); }
public static void AddItem(CostumeItemSheet costumeItemSheet, EquipmentItemSheet equipmentItemSheet, EquipmentItemOptionSheet optionSheet, SkillSheet skillSheet, MaterialItemSheet materialItemSheet, ConsumableItemSheet consumableItemSheet, IRandom random, Item item, AddedItemInfo addedItemInfo, AvatarState avatarState) { switch (item.ItemSubType) { case ItemSubType.FullCostume: case ItemSubType.HairCostume: case ItemSubType.EarCostume: case ItemSubType.EyeCostume: case ItemSubType.TailCostume: case ItemSubType.Title: if (costumeItemSheet.TryGetValue(item.ID, out var costumeRow)) { var costume = ItemFactory.CreateCostume(costumeRow, addedItemInfo.TradableId); avatarState.inventory.AddItem(costume); } break; case ItemSubType.Weapon: case ItemSubType.Armor: case ItemSubType.Belt: case ItemSubType.Necklace: case ItemSubType.Ring: if (equipmentItemSheet.TryGetValue(item.ID, out var equipmentRow)) { var equipment = (Equipment)ItemFactory.CreateItemUsable(equipmentRow, addedItemInfo.TradableId, 0, item.Level); if (item.OptionIds.Length > 0) { var optionRows = new List <EquipmentItemOptionSheet.Row>(); foreach (var optionId in item.OptionIds) { if (!optionSheet.TryGetValue(optionId, out var optionRow)) { continue; } optionRows.Add(optionRow); } AddOption(skillSheet, equipment, optionRows, random); } avatarState.inventory.AddItem(equipment); } break; case ItemSubType.Hourglass: case ItemSubType.ApStone: if (materialItemSheet.TryGetValue(item.ID, out var materialRow)) { var material = ItemFactory.CreateTradableMaterial(materialRow); avatarState.inventory.AddItem(material, item.Count); addedItemInfo.TradableId = material.TradableId; } break; case ItemSubType.Food: if (consumableItemSheet.TryGetValue(item.ID, out var consumableRow)) { var consumable = (Consumable)ItemFactory.CreateItemUsable(consumableRow, addedItemInfo.TradableId, 0, item.Level); avatarState.inventory.AddItem(consumable); } break; default: throw new ArgumentOutOfRangeException(); } }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { foreach (var purchaseInfo in purchaseInfos) { Address shardedShopAddress = ShardedShopState.DeriveAddress(purchaseInfo.itemSubType, purchaseInfo.productId); states = states .SetState(shardedShopAddress, MarkChanged) .SetState(purchaseInfo.sellerAvatarAddress, MarkChanged) .MarkBalanceChanged( GoldCurrencyMock, ctx.Signer, purchaseInfo.sellerAgentAddress, GoldCurrencyState.Address); } return(states .SetState(buyerAvatarAddress, MarkChanged) .SetState(ctx.Signer, MarkChanged) .SetState(Addresses.Shop, MarkChanged)); } CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context); var addressesHex = GetSignerAndOtherAddressesHex(context, buyerAvatarAddress); var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}Buy exec started", addressesHex); if (!states.TryGetAvatarState(ctx.Signer, buyerAvatarAddress, out var buyerAvatarState)) { throw new FailedLoadStateException( $"{addressesHex}Aborted as the avatar state of the buyer was failed to load."); } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Buyer AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (!buyerAvatarState.worldInformation.IsStageCleared(GameConfig.RequireClearedStageLevel.ActionsInShop)) { buyerAvatarState.worldInformation.TryGetLastClearedStageId(out var current); throw new NotEnoughClearedStageLevelException(addressesHex, GameConfig.RequireClearedStageLevel.ActionsInShop, current); } List <Buy7.PurchaseResult> purchaseResults = new List <Buy7.PurchaseResult>(); List <Buy7.SellerResult> sellerResults = new List <Buy7.SellerResult>(); MaterialItemSheet materialSheet = states.GetSheet <MaterialItemSheet>(); buyerMultipleResult = new Buy7.BuyerMultipleResult(); sellerMultipleResult = new Buy7.SellerMultipleResult(); foreach (var purchaseInfo in purchaseInfos) { Buy7.PurchaseResult purchaseResult = new Buy7.PurchaseResult(purchaseInfo.productId); Address shardedShopAddress = ShardedShopState.DeriveAddress(purchaseInfo.itemSubType, purchaseInfo.productId); Address sellerAgentAddress = purchaseInfo.sellerAgentAddress; Address sellerAvatarAddress = purchaseInfo.sellerAvatarAddress; Guid productId = purchaseInfo.productId; purchaseResults.Add(purchaseResult); if (purchaseInfo.sellerAgentAddress == ctx.Signer) { purchaseResult.errorCode = ErrorCodeInvalidAddress; continue; } if (!states.TryGetState(shardedShopAddress, out Bencodex.Types.Dictionary shopStateDict)) { ShardedShopState shardedShopState = new ShardedShopState(shardedShopAddress); shopStateDict = (Dictionary)shardedShopState.Serialize(); } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get ShopState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); Log.Verbose( "{AddressesHex}Execute Buy; buyer: {Buyer} seller: {Seller}", addressesHex, buyerAvatarAddress, sellerAvatarAddress); // Find product from ShardedShopState. List products = (List)shopStateDict[ProductsKey]; IValue productIdSerialized = productId.Serialize(); IValue sellerAgentSerialized = purchaseInfo.sellerAgentAddress.Serialize(); Dictionary productSerialized = products .Select(p => (Dictionary)p) .FirstOrDefault(p => p[LegacyProductIdKey].Equals(productIdSerialized) && p[LegacySellerAgentAddressKey].Equals(sellerAgentSerialized)); bool fromLegacy = false; if (productSerialized.Equals(Dictionary.Empty)) { if (purchaseInfo.itemSubType == ItemSubType.Hourglass || purchaseInfo.itemSubType == ItemSubType.ApStone) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } // Backward compatibility. IValue rawShop = states.GetState(Addresses.Shop); if (!(rawShop is null)) { Dictionary legacyShopDict = (Dictionary)rawShop; Dictionary legacyProducts = (Dictionary)legacyShopDict[LegacyProductsKey]; IKey productKey = (IKey)productId.Serialize(); // SoldOut if (!legacyProducts.ContainsKey(productKey)) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } productSerialized = (Dictionary)legacyProducts[productKey]; legacyProducts = (Dictionary)legacyProducts.Remove(productKey); legacyShopDict = legacyShopDict.SetItem(LegacyProductsKey, legacyProducts); states = states.SetState(Addresses.Shop, legacyShopDict); fromLegacy = true; } } ShopItem shopItem = new ShopItem(productSerialized); if (!shopItem.SellerAgentAddress.Equals(sellerAgentAddress)) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Item: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (0 < shopItem.ExpiredBlockIndex && shopItem.ExpiredBlockIndex < context.BlockIndex) { purchaseResult.errorCode = ErrorCodeShopItemExpired; continue; } if (!states.TryGetAvatarState(sellerAgentAddress, sellerAvatarAddress, out var sellerAvatarState)) { purchaseResult.errorCode = ErrorCodeFailedLoadingState; continue; } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Seller AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); // Check Balance. FungibleAssetValue buyerBalance = states.GetBalance(context.Signer, states.GetGoldCurrency()); if (buyerBalance < shopItem.Price) { purchaseResult.errorCode = ErrorCodeInsufficientBalance; continue; } var tax = shopItem.Price.DivRem(100, out _) * TaxRate; var taxedPrice = shopItem.Price - tax; // Transfer tax. states = states.TransferAsset( context.Signer, GoldCurrencyState.Address, tax); // Transfer seller. states = states.TransferAsset( context.Signer, sellerAgentAddress, taxedPrice ); products = (List)products.Remove(productSerialized); shopStateDict = shopStateDict.SetItem(ProductsKey, new List <IValue>(products)); ITradableItem tradableItem; int count = 1; if (!(shopItem.ItemUsable is null)) { tradableItem = shopItem.ItemUsable; }
public SimulatorTest() { _materialItemSheet = new MaterialItemSheet(); _materialItemSheet.Set(TableSheetsImporter.ImportSheets()[nameof(MaterialItemSheet)]); _random = new ItemEnhancementTest.TestRandom(); }
public override IAccountStateDelta Execute(IActionContext context) { IActionContext ctx = context; var states = ctx.PreviousStates; if (ctx.Rehearsal) { foreach (var purchaseInfo in purchaseInfos) { Address shardedShopAddress = ShardedShopState.DeriveAddress(purchaseInfo.itemSubType, purchaseInfo.productId); states = states .SetState(shardedShopAddress, MarkChanged) .SetState(purchaseInfo.sellerAvatarAddress, MarkChanged) .MarkBalanceChanged( GoldCurrencyMock, ctx.Signer, purchaseInfo.sellerAgentAddress, GoldCurrencyState.Address); } return(states .SetState(buyerAvatarAddress, MarkChanged) .SetState(ctx.Signer, MarkChanged) .SetState(Addresses.Shop, MarkChanged)); } CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context); var addressesHex = GetSignerAndOtherAddressesHex(context, buyerAvatarAddress); var sw = new Stopwatch(); sw.Start(); var started = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}Buy exec started", addressesHex); if (!states.TryGetAvatarState(ctx.Signer, buyerAvatarAddress, out var buyerAvatarState)) { throw new FailedLoadStateException( $"{addressesHex}Aborted as the avatar state of the buyer was failed to load."); } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Buyer AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (!buyerAvatarState.worldInformation.IsStageCleared(GameConfig.RequireClearedStageLevel.ActionsInShop)) { buyerAvatarState.worldInformation.TryGetLastClearedStageId(out var current); throw new NotEnoughClearedStageLevelException(addressesHex, GameConfig.RequireClearedStageLevel.ActionsInShop, current); } List <Buy7.PurchaseResult> purchaseResults = new List <Buy7.PurchaseResult>(); List <Buy7.SellerResult> sellerResults = new List <Buy7.SellerResult>(); MaterialItemSheet materialSheet = states.GetSheet <MaterialItemSheet>(); buyerMultipleResult = new Buy7.BuyerMultipleResult(); sellerMultipleResult = new Buy7.SellerMultipleResult(); foreach (var purchaseInfo in purchaseInfos) { Buy7.PurchaseResult purchaseResult = new Buy7.PurchaseResult(purchaseInfo.productId); Address shardedShopAddress = ShardedShopState.DeriveAddress(purchaseInfo.itemSubType, purchaseInfo.productId); Address sellerAgentAddress = purchaseInfo.sellerAgentAddress; Address sellerAvatarAddress = purchaseInfo.sellerAvatarAddress; Guid productId = purchaseInfo.productId; purchaseResults.Add(purchaseResult); if (purchaseInfo.sellerAgentAddress == ctx.Signer) { purchaseResult.errorCode = ErrorCodeInvalidAddress; continue; } if (!states.TryGetState(shardedShopAddress, out Bencodex.Types.Dictionary shopStateDict)) { ShardedShopState shardedShopState = new ShardedShopState(shardedShopAddress); shopStateDict = (Dictionary)shardedShopState.Serialize(); } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get ShopState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); Log.Verbose( "{AddressesHex}Execute Buy; buyer: {Buyer} seller: {Seller}", addressesHex, buyerAvatarAddress, sellerAvatarAddress); // Find product from ShardedShopState. List products = (List)shopStateDict[ProductsKey]; IValue productIdSerialized = productId.Serialize(); Dictionary productSerialized = products .Select(p => (Dictionary)p) .FirstOrDefault(p => p[LegacyProductIdKey].Equals(productIdSerialized)); // Since Bencodex 0.4, Dictionary/List are reference types; so their default values // are not a empty container, but a null reference: productSerialized = productSerialized ?? Dictionary.Empty; bool fromLegacy = false; if (productSerialized.Equals(Dictionary.Empty)) { // Backward compatibility. IValue rawShop = states.GetState(Addresses.Shop); if (!(rawShop is null)) { Dictionary legacyShopDict = (Dictionary)rawShop; Dictionary legacyProducts = (Dictionary)legacyShopDict[LegacyProductsKey]; IKey productKey = (IKey)productId.Serialize(); // SoldOut if (!legacyProducts.ContainsKey(productKey)) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } productSerialized = (Dictionary)legacyProducts[productKey]; legacyProducts = (Dictionary)legacyProducts.Remove(productKey); legacyShopDict = legacyShopDict.SetItem(LegacyProductsKey, legacyProducts); states = states.SetState(Addresses.Shop, legacyShopDict); fromLegacy = true; } } ShopItem shopItem = new ShopItem(productSerialized); if (!shopItem.SellerAgentAddress.Equals(sellerAgentAddress)) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Item: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); if (0 < shopItem.ExpiredBlockIndex && shopItem.ExpiredBlockIndex < context.BlockIndex) { purchaseResult.errorCode = ErrorCodeShopItemExpired; continue; } if (!states.TryGetAvatarState(sellerAgentAddress, sellerAvatarAddress, out var sellerAvatarState)) { purchaseResult.errorCode = ErrorCodeFailedLoadingState; continue; } sw.Stop(); Log.Verbose("{AddressesHex}Buy Get Seller AgentAvatarStates: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); // Check Balance. FungibleAssetValue buyerBalance = states.GetBalance(context.Signer, states.GetGoldCurrency()); if (buyerBalance < shopItem.Price) { purchaseResult.errorCode = ErrorCodeInsufficientBalance; continue; } var tax = shopItem.Price.DivRem(100, out _) * TaxRate; var taxedPrice = shopItem.Price - tax; // Transfer tax. states = states.TransferAsset( context.Signer, GoldCurrencyState.Address, tax); // Transfer seller. states = states.TransferAsset( context.Signer, sellerAgentAddress, taxedPrice ); products = (List)products.Remove(productSerialized); shopStateDict = shopStateDict.SetItem(ProductsKey, new List <IValue>(products)); INonFungibleItem nonFungibleItem = (INonFungibleItem)shopItem.ItemUsable ?? shopItem.Costume; if (!sellerAvatarState.inventory.RemoveNonFungibleItem(nonFungibleItem) && !fromLegacy) { purchaseResult.errorCode = ErrorCodeItemDoesNotExist; continue; } nonFungibleItem.RequiredBlockIndex = context.BlockIndex; // Send result mail for buyer, seller. purchaseResult.shopItem = shopItem; purchaseResult.itemUsable = shopItem.ItemUsable; purchaseResult.costume = shopItem.Costume; var buyerMail = new BuyerMail(purchaseResult, ctx.BlockIndex, ctx.Random.GenerateRandomGuid(), ctx.BlockIndex); purchaseResult.id = buyerMail.id; var sellerResult = new Buy7.SellerResult { shopItem = shopItem, itemUsable = shopItem.ItemUsable, costume = shopItem.Costume, gold = taxedPrice }; var sellerMail = new SellerMail(sellerResult, ctx.BlockIndex, ctx.Random.GenerateRandomGuid(), ctx.BlockIndex); sellerResult.id = sellerMail.id; sellerResults.Add(sellerResult); buyerAvatarState.Update(buyerMail); if (purchaseResult.itemUsable != null) { buyerAvatarState.UpdateFromAddItem2(purchaseResult.itemUsable, false); } if (purchaseResult.costume != null) { buyerAvatarState.UpdateFromAddCostume(purchaseResult.costume, false); } sellerAvatarState.Update(sellerMail); // Update quest. buyerAvatarState.questList.UpdateTradeQuest(TradeType.Buy, shopItem.Price); sellerAvatarState.questList.UpdateTradeQuest(TradeType.Sell, shopItem.Price); sellerAvatarState.updatedAt = ctx.BlockIndex; sellerAvatarState.blockIndex = ctx.BlockIndex; buyerAvatarState.UpdateQuestRewards2(materialSheet); sellerAvatarState.UpdateQuestRewards2(materialSheet); states = states.SetState(sellerAvatarAddress, sellerAvatarState.Serialize()); sw.Stop(); Log.Verbose("{AddressesHex}Buy Set Seller AvatarState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); states = states.SetState(shardedShopAddress, shopStateDict); sw.Stop(); Log.Verbose("{AddressesHex}Buy Set ShopState: {Elapsed}", addressesHex, sw.Elapsed); } buyerMultipleResult.purchaseResults = purchaseResults; sellerMultipleResult.sellerResults = sellerResults; buyerAvatarState.updatedAt = ctx.BlockIndex; buyerAvatarState.blockIndex = ctx.BlockIndex; states = states.SetState(buyerAvatarAddress, buyerAvatarState.Serialize()); sw.Stop(); Log.Verbose("{AddressesHex}Buy Set Buyer AvatarState: {Elapsed}", addressesHex, sw.Elapsed); sw.Restart(); var ended = DateTimeOffset.UtcNow; Log.Verbose("{AddressesHex}Buy Total Executed Time: {Elapsed}", addressesHex, ended - started); return(states); }
public static Material CreateMaterial(MaterialItemSheet sheet, int itemId) { return(!sheet.TryGetValue(itemId, out var itemData) ? null : CreateMaterial(itemData)); }