Skip to content

Commit 44a9b6f

Browse files
committed
Add (optional) onScriptBegin method to ScriptInvocationListener
1 parent c346e1b commit 44a9b6f

File tree

14 files changed

+145
-22
lines changed

14 files changed

+145
-22
lines changed

core/src/main/java/org/mini2Dx/miniscript/core/GameScriptingEngine.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ public void run() {
330330
}
331331

332332
ScriptExecutionTask<?> executionTask = scriptExecutorPool.execute(scriptInvocation.getTaskId(),
333-
scriptInvocation.getScriptId(), scriptInvocation.getScriptBindings(), invocationListener);
333+
scriptInvocation.getScriptId(), scriptInvocation.getScriptBindings(), invocationListener, false);
334334
Future<?> taskFuture = threadPoolProvider.submit(executionTask);
335335
executionTask.setTaskFuture(taskFuture);
336336
runningScripts.put(executionTask.getTaskId(), executionTask);
@@ -747,7 +747,7 @@ public void invokeCompiledScriptSync(int taskId, int scriptId, ScriptBindings sc
747747
*/
748748
public void invokeCompiledScriptSync(int taskId, int scriptId, ScriptBindings scriptBindings,
749749
ScriptInvocationListener invocationListener) {
750-
ScriptExecutionTask<?> executionTask = scriptExecutorPool.execute(taskId, scriptId, scriptBindings, invocationListener);
750+
ScriptExecutionTask<?> executionTask = scriptExecutorPool.execute(taskId, scriptId, scriptBindings, invocationListener, true);
751751
runningScripts.put(executionTask.getTaskId(), executionTask);
752752
executionTask.run();
753753
}
@@ -794,6 +794,14 @@ public int getTotalNonInteractiveScriptsQueued() {
794794
return scriptInvocationQueue.getNonInteractiveScriptsQueued();
795795
}
796796

797+
/**
798+
* Returns true if interactive script is running
799+
* @return
800+
*/
801+
public boolean isInteractiveScriptRunning() {
802+
return scriptInvocationQueue.isInteractiveScriptRunnung();
803+
}
804+
797805
void submitGameFuture(GameFuture gameFuture) {
798806
queuedFutures.offer(gameFuture);
799807
}

core/src/main/java/org/mini2Dx/miniscript/core/ScriptExecutionTask.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package org.mini2Dx.miniscript.core;
2525

2626
import org.mini2Dx.miniscript.core.exception.ScriptSkippedException;
27+
import org.mini2Dx.miniscript.core.notification.ScriptBeginNotification;
2728
import org.mini2Dx.miniscript.core.notification.ScriptExceptionNotification;
2829
import org.mini2Dx.miniscript.core.notification.ScriptSkippedNotification;
2930
import org.mini2Dx.miniscript.core.notification.ScriptSuccessNotification;
@@ -42,24 +43,42 @@ public class ScriptExecutionTask<S> implements Runnable {
4243
private final GameScript<S> script;
4344
private final ScriptBindings scriptBindings;
4445
private final ScriptInvocationListener scriptInvocationListener;
46+
private final boolean syncCall;
4547

4648
private final AtomicBoolean completed = new AtomicBoolean(false);
4749
private Future<?> taskFuture;
4850

4951
public ScriptExecutionTask(int taskId, GameScriptingEngine gameScriptingEngine, ScriptExecutor<S> executor,
50-
int scriptId, GameScript<S> script, ScriptBindings scriptBindings, ScriptInvocationListener scriptInvocationListener) {
52+
int scriptId, GameScript<S> script, ScriptBindings scriptBindings,
53+
ScriptInvocationListener scriptInvocationListener, boolean syncCall) {
5154
this.taskId = taskId;
5255
this.scriptingEngine = gameScriptingEngine;
5356
this.executor = executor;
5457
this.scriptId = scriptId;
5558
this.script = script;
5659
this.scriptBindings = scriptBindings;
5760
this.scriptInvocationListener = scriptInvocationListener;
61+
this.syncCall = syncCall;
5862
}
5963

6064
@Override
6165
public void run() {
6266
try {
67+
if(scriptInvocationListener != null) {
68+
if(scriptInvocationListener.callOnGameThread() && !syncCall) {
69+
final ScriptBeginNotification beginNotification = new ScriptBeginNotification(scriptInvocationListener, scriptId);
70+
scriptingEngine.scriptNotifications.offer(beginNotification);
71+
72+
while(!beginNotification.isProcessed()) {
73+
synchronized(beginNotification) {
74+
beginNotification.wait();
75+
}
76+
}
77+
} else {
78+
scriptInvocationListener.onScriptBegin(scriptId);
79+
}
80+
}
81+
6382
ScriptExecutionResult executionResult = executor.execute(scriptId, script, scriptBindings,
6483
scriptInvocationListener != null);
6584
if (scriptInvocationListener != null) {

core/src/main/java/org/mini2Dx/miniscript/core/ScriptExecutorPool.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public interface ScriptExecutorPool<S> {
3939
public int preCompileScript(String filepath, String scriptContent) throws InsufficientCompilersException;
4040

4141
public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings scriptBindings,
42-
ScriptInvocationListener invocationListener);
42+
ScriptInvocationListener invocationListener, boolean syncCall);
4343

4444
public void release(ScriptExecutor<S> executor);
4545

core/src/main/java/org/mini2Dx/miniscript/core/ScriptInvocationListener.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@
2929
* Note: All callbacks occur on a different thread from the game thread
3030
*/
3131
public interface ScriptInvocationListener {
32+
/**
33+
* Called just before a script begins execution. Note: If callOnGameThread() is true,
34+
* the script will not begin until this callback is processed on the game thread
35+
* @param scriptId The script id
36+
*/
37+
public default void onScriptBegin(int scriptId) {
38+
39+
}
40+
3241
/**
3342
* Called when a script successfully completes
3443
*
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright 2021 Viridian Software Ltd.
3+
*/
4+
package org.mini2Dx.miniscript.core.notification;
5+
6+
import org.mini2Dx.miniscript.core.ScriptInvocationListener;
7+
8+
import java.util.concurrent.atomic.AtomicBoolean;
9+
10+
public class ScriptBeginNotification implements ScriptNotification {
11+
private final AtomicBoolean processed = new AtomicBoolean(false);
12+
private final ScriptInvocationListener invocationListener;
13+
private final int scriptId;
14+
15+
public ScriptBeginNotification(ScriptInvocationListener invocationListener, int scriptId) {
16+
this.invocationListener = invocationListener;
17+
this.scriptId = scriptId;
18+
}
19+
@Override
20+
public void process() {
21+
invocationListener.onScriptBegin(scriptId);
22+
processed.set(true);
23+
24+
synchronized(this) {
25+
this.notifyAll();
26+
}
27+
}
28+
29+
public boolean isProcessed() {
30+
return processed.get();
31+
}
32+
}

core/src/test/java/org/mini2Dx/miniscript/core/AbstractGameScriptingEngineTest.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,62 @@ public boolean callOnGameThread() {
220220
Assert.assertEquals(false, gameFuture.isFutureSkipped());
221221
Assert.assertEquals(false, gameFuture.isScriptSkipped());
222222
}
223-
223+
224+
@Test
225+
public void testInvokeScriptBeginNotificationOnGameThread() throws Exception {
226+
final int expectedScriptId = scriptingEngine.compileScript(getDefaultScript());
227+
final AtomicBoolean notificationReceived = new AtomicBoolean(false);
228+
229+
scriptingEngine.invokeCompiledScript(expectedScriptId, scriptBindings, new ScriptInvocationListener() {
230+
231+
@Override
232+
public void onScriptBegin(int scriptId) {
233+
notificationReceived.set(true);
234+
}
235+
236+
@Override
237+
public void onScriptSuccess(int scriptId, ScriptExecutionResult executionResult) {
238+
if(scriptId != expectedScriptId) {
239+
scriptResult.set(ScriptResult.INCORRECT_SCRIPT_ID);
240+
scriptExecuted.set(true);
241+
} else if(!checkExpectedScriptResults(executionResult)) {
242+
scriptResult.set(ScriptResult.INCORRECT_VARIABLES);
243+
scriptExecuted.set(true);
244+
} else {
245+
scriptResult.set(ScriptResult.SUCCESS);
246+
scriptExecuted.set(true);
247+
}
248+
}
249+
250+
@Override
251+
public void onScriptSkipped(int scriptId) {
252+
scriptResult.set(ScriptResult.SKIPPED);
253+
scriptExecuted.set(true);
254+
}
255+
256+
@Override
257+
public void onScriptException(int scriptId, Exception e) {
258+
e.printStackTrace();
259+
scriptResult.set(ScriptResult.EXCEPTION);
260+
scriptExecuted.set(true);
261+
}
262+
263+
@Override
264+
public boolean callOnGameThread() {
265+
return true;
266+
}
267+
});
268+
while(!scriptExecuted.get()) {
269+
scriptingEngine.update(1f);
270+
}
271+
Assert.assertEquals(ScriptResult.SUCCESS, scriptResult.get());
272+
Assert.assertEquals(true, gameFuture.isUpdated());
273+
Assert.assertEquals(false, gameFuture.waitOccurred());
274+
Assert.assertEquals(false, gameFuture.isFutureSkipped());
275+
Assert.assertEquals(false, gameFuture.isScriptSkipped());
276+
Assert.assertEquals(true, notificationReceived.get());
277+
}
278+
224279
@Test
225280
public void testWaitForCompletion() throws Exception {
226281
final int expectedScriptId = scriptingEngine.compileScript(getWaitForCompletionScript());

core/src/test/java/org/mini2Dx/miniscript/core/ScriptExecutionTaskTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class ScriptExecutionTaskTest {
3838
public void testRunExecutesScript() {
3939
DummyScript script = new DummyScript("");
4040
ScriptExecutionTask<DummyScript> task = new ScriptExecutionTask<DummyScript>(0, new DummyGameScriptingEngine(),
41-
new DummyScriptExecutor(null), 0, new GlobalGameScript<DummyScript>(script), new ScriptBindings(), null);
41+
new DummyScriptExecutor(null), 0, new GlobalGameScript<DummyScript>(script), new ScriptBindings(), null, true);
4242
task.run();
4343
Assert.assertEquals(true, script.isExecuted());
4444
}

core/src/test/java/org/mini2Dx/miniscript/core/dummy/DummyScriptExecutorPool.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ public String getCompiledScriptPath(int scriptId) {
8484

8585
@Override
8686
public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings scriptBindings,
87-
ScriptInvocationListener invocationListener) {
87+
ScriptInvocationListener invocationListener, boolean syncCall) {
8888
ScriptExecutor<DummyScript> executor = allocateExecutor();
8989
if (executor == null) {
9090
throw new ScriptExecutorUnavailableException(scriptId);
9191
}
9292
return new ScriptExecutionTask<DummyScript>(taskId, gameScriptingEngine, executor, scriptId,
93-
scripts.get(scriptId), scriptBindings, invocationListener);
93+
scripts.get(scriptId), scriptBindings, invocationListener, syncCall);
9494
}
9595

9696
@Override

groovy/src/main/java/org/mini2Dx/miniscript/groovy/GroovyScriptExecutorPool.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public int preCompileScript(String filepath, String scriptContent) throws Insuff
9494

9595
@Override
9696
public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings scriptBindings,
97-
ScriptInvocationListener invocationListener) {
97+
ScriptInvocationListener invocationListener, boolean syncCall) {
9898
ScriptExecutor<Script> executor = allocateExecutor();
9999
if (executor == null) {
100100
throw new ScriptExecutorUnavailableException(scriptId);
@@ -104,7 +104,7 @@ public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings s
104104
throw new NoSuchScriptException(scriptId);
105105
}
106106
return new ScriptExecutionTask<Script>(taskId, gameScriptingEngine, executor, scriptId,
107-
scripts.get(scriptId), scriptBindings, invocationListener);
107+
scripts.get(scriptId), scriptBindings, invocationListener, syncCall);
108108
}
109109

110110
private ScriptExecutor<Script> allocateExecutor() {

kotlin/src/main/java/org/mini2Dx/miniscript/kotlin/KotlinScriptExecutorPool.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public int preCompileScript(String filepath, String scriptContent) throws Insuff
9898

9999
@Override
100100
public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings scriptBindings,
101-
ScriptInvocationListener invocationListener) {
101+
ScriptInvocationListener invocationListener, boolean syncCall) {
102102
ScriptExecutor<CompiledKotlinScript> executor = allocateExecutor();
103103
if (executor == null) {
104104
throw new ScriptExecutorUnavailableException(scriptId);
@@ -108,7 +108,7 @@ public ScriptExecutionTask<?> execute(int taskId, int scriptId, ScriptBindings s
108108
throw new NoSuchScriptException(scriptId);
109109
}
110110
return new ScriptExecutionTask<CompiledKotlinScript>(taskId, gameScriptingEngine, executor,
111-
scriptId, scripts.get(scriptId), scriptBindings, invocationListener);
111+
scriptId, scripts.get(scriptId), scriptBindings, invocationListener, syncCall);
112112
}
113113

114114
private ScriptExecutor<CompiledKotlinScript> allocateExecutor() {

0 commit comments

Comments
 (0)