@@ -26,9 +26,6 @@ of this software and associated documentation files (the "Software"), to deal
2626package bwapi ;
2727
2828import java .nio .ByteBuffer ;
29- import java .util .concurrent .locks .Condition ;
30- import java .util .concurrent .locks .Lock ;
31- import java .util .concurrent .locks .ReentrantLock ;
3229
3330/**
3431 * Manages invocation of bot event handlers
@@ -40,10 +37,7 @@ class BotWrapper {
4037 private final FrameBuffer frameBuffer ;
4138 private Game game ;
4239 private Thread botThread ;
43- private boolean idle = false ;
44-
45- Lock idleLock = new ReentrantLock ();
46- Condition idleCondition = idleLock .newCondition ();
40+ private boolean gameOver ;
4741
4842 BotWrapper (BWClientConfiguration configuration , BWEventListener eventListener ) {
4943 this .configuration = configuration ;
@@ -54,12 +48,12 @@ class BotWrapper {
5448 /**
5549 * Resets the BotWrapper for a new game.
5650 */
57- void initialize (ByteBuffer dataSource ) {
51+ void startNewGame (ByteBuffer dataSource ) {
5852 frameBuffer .initialize (dataSource );
5953 game = new Game (liveClientData );
6054 liveClientData .setBuffer (dataSource );
6155 botThread = null ;
62- idle = false ;
56+ gameOver = false ;
6357 }
6458
6559 /**
@@ -71,68 +65,63 @@ Game getGame() {
7165 }
7266
7367 /**
74- * True if the bot has handled all enqueued frames and is waiting for a new frame from StarCraft.
68+ * Handles the arrival of a new frame from BWAPI
7569 */
76- boolean botIdle () {
77- return idle || ! configuration .async ;
78- }
79-
80- void step () {
70+ void onFrame () {
8171 if (configuration .async ) {
82- frameBuffer .enqueueFrame ();
8372 if (botThread == null ) {
84- botThread = new Thread (() -> {
85- //noinspection InfiniteLoopStatement
86- while (true ) {
87- // Await non-empty frame buffer
88- frameBuffer .lockCapacity .lock ();
89- try {
90- while (frameBuffer .empty ()) {
91- // Signal idleness
92- idleLock .lock ();
93- try {
94- idle = true ;
95- idleCondition .signalAll ();
96- } finally {
97- idleLock .unlock ();
98- }
99- frameBuffer .conditionEmpty .awaitUninterruptibly ();
100- }
101- } finally {
102- frameBuffer .lockCapacity .unlock ();
103- }
104-
105- // Signal non-idleness
106- idleLock .lock ();
107- try {
108- idle = false ;
109- idleCondition .signalAll ();
110- } finally {
111- idleLock .unlock ();
112- }
113-
114- game .clientData ().setBuffer (frameBuffer .dequeueFrame ());
115- System .out .println ("Bot thread: Handling events while " + frameBuffer .framesBuffered () + " frames behind." );
116- handleEvents ();
117- System .out .println ("Bot thread: Handled events." );
118-
119- if ( ! game .clientData ().gameData ().isInGame ()) {
120- System .out .println ("Bot thread: Ending because game is over." );
121- return ;
122- }
123- }});
73+ System .out .println ("Creating bot thread" );
74+ botThread = createBotThread ();
12475 botThread .setName ("JBWAPI Bot" );
12576 botThread .start ();
12677 }
78+ frameBuffer .enqueueFrame ();
79+ frameBuffer .lockSize .lock ();
80+ try {
81+ while ( ! frameBuffer .empty ()) frameBuffer .conditionSize .awaitUninterruptibly ();
82+ } finally {
83+ frameBuffer .lockSize .unlock ();
84+ }
12785 } else {
12886 handleEvents ();
12987 }
13088 }
13189
90+ /**
91+ * Allows an asynchronous bot time to finish operation
92+ */
93+ void endGame () {
94+ if (botThread != null ) {
95+ try {
96+ botThread .join ();
97+ } catch (InterruptedException ignored ) {}
98+ }
99+ }
100+
101+ private Thread createBotThread () {
102+ return new Thread (() -> {
103+ while ( ! gameOver ) {
104+ frameBuffer .lockSize .lock ();
105+ try { while (frameBuffer .empty ()) frameBuffer .conditionSize .awaitUninterruptibly (); } finally { frameBuffer .lockSize .unlock (); }
106+
107+ game .clientData ().setBuffer (frameBuffer .peek ());
108+ System .out .println ("Bot thread: Handling events." );
109+ handleEvents ();
110+ System .out .println ("Bot thread: Handled events." );
111+ frameBuffer .dequeue ();
112+ }
113+ System .out .println ("Bot thread: Ending because game is over." );
114+ });
115+ }
116+
132117 private void handleEvents () {
133118 ClientData .GameData gameData = game .clientData ().gameData ();
134119 for (int i = 0 ; i < gameData .getEventCount (); i ++) {
135- EventHandler .operation (eventListener , game , gameData .getEvents (i ));
120+ ClientData .Event event = gameData .getEvents (i );
121+ EventHandler .operation (eventListener , game , event );
122+ if (event .getType () == EventType .MatchEnd ) {
123+ gameOver = true ;
124+ }
136125 }
137126 }
138127}
0 commit comments