Skip to content

Commit

Permalink
Moved game file opfs import into a web worker.
Browse files Browse the repository at this point in the history
  • Loading branch information
lanceewing committed Apr 10, 2024
1 parent 285ff87 commit 59326b6
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
15 changes: 14 additions & 1 deletion html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import com.agifans.agile.ui.ImportTypeResponseHandler;
import com.agifans.agile.ui.OpenFileResponseHandler;
import com.agifans.agile.ui.TextInputResponseHandler;
import com.agifans.agile.worker.Worker;
import com.akjava.gwt.jszip.JSFile;
import com.akjava.gwt.jszip.JSZip;
import com.badlogic.gdx.Gdx;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.typedarrays.shared.ArrayBuffer;
import com.google.gwt.typedarrays.shared.Int8Array;
Expand All @@ -29,6 +31,8 @@ public class GwtDialogHandler implements DialogHandler {

private GameFileMapEncoder gameFileMapEncoder;

private Worker worker;

private boolean dialogOpen;

/**
Expand All @@ -37,6 +41,10 @@ public class GwtDialogHandler implements DialogHandler {
public GwtDialogHandler() {
gameFileMapEncoder = new GameFileMapEncoder();
opfsGameFiles = new OPFSGameFiles();

// The same worker script is used for importing game data as is used for
// the interpreter but they are run in two different running web workers.
worker = Worker.create("worker/worker.nocache.js");
}

@Override
Expand Down Expand Up @@ -215,7 +223,8 @@ public void onFileResultsReady(GwtOpenFileResult[] openFileResultArray) {

// Use GameFileMapEncoder to encode to single ArrayBuffer and store in OPFS.
ArrayBuffer fullGameBuffer = gameFileMapEncoder.encodeGameFileMap(gameFilesMap);
opfsGameFiles.writeGameFilesData(opfsDirectoryName, fullGameBuffer);
worker.postArrayBufferAndObject(
"ImportGame", fullGameBuffer, createDirectoryNameObject(opfsDirectoryName));

openFileResponseHandler.openFileResult(true, opfsDirectoryName, gameName, detection.gameId);

Expand All @@ -234,6 +243,10 @@ public void onFileResultsReady(GwtOpenFileResult[] openFileResultArray) {
});
}

private native JavaScriptObject createDirectoryNameObject(String directoryName)/*-{
return { directoryName: directoryName };
}-*/;

private final native String slugify(String str)/*-{
return String(str)
.normalize('NFKD')
Expand Down
14 changes: 13 additions & 1 deletion html/src/main/java/com/agifans/agile/worker/AgileWebWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.agifans.agile.gwt.GwtUserInput;
import com.agifans.agile.gwt.GwtVariableData;
import com.agifans.agile.gwt.GwtWavePlayer;
import com.agifans.agile.gwt.OPFSGameFiles;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.typedarrays.shared.ArrayBuffer;
import com.google.gwt.webworker.client.DedicatedWorkerEntryPoint;
Expand Down Expand Up @@ -72,6 +73,11 @@ public class AgileWebWorker extends DedicatedWorkerEntryPoint implements Message
*/
private Interpreter interpreter;

/**
* Used to store game data files.
*/
private OPFSGameFiles opfsGameFiles;

/**
* Incoming messages from the UI thread are for two purposes: One is to set things
* up, and then once both sides are up and running, the UI thread then starts sending
Expand All @@ -88,6 +94,12 @@ public void onMessage(MessageEvent event) {
JavaScriptObject eventObject = event.getDataAsObject();

switch (getEventType(eventObject)) {
case "ImportGame":
ArrayBuffer importGameDataBuffer = getArrayBuffer(eventObject);
String opfsDirectionName = getNestedString(eventObject, "directoryName");
opfsGameFiles.writeGameFilesData(opfsDirectionName, importGameDataBuffer);
break;

case "Initialise":
JavaScriptObject keyPressQueueSAB = getNestedObject(eventObject, "keyPressQueueSAB");
JavaScriptObject keysSAB = getNestedObject(eventObject, "keysSAB");
Expand All @@ -106,7 +118,6 @@ public void onMessage(MessageEvent event) {
GameFileMapEncoder gameFileMapDecoder = new GameFileMapEncoder();
gameLoader = new GwtGameLoader(pixelData);
Game game = gameLoader.loadGame(gameFileMapDecoder.decodeGameFileMap(gameDataBuffer));
// TODO: This won't work for fan games that haven't set the game ID.
savedGameStore.initialise(game.gameId);
interpreter = new Interpreter(
game, userInput, wavePlayer, savedGameStore,
Expand Down Expand Up @@ -166,6 +177,7 @@ protected final void setOnMessage(MessageHandler messageHandler) {
@Override
public void onWorkerLoad() {
this.scope = DedicatedWorkerGlobalScope.get();
this.opfsGameFiles = new OPFSGameFiles();

this.importScript("/opfs-saved-games.js");

Expand Down
12 changes: 12 additions & 0 deletions html/src/main/java/com/agifans/agile/worker/Worker.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ public final native void postArrayBuffer(String name, ArrayBuffer buffer) /*-{
this.postMessage({name: name, buffer: buffer}, [buffer]);
}-*/;

/**
* This method can be used to transfer an ArrayBuffer along with a normal JavaScript
* object in the same message.
*
* @param name The name of the object. Used for identification of the object.
* @param buffer The JS ArrayByffer to send in the postMessage call.
* @param object The normal JavaScript object to send with the ArrayBuffer.
*/
public final native void postArrayBufferAndObject(String name, ArrayBuffer buffer, JavaScriptObject object) /*-{
this.postMessage({name: name, buffer: buffer, object: object}, [buffer]);
}-*/;

private static void onMessageImpl(MessageHandler messageHandler, MessageEvent event) {
UncaughtExceptionHandler ueh = GWT.getUncaughtExceptionHandler();
if (ueh != null) {
Expand Down

0 comments on commit 59326b6

Please sign in to comment.