diff --git a/backends/backend-teavm/build.gradle.kts b/backends/backend-teavm/build.gradle.kts index 1037e4d9..66202e27 100644 --- a/backends/backend-teavm/build.gradle.kts +++ b/backends/backend-teavm/build.gradle.kts @@ -25,6 +25,8 @@ dependencies { api("org.teavm:teavm-jso:${LibExt.teaVMVersion}") api("org.teavm:teavm-jso-apis:${LibExt.teaVMVersion}") api("org.teavm:teavm-jso-impl:${LibExt.teaVMVersion}") + + testImplementation("com.google.truth:truth:${LibExt.truthVersion}") } publishing { diff --git a/backends/backend-teavm/emu/com/badlogic/gdx/assets/loaders/resolvers/ResolutionFileResolverEmu.java b/backends/backend-teavm/emu/com/badlogic/gdx/assets/loaders/resolvers/ResolutionFileResolverEmu.java index 2804bd79..02eadfd8 100644 --- a/backends/backend-teavm/emu/com/badlogic/gdx/assets/loaders/resolvers/ResolutionFileResolverEmu.java +++ b/backends/backend-teavm/emu/com/badlogic/gdx/assets/loaders/resolvers/ResolutionFileResolverEmu.java @@ -49,7 +49,7 @@ public ResolutionFileResolverEmu(FileHandleResolver baseResolver, ResolutionFile @Override public FileHandle resolve(String fileName) { ResolutionFileResolver.Resolution bestDesc = choose(descriptors); - FileHandle originalHandle = new TeaFileHandle(fileName); + FileHandle originalHandle = Gdx.files.internal(fileName); FileHandle handle = baseResolver.resolve(resolve(originalHandle, bestDesc.folder)); if(!handle.exists()) handle = baseResolver.resolve(fileName); return handle; diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaApplication.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaApplication.java index 64418964..17655f54 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaApplication.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaApplication.java @@ -118,7 +118,7 @@ else if(agentInfo.isLinux()) AssetLoaderListener assetListener = new AssetLoaderListener(); input = new TeaInput(graphics.canvas); - files = new TeaFiles(preloader); + files = new TeaFiles(config, preloader); net = new TeaNet(); logger = new TeaApplicationLogger(); clipboard = new TeaClipboard(); @@ -188,8 +188,6 @@ public void handleEvent(EventWrapper evt) { }); } - // Init database - TeaFileHandle.initHandle(config); preloader.preload(config, "assets.txt"); window.requestAnimationFrame(this); diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFileHandle.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFileHandle.java index 1855d6d6..c9d951f3 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFileHandle.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFileHandle.java @@ -1,13 +1,10 @@ package com.github.xpenatan.gdx.backends.teavm; import com.badlogic.gdx.Files.FileType; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.GdxRuntimeException; import com.badlogic.gdx.utils.StreamUtils; import com.github.xpenatan.gdx.backends.teavm.filesystem.FileDB; -import com.github.xpenatan.gdx.backends.teavm.filesystem.types.InternalDBStorage; -import com.github.xpenatan.gdx.backends.teavm.filesystem.types.LocalDBStorage; import com.github.xpenatan.gdx.backends.teavm.preloader.Preloader; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -28,43 +25,20 @@ * @author xpenatan */ public class TeaFileHandle extends FileHandle { - private static InternalDBStorage internalStorage; - private static LocalDBStorage localStorage; - public final Preloader preloader; private final String file; private final FileType type; private FileDB fileDB; - public static void initHandle(TeaApplicationConfiguration config) { - if(config.useNewFileHandle) { - internalStorage = new InternalDBStorage(); - localStorage = new LocalDBStorage(); - } - } - - public TeaFileHandle(Preloader preloader, String fileName, FileType type) { + public TeaFileHandle(Preloader preloader, FileDB fileDB, String fileName, FileType type) { if((type != FileType.Internal) && (type != FileType.Classpath) && (type != FileType.Local)) { throw new GdxRuntimeException("FileType '" + type + "' Not supported in web backend"); } this.preloader = preloader; this.file = fixSlashes(fileName); this.type = type; - TeaApplicationConfiguration config = ((TeaApplication)Gdx.app).getConfig(); - if(config.useNewFileHandle) { - if(type == FileType.Local) { - fileDB = localStorage; - } - else { - // Internal and Classpath share the same storage - fileDB = internalStorage; - } - } - } - - public TeaFileHandle(String path) { - this(((TeaApplication)Gdx.app).getPreloader(), path, FileType.Internal); + this.fileDB = fileDB; } /** @return The full url to an asset, e.g. http://localhost:8080/assets/data/shotgun.ogg */ @@ -555,7 +529,7 @@ else if(type == FileType.Local) { * doesn't exist. */ public FileHandle child(String name) { - return new TeaFileHandle(preloader, (file.isEmpty() ? "" : (file + (file.endsWith("/") ? "" : "/"))) + name, + return new TeaFileHandle(preloader, fileDB, (file.isEmpty() ? "" : (file + (file.endsWith("/") ? "" : "/"))) + name, type); } @@ -563,7 +537,7 @@ public FileHandle parent() { int index = file.lastIndexOf("/"); String dir = ""; if(index > 0) dir = file.substring(0, index); - return new TeaFileHandle(preloader, dir, type); + return new TeaFileHandle(preloader, fileDB, dir, type); } public FileHandle sibling(String name) { diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFiles.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFiles.java index f05373a8..82dc2a7b 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFiles.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/TeaFiles.java @@ -3,6 +3,8 @@ import com.badlogic.gdx.Files; import com.badlogic.gdx.files.FileHandle; import com.github.xpenatan.gdx.backends.teavm.filesystem.FileDB; +import com.github.xpenatan.gdx.backends.teavm.filesystem.types.InternalDBStorage; +import com.github.xpenatan.gdx.backends.teavm.filesystem.types.LocalDBStorage; import com.github.xpenatan.gdx.backends.teavm.preloader.Preloader; /** @@ -12,38 +14,55 @@ public class TeaFiles implements Files { final Preloader preloader; - public TeaFiles(Preloader preloader) { + public InternalDBStorage internalStorage; + public LocalDBStorage localStorage; + + public TeaFiles(TeaApplicationConfiguration config, Preloader preloader) { this.preloader = preloader; + if(config.useNewFileHandle) { + this.internalStorage = new InternalDBStorage(); + this.localStorage = new LocalDBStorage(); + } } @Override public FileHandle getFileHandle(String path, FileType type) { - return new TeaFileHandle(preloader, path, type); + FileDB fileDB = null; + if(type == FileType.Internal) { + return internal(path); + } + else if(type == FileType.Classpath) { + return classpath(path); + } + else if(type == FileType.Local) { + return local(path); + } + return new TeaFileHandle(preloader, null, path, type); } @Override public FileHandle classpath(String path) { - return new TeaFileHandle(preloader, path, FileType.Classpath); + return new TeaFileHandle(preloader, internalStorage, path, FileType.Classpath); } @Override public FileHandle internal(String path) { - return new TeaFileHandle(preloader, path, FileType.Internal); + return new TeaFileHandle(preloader, internalStorage, path, FileType.Internal); } @Override public FileHandle external(String path) { - return new TeaFileHandle(preloader, path, FileType.External); + return new TeaFileHandle(preloader, null, path, FileType.External); } @Override public FileHandle absolute(String path) { - return new TeaFileHandle(preloader, path, FileType.Absolute); + return new TeaFileHandle(preloader, null, path, FileType.Absolute); } @Override public FileHandle local(String path) { - return new TeaFileHandle(preloader, path, FileType.Local); + return new TeaFileHandle(preloader, localStorage, path, FileType.Local); } @Override diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileDB.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileDB.java index 0e26649e..1ddb3784 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileDB.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileDB.java @@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.GdxRuntimeException; import com.github.xpenatan.gdx.backends.teavm.TeaApplication; import com.github.xpenatan.gdx.backends.teavm.TeaFileHandle; +import com.github.xpenatan.gdx.backends.teavm.preloader.Preloader; import java.io.ByteArrayOutputStream; import java.io.FileFilter; import java.io.FilenameFilter; @@ -80,13 +81,18 @@ public void close() throws IOException { public final FileHandle[] list(TeaFileHandle file) { // convert paths to file handles String[] paths = paths(file); - FileHandle[] files = new FileHandle[paths.length]; + FileHandle[] files = new TeaFileHandle[paths.length]; + + Preloader preloader = null; + if(Gdx.app != null) { + preloader = ((TeaApplication)Gdx.app).getPreloader(); + } for(int i = 0; i < paths.length; i++) { String path = paths[i]; if((path.length() > 0) && (path.charAt(path.length() - 1) == '/')) { path = path.substring(0, path.length() - 1); } - files[i] = new TeaFileHandle(((TeaApplication)Gdx.app).getPreloader(), path, Files.FileType.Local); + files[i] = new TeaFileHandle(preloader, this, path, file.type()); } return files; } diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileData.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileData.java index f01c7790..0ba40b4b 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileData.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/FileData.java @@ -5,27 +5,26 @@ public class FileData { public static final int TYPE_DIRECTORY = 1; public static final int TYPE_FILE = 2; - private final String name; + private final String path; private final byte[] bytes; private final int type; - public FileData(String name) { - this(name, TYPE_DIRECTORY, null); + public FileData(String path) { + this(path, TYPE_DIRECTORY, null); } - public FileData(String name, byte[] bytes) { - this(name, TYPE_FILE, bytes); + public FileData(String path, byte[] bytes) { + this(path, TYPE_FILE, bytes); } public FileData(String name, int type, byte[] bytes) { - this.name = name; + this.path = name; this.bytes = bytes; this.type = type; } - - public String getName() { - return name; + public String getPath() { + return path; } public byte[] getBytes() { @@ -39,4 +38,8 @@ public boolean isDirectory() { public int getType() { return type; } + + public int getBytesSize() { + return bytes != null ? bytes.length : 0; + } } \ No newline at end of file diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorage.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorage.java index c675adb7..dd9552b2 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorage.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorage.java @@ -6,8 +6,6 @@ import com.badlogic.gdx.utils.GdxRuntimeException; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.OrderedMap; -import com.github.xpenatan.gdx.backends.teavm.TeaApplication; -import com.github.xpenatan.gdx.backends.teavm.TeaApplicationConfiguration; import com.github.xpenatan.gdx.backends.teavm.TeaFileHandle; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -21,12 +19,6 @@ public class MemoryFileStorage extends FileDB { public MemoryFileStorage() { fileMap = new OrderedMap<>(); - setupIndexedDB(); - } - - private void setupIndexedDB() { - TeaApplication teaApplication = (TeaApplication)Gdx.app; - TeaApplicationConfiguration config = teaApplication.getConfig(); } @Override @@ -40,7 +32,6 @@ public InputStream read(TeaFileHandle file) { catch(RuntimeException e) { // Something corrupted: we remove it & re-throw the error remove(path); - removeFile(path); throw e; } } @@ -60,14 +51,36 @@ public byte[] readBytes(TeaFileHandle file) { protected void writeInternal(TeaFileHandle file, byte[] data, boolean append, int expectedLength) { String path = fixPath(file.path()); - FileData fileData = new FileData(path, data); - put(path, fileData); - putFile(path, fileData); + byte[] newBytes = null; + FileData oldData = fileMap.get(path); + if(append) { + if(oldData == null) { + newBytes = data; + } + else { + byte[] oldBytes = oldData.getBytes(); + int newSize = data.length + oldBytes.length; + newBytes = new byte[newSize]; + for(int i = 0; i < oldBytes.length; i++) { + newBytes[i] = oldBytes[i]; + } + for(int i = oldBytes.length, j = 0; i < newSize; i++, j++) { + newBytes[i] = data[j]; + } + } + } + else { + newBytes = data; + } + + putFileInternal(path, newBytes); FileHandle cur = file.parent(); while(!isRootFolder(cur)) { String parentPath = fixPath(cur.path()); - putFolder(parentPath); + if(!fileMap.containsKey(parentPath)) { + putFolderInternal(parentPath); + } cur = cur.parent(); } } @@ -95,11 +108,13 @@ public boolean isDirectory(TeaFileHandle file) { @Override public void mkdirs(TeaFileHandle file) { String path = fixPath(file.path()); - putFolder(path); + putFolderInternal(path); FileHandle cur = file.parent(); while(!isRootFolder(cur)) { String parentPath = fixPath(cur.path()); - putFolder(parentPath); + if(!fileMap.containsKey(parentPath)) { + putFolderInternal(parentPath); + } cur = cur.parent(); } } @@ -126,7 +141,6 @@ public boolean delete(TeaFileHandle file) { return false; } if(remove(path) != null) { - removeFile(path); return true; } } @@ -146,16 +160,11 @@ public boolean deleteDirectory(TeaFileHandle file) { } if(remove(path) != null) { - removeFile(path); - FileHandle[] list = file.list(); // Get all children paths and delete them all String[] paths = getAllChildrenAndSiblings(file); for(int i = 0; i < paths.length; i++) { String childOrSiblingPath = fixPath(paths[i]); boolean rem = remove(childOrSiblingPath) != null; - if(rem) { - removeFile(childOrSiblingPath); - } } return true; } @@ -180,8 +189,7 @@ public void rename(TeaFileHandle source, TeaFileHandle target) { String targetPath = fixPath(target.path()); FileData data = remove(sourcePath); if(data != null) { - put(targetPath, data); - renameFile(sourcePath, targetPath, data); + putFileInternal(targetPath, data.getBytes()); } } @@ -190,6 +198,33 @@ public String getPath() { return ""; } + public String debugAllFiles() { + String text = ""; + text += println("####### Start File: " + fileMap.size + "\n"); + ObjectMap.Entries it = fileMap.iterator(); + while(it.hasNext) { + ObjectMap.Entry next = it.next(); + FileData value = next.value; + String name = ""; + String key = next.key; + key = "\"" + key + "\""; + if(!value.getPath().equals(next.key)) { + name = " Name: " + value.getPath(); + } + text += println("Key: " + key + name + " Type: " + value.getType() + " Bytes: " + value.getBytesSize()+ "\n"); + } + text += println("####### End File"); + return text; + } + + public void printAllFiles() { + System.out.println(debugAllFiles()); + } + + private String println(String value) { + return value; + } + private boolean isRootFolder(FileHandle cur) { String path = fixPath(cur.path()); if(path.isEmpty() || path.equals(".") || path.equals("/") || path.equals("./")) { @@ -209,38 +244,57 @@ private String[] getAllChildren(FileHandle file) { } private String[] list(FileHandle file, boolean equals) { - String dirPath = fixPath(file.path()); - + String dir = fixPath(file.path()); boolean isRoot = isRootFolder(file); - - String dir = fixPath(dirPath); - ObjectMap.Entries it = fileMap.iterator(); - while(it.hasNext) { - ObjectMap.Entry next = it.next(); - String path = fixPath(next.key); - - FileHandle parent = getFilePath(path).parent(); - String parentPath = fixPath(parent.path()); - - boolean isChildParentRoot = isRootFolder(parent); - - // Only add path if parent is dir - if(isChildParentRoot && isRoot) { - tmpPaths.add(path); - } - else { - if(equals) { - if(parentPath.equals(dir)) { + if(debug) { + System.out.println("### START LIST ### " + isRoot + " DIR: " + dir); + } +// if(file.exists()) { + ObjectMap.Entries it = fileMap.iterator(); + while(it.hasNext) { + ObjectMap.Entry next = it.next(); + String path = fixPath(next.key); + + FileHandle parent = getFilePath(path).parent(); + String parentPath = fixPath(parent.path()); + + boolean isChildParentRoot = isRootFolder(parent); + + // Only add path if parent is dir + if(isRoot) { + if(isChildParentRoot) { + if(debug) { + System.out.println("LIST ROOD ADD: " + path); + } tmpPaths.add(path); } } else { - if(parentPath.startsWith(dir)) { - tmpPaths.add(path); + if(equals) { + if(parentPath.equals(dir)) { + if(debug) { + System.out.println("LIST EQUAL ADD: PARENT PATH: " + parentPath); + System.out.println("LIST EQUAL ADD: PATH: " + path); + } + tmpPaths.add(path); + } + } + else { + if(parentPath.startsWith(dir)) { + if(debug) { + System.out.println("LIST STARTWITH ADD: PARENT PATH: " + parentPath); + System.out.println("LIST STARTWITH ADD: PATH: " + path); + } + tmpPaths.add(path); + } } } } +// } + if(debug) { + System.out.println("### END LIST ###"); } + tmpPaths.sort(); String[] str = new String[tmpPaths.size]; for(int i = 0; i < tmpPaths.size; i++) { @@ -254,21 +308,10 @@ private String[] list(FileHandle file, boolean equals) { return str; } - private void putFolder(String path) { - FileData fileData = new FileData(path); - put(path, fileData); - putFile(path, fileData); - } - protected FileHandle getFilePath(String path) { return Gdx.files.internal(path); } - protected void renameFile(String sourcePath, String targetPath, FileData data) { - removeFile(sourcePath); - putFile(targetPath, data); - } - protected void putFile(String key, FileData data) { } @@ -276,35 +319,56 @@ protected void removeFile(String key) { } final protected FileData get(String path) { - FileData data = fileMap.get(path); + FileData fileData = fileMap.get(path); if(debug) { - System.out.println(getClass().getSimpleName() + " GET FILE: " + (data != null) + " Path: " + path); + String type = fileData != null && fileData.isDirectory() ? " GET FOLDER: " : " GET FILE: "; + System.out.println(getClass().getSimpleName() + type + (fileData != null) + " Path: " + path); } - return data; + return fileData; } - final protected void put(String path, FileData fileData) { + final public void putFileInternal(String path, byte[] bytes) { if(debug) { System.out.println(getClass().getSimpleName() + " PUT FILE: " + path); } if(path.isEmpty() || path.equals(".") || path.equals("/") || path.equals("./")) { throw new GdxRuntimeException("Cannot put an empty folder name"); } + FileData fileData = new FileData(path, bytes); fileMap.put(path, fileData); + putFile(path, fileData); } - final protected FileData remove(String path) { - FileData data = fileMap.remove(path); + final public void putFolderInternal(String path) { if(debug) { - System.out.println(getClass().getSimpleName() + " REMOVE FILE: " + (data != null) + " Path: " + path); + System.out.println(getClass().getSimpleName() + " PUT FOLDER: " + path); + } + if(path.isEmpty() || path.equals(".") || path.equals("/") || path.equals("./")) { + throw new GdxRuntimeException("Cannot put an empty folder name"); } - return data; + FileData fileData = new FileData(path); + fileMap.put(path, new FileData(path)); + putFile(path, fileData); } - final protected boolean containsKey(String path) { - boolean flag = fileMap.containsKey(path); + final public FileData remove(String path) { + FileData fileData = fileMap.remove(path); if(debug) { - System.out.println(getClass().getSimpleName() + " CONTAINS FILE: " + flag + " Path: " + path); + String type = fileData != null && fileData.isDirectory() ? " REMOVE FOLDER: " : " REMOVE FILE: "; + System.out.println(getClass().getSimpleName() + type + (fileData != null) + " Path: " + path); + } + if(fileData != null) { + removeFile(path); + } + return fileData; + } + + final public boolean containsKey(String path) { + FileData fileData = fileMap.get(path); + boolean flag = fileData != null; + if(debug) { + String type = fileData != null && fileData.isDirectory() ? " CONTAINS FOLDER: " : " CONTAINS FILE: "; + System.out.println(getClass().getSimpleName() + type + flag + " Path: " + path); } return flag; } @@ -322,6 +386,9 @@ final protected String fixPath(String path) { if(!path.startsWith("/")) { path = "/" + path; } + if(!path.endsWith("/")) { + path = path + "/"; + } return path; } } \ No newline at end of file diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/types/LocalDBStorage.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/types/LocalDBStorage.java index a1f54af5..e9f4baee 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/types/LocalDBStorage.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/filesystem/types/LocalDBStorage.java @@ -35,6 +35,9 @@ public LocalDBStorage() { private void setupIndexedDB() { TeaApplication teaApplication = (TeaApplication)Gdx.app; + if(teaApplication == null) { + return; + } TeaApplicationConfiguration config = teaApplication.getConfig(); teaApplication.delayInitCount++; @@ -87,22 +90,17 @@ protected FileHandle getFilePath(String path) { } @Override - protected void renameFile(String sourcePath, String targetPath, FileData data) { - removeFile(sourcePath); - putFile(targetPath, data); - } - - @Override - protected void putFile(String key, FileData data) { + protected void putFile(String key, FileData fileData) { if(debug) { - System.out.println("PUT FILE DB: " + key); + String type = fileData != null && fileData.isDirectory() ? "PUT FOLDER DB: " : "PUT FILE DB: "; + System.out.println(type + key); } IDBTransaction transaction = dataBase.transaction(KEY_OBJECT_STORE, "readwrite"); IDBObjectStore objectStore = transaction.objectStore(KEY_OBJECT_STORE); - IndexedDBFileData dbFileData = IndexedDBFileData.create(data.getType(), new JSDate()); - if(!data.isDirectory()) { - dbFileData.setContents(data.getBytes()); + IndexedDBFileData dbFileData = IndexedDBFileData.create(fileData.getType(), new JSDate()); + if(!fileData.isDirectory()) { + dbFileData.setContents(fileData.getBytes()); } IDBRequest request = objectStore.put(dbFileData, getJSString(key)); request.setOnError(() -> { @@ -134,17 +132,16 @@ private void readAllFilesAsync(TeaApplication teaApplication) { JSObject value = cursor.getValue(); IndexedDBFileData dbFileData = getFileData(value); int type = dbFileData.getType(); - FileData fileData = null; if(type == FileData.TYPE_DIRECTORY) { - fileData = new FileData(key); + putFolderInternal(key); } else { Int8ArrayWrapper contents = dbFileData.getContents(); byte[] bytes = TypedArrays.toByteArray(contents); - fileData = new FileData(key, type, bytes); + putFileInternal(key, bytes); } - put(key, fileData); + cursor.doContinue(); } teaApplication.delayInitCount--; diff --git a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/preloader/Preloader.java b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/preloader/Preloader.java index 55570b6c..7b4c9957 100644 --- a/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/preloader/Preloader.java +++ b/backends/backend-teavm/src/main/java/com/github/xpenatan/gdx/backends/teavm/preloader/Preloader.java @@ -465,22 +465,22 @@ private FileHandle[] getMatchedAssetFiles(FilePathFilter filter) { Array files = new Array<>(); for(String file : texts.keys()) { if(filter.accept(file)) { - files.add(new TeaFileHandle(this, file, FileType.Internal)); + files.add(new TeaFileHandle(this, null, file, FileType.Internal)); } } for(String file : images.keys()) { if(filter.accept(file)) { - files.add(new TeaFileHandle(this, file, FileType.Internal)); + files.add(new TeaFileHandle(this, null, file, FileType.Internal)); } } for(String file : binaries.keys()) { if(filter.accept(file)) { - files.add(new TeaFileHandle(this, file, FileType.Internal)); + files.add(new TeaFileHandle(this, null, file, FileType.Internal)); } } for(String file : audio.keys()) { if(filter.accept(file)) { - files.add(new TeaFileHandle(this, file, FileType.Internal)); + files.add(new TeaFileHandle(this, null, file, FileType.Internal)); } } FileHandle[] filesArray = new FileHandle[files.size]; diff --git a/backends/backend-teavm/src/test/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorageTest.java b/backends/backend-teavm/src/test/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorageTest.java new file mode 100644 index 00000000..f12b2c0d --- /dev/null +++ b/backends/backend-teavm/src/test/java/com/github/xpenatan/gdx/backends/teavm/filesystem/MemoryFileStorageTest.java @@ -0,0 +1,122 @@ +package com.github.xpenatan.gdx.backends.teavm.filesystem; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.files.FileHandle; +import com.github.xpenatan.gdx.backends.teavm.TeaApplicationConfiguration; +import com.github.xpenatan.gdx.backends.teavm.TeaFileHandle; +import com.github.xpenatan.gdx.backends.teavm.TeaFiles; +import com.github.xpenatan.gdx.backends.teavm.filesystem.types.InternalDBStorage; +import com.google.common.truth.Truth; +import org.junit.Before; +import org.junit.Test; + +public class MemoryFileStorageTest { + + private InternalDBStorage internalStorage; + + @Before + public void setUp() { + TeaApplicationConfiguration config = new TeaApplicationConfiguration(""); + TeaFiles teaFiles = new TeaFiles(config, null) { + @Override + public FileHandle local(String path) { + return new TeaFileHandle(null, internalStorage, path, FileType.Local); + } + }; + Gdx.files = teaFiles; + internalStorage = teaFiles.internalStorage; + internalStorage.debug = false; + } + + @Test + public void test_add_remove_01() { + // Have 2 folders and another as a child of the second folder. + // Delete the first folder. + + FileHandle A = Gdx.files.local("New folder"); + FileHandle B = Gdx.files.local("New folder(2)"); + FileHandle BA = B.child("New folder(2)/New folder"); + + A.mkdirs(); + B.mkdirs(); + BA.mkdirs(); + + System.out.println("FILES BEFORE: "); + internalStorage.printAllFiles(); + + boolean b = A.deleteDirectory(); + + System.out.println("FILES AFTER: "); + internalStorage.printAllFiles(); + + Truth.assertThat(B.exists()).isTrue(); + Truth.assertThat(BA.exists()).isTrue(); + } + + @Test + public void test_add_remove_02() { + // Have 2 folders and another as a child of the second folder. + // Delete the first folder. + + FileHandle A = Gdx.files.local("A"); + FileHandle B = Gdx.files.local("B"); + FileHandle BA = B.child("A"); + + A.mkdirs(); + B.mkdirs(); + BA.mkdirs(); + + boolean b = A.deleteDirectory(); + + Truth.assertThat(B.exists()).isTrue(); + Truth.assertThat(BA.exists()).isTrue(); + } + + @Test + public void test_move_from_A_to_B() { + // Have 2 folders and another as a child of the second folder. + // Delete the first folder. + + FileHandle A = Gdx.files.local("A"); + FileHandle AA = A.child("AA"); + FileHandle AB = A.child("AB"); + FileHandle ABA = AB.child("ABA"); + FileHandle ABAX = ABA.child("file.txt"); + FileHandle AC = A.child("AC"); + FileHandle B = Gdx.files.local("B"); + + A.mkdirs(); + AA.mkdirs(); + AB.mkdirs(); + ABA.mkdirs(); + AC.mkdirs(); + B.mkdirs(); + + ABAX.writeString("Text", false); + ABAX.writeString("One", true); + + Truth.assertThat(A.exists()).isTrue(); + Truth.assertThat(B.exists()).isTrue(); + Truth.assertThat(AA.exists()).isTrue(); + Truth.assertThat(AB.exists()).isTrue(); + Truth.assertThat(ABA.exists()).isTrue(); + Truth.assertThat(ABAX.exists()).isTrue(); + Truth.assertThat(AC.exists()).isTrue(); + + System.out.println("FILES BEFORE: "); + internalStorage.printAllFiles(); + + A.moveTo(B); + + System.out.println("FILES AFTER: "); + internalStorage.printAllFiles(); + + Truth.assertThat(A.exists()).isFalse(); + Truth.assertThat(B.exists()).isTrue(); + Truth.assertThat(AA.exists()).isFalse(); + Truth.assertThat(AB.exists()).isFalse(); + Truth.assertThat(ABA.exists()).isFalse(); + Truth.assertThat(ABAX.exists()).isFalse(); + Truth.assertThat(AC.exists()).isFalse(); + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 8503961c..b1608125 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -16,6 +16,8 @@ object LibExt { const val jettyVersion = "11.0.13" const val aiVersion = "1.8.2" + + const val truthVersion = "1.4.2" } private fun getVersion(): String {