diff --git a/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java new file mode 100644 index 00000000..1521fa89 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/inventory/EggIncubator.java @@ -0,0 +1,91 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.inventory; + +import POGOProtos.Inventory.EggIncubatorOuterClass; +import POGOProtos.Networking.Requests.Messages.UseItemEggIncubatorMessageOuterClass.UseItemEggIncubatorMessage; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Responses.UseItemEggIncubatorResponseOuterClass.UseItemEggIncubatorResponse; +import com.google.protobuf.InvalidProtocolBufferException; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.EggPokemon; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; +import lombok.Getter; + +public class EggIncubator { + private final EggIncubatorOuterClass.EggIncubator proto; + private final PokemonGo pgo; + @Getter + private boolean inUse = false; + + /** + * Create new EggIncubator with given proto. + * + * @param pgo the api + * @param proto the proto + */ + public EggIncubator(PokemonGo pgo, EggIncubatorOuterClass.EggIncubator proto) { + this.pgo = pgo; + this.proto = proto; + this.inUse = proto.getPokemonId() != 0; + } + + /** + * Returns the remaining uses. + * + * @return uses remaining + */ + public int getUsesRemaining() { + return proto.getUsesRemaining(); + } + + /** + * Hatch an egg. + * + * @param egg the egg + * @return status of putting egg in incubator + * @throws RemoteServerException the remote server exception + * @throws LoginFailedException the login failed exception + */ + public UseItemEggIncubatorResponse.Result hatchEgg(EggPokemon egg) + throws LoginFailedException, RemoteServerException { + if (!egg.getIsEgg()) { + return null; + } + UseItemEggIncubatorMessage reqMsg = UseItemEggIncubatorMessage.newBuilder() + .setItemId(proto.getId()) + .setPokemonId(egg.getId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.USE_ITEM_EGG_INCUBATOR, reqMsg); + pgo.getRequestHandler().sendServerRequests(serverRequest); + + UseItemEggIncubatorResponse response; + try { + response = UseItemEggIncubatorResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(e); + } + + pgo.getInventories().updateInventories(true); + + this.inUse = true; + + return response.getResult(); + } +} diff --git a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java index 7b8990c6..22b3cd89 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java +++ b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java @@ -15,6 +15,28 @@ package com.pokegoapi.api.inventory; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.EggPokemon; +import com.pokegoapi.api.pokemon.Pokemon; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class Hatchery { + @Getter + Set eggs = new HashSet(); + @Getter + PokemonGo instance; + + public Hatchery(PokemonGo instance) { + this.instance = instance; + } + + public void addEgg(EggPokemon egg) { + eggs.add(egg); + } } diff --git a/src/main/java/com/pokegoapi/api/inventory/Inventories.java b/src/main/java/com/pokegoapi/api/inventory/Inventories.java index b5926fd5..ab41960f 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Inventories.java +++ b/src/main/java/com/pokegoapi/api/inventory/Inventories.java @@ -16,7 +16,8 @@ package com.pokegoapi.api.inventory; import POGOProtos.Enums.PokemonFamilyIdOuterClass; -import POGOProtos.Enums.PokemonIdOuterClass; +import POGOProtos.Enums.PokemonIdOuterClass.PokemonId; +import POGOProtos.Inventory.EggIncubatorOuterClass; import POGOProtos.Inventory.InventoryItemDataOuterClass; import POGOProtos.Inventory.InventoryItemOuterClass; import POGOProtos.Inventory.Item.ItemDataOuterClass.ItemData; @@ -26,12 +27,16 @@ import POGOProtos.Networking.Responses.GetInventoryResponseOuterClass.GetInventoryResponse; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.EggPokemon; import com.pokegoapi.api.pokemon.Pokemon; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.main.ServerRequest; import lombok.Getter; +import java.util.ArrayList; +import java.util.List; + public class Inventories { @@ -44,6 +49,10 @@ public class Inventories { private CandyJar candyjar; @Getter private Pokedex pokedex; + @Getter + private List incubators; + @Getter + private Hatchery hatchery; private long lastInventoryUpdate = 0; @@ -60,6 +69,8 @@ public Inventories(PokemonGo api) throws LoginFailedException, RemoteServerExcep pokebank = new PokeBank(api); candyjar = new CandyJar(api); pokedex = new Pokedex(api); + incubators = new ArrayList<>(); + hatchery = new Hatchery(api); updateInventories(); } @@ -87,6 +98,8 @@ public void updateInventories(boolean forceUpdate) throws LoginFailedException, pokebank = new PokeBank(api); candyjar = new CandyJar(api); pokedex = new Pokedex(api); + incubators = new ArrayList<>(); + hatchery = new Hatchery(api); } GetInventoryMessage invReqMsg = GetInventoryMessage.newBuilder() .setLastTimestampMs(lastInventoryUpdate) @@ -98,36 +111,54 @@ public void updateInventories(boolean forceUpdate) throws LoginFailedException, try { response = GetInventoryResponse.parseFrom(inventoryRequest.getData()); } catch (InvalidProtocolBufferException e) { - e.printStackTrace(); + throw new RemoteServerException(e); } for (InventoryItemOuterClass.InventoryItem inventoryItem : response.getInventoryDelta().getInventoryItemsList()) { InventoryItemDataOuterClass.InventoryItemData itemData = inventoryItem.getInventoryItemData(); - if (itemData.getPokemonData().getPokemonId() != PokemonIdOuterClass.PokemonId.MISSINGNO) { + // hatchery + if (itemData.getPokemonData().getPokemonId() == PokemonId.MISSINGNO && itemData.getPokemonData().getIsEgg()) { + hatchery.addEgg(new EggPokemon(itemData.getPokemonData())); + } + + // pokebank + if (itemData.getPokemonData().getPokemonId() != PokemonId.MISSINGNO) { pokebank.addPokemon(new Pokemon(inventoryItem.getInventoryItemData().getPokemonData())); } + + // items if (itemData.getItem().getItemId() != ItemId.UNRECOGNIZED && itemData.getItem().getItemId() != ItemId.ITEM_UNKNOWN) { - ItemData item = inventoryItem.getInventoryItemData().getItem(); + ItemData item = itemData.getItem(); itemBag.addItem(new Item(item)); } + + // candyjar if (itemData.getPokemonFamily().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.UNRECOGNIZED && itemData.getPokemonFamily().getFamilyId() != PokemonFamilyIdOuterClass.PokemonFamilyId.FAMILY_UNSET) { candyjar.setCandy( - inventoryItem.getInventoryItemData().getPokemonFamily().getFamilyId(), - inventoryItem.getInventoryItemData().getPokemonFamily().getCandy() + itemData.getPokemonFamily().getFamilyId(), + itemData.getPokemonFamily().getCandy() ); } + // player stats if (itemData.hasPlayerStats()) { - api.getPlayerProfile().setStats(inventoryItem.getInventoryItemData().getPlayerStats()); + api.getPlayerProfile().setStats(itemData.getPlayerStats()); } + // pokedex if (itemData.hasPokedexEntry()) { pokedex.add(itemData.getPokedexEntry()); } + if (itemData.hasEggIncubators()) { + for (EggIncubatorOuterClass.EggIncubator incubator : itemData.getEggIncubators().getEggIncubatorList()) { + incubators.add(new EggIncubator(api, incubator)); + } + } + lastInventoryUpdate = System.currentTimeMillis(); } } diff --git a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java index f3d1de05..fe40c054 100644 --- a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java +++ b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java @@ -54,8 +54,6 @@ public boolean test(Pokemon testPokemon) { } } - - /** * Gets pokemon by pokemon id. * diff --git a/src/main/java/com/pokegoapi/api/map/Map.java b/src/main/java/com/pokegoapi/api/map/Map.java index 95318434..44aed570 100644 --- a/src/main/java/com/pokegoapi/api/map/Map.java +++ b/src/main/java/com/pokegoapi/api/map/Map.java @@ -35,6 +35,7 @@ import POGOProtos.Networking.Responses.FortDetailsResponseOuterClass; import POGOProtos.Networking.Responses.FortSearchResponseOuterClass.FortSearchResponse; import POGOProtos.Networking.Responses.GetMapObjectsResponseOuterClass; + import com.annimon.stream.Collectors; import com.annimon.stream.Stream; import com.annimon.stream.function.Function; @@ -49,11 +50,14 @@ import com.pokegoapi.google.common.geometry.S2CellId; import com.pokegoapi.google.common.geometry.S2LatLng; import com.pokegoapi.main.ServerRequest; + import lombok.Getter; import lombok.Setter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class Map { @@ -93,7 +97,7 @@ public void clearCache() { * @return a List of CatchablePokemon at your current location */ public List getCatchablePokemon() throws LoginFailedException, RemoteServerException { - List catchablePokemons = new ArrayList<>(); + Set catchablePokemons = new HashSet<>(); MapObjects objects = getMapObjects(); for (MapPokemon mapPokemon : objects.getCatchablePokemons()) { @@ -111,7 +115,7 @@ public List getCatchablePokemon() throws LoginFailedException, } }*/ - return catchablePokemons; + return new ArrayList<>(catchablePokemons); } /** diff --git a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java index 3036984d..ad144cca 100644 --- a/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java +++ b/src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java @@ -62,9 +62,11 @@ public class CatchablePokemon { /** * Instantiates a new Catchable pokemon. - * - * @param api the api - * @param proto the proto + * + * @param api + * the api + * @param proto + * the proto */ public CatchablePokemon(PokemonGo api, MapPokemon proto) { this.api = api; @@ -77,12 +79,13 @@ public CatchablePokemon(PokemonGo api, MapPokemon proto) { this.longitude = proto.getLongitude(); } - /** * Instantiates a new Catchable pokemon. - * - * @param api the api - * @param proto the proto + * + * @param api + * the api + * @param proto + * the proto */ public CatchablePokemon(PokemonGo api, WildPokemon proto) { this.api = api; @@ -96,9 +99,11 @@ public CatchablePokemon(PokemonGo api, WildPokemon proto) { /** * Instantiates a new Catchable pokemon. - * - * @param api the api - * @param proto the proto + * + * @param api + * the api + * @param proto + * the proto */ public CatchablePokemon(PokemonGo api, FortData proto) { if (!proto.hasLureInfo()) { @@ -109,30 +114,35 @@ public CatchablePokemon(PokemonGo api, FortData proto) { this.spawnPointId = null; this.encounterId = proto.getLureInfo().getEncounterId(); this.pokemonId = proto.getLureInfo().getActivePokemonId(); - this.expirationTimestampMs = proto.getLureInfo().getLureExpiresTimestampMs(); + this.expirationTimestampMs = proto.getLureInfo() + .getLureExpiresTimestampMs(); this.latitude = proto.getLatitude(); this.longitude = proto.getLongitude(); } /** * Encounter pokemon encounter result. - * + * * @return the encounter result - * @throws LoginFailedException the login failed exception - * @throws RemoteServerException the remote server exception + * @throws LoginFailedException + * the login failed exception + * @throws RemoteServerException + * the remote server exception */ - public EncounterResult encounterPokemon() throws LoginFailedException, RemoteServerException { - EncounterMessageOuterClass.EncounterMessage reqMsg = EncounterMessageOuterClass.EncounterMessage.newBuilder() - .setEncounterId(getEncounterId()) + public EncounterResult encounterPokemon() throws LoginFailedException, + RemoteServerException { + EncounterMessageOuterClass.EncounterMessage reqMsg = EncounterMessageOuterClass.EncounterMessage + .newBuilder().setEncounterId(getEncounterId()) .setPlayerLatitude(api.getLatitude()) .setPlayerLongitude(api.getLongitude()) - .setSpawnPointId(getSpawnPointId()) - .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ENCOUNTER, reqMsg); + .setSpawnPointId(getSpawnPointId()).build(); + ServerRequest serverRequest = new ServerRequest( + RequestTypeOuterClass.RequestType.ENCOUNTER, reqMsg); api.getRequestHandler().sendServerRequests(serverRequest); EncounterResponseOuterClass.EncounterResponse response = null; try { - response = EncounterResponseOuterClass.EncounterResponse.parseFrom(serverRequest.getData()); + response = EncounterResponseOuterClass.EncounterResponse + .parseFrom(serverRequest.getData()); } catch (InvalidProtocolBufferException e) { throw new RemoteServerException(e); } @@ -141,13 +151,17 @@ public EncounterResult encounterPokemon() throws LoginFailedException, RemoteSer } /** - * Tries to catch a pokemon (will attempt to use a pokeball, if you have none will use greatball etc). - * + * Tries to catch a pokemon (will attempt to use a pokeball, if you have + * none will use greatball etc). + * * @return CatchResult - * @throws LoginFailedException if failed to login - * @throws RemoteServerException if the server failed to respond + * @throws LoginFailedException + * if failed to login + * @throws RemoteServerException + * if the server failed to respond */ - public CatchResult catchPokemon() throws LoginFailedException, RemoteServerException { + public CatchResult catchPokemon() throws LoginFailedException, + RemoteServerException { Pokeball pokeball; ItemBag bag = api.getInventories().getItemBag(); @@ -164,47 +178,64 @@ public CatchResult catchPokemon() throws LoginFailedException, RemoteServerExcep return catchPokemon(pokeball); } - /** * Tries to catch a pokeball with the given type. - * - * @param pokeball Type of pokeball + * + * @param pokeball + * Type of pokeball * @return CatchResult - * @throws LoginFailedException if failed to login - * @throws RemoteServerException if the server failed to respond + * @throws LoginFailedException + * if failed to login + * @throws RemoteServerException + * if the server failed to respond */ - public CatchResult catchPokemon(Pokeball pokeball) throws LoginFailedException, RemoteServerException { + public CatchResult catchPokemon(Pokeball pokeball) + throws LoginFailedException, RemoteServerException { return catchPokemon(pokeball, -1); } /** * Tried to catch a pokemon with given pokeball and max number of pokeballs. - * - * @param pokeball Type of pokeball - * @param amount Max number of pokeballs to use + * + * @param pokeball + * Type of pokeball + * @param amount + * Max number of pokeballs to use * @return CatchResult - * @throws LoginFailedException if failed to login - * @throws RemoteServerException if the server failed to respond + * @throws LoginFailedException + * if failed to login + * @throws RemoteServerException + * if the server failed to respond */ - public CatchResult catchPokemon(Pokeball pokeball, int amount) throws LoginFailedException, RemoteServerException { - return catchPokemon(1.0, 1.95 + Math.random() * 0.05, 0.85 + Math.random() * 0.15, pokeball, amount); + public CatchResult catchPokemon(Pokeball pokeball, int amount) + throws LoginFailedException, RemoteServerException { + return catchPokemon(1.0, 1.95 + Math.random() * 0.05, + 0.85 + Math.random() * 0.15, pokeball, amount); } /** * Tries to catch a pokemon. - * - * @param normalizedHitPosition the normalized hit position - * @param normalizedReticleSize the normalized hit reticle - * @param spinModifier the spin modifier - * @param type Type of pokeball to throw - * @param amount Max number of Pokeballs to throw, negative number for unlimited + * + * @param normalizedHitPosition + * the normalized hit position + * @param normalizedReticleSize + * the normalized hit reticle + * @param spinModifier + * the spin modifier + * @param type + * Type of pokeball to throw + * @param amount + * Max number of Pokeballs to throw, negative number for + * unlimited * @return CatchResult of resulted try to catch pokemon - * @throws LoginFailedException if failed to login - * @throws RemoteServerException if the server failed to respond + * @throws LoginFailedException + * if failed to login + * @throws RemoteServerException + * if the server failed to respond */ - public CatchResult catchPokemon( - double normalizedHitPosition, double normalizedReticleSize, double spinModifier, Pokeball type, int amount) - throws LoginFailedException, RemoteServerException { + public CatchResult catchPokemon(double normalizedHitPosition, + double normalizedReticleSize, double spinModifier, Pokeball type, + int amount) throws LoginFailedException, RemoteServerException { if (!isEncountered()) { return new CatchResult(); } @@ -213,19 +244,19 @@ public CatchResult catchPokemon( CatchPokemonResponse response = null; do { CatchPokemonMessage reqMsg = CatchPokemonMessage.newBuilder() - .setEncounterId(getEncounterId()) - .setHitPokemon(true) + .setEncounterId(getEncounterId()).setHitPokemon(true) .setNormalizedHitPosition(normalizedHitPosition) .setNormalizedReticleSize(normalizedReticleSize) .setSpawnPointGuid(getSpawnPointId()) .setSpinModifier(spinModifier) - .setPokeball(type.getBallType()) - .build(); - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.CATCH_POKEMON, reqMsg); + .setPokeball(type.getBallType()).build(); + ServerRequest serverRequest = new ServerRequest( + RequestTypeOuterClass.RequestType.CATCH_POKEMON, reqMsg); api.getRequestHandler().sendServerRequests(serverRequest); try { - response = CatchPokemonResponse.parseFrom(serverRequest.getData()); + response = CatchPokemonResponse.parseFrom(serverRequest + .getData()); } catch (InvalidProtocolBufferException e) { throw new RemoteServerException(e); } @@ -235,12 +266,27 @@ public CatchResult catchPokemon( break; } numThrows++; - } - while (amount < 0 || numThrows < amount); + } while (amount < 0 || numThrows < amount); api.getInventories().updateInventories(); return new CatchResult(response); } + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof CatchablePokemon) { + return this.getEncounterId() == ((CatchablePokemon) obj) + .getEncounterId(); + } + return false; + } + + @Override + public int hashCode() { + return (int) this.getEncounterId(); + } + } diff --git a/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java new file mode 100644 index 00000000..120744b6 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/pokemon/EggPokemon.java @@ -0,0 +1,82 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.pokegoapi.api.pokemon; + +import POGOProtos.Data.PokemonDataOuterClass.PokemonData; +import com.pokegoapi.api.PokemonGo; +import lombok.Setter; + +/** + * The egg pokemon. + */ +public class EggPokemon { + + private static final String TAG = EggPokemon.class.getSimpleName(); + @Setter + PokemonGo pgo; + private PokemonData proto; + + // API METHODS // + + // DELEGATE METHODS BELOW // + public EggPokemon(PokemonData proto) { + this.proto = proto; + } + + public long getId() { + return proto.getId(); + } + + public boolean getIsEgg() { + return proto.getIsEgg(); + } + + public double getEggKmWalkedTarget() { + return proto.getEggKmWalkedTarget(); + } + + public double getEggKmWalkedStart() { + return proto.getEggKmWalkedStart(); + } + + public long getCapturedCellId() { + return proto.getCapturedCellId(); + } + + public long getCreationTimeMs() { + return proto.getCreationTimeMs(); + } + + public String getEggIncubatorId() { + return proto.getEggIncubatorId(); + } + + @Override + public int hashCode() { + return proto.getPokemonId().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EggPokemon) { + EggPokemon other = (EggPokemon) obj; + return (this.getId() == other.getId()); + } + + return false; + } + // TODO: add wrapper objects for encubators and allow to be got. +}