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;
+ }
+}