Skip to content

Commit 15b2dc7

Browse files
committed
Fixed an NPE caused by stopping an EntityContainer that only partially started.
1 parent 7e6c8f8 commit 15b2dc7

2 files changed

Lines changed: 52 additions & 47 deletions

File tree

release-notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Version 1.9.0 (unreleased)
2121
* Added a SystemTiming class that can optionally be given to GameSystemManager
2222
to track per-system timings and dump the information as a warning when
2323
a frame exceeds a certain threshold.
24+
* Fixed an NPE when stopping an EntityContainer that did not fully start.
2425

2526

2627
Version 1.8.0 (latest)

src/main/java/com/simsilica/es/EntityContainer.java

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11
/*
22
* $Id$
3-
*
3+
*
44
* Copyright (c) 2015, Simsilica, LLC
55
* All rights reserved.
6-
*
6+
*
77
* Redistribution and use in source and binary forms, with or without
8-
* modification, are permitted provided that the following conditions
8+
* modification, are permitted provided that the following conditions
99
* are met:
10-
*
11-
* 1. Redistributions of source code must retain the above copyright
10+
*
11+
* 1. Redistributions of source code must retain the above copyright
1212
* notice, this list of conditions and the following disclaimer.
13-
*
14-
* 2. Redistributions in binary form must reproduce the above copyright
15-
* notice, this list of conditions and the following disclaimer in
16-
* the documentation and/or other materials provided with the
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in
16+
* the documentation and/or other materials provided with the
1717
* distribution.
18-
*
19-
* 3. Neither the name of the copyright holder nor the names of its
20-
* contributors may be used to endorse or promote products derived
18+
*
19+
* 3. Neither the name of the copyright holder nor the names of its
20+
* contributors may be used to endorse or promote products derived
2121
* from this software without specific prior written permission.
22-
*
23-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24-
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25-
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26-
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27-
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28-
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29-
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30-
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31-
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32-
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33-
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
22+
*
23+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27+
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3434
* OF THE POSSIBILITY OF SUCH DAMAGE.
3535
*/
3636

@@ -70,29 +70,29 @@
7070
public abstract class EntityContainer<T> {
7171

7272
static Logger log = LoggerFactory.getLogger(EntityContainer.class);
73-
73+
7474
private EntityData ed;
7575
private ComponentFilter filter;
7676
private Class<? extends EntityComponent>[] componentTypes;
7777
private EntitySet entities;
7878
private T[] array;
7979
private Map<EntityId, T> objects = new HashMap<>();
8080
private Class parameter;
81-
81+
8282
@SuppressWarnings("unchecked")
8383
@SafeVarargs
8484
protected EntityContainer( EntityData ed, Class<? extends EntityComponent>... componentTypes ) {
8585
this(ed, null, componentTypes);
8686
}
87-
87+
8888
@SuppressWarnings("unchecked")
8989
@SafeVarargs
9090
protected EntityContainer( EntityData ed, ComponentFilter filter, Class<? extends EntityComponent>... componentTypes ) {
9191
this.ed = ed;
9292
this.filter = filter;
9393
this.componentTypes = componentTypes;
94-
95-
// Find out what the type parameter is
94+
95+
// Find out what the type parameter is
9696
for( Type t = getClass().getGenericSuperclass(); t != null; ) {
9797
if( t instanceof ParameterizedType ) {
9898
ParameterizedType pt = (ParameterizedType)t;
@@ -103,10 +103,10 @@ protected EntityContainer( EntityData ed, ComponentFilter filter, Class<? extend
103103
parameter = (Class)pt.getActualTypeArguments()[0];
104104
}
105105
break;
106-
}
106+
}
107107
} else if( t instanceof Class ) {
108108
t = ((Class)t).getGenericSuperclass();
109-
} else {
109+
} else {
110110
t = null;
111111
}
112112
}
@@ -125,23 +125,23 @@ protected void setFilter( ComponentFilter filter ) {
125125
protected EntityData getEntityData() {
126126
return ed;
127127
}
128-
128+
129129
@SuppressWarnings("unchecked")
130130
protected void addComponentTypes( Class<? extends EntityComponent>... add ) {
131131
Class[] merged = new Class[add.length + componentTypes.length];
132132
System.arraycopy(componentTypes, 0, merged, 0, componentTypes.length);
133133
System.arraycopy(add, 0, merged, componentTypes.length, add.length);
134134
this.componentTypes = merged;
135135
}
136-
136+
137137
public int size() {
138138
return entities.size();
139139
}
140140

141141
public T getObject( EntityId id ) {
142142
return objects.get(id);
143143
}
144-
144+
145145
@SuppressWarnings("unchecked")
146146
protected T[] getArray() {
147147
if( array != null ) {
@@ -151,13 +151,13 @@ protected T[] getArray() {
151151
array = objects.values().toArray(array);
152152
return array;
153153
}
154-
154+
155155
protected abstract T addObject( Entity e );
156-
156+
157157
protected abstract void updateObject( T object, Entity e );
158-
159-
protected abstract void removeObject( T object, Entity e );
160-
158+
159+
protected abstract void removeObject( T object, Entity e );
160+
161161
protected void addObjects( Set<Entity> set ) {
162162
if( set.isEmpty() ) {
163163
return;
@@ -168,7 +168,7 @@ protected void addObjects( Set<Entity> set ) {
168168
}
169169
array = null;
170170
}
171-
171+
172172
protected void updateObjects( Set<Entity> set ) {
173173
if( set.isEmpty() ) {
174174
return;
@@ -182,7 +182,7 @@ protected void updateObjects( Set<Entity> set ) {
182182
updateObject(object, e);
183183
}
184184
}
185-
185+
186186
protected void removeObjects( Set<Entity> set ) {
187187
if( set.isEmpty() ) {
188188
return;
@@ -197,13 +197,13 @@ protected void removeObjects( Set<Entity> set ) {
197197
}
198198
array = null;
199199
}
200-
200+
201201
public void start() {
202202
this.entities = ed.getEntities(filter, componentTypes);
203203
entities.applyChanges();
204-
addObjects(entities);
204+
addObjects(entities);
205205
}
206-
206+
207207
public boolean update() {
208208
if( entities.applyChanges() ) {
209209
removeObjects(entities.getRemovedEntities());
@@ -213,17 +213,21 @@ public boolean update() {
213213
}
214214
return false;
215215
}
216-
216+
217217
public void stop() {
218+
if( entities == null ) {
219+
// We were never started or startup failed
220+
return;
221+
}
218222
removeObjects(entities);
219223
this.entities.release();
220224
this.entities = null;
221225
}
222-
226+
223227
public boolean isStarted() {
224228
return entities != null;
225229
}
226-
230+
227231
@Override
228232
public String toString() {
229233
return getClass().getName() + "[components=" + Arrays.asList(componentTypes) + "]";

0 commit comments

Comments
 (0)