Skip to content
This repository was archived by the owner on Jul 22, 2019. It is now read-only.

Feature: Sniping (with PogoLocationFeeder) #1036

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config.properties.template
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ use_lucky_egg=1
# Port where the socketserver should listen, 0 = do not listen
gui_port_socket=8001

# Allow sniping (Recommended value: false)
want_sniping false

# Port where the sniping information is sent to
sniping_port=16969

# Export player/pokemondata on Profile Update. Options are:
# *empty* Don't export (default)
# CSV Correct USA/UK CSV format ("," as delimiter and "." as decimal separator)
Expand Down
1 change: 1 addition & 0 deletions json-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"useLuckyEgg" : 1,
"export" : "",
"guiPortSocket" : 8001,
"snipingPort": 16969,
"initialMapSize" : 9,
"waitChance" : 0.0,
"waitTimeMin" : 0,
Expand Down
10 changes: 8 additions & 2 deletions src/main/kotlin/ink/abb/pogo/scraper/Bot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,15 @@ class Bot(val api: PokemonGo, val settings: Settings) {
"Have ${it.pokemonId.name} (${it.nickname}) with ${it.cp} CP and IV $IV% \r\n ${it.getStatsFormatted()}"
}.forEach { Log.normal(it) }

val keepalive = GetMapRandomDirection()
val keepalive = GetMapRandomDirection(isForSniping=false)
val drop = DropUselessItems()
val profile = UpdateProfile()
val catch = CatchOneNearbyPokemon()
val release = ReleasePokemon()
val evolve = EvolvePokemon()
val hatchEggs = HatchEggs()
val export = Export()
val sniper = SnipeListener()

if (settings.export.length > 0)
task(export)
Expand Down Expand Up @@ -156,7 +157,6 @@ class Bot(val api: PokemonGo, val settings: Settings) {
task(drop)
if (settings.autotransfer)
task(release)

}

runLoop(500, "PokestopLoop") {
Expand All @@ -166,6 +166,8 @@ class Bot(val api: PokemonGo, val settings: Settings) {
task(WalkToStartPokestop(process.startPokestop as Pokestop))
}



Log.setContext(ctx)

if (settings.guiPortSocket > 0) {
Expand All @@ -178,6 +180,10 @@ class Bot(val api: PokemonGo, val settings: Settings) {
Log.green("Open the map on http://ui.pogobot.club/")
}

if (settings.wantSniping && settings.snipingPort > 0) {
task(sniper)
Log.normal("Listening for snipe info on port ${settings.snipingPort}")
}

if (settings.timerWalkToStartPokestop > 0)
runLoop(TimeUnit.SECONDS.toMillis(settings.timerWalkToStartPokestop), "BotWalkBackLoop") {
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/ink/abb/pogo/scraper/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ data class Context(

val walking: AtomicBoolean = AtomicBoolean(false),

val pauseWalking: AtomicBoolean = AtomicBoolean(false)
val pauseWalking: AtomicBoolean = AtomicBoolean(false),
val pauseForSniping: AtomicBoolean = AtomicBoolean(false)

)
7 changes: 7 additions & 0 deletions src/main/kotlin/ink/abb/pogo/scraper/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class SettingsParser(val properties: Properties) {

guiPortSocket = getPropertyIfSet("Port where the socketserver should listen", "gui_port_socket", defaults.guiPortSocket, String::toInt),

wantSniping = getPropertyIfSet("Enable or disable the sniping feature", "want_sniping", defaults.wantSniping, String::toBoolean),

snipingPort = getPropertyIfSet("Port where the sniping information will be sent to", "sniping_port", defaults.snipingPort, String::toInt),

initialMapSize = getPropertyIfSet("Initial map size (S2 tiles) to fetch", "initial_map_size", defaults.initialMapSize, String::toInt),

waitChance = getPropertyIfSet("Chance to wait on a pokestop", "wait_chance", defaults.waitChance, String::toDouble),
Expand Down Expand Up @@ -256,6 +260,9 @@ data class Settings(

val guiPortSocket: Int = 8001,

val wantSniping: Boolean = false,
val snipingPort: Int = 16969,

var initialMapSize: Int = 9,

val version: String = Settings.version,
Expand Down
19 changes: 18 additions & 1 deletion src/main/kotlin/ink/abb/pogo/scraper/Values.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,21 @@ package ink.abb.pogo.scraper

val requiredXp = arrayOf(0, 1000, 3000, 6000, 10000, 15000, 21000, 28000, 36000, 45000, 55000, 65000, 75000,
85000, 100000, 120000, 140000, 160000, 185000, 210000, 260000, 335000, 435000, 560000, 710000, 900000, 1100000,
1350000, 1650000, 2000000, 2500000, 3000000, 3750000, 4750000, 6000000, 7500000, 9500000, 12000000, 15000000, 20000000)
1350000, 1650000, 2000000, 2500000, 3000000, 3750000, 4750000, 6000000, 7500000, 9500000, 12000000, 15000000, 20000000)

val pokedexId2Names = arrayOf("missingno", "bulbasaur", "ivysaur", "venosaur", "charmander", "charmeleon", "charizard", "squirtle", "wartortle", "blastoise",
"caterpie", "metapod", "butterfree", "weedle", "kakuna", "beedrill", "pidgey", "pidgeotto", "pidgeot", "rattata",
"raticate", "spearow", "fearow", "ekans", "arbok", "pikachu", "raichu", "sandshrew", "sandslash", "nidoran",
"nidorina", "nidoqueen", "nidoran", "nidorino", "nidoking", "clefairy", "clefable", "vulpix", "ninetales", "ninetails",
"jigglypuff", "wigglytuff", "zubat", "golbat", "oddish", "gloom", "vileplume", "paras", "parasect", "venonat",
"venomoth", "diglett", "dugtrio", "meowth", "persian", "psyduck", "golduck", "mankey", "primeape", "growlithe",
"arcanine", "poliwag", "poliwhirl", "poliwrath", "abra", "kadabra", "alakazam", "machop", "machoke", "machamp",
"bellsprout", "weepinbell", "victreebell", "tentacool", "tentacruel", "geodude", "graveler", "golem", "ponyta",
"rapidash", "slowpoke", "slowbro", "magnemite", "magneton", "farfetch", "doduo", "dodrio", "seel", "dewgong",
"grimer", "muk", "shellder", "cloyster", "gastly", "haunter", "gengar", "onix", "drowzee", "hypno", "krabby",
"kingler", "voltorb", "electrode", "exeggcute", "exeggutor", "cubone", "marowak", "hitmonlee", "hitmonchan",
"lickitung", "koffing", "weezing", "rhyhorn", "rhydon", "chansey", "tangela", "kangaskhan", "horsea", "seadra",
"goldeen", "seaking", "staryu", "starmie", "mime", "scyther", "jynx", "electrabuzz", "magmar", "pinsir", "tauros",
"magikarp", "gyarados", "lapras", "ditto", "eevee", "vaporeon", "jolteon", "flareon", "porygon", "omanyte", "omastar",
"kabuto", "kabutops", "aerodactyl", "snorlax", "articuno", "zapdos", "moltres", "dratini", "dragonair", "dragonite",
"mewtwo", "mew", "venusaur")
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import ink.abb.pogo.scraper.util.pokemon.shouldTransfer
class CatchOneNearbyPokemon : Task {
override fun run(bot: Bot, ctx: Context, settings: Settings) {
// STOP WALKING
if (ctx.pauseForSniping.get()) {
return
}
ctx.pauseWalking.set(true)
val pokemon = ctx.api.map.getCatchablePokemon(ctx.blacklistedEncounters)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import ink.abb.pogo.scraper.Settings
import ink.abb.pogo.scraper.Task
import ink.abb.pogo.scraper.util.Log

class GetMapRandomDirection : Task {
class GetMapRandomDirection(val isForSniping: Boolean) : Task {
override fun run(bot: Bot, ctx: Context, settings: Settings) {
// query a small area to keep alive

if (ctx.pauseForSniping.get() && !isForSniping) {
return
}

val lat = ctx.lat.get() + randomLatLng()
val lng = ctx.lng.get() + randomLatLng()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class ProcessPokestops(var pokestops: MutableCollection<Pokestop>) : Task {
var startPokestop: Pokestop? = null

override fun run(bot: Bot, ctx: Context, settings: Settings) {
if (ctx.pauseForSniping.get()) {
return
}

var writeCampStatus = false
if (lastFetch + refetchTime < bot.api.currentTimeMillis()) {
writeCampStatus = true
Expand Down
60 changes: 60 additions & 0 deletions src/main/kotlin/ink/abb/pogo/scraper/tasks/SnipeListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Pokemon Go Bot Copyright (C) 2016 PokemonGoBot-authors (see authors.md for more information)
* This program comes with ABSOLUTELY NO WARRANTY;
* This is free software, and you are welcome to redistribute it under certain conditions.
*
* For more information, refer to the LICENSE file in this repositories root directory
*/

package ink.abb.pogo.scraper.tasks

import ink.abb.pogo.scraper.Bot
import ink.abb.pogo.scraper.Context
import ink.abb.pogo.scraper.Settings
import ink.abb.pogo.scraper.Task
import ink.abb.pogo.scraper.pokedexId2Names
import kotlin.collections.Map
import java.io.*
import java.net.*
import java.util.ArrayList
import com.fasterxml.jackson.databind.*
import ink.abb.pogo.scraper.util.Log

class SnipeListener : Task {
override fun run(bot: Bot, ctx: Context, settings: Settings) {
val clientSocket = Socket("localhost", settings.snipingPort)

while (true) {
val dataReceived: BufferedReader
val multipleSnipes = ArrayList<Map<*,*>>()

try {
dataReceived = BufferedReader(InputStreamReader(clientSocket.inputStream))
val results = dataReceived.readLine().split("\n")
Log.red("$results")
for (result in results)
{
val result_map = ObjectMapper().readValue(result, Map::class.java)
multipleSnipes.add(result_map)
}

}
catch (e: Exception) {
continue
}

// We use a for loop because it processes multiple pokemon snipes at once.
for (snipe in multipleSnipes)
{
val latitude = snipe["Latitude"].toString().toDouble()
val longitude = snipe["Longitude"].toString().toDouble()
val pokemonId = snipe["Id"].toString().toInt()
val pokemonName: String = (pokedexId2Names[pokemonId + 1]).toString()

Log.green(text="ayo data: $snipe with name $pokemonName")
bot.task(SnipePokemon(latitude, longitude, pokemonName))
}

}
}
}
153 changes: 153 additions & 0 deletions src/main/kotlin/ink/abb/pogo/scraper/tasks/SnipePokemon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* Pokemon Go Bot Copyright (C) 2016 PokemonGoBot-authors (see authors.md for more information)
* This program comes with ABSOLUTELY NO WARRANTY;
* This is free software, and you are welcome to redistribute it under certain conditions.
*
* For more information, refer to the LICENSE file in this repositories root directory
*/

package ink.abb.pogo.scraper.tasks

import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse
import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse.Status
import com.pokegoapi.api.inventory.Pokeball
import com.pokegoapi.api.map.pokemon.encounter.DiskEncounterResult
import ink.abb.pogo.scraper.Bot
import ink.abb.pogo.scraper.Context
import ink.abb.pogo.scraper.Settings
import ink.abb.pogo.scraper.Task
import ink.abb.pogo.scraper.util.Log
import ink.abb.pogo.scraper.util.cachedInventories
import ink.abb.pogo.scraper.util.inventory.hasPokeballs
import ink.abb.pogo.scraper.util.map.getCatchablePokemon
import ink.abb.pogo.scraper.util.pokemon.catch
import ink.abb.pogo.scraper.util.pokemon.getIvPercentage
import ink.abb.pogo.scraper.util.pokemon.getStatsFormatted
import ink.abb.pogo.scraper.util.pokemon.shouldTransfer

class SnipePokemon (val latitude: Double, val longitude: Double, val pokemonName: String): Task {
override fun run(bot: Bot, ctx: Context, settings: Settings) {
ctx.pauseWalking.set(true)
ctx.pauseForSniping.set(true)
val hasPokeballs = ctx.api.cachedInventories.itemBag.hasPokeballs()
if (!hasPokeballs) {
ctx.pauseWalking.set(false)
return
}

var oldLatitude = ctx.lat.get()
var oldLongitude = ctx.lng.get()

ctx.lat.set(latitude); ctx.lng.set(longitude)
ctx.api.setLocation(latitude, longitude, 0.0)
bot.task(GetMapRandomDirection(isForSniping=true))

val pokemon = ctx.api.map.getCatchablePokemon(ctx.blacklistedEncounters)

Log.cyan("Sniper Found $pokemon at long/lat ${ctx.lng.get()}/${ctx.lat.get()}")
val catchablePokemon = pokemon.find { it.pokemonId.toString().toLowerCase().equals(pokemonName.toLowerCase()) }

Log.cyan(text="$catchablePokemon")
if (null != catchablePokemon) {
if (settings.obligatoryTransfer.contains(catchablePokemon.pokemonId) && settings.desiredCatchProbabilityUnwanted == -1.0) {
ctx.blacklistedEncounters.add(catchablePokemon.encounterId)
Log.normal("Found pokemon ${catchablePokemon.pokemonId}; blacklisting it because it's unwanted")
ctx.pauseWalking.set(false)
return
}
Log.green("Found pokemon ${catchablePokemon.pokemonId}")

val encounterResult = catchablePokemon.encounterPokemon()
val wasFromLure = encounterResult is DiskEncounterResult
if (encounterResult.wasSuccessful()) {
val pokemonData = encounterResult.pokemonData
Log.green("Encountered pokemon ${catchablePokemon.pokemonId} " +
"with CP ${pokemonData.cp} and IV ${pokemonData.getIvPercentage()}%")

ctx.lat.set(oldLatitude); ctx.lng.set(oldLongitude)
ctx.api.setLocation(oldLatitude, oldLongitude, 0.0)

bot.task(GetMapRandomDirection(isForSniping=true))

val (shouldRelease, reason) = pokemonData.shouldTransfer(settings)
val desiredCatchProbability = if (shouldRelease) {
Log.yellow("Using desired_catch_probability_unwanted because $reason")
settings.desiredCatchProbabilityUnwanted
} else {
settings.desiredCatchProbability
}
if (desiredCatchProbability == -1.0) {
ctx.blacklistedEncounters.add(catchablePokemon.encounterId)
Log.normal("CP/IV of encountered pokemon ${catchablePokemon.pokemonId} is too low; blacklisting encounter")
ctx.pauseWalking.set(false)
return
}

val isCurveBall = (Math.random() < settings.desiredCurveRate)
val result = catchablePokemon.catch(
encounterResult.captureProbability,
ctx.api.cachedInventories.itemBag,
desiredCatchProbability,
isCurveBall,
!settings.neverUseBerries,
settings.randomBallThrows,
settings.waitBetweenThrows,
-1)

if (result == null) {
ctx.blacklistedEncounters.add(catchablePokemon.encounterId)
Log.red("No Pokeballs in your inventory; blacklisting Pokemon")
ctx.pauseWalking.set(false)
return
}

ctx.blacklistedEncounters.add(catchablePokemon.encounterId)
if (result.status == CatchPokemonResponse.CatchStatus.CATCH_SUCCESS) {
ctx.pokemonStats.first.andIncrement
if (wasFromLure) {
ctx.luredPokemonStats.andIncrement
}
val iv = (pokemonData.individualAttack + pokemonData.individualDefense + pokemonData.individualStamina) * 100 / 45
var message = "Caught a ${catchablePokemon.pokemonId} " +
"with CP ${pokemonData.cp} and IV $iv%"
message += "\r\n ${pokemonData.getStatsFormatted()}"
if (settings.displayIfPokemonFromLure) {
if (encounterResult is DiskEncounterResult)
message += " (lured pokemon) "
else
message += " (wild pokemon) "
}
if (settings.displayPokemonCatchRewards)
message += ": [${result.xpList.sum()}x XP, ${result.candyList.sum()}x " +
"Candy, ${result.stardustList.sum()}x Stardust]"
Log.cyan(message)

ctx.server.newPokemon(catchablePokemon.latitude, catchablePokemon.longitude, pokemonData)
ctx.server.sendProfile()
} else {
Log.red("Capture of ${catchablePokemon.pokemonId} failed with status : ${result.status}")
if (result.status == CatchPokemonResponse.CatchStatus.CATCH_ERROR) {
Log.red("Blacklisting pokemon to prevent infinite loop")
}
}
} else {
// We need to set this back to the old value.
ctx.lat.set(oldLatitude); ctx.lng.set(oldLongitude)
ctx.api.setLocation(oldLatitude, oldLongitude, 0.0)

Log.red("Encounter failed with result: ${encounterResult.status}")
if (encounterResult.status == Status.POKEMON_INVENTORY_FULL) {
Log.red("Disabling catching of Pokemon")

ctx.pokemonInventoryFullStatus.second.set(true)

settings.catchPokemon = false
}
}
}
ctx.pauseWalking.set(false)
bot.task(GetMapRandomDirection(isForSniping=false))
ctx.pauseForSniping.set(false)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import java.util.concurrent.atomic.AtomicBoolean

class WalkToStartPokestop(val startPokeStop: Pokestop) : Task {
override fun run(bot: Bot, ctx: Context, settings: Settings) {
if (ctx.pauseForSniping.get()) {
return
}
if (settings.followStreets) walkRoute(bot, ctx, settings)
else walk(bot, ctx, settings)

Expand Down