/// Event Hero Creation //[DisplayName("heroCreation")] //public static event Action<BigInteger, byte[], BigInteger[], BigInteger[]> heroCreation; /// <summary> /// Entry point of smartcontract /// </summary> /// <param name="param">Method name</param> /// <param name="args">method arguments array</param> /// <returns>1 if success, 0 if failed</returns> public static byte[] Main(string param, object[] args) { if (param.Equals("initializeCoffers")) { int maxCityAmount = (int)MAX_CITY_AMOUNT; BigInteger[] coffersList = new BigInteger[maxCityAmount]; int i = 0; for (; i < maxCityAmount; i++) { coffersList[i] = 0; } byte[] coffers = Neo.SmartContract.Framework.Helper.Serialize(coffersList); Storage.Put(CITY_COFFERS_KEY, coffers); } else if (param.Equals("setSetting")) { Settings.Set((string)args[0], (byte[])args[1]); } else if (param.Equals("payoutCoffers")) { // Prepare all variables. // Get last payout session // Check that coffer percent parameter is matching with setting value byte[] cofferPercentsSettingBytes = Storage.Get(Storage.CurrentContext, PERCENTS_COFFER_PAY); byte[] cofferPercentsBytes = (byte[])args[1]; BigInteger payoutPercents = (BigInteger)args[1]; if (!cofferPercentsSettingBytes.Equals(cofferPercentsBytes)) { Runtime.Notify(11); throw new Exception(); } // Check that payment interval parameter is matching with setting value byte[] paymentIntervalSettingBytes = Storage.Get(Storage.CurrentContext, GeneralContract.INTERVAL_COFFER); byte[] paymentIntervalBytes = (byte[])args[2]; BigInteger paymentInterval = (BigInteger)args[2]; if (!paymentIntervalSettingBytes.Equals(paymentIntervalBytes)) { Runtime.Notify(10); throw new Exception(); } // Get latest coffer payout CofferPayment session = new CofferPayment(); session.Block = 1;// Blockchain.GetHeight(); byte[] lastCofferSession = Storage.Get(Storage.CurrentContext, COFFER_PAYMENT_SESSION); if (lastCofferSession.Length > 0) { session = (CofferPayment)Neo.SmartContract.Framework.Helper.Deserialize(lastCofferSession); } if (Blockchain.GetHeight() < session.Block + paymentInterval) { Runtime.Notify(6001); throw new Exception(); } // Get city amount byte[] cityAmountSettingBytes = Storage.Get(AMOUNT_CITIES); if (cityAmountSettingBytes.Length <= 0) { Runtime.Notify(15); throw new Exception(); } byte[] cityAmountBytes = (byte[])args[0]; if (!cityAmountBytes.Equals(cityAmountSettingBytes)) { Runtime.Notify(9); throw new Exception(); } int cityAmountInt = (int)args[0]; Transaction TX = (Transaction)ExecutionEngine.ScriptContainer; TransactionOutput[] outputs = TX.GetOutputs(); BigInteger[] coffers = Helper.GetCoffers(); int maxCityAmount = (int)MAX_CITY_AMOUNT; BigInteger[] payouts = new BigInteger[maxCityAmount]; for (var id = 1; id <= cityAmountInt; id++) { BigInteger coffer = coffers[id]; // Skip from paying out if number is less than 0.1 GAS if (coffer <= 10000000) { payouts[id] = 0; continue; } BigInteger percent = BigInteger.Divide(coffer, 100); BigInteger payoutAmount = BigInteger.Multiply(percent, payoutPercents); // Payout amount coffers[id] = BigInteger.Subtract(coffers[id], payoutAmount); payouts[id] = payoutAmount; } Helper.SetCoffers(coffers); session.Block = Blockchain.GetHeight(); lastCofferSession = Neo.SmartContract.Framework.Helper.Serialize(session); Storage.Put(Storage.CurrentContext, COFFER_PAYMENT_SESSION, lastCofferSession); byte[] payoutsBytes = Neo.SmartContract.Framework.Helper.Serialize(payouts); Storage.Put(Storage.CurrentContext, PAYOUTS_KEY, payoutsBytes); Runtime.Notify(6000, payouts); } else if (param.Equals("dropItem")) { Periodical.SimpleDropItem((byte[])args[0], args[1], args[2]); } else if (param.Equals("putCity")) { Put.City((BigInteger)args[0], (BigInteger)args[1], (BigInteger)args[2]); } else if (param.Equals("putStronghold")) { Put.Stronghold((BigInteger)args[0]); } else if (param.Equals("putBanditCamp")) { Put.BanditCamp((BigInteger)args[0]); } else if (param.Equals("putItem")) { if (args.Length != 6) { Runtime.Notify(1001); // This function has 7 parameters throw new Exception(); } // Item given type: for hero creation or drop for stronghold if ((BigInteger)args[0] != STRONGHOLD_REWARD_BATCH && (BigInteger)args[0] != HERO_CREATION_BATCH) { Runtime.Notify(1002); throw new Exception(); } Runtime.Log("Item was upload"); // Item Parameters Item item = new Item(); item.STAT_TYPE = (BigInteger)args[2]; // 1 length item.QUALITY = (BigInteger)args[3]; // 1 length item.GENERATION = (BigInteger)args[4]; // ??? item.STAT_VALUE = (BigInteger)args[5]; // ??? item.LEVEL = 0; // ??? //item.OWNER = new byte[] { }; // 20 item.XP = 0; // ??? item.HERO = 0; //item.INITIAL = (BigInteger)args[7]; // 1 //item.OWNER = ExecutionEngine.CallingScriptHash; item.BATCH = (BigInteger)args[0]; Runtime.Log("Item settings were set"); Put.Item((byte[])args[1], item, false); } else if (param.Equals("putHero")) { if (Runtime.CheckWitness(GameOwner)) { Runtime.Notify(1); throw new Exception(); } // Failure. Game Admin is not allowed to play the game byte[] scriptHash = (byte[])args[0]; if (!Runtime.CheckWitness(scriptHash)) { Runtime.Notify(4002); throw new Exception(); } //Runtime.Log("Scripthash wallet is running game. Check referers"); BigInteger heroId = (BigInteger)args[1]; BigInteger refererHeroId = (BigInteger)args[2]; byte[] refererScriptHash = (byte[])args[3]; Runtime.Log("Referers were checked. Check Hero ID"); if (heroId <= 0) { Runtime.Notify(4003); throw new Exception(); } Runtime.Log("Hero id is not 0 or lower than 0. Check existance of hero on the given id"); string heroKey = HERO_MAP + heroId.ToByteArray(); byte[] heroBytes = Storage.Get(Storage.CurrentContext, heroKey); if (heroBytes.Length > 0) { Runtime.Notify(4004); throw new Exception(); } Runtime.Log("Hero on the id is not existing. Check the Referer hero"); if (refererHeroId > 0) { Runtime.Log("Referer is exist"); string refererHeroKey = HERO_MAP + refererHeroId.ToByteArray(); byte[] refererHeroBytes = Storage.Get(Storage.CurrentContext, refererHeroKey); if (refererHeroBytes.Length <= 0) { Runtime.Notify(4005); throw new Exception(); } Hero refererHero = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(refererHeroBytes); if (Runtime.CheckWitness(refererHero.OWNER)) { Runtime.Notify(4006); throw new Exception(); } if (!refererHero.OWNER.Equals(refererScriptHash)) { Runtime.Notify(4007); throw new Exception(); } } Runtime.Log("Referer is not exist"); byte[] feeBytes = Storage.Get(Storage.CurrentContext, FEE_HERO_CREATION); if (!AttachmentExistAB(feeBytes, GameOwner)) { if (!AttachmentExistAB(feeBytes, GameOwner2)) { Runtime.Notify(4009); throw new Exception(); } } Runtime.Log("Hero creation fee is attached"); byte[][] stats = (byte[][])args[4]; Runtime.Log("Array of stats are not given"); if (stats.Length != 5) { Runtime.Notify(4010); throw new Exception(); } Runtime.Log("Array of stats are given"); Hero hero = new Hero(); hero.OWNER = scriptHash; hero.INTELLIGENCE = stats[2]; hero.SPEED = stats[3]; hero.STRENGTH = stats[4]; hero.LEADERSHIP = stats[1]; hero.DEFENSE = stats[0]; hero.StrongholdsAmount = 0; hero.ID = heroId; Runtime.Log("Hero Data set"); byte[] equipment1 = (byte[])args[5]; byte[] equipment2 = (byte[])args[6]; byte[] equipment3 = (byte[])args[7]; byte[] equipment4 = (byte[])args[8]; byte[] equipment5 = (byte[])args[9]; Runtime.Log("Define equipments"); byte[] signature = (byte[])args[10]; Runtime.Log("Define signature"); byte[] heroIdBytes = heroId.ToByteArray(); Runtime.Log("Hero Id converted to bytes"); Runtime.Log("Define sign message"); byte[] signMessage = Neo.SmartContract.Framework.Helper.Concat(heroIdBytes, stats[0]); Runtime.Log("Concatination of Defense was succ"); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, hero.LEADERSHIP); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, hero.INTELLIGENCE); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, hero.SPEED); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, hero.STRENGTH); Runtime.Log("Concatination of all stats was successfull"); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, equipment1); Runtime.Log("Concatination of equpiment id was successfull"); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, equipment2); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, equipment3); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, equipment4); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, equipment5); Runtime.Log("Concatted Item"); Runtime.Log("Message converted"); if (!VerifySignature(signMessage, signature, GameOwnerPublicKey)) { Runtime.Notify(2); Runtime.Notify(signMessage); Runtime.Notify(signature); Runtime.Log("Signature Verification Failed"); throw new Exception(); } Runtime.Log("Verified successuly"); // Change Item Owners Helper.ChangeItemOwner(equipment1, heroId); Helper.ChangeItemOwner(equipment2, heroId); Helper.ChangeItemOwner(equipment3, heroId); Helper.ChangeItemOwner(equipment4, heroId); Helper.ChangeItemOwner(equipment5, heroId); Put.Hero(heroId, hero); //heroCreation(heroId, scriptHash, stats, equipments); Runtime.Notify(4000, scriptHash, heroId, refererHeroId, refererScriptHash, stats, equipment1, equipment2, equipment3, equipment4, equipment5); } else if (param.Equals("marketAddItem")) { // 1: Item Id, 2: Price, 3: Duration in seconds, 4: City ID, 5: coffer addition amount if (args.Length != 5) { Runtime.Notify(1001); throw new Exception(); } Runtime.Log("Market enetered"); byte[] itemId = (byte[])args[0]; BigInteger price = (BigInteger)args[1]; BigInteger duration = (BigInteger)args[2]; BigInteger cityId = (BigInteger)args[3]; byte[] cofferAdditionAmountBytes = (byte[])args[4]; Runtime.Log("Item data retrieved"); if (Runtime.CheckWitness(GameOwner)) { Runtime.Notify(1); throw new Exception(); } Runtime.Log("Data is not called by player"); byte[] durationFeeSettingBytes = new byte[0] { }; // Increase coffer byte[] marketCofferAdditionSettingBytes = new byte[0] { }; if (duration == duration8Hours) { durationFeeSettingBytes = Storage.Get(Storage.CurrentContext, FEE_8_HOURS); marketCofferAdditionSettingBytes = Storage.Get(Storage.CurrentContext, MARKET_COFFER_ADDITION_8_HOURS); } else if (duration == duration12Hours) { durationFeeSettingBytes = Storage.Get(Storage.CurrentContext, FEE_12_HOURS); marketCofferAdditionSettingBytes = Storage.Get(Storage.CurrentContext, MARKET_COFFER_ADDITION_12_HOURS); } else if (duration == duration24Hours) { durationFeeSettingBytes = Storage.Get(Storage.CurrentContext, FEE_24_HOURS); marketCofferAdditionSettingBytes = Storage.Get(Storage.CurrentContext, MARKET_COFFER_ADDITION_24_HOURS); } else { Runtime.Notify(1002); throw new Exception(); } Runtime.Log("Duration is retreived from storage"); string cityKey = CITY_MAP + cityId.ToByteArray(); byte[] cityBytes = Storage.Get(Storage.CurrentContext, cityKey); if (cityBytes.Length <= 0) { Runtime.Notify(1003); throw new Exception(); } Runtime.Log("City on storage"); City city = (City)Neo.SmartContract.Framework.Helper.Deserialize(cityBytes); if (city.ItemsOnMarket + 1 >= city.ItemsCap) { Runtime.Notify(1004); throw new Exception(); } Runtime.Log("City market is not full"); string itemKey = ITEM_MAP + itemId; byte[] itemBytes = Storage.Get(Storage.CurrentContext, itemKey); if (itemBytes.Length <= 0) { Runtime.Notify(1005); throw new Exception(); } Runtime.Log("Item on storage"); Item item = (Item)Neo.SmartContract.Framework.Helper.Deserialize(itemBytes); if (item.HERO <= 0) { Runtime.Notify(1006); throw new Exception(); } BigInteger itemLordId = item.HERO; string heroKey = HERO_MAP + itemLordId.ToByteArray(); byte[] heroBytes = Storage.Get(Storage.CurrentContext, heroKey); if (heroBytes.Length <= 0) { Runtime.Notify(1007); throw new Exception(); } Runtime.Log("Item owner on storage"); // Seller Hero hero = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(heroBytes); if (!Runtime.CheckWitness(hero.OWNER)) { Runtime.Notify(1008); throw new Exception(); } Runtime.Log("Item owner invoked marked adding method"); string marketItemKey = MARKET_MAP + itemId; byte[] marketItemBytes = Storage.Get(Storage.CurrentContext, marketItemKey); if (marketItemBytes.Length > 0) { MarketItemData oldMarketItem = (MarketItemData)Neo.SmartContract.Framework.Helper.Deserialize(marketItemBytes); if (Blockchain.GetBlock(Blockchain.GetHeight()).Timestamp < oldMarketItem.Duration + oldMarketItem.CreatedTime) { Runtime.Notify(1009); throw new Exception(); } } Runtime.Log("Market item duration not expired"); if (!AttachmentExistAB(durationFeeSettingBytes, GameOwner)) { if (!AttachmentExistAB(durationFeeSettingBytes, GameOwner2)) { Runtime.Notify(1010); throw new Exception(); } } Runtime.Log("Fee attached"); if (marketCofferAdditionSettingBytes.Length > 0) { if (!marketCofferAdditionSettingBytes.Equals(cofferAdditionAmountBytes)) { Runtime.Notify(1011, marketCofferAdditionSettingBytes, cofferAdditionAmountBytes); throw new Exception(); } } MarketItemData marketItem = new MarketItemData(); marketItem.Duration = duration; marketItem.Price = price; marketItem.City = cityId; marketItem.CreatedTime = Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp; marketItem.Seller = hero.OWNER; marketItemBytes = Neo.SmartContract.Framework.Helper.Serialize(marketItem); BigInteger cofferAdditionNum = (BigInteger)args[4]; BigInteger cityCoffer = Helper.GetCoffer(cityId); cityCoffer = BigInteger.Add(cityCoffer, cofferAdditionNum); Helper.SetCoffer(cityId, cityCoffer); city.ItemsOnMarket = BigInteger.Add(city.ItemsOnMarket, 1); Runtime.Log("City data update"); // Save on Storage!!! Storage.Put(Storage.CurrentContext, marketItemKey, marketItemBytes); //// Update City cityBytes = Neo.SmartContract.Framework.Helper.Serialize(city); Storage.Put(Storage.CurrentContext, cityKey, cityBytes); Runtime.Notify(1000, itemId, price, duration, cityId); } else if (param.Equals("marketBuyItem")) { BigInteger heroId = (BigInteger)args[0]; byte[] itemId = (byte[])args[1]; if (Runtime.CheckWitness(GameOwner)) { Runtime.Notify(1); throw new Exception(); } Runtime.Log("Item buying retreived"); string itemKey = ITEM_MAP + itemId; byte[] itemBytes = Storage.Get(Storage.CurrentContext, itemKey); if (itemBytes.Length <= 0) { Runtime.Notify(1005); throw new Exception(); } Runtime.Log("Item on blockchain"); Item item = (Item)Neo.SmartContract.Framework.Helper.Deserialize(itemBytes); if (item.HERO <= 0) { Runtime.Notify(1006); throw new Exception(); } BigInteger itemLordId = item.HERO; string heroKey = HERO_MAP + itemLordId.ToByteArray(); byte[] heroBytes = Storage.Get(Storage.CurrentContext, heroKey); if (heroBytes.Length <= 0) { Runtime.Notify(1007); throw new Exception(); } //Runtime.Log("Item owned by someone"); // Seller Hero hero = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(heroBytes); if (Runtime.CheckWitness(hero.OWNER)) { Runtime.Notify(2004); throw new Exception(); } Runtime.Log("Buyer and seller are not the same"); string buyerHeroKey = HERO_MAP + heroId.ToByteArray(); byte[] buyerHeroBytes = Storage.Get(Storage.CurrentContext, buyerHeroKey); if (buyerHeroBytes.Length <= 0) { Runtime.Notify(2005); throw new Exception(); } //Runtime.Log("Buyer on blockchain"); Hero buyer = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(buyerHeroBytes); if (!Runtime.CheckWitness(buyer.OWNER)) { Runtime.Notify(2006); throw new Exception(); } Runtime.Log("Buyer owner called buying method"); string marketItemKey = MARKET_MAP + itemId; byte[] marketItemBytes = Storage.Get(Storage.CurrentContext, marketItemKey); if (marketItemBytes.Length > 0) { Runtime.Log("Market item on blockchain"); MarketItemData marketItem = (MarketItemData)Neo.SmartContract.Framework.Helper.Deserialize(marketItemBytes); if (Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp > marketItem.Duration + marketItem.CreatedTime) { Runtime.Notify(2007); throw new Exception(); } else { Runtime.Log("Market item duration not expired"); // original price based sum of money that buyer should attach to tx. byte[] lordFeeSettingBytes = Storage.Get(Storage.CurrentContext, PERCENTS_LORD); byte[] gameOwnerSettingBytes = Storage.Get(Storage.CurrentContext, PERCENTS_GAME_OWNER); BigInteger marketCityId = marketItem.City; string cityKey = CITY_MAP + marketCityId.ToByteArray(); City city = (City)Neo.SmartContract.Framework.Helper.Deserialize(Storage.Get(Storage.CurrentContext, cityKey)); Runtime.Log("City returned"); BigInteger gameOwnerExpectation = 0; BigInteger lordExpectation = 0; BigInteger sellerExpectation = 0; if (gameOwnerSettingBytes.Length > 0) { byte[] lordFeeBytes = (byte[])args[2]; if (!lordFeeBytes.Equals(lordFeeSettingBytes)) { Runtime.Notify(2012, lordFeeSettingBytes, lordFeeBytes); throw new Exception(); } byte[] gameOwnerFeeBytes = (byte[])args[3]; if (!gameOwnerFeeBytes.Equals(gameOwnerSettingBytes)) { Runtime.Notify(2013, gameOwnerSettingBytes, gameOwnerFeeBytes); throw new Exception(); } Runtime.Log("Pay correct fee"); BigInteger pricePercent = BigInteger.Divide(marketItem.Price, 100); BigInteger lordFeePercents = (BigInteger)args[2]; BigInteger gameOwnerPercents = (BigInteger)args[3]; BigInteger lordFee = BigInteger.Multiply(pricePercent, lordFeePercents); BigInteger gameOwnerFee = BigInteger.Multiply(pricePercent, gameOwnerPercents); Runtime.Log("Lord percent fee"); // city is owned by buyer? if (city.Hero > 0 && city.Hero == heroId) { sellerExpectation = marketItem.Price; gameOwnerExpectation = gameOwnerFee; } // city owned by seller? else if (city.Hero > 0 && city.Hero == item.HERO) { lordExpectation = BigInteger.Add(marketItem.Price, lordFee); gameOwnerExpectation = gameOwnerFee; } // city is owned by NPC? else if (city.Hero <= 0) { sellerExpectation = marketItem.Price; gameOwnerExpectation = BigInteger.Add(gameOwnerFee, lordFee); } // city is owned by someone else? else { sellerExpectation = marketItem.Price; gameOwnerExpectation = gameOwnerFee; lordExpectation = lordFee; } Runtime.Log("Lord expectation is increased"); Runtime.Log("Game owner expectation set"); byte[] sellerExpectationBytes = sellerExpectation.ToByteArray(); if (sellerExpectation > 0 && !AttachmentExistAB(sellerExpectationBytes, hero.OWNER)) { Runtime.Notify(2008); throw new Exception(); } Runtime.Log("Check seller attahment fee"); if (city.Hero > 0) { BigInteger cityLordId = city.Hero; string cityLordKey = HERO_MAP + cityLordId.ToByteArray(); Hero cityLord = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(Storage.Get(Storage.CurrentContext, cityLordKey)); byte[] lordExpectationBytes = lordExpectation.ToByteArray(); if (lordExpectation > 0 && !AttachmentExistAB(lordExpectationBytes, cityLord.OWNER)) { Runtime.Notify(2009, lordExpectationBytes, lordExpectation, lordFee, pricePercent, lordFeePercents); throw new Exception(); } } Runtime.Log("Check Lord attachment fee"); byte[] gameOwnerExpectationBytes = gameOwnerExpectation.ToByteArray(); if (gameOwnerExpectation > 0 && !AttachmentExistAB(gameOwnerExpectationBytes, GameOwner)) { if (gameOwnerExpectation > 0 && !AttachmentExistAB(gameOwnerExpectationBytes, GameOwner2)) { Runtime.Notify(2010, gameOwnerExpectationBytes, gameOwnerExpectation, gameOwnerFee, pricePercent, gameOwnerPercents); throw new Exception(); } } Runtime.Log("Check game owner attachment fee"); } city.ItemsOnMarket = BigInteger.Subtract(city.ItemsOnMarket, 1); Storage.Put(Storage.CurrentContext, cityKey, Neo.SmartContract.Framework.Helper.Serialize(city)); item.HERO = heroId; Storage.Put(Storage.CurrentContext, itemKey, Neo.SmartContract.Framework.Helper.Serialize(item)); Storage.Delete(Storage.CurrentContext, marketItemKey); Runtime.Notify(2000, itemId, heroId, sellerExpectation, lordExpectation, gameOwnerExpectation); } } else { Runtime.Notify(2014); throw new Exception(); } } else if (param.Equals("marketDeleteItem")) { byte[] itemId = (byte[])args[0]; if (Runtime.CheckWitness(GameOwner)) { Runtime.Notify(1); throw new Exception(); } string key = MARKET_MAP + itemId; byte[] mBytes = Storage.Get(Storage.CurrentContext, key); if (mBytes.Length <= 0) { Runtime.Notify(2011); throw new Exception(); } MarketItemData mItem = (MarketItemData)Neo.SmartContract.Framework.Helper.Deserialize(mBytes); // Item can be removed from Blockchain before expiration, only by Item owner if (Blockchain.GetBlock(Blockchain.GetHeight()).Timestamp < mItem.Duration + mItem.CreatedTime) { if (!Runtime.CheckWitness(mItem.Seller)) { Runtime.Notify(3002); throw new Exception(); } } BigInteger marketCityId = mItem.City; string cityKey = CITY_MAP + marketCityId.ToByteArray(); byte[] cityBytes = Storage.Get(Storage.CurrentContext, cityKey); City city = (City)Neo.SmartContract.Framework.Helper.Deserialize(cityBytes); city.ItemsOnMarket = BigInteger.Subtract(city.ItemsOnMarket, 1); Storage.Delete(Storage.CurrentContext, key); cityBytes = Neo.SmartContract.Framework.Helper.Serialize(city); Storage.Put(Storage.CurrentContext, cityKey, cityBytes); Runtime.Notify(3000, itemId); } else if (param.Equals("logBattle")) { if (Runtime.CheckWitness(GeneralContract.GameOwner)) { Runtime.Notify(1); throw new Exception(); } // Prepare log BattleLog log = new BattleLog(); log.BattleId = (byte[])args[0]; log.BattleResult = (BigInteger)args[1]; // 0 - Attacker WON, 1 - Attacker Lose log.BattleType = (BigInteger)args[2]; // 0 - City, 1 - Stronghold, 2 - Bandit Camp log.Attacker = (byte[])args[3]; // Hero log.AttackerTroops = (BigInteger)args[4]; log.AttackerRemained = (BigInteger)args[5]; log.DefenderObject = (byte[])args[6]; // City|Stronghold|Bandit Camp ID log.DefenderTroops = (BigInteger)args[7]; log.DefenderRemained = (BigInteger)args[8]; string battleIdKey = BATTLE_LOG_MAP + log.BattleId; byte[] battleLogBytes = Storage.Get(Storage.CurrentContext, battleIdKey); if (battleLogBytes.Length > 0) { Runtime.Notify(7002); throw new Exception(); } // Get Hero string heroKey = HERO_MAP + log.Attacker; byte[] heroBytes = Storage.Get(Storage.CurrentContext, heroKey); if (heroBytes.Length <= 0) { Runtime.Notify(7003); throw new Exception(); } Hero hero = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(heroBytes); if (!Runtime.CheckWitness(hero.OWNER)) { Runtime.Notify(7004); throw new Exception(); } log.AttackerItem1 = (byte[])args[9]; log.AttackerItem2 = (byte[])args[10]; log.AttackerItem3 = (byte[])args[11]; log.AttackerItem4 = (byte[])args[12]; log.AttackerItem5 = (byte[])args[13]; Log.CheckItemOwnership(log.AttackerItem1, log.Attacker); Log.CheckItemOwnership(log.AttackerItem2, log.Attacker); Log.CheckItemOwnership(log.AttackerItem3, log.Attacker); Log.CheckItemOwnership(log.AttackerItem4, log.Attacker); Log.CheckItemOwnership(log.AttackerItem5, log.Attacker); BigInteger attackerNum = (BigInteger)args[3]; if (attackerNum == 0) { Runtime.Log("Hero Number is 0"); } // Check Signature byte[] signature = (byte[])args[14]; byte[] battleResultBytes = (byte[])args[1]; byte[] battleTypeBytes = (byte[])args[2]; byte[] signMessage = Neo.SmartContract.Framework.Helper.Concat(log.BattleId, battleResultBytes); Runtime.Log("Concatination of Defense was succ"); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, battleTypeBytes); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.Attacker); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.DefenderObject); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.AttackerItem1); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.AttackerItem2); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.AttackerItem3); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.AttackerItem4); signMessage = Neo.SmartContract.Framework.Helper.Concat(signMessage, log.AttackerItem5); Runtime.Log("Concatted message data"); Runtime.Log("Message converted"); if (!VerifySignature(signMessage, signature, GameOwnerPublicKey)) { Runtime.Notify(2); Runtime.Notify(signMessage); Runtime.Notify(signature); Runtime.Log("Signature Verification Failed"); throw new Exception(); } BigInteger defenderObject = (BigInteger)args[6]; Log.Battle(log, hero, attackerNum, args[15], defenderObject); } //else if (param.Equals("changeMarketFee")) //{ // // Available ranges are: // BigInteger min = 0; // BigInteger max = 70; // // If city is owned by a player, then should be called by a player // // If city is owned by NPC, then should be called by game owner //} //else if (param.Equals("changeCofferPercents")) //{ // // Should be called by game owner // BigInteger min = 10; // BigInteger max = 70; //} byte[] res = new byte[1] { 0 }; return(res); }
/// <summary> /// /// </summary> /// <param name="log"></param> /// <param name="hero"></param> /// <param name="attackerNum"></param> /// <param name="cofferSize"></param> /// <param name="defenderObject"></param> public static void Battle(BattleLog log, Hero hero, BigInteger attackerNum, object cofferSize, BigInteger defenderObject) { // Get Hero of Defender string key; byte[] bytes; if (log.BattleType == GeneralContract.PVC) { Runtime.Log("Attack to city"); key = GeneralContract.CITY_MAP + log.DefenderObject; bytes = Storage.Get(Storage.CurrentContext, key); if (bytes.Length <= 0) { Runtime.Notify(7005); throw new Exception(); } else { City city = (City)Neo.SmartContract.Framework.Helper.Deserialize(bytes); if (city.Hero > 0 && city.Hero == attackerNum) { Runtime.Notify(7006); throw new System.Exception(); } else { byte[] feeBytes = Storage.Get(Storage.CurrentContext, GeneralContract.FEE_PVC); if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner)) { if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner2)) { Runtime.Notify(7007); throw new Exception(); } } // Increase city coffer byte[] pvcCofferAdditionBytes = Storage.Get(Storage.CurrentContext, GeneralContract.PVC_COFFER_ADDITION_AMOUNT); byte[] cofferSizeBytes = (byte[])cofferSize; if (pvcCofferAdditionBytes.Length > 0) { if (!pvcCofferAdditionBytes.Equals(cofferSizeBytes)) { Runtime.Notify(7020, cofferSizeBytes, pvcCofferAdditionBytes); throw new Exception(); } } BigInteger cofferSizeNum = (BigInteger)cofferSize; BigInteger cityCoffer = Helper.GetCoffer(defenderObject); cityCoffer = BigInteger.Add(cityCoffer, cofferSizeNum); if (log.BattleResult == GeneralContract.ATTACKER_WON) { // change city owner city.Hero = attackerNum; } else if (log.BattleResult != GeneralContract.ATTACKER_LOSE) { Runtime.Notify(7008); throw new Exception(); } Helper.SetCoffer(defenderObject, cityCoffer); key = GeneralContract.CITY_MAP + log.DefenderObject; bytes = Neo.SmartContract.Framework.Helper.Serialize(city); Storage.Put(Storage.CurrentContext, key, bytes); } } } else if (log.BattleType == GeneralContract.PVP) { key = GeneralContract.STRONGHOLD_MAP + log.DefenderObject; bytes = Storage.Get(Storage.CurrentContext, key); if (bytes.Length <= 0) { Runtime.Notify(7009); throw new Exception(); } else { Runtime.Log("Stronghold is on blockchain"); if (hero.StrongholdsAmount > 0) { Runtime.Notify(7010); throw new Exception(); } Stronghold stronghold = (Stronghold)Neo.SmartContract.Framework.Helper.Deserialize(bytes); if (stronghold.Hero > 0 && stronghold.Hero == attackerNum) { Runtime.Notify(7010); throw new Exception(); } else { Runtime.Log("Stronghold is not owned by player"); byte[] feeBytes = Storage.Get(Storage.CurrentContext, GeneralContract.FEE_PVP); if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner)) { if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner2)) { Runtime.Notify(7012); throw new Exception(); } } Runtime.Log("Attachment is included"); if (log.BattleResult == GeneralContract.ATTACKER_WON) { // Can not compile // byte[] oldHeroIdBytes = stronghold.Hero.ToByteArray(); BigInteger oldHeroKeyInt = stronghold.Hero; byte[] oldHeroIdBytes = oldHeroKeyInt.ToByteArray(); string oldHeroKey = GeneralContract.HERO_MAP + oldHeroIdBytes; byte[] oldHeroBytes = Storage.Get(oldHeroKey); if (oldHeroKeyInt > 0 && oldHeroIdBytes.Length <= 0) { Runtime.Notify(7022); throw new Exception(); } else if (oldHeroKeyInt > 0) { Hero oldHero = (Hero)Neo.SmartContract.Framework.Helper.Deserialize(oldHeroBytes); oldHero.StrongholdsAmount = BigInteger.Subtract(oldHero.StrongholdsAmount, 1); oldHeroBytes = Neo.SmartContract.Framework.Helper.Serialize(oldHero); Storage.Put(oldHeroKey, oldHeroBytes); } // change stronghold owner stronghold.Hero = attackerNum; stronghold.CreatedBlock = Blockchain.GetHeight(); hero.StrongholdsAmount = BigInteger.Add(hero.StrongholdsAmount, 1); string heroKey = GeneralContract.HERO_MAP + log.Attacker; byte[] heroBytes = Neo.SmartContract.Framework.Helper.Serialize(hero); Storage.Put(Storage.CurrentContext, heroKey, heroBytes); } else if (log.BattleResult != GeneralContract.ATTACKER_LOSE) { Runtime.Notify(7013); throw new Exception(); } Runtime.Log("Stronghold attack data prepared"); key = GeneralContract.STRONGHOLD_MAP + log.DefenderObject; bytes = Neo.SmartContract.Framework.Helper.Serialize(stronghold); Storage.Put(Storage.CurrentContext, key, bytes); Runtime.Log("Stronghold data inserted"); } } } else if (log.BattleType == GeneralContract.PVE) { Runtime.Log("Bandit camp attack"); key = GeneralContract.BANDIT_CAMP_MAP + log.DefenderObject; bytes = Storage.Get(Storage.CurrentContext, key); if (bytes.Length <= 0) { Runtime.Notify(7014); throw new System.Exception(); } else { Runtime.Log("Bandit camp on blockchain"); byte[] feeBytes = Storage.Get(Storage.CurrentContext, GeneralContract.FEE_PVE); if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner)) { if (!GeneralContract.AttachmentExistAB(feeBytes, GeneralContract.GameOwner2)) { Runtime.Notify(7015); throw new Exception(); } } BigInteger exp = (BigInteger)cofferSize; if (log.BattleResult == GeneralContract.ATTACKER_WON) { Runtime.Log("Bandit camp attacker won"); UpdateItemStats(log.AttackerItem1, log.AttackerItem2, log.AttackerItem3, log.AttackerItem4, log.AttackerItem5, log.BattleId, exp); } else if (log.BattleResult == GeneralContract.ATTACKER_LOSE) { Runtime.Log("Bandit camp attacker Lose"); UpdateItemStats(log.AttackerItem1, log.AttackerItem2, log.AttackerItem3, log.AttackerItem4, log.AttackerItem5, log.BattleId, exp); } else { Runtime.Notify(7016); throw new System.Exception(); } } } else { Runtime.Notify(7017); throw new Exception(); } Runtime.Log("Battle typ specific data change finished"); log.Time = Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp; Runtime.Log("Battle data returned"); string battleIdKey = GeneralContract.BATTLE_LOG_MAP + log.BattleId; byte[] battleLogBytes = Storage.Get(Storage.CurrentContext, battleIdKey); battleLogBytes = Neo.SmartContract.Framework.Helper.Serialize(log); Storage.Put(Storage.CurrentContext, battleIdKey, battleLogBytes); Runtime.Log("Battle Data on blockchain"); Runtime.Notify(7000, log.BattleId, log.BattleResult, log.BattleType, log.Attacker, log.AttackerTroops, log.AttackerRemained, log.AttackerItem1, log.AttackerItem2, log.AttackerItem3, log.AttackerItem4, log.AttackerItem5, log.DefenderObject, log.DefenderTroops, log.DefenderRemained); }