@@ -26,6 +26,7 @@ of this software and associated documentation files (the "Software"), to deal
2626package bwapi ;
2727
2828import java .nio .ByteBuffer ;
29+ import java .util .concurrent .locks .ReentrantLock ;
2930
3031/**
3132 * Manages invocation of bot event handlers
@@ -39,6 +40,8 @@ class BotWrapper {
3940 private Thread botThread ;
4041 private boolean gameOver ;
4142 private PerformanceMetrics performanceMetrics ;
43+ private Exception lastBotException ;
44+ private ReentrantLock lastBotExceptionLock = new ReentrantLock ();
4245
4346 BotWrapper (BWClientConfiguration configuration , BWEventListener eventListener ) {
4447 this .configuration = configuration ;
@@ -50,7 +53,9 @@ class BotWrapper {
5053 * Resets the BotWrapper for a new game.
5154 */
5255 void startNewGame (ByteBuffer dataSource , PerformanceMetrics performanceMetrics ) {
53- frameBuffer .initialize (dataSource , performanceMetrics );
56+ if (configuration .async ) {
57+ frameBuffer .initialize (dataSource , performanceMetrics );
58+ }
5459 this .performanceMetrics = performanceMetrics ;
5560 game = new Game (liveClientData );
5661 liveClientData .setBuffer (dataSource );
@@ -80,7 +85,7 @@ void onFrame() {
8085 }
8186 /*
8287 Add a frame to buffer
83- If buffer is full, it will wait until it has capacity
88+ If buffer is full, it will wait until it has capacity
8489 Wait for empty buffer OR termination condition
8590 */
8691 boolean isFrameZero = liveClientData .gameData ().getFrameCount () == 0 ;
@@ -89,6 +94,13 @@ void onFrame() {
8994 frameBuffer .lockSize .lock ();
9095 try {
9196 while (!frameBuffer .empty ()) {
97+
98+ // Make bot exceptions fall through to the main thread.
99+ Exception lastBotException = getLastBotException ();
100+ if (lastBotException != null ) {
101+ throw new RuntimeException (lastBotException );
102+ }
103+
92104 if (configuration .unlimitedFrameZero && isFrameZero ) {
93105 frameBuffer .conditionSize .await ();
94106 } else {
@@ -104,6 +116,9 @@ void onFrame() {
104116 }
105117 } else {
106118 handleEvents ();
119+ if (lastBotException != null ) {
120+ throw new RuntimeException (lastBotException );
121+ }
107122 }
108123 }
109124
@@ -118,6 +133,13 @@ void endGame() {
118133 }
119134 }
120135
136+ Exception getLastBotException () {
137+ lastBotExceptionLock .lock ();
138+ Exception output = lastBotException ;
139+ lastBotExceptionLock .unlock ();
140+ return output ;
141+ }
142+
121143 private Thread createBotThread () {
122144 return new Thread (() -> {
123145 while ( ! gameOver ) {
@@ -144,12 +166,18 @@ private void handleEvents() {
144166 if (gameData .getFrameCount () > 0 || ! configuration .unlimitedFrameZero ) {
145167 performanceMetrics .botResponse .startTiming ();
146168 }
147- for (int i = 0 ; i < gameData .getEventCount (); i ++) {
148- ClientData .Event event = gameData .getEvents (i );
149- EventHandler .operation (eventListener , game , event );
150- if (event .getType () == EventType .MatchEnd ) {
151- gameOver = true ;
169+ try {
170+ for (int i = 0 ; i < gameData .getEventCount (); i ++) {
171+ ClientData .Event event = gameData .getEvents (i );
172+ EventHandler .operation (eventListener , game , event );
173+ if (event .getType () == EventType .MatchEnd ) {
174+ gameOver = true ;
175+ }
152176 }
177+ } catch (Exception exception ) {
178+ lastBotExceptionLock .lock ();
179+ lastBotException = exception ;
180+ lastBotExceptionLock .unlock ();
153181 }
154182 performanceMetrics .botResponse .stopTiming ();
155183 }
0 commit comments