1313import java .util .concurrent .atomic .AtomicReference ;
1414
1515public class InteractiveScriptListener implements ScriptInvocationListener {
16+ /**
17+ * When true sends notifications then allows next interaction script.
18+ * Defaults to false which allows next interaction script then notifies.
19+ */
20+ public static boolean NOTIFY_THEN_ALLOW_INTERACTION = false ;
21+ /**
22+ * When true waits for game thread notifications to be processed before proceeding
23+ */
24+ public static boolean WAIT_FOR_GAME_THREAD_NOTIFICATIONS = false ;
25+
1626 private final AtomicInteger scriptId = new AtomicInteger ();
1727 private final AtomicReference <ScriptInvocationListener > invocationListener = new AtomicReference <>();
1828
@@ -32,69 +42,112 @@ public void track(int scriptId, ScriptInvocationListener invocationListener) {
3242 @ Override
3343 public void onScriptBegin (int scriptId ) {
3444 final ScriptInvocationListener invocationListener = this .invocationListener .get ();
35- if (scriptId == this .scriptId .get ()) {
36- if (invocationListener != null ) {
37- if (invocationListener .callOnGameThread ()) {
38- scriptingEngine .scriptNotifications .offer (
39- new ScriptBeginNotification (invocationListener , scriptId ));
40- } else {
41- invocationListener .onScriptBegin (scriptId );
42- }
43- }
45+ if (scriptId != this .scriptId .get ()) {
46+ return ;
47+ }
48+ if (invocationListener == null ) {
49+ return ;
50+ }
51+ if (invocationListener .callOnGameThread ()) {
52+ scriptingEngine .scriptNotifications .offer (
53+ new ScriptBeginNotification (invocationListener , scriptId ));
54+ } else {
55+ invocationListener .onScriptBegin (scriptId );
4456 }
4557 }
4658
4759 @ Override
4860 public void onScriptSuccess (int scriptId , ScriptExecutionResult executionResult ) {
4961 final ScriptInvocationListener invocationListener = this .invocationListener .get ();
50- if (scriptId == this .scriptId .get ()) {
51- invocationQueue .clearInteractiveScriptStatus ();
62+ if (scriptId != this .scriptId .get ()) {
63+ return ;
64+ }
65+ clearInteractionStatusBeforeNotification ();
5266
67+ try {
5368 if (invocationListener != null ) {
5469 if (invocationListener .callOnGameThread ()) {
55- scriptingEngine .scriptNotifications .offer (
56- new ScriptSuccessNotification (invocationListener , scriptId , executionResult ));
70+ final ScriptSuccessNotification notification = new ScriptSuccessNotification (
71+ invocationListener , scriptId , executionResult );
72+ scriptingEngine .scriptNotifications .offer (notification );
73+ if (WAIT_FOR_GAME_THREAD_NOTIFICATIONS ) {
74+ notification .waitForNotification ();
75+ }
5776 } else {
5877 invocationListener .onScriptSuccess (scriptId , executionResult );
5978 }
6079 }
80+ } finally {
81+ clearInteractionStatusAfterNotification ();
6182 }
6283 }
6384
6485 @ Override
6586 public void onScriptSkipped (int scriptId ) {
6687 final ScriptInvocationListener invocationListener = this .invocationListener .get ();
67- if (scriptId == this .scriptId .get ()) {
68- invocationQueue .clearInteractiveScriptStatus ();
88+ if (scriptId != this .scriptId .get ()) {
89+ return ;
90+ }
91+ clearInteractionStatusBeforeNotification ();
6992
93+ try {
7094 if (invocationListener != null ) {
7195 if (invocationListener .callOnGameThread ()) {
72- scriptingEngine .scriptNotifications
73- .offer (new ScriptSkippedNotification (invocationListener , scriptId ));
96+ final ScriptSkippedNotification notification =
97+ new ScriptSkippedNotification (invocationListener , scriptId );
98+ scriptingEngine .scriptNotifications .offer (notification );
99+ if (WAIT_FOR_GAME_THREAD_NOTIFICATIONS ) {
100+ notification .waitForNotification ();
101+ }
74102 } else {
75103 invocationListener .onScriptSkipped (scriptId );
76104 }
77105 }
106+ } finally {
107+ clearInteractionStatusAfterNotification ();
78108 }
79109 }
80110
81111 @ Override
82112 public void onScriptException (int scriptId , Exception e ) {
83113 final ScriptInvocationListener invocationListener = this .invocationListener .get ();
84- if (scriptId == this .scriptId .get ()) {
85- invocationQueue .clearInteractiveScriptStatus ();
114+ if (scriptId != this .scriptId .get ()) {
115+ return ;
116+ }
117+ clearInteractionStatusBeforeNotification ();
86118
119+ try {
87120 if (invocationListener != null ) {
88121 if (invocationListener .callOnGameThread ()) {
89- scriptingEngine .scriptNotifications
90- .offer (new ScriptExceptionNotification (invocationListener , scriptId , e ));
122+ ScriptExceptionNotification notification =
123+ new ScriptExceptionNotification (invocationListener , scriptId , e );
124+ scriptingEngine .scriptNotifications .offer (notification );
125+ if (WAIT_FOR_GAME_THREAD_NOTIFICATIONS ) {
126+ notification .waitForNotification ();
127+ }
91128 } else {
92129 invocationListener .onScriptException (scriptId , e );
93130 }
94131 } else {
95132 e .printStackTrace ();
96133 }
134+ } finally {
135+ clearInteractionStatusAfterNotification ();
136+ }
137+ }
138+
139+ private void clearInteractionStatusBeforeNotification () {
140+ if (NOTIFY_THEN_ALLOW_INTERACTION ) {
141+ return ;
142+ }
143+ invocationQueue .clearInteractiveScriptStatus ();
144+ }
145+
146+ private void clearInteractionStatusAfterNotification () {
147+ if (!NOTIFY_THEN_ALLOW_INTERACTION ) {
148+ return ;
97149 }
150+ invocationQueue .clearInteractiveScriptStatus ();
98151 }
99152
100153 public ScriptInvocationListener getInvocationListener () {
0 commit comments