Skip to content

Commit 76fb2b5

Browse files
authored
WIP: Gym/Battle (#203)
* Add info about native google sign in * fix force updating inventories * REAME.md: fix Usefull->Useful typo * README.md: fix PtcLogin classname type * Start Gym + Battle API * Battle API - Example included, utility functions to get state of battle. Can only spam attack right now.
1 parent 89697f2 commit 76fb2b5

File tree

4 files changed

+547
-0
lines changed

4 files changed

+547
-0
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/*
2+
* This program is free software: you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License as published by
4+
* the Free Software Foundation, either version 3 of the License, or
5+
* (at your option) any later version.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License
13+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
14+
*/
15+
16+
package com.pokegoapi.api.gym;
17+
18+
import POGOProtos.Data.Battle.BattleActionOuterClass.BattleAction;
19+
import POGOProtos.Data.Battle.BattleActionTypeOuterClass;
20+
import POGOProtos.Data.Battle.BattlePokemonInfoOuterClass.BattlePokemonInfo;
21+
import POGOProtos.Data.Battle.BattleStateOuterClass;
22+
import POGOProtos.Data.Battle.BattleStateOuterClass.BattleState;
23+
import POGOProtos.Data.PokemonDataOuterClass;
24+
import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass;
25+
import POGOProtos.Networking.Requests.Messages.AttackGymMessageOuterClass.AttackGymMessage;
26+
import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass;
27+
import POGOProtos.Networking.Requests.Messages.StartGymBattleMessageOuterClass.StartGymBattleMessage.Builder;
28+
import POGOProtos.Networking.Requests.RequestTypeOuterClass;
29+
import POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType;
30+
import POGOProtos.Networking.Responses.AttackGymResponseOuterClass;
31+
import POGOProtos.Networking.Responses.AttackGymResponseOuterClass.AttackGymResponse;
32+
import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse;
33+
import POGOProtos.Networking.Responses.StartGymBattleResponseOuterClass.StartGymBattleResponse.Result;
34+
import com.google.protobuf.InvalidProtocolBufferException;
35+
import com.pokegoapi.api.PokemonGo;
36+
import com.pokegoapi.api.pokemon.Pokemon;
37+
import com.pokegoapi.exceptions.LoginFailedException;
38+
import com.pokegoapi.exceptions.RemoteServerException;
39+
import com.pokegoapi.main.ServerRequest;
40+
import lombok.Getter;
41+
42+
import java.util.ArrayList;
43+
import java.util.List;
44+
45+
public class Battle {
46+
private Gym gym;
47+
private Pokemon[] team;
48+
private List<BattlePokemonInfo> bteam;
49+
private StartGymBattleResponse battleResponse;
50+
private PokemonGo api;
51+
private List<Integer> gymIndex;
52+
@Getter
53+
private boolean concluded;
54+
@Getter
55+
private BattleState outcome;
56+
57+
/**
58+
* New battle to track the state of a battle.
59+
*
60+
*/
61+
public Battle(PokemonGo api, Pokemon[] team, Gym gym) {
62+
this.team = team;
63+
this.gym = gym;
64+
this.api = api;
65+
66+
this.bteam = new ArrayList<BattlePokemonInfo>();
67+
this.gymIndex = new ArrayList<>();
68+
69+
for (int i = 0; i < team.length; i++) {
70+
bteam.add(this.createBattlePokemon(team[i]));
71+
}
72+
}
73+
74+
/**
75+
* Start a battle.
76+
*
77+
* @return Result of the attempt to start
78+
*/
79+
public Result start() throws LoginFailedException, RemoteServerException {
80+
81+
Builder builder = StartGymBattleMessageOuterClass.StartGymBattleMessage.newBuilder();
82+
83+
for (int i = 0; i < team.length; i++) {
84+
builder.addAttackingPokemonIds(team[i].getId());
85+
}
86+
87+
88+
List<PokemonDataOuterClass.PokemonData> defenders = gym.getDefendingPokemon();
89+
builder.setGymId(gym.getId());
90+
builder.setPlayerLongitude(api.getLongitude());
91+
builder.setPlayerLatitude(api.getLatitude());
92+
builder.setDefendingPokemonId(defenders.get(0).getId()); // may need to be sorted
93+
94+
ServerRequest serverRequest = new ServerRequest(RequestType.START_GYM_BATTLE, builder.build());
95+
api.getRequestHandler().sendServerRequests(serverRequest);
96+
97+
98+
try {
99+
battleResponse = StartGymBattleResponse.parseFrom(serverRequest.getData());
100+
} catch (InvalidProtocolBufferException e) {
101+
throw new RemoteServerException();
102+
}
103+
104+
// need to send blank action
105+
this.sendBlankAction();
106+
107+
108+
for (BattleAction action : battleResponse.getBattleLog().getBattleActionsList()) {
109+
gymIndex.add(action.getTargetIndex());
110+
}
111+
112+
return battleResponse.getResult();
113+
}
114+
115+
116+
117+
118+
/**
119+
* Attack a gym.
120+
*
121+
* @param times the amount of times to attack
122+
* @return Battle
123+
*/
124+
public AttackGymResponse attack(int times) throws LoginFailedException, RemoteServerException {
125+
126+
ArrayList<BattleAction> actions = new ArrayList<BattleAction>();
127+
128+
for (int i = 0; i < times; i++) {
129+
BattleAction action = BattleAction
130+
.newBuilder()
131+
.setType(BattleActionTypeOuterClass.BattleActionType.ACTION_ATTACK)
132+
.setActionStartMs(System.currentTimeMillis() + (100 * times))
133+
.setDurationMs(500)
134+
.setTargetIndex(-1)
135+
.build();
136+
actions.add(action);
137+
}
138+
139+
AttackGymResponse result = doActions(actions);
140+
141+
142+
143+
return result;
144+
}
145+
146+
147+
/**
148+
* Creates a battle pokemon object to send with the request.
149+
*
150+
* @Param Pokemon
151+
* @return BattlePokemonInfo
152+
*/
153+
private BattlePokemonInfo createBattlePokemon(Pokemon pokemon) {
154+
BattlePokemonInfo info = BattlePokemonInfo
155+
.newBuilder()
156+
.setCurrentEnergy(0)
157+
.setCurrentHealth(100)
158+
.setPokemonData(pokemon.getDefaultInstanceForType())
159+
.build();
160+
return info;
161+
}
162+
163+
/**
164+
* Get the Pokemondata for the defenders.
165+
*
166+
* @param index of defender(0 to gym lever)
167+
* @return Battle
168+
*/
169+
private PokemonDataOuterClass.PokemonData getDefender(int index) throws LoginFailedException, RemoteServerException {
170+
return gym.getGymMembers().get(0).getPokemonData();
171+
}
172+
173+
/**
174+
* Get the last action from server.
175+
*
176+
* @return BattleAction
177+
*/
178+
private BattleAction getLastActionFromServer() {
179+
BattleAction action;
180+
int actionCount = battleResponse.getBattleLog().getBattleActionsCount();
181+
action = battleResponse.getBattleLog().getBattleActions(actionCount - 1);
182+
return action;
183+
}
184+
185+
/**
186+
* Send blank action, used for polling the state of the battle. (i think).
187+
*
188+
* @return AttackGymResponse
189+
*/
190+
private AttackGymResponse sendBlankAction() throws LoginFailedException, RemoteServerException {
191+
AttackGymMessage message = AttackGymMessage
192+
.newBuilder()
193+
.setGymId(gym.getId())
194+
.setPlayerLatitude(api.getLatitude())
195+
.setPlayerLongitude(api.getLongitude())
196+
.setBattleId(battleResponse.getBattleId())
197+
.build();
198+
199+
ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message);
200+
api.getRequestHandler().sendServerRequests(serverRequest);
201+
202+
203+
try {
204+
return AttackGymResponse.parseFrom(serverRequest.getData());
205+
} catch (InvalidProtocolBufferException e) {
206+
throw new RemoteServerException();
207+
}
208+
}
209+
210+
211+
/**
212+
* Do Actions in battle.
213+
*
214+
* @param actions list of actions to send in this request
215+
* @return AttackGymResponse
216+
*/
217+
private AttackGymResponse doActions(List<BattleAction> actions) throws LoginFailedException, RemoteServerException {
218+
219+
220+
AttackGymMessage.Builder message = AttackGymMessage
221+
.newBuilder()
222+
.setGymId(gym.getId())
223+
.setPlayerLatitude(api.getLatitude())
224+
.setPlayerLongitude(api.getLongitude())
225+
.setBattleId(battleResponse.getBattleId());
226+
227+
for (BattleAction action : actions) {
228+
message.addAttackActions(action);
229+
}
230+
231+
232+
233+
ServerRequest serverRequest = new ServerRequest(RequestType.ATTACK_GYM, message.build());
234+
api.getRequestHandler().sendServerRequests(serverRequest);
235+
236+
237+
try {
238+
AttackGymResponse response = AttackGymResponse.parseFrom(serverRequest.getData());
239+
240+
if (response.getBattleLog().getState() == BattleState.DEFEATED
241+
|| response.getBattleLog().getState() == BattleState.VICTORY
242+
|| response.getBattleLog().getState() == BattleState.TIMED_OUT) {
243+
concluded = true;
244+
}
245+
246+
outcome = response.getBattleLog().getState();
247+
248+
249+
250+
return response;
251+
} catch (InvalidProtocolBufferException e) {
252+
throw new RemoteServerException();
253+
}
254+
255+
}
256+
257+
}

0 commit comments

Comments
 (0)