Skip to content

Commit a80d422

Browse files
authored
Synchronize inventories to prevent CMEs (#819)
* Blocking inventories to prevent CMEs * Fix checkstyle
1 parent b368222 commit a80d422

File tree

9 files changed

+177
-90
lines changed

9 files changed

+177
-90
lines changed

library/src/main/java/com/pokegoapi/api/PokemonGo.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656

5757
import java.lang.reflect.Method;
5858
import java.util.ArrayList;
59+
import java.util.Collections;
5960
import java.util.List;
6061
import java.util.Random;
6162
import java.util.UUID;
@@ -110,7 +111,9 @@ public class PokemonGo {
110111
private String challengeURL;
111112

112113
@Getter
113-
private List<Listener> listeners = new ArrayList<Listener>();
114+
private List<Listener> listeners = Collections.synchronizedList(new ArrayList<Listener>());
115+
116+
private final Object lock = new Object();
114117

115118
@Getter
116119
private boolean loggingIn;
@@ -452,9 +455,11 @@ public void removeListener(Listener listener) {
452455
*/
453456
public <T extends Listener> List<T> getListeners(Class<T> listenerType) {
454457
List<T> listeners = new ArrayList<T>();
455-
for (Listener listener : this.listeners) {
456-
if (listenerType.isAssignableFrom(listener.getClass())) {
457-
listeners.add((T) listener);
458+
synchronized (this.lock) {
459+
for (Listener listener : this.listeners) {
460+
if (listenerType.isAssignableFrom(listener.getClass())) {
461+
listeners.add((T) listener);
462+
}
458463
}
459464
}
460465
return listeners;

library/src/main/java/com/pokegoapi/api/inventory/CandyJar.java

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,32 @@
1515

1616
package com.pokegoapi.api.inventory;
1717

18+
import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId;
1819
import com.pokegoapi.api.PokemonGo;
20+
import lombok.ToString;
1921

22+
import java.util.Collections;
2023
import java.util.HashMap;
21-
22-
import POGOProtos.Enums.PokemonFamilyIdOuterClass.PokemonFamilyId;
23-
import lombok.ToString;
24+
import java.util.Map;
2425

2526
@ToString
2627
public class CandyJar {
2728
private final PokemonGo api;
28-
private final HashMap<PokemonFamilyId, Integer> candies = new HashMap<>();
29+
private final Map<PokemonFamilyId, Integer> candies =
30+
Collections.synchronizedMap(new HashMap<PokemonFamilyId, Integer>());
31+
private final Object lock = new Object();
2932

3033
public CandyJar(PokemonGo api) {
3134
this.api = api;
3235
}
3336

37+
/**
38+
* Resets this candy jar and removes all candies
39+
*/
3440
public void reset() {
35-
candies.clear();
41+
synchronized (this.lock) {
42+
candies.clear();
43+
}
3644
}
3745

3846
/**
@@ -42,7 +50,9 @@ public void reset() {
4250
* @param candies Amount to set it to
4351
*/
4452
public void setCandy(PokemonFamilyId family, int candies) {
45-
this.candies.put(family, candies);
53+
synchronized (this.lock) {
54+
this.candies.put(family, candies);
55+
}
4656
}
4757

4858
/**
@@ -52,10 +62,12 @@ public void setCandy(PokemonFamilyId family, int candies) {
5262
* @param amount Amount of candies to add
5363
*/
5464
public void addCandy(PokemonFamilyId family, int amount) {
55-
if (candies.containsKey(family)) {
56-
candies.put(family, candies.get(family) + amount);
57-
} else {
58-
candies.put(family, amount);
65+
synchronized (this.lock) {
66+
if (candies.containsKey(family)) {
67+
candies.put(family, candies.get(family) + amount);
68+
} else {
69+
candies.put(family, amount);
70+
}
5971
}
6072
}
6173

@@ -66,14 +78,16 @@ public void addCandy(PokemonFamilyId family, int amount) {
6678
* @param amount Amount of candies to remove
6779
*/
6880
public void removeCandy(PokemonFamilyId family, int amount) {
69-
if (candies.containsKey(family)) {
70-
if (candies.get(family) - amount < 0) {
71-
candies.put(family, 0);
81+
synchronized (this.lock) {
82+
if (candies.containsKey(family)) {
83+
if (candies.get(family) - amount < 0) {
84+
candies.put(family, 0);
85+
} else {
86+
candies.put(family, candies.get(family) - amount);
87+
}
7288
} else {
73-
candies.put(family, candies.get(family) - amount);
89+
candies.put(family, 0);
7490
}
75-
} else {
76-
candies.put(family, 0);
7791
}
7892
}
7993

@@ -84,10 +98,12 @@ public void removeCandy(PokemonFamilyId family, int amount) {
8498
* @return number of candies in jar
8599
*/
86100
public int getCandies(PokemonFamilyId family) {
87-
if (candies.containsKey(family)) {
88-
return this.candies.get(family);
89-
} else {
90-
return 0;
101+
synchronized (this.lock) {
102+
if (candies.containsKey(family)) {
103+
return this.candies.get(family);
104+
} else {
105+
return 0;
106+
}
91107
}
92108
}
93109
}

library/src/main/java/com/pokegoapi/api/inventory/Hatchery.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,38 +30,47 @@
3030
import lombok.Getter;
3131

3232
import java.util.ArrayList;
33+
import java.util.Collections;
3334
import java.util.HashSet;
3435
import java.util.List;
3536
import java.util.Set;
3637

3738
public class Hatchery {
3839
@Getter
39-
private final Set<EggPokemon> eggs = new HashSet<EggPokemon>();
40+
private final Set<EggPokemon> eggs = Collections.synchronizedSet(new HashSet<EggPokemon>());
4041
@Getter
41-
private final Set<HatchedEgg> hatchedEggs = new HashSet<HatchedEgg>();
42+
private final Set<HatchedEgg> hatchedEggs = Collections.synchronizedSet(new HashSet<HatchedEgg>());
4243
@Getter
4344
private PokemonGo api;
4445

46+
private final Object lock = new Object();
47+
4548
public Hatchery(PokemonGo api) {
4649
this.api = api;
4750
}
4851

4952
public void reset() {
50-
eggs.clear();
51-
hatchedEggs.clear();
53+
synchronized (this.lock) {
54+
eggs.clear();
55+
hatchedEggs.clear();
56+
}
5257
}
5358

5459
public void addEgg(EggPokemon egg) {
5560
egg.setApi(api);
56-
eggs.add(egg);
61+
synchronized (this.lock) {
62+
eggs.add(egg);
63+
}
5764
}
5865

5966
/**
6067
* Adds the given hatched egg to the hatchedEggs set.
6168
* @param egg the egg to add
6269
*/
6370
public void addHatchedEgg(HatchedEgg egg) {
64-
hatchedEggs.add(egg);
71+
synchronized (this.lock) {
72+
hatchedEggs.add(egg);
73+
}
6574
boolean remove = false;
6675
List<PokemonListener> listeners = api.getListeners(PokemonListener.class);
6776
for (PokemonListener listener : listeners) {
@@ -77,7 +86,9 @@ public void addHatchedEgg(HatchedEgg egg) {
7786
* @param egg the egg to remove
7887
*/
7988
public void removeHatchedEgg(HatchedEgg egg) {
80-
hatchedEggs.remove(egg);
89+
synchronized (this.lock) {
90+
hatchedEggs.remove(egg);
91+
}
8192
}
8293

8394
/**

library/src/main/java/com/pokegoapi/api/inventory/Inventories.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import lombok.Getter;
3737

3838
import java.util.ArrayList;
39+
import java.util.Collections;
3940
import java.util.List;
4041

4142

@@ -51,12 +52,15 @@ public class Inventories {
5152
@Getter
5253
private Pokedex pokedex;
5354
@Getter
54-
private final List<EggIncubator> incubators = new ArrayList<>();
55+
private final List<EggIncubator> incubators = Collections.synchronizedList(new ArrayList<EggIncubator>());
5556
@Getter
5657
private Hatchery hatchery;
5758
@Getter
5859
private long lastInventoryUpdate = 0;
5960

61+
@Getter
62+
private final Object lock = new Object();
63+
6064
/**
6165
* Creates Inventories and initializes content.
6266
*
@@ -98,7 +102,9 @@ public void updateInventories(boolean forceUpdate)
98102
pokebank.reset();
99103
candyjar.reset();
100104
pokedex.reset();
101-
incubators.clear();
105+
synchronized (this.lock) {
106+
incubators.clear();
107+
}
102108
hatchery.reset();
103109
}
104110
GetInventoryMessage invReqMsg = GetInventoryMessage.newBuilder()
@@ -167,8 +173,10 @@ public void updateInventories(GetInventoryResponse response) {
167173
if (itemData.hasEggIncubators()) {
168174
for (EggIncubatorOuterClass.EggIncubator incubator : itemData.getEggIncubators().getEggIncubatorList()) {
169175
EggIncubator eggIncubator = new EggIncubator(api, incubator);
170-
incubators.remove(eggIncubator);
171-
incubators.add(eggIncubator);
176+
synchronized (this.lock) {
177+
incubators.remove(eggIncubator);
178+
incubators.add(eggIncubator);
179+
}
172180
}
173181
}
174182

library/src/main/java/com/pokegoapi/api/inventory/ItemBag.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,34 @@
3535

3636
import java.util.ArrayList;
3737
import java.util.Collection;
38+
import java.util.Collections;
3839
import java.util.HashMap;
3940
import java.util.List;
41+
import java.util.Map;
4042

4143

4244
/**
4345
* The type Bag.
4446
*/
4547
public class ItemBag {
4648
private final PokemonGo api;
47-
private final HashMap<ItemId, Item> items = new HashMap<>();
49+
private final Map<ItemId, Item> items = Collections.synchronizedMap(new HashMap<ItemId, Item>());
50+
private final Object lock = new Object();
4851

4952
public ItemBag(PokemonGo api) {
5053
this.api = api;
5154
}
5255

5356
public void reset() {
54-
items.clear();
57+
synchronized (this.lock) {
58+
items.clear();
59+
}
5560
}
5661

5762
public void addItem(Item item) {
58-
items.put(item.getItemId(), item);
63+
synchronized (this.lock) {
64+
items.put(item.getItemId(), item);
65+
}
5966
}
6067

6168
/**
@@ -106,7 +113,9 @@ public Result removeItem(ItemId id, int quantity)
106113
* @return The item removed, if any
107114
*/
108115
public Item removeItem(ItemId id) {
109-
return items.remove(id);
116+
synchronized (this.lock) {
117+
return items.remove(id);
118+
}
110119
}
111120

112121
/**
@@ -120,16 +129,20 @@ public Item getItem(ItemId type) {
120129
throw new IllegalArgumentException("You cannot get item for UNRECOGNIZED");
121130
}
122131

123-
// prevent returning null
124-
if (!items.containsKey(type)) {
125-
return new Item(ItemData.newBuilder().setCount(0).setItemId(type).build(), this);
126-
}
132+
synchronized (this.lock) {
133+
// prevent returning null
134+
if (!items.containsKey(type)) {
135+
return new Item(ItemData.newBuilder().setCount(0).setItemId(type).build(), this);
136+
}
127137

128-
return items.get(type);
138+
return items.get(type);
139+
}
129140
}
130141

131142
public Collection<Item> getItems() {
132-
return items.values();
143+
synchronized (this.lock) {
144+
return items.values();
145+
}
133146
}
134147

135148
/**
@@ -138,11 +151,13 @@ public Collection<Item> getItems() {
138151
* @return used space
139152
*/
140153
public int getItemsCount() {
141-
int ct = 0;
142-
for (Item item : items.values()) {
143-
ct += item.getCount();
154+
synchronized (this.lock) {
155+
int ct = 0;
156+
for (Item item : items.values()) {
157+
ct += item.getCount();
158+
}
159+
return ct;
144160
}
145-
return ct;
146161
}
147162

148163
/**

0 commit comments

Comments
 (0)