diff --git a/SLY_Assistant.user.js b/SLY_Assistant.user.js index 99d1609..cfd3790 100644 --- a/SLY_Assistant.user.js +++ b/SLY_Assistant.user.js @@ -1,15 +1,15 @@ // ==UserScript== // @name SLY Assistant -// @namespace http://tampermonkey.net/ -// @version 0.7.0 -// @description try to take over the world! +// @namespace https://github.com/ImGroovin/SLY-Assistant +// @version 0.7.0.34 +// @description Base http://tampermonkey.net/ // @author SLY w/ Contributions by niofox, SkyLove512, anthonyra, [AEP] Valkynen, Risingson, Swift42 // @match https://*.based.staratlas.com/ // @require https://unpkg.com/@solana/web3.js@1.95.8/lib/index.iife.min.js#sha256=a759deca1b65df140e8dda5ad8645c19579536bf822e5c0c7e4adb7793a5bd08 // @require https://raw.githubusercontent.com/ImGroovin/SAGE-Lab-Assistant/main/anchor-browserified.js#sha256=f29ef75915bcf59221279f809eefc55074dbebf94cf16c968e783558e7ae3f0a // @require https://raw.githubusercontent.com/ImGroovin/SAGE-Lab-Assistant/main/buffer-browserified.js#sha256=4fa88e735f9f1fdbff85f4f92520e8874f2fec4e882b15633fad28a200693392 // @require https://raw.githubusercontent.com/ImGroovin/SAGE-Lab-Assistant/main/bs58-browserified.js#sha256=87095371ec192e5a0e50c6576f327eb02532a7c29f1ed86700a2f8fb5018d947 -// @icon https://www.google.com/s2/favicons?sz=64&domain=staratlas.com +// @icon https://cdn.staratlas.com/sage-labs/favicon.ico // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue @@ -187,6 +187,12 @@ //Subwarp when the distance is 1 diagonal sector or less subwarpShortDist: parseBoolDefault(globalSettings.subwarpShortDist, true), + //How many fleet max distance rate to subwarp when is wrap cd (higher number = 2, 0 = none) + smartWarpRemainingDistanceRate: parseIntDefault(globalSettings.smartWarpRemainingDistanceRate, 0), + + //How much multiple food for mining (max: 2, default: 1) + multipleFoodMining: parseIntDefault(globalSettings.multipleFoodMining, 1), + //Determines if your transports should use their ammo banks to move ammo (in addition to their cargo holds) transportUseAmmoBank: parseBoolDefault(globalSettings.transportUseAmmoBank, true), @@ -494,17 +500,17 @@ }, ]); - cLog(0,'getResourceTokens()'); + cLog(1,'getResourceTokens()'); await getResourceTokens(); - cLog(0,'getCraftRecipes()'); + cLog(1,'getCraftRecipes()'); await getCraftRecipes(); - cLog(0,'getALTs()'); + cLog(1,'getALTs()'); await getALTs(); - console.log('craftRecipes: ', craftRecipes); - console.log('upgradeRecipes: ', upgradeRecipes); + cLog(1, 'craftRecipes: ', craftRecipes); + cLog(1, 'upgradeRecipes: ', upgradeRecipes); let sduItem = cargoItems.find(item => item.name === 'Survey Data Unit'); let fuelItem = cargoItems.find(item => item.token === sageGameAcct.account.mints.fuel.toString()); @@ -4246,6 +4252,9 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee debugLogLevel: parseIntDefault(document.querySelector('#debugLogLevel').value, 3), craftingJobs: parseIntDefault(document.querySelector('#craftingJobs').value, 4), subwarpShortDist: document.querySelector('#subwarpShortDist').checked, + smartWarpRemainingDistanceRate: parseIntDefault(document.querySelector('#smartWarpRemainingDistanceRate').value, 0), + + multipleFoodMining: parseIntDefault(document.querySelector('#multipleFoodMining').value, 1), transportUseAmmoBank: document.querySelector('#transportUseAmmoBank').checked, transportStopOnError: document.querySelector('#transportStopOnError').checked, transportFuel100: document.querySelector('#transportFuel100').checked, @@ -4311,6 +4320,9 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee document.querySelector('#debugLogLevel').value = globalSettings.debugLogLevel; document.querySelector('#craftingJobs').value = globalSettings.craftingJobs; document.querySelector('#subwarpShortDist').checked = globalSettings.subwarpShortDist; + document.querySelector('#smartWarpRemainingDistanceRate').value = globalSettings.smartWarpRemainingDistanceRate; + + document.querySelector('#multipleFoodMining').value = globalSettings.multipleFoodMining; document.querySelector('#transportUseAmmoBank').checked = globalSettings.transportUseAmmoBank; document.querySelector('#transportStopOnError').checked = globalSettings.transportStopOnError; document.querySelector('#transportFuel100').checked = globalSettings.transportFuel100; @@ -4614,47 +4626,69 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee let currentCargoFuel = fleetCurrentCargo.value.find(item => item.account.data.parsed.info.mint === sageGameAcct.account.mints.fuel.toString()); let currentCargoFuelCnt = currentCargoFuel ? currentCargoFuel.account.data.parsed.info.tokenAmount.uiAmount : 0; - let shortSubwarp = moveDist < 1.5 && globalSettings.subwarpShortDist ? true : false; + let shortSubwarp = moveDist < 1.5 && globalSettings.subwarpShortDist ? true : false; //Should a warp be attempted? if (userFleets[i].moveType == 'warp' && (currentFuelCnt + currentCargoFuelCnt) >= warpCost && !shortSubwarp) { let fleetAcctData = sageProgram.coder.accounts.decode('fleet', fleetAcctInfo.data); let warpCooldownExpiresAt = fleetAcctData.warpCooldownExpiresAt.toNumber() * 1000; - //Wait for cooldown - while (Date.now() < warpCooldownExpiresAt) { - if (!userFleets[i].state.includes('Warp C/D')) { - const warpCDExpireTimeStr = `[${TimeToStr(new Date(warpCooldownExpiresAt))}]`; - cLog(1,`${FleetTimeStamp(userFleets[i].label)} Awaiting Warp C/D ${warpCDExpireTimeStr}`); - updateFleetState(userFleets[i], `Warp C/D ${warpCDExpireTimeStr}`); + // smart movement (author: zihan) + cLog(2, `smart movement ready? moveDist:${moveDist}, maxWarpDistance:${maxWarpDistance}, Setting:${globalSettings.smartWarpRemainingDistanceRate}`) + const maxWarpDistance = userFleets[i].maxWarpDistance / 100 + if (globalSettings.smartWarpRemainingDistanceRate > 0 && + ( + moveDist > maxWarpDistance && (warpCooldownExpiresAt - Date.now() > userFleets[i].warpCooldown * 1000 * 0.3) + || moveDist <= maxWarpDistance * globalSettings.smartWarpRemainingDistanceRate * 0.01 + ) + ) { + let moveDistNew = moveDist; + if (moveDist > maxWarpDistance) { + cLog(2, `smart movement going`) + // if moveDist is too long distance, just subwarp half maxWarpDistance + moveDistNew = max(moveDist - maxWarpDistance, globalSettings.smartWarpRemainingDistanceRate * 0.01 * maxWarpDistance); + moveDistNew = min(moveDist, moveDistNew) + [moveX, moveY] = calcNextWarpPoint(moveDistNew, extra, [moveX, moveY]); } + moveTime = calculateSubwarpTime(userFleets[i], moveDistNew); + await execSubwarp(userFleets[i], moveX, moveY, moveTime); + } else { + //Wait for cooldown + while (Date.now() < warpCooldownExpiresAt) { + if (!userFleets[i].state.includes('Warp C/D')) { + const warpCDExpireTimeStr = `[${TimeToStr(new Date(warpCooldownExpiresAt))}]`; + cLog(1,`${FleetTimeStamp(userFleets[i].label)} Awaiting Warp C/D ${warpCDExpireTimeStr}`); + updateFleetState(userFleets[i], `Warp C/D ${warpCDExpireTimeStr}`); + } - //await wait(Math.max(1000, warpCooldownExpiresAt - Date.now())); - if(warpCooldownExpiresAt - Date.now() < 5000) await wait(Math.max(1000, warpCooldownExpiresAt - Date.now())); - else await wait(5000); - if(userFleets[i].stopping) return; - } - await wait(2000); //Extra wait to ensure accuracy - - //Calculate next warp point if more than 1 is needed to arrive at final destination - if (moveDist > userFleets[i].maxWarpDistance / 100) { - [moveX, moveY] = calcNextWarpPoint(userFleets[i].maxWarpDistance, extra, [moveX, moveY]); - - //Saves temporary waypoints for transports in case the page is refreshed mid-journey while using warp - const fleetPK = userFleets[i].publicKey.toString(); - const fleetSavedData = await GM.getValue(fleetPK, '{}'); - const fleetParsedData = JSON.parse(fleetSavedData); - //cLog(3, `${FleetTimeStamp(userFleets[i].label)} moveTargets`, fleetParsedData.moveTarget, userFleets[i].moveTarget); - fleetParsedData.moveTarget = userFleets[i].moveTarget; - await GM.setValue(fleetPK, JSON.stringify(fleetParsedData)); + //await wait(Math.max(1000, warpCooldownExpiresAt - Date.now())); + if (warpCooldownExpiresAt - Date.now() < 5000) await wait(Math.max(1000, warpCooldownExpiresAt - Date.now())); + else await wait(5000); + if (userFleets[i].stopping) return; + } + await wait(2000); //Extra wait to ensure accuracy + + //Calculate next warp point if more than 1 is needed to arrive at final destination + if (moveDist > userFleets[i].maxWarpDistance / 100) { + [moveX, moveY] = calcNextWarpPoint(userFleets[i].maxWarpDistance, extra, [moveX, moveY]); + + //Saves temporary waypoints for transports in case the page is refreshed mid-journey while using warp + const fleetPK = userFleets[i].publicKey.toString(); + const fleetSavedData = await GM.getValue(fleetPK, '{}'); + const fleetParsedData = JSON.parse(fleetSavedData); + //cLog(3, `${FleetTimeStamp(userFleets[i].label)} moveTargets`, fleetParsedData.moveTarget, userFleets[i].moveTarget); + fleetParsedData.moveTarget = userFleets[i].moveTarget; + await GM.setValue(fleetPK, JSON.stringify(fleetParsedData)); + + //Update distance based on new warp target + moveDist = calculateMovementDistance(extra, [moveX,moveY]); + } - //Update distance based on new warp target - moveDist = calculateMovementDistance(extra, [moveX,moveY]); + moveTime = calculateWarpTime(userFleets[i], moveDist); + const warpResult = await execWarp(userFleets[i], moveX, moveY, moveTime); + warpCooldownFinished = warpResult.warpCooldownFinished; } - - moveTime = calculateWarpTime(userFleets[i], moveDist); - const warpResult = await execWarp(userFleets[i], moveX, moveY, moveTime); - warpCooldownFinished = warpResult.warpCooldownFinished; - } else if (currentFuelCnt + currentCargoFuelCnt >= subwarpCost) { + } + else if (currentFuelCnt + currentCargoFuelCnt >= subwarpCost) { moveTime = calculateSubwarpTime(userFleets[i], moveDist); await execSubwarp(userFleets[i], moveX, moveY, moveTime); } else { @@ -5188,13 +5222,46 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee await execDock(userFleets[i], userFleets[i].starbaseCoord); cLog(1,`${FleetTimeStamp(userFleets[i].label)} Unloading resource`); updateFleetState(userFleets[i], `Unloading`); - //if (currentResourceCnt > 0) { - let unloadAmount = currentResourceCnt; - if(globalSettings.minerKeep1 && unloadAmount > 0) { unloadAmount -= 1; } - if (unloadAmount > 0) { - await execCargoFromFleetToStarbase(userFleets[i], userFleets[i].cargoHold, userFleets[i].mineResource, userFleets[i].starbaseCoord, unloadAmount); - //await wait(2000); - } + + // let unloadAmount = currentResourceCnt; + // if(globalSettings.minerKeep1 && unloadAmount > 0) { unloadAmount -= 1; } + // if (unloadAmount > 0) { + // await execCargoFromFleetToStarbase(userFleets[i], userFleets[i].cargoHold, userFleets[i].mineResource, userFleets[i].starbaseCoord, unloadAmount); + // //await wait(2000); + // } + + //Unload all token except food (author: zihan) + const unloadQueue = [] + // console.log('mining fleetCurrentCargo', fleetCurrentCargo) + fleetCurrentCargo.value.forEach(async (item) => { + if (item.account.data.parsed.info.tokenAmount.uiAmount > 1 && + item.account.data.parsed.info.mint !== sageGameAcct.account.mints.food.toString()) { + // console.log('mining fleetCurrentCargo item', item.account.data.parsed.info) + unloadQueue.push( + execCargoFromFleetToStarbase( + userFleets[i], + userFleets[i].cargoHold, + item.account.data.parsed.info.mint, + userFleets[i].starbaseCoord, + item.account.data.parsed.info.tokenAmount.uiAmount - (globalSettings.minerKeep1 ? 1 : 0)) + ) + } + // if there is too much food, unload part of food + else if (item.account.data.parsed.info.tokenAmount.uiAmount > foodForDuration * 2 && + item.account.data.parsed.info.mint === sageGameAcct.account.mints.food.toString()) { + // console.log('mining fleetCurrentCargo food item', item.account.data.parsed.info) + unloadQueue.push( + execCargoFromFleetToStarbase( + userFleets[i], + userFleets[i].cargoHold, + item.account.data.parsed.info.mint, + userFleets[i].starbaseCoord, + item.account.data.parsed.info.tokenAmount.uiAmount - foodForDuration * 2) + ) + } + }) + await Promise.all(unloadQueue) + await wait(500); //if (currentFuelCnt < userFleets[i].fuelCapacity) { if (currentFuelCnt < fuelNeeded) { @@ -5232,10 +5299,20 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee cLog(1,`${FleetTimeStamp(userFleets[i].label)} Loading food`); updateFleetState(userFleets[i], `Loading`); let foodCargoTypeAcct = cargoTypes.find(item => item.account.mint.toString() == sageGameAcct.account.mints.food); - let foodResp = await execCargoFromStarbaseToFleet(userFleets[i], userFleets[i].cargoHold, fleetFoodAcct, sageGameAcct.account.mints.food.toString(), foodCargoTypeAcct, userFleets[i].starbaseCoord, foodForDuration - currentFoodCnt); + + // use multiple food for mining (authoer: zihan) + function respFoodfn(amount) { + return execCargoFromStarbaseToFleet(userFleets[i], userFleets[i].cargoHold, fleetFoodAcct, sageGameAcct.account.mints.food.toString(), foodCargoTypeAcct, userFleets[i].starbaseCoord, amount); + } + let foodResp = await respFoodfn(foodForDuration * globalSettings.multipleFoodMining - currentFoodCnt); if (foodResp && foodResp.name == 'NotEnoughResource') { - cLog(1,`${FleetTimeStamp(userFleets[i].label)} ERROR: Not enough food`); - errorResource.push('food'); + // try load food little again + cLog(1, 'try load food little again'); + foodResp = await respFoodfn(foodForDuration - currentFoodCnt); + if (foodResp && foodResp.name == 'NotEnoughResource') { + cLog(1,`${FleetTimeStamp(userFleets[i].label)} ERROR: Not enough food`); + errorResource.push('food'); + } } //await wait(2000); } else { cLog(1,`${FleetTimeStamp(userFleets[i].label)} Food loading skipped: ${currentFoodCnt} / ${foodForDuration}`); } @@ -5259,7 +5336,7 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee //At mining area? else if (fleetCoords[0] == destX && fleetCoords[1] == destY) { - if(userFleets[i].stopping) return; + if (userFleets[i].stopping) return; fleetCurrentCargo = await solanaReadConnection.getParsedTokenAccountsByOwner(userFleets[i].cargoHold, {programId: tokenProgramPK}); cargoCnt = fleetCurrentCargo.value.reduce((n, {account}) => n + account.data.parsed.info.tokenAmount.uiAmount, 0); currentFood = fleetCurrentCargo.value.find(item => item.account.data.parsed.info.mint === sageGameAcct.account.mints.food.toString()); @@ -6759,7 +6836,7 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee validMRZTargets.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); validTargets = validMainTargets.concat(validMRZTargets); - console.log('validTargets:',validTargets); + cLog(1, `validTargets: ${validTargets}`); resolve(); }); @@ -7151,6 +7228,9 @@ async function sendAndConfirmTx(txSerialized, lastValidBlockHeight, txHash, flee settingsModalContentString += ''; settingsModalContentString += '