From e8ed0449c640f7fc9baa1b3d1d517567b4abecad Mon Sep 17 00:00:00 2001 From: Max K Date: Sun, 24 Jul 2016 18:10:27 +0200 Subject: [PATCH 1/6] Add info about native google sign in --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d25a2b20..7d08f632 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ You're running the sample code on the UI thread. Strict mode policy will throw a This library is meant to be a Java implementation of the API. Google Volley is specific to Android and should not be introduced in this library. However, if you still want to refactor it, you should create it as a separate project. + - How can I use Android's native Google sign in with this libary? + +You can't. The Google Indentity Platform uses the SHA1 fingerprint and package name to authenticate the caller of all sign in requests. This means that Niantic would need to add your app's SHA1 fingerprint and package name to their Google API Console. If you ever requested a Google Maps API key, you went through the same process. An alternative would be using a WebView to access the web based OAuth flow. This will work with the client ID and secret provided by this library. + ## Contributing - Fork it! From 7bbe0ba8c4cf71655e06db13f71202a35ac1824d Mon Sep 17 00:00:00 2001 From: Jasper Abbink Date: Sun, 24 Jul 2016 23:36:25 +0200 Subject: [PATCH 2/6] fix force updating inventories --- src/main/java/com/pokegoapi/api/inventory/Hatchery.java | 1 + src/main/java/com/pokegoapi/api/inventory/PokeBank.java | 1 + src/main/java/com/pokegoapi/api/inventory/Pokedex.java | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java index f44c60fc..710f50ea 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Hatchery.java +++ b/src/main/java/com/pokegoapi/api/inventory/Hatchery.java @@ -45,6 +45,7 @@ public Hatchery(PokemonGo pgo) { public void reset(PokemonGo pgo) { this.instance = pgo; + eggs = new HashSet<>(); } public void addEgg(EggPokemon egg) { diff --git a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java index 423f1ea1..e4e736c6 100644 --- a/src/main/java/com/pokegoapi/api/inventory/PokeBank.java +++ b/src/main/java/com/pokegoapi/api/inventory/PokeBank.java @@ -39,6 +39,7 @@ public PokeBank(PokemonGo pgo) { public void reset(PokemonGo pgo) { this.instance = pgo; + pokemons = new ArrayList<>(); } /** diff --git a/src/main/java/com/pokegoapi/api/inventory/Pokedex.java b/src/main/java/com/pokegoapi/api/inventory/Pokedex.java index ca9c8320..bcf23b3a 100644 --- a/src/main/java/com/pokegoapi/api/inventory/Pokedex.java +++ b/src/main/java/com/pokegoapi/api/inventory/Pokedex.java @@ -25,7 +25,7 @@ public class Pokedex { private PokemonGo api; - private Map pokedexMap = new HashMap(); + private Map pokedexMap = new HashMap<>(); public Pokedex(PokemonGo pgo) { reset(pgo); @@ -33,6 +33,7 @@ public Pokedex(PokemonGo pgo) { public void reset(PokemonGo pgo) { this.api = pgo; + pokedexMap = new HashMap<>(); } /** From d5dc532187fd92978e1268d7805fdc9a7a223aa8 Mon Sep 17 00:00:00 2001 From: Andres Rodriguez Date: Sun, 24 Jul 2016 14:06:43 -0400 Subject: [PATCH 3/6] REAME.md: fix Usefull->Useful typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d08f632..45e4d930 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ You can't. The Google Indentity Platform uses the SHA1 fingerprint and package n ## Contributing - Fork it! - Create your feature branch: `git checkout -b my-new-feature` - - Commit your changes: `git commit -am 'Usefull information about your new features'` + - Commit your changes: `git commit -am 'Useful information about your new features'` - Push to the branch: `git push origin my-new-feature` - Submit a pull request on the `Development` branch :D From 1668ee4a09b3b7d654f1405895fc543f494d0371 Mon Sep 17 00:00:00 2001 From: Andres Rodriguez Date: Sun, 24 Jul 2016 15:31:55 -0400 Subject: [PATCH 4/6] README.md: fix PtcLogin classname type --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 45e4d930..5d56df04 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Include the API as jar from your own build, or use Maven/Gradle/SBT/Leiningen: h Mostly everything is accessed through the PokemonGo class in the API package. -The constructor of PokemonGo class requires a AuthInfo object which can be obtained from GoogleLogin().login or PTCLogin().login, and a OkHttpClient object. +The constructor of PokemonGo class requires a AuthInfo object which can be obtained from GoogleLogin().login or PtcLogin().login, and a OkHttpClient object. EG: ```java From f36a082dbc3b7b725baad3614c356416e4f385df Mon Sep 17 00:00:00 2001 From: Grover-c13 Date: Mon, 25 Jul 2016 16:51:46 +0800 Subject: [PATCH 5/6] Start Gym + Battle API --- .../java/com/pokegoapi/api/gym/Battle.java | 186 ++++++++++++++++++ src/main/java/com/pokegoapi/api/gym/Gym.java | 159 +++++++++++++++ src/main/java/com/pokegoapi/api/map/Map.java | 16 ++ 3 files changed, 361 insertions(+) create mode 100644 src/main/java/com/pokegoapi/api/gym/Battle.java create mode 100644 src/main/java/com/pokegoapi/api/gym/Gym.java diff --git a/src/main/java/com/pokegoapi/api/gym/Battle.java b/src/main/java/com/pokegoapi/api/gym/Battle.java new file mode 100644 index 00000000..b621b374 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/gym/Battle.java @@ -0,0 +1,186 @@ +/* + * 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.gym; + +import POGOProtos.Data.Battle.BattleActionOuterClass.BattleAction; +import POGOProtos.Data.Battle.BattleActionTypeOuterClass; +import POGOProtos.Data.Battle.BattleParticipantOuterClass.BattleParticipant; +import POGOProtos.Data.Battle.BattlePokemonInfoOuterClass.BattlePokemonInfo; +import POGOProtos.Data.PokemonDataOuterClass; +import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder; +import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Responses.AttackGymResponseOuterClass.AttackGymResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; +import com.google.protobuf.InvalidProtocolBufferException; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; + +import java.util.ArrayList; +import java.util.List; + +public class Battle { + private Gym gym; + private Pokemon[] team; + private List bteam; + private StartGymBattleResponse battleResponse; + private PokemonGo api; + private int active_index; + private Pokemon active; + private int defeated; + + public Battle(PokemonGo api, Pokemon[] team, Gym gym) { + this.team = team; + this.gym = gym; + this.api = api; + this.active = team[0]; + this.defeated = 0; + this.active_index = 0; + + this.bteam = new ArrayList(); + for (int i = 0; i < team.length; i++) { + bteam.add(this.createBattlePokemon(team[i])); + } + + } + + public Result start() throws LoginFailedException, RemoteServerException { + + Builder builder = StartGymBattleMessageOuterClass.StartGymBattleMessage.newBuilder(); + + for (int i = 0; i < team.length; i++) { + builder.addAttackingPokemonIds(team[i].getId()); + } + + + List defenders = gym.getDefendingPokemon(); + builder.setGymId(gym.getId()); + builder.setPlayerLongitude(api.getLongitude()); + builder.setPlayerLatitude(api.getLatitude()); + builder.setDefendingPokemonId(defenders.get(0).getId()); // may need to be sorted + + ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.START_GYM_BATTLE, builder.build()); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + battleResponse = StartGymBattleResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + return battleResponse.getResult(); + } + + + public AttackGymResponse.Result join() throws LoginFailedException, RemoteServerException { + BattleParticipant participant = BattleParticipant + .newBuilder() + .setActivePokemon(bteam.get(0)) + .addAllReversePokemon(bteam) + .build(); + + BattleAction action = BattleAction + .newBuilder() + .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_PLAYER_JOIN) + .setActionStartMs(System.currentTimeMillis()) + .setAttackerIndex(0) + .setActivePokemonId(active.getId()) + .setPlayerJoined(participant) + .build(); + + AttackGymResponse response = doAction(action); + System.out.println(response); + return response.getResult(); + + } + + public void attack() throws LoginFailedException, RemoteServerException { + // TODO: need meta information about attack durations, can be extracted from game master dump + BattleAction action = BattleAction + .newBuilder() + .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_ATTACK) + .setActionStartMs(System.currentTimeMillis()) + .setDurationMs(3) + .setEnergyDelta(0) + .setAttackerIndex(active_index) + .setTargetIndex(defeated) + .setActivePokemonId(active.getId()) + .setTargetPokemonId(getDefender(defeated).getId()) + .setDamageWindowsStartTimestampMss(System.currentTimeMillis()+1000) + .setDamageWindowsEndTimestampMss(System.currentTimeMillis()+2000) + .build(); + doAction(action); + } + + public void dodge() { + + } + + public void swap(Pokemon pokemon) { + + } + + private BattlePokemonInfo createBattlePokemon(Pokemon pokemon) { + BattlePokemonInfo info = BattlePokemonInfo + .newBuilder() + .setCurrentEnergy(0) + .setCurrentHealth(100) + .setPokemonData(pokemon.getDefaultInstanceForType()) + .build(); + return info; + } + + private PokemonDataOuterClass.PokemonData getDefender(int index) throws LoginFailedException, RemoteServerException { + return gym.getGymMembers().get(0).getPokemonData(); + } + + private BattleAction getLastActionFromServer() { + BattleAction action; + int actionCount = battleResponse.getBattleLog().getBattleActionsCount(); + action = battleResponse.getBattleLog().getBattleActions(actionCount-1); + return action; + } + + private AttackGymResponse doAction(BattleAction action) throws LoginFailedException, RemoteServerException { + AttackGymMessageOuterClass.AttackGymMessage message = AttackGymMessageOuterClass.AttackGymMessage + .newBuilder() + .addAttackActions(action) + .setGymId(gym.getId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .setLastRetrievedActions(action) + .setBattleId(battleResponse.getBattleId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ATTACK_GYM, message); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + return AttackGymResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + } + +} diff --git a/src/main/java/com/pokegoapi/api/gym/Gym.java b/src/main/java/com/pokegoapi/api/gym/Gym.java new file mode 100644 index 00000000..dfa0e772 --- /dev/null +++ b/src/main/java/com/pokegoapi/api/gym/Gym.java @@ -0,0 +1,159 @@ +/* + * 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.gym; + +import POGOProtos.Data.Gym.GymMembershipOuterClass.GymMembership; +import POGOProtos.Data.PokemonDataOuterClass.PokemonData; +import POGOProtos.Enums.PokemonIdOuterClass; +import POGOProtos.Enums.TeamColorOuterClass; +import POGOProtos.Map.Fort.FortDataOuterClass.FortData; +import POGOProtos.Networking.Requests.Messages.GetGymDetailsMessageOuterClass.GetGymDetailsMessage; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage; +import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; +import POGOProtos.Networking.Responses.GetGymDetailsResponseOuterClass.GetGymDetailsResponse; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.ProtocolStringList; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.main.ServerRequest; + +import java.util.ArrayList; +import java.util.List; + +public class Gym { + private FortData proto; + private GetGymDetailsResponse details; + private PokemonGo api; + + /** + * . + * + * @return + */ + public Gym(PokemonGo api, FortData proto) { + this.api = api; + this.proto = proto; + this.details = null; + } + + public String getId() { + return proto.getId(); + } + + public double getLatitude() { + return proto.getLatitude(); + } + + public double getLongitude() { + return proto.getLongitude(); + } + + public boolean getEnabled() { + return proto.getEnabled(); + } + + public TeamColorOuterClass.TeamColor getOwnedByTeam() { + return proto.getOwnedByTeam(); + } + + public PokemonIdOuterClass.PokemonId getGuardPokemonId() { + return proto.getGuardPokemonId(); + } + + public int getGuardPokemonCp() { + return proto.getGuardPokemonCp(); + } + + public boolean getIsInBattle() { + return proto.getIsInBattle(); + } + + + + private GetGymDetailsResponse details() throws LoginFailedException, RemoteServerException { + if (details == null) { + GetGymDetailsMessage reqMsg = GetGymDetailsMessage + .newBuilder() + .setGymId(this.getId()) + .setGymLatitude(this.getLatitude()) + .setGymLongitude(this.getLongitude()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .build(); + + + ServerRequest serverRequest = new ServerRequest(RequestType.GET_GYM_DETAILS, reqMsg); + api.getRequestHandler().sendServerRequests(serverRequest); + + try { + details = GetGymDetailsResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + + } + + return details; + } + + public String getName() throws LoginFailedException, RemoteServerException { + return details().getName(); + } + + public ProtocolStringList getUrlsList() throws LoginFailedException, RemoteServerException { + return details().getUrlsList(); + } + + public GetGymDetailsResponse.Result getResult() throws LoginFailedException, RemoteServerException { + return details().getResult(); + } + + public boolean inRange() throws LoginFailedException, RemoteServerException { + GetGymDetailsResponse.Result result = getResult(); + System.out.println(result + " != " + GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); + System.out.println(result != GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); + return ( result != GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); + } + + public String getDescription() throws LoginFailedException, RemoteServerException { + return details().getDescription(); + } + + + public List getGymMembers() throws LoginFailedException, RemoteServerException { + return details().getGymState().getMembershipsList(); + } + + public List getDefendingPokemon() throws LoginFailedException, RemoteServerException { + List data = new ArrayList(); + + for (GymMembership gymMember : getGymMembers()) { + data.add(gymMember.getPokemonData()); + } + + return data; + } + + protected PokemonGo getApi() { + return api; + } + + +} diff --git a/src/main/java/com/pokegoapi/api/map/Map.java b/src/main/java/com/pokegoapi/api/map/Map.java index 6145a287..03200872 100644 --- a/src/main/java/com/pokegoapi/api/map/Map.java +++ b/src/main/java/com/pokegoapi/api/map/Map.java @@ -39,9 +39,11 @@ import com.annimon.stream.Collectors; import com.annimon.stream.Stream; import com.annimon.stream.function.Function; +import com.annimon.stream.function.Predicate; import com.google.protobuf.InvalidProtocolBufferException; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.map.fort.FortDetails; +import com.pokegoapi.api.gym.Gym; import com.pokegoapi.api.map.pokemon.CatchablePokemon; import com.pokegoapi.api.map.pokemon.NearbyPokemon; import com.pokegoapi.exceptions.LoginFailedException; @@ -150,6 +152,20 @@ public List getSpawnPoints() throws LoginFailedException, RemoteServerExc return points; } + + public List getGyms() throws LoginFailedException, RemoteServerException { + List gyms = new ArrayList<>(); + MapObjects objects = getMapObjects(); + + for (FortData fortdata : objects.getGyms()) { + gyms.add(new Gym(api, fortdata)); + } + + return gyms; + } + + + /** * Returns a list of decimated spawn points at current location. * From 432bd93bf7415a8ee37fb3b7cedce355ceb77988 Mon Sep 17 00:00:00 2001 From: Grover-c13 Date: Tue, 26 Jul 2016 18:30:47 +0800 Subject: [PATCH 6/6] Battle API - Example included, utility functions to get state of battle. Can only spam attack right now. --- .../java/com/pokegoapi/api/gym/Battle.java | 185 ++++++++++++------ src/main/java/com/pokegoapi/api/gym/Gym.java | 17 +- src/main/java/com/pokegoapi/api/map/Map.java | 6 +- .../pokegoapi/examples/FightGymExample.java | 102 ++++++++++ 4 files changed, 248 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/pokegoapi/examples/FightGymExample.java diff --git a/src/main/java/com/pokegoapi/api/gym/Battle.java b/src/main/java/com/pokegoapi/api/gym/Battle.java index b621b374..18b1a200 100644 --- a/src/main/java/com/pokegoapi/api/gym/Battle.java +++ b/src/main/java/com/pokegoapi/api/gym/Battle.java @@ -17,13 +17,17 @@ import POGOProtos.Data.Battle.BattleActionOuterClass.BattleAction; import POGOProtos.Data.Battle.BattleActionTypeOuterClass; -import POGOProtos.Data.Battle.BattleParticipantOuterClass.BattleParticipant; import POGOProtos.Data.Battle.BattlePokemonInfoOuterClass.BattlePokemonInfo; +import POGOProtos.Data.Battle.BattleStateOuterClass; +import POGOProtos.Data.Battle.BattleStateOuterClass.BattleState; import POGOProtos.Data.PokemonDataOuterClass; import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass; +import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass.AttackGymMessage; import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass; import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder; import POGOProtos.Networking.Requests.RequestTypeOuterClass; +import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType; +import POGOProtos.Networking.Responses.AttackGymResponseOuterClass; import POGOProtos.Networking.Responses.AttackGymResponseOuterClass.AttackGymResponse; import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse; import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; @@ -33,6 +37,7 @@ 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; @@ -43,25 +48,34 @@ public class Battle { private List bteam; private StartGymBattleResponse battleResponse; private PokemonGo api; - private int active_index; - private Pokemon active; - private int defeated; - + private List gymIndex; + @Getter + private boolean concluded; + @Getter + private BattleState outcome; + + /** + * New battle to track the state of a battle. + * + */ public Battle(PokemonGo api, Pokemon[] team, Gym gym) { this.team = team; this.gym = gym; this.api = api; - this.active = team[0]; - this.defeated = 0; - this.active_index = 0; this.bteam = new ArrayList(); + this.gymIndex = new ArrayList<>(); + for (int i = 0; i < team.length; i++) { bteam.add(this.createBattlePokemon(team[i])); } - } + /** + * Start a battle. + * + * @return Result of the attempt to start + */ public Result start() throws LoginFailedException, RemoteServerException { Builder builder = StartGymBattleMessageOuterClass.StartGymBattleMessage.newBuilder(); @@ -77,7 +91,7 @@ public Result start() throws LoginFailedException, RemoteServerException { builder.setPlayerLatitude(api.getLatitude()); builder.setDefendingPokemonId(defenders.get(0).getId()); // may need to be sorted - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.START_GYM_BATTLE, builder.build()); + ServerRequest serverRequest = new ServerRequest(RequestType.START_GYM_BATTLE, builder.build()); api.getRequestHandler().sendServerRequests(serverRequest); @@ -87,58 +101,55 @@ public Result start() throws LoginFailedException, RemoteServerException { throw new RemoteServerException(); } + // need to send blank action + this.sendBlankAction(); + + + for (BattleAction action : battleResponse.getBattleLog().getBattleActionsList()) { + gymIndex.add(action.getTargetIndex()); + } + return battleResponse.getResult(); } - public AttackGymResponse.Result join() throws LoginFailedException, RemoteServerException { - BattleParticipant participant = BattleParticipant - .newBuilder() - .setActivePokemon(bteam.get(0)) - .addAllReversePokemon(bteam) - .build(); - BattleAction action = BattleAction - .newBuilder() - .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_PLAYER_JOIN) - .setActionStartMs(System.currentTimeMillis()) - .setAttackerIndex(0) - .setActivePokemonId(active.getId()) - .setPlayerJoined(participant) - .build(); - AttackGymResponse response = doAction(action); - System.out.println(response); - return response.getResult(); + /** + * Attack a gym. + * + * @param times the amount of times to attack + * @return Battle + */ + public AttackGymResponse attack(int times) throws LoginFailedException, RemoteServerException { - } + ArrayList actions = new ArrayList(); - public void attack() throws LoginFailedException, RemoteServerException { - // TODO: need meta information about attack durations, can be extracted from game master dump - BattleAction action = BattleAction - .newBuilder() - .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_ATTACK) - .setActionStartMs(System.currentTimeMillis()) - .setDurationMs(3) - .setEnergyDelta(0) - .setAttackerIndex(active_index) - .setTargetIndex(defeated) - .setActivePokemonId(active.getId()) - .setTargetPokemonId(getDefender(defeated).getId()) - .setDamageWindowsStartTimestampMss(System.currentTimeMillis()+1000) - .setDamageWindowsEndTimestampMss(System.currentTimeMillis()+2000) - .build(); - doAction(action); - } + for (int i = 0; i < times; i++) { + BattleAction action = BattleAction + .newBuilder() + .setType(BattleActionTypeOuterClass.BattleActionType.ACTION_ATTACK) + .setActionStartMs(System.currentTimeMillis() + (100 * times)) + .setDurationMs(500) + .setTargetIndex(-1) + .build(); + actions.add(action); + } - public void dodge() { + AttackGymResponse result = doActions(actions); - } - public void swap(Pokemon pokemon) { + return result; } + + /** + * Creates a battle pokemon object to send with the request. + * + * @Param Pokemon + * @return BattlePokemonInfo + */ private BattlePokemonInfo createBattlePokemon(Pokemon pokemon) { BattlePokemonInfo info = BattlePokemonInfo .newBuilder() @@ -149,34 +160,94 @@ private BattlePokemonInfo createBattlePokemon(Pokemon pokemon) { return info; } + /** + * Get the Pokemondata for the defenders. + * + * @param index of defender(0 to gym lever) + * @return Battle + */ private PokemonDataOuterClass.PokemonData getDefender(int index) throws LoginFailedException, RemoteServerException { return gym.getGymMembers().get(0).getPokemonData(); } + /** + * Get the last action from server. + * + * @return BattleAction + */ private BattleAction getLastActionFromServer() { BattleAction action; int actionCount = battleResponse.getBattleLog().getBattleActionsCount(); - action = battleResponse.getBattleLog().getBattleActions(actionCount-1); + action = battleResponse.getBattleLog().getBattleActions(actionCount - 1); return action; } - private AttackGymResponse doAction(BattleAction action) throws LoginFailedException, RemoteServerException { - AttackGymMessageOuterClass.AttackGymMessage message = AttackGymMessageOuterClass.AttackGymMessage + /** + * Send blank action, used for polling the state of the battle. (i think). + * + * @return AttackGymResponse + */ + private AttackGymResponse sendBlankAction() throws LoginFailedException, RemoteServerException { + AttackGymMessage message = AttackGymMessage + .newBuilder() + .setGymId(gym.getId()) + .setPlayerLatitude(api.getLatitude()) + .setPlayerLongitude(api.getLongitude()) + .setBattleId(battleResponse.getBattleId()) + .build(); + + ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message); + api.getRequestHandler().sendServerRequests(serverRequest); + + + try { + return AttackGymResponse.parseFrom(serverRequest.getData()); + } catch (InvalidProtocolBufferException e) { + throw new RemoteServerException(); + } + } + + + /** + * Do Actions in battle. + * + * @param actions list of actions to send in this request + * @return AttackGymResponse + */ + private AttackGymResponse doActions(List actions) throws LoginFailedException, RemoteServerException { + + + AttackGymMessage.Builder message = AttackGymMessage .newBuilder() - .addAttackActions(action) .setGymId(gym.getId()) .setPlayerLatitude(api.getLatitude()) .setPlayerLongitude(api.getLongitude()) - .setLastRetrievedActions(action) - .setBattleId(battleResponse.getBattleId()) - .build(); + .setBattleId(battleResponse.getBattleId()); + + for (BattleAction action : actions) { + message.addAttackActions(action); + } + + - ServerRequest serverRequest = new ServerRequest(RequestTypeOuterClass.RequestType.ATTACK_GYM, message); + ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message.build()); api.getRequestHandler().sendServerRequests(serverRequest); try { - return AttackGymResponse.parseFrom(serverRequest.getData()); + AttackGymResponse response = AttackGymResponse.parseFrom(serverRequest.getData()); + + if (response.getBattleLog().getState() == BattleState.DEFEATED + || response.getBattleLog().getState() == BattleState.VICTORY + || response.getBattleLog().getState() == BattleState.TIMED_OUT) { + concluded = true; + } + + outcome = response.getBattleLog().getState(); + + + + return response; } catch (InvalidProtocolBufferException e) { throw new RemoteServerException(); } diff --git a/src/main/java/com/pokegoapi/api/gym/Gym.java b/src/main/java/com/pokegoapi/api/gym/Gym.java index dfa0e772..9ece4120 100644 --- a/src/main/java/com/pokegoapi/api/gym/Gym.java +++ b/src/main/java/com/pokegoapi/api/gym/Gym.java @@ -43,9 +43,8 @@ public class Gym { private PokemonGo api; /** - * . + * Gym object. * - * @return */ public Gym(PokemonGo api, FortData proto) { this.api = api; @@ -85,6 +84,13 @@ public boolean getIsInBattle() { return proto.getIsInBattle(); } + public boolean isAttackable() throws LoginFailedException, RemoteServerException { + return this.getGymMembers().size() != 0; + } + + public Battle battle(Pokemon[] team) { + return new Battle(api, team, this); + } private GetGymDetailsResponse details() throws LoginFailedException, RemoteServerException { @@ -127,8 +133,6 @@ public GetGymDetailsResponse.Result getResult() throws LoginFailedException, Rem public boolean inRange() throws LoginFailedException, RemoteServerException { GetGymDetailsResponse.Result result = getResult(); - System.out.println(result + " != " + GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); - System.out.println(result != GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); return ( result != GetGymDetailsResponse.Result.ERROR_NOT_IN_RANGE); } @@ -141,6 +145,11 @@ public List getGymMembers() throws LoginFailedException, RemoteSe return details().getGymState().getMembershipsList(); } + /** + * Get a list of pokemon defending this gym. + * + * @return List of pokemon + */ public List getDefendingPokemon() throws LoginFailedException, RemoteServerException { List data = new ArrayList(); diff --git a/src/main/java/com/pokegoapi/api/map/Map.java b/src/main/java/com/pokegoapi/api/map/Map.java index 03200872..b1cf1109 100644 --- a/src/main/java/com/pokegoapi/api/map/Map.java +++ b/src/main/java/com/pokegoapi/api/map/Map.java @@ -152,7 +152,11 @@ public List getSpawnPoints() throws LoginFailedException, RemoteServerExc return points; } - + /** + * Get a list of gyms near the current location. + * + * @return List of gyms + */ public List getGyms() throws LoginFailedException, RemoteServerException { List gyms = new ArrayList<>(); MapObjects objects = getMapObjects(); diff --git a/src/main/java/com/pokegoapi/examples/FightGymExample.java b/src/main/java/com/pokegoapi/examples/FightGymExample.java new file mode 100644 index 00000000..f1abae3b --- /dev/null +++ b/src/main/java/com/pokegoapi/examples/FightGymExample.java @@ -0,0 +1,102 @@ +/* + * 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 . + */ + +/* + * 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.examples; + + +import POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass; +import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result; +import com.pokegoapi.api.PokemonGo; +import com.pokegoapi.api.gym.Battle; +import com.pokegoapi.api.gym.Gym; +import com.pokegoapi.api.pokemon.Pokemon; +import com.pokegoapi.auth.PtcLogin; +import com.pokegoapi.exceptions.LoginFailedException; +import com.pokegoapi.exceptions.RemoteServerException; +import com.pokegoapi.util.Log; +import okhttp3.OkHttpClient; + +import java.util.List; + +public class FightGymExample { + + /** + * Catches a pokemon at an area. + */ + public static void main(String[] args) { + OkHttpClient http = new OkHttpClient(); + RequestEnvelopeOuterClass.RequestEnvelope.AuthInfo auth = null; + try { + auth = new PtcLogin(http).login(ExampleLoginDetails.LOGIN, ExampleLoginDetails.PASSWORD); + // or google + //auth = new GoogleLogin(http).login("", ""); // currently uses oauth flow so no user or pass needed + PokemonGo go = new PokemonGo(auth, http); + // set location + go.setLocation(-32.011011, 115.932831, 0); + + List pokemons = go.getInventories().getPokebank().getPokemons(); + Pokemon[] attackers = new Pokemon[6]; + + for (int i = 0; i < 6; i++) { + attackers[i] = pokemons.get(i); + } + + + for (Gym gym : go.getMap().getGyms()) { + if (gym.isAttackable()) { + Battle battle = gym.battle(attackers); + // start the battle + Result result = battle.start(); + + if (result == Result.SUCCESS) { + // started battle successfully + + // loop while battle is not finished + while (!battle.isConcluded()) { + System.out.println("attack:" + battle.attack(5)); + Thread.sleep(500); + } + + System.out.println("Battle result:" + battle.getOutcome()); + + } else { + System.out.println("FAILED:" + result); + } + } + + } + + } catch (LoginFailedException | RemoteServerException | InterruptedException e) { + // failed to login, invalid credentials, auth issue or server issue. + Log.e("Main", "Failed to login or server issue: ", e); + + } + } +}