/* Afflands API (Javascript); @cheatcodezz ©️ 2024 */ /*if(!location.href.startsWith('https:')) location.href = 'http://afflands.ru';*/ if (window.network) throw new Error("window.network has been loaded on this page wtfak??"); const REST_API_ADDRESS = location.href.startsWith('https:') ? 'https://afflands.ru/bridge' : 'http://afflands.ru/bridge'; // 95.141.206.151 if (window.DEBUGLOG === false) { } else window.DEBUGLOG = true; window.DEBUGLOG = false; //-- примеры кода (async function example_code() { // as Документация if (1 === 1) return 'dont run this, stub!'; //(!) подписываться на события вовсе не обязательно // подписываемся на событие потери соединения с сервером // реконнект невозможен из кода, если сеть доступна, клиент автоматически подключиться network.on_connection_lost = () => { }; // если соединения вернулось, произойдет событие on_connection_restored // в этом случае можно убрать окно показа "Соединение потеряно" network.on_connection_restored = () => { }; // (!) Обязательные события // Эти два события вызываются когда Авторизация произошла успешна // тут приходят данные базы авторизованого игрока // все его прокачки гексы инвентари балансы монет // смотри консоль в Kiwi Browser чтобы смотреть удобно все данные что тут есть // если эти события происходят, надо перекидывать ясно дело на базу и рендерить все ето дело network.onAcceptBaseData = (data) => { // базовая информация if (DEBUGLOG) console.log('onAcceptBaseData:', data); }; network.onAcceptSecondaryData = (data) => { // вторичная информация if (DEBUGLOG) console.log('onAcceptSecondaryData:', data); }; network.onEnemyAction = (data) => { if (DEBUGLOG) console.log('onEnemyAction:', data); } // Общая концепция: все нижописанные методы возвращают первым аргументов число // к примеру: // результат вызова // const result = await network.auth('Email', 'Password'); // Вернет: [0, 'null'] // Первый элемент массива - результат операции // >= 1 - операция выполнена успешно // <=0 - операция не успешна, сервер ответил с ошибкой, // например тут 0 - значит игрок с таким эмейлом и паролем не найден // остальные элементы массива какие-либо данные.. // Иногда NaN // (!) Таймстампы // Сервер активно использует таймстампы(в секундах!) // - Это отчет секунд от 1970 год бла бла бла // Получить текущий таймстамп: (+Date.now()/1000) function getNowTimestamp() { return (+Date.now() / 1000); } // (*) Получить текущий таймстамп в секундах по серверному времени await network.getNowTimestamp(); // Получить из таймстампа сервера текущую дату: // new Date(timestamp * 1000); // Что вернет обьект Date -> Fri Sep 27 2024 14:40:30 GMT+0300 (Moscow Standard Time) // Ну и изнего мона getHours getMinutes и тп. получати // Глава [Пользовательские функции] // (*) авторизация игрока, данные могут браться из localStorage для сохранения сессии await network.auth('Email', 'Password'); // Return: // Успешно: [>=1(а может и NaN), 'null'] (!) или другой ответ, контролировать успешную авторизациию надо когда вызываются // onAcceptBaseData и onAcceptSecondaryData - их вызов означает успешную авторизацию на сервере, рендерим базу игрока! // Неуспешно: [0, 'null'] // аккаунт не найден // Неуспешно: [-5, block, reason] // аккаунт заблокирован, //* block - таймстамп блока(дату отблока можно получить как: new Date(+block) //* reason - причина блока // (*) Регистрация аккаунта await network.registration(nickname, password, email); // если регистрация неуспешная - первым элементом ответа массива бует 0 или меньшнее число // если регистрация прошла успешно, сервер вызовет события авторизации(onAcceptBaseData и onAcceptSecondaryData) // автоматически // (!) методы нижее работают для авторизованных пользователей // вызов их не имея авторизации соединения не имеют проху и не скажутся на работе серва :) // (*) синхронизация данных ui // вызываем разок(можно и не разок) когда пользователь авторизован(тобиш вызов етот сунуть в onAcceptBaseData событие) // затем каждые "5" секунд, будет запрашивать актуальные данные энергии, монеток, банкнот и тп. await network.syncData(5); // Событие синхронизации данных с верхней панели network.onSyncData = (data) => { if (DEBUGLOG) console.log('onSyncData: ', data); // данные из data меняем в ui: энергия монеты, чек лог что тут ести! }; // (*) Смена никнейма await network.setNickname(nickname); // 0 <= - не успешно, 1 успешно, вторым аргументом в успехе прилетит ник // (*) Смена пароля await network.setPassword(password); // (*) Добавление друга(можно передавать ид или ник игрока) await network.addFriend(idOrNickname); // (*) Удалить заявку в друзья, по номеру заявки await network.removeApplication(numberApp); // (*) Загрузить список друзей await network.loadFriends(); // (*) Удалить из друзей по иду игрока await network.removeFriend(idRemoveFriend); // (*) Отправить заявку в друзья по иду игрока и описание заявки await network.sendApplication(id_player, description); // (*) Загрузить список заявок в друзья await network.showApplications(); // (*) Купить энергию(не бачок, а сразу +100 энергии) await network.buyEnergy(); // (*) Купить монеты // любое кол-во сюда можно передать но кратное 100 // за 100 монет 1 банкнота await network.buyCoin(100); // (*) Загрузить Топ Славы // whoSort: "clans" или "users" ( ну у нас users тока терь раз кланов нема) // numberTypeSort: 0 1 или 2 -> соответстуя соортировкам по fame_day, fame_week, fame_month(дневной, недельный, месячный) // point: от 1 до 20, типо по 5 мест берется для загрузки, типо отправим 1 - получим места с 1 по 5ое, отправим 2 - 6-10 await network.loadTop("users", numberTypeSort, point); // (*) Загрузить информацию от топах(типо все места в трех топах дневном нед. и ежемес.) await network.loadInfoTops(); // (*) Покупка зоны(от 1 до 25, смотри файл там инфа с гексами каждой зоны) // Цена: 50000 монет await network.buyZone(numZone); // (*) Купить расходники // index: 0 или 1 соответствуя "Авиаудар" "Авиалечение" // count: кол-во // Цена 10 и 5 банкнот соответственно за единицу товара // (!) мона покупать расходники и через 'buyPurchase' метод сети :) await network.buyConsumable(index, count); // (*) Удвоить награду за бой после просмотра рекламного ролика, удваивается опыт и монеты await network.doubleReward(); // (*) Получить награду за прокрут рулетки, только после просмотра ролика! Обманивать низя! Ограничение 10 рол./сут await network.getRewardForRoulette(); // (*) Установить режим загрузки аватара, нужно перед вызовом setAvatar, чтобы сервер знал что сча base64 картинка полетит await network.setModeAvatar(); // (*) Установить аватарку // base64 - строка, можно получить как: // https://stackoverflow.com/questions/6150289/how-can-i-convert-an-image-into-base64-string-using-javascript // base64 строка должна быть без протокола, чисто строка, тоббиш: // 'data:image/png,base64,KDOEENEF...' - не верно, // 'data:image/jpeg,base64,KDOEENEF...' - не верно, // 'KDOEENEF...' - верно await network.setAvatar(base64); // (*) Покупка // если достаточно ресурса(-ов) для покупки, кидает в инвентарь, на клиенте сделать проверку касательно // лимитированных обьектов(там когда база после авторизации грузится ети данные мелькают) // чтобы как ты грил небыло бага, тип в инвентаре если лежит уже штукенца, второй раз покупаеш но неставиш то // чтобы не улетела в инвентарь. Ну если я прально помню баг. // (1) section: Resources // nameInRequest: Энергетик 5 banknote // nameInRequest: Авиаудар 10 banknote // nameInRequest: Авиалечение 5 banknote // nameInRequest: Обелиск 3000 coin // nameInRequest: Скамейка 3000 coin // (2) section: Constructions // nameInRequest: любая покупка из Data.ManagerCosts // в файле Data.cs(могу скинуть), или в файле котором я тебе кидал ранее // (3) section: Units // nameInRequest: любая покупка из Data.ManagerCosts // (4) section: ClanShop // неактуалити // (5) section: AdsRoullete // 'Громовержец' 55_000 tokenRoulette // 'Боец СП' 17500 tokenRoulette // '10 кредитов' 8000 tokenRoulette // 'Энергетик' 1000 tokenRoulette // '10000 монет' 3000 tokenRoulette // '500 руды' 1000 tokenRoulette // '300 нефти' 1000 tokenRoulette // (6) section: Machine_Guns // nameInRequest: любая покупка из Data.ManagerCosts await network.buyPurchase(section, nameInRequest); // (*) Загрузить чужую базу по никнейму игрока(для просмотра, не нападения) await network.loadAnotherBase(nickname); // (*) Использовать энергетик из ивентаря(+100 энергии, минус энергетик) await network.usePowerEngineer(); // (*) Оповестить сервер об успешном прохождении миссии(ведь они у нас сделаны клиентскими) // numberMission - номер миссии от 1 до 50 // outcome - исход битвы, 1 - победа, 0 - поражение // countCoin - кол-во заработанных монет при прохождении миссии, не более 1500 await network.completeMission(numberMission, outcome, countCoin); // (*) Оповестить сервер о потере юнитов(тобиш минуснуть с базы и добавить в госпиталь) await network.subtractLostUnits(nameUnit, count); // (*) Загрузить информацию госпиталя await network.loadHospital(); // (*) Восстановить юнита из госпиталя // (?) Как определяется цена?: // Если юнит есть в Data.ManagerCosts(см файл)(вроде все юниты есть там) // - то 1/10 от цены его в той валюте что и его цена // Если "Град" - 50 банкнот (ну так в сервере прописано, града у нас вроде нет и ет лишнее) // Остальное - 3000 монет await network.reviveUnit(nameUnit); // (*) Активация перемирия в МИД-е // mode - 0 1 или 2 - соответствуя активации на 72 168 и 720 часов // цены 20, 120, 400 банкнот соотвественно await network.activateTruce(mode); // (*) Загрузить информацию мида(вторым аргументов прилетит таймстамп перемирия(тобиш до какого)) // Если (+Date.now() / 1000) > етого_значения значется перемирия нету await network.loadMFAContent(); // (*) Загрузить информацию штаба(тут будут нападения на базу игрока) await network.loadHistoryAssaults(); // (*) Получить энергию +100 за просмотр ролика(о5 же обманывать низяя :( ) await network.getEnergy(); // (*) Загрузить информацию штаба(тут будут нападения на базу игрока) await network.loadHistoryAssaults(); // Глава [Функции базы и построек] // (строительство, перемещение, ротейт, запуск продовольствия ням ням:) // (*) Установить постройку/юнита на базу // nameBuild - Имя постройки/юнита // wherePurchase="Inventory", если указать другое значение - будет считаться как покупка из магазина // numberHex - гекс для установки await network.setBuild(nameBuild, wherePurchase, numberHex); // (*) Оповестить, что постройка достроена и готова к использованию(хотя сервер сам сделает ее готовой)/ // но шоб невтыкал :) // targetHex - гекс постройки await network.setReadyConstruction(targetHex); // (*) Переместить постройку/юнита с одного места на другое // sourceHex - гекс на котором постройка сча, // hexTo - гекс куда надобно поставить await network.moveBuild(sourceHex, hexTo); // (*) Удалить постройку/юнита с базы // Если есть в ManagerCosts - 10% от стоимости начислится на баланс в той валюте // Если нету 500 монет await network.deleteBuild(numberHex); // (*) Повернуть постройку // numberHex - гекс постройки // angleRotate - 0 1 2 3 - соответствуя 0 90 180 270 градусам await network.rotateBuild(numberHex, angleRotate); // (*) Запустить производство на постройке // targetHexBuild - гекс постройки // mode - 1, 2, 3, 4 (и еще 5 но для форвардера только) await network.launchProduction(targetHexBuild, mode); // (*) Забрать продовольствие у постройки // targetHexBuild - гекс постройки await network.takeProduction(targetHexBuild); // (*) Улучшить юнита(из академии которые, тренируемые) // Это частичное улучшение, часть прокачки, не полный апгрейд и лиш этап его // unit - "Отряд наемников" ||"Отряд разведки" || "Снайпер" || "Сапёр" и тд. там техника и флот // numImpr - от 0 до 3 (это уровень прокачки) // Цены и апгрейды в файлике чекай(там где Data.UpgraderUnitsCost) await network.makeImprovementUnit(unit, numImpr); // (*) Апгрейд юнита(из академии которые, тренируемые) // Если условия прокачек соблюдены, можно апгрейднуть // lvl - 2 или 3 await network.upgradeLvlUnit(unit, lvl); // (*) Апгрейд здания и конструкций(палатки, склады, пулеметы и тп) // запроси у меня кусок кода там все цены и что улучшается ести // в функцию передается ток гекс здания, что улучшается, больше данных не нужно само высчитывает await network.upgradeLvlConstruction(hex); // (*) Исследовать юнита(ну открыть его в исследовательском центре) // запроси у меня кусок кода где цены await network.researchUnit(nameUnit); // (*) Исследовать юнита(ну открыть его в исследовательском центре) // запроси у меня кусок кода где цены await network.researchUnit(nameUnit); // Глава [Чат] // Показ чата, отправка сообщений и модерирование // (*) Загрузка последних сообщений(вызывать каждые N-секунд и обновлять чатик) await network.showChat(); // (*) Отправить сообщение в чат await network.submitMessage(msg); // (*) Удалить сообщение(если прав хватит) await network.deleteMessage(idMessageForDelete); // (*) Забанить игрока в чате await network.banPlayer(mode, nickname, reason); // Глава [Pve бои] // (*) Найти и загрузить рандомную вражескую базу // numMission - если миссия - то указать номер ее // если бой с рандомным игркоом ниче не указывать await network.findEnemyBase(numMission); // (*) Загрузить миссию // numberMission - от 1 до 50 await network.loadMissionBase(numberMission); // (*) Напасть на базу // После findEnemyBase для потверждения нападаения на базу // вернет кол-во техники пехоты и зданий на базе в случае успешного выполнения await network.attackEnemyBase(); // (*) Напасть на базу // После attackEnemyBase для высадки всех юнитов на базе врага // Что важно? Тут все юниты высаживаются, вызывать можно один раз // boarding - строка с гексами юнитов, а именно куда высаживается, и гекс юнита на базе // тобиш: // boarding += numberHexBoarding + "?&" + numberHexOnOwnBase + "?&" // Хотим добавить штурмовиков которые у нас на базе на 765 гексе, а хотим высадить на 553 гекс базы противника: // let boarding = ''; // boarding += 553 + "&" + 765 + "&"; // и так со всеми высаживаемыми юнитами. // Тобиш когда игрок ищет базу врагу, надо сохранять информацию о всех своих юнитах на базе на стороне клиента // Можно сделать обьект по типу такого: // { // "Отряд разведки": [375, 389], // ... // } // ну т.е. пройтись перед отправкой поиска вражеской базы по своей базе и собрать весь актуальный состав на битву await network.setUnitsToEnemyBase(boarding); // после этого момента битва началась // (*) Загрузить битву(если игрок в битве, вышел из игры, чтобы попасть обратно в битву - эта функция загрузки) // (!) можно вызывать и просто так во время битвы, тут есть полезная инфа касательно кол-во ресурсов await network.loadEnemyBase(); // (!) Функции 'makeMove' 'makeAttack' 'makeMoveAndAttack' и 'skipRound' возвращают в ответе // действие врага(ну там будет гекс юнита, перемещение, или атака нашего юнита в понятном формате) // (*) Получить путь гексов от исх. к желаемому гексу // Вернет "None", если пути нет // Вернет что-то типа "359,360,361", тобиш чекнуть и преобразовать в массив split-ом для использования // в функции makeMove await network.getMovePath(hexFrom, hexTo, lengthMove); // (*) Получить гексы стреляющие(дотягивающиеся по дистанции стрельбы) до указаной постройки/юнита // hexAcceptAttack - гекс принимающий атаку // isOurUnit - Это наш юнит принимает атаку? Или вражеский. 0 - наш, 1 - вражеский // Вернет "None", если никто не дотягивается // Вернет что-то типа "359,360,361", тобиш чекнуть и преобразовать в массив split-ом await network.getShootingHexes(hexAcceptAttack, isOurUnit); // (*) Получить хп у постройки на гекса await network.getHpOnHex(hex); // (*) Переместить юнита(ход) // array_move_hexes - массив всего пути // к примеру: [356, 357, 358] // что означает что наш юнит на 356 гексе передвигается на 357 и на конечную точку 358 гекс await network.makeMove(array_move_hexes); // (*) Атаковать вражескую постройку/юнита ну и усе что атакуемо // numberHexAttack - гекс постройки в которую стреляют // (!) дополнительно к вражескому ходу если постройка уничтожена вернет строку с наградой за уничтожение await network.makeAttack(numberHexAttack); // (*) Передвинуться и атаковать противника за один ход // array_movattk_hexes - массив всего пути и гекс удара // к примеру: [356, 357, 358, 359] // что означает что наш юнит на 356 гексе передвигается на конечную точку 358 гекс и стреляет на 359 гекс await network.makeMoveAndAttack(array_movattk_hexes); // (*) Авиаудар или Авиалечение // index : 0 или 1 -> "Авиаудар" или "Авиалечение" соответственно // hex - куда применяем await network.makeAction(index, hex); // (*) Завершить бой // вернет результаты боя награду и прочее await network.finishFight(); //АРЕНА ++++: //Подача заявки в бой await network.IntoQueue(hex1, hex2, hex3, hex4); //Отмена заявки в бой await network.OutOfQueue(); //Получение состояния боя await network.GetStateInArena(); //Перенаправление в бой await network.RedirectionInArena(); //Получения гексов перемещенияи езда await network.getMovePathArena(hexFrom, hexTo, lengthMove); //Атака await network.makeAttackArena(numberHexAttack); //Езда+Атака await network.makeMoveAndAttackArena(hexsNumberFrom, hexsNumberShoot); //Получение хп гекса await network.getHpOnHexArena(hexsNumberShoot); })(); //--все что ниже, не должно интересовать //--это не нужно для понимания, все функции описаны выше. const network = window.network = new function _AfflandsNetwork() { this; this.on_connection_lost = () => { return; alert(`Вебсокет закрыт, на время тестирования оповещаем через alert, для вызова своего кода, сделайте калбэк network.on_connection_lost = () => { /*.. показуем потерю соединения и обновляем страницу для реконнекта ..*/ }; `) }; this.on_connection_restored = () => { }; this.onAcceptBaseData = (data) => { if (DEBUGLOG) console.log(TAG, 'onAcceptBaseData:', data); }; this.onAcceptSecondaryData = (data) => { if (DEBUGLOG) console.log(TAG, 'onAcceptSecondaryData:', data); }; this.onSyncData = (data) => { if (DEBUGLOG) console.log(TAG, 'onSyncData:', data); }; const TAG = '[WEBSOCKET]', TAGERROR = '[WEBSOCKET-ERROR]'; // connect to rest api const client_token = makeid(16); const deliver = '_%@£££££££££££@@%_'; function RestApi(REST_API_ADDRESS) { const route = REST_API_ADDRESS; this.send = (message) => { fetch(route, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ data: client_token + deliver + message }) }).then(d => d.text()).then(text => this.onmessage({ data: text })); }; this.onopen = () => { }; this.onmessage = () => { }; setTimeout(() => { this.isOpen = true; this.onopen(); }, 500); return this; } const ws = this.ws = new RestApi(REST_API_ADDRESS); ws.onopen = _ => { if (DEBUGLOG) console.log(TAG, 'Соединение установлено'); ws.isOpen = true; this.on_connection_restored(); }; ws.onclose = _ => { if (DEBUGLOG) console.log(TAG, 'Соединение потеряно'); ws.isOpen = false; this.on_connection_lost(); }; let response = ''; ws.onmessage = _ => { if (DEBUGLOG) console.log(TAG, 'Входящее:', _.data.substring(0, 100)); return response += _.data; }; ws.onerror = _ => { ws.isOpen = false; if (DEBUGLOG) console.error(TAGERROR, _); this.on_connection_lost(); }; const queue_send = []; const timeout = 10; let locker_queue = false; (async function queue() { while (true) { const data = queue_send.shift(); if (data) { if (DEBUGLOG) console.log('sendy:', data); locker_queue = true; ws.send(data); while(locker_queue) await w(timeout*3); /*while (response.length == 0) */await w(timeout); } else await w(timeout); } })(); async function send(data) { const result = await _send(_formRequest(data)); // парсим ответ return parseResponse(result); } async function _send(data) { while (response.length > 0) await w(timeout); while (queue_send.length > 0) await w(timeout); if (!ws.isOpen) throw new Error('Соединение с вебсокетом не открыто.'); while (!ws.isOpen) await w(timeout); if (DEBUGLOG) console.log(TAG, 'Отправляем:', data.substring(0, 100)); queue_send.push(data); while (response.length == 0) await w(timeout); locker_queue = false; const r = response; response = ''; return r; } function _formRequest(request) { let _request = request.replaceAll("$", "/:022:/"); _request = "$" + _request + "$"; return _request; } function parseResponse(_response) { //console.log('parseResponse:', _response); const resultParse = parse(_response); return parseResultParse(resultParse); } function parseResultParse(resultParse) { const result = resultParse; if (resultParse) { const classHandler = resultParse[0], methodHandler = resultParse[1], result = resultParse[2]; //console.log('parse, methodHandler: ' + methodHandler); if (methodHandler == 'ServerError') { return [-100, 'Ошибка выполнения запроса']; } else if (methodHandler == 'AcceptInfoPlayerBaseData') { const data = {}; const ip = data; const _parameters = result; ip["coin"] = Number(_parameters[0]); ip["banknote"] = Number(_parameters[1]); ip.nickname = _parameters[2]; ip["energy"] = Number(_parameters[3]); ip.lvl = Number(_parameters[4]); ip.rank = Number(_parameters[5]); ip.rankMax = Number(_parameters[6]); ip.idRank = Number(_parameters[7]); ip.exp = Number(_parameters[8]); ip.expMax = Number(_parameters[9]); ip["ore"] = Number(_parameters[10]); ip["oreMax"] = Number(_parameters[11]); ip["token"] = Number(_parameters[12]); ip["tokenMax"] = Number(_parameters[13]); ip["oil"] = Number(_parameters[14]); ip["oilMax"] = Number(_parameters[15]); ip.stars = Number(_parameters[17]); ip.LvlBattlepass = Number(_parameters[18]); ip.starsMax = Number(_parameters[19]); ip["sight"] = Number(_parameters[20]); ip["boots"] = Number(_parameters[21]); ip["armor"] = Number(_parameters[22]); ip["bullets338"] = Number(_parameters[23]); ip["engine"] = Number(_parameters[24]); ip["barrel"] = Number(_parameters[25]); ip["ammunition"] = Number(_parameters[26]); ip["armor_plate"] = Number(_parameters[27]); ip["tehnic"] = Number(_parameters[28]); ip["infantry"] = Number(_parameters[29]); ip["construction"] = Number(_parameters[30]); ip["tokenRoulette"] = Number(_parameters[31]); ip["fame_day"] = Number(_parameters[32]); ip["fame_week"] = Number(_parameters[33]); ip["fame_month"] = Number(_parameters[34]); ip.IdViewBase = Number(_parameters[35]); ip.LvlViewBase = Number(_parameters[36]); ip.IdRoom = Number(_parameters[37]); ip["viewsAd"] = Number(_parameters[38]); ip.IndexPveInClanWarList = Number(_parameters[39]); ip["progress_mission"] = Number(_parameters[40]); ip.SpecialBP = _parameters[41] == "true" ? true : false; ip["KM"] = Number(_parameters[42]); ip["timestamp_next_change_avatar"] = Number(_parameters[44]); ip["isModerator"] = (_parameters[45]) == "true" ? true : false; ip["id_prev_daily_reward"] = _parameters[46]; ip["prev_banknote_bonus"] = _parameters[47]; data.hexes = deserialize(result[16]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } data.avatar = 'data:image/jpeg;base64,' + (result[43]); return window.network.onAcceptBaseData(data); } else if (methodHandler == 'AcceptInfoPlayerSecondaryData') { const data = {}; data.tasks = (result[0]); data.upgrades = deserialize(result[1]); data.builds = deserialize(result[2]); for (let i = 0; i < data.builds.length; i++) { data.builds[i].typeBuild = getPropertyBuild(data.builds[i], 'typeBuild'); data.builds[i].countHexBuild = getPropertyBuild(data.builds[i], 'countHexBuild'); data.builds[i].angleRotate = getPropertyBuild(data.builds[i], 'angleRotate'); data.builds[i].Army = getPropertyBuild(data.builds[i], 'Army'); data.builds[i].lvl = getPropertyBuild(data.builds[i], 'lvl'); data.builds[i].terrain = getPropertyBuild(data.builds[i], 'terrain'); data.builds[i].readyBuild = getPropertyBuild(data.builds[i], 'readyBuild'); data.builds[i].access = getPropertyBuild(data.builds[i], 'access'); data.builds[i].unitInFight = getPropertyBuild(data.builds[i], 'unitInFight'); const build = data.builds[i]; build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } data.researches = deserialize(result[3]); data.units = JSON.parse(result[4]); data.availableCountBuilds = deserialize(result[5]); data.inventory = deserialize(result[6]); return window.network.onAcceptSecondaryData(data); } else if (methodHandler == 'PlusEnergy') { const data = {}; data.energy = Number(result[0]); data.banknote = Number(result[1]); data.coin = Number(result[2]); data.oil = Number(result[3]); data.ore = Number(result[4]); data.token = Number(result[5]); data.tokenMax = Number(result[6]); if (data.banknote.toString() == 'NaN') return [1]; return window.network.onSyncData(data); } else if (methodHandler == 'ShowApplications') { const data = deserialize(result[1]); return data; } else if (methodHandler == 'FindEnemyBase') { try { const data = {}; const _parameters = result; data["lvl"] = Number(_parameters[1]); data["nickname"] = (_parameters[2]); data["hexes"] = deserialize(result[3]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } data["id_clan"] = Number(_parameters[4]); data["coin"] = Number(_parameters[5]); data["oil"] = Number(_parameters[6]); data["ore"] = Number(_parameters[7]); data["idRank"] = Number(_parameters[8]); data["avatar"] = 'data:image/jpeg;base64,' + (result[9]); data["fame_day"] = Number(_parameters[10]); return data; } catch (ex) { console.error("err in FindEnemyBase: ", ex); } } else if (methodHandler == 'RedirectionInArena') { try { const data = {}; const _parameters = result; data["hexes"] = deserialize(result[1]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } return data; } catch (ex) { console.error("err in RedirectionInArena: ", ex); } } else if (methodHandler == 'LoadAnotherBase') { const data = {}; const _parameters = result; data["hexes"] = deserialize(result[1]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } data["playerInfo"] = JSON.parse(_parameters[3]); return data; } else if (methodHandler == 'LoadMissionBase') { const data = {}; const _parameters = result; data["hexes"] = deserialize(result[1]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } return data; } else if (methodHandler == 'AttackEnemyBase') { const data = {}; if (result[0] <= 0) return result; data["count_tehnic"] = Number(result[1]); data["count_infantry"] = Number(result[2]); data["count_construction"] = Number(result[3]); return data; } else if (methodHandler == 'LoadEnemyBase') { try { if (result[0] <= 0) { response = ''; return result; } const data = JSON.parse(result[1]); const _parameters = result; data["hexes"] = deserialize(data["hexesJson"]); for (let i = 0; i < data.hexes.length; i++) { data.hexes[i].busy = getPropertyHex(data.hexes[i], 'busy'); data.hexes[i].owner = getPropertyHex(data.hexes[i], 'owner'); data.hexes[i].terrain = getPropertyHex(data.hexes[i], 'terrain'); data.hexes[i].whose = getPropertyHex(data.hexes[i], 'whose'); if (data.hexes[i].build?.length > 0) { data.hexes[i].build = JSON.parse(data.hexes[i].build); const build = data.hexes[i].build; build.typeBuild = getPropertyBuild(build, 'typeBuild'); build.countHexBuild = getPropertyBuild(build, 'countHexBuild'); build.angleRotate = getPropertyBuild(build, 'angleRotate'); build.Army = getPropertyBuild(build, 'Army'); build.lvl = getPropertyBuild(build, 'lvl'); build.terrain = getPropertyBuild(build, 'terrain'); build.readyBuild = getPropertyBuild(build, 'readyBuild'); build.access = getPropertyBuild(build, 'access'); build.unitInFight = getPropertyBuild(build, 'unitInFight'); build.currentHp = getParamBuild(build, 'currentHp'); build.maxHp = getParamBuild(build, 'maxHp'); build.attack = getParamBuild(build, 'attack'); build.distance = getParamBuild(build, 'distance'); build.lengthMove = getParamBuild(build, 'lengthMove'); build.skill = getParamBuild(build, 'skill'); } } delete data["hexesJson"]; return data; } catch (ex) { console.warn("err in LoadEnemyBase: ", ex); return result; } } else if (methodHandler == 'GetMovePath') { return result; } else if (methodHandler == 'EnemyAction') { network.onEnemyAction(result); return result; } // проверка на параметры для десериализации for (let e = 1; e < result.length; e++) try { const elem = result[e]; if (elem.toString().startsWith('{') && elem.toString().endsWith('}') && elem.toString().includes(':')) result[e] = JSON.parse(elem); } catch { } return result; } else return null; } let chunk = ""; function parse(_responce) { // rewrited from Csharp { if (chunk != "") { _responce = chunk + _responce; chunk = ""; } let resultParse = []; try { let max = 1; let posStartQuery = 0; let posEndQuery = 0; let flag = true; while (max < 20 && flag) { // 0. find edges respond posStartQuery = _responce.indexOf("$", posEndQuery); posEndQuery = _responce.indexOf("$", posStartQuery + 1); if (posEndQuery == -1) { chunk = _responce.substr(0); return; } if (posEndQuery == _responce.length - 1) flag = false; let _action = _responce.substr(posStartQuery + 1, posEndQuery - posStartQuery); posEndQuery++; // 1. find class handler and transmitting him parameters query let pos = _action.indexOf("?") + 1; let endPos = _action.indexOf("?", pos); //int prevEndPos = 0; let nextPos = endPos + 1; if (pos == 0) { /*console.error(TAGERROR, `Error parsing: failed responde.(responde: ${_responce}`);*/ for (let i = 0; i < resultParse.length - 1; i++) parseResultParse(resultParse[i]); return resultParse[resultParse.length - 1]; } let className = _action.substr(0, (pos - 1)); let methodName = _action.substr(pos, (_action.indexOf("?", pos) - pos)); let parameters = []; for (let i = 0; i < 400; i++) // 400 - max count parameters from all methods handlers { endPos = _action.indexOf("&", nextPos); if (endPos == -1) break; parameters[i] = _action.substr(nextPos, (endPos - nextPos)).replaceAll("&", "¬").replaceAll("$", "¬"); nextPos = endPos + 1; } if (methodName != "GetMovePath" && methodName != "GetShootingHexes" && parameters[0]) parameters[0] = Number(parameters[0]); if (DEBUGLOG) console.log(TAG, 'FindHandlerAndInvoke:', className, methodName, parameters); resultParse.push([className, methodName, parameters]); max++; } for (let i = 0; i < resultParse.length - 1; i++) parseResultParse(resultParse[i]); return resultParse[resultParse.length - 1]; } catch (Exception) { if (DEBUGLOG) console.error(TAGERROR, 'Error while parsing response from server:', Exception); } } } function deserialize(string) { // afflands deserializator let d = JSON.parse(string); let key = Object.keys(d)[0]; for (let i = 0; i < d[key].length; i++) d[key][i] = JSON.parse(d[key][i]); return removeUndefineds(d[key]); } function removeUndefineds(array) { return (array = array.filter(function (element) { return element != undefined; })) } function getPropertyHex(hex, nameProperty) { if (hex == null) throw new Error("Ссылка на гекс равна null."); switch (nameProperty) { case "busy": { let numBit = 0; let val = (hex.propertyHex & (1 << numBit)) == 0 ? 0 : 1; return val; } case "owner": { let numBit = 1; let val = (hex.propertyHex & (1 << numBit)) == 0 ? 0 : 1; return val; } case "terrain": { let numBit1 = 2; let numBit2 = 3; let val = (hex.propertyHex & (1 << numBit1)) == 0 ? 0 : 1; val |= (((hex.propertyHex & (1 << numBit2)) == 0 ? 0 : 1) << 1); return val; } case "whose": { let numBit = 4; let val = (hex.propertyHex & (1 << numBit)) == 0 ? 0 : 1; return val; } default: { throw new Error(`Свойства \"${nameProperty}\" не существует у гекса!`); } } } function getPropertyBuild(build, nameProperty) { if (build == null) throw new Error("Ссылка на билд равна null."); switch (nameProperty) { case "typeBuild": { let numBit1 = 0, numBit2 = 1, numBit3 = 2, numBit4 = 3; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.propertyBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.propertyBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.propertyBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); return val; } case "countHexBuild": { let numBit1 = 4, numBit2 = 5, numBit3 = 6, numBit4 = 7, numBit5 = 8; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.propertyBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.propertyBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.propertyBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); val |= (((build.propertyBuild & (1 << numBit5)) == 0 ? 0 : 1) << 4); return val; } case "angleRotate": { let numBit1 = 9, numBit2 = 10; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.propertyBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); return val; } case "Army": { let numBit1 = 11; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; return val; } case "lvl": { let numBit1 = 12, numBit2 = 13, numBit3 = 14; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.propertyBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.propertyBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); return val; } case "terrain": { let numBit1 = 15, numBit2 = 19; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.propertyBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); return val; } case "readyBuild": { let numBit1 = 16; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; return val; } case "access": { let numBit1 = 17; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; return val; } case "unitInFight": { let numBit1 = 18; let val = (build.propertyBuild & (1 << numBit1)) == 0 ? 0 : 1; return val; } default: { throw new Error(`Свойства \"${nameProperty}\" не существует у постройки.`); } } } function getParamBuild(build, nameParam) { if (build == null) throw new Error("Ссылка на билд равна null."); switch (nameParam) { case "currentHp": { let numBit1 = 0, numBit2 = 1, numBit3 = 2, numBit4 = 3, numBit5 = 4, numBit6 = 5, numBit7 = 6; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.paramBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); val |= (((build.paramBuild & (1 << numBit5)) == 0 ? 0 : 1) << 4); val |= (((build.paramBuild & (1 << numBit6)) == 0 ? 0 : 1) << 5); val |= (((build.paramBuild & (1 << numBit7)) == 0 ? 0 : 1) << 6); return val; } case "maxHp": { let numBit1 = 7, numBit2 = 8, numBit3 = 9, numBit4 = 10, numBit5 = 11, numBit6 = 12, numBit7 = 13; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.paramBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); val |= (((build.paramBuild & (1 << numBit5)) == 0 ? 0 : 1) << 4); val |= (((build.paramBuild & (1 << numBit6)) == 0 ? 0 : 1) << 5); val |= (((build.paramBuild & (1 << numBit7)) == 0 ? 0 : 1) << 6); return val; } case "attack": { let numBit1 = 14, numBit2 = 15, numBit3 = 16, numBit4 = 17, numBit5 = 18, numBit6 = 19, numBit7 = 20; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.paramBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); val |= (((build.paramBuild & (1 << numBit5)) == 0 ? 0 : 1) << 4); val |= (((build.paramBuild & (1 << numBit6)) == 0 ? 0 : 1) << 5); val |= (((build.paramBuild & (1 << numBit7)) == 0 ? 0 : 1) << 6); return val; } case "distance": { let numBit1 = 21, numBit2 = 22, numBit3 = 23, numBit4 = 24; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.paramBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); return val; } case "lengthMove": { let numBit1 = 25, numBit2 = 26, numBit3 = 27, numBit4 = 28; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); val |= (((build.paramBuild & (1 << numBit4)) == 0 ? 0 : 1) << 3); return val; } case "skill": { let numBit1 = 29, numBit2 = 30, numBit3 = 31; let val = (build.paramBuild & (1 << numBit1)) == 0 ? 0 : 1; val |= (((build.paramBuild & (1 << numBit2)) == 0 ? 0 : 1) << 1); val |= (((build.paramBuild & (1 << numBit3)) == 0 ? 0 : 1) << 2); return val; } default: { throw new Error(`Свойства \"${nameParam}\" не существует.`); } } } // методы сети // PveHandler this.method = async function () { const request = ""; return await send(request); }; this.getMovePath = async function (hexFrom, hexTo, lengthMove) { const request = `PveHandler?GetMovePath?${hexFrom}&${hexTo}&${lengthMove}&`; return await send(request); }; this.getShootingHexes = async function (hexAcceptAttack, isOurUnit) { const request = `PveHandler?GetShootingHexes?${hexAcceptAttack}&${isOurUnit}&`; return await send(request); }; this.getHpOnHex = async function (hex) { const request = `PveHandler?GetHpOnHex?${hex}&`; return await send(request); }; this.finishFight = async function () { const request = "PveHandler?FinishFight?1&"; return await send(request); }; this.skipRound = async function () { const request = `PveHandler?SkipRound?1&`; return await send(request); }; this.makeMoveAndAttack = async function (array_movattk_hexes) { let parameters = ""; for (let s of array_movattk_hexes) parameters += s + "&"; const request = `PveHandler?MakeMoveAndAttack?${parameters}`; return await send(request); }; this.makeAttack = async function (numberHexAttack) { const request = `PveHandler?MakeAttack?${numberHexAttack}&`; return await send(request); }; this.makeAction = async function (index, hex) { const request = `PveHandler?MakeAction?${index}&${hex}&`; return await send(request); }; this.makeMove = async function (array_move_hexes) { let parameters = ""; for (let s of array_move_hexes) parameters += s + "&"; const request = `PveHandler?MakeMove?${parameters}`; return await send(request); }; this.setUnitsToEnemyBase = async function (boarding) { const request = `PveHandler?SetUnitsToEnemyBase?${boarding}`; return await send(request); }; this.loadEnemyBase = async function () { const request = `PveHandler?LoadEnemyBase?1&`; return await send(request); }; this.attackEnemyBase = async function () { const request = `PveHandler?AttackEnemyBase?1&`; return await send(request); }; this.loadMissionBase = async function (numberMission) { const request = `PveHandler?LoadMissionBase?${numberMission}&`; return await send(request); }; this.findEnemyBase = async function (missionNum) { const request = `PveHandler?FindEnemyBase?1&` + (missionNum ? missionNum + '&' : ''); return await send(request); }; // ChatHandler this.banPlayer = async function (mode, nickname, reason) { const request = `ChatHandler?BanPlayer?${mode}&${nickname}&${reason}&`; return await send(request); }; this.deleteMessage = async function (idMessageForDelete) { const request = `ChatHandler?DeleteMessage?${idMessageForDelete}&`; return await send(request); }; this.submitMessage = async function (msg) { const request = `ChatHandler?SubmitMessage?${msg}&`; return await send(request); }; this.toggleChat = async function (numberChat) { const request = `ChatHandler?ToggleChat?${numberChat}&`; return await send(request); }; this.showChat = async function () { const request = `ChatHandler?ShowChat?1?&`; return await send(request); }; // BuildHandler this.researchUnit = async function (nameUnit) { const request = `BuildHandler?ResearchUnit?${nameUnit}&`; return await send(request); }; this.upgradeLvlConstruction = async function (hex) { const request = `BuildHandler?UpgradeLvlConstruction?${hex}&`; return await send(request); }; this.upgradeLvlUnit = async function (unit, lvl) { const request = `BuildHandler?UpgradeLvlUnit?${unit}&${lvl}&`; return await send(request); }; this.makeImprovementUnit = async function (unit, numImpr) { const request = `BuildHandler?MakeImprovementUnit?${unit}&${numImpr}&`; return await send(request); }; this.takeProduction = async function (targetHexBuild) { const request = `BuildHandler?TakeProduction?${targetHexBuild}&`; return await send(request); }; this.launchProduction = async function (targetHexBuild, mode) { const request = `BuildHandler?LaunchProduction?${targetHexBuild}&${mode}&`; return await send(request); }; this.rotateBuild = async function (numberHex, angleRotate) { const request = `BuildHandler?Rotate?${numberHex}&${angleRotate}&`; return await send(request); }; this.deleteBuild = async function (numberHex) { const request = `BuildHandler?Delete?${numberHex}&`; return await send(request); }; this.moveBuild = async function (sourceHex, hexTo) { const request = `BuildHandler?Move?${sourceHex}&${hexTo}&`; return await send(request); }; this.setReadyConstruction = async function (targetHex) { const request = `BuildHandler?SetReadyConstruction?${targetHex}&`; return await send(request); }; this.setBuild = async function (name, wherePurchase = "Inventory", numberHex) { const request = `BuildHandler?SetBuild?${name}&${wherePurchase}&${numberHex}&`; return await send(request); }; // UserHandler this.getEnergy = async function () { const request = `UserHandler?GetEnergy?1&`; return await send(request); }; this.loadHistoryAssaults = async function () { const request = `UserHandler?LoadHistoryAssaults?1&`; return await send(request); }; this.loadMFAContent = async function () { const request = `UserHandler?LoadMFAContent?1&`; return await send(request); }; this.activateTruce = async function (mode) { const request = `UserHandler?ActivateTruce?${mode}&`; return await send(request); }; this.reviveUnit = async function (nameUnit) { const request = `UserHandler?ReviveUnit?${nameUnit}&`; return await send(request); }; this.loadHospital = async function () { const request = "UserHandler?LoadHospital?1&"; return await send(request); }; this.subtractLostUnits = async function (name, count) { const result = `%${name}%^${count}^*${count}*`; const request = `UserHandler?SubtractLostUnits?${result}&`; return await send(request); }; this.completeMission = async function (numberMission, outcome, countCoin) { const request = `UserHandler?CompleteMission?${numberMission}&${outcome}&${countCoin}&`; return await send(request); }; this.usePowerEngineer = async function () { const request = `UserHandler?UsePowerEngineer?1&`; return await send(request); }; this.loadAnotherBase = async function (nickname) { const request = `UserHandler?LoadAnotherBase?${nickname}&`; return await send(request); }; this.buyPurchase = async function (section, nameInRequest) { const request = `UserHandler?BuyPurchase?${section}&${nameInRequest}&`; return await send(request); }; this.setModeAvatar = async function () { const request = `UserHandler?SetModeAvatar?1&`; return await send(request); }; this.setAvatar = async function (base64) { const request = `UserHandler?SetAvatar?${base64}&`; return await send(request); }; this.getRewardForRoulette = async function () { const request = "UserHandler?WatchedAd?1&"; return await send(request); }; this.doubleReward = async function () { const request = "UserHandler?DoubleReward?1&"; return await send(request); }; this.buyConsumable = async function (index, count) { const request = `UserHandler?BuyConsumable?${index}&${count}&`; return await send(request); }; this.buyZone = async function (numZone) { const request = `UserHandler?BuyZone?${numZone}&`; return await send(request); }; this.takeTask = async function (nameTask) { const request = `UserHandler?TakeTask?${nameTask}&`; return await send(request); }; this.getTask = async function (nameTask) { const request = `UserHandler?GetTask?${nameTask}&`; return await send(request); }; this.getTasks = async function () { const request = `UserHandler?GetTasks?${1}&`; return await send(request); }; this.buySpecialBPForBanknotes = async function () { const request = `UserHandler?BuySpecialBPForBanknotes?${1}&`; return await send(request); }; this.loadInfoTops = async function () { const request = "UserHandler?LoadInfoTops?1&"; return await send(request); }; this.loadTop = async function (whoSort, numberTypeSort, point) { const request = `UserHandler?LoadTop?${whoSort}&${numberTypeSort}&${point}&`; return await send(request); }; this.buyCoin = async function (countCoin) { const request = `UserHandler?BuyCoin?${countCoin}&`; return await send(request); }; this.buyEnergy = async function () { const request = `UserHandler?BuyEnergy?1?&`; return await send(request); }; this.removeFriend = async function (idRemoveFriend) { const request = `UserHandler?RemoveFriend?${idRemoveFriend}?&`; return await send(request); }; this.showApplications = async function () { const request = "UserHandler?ShowApplications?" + '0' + "?&"; return await send(request); }; this.sendApplication = async function (id_player, description = "Добавляйся в друзья!") { const request = `UserHandler?SendApplication?${id_player}?&${description}?&`; return await send(request); }; this.removeApplication = async function (numberApp) { const request = `UserHandler?RemoveApplication?${numberApp}?&`; return await send(request); }; this.addFriend = async function (idOrNickname) { const request = `UserHandler?AddFriend?${idOrNickname}?&`; return await send(request); }; this.auth = async function (email, password) { const request = "UserHandler?Authorization?" + email + "?&" + password + "?&"; return await send(request); }; let intervalSync = -1; this.syncData = async function (sec) { if (intervalSync >= 0) clearInterval(intervalSync); const request = "UserHandler?PlusEnergy?" + '0' + "?&"; if (sec == 0) sec = 1; intervalSync = setInterval(() => send(request), sec * 1e3); }; this.registration = async function (nickname, password, email) { emailpass = email + ':' + password; const request = "UserHandler?Registration?" + nickname + "&" + password + "&" + email + "&"; return await send(request); }; this.setNickname = async function (nickname) { const request = "UserHandler?SetNickname?" + nickname + "?&"; return await send(request); }; this.setPassword = async function (password) { const request = "UserHandler?SetPassword?" + password + "?&"; return await send(request); }; this.getNowTimestamp = async function () { const request = "UserHandler?GetNowTimestamp?1?&"; return await send(request); }; this.loadFriends = async function () { const request = "UserHandler?LoadFriends?" + '0' + "?&"; return await send(request); }; //АРЕНА ++++: this.intoQueue = async function(hex1, hex2, hex3, hex4) { if ([hex1, hex2, hex3, hex4].some(v => typeof v === "undefined")) { throw new Error("Нужно передавать 4 гекса (4 числа)."); } const request = `ArenaHandler?IntoQueue?${hex1}&${hex2}&${hex3}&${hex4}&`; return await send(request); }; this.outOfQueue = async function() { const request = "ArenaHandler?OutOfQueue?1?&"; return await send(request); }; this.getStateInArena = async function() { const request = "ArenaHandler?GetStateInArena?1?&"; return await send(request); }; this.redirectionInArena = async function() { const request = "ArenaHandler?RedirectionInArena?1?&"; return await send(request); }; this.getMovePathArena = async function(hexFrom, hexTo, lengthMove) { const request = `ArenaHandler?GetMovePathArena?${hexFrom}&${hexTo}&${lengthMove}&`; return await send(request); }; this.makeAttackArena = async function(numberHexAttack) { const request = `ArenaHandler?MakeAttackArena?${numberHexAttack}&`; return await send(request); }; this.makeMoveAndAttackArena = async function(hexsNumberFrom, hexsNumberShoot) { const request = `ArenaHandler?MakeMoveAndAttackArena?${hexsNumberFrom}&${hexsNumberShoot}&`; return await send(request); }; this.getHpOnHexArena = async function(hex) { const request = `ArenaHandler?GetHpOnHexArena?${hex}&`; return await send(request); }; //--useful funcs async function w(ms) { // wait return await new Promise(r => setTimeout(r, ms)); } function makeid(length) { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; let counter = 0; while (counter < length) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); counter += 1; } return result; }; // object ready return this; };