From 31914ff6afbd35f885eca0bab97510590f44e689 Mon Sep 17 00:00:00 2001 From: Robert Vokac Date: Fri, 9 Aug 2024 22:03:33 +0200 Subject: [PATCH] Added storage classes - work in progress --- .../java/com/openeggbert/storage/Storage.java | 93 +++++ .../storage/StorageImplementationLoader.java | 64 ++++ .../storage/filesystem/AndroidStorage.java | 31 ++ .../filesystem/DesktopAndroidStorage.java | 124 +++++++ .../storage/filesystem/DesktopStorage.java | 31 ++ .../openeggbert/storage/map/MapFileType.java | 46 +++ .../openeggbert/storage/map/MapStorage.java | 327 ++++++++++++++++++ .../storage/map/MapStorageCompression.java | 28 ++ .../storage/map/MemoryStorage.java | 39 +++ .../storage/map/SimpleJavaMap.java | 93 +++++ .../storage/map/SimpleLocalStorageMap.java | 99 ++++++ .../openeggbert/storage/map/SimpleMap.java | 50 +++ .../openeggbert/storage/map/WebGLStorage.java | 40 +++ .../openeggbert/utils/OpenEggbertUtils.java | 30 +- .../DebuggingAssetsTxt.java} | 6 +- .../debugging/StorageCommandWrapper.java | 203 +++++++++++ 16 files changed, 1294 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/com/openeggbert/storage/Storage.java create mode 100644 core/src/main/java/com/openeggbert/storage/StorageImplementationLoader.java create mode 100644 core/src/main/java/com/openeggbert/storage/filesystem/AndroidStorage.java create mode 100644 core/src/main/java/com/openeggbert/storage/filesystem/DesktopAndroidStorage.java create mode 100644 core/src/main/java/com/openeggbert/storage/filesystem/DesktopStorage.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/MapFileType.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/MapStorage.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/MapStorageCompression.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/MemoryStorage.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/SimpleJavaMap.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/SimpleLocalStorageMap.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/SimpleMap.java create mode 100644 core/src/main/java/com/openeggbert/storage/map/WebGLStorage.java rename lwjgl3/src/main/java/com/openeggbert/lwjgl3/{TestAssetsTxt.java => debugging/DebuggingAssetsTxt.java} (99%) create mode 100644 lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/StorageCommandWrapper.java diff --git a/core/src/main/java/com/openeggbert/storage/Storage.java b/core/src/main/java/com/openeggbert/storage/Storage.java new file mode 100644 index 0000000..113e3d0 --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/Storage.java @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage; + +import com.badlogic.gdx.Application; +import java.util.List; + +/** + * + * @author robertvokac + */ +public interface Storage { + + Application.ApplicationType getApplicationType(); + + public String cd(String path); + + default String cd() { + mkdir("home"); + cd("home"); + mkdir("openeggbert"); + cd("openeggbert"); + return ""; + } + + public String mkdir(String name); + default String mkdir(String... name) { + + for(String n:name) { + String result = mkdir(n); + if(!result.isEmpty()) { + return result; + } + } + return ""; + } + + public String pwd(); + + public List ls(String workingDirectory); + + default List ls() { + return ls(pwd()); + } + + public int depth(String path); + + default int depth() { + return depth(pwd()); + } + + public String touch(String name); + + public boolean rm(String name); + + public String cp(String source, String target); + + public String mv(String source, String target); + + public String readtext(String name); + + public byte[] readbin(String name); + + public String savetext(String name, String text); + + public String savebin(String name, byte[] data); + + public boolean exists(String name); + + public boolean isfile(String name); + + public boolean isdir(String name); + + public String debug(); + +} diff --git a/core/src/main/java/com/openeggbert/storage/StorageImplementationLoader.java b/core/src/main/java/com/openeggbert/storage/StorageImplementationLoader.java new file mode 100644 index 0000000..14a852e --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/StorageImplementationLoader.java @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage; + +import com.openeggbert.storage.map.WebGLStorage; +import com.openeggbert.storage.map.MemoryStorage; +import com.openeggbert.storage.filesystem.AndroidStorage; +import com.openeggbert.storage.filesystem.DesktopStorage; +import com.badlogic.gdx.Application; +import com.badlogic.gdx.Gdx; +import com.openeggbert.entity.common.OpenEggbertException; + +/** + * + * @author robertvokac + */ +public class StorageImplementationLoader { + + private StorageImplementationLoader() { + //Not meant to be instantiated. + } + private static Storage storage = null; + + public static Storage getStorage() { + final Application.ApplicationType type = Gdx.app.getType(); + if (storage == null) { + storage = new MemoryStorage(); + } + if (storage == null) { + + if (type == Application.ApplicationType.Desktop) { + storage = new DesktopStorage(); + } + if (type == Application.ApplicationType.Android) { + storage = new AndroidStorage(); + } + if (type == Application.ApplicationType.WebGL) { + storage = new WebGLStorage(); + } + } + if (storage == null) { + throw new OpenEggbertException("Platform is not supported: " + type); + } + return storage; + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/filesystem/AndroidStorage.java b/core/src/main/java/com/openeggbert/storage/filesystem/AndroidStorage.java new file mode 100644 index 0000000..2815f1f --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/filesystem/AndroidStorage.java @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.filesystem; + +/** + * + * @author robertvokac + */ +public class AndroidStorage extends DesktopAndroidStorage { + + public AndroidStorage() { + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/filesystem/DesktopAndroidStorage.java b/core/src/main/java/com/openeggbert/storage/filesystem/DesktopAndroidStorage.java new file mode 100644 index 0000000..e253e5c --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/filesystem/DesktopAndroidStorage.java @@ -0,0 +1,124 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.filesystem; + +import com.badlogic.gdx.Application; +import com.openeggbert.storage.Storage; +import java.util.List; + +/** + * + * @author robertvokac + */ +public abstract class DesktopAndroidStorage implements Storage { + + public DesktopAndroidStorage() { + } + + @Override + public Application.ApplicationType getApplicationType() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String cd(String path) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String mkdir(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String pwd() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public List ls(String path) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public int depth(String path) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String touch(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean rm(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String cp(String source, String target) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String mv(String source, String target) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String readtext(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public byte[] readbin(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String savetext(String name, String text) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String savebin(String name, byte[] data) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean exists(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean isfile(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public boolean isdir(String name) { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } + + @Override + public String debug() { + throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody + } +} diff --git a/core/src/main/java/com/openeggbert/storage/filesystem/DesktopStorage.java b/core/src/main/java/com/openeggbert/storage/filesystem/DesktopStorage.java new file mode 100644 index 0000000..13b6b49 --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/filesystem/DesktopStorage.java @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.filesystem; + +/** + * + * @author robertvokac + */ +public class DesktopStorage extends DesktopAndroidStorage { + + public DesktopStorage() { + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/map/MapFileType.java b/core/src/main/java/com/openeggbert/storage/map/MapFileType.java new file mode 100644 index 0000000..387cf94 --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/MapFileType.java @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import com.openeggbert.entity.common.OpenEggbertException; + +/** + * + * @author robertvokac + */ +public enum MapFileType { + FILE, DIRECTORY; + + public static MapFileType ofKey(String key, SimpleMap map) { + if (!map.contains(key)) { + throw new OpenEggbertException("Map does not contain key: " + key); + } + String value = map.getString(key); + if (value.startsWith(FILE.name())) { + return FILE; + } + if (value.startsWith(DIRECTORY.name())) { + return DIRECTORY; + } + throw new OpenEggbertException("Unsupported MapFileType for key in the map: " + key); + + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/map/MapStorage.java b/core/src/main/java/com/openeggbert/storage/map/MapStorage.java new file mode 100644 index 0000000..cb3eee1 --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/MapStorage.java @@ -0,0 +1,327 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import com.badlogic.gdx.Application; +import com.badlogic.gdx.Gdx; +import com.openeggbert.entity.common.OpenEggbertException; +import com.openeggbert.storage.Storage; +import com.openeggbert.utils.OpenEggbertUtils; +import java.util.List; +import java.util.stream.Collectors; + +/** + * + * @author robertvokac + */ +public class MapStorage implements Storage { + + private final SimpleMap map; + + private final MapStorageCompression mapStorageCompression; + public MapStorage(SimpleMap mapIn) { + this(mapIn, MapStorageCompression.NONE); + } + public MapStorage(SimpleMap mapIn, MapStorageCompression mapStorageCompressionIn) { + this.map = mapIn; + this.mapStorageCompression = mapStorageCompressionIn; + mkdir("/"); + + } + + private String workingDirectory = "/"; + + @Override + public Application.ApplicationType getApplicationType() { + return null; + } + + private String convertToAbsolutePathIfNeeded(String path) { + if (path.startsWith(SLASH)) { + return path; + } + + return workingDirectory + (workingDirectory.equals("/") ? "" : SLASH) + path; + } + + @Override + public String cd(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + + if (!exists(path)) { + final String msg = "Path does not exist: " + path; + logError(msg); + return msg; + } + if (!isdir(path)) { + final String msg = "Path is not directory: " + path; + logError(msg); + return msg; + } + + workingDirectory = absolutePath; + return ""; + } + private static final String SLASH = "/"; + + private void logError(String msg) { + Application app = Gdx.app; + if(app != null) Gdx.app.error(getClass().getName(), msg); + } + + + @Override + public String mkdir(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + final String parentPath = getParentPath(absolutePath); + if (!path.equals(SLASH) && !exists(parentPath)) { + var msg = "Cannot create new directory, because parent path does not exist: " + parentPath; + logError(msg); + return msg; + } + if (!path.equals(SLASH) && !isdir(parentPath)) { + var msg = "Cannot create new directory, because parent path is not directory: " + parentPath; + logError(msg); + return msg; + } + if (exists(absolutePath)) { + var msg = "Cannot create new directory, because path already exists: " + absolutePath; + logError(msg); + return msg; + } + map.putString(absolutePath, MapFileType.DIRECTORY + EIGHT_COLONS); + + return ""; + + } + private static final String EIGHT_COLONS = "::::::::"; + + private static String getParentPath(String path) { + if (path == null) { + throw new OpenEggbertException("path is null"); + } + if (path.trim().isEmpty()) { + throw new OpenEggbertException("path is empty"); + } + + if (path.equals("/")) { + return path; + } + String[] array = path.split(SLASH); + if (array.length == 2) { + return SLASH; + } + return path.substring(0, path.length() - 1 - array[array.length - 1].length()); + } + + @Override + public String pwd() { + return workingDirectory; + } + + @Override + public int depth(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + if (absolutePath.equals(SLASH)) { + return 0; + } + String[] array = absolutePath.split(SLASH); + return array.length -1; + } + + @Override + public List ls(String path) { + int currentDepth = depth(path); + return map + .keyList() + .stream() + .filter(key -> key.startsWith(workingDirectory)) + .filter(key -> depth(key) == (currentDepth + 1)) + .collect(Collectors.toList()); + } + + @Override + public String touch(String path) { + return touch(path, ""); + } + + public String touch(String path, String content) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + final String parentPath = getParentPath(absolutePath); + if (!exists(parentPath)) { + var msg = "Cannot create new file, because parent path does not exist: " + parentPath; + logError(msg); + return msg; + } + if (!isdir(parentPath)) { + var msg = "Cannot create new file, because parent path is not directory: " + parentPath; + logError(msg); + return msg; + } + if (exists(absolutePath)) { + var msg = "Cannot create new file, because path already exists: " + absolutePath; + logError(msg); + return msg; + } + map.putString(absolutePath, MapFileType.FILE + EIGHT_COLONS + content); + + return ""; + } + + @Override + public boolean rm(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + + if (!map.contains(absolutePath)) { + logError("Cannot remove file, because it does not exist: " + absolutePath); + return false; + } + map.remove(absolutePath); + return true; + } + + @Override + public String cp(String source, String target) { + return moveOrCp(source, target, false, true); + } + + @Override + public String mv(String source, String target) { + return moveOrCp(source, target, true, false); + } + + private String moveOrCp(String source, String target, boolean move, boolean cp) { + if (move && cp) { + throw new OpenEggbertException("move == true && cp == true"); + } + if (!move && !cp) { + throw new OpenEggbertException("move != true && cp != true"); + } + String absolutePathSource = convertToAbsolutePathIfNeeded(source); + String absolutePathTarget = convertToAbsolutePathIfNeeded(target); + String targetParentPath = getParentPath(absolutePathTarget); + + if (!exists(absolutePathSource)) { + final String msg = "absolutePathSource does not exist: " + absolutePathSource; + logError(msg); + return msg; + } + if (isdir(absolutePathSource)) { + final String msg = "absolutePathSource is directory: " + absolutePathSource; + logError(msg); + return msg; + } + if (!exists(targetParentPath)) { + final String msg = "targetParentPath does not exist: " + absolutePathSource; + logError(msg); + return msg; + } + if (!isdir(targetParentPath)) { + final String msg = "targetParentPath is not directory: " + absolutePathSource; + logError(msg); + return msg; + } + String contentOfSourceFile = map.getString(absolutePathSource); + String result = touch(absolutePathTarget); + if (!result.isEmpty()) { + var msg = "Creating new file failed: " + absolutePathTarget; + logError(msg); + return msg; + } + map.remove(absolutePathTarget); + map.putString(absolutePathTarget, contentOfSourceFile); + if (move) { + map.remove(absolutePathSource); + } + return ""; + } + + @Override + public String readtext(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + if (!exists(absolutePath)) { + logError("absolutePathSource does not exist: " + absolutePath); + return null; + } + if (isdir(absolutePath)) { + logError("absolutePathSource is directory: " + absolutePath); + return null; + } + String value = map.getString(absolutePath); + return value.split(EIGHT_COLONS)[1]; + } + + @Override + public byte[] readbin(String path) { + String absolutePath = convertToAbsolutePathIfNeeded(path); + + String text = readtext(absolutePath); + if (!text.startsWith(BINARYFILE)) { + logError("File is not binary:" + absolutePath); + return null; + } + text = text.substring(BINARYFILE.length()); + return OpenEggbertUtils.decodeBase64AsByteArray(text); + } + private static final String BINARYFILE = "BINARYFILE"; + + @Override + public String savetext(String name, String text) { + return touch(name, text); + } + + @Override + public String savebin(String name, byte[] data) { + return savetext(name, BINARYFILE + OpenEggbertUtils.encodeToBase64(data)); + } + + @Override + public boolean exists(String name) { + return map.contains(convertToAbsolutePathIfNeeded(name)); + } + + @Override + public boolean isfile(String name) { + return filetype(name) == MapFileType.FILE; + } + + @Override + public boolean isdir(String name) { + return filetype(name) == MapFileType.DIRECTORY; + } + + public MapFileType filetype(String name) { + return MapFileType.ofKey(convertToAbsolutePathIfNeeded(name), map); + } + + @Override + public String debug() { + StringBuilder sb = new StringBuilder(); + for(String key: map.keyList()) { + sb + .append(key) + .append("=") + .append(map.getString(key)) + .append("\n"); + } + return sb.toString(); + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/map/MapStorageCompression.java b/core/src/main/java/com/openeggbert/storage/map/MapStorageCompression.java new file mode 100644 index 0000000..6af03a6 --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/MapStorageCompression.java @@ -0,0 +1,28 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +/** + * + * @author robertvokac + */ +public enum MapStorageCompression { + NONE; +} diff --git a/core/src/main/java/com/openeggbert/storage/map/MemoryStorage.java b/core/src/main/java/com/openeggbert/storage/map/MemoryStorage.java new file mode 100644 index 0000000..04945fe --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/MemoryStorage.java @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import com.badlogic.gdx.Application; + +/** + * + * @author robertvokac + */ +public class MemoryStorage extends MapStorage { + + @Override + public Application.ApplicationType getApplicationType() { + return null; + } + + public MemoryStorage() { + super(new SimpleJavaMap()); + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/map/SimpleJavaMap.java b/core/src/main/java/com/openeggbert/storage/map/SimpleJavaMap.java new file mode 100644 index 0000000..bb8f21d --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/SimpleJavaMap.java @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * + * @author robertvokac + */ +public class SimpleJavaMap implements SimpleMap { + + private final Map map; + + public SimpleJavaMap() { + this(new HashMap<>()); + } + public SimpleJavaMap(Map mapIn) { + this.map = mapIn; + } + + @Override + public void putString(String key, String val) { + map.put(key, val); + } + + @Override + public void put(Map map) { + for (String key : map.keySet()) { + putString(key, map.get(key)); + } + } + + @Override + public String getString(String key) { + return map.get(key); + } + + @Override + public String getString(String key, String defaultValue) { + return contains(key) ? getString(key) : defaultValue; + } + + @Override + public Map getReadOnlyMap() { + return Collections.unmodifiableMap(map); + } + + @Override + public boolean contains(String key) { + return map.containsKey(key); + } + + @Override + public void clear() { + map.clear(); + } + + @Override + public void remove(String key) { + map.remove(key); + } + + @Override + public void flush() { + //nothing to do + } + @Override + public List keyList() { + return map.keySet().stream().collect(Collectors.toList()); + } +} diff --git a/core/src/main/java/com/openeggbert/storage/map/SimpleLocalStorageMap.java b/core/src/main/java/com/openeggbert/storage/map/SimpleLocalStorageMap.java new file mode 100644 index 0000000..af7b60f --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/SimpleLocalStorageMap.java @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import com.badlogic.gdx.Preferences; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * + * @author robertvokac + */ +public class SimpleLocalStorageMap implements SimpleMap { + + private final Preferences preferences; + + public SimpleLocalStorageMap(Preferences preferencesIn) { + this.preferences = preferencesIn; + } + + @Override + public void putString(String key, String val) { + preferences.putString(key, val); + } + + @Override + public void put(Map map) { + preferences.put(map); + } + + @Override + public String getString(String key) { + return preferences.getString(key); + } + + @Override + public String getString(String key, String defaultValue) { + return preferences.getString(key, defaultValue); + } + + @Override + public Map getReadOnlyMap() { + Map map = preferences.get(); + Map result = new HashMap<>(); + for (String key : map.keySet()) { + Object o = map.get(key); + if (o instanceof String) { + result.put(key, (String) o); + } + } + return Collections.unmodifiableMap(result); + } + + @Override + public boolean contains(String key) { + return preferences.contains(key); + } + + @Override + public void clear() { + preferences.clear(); + } + + @Override + public void remove(String key) { + preferences.remove(key); + } + + @Override + public void flush() { + preferences.flush(); + } + + @Override + public List keyList() { + return preferences.get().keySet().stream().collect(Collectors.toList()); + } + +} diff --git a/core/src/main/java/com/openeggbert/storage/map/SimpleMap.java b/core/src/main/java/com/openeggbert/storage/map/SimpleMap.java new file mode 100644 index 0000000..d2a90dd --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/SimpleMap.java @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import java.util.List; +import java.util.Map; + +/** + * + * @author robertvokac + */ +public interface SimpleMap { + + public void putString(String key, String val); + + public void put(Map map); + + public String getString(String key); + + public String getString(String key, String defaultValue); + + public Map getReadOnlyMap(); + + public boolean contains(String key); + + public void clear(); + + public void remove(String key); + + public void flush(); + + public List keyList(); +} diff --git a/core/src/main/java/com/openeggbert/storage/map/WebGLStorage.java b/core/src/main/java/com/openeggbert/storage/map/WebGLStorage.java new file mode 100644 index 0000000..38906ed --- /dev/null +++ b/core/src/main/java/com/openeggbert/storage/map/WebGLStorage.java @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.storage.map; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Preferences; + +/** + * + * @author robertvokac + */ +public class WebGLStorage extends MapStorage { + public WebGLStorage() { + this("open-eggbert.webGL.Local-Storage"); + } + public WebGLStorage(String preferencesName) { + this(Gdx.app.getPreferences(preferencesName)); + } + public WebGLStorage(Preferences preferences) { + super(new SimpleLocalStorageMap(preferences)); + } + +} diff --git a/core/src/main/java/com/openeggbert/utils/OpenEggbertUtils.java b/core/src/main/java/com/openeggbert/utils/OpenEggbertUtils.java index a99f503..123f82c 100644 --- a/core/src/main/java/com/openeggbert/utils/OpenEggbertUtils.java +++ b/core/src/main/java/com/openeggbert/utils/OpenEggbertUtils.java @@ -19,6 +19,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////// package com.openeggbert.utils; +import com.badlogic.gdx.utils.Base64Coder; import com.openeggbert.compatibility.FileNameCaseType; import com.openeggbert.compatibility.ImageFormat; import com.openeggbert.compatibility.MusicFormat; @@ -27,6 +28,7 @@ import com.openeggbert.entity.common.GameFileType; import com.openeggbert.entity.common.OpenEggbertException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -77,13 +79,11 @@ public class OpenEggbertUtils { } return list; } - if ( - gameFileType == GameFileType.CONFIG || - gameFileType == GameFileType.WORLD || - gameFileType == GameFileType.DEMO || - gameFileType == GameFileType.SAVE || - gameFileType == GameFileType.USER_INFO - ) { + if (gameFileType == GameFileType.CONFIG + || gameFileType == GameFileType.WORLD + || gameFileType == GameFileType.DEMO + || gameFileType == GameFileType.SAVE + || gameFileType == GameFileType.USER_INFO) { for (FileNameCaseType fileNameCaseType : FileNameCaseType.values()) { list.add(FileNameCaseType.convertToString(fileName, fileNameCaseType)); } @@ -115,4 +115,20 @@ public class OpenEggbertUtils { } + public static String decodeBase64AsString(String string) { + return new String(decodeBase64AsByteArray(string)); + } + + public static byte[] decodeBase64AsByteArray(String string) { + return Base64Coder.decode(string); + } + + public static String encodeToBase64(String string) { + return encodeToBase64(string.getBytes()); + } + + public static String encodeToBase64(byte[] data) { + return String.valueOf(Base64Coder.encode(data)); + } + } diff --git a/lwjgl3/src/main/java/com/openeggbert/lwjgl3/TestAssetsTxt.java b/lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/DebuggingAssetsTxt.java similarity index 99% rename from lwjgl3/src/main/java/com/openeggbert/lwjgl3/TestAssetsTxt.java rename to lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/DebuggingAssetsTxt.java index e5af884..d2f0630 100644 --- a/lwjgl3/src/main/java/com/openeggbert/lwjgl3/TestAssetsTxt.java +++ b/lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/DebuggingAssetsTxt.java @@ -17,7 +17,7 @@ // or write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. /////////////////////////////////////////////////////////////////////////////////////////////// -package com.openeggbert.lwjgl3; +package com.openeggbert.lwjgl3.debugging; import com.openeggbert.utils.AssetsTxt; import java.util.List; @@ -27,8 +27,8 @@ import java.util.Scanner; * * @author robertvokac */ -public class TestAssetsTxt { - private TestAssetsTxt() { +public class DebuggingAssetsTxt { + private DebuggingAssetsTxt() { //Not meant to be instantiated. } public static void main(String[] args) { diff --git a/lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/StorageCommandWrapper.java b/lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/StorageCommandWrapper.java new file mode 100644 index 0000000..4e62a1f --- /dev/null +++ b/lwjgl3/src/main/java/com/openeggbert/lwjgl3/debugging/StorageCommandWrapper.java @@ -0,0 +1,203 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Open Eggbert: Free recreation of the computer game Speedy Eggbert. +// Copyright (C) 2024 the original author or authors. +// +// This program is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see +// or write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +/////////////////////////////////////////////////////////////////////////////////////////////// +package com.openeggbert.lwjgl3.debugging; + +import com.openeggbert.storage.Storage; +import com.openeggbert.storage.map.MemoryStorage; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.Scanner; +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * + * @author robertvokac + */ +public class StorageCommandWrapper { + + private StorageCommandWrapper(String userIn, String hostnameIn, Storage storageIn) { + this.user = userIn; + this.hostname = hostnameIn; + this.storage = storageIn; + } + private String user; + private String hostname; + private Storage storage; + +// @AllArgsConstructor +// @Data +// class StorageCommandWrapperResult { +// +// private String output; +// private boolean error; +// } +// +// public StorageCommandWrapperResult execute(String commandWithArguments) { +// return null; +// } + + public static void main(String[] args) { + + Scanner scanner = new Scanner(System.in); + + MemoryStorage memoryStorage = new MemoryStorage(); + + while (true) { + System.out.print("player@openegggbert:" + memoryStorage.pwd() + "$ "); + String argument = scanner.nextLine(); + String[] arguments = argument.split(" "); + int argumentCount = arguments.length - 1; + //System.out.println("argumentCount=" + argumentCount); + Optional argument1 = Optional.ofNullable(argumentCount >= 1 ? arguments[1] : null); + Optional argument2 = Optional.ofNullable(argumentCount >= 2 ? arguments[2] : null); + String command = arguments.length == 0 ? "" : arguments[0]; + + switch (command) { + case "whoami": + print("player");break; + case "hostname": + print("openegggbert");break; + case "uname": + if (argumentCount == 0) { + print("LinuxBashCommandLinePartialEmulation"); + } else { + if (argument1.get().equals("-a")) { + print("LinuxBashCommandLinePartialEmulation openeggbert 0.0.0 (" + LocalDateTime.now().toString().replace("T", " ").substring(0, 10) + ")"); + } else { + print("LinuxBashCommandLinePartialEmulation"); + } + } + break; + case "exit": + return; + case "": + continue; + case "ls": + memoryStorage + .ls() + .stream() + .map(l->{ + String[] a = l.split("/");return a[a.length-1]; + } + ) + .forEach(l -> print(l)); + break; + case "pwd": + print(memoryStorage.pwd()); + break; + + case "depth": + print(memoryStorage.depth()); + break; + case "mkdir": + if (checkArgumentCount(1, argumentCount)) { + String result = memoryStorage.mkdir(argument1.get()); + if (result.isEmpty()) { + System.out.println("New directory was successfully created"); + } else { + System.err.println("Creating new directory failed: " + result); + } + + } + break; + case "touch": + if (checkArgumentCount(1, argumentCount)) { + String result = memoryStorage.touch(argument1.get()); + if (result.isEmpty()) { + System.out.println("New file was successfully created"); + } else { + System.err.println("Creating new directory failed: " + result); + } + + } + break; + case "readtext": + if (checkArgumentCount(1, argumentCount)) { + String result = memoryStorage.readtext(argument1.get()); + if (result != null) { + System.out.println("Text file was successfully loaded"); + System.out.println(result); + } else { + System.err.println("Loading text file failed:"); + } + + } + break; + + case "savetext": + if (checkArgumentCount(2, argumentCount)) { + String result = memoryStorage.savetext(argument1.get(), argument2.get()); + if (result.isEmpty()) { + System.out.println("Text file was successfully saved"); + } else { + System.err.println("Saving text file failed: " + result); + } + + } + break; + case "cd": + String result = argument1.isEmpty() ? memoryStorage.cd() : memoryStorage.cd(argument1.get()); + if (result.isEmpty()) { + System.out.println("Changing working directory was successfully created"); + } else { + System.err.println("Changing working directory failed: " + result); + } + + break; + case "debug": + print(memoryStorage.debug()); + + break; + default: { + System.err.println("Unsupported command: " + command); + } + } + + } + } + + private static void print(int msg) { + print(String.valueOf(msg)); + } + + private static void print(String msg) { + System.out.println(msg); + } + + private static void printError(String msg) { + System.err.println(msg); + } + + private static boolean checkArgumentCount(int wantedCount, int currentCount) { +// System.out.println("wantedCount=" + wantedCount); +// System.out.println("currentCount=" + currentCount); + boolean b = wantedCount < currentCount; +// System.out.println("b=" + b); + if (currentCount < wantedCount) { + + printError("Wanted argument count is: " + wantedCount + ", but the current count of arguments is: " + currentCount); +// System.out.println("return false"); + return false; + } +// System.out.println("return true"); + return true; + } +}