Skip to content

Commit bf0a997

Browse files
authored
luresfixesandgoodtimes (#418)
* Added lured pokemon to getCatchablePokemon removed DummyFuture Fixed NPE in FutureWrapper when using .just Fixed issue when caught pokemon will still appearing in catchable pokemon Added a little more detail to the PTC login exception Changed exception message from "Error in url" to "Invalid auth status code recieved" * Checkstyle * Travis fix
1 parent 0c5e008 commit bf0a997

File tree

13 files changed

+254
-158
lines changed

13 files changed

+254
-158
lines changed

src/main/java/com/pokegoapi/api/gym/Gym.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import java.util.ArrayList;
3636
import java.util.List;
3737

38-
public class Gym implements MapPoint{
38+
public class Gym implements MapPoint {
3939
private FortData proto;
4040
private GetGymDetailsResponse details;
4141
private PokemonGo api;

src/main/java/com/pokegoapi/api/map/Map.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import POGOProtos.Map.Fort.FortDataOuterClass.FortData;
2020
import POGOProtos.Map.Fort.FortTypeOuterClass.FortType;
2121
import POGOProtos.Map.MapCellOuterClass.MapCell;
22+
import POGOProtos.Map.Pokemon.MapPokemonOuterClass;
2223
import POGOProtos.Map.Pokemon.MapPokemonOuterClass.MapPokemon;
2324
import POGOProtos.Map.Pokemon.NearbyPokemonOuterClass;
2425
import POGOProtos.Map.Pokemon.WildPokemonOuterClass;
@@ -38,11 +39,13 @@
3839
import com.annimon.stream.Collectors;
3940
import com.annimon.stream.Stream;
4041
import com.annimon.stream.function.Function;
42+
import com.annimon.stream.function.Predicate;
4143
import com.google.protobuf.ByteString;
4244
import com.google.protobuf.InvalidProtocolBufferException;
4345
import com.pokegoapi.api.PokemonGo;
4446
import com.pokegoapi.api.gym.Gym;
4547
import com.pokegoapi.api.map.fort.FortDetails;
48+
import com.pokegoapi.api.map.fort.Pokestop;
4649
import com.pokegoapi.api.map.pokemon.CatchablePokemon;
4750
import com.pokegoapi.api.map.pokemon.NearbyPokemon;
4851
import com.pokegoapi.exceptions.LoginFailedException;
@@ -52,7 +55,6 @@
5255
import com.pokegoapi.google.common.geometry.S2LatLng;
5356
import com.pokegoapi.main.AsyncServerRequest;
5457
import com.pokegoapi.main.ServerRequest;
55-
import com.pokegoapi.util.DummyFuture;
5658
import com.pokegoapi.util.FutureWrapper;
5759
import com.pokegoapi.util.MapUtil;
5860
import com.pokegoapi.util.PokemonFuture;
@@ -69,6 +71,7 @@ public class Map {
6971
private static int RESEND_REQUEST = 5000;
7072
private final PokemonGo api;
7173
private MapObjects cachedMapObjects;
74+
private List<CatchablePokemon> cachedCatchable;
7275
private long lastMapUpdate;
7376

7477
/**
@@ -91,6 +94,11 @@ public Map(PokemonGo api) throws LoginFailedException, RemoteServerException {
9194
* @return a List of CatchablePokemon at your current location
9295
*/
9396
public PokemonFuture<List<CatchablePokemon>> getCatchablePokemonAsync() {
97+
98+
if (useCache() && cachedCatchable != null) {
99+
return FutureWrapper.just(cachedCatchable);
100+
}
101+
94102
List<Long> cellIds = getDefaultCells();
95103
return new FutureWrapper<MapObjects, List<CatchablePokemon>>(getMapObjectsAsync(cellIds)) {
96104
@Override
@@ -103,13 +111,22 @@ protected List<CatchablePokemon> handle(MapObjects mapObjects) throws RemoteServ
103111
for (WildPokemonOuterClass.WildPokemon wildPokemon : mapObjects.getWildPokemons()) {
104112
catchablePokemons.add(new CatchablePokemon(api, wildPokemon));
105113
}
106-
// TODO: Check if this code is correct; merged because this contains many other fixes
107-
/*for (Pokestop pokestop : objects.getPokestops()) {
108-
if (pokestop.inRange() && pokestop.hasLurePokemon()) {
114+
115+
/*
116+
TODO: i have more success checking if encounterId > 0
117+
i don't want to use the hasLure because it do a request every call
118+
*/
119+
for (Pokestop pokestop : mapObjects.getPokestops()) {
120+
if (pokestop.inRange()
121+
&& pokestop.getFortData().hasLureInfo()
122+
&& pokestop.getFortData().getLureInfo().getEncounterId() > 0) {
123+
//if (pokestop.inRange() && pokestop.hasLurePokemon()) {
109124
catchablePokemons.add(new CatchablePokemon(api, pokestop.getFortData()));
110125
}
111-
}*/
112-
return new ArrayList<>(catchablePokemons);
126+
}
127+
128+
cachedCatchable = new ArrayList<>(catchablePokemons);
129+
return cachedCatchable;
113130
}
114131
};
115132
}
@@ -310,8 +327,8 @@ public PokemonFuture<MapObjects> getMapObjectsAsync(int width) {
310327
*/
311328
public PokemonFuture<MapObjects> getMapObjectsAsync(List<Long> cellIds) {
312329

313-
if ((api.currentTimeMillis() - lastMapUpdate) < RESEND_REQUEST) {
314-
return new DummyFuture<MapObjects>(cachedMapObjects);
330+
if (useCache()) {
331+
return FutureWrapper.just(cachedMapObjects);
315332
}
316333

317334
lastMapUpdate = api.currentTimeMillis();
@@ -649,6 +666,14 @@ public CatchPokemonResponse catchPokemon(
649666
return response;
650667
}
651668

669+
/**
670+
* Wether or not to get a fresh copy or use cache;
671+
*
672+
* @return true if enough time has elapsed since the last request, false otherwise
673+
*/
674+
private boolean useCache() {
675+
return (api.currentTimeMillis() - lastMapUpdate) < RESEND_REQUEST;
676+
}
652677

653678
private List<Long> getDefaultCells() {
654679
return getCellIds(api.getLatitude(), api.getLongitude(), CELL_WIDTH);

src/main/java/com/pokegoapi/api/map/Point.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import lombok.Getter;
2121
import lombok.Setter;
2222

23-
public class Point implements MapPoint{
23+
public class Point implements MapPoint {
2424
@Getter
2525
@Setter
2626
private double longitude;

src/main/java/com/pokegoapi/api/map/pokemon/CatchablePokemon.java

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,31 @@
1515

1616
package com.pokegoapi.api.map.pokemon;
1717

18-
import POGOProtos.Enums.PokemonIdOuterClass;
18+
19+
import POGOProtos.Enums.PokemonIdOuterClass.PokemonId;
1920
import POGOProtos.Inventory.Item.ItemIdOuterClass.ItemId;
2021
import POGOProtos.Map.Fort.FortDataOuterClass.FortData;
2122
import POGOProtos.Map.Pokemon.MapPokemonOuterClass.MapPokemon;
2223
import POGOProtos.Map.Pokemon.WildPokemonOuterClass.WildPokemon;
2324
import POGOProtos.Networking.Requests.Messages.CatchPokemonMessageOuterClass.CatchPokemonMessage;
24-
import POGOProtos.Networking.Requests.Messages.EncounterMessageOuterClass;
25+
import POGOProtos.Networking.Requests.Messages.DiskEncounterMessageOuterClass;
26+
import POGOProtos.Networking.Requests.Messages.DiskEncounterMessageOuterClass.DiskEncounterMessage;
27+
import POGOProtos.Networking.Requests.Messages.EncounterMessageOuterClass.EncounterMessage;
2528
import POGOProtos.Networking.Requests.Messages.UseItemCaptureMessageOuterClass.UseItemCaptureMessage;
26-
import POGOProtos.Networking.Requests.RequestTypeOuterClass;
29+
import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType;
2730
import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse;
2831
import POGOProtos.Networking.Responses.CatchPokemonResponseOuterClass.CatchPokemonResponse.CatchStatus;
29-
import POGOProtos.Networking.Responses.EncounterResponseOuterClass;
32+
import POGOProtos.Networking.Responses.DiskEncounterResponseOuterClass.DiskEncounterResponse;
3033
import POGOProtos.Networking.Responses.EncounterResponseOuterClass.EncounterResponse;
3134
import POGOProtos.Networking.Responses.UseItemCaptureResponseOuterClass.UseItemCaptureResponse;
3235
import com.google.protobuf.ByteString;
3336
import com.google.protobuf.InvalidProtocolBufferException;
3437
import com.pokegoapi.api.PokemonGo;
3538
import com.pokegoapi.api.inventory.ItemBag;
3639
import com.pokegoapi.api.inventory.Pokeball;
40+
import com.pokegoapi.api.map.pokemon.encounter.DiskEncounterResult;
41+
import com.pokegoapi.api.map.pokemon.encounter.EncounterResult;
42+
import com.pokegoapi.api.map.pokemon.encounter.NormalEncounterResult;
3743
import com.pokegoapi.exceptions.LoginFailedException;
3844
import com.pokegoapi.exceptions.NoSuchItemException;
3945
import com.pokegoapi.exceptions.RemoteServerException;
@@ -48,11 +54,19 @@
4854

4955
import java.util.concurrent.Future;
5056

57+
5158
/**
5259
* The type Catchable pokemon.
5360
*/
5461
@ToString
55-
public class CatchablePokemon implements MapPoint{
62+
public class CatchablePokemon implements MapPoint {
63+
64+
private enum EncounterKind {
65+
NORMAL,
66+
DISK;
67+
}
68+
69+
5670
private static final String TAG = CatchablePokemon.class.getSimpleName();
5771
private final PokemonGo api;
5872

@@ -61,16 +75,19 @@ public class CatchablePokemon implements MapPoint{
6175
@Getter
6276
private final long encounterId;
6377
@Getter
64-
private final PokemonIdOuterClass.PokemonId pokemonId;
78+
private final PokemonId pokemonId;
6579
@Getter
6680
private final long expirationTimestampMs;
6781
@Getter
6882
private final double latitude;
6983
@Getter
7084
private final double longitude;
85+
private final EncounterKind encounterKind;
7186

7287
private Boolean encountered = null;
7388

89+
90+
7491
/**
7592
* Instantiates a new Catchable pokemon.
7693
*
@@ -79,7 +96,7 @@ public class CatchablePokemon implements MapPoint{
7996
*/
8097
public CatchablePokemon(PokemonGo api, MapPokemon proto) {
8198
this.api = api;
82-
99+
this.encounterKind = EncounterKind.NORMAL;
83100
this.spawnPointId = proto.getSpawnPointId();
84101
this.encounterId = proto.getEncounterId();
85102
this.pokemonId = proto.getPokemonId();
@@ -96,6 +113,7 @@ public CatchablePokemon(PokemonGo api, MapPokemon proto) {
96113
*/
97114
public CatchablePokemon(PokemonGo api, WildPokemon proto) {
98115
this.api = api;
116+
this.encounterKind = EncounterKind.NORMAL;
99117
this.spawnPointId = proto.getSpawnPointId();
100118
this.encounterId = proto.getEncounterId();
101119
this.pokemonId = proto.getPokemonData().getPokemonId();
@@ -116,13 +134,24 @@ public CatchablePokemon(PokemonGo api, FortData proto) {
116134
}
117135
this.api = api;
118136
// TODO: does this work?
119-
this.spawnPointId = null;
137+
// seems that spawnPoint it's fortId in catchAPI so it should be safe to just set it in that way
138+
this.spawnPointId = proto.getLureInfo().getFortId();
120139
this.encounterId = proto.getLureInfo().getEncounterId();
121140
this.pokemonId = proto.getLureInfo().getActivePokemonId();
122141
this.expirationTimestampMs = proto.getLureInfo()
123142
.getLureExpiresTimestampMs();
124143
this.latitude = proto.getLatitude();
125144
this.longitude = proto.getLongitude();
145+
this.encounterKind = EncounterKind.DISK;
146+
}
147+
148+
/**
149+
* Encounter pokemon
150+
*
151+
* @return the encounter result
152+
*/
153+
public EncounterResult encounterPokemon() throws LoginFailedException, RemoteServerException {
154+
return encounterPokemonAsync().toBlocking();
126155
}
127156

128157
/**
@@ -131,26 +160,41 @@ public CatchablePokemon(PokemonGo api, FortData proto) {
131160
* @return the encounter result
132161
*/
133162
public PokemonFuture<EncounterResult> encounterPokemonAsync() {
134-
EncounterMessageOuterClass.EncounterMessage reqMsg = EncounterMessageOuterClass.EncounterMessage
163+
if (encounterKind == EncounterKind.NORMAL) {
164+
return encounterNormalPokemonAsync();
165+
} else if (encounterKind == EncounterKind.DISK) {
166+
return encounterDiskPokemonAsync();
167+
}
168+
169+
throw new IllegalStateException("Catchable pokemon missing encounter type");
170+
}
171+
172+
/**
173+
* Encounter pokemon encounter result.
174+
*
175+
* @return the encounter result
176+
*/
177+
public PokemonFuture<EncounterResult> encounterNormalPokemonAsync() {
178+
EncounterMessage reqMsg = EncounterMessage
135179
.newBuilder().setEncounterId(getEncounterId())
136180
.setPlayerLatitude(api.getLatitude())
137181
.setPlayerLongitude(api.getLongitude())
138182
.setSpawnPointId(getSpawnPointId()).build();
139183
AsyncServerRequest serverRequest = new AsyncServerRequest(
140-
RequestTypeOuterClass.RequestType.ENCOUNTER, reqMsg);
184+
RequestType.ENCOUNTER, reqMsg);
141185
return new FutureWrapper<ByteString, EncounterResult>(api.getRequestHandler()
142186
.sendAsyncServerRequests(serverRequest)) {
143187
@Override
144188
protected EncounterResult handle(ByteString result) throws RemoteServerException {
145-
EncounterResponseOuterClass.EncounterResponse response;
189+
EncounterResponse response;
146190
try {
147-
response = EncounterResponseOuterClass.EncounterResponse
191+
response = EncounterResponse
148192
.parseFrom(result);
149193
} catch (InvalidProtocolBufferException e) {
150194
throw new RemoteServerException(e);
151195
}
152196
encountered = response.getStatus() == EncounterResponse.Status.ENCOUNTER_SUCCESS;
153-
return new EncounterResult(response);
197+
return new NormalEncounterResult(response);
154198
}
155199
};
156200
}
@@ -162,11 +206,42 @@ protected EncounterResult handle(ByteString result) throws RemoteServerException
162206
* @throws LoginFailedException the login failed exception
163207
* @throws RemoteServerException the remote server exception
164208
*/
165-
public EncounterResult encounterPokemon() throws LoginFailedException,
209+
public EncounterResult encounterNormalPokemon() throws LoginFailedException,
166210
RemoteServerException {
167-
return encounterPokemonAsync().toBlocking();
211+
return encounterNormalPokemonAsync().toBlocking();
212+
}
213+
214+
215+
216+
/**
217+
* Encounter pokemon
218+
*
219+
* @return the encounter result
220+
*/
221+
public PokemonFuture<EncounterResult> encounterDiskPokemonAsync() {
222+
DiskEncounterMessage reqMsg = DiskEncounterMessage
223+
.newBuilder().setEncounterId(getEncounterId())
224+
.setPlayerLatitude(api.getLatitude())
225+
.setPlayerLongitude(api.getLongitude())
226+
.setFortId(getSpawnPointId()).build();
227+
AsyncServerRequest serverRequest = new AsyncServerRequest(RequestType.DISK_ENCOUNTER, reqMsg);
228+
return new FutureWrapper<ByteString, EncounterResult>(api.getRequestHandler()
229+
.sendAsyncServerRequests(serverRequest)) {
230+
@Override
231+
protected EncounterResult handle(ByteString result) throws RemoteServerException {
232+
DiskEncounterResponse response;
233+
try {
234+
response = DiskEncounterResponse.parseFrom(result);
235+
} catch (InvalidProtocolBufferException e) {
236+
throw new RemoteServerException(e);
237+
}
238+
encountered = response.getResult() == DiskEncounterResponse.Result.SUCCESS;
239+
return new DiskEncounterResult(response);
240+
}
241+
};
168242
}
169243

244+
170245
/**
171246
* Tries to catch a pokemon (will attempt to use a pokeball, if you have
172247
* none will use greatball etc) and uwill use a single razz berry if available.
@@ -389,11 +464,12 @@ public PokemonFuture<CatchResult> catchPokemonAsync(double normalizedHitPosition
389464
.setSpinModifier(spinModifier)
390465
.setPokeball(type.getBallType()).build();
391466
AsyncServerRequest serverRequest = new AsyncServerRequest(
392-
RequestTypeOuterClass.RequestType.CATCH_POKEMON, reqMsg);
467+
RequestType.CATCH_POKEMON, reqMsg);
393468
return new FutureWrapper<ByteString, CatchResult>(api.getRequestHandler()
394469
.sendAsyncServerRequests(serverRequest)) {
395470
@Override
396471
protected CatchResult handle(ByteString result) throws RemoteServerException, LoginFailedException {
472+
System.out.println("ASYNC CATCH CALL");
397473
CatchPokemonResponse response;
398474

399475
try {
@@ -439,7 +515,7 @@ public PokemonFuture<CatchItemResult> useItemAsync(ItemId item) {
439515
.build();
440516

441517
AsyncServerRequest serverRequest = new AsyncServerRequest(
442-
RequestTypeOuterClass.RequestType.USE_ITEM_CAPTURE, reqMsg);
518+
RequestType.USE_ITEM_CAPTURE, reqMsg);
443519
return new FutureWrapper<ByteString, CatchItemResult>(api.getRequestHandler()
444520
.sendAsyncServerRequests(serverRequest)) {
445521
@Override

0 commit comments

Comments
 (0)