diff --git a/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java b/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java index 403ab77..57f9899 100644 --- a/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java +++ b/html/src/main/java/com/agifans/agile/gwt/GwtDialogHandler.java @@ -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; @@ -29,6 +31,8 @@ public class GwtDialogHandler implements DialogHandler { private GameFileMapEncoder gameFileMapEncoder; + private Worker worker; + private boolean dialogOpen; /** @@ -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 @@ -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); @@ -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') diff --git a/html/src/main/java/com/agifans/agile/worker/AgileWebWorker.java b/html/src/main/java/com/agifans/agile/worker/AgileWebWorker.java index ed19336..82969eb 100644 --- a/html/src/main/java/com/agifans/agile/worker/AgileWebWorker.java +++ b/html/src/main/java/com/agifans/agile/worker/AgileWebWorker.java @@ -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; @@ -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 @@ -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"); @@ -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, @@ -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"); diff --git a/html/src/main/java/com/agifans/agile/worker/Worker.java b/html/src/main/java/com/agifans/agile/worker/Worker.java index cbfad55..bd9b88d 100644 --- a/html/src/main/java/com/agifans/agile/worker/Worker.java +++ b/html/src/main/java/com/agifans/agile/worker/Worker.java @@ -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) {