From 15bfa8a16020821c4e84d47b00c9c3114f1f89c5 Mon Sep 17 00:00:00 2001 From: zhaodengke Date: Wed, 13 Nov 2024 17:14:00 +0800 Subject: [PATCH] Launcher: extract resource --- Q3E/src/main/java/com/n0n3m4/q3e/Q3EGUI.java | 8 +- .../java/com/n0n3m4/q3e/Q3EGameHelper.java | 31 +--- .../main/java/com/n0n3m4/q3e/Q3EGlobals.java | 9 + .../java/com/n0n3m4/q3e/Q3EInterface.java | 98 +++++++++++ .../java/com/n0n3m4/q3e/Q3EPatchResource.java | 105 ++++++++++++ .../n0n3m4/q3e/Q3EPatchResourceManager.java | 116 +++++++++++++ .../main/java/com/n0n3m4/q3e/Q3EUtils.java | 160 ++++++++++++++++++ Q3E/src/main/res/values-ru/strings.xml | 6 + Q3E/src/main/res/values-zh/strings.xml | 6 + Q3E/src/main/res/values/strings.xml | 6 + .../java/com/n0n3m4/DIII4A/GameLauncher.java | 21 ++- .../launcher/ExtractPatchResourceFunc.java | 102 +++++++---- .../DIII4A/launcher/GameLauncherFunc.java | 6 + .../src/main/res/layout/launcher_tab1.xml | 32 +++- idTech4Amm/src/main/res/values-ru/strings.xml | 4 +- idTech4Amm/src/main/res/values-zh/strings.xml | 4 +- idTech4Amm/src/main/res/values/strings.xml | 4 +- 17 files changed, 641 insertions(+), 77 deletions(-) create mode 100644 Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResource.java create mode 100644 Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResourceManager.java diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGUI.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGUI.java index 30e044e93..27efcbed8 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGUI.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGUI.java @@ -10,11 +10,11 @@ public class Q3EGUI { - public final static int DIALOG_ERROR = -1; + public final static int DIALOG_ERROR = -1; public final static int DIALOG_CANCEL = 0; - public final static int DIALOG_YES = 1; - public final static int DIALOG_NO = 2; - public final static int DIALOG_OTHER = 3; + public final static int DIALOG_YES = 1; + public final static int DIALOG_NO = 2; + public final static int DIALOG_OTHER = 3; private final Activity m_context; diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGameHelper.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGameHelper.java index 3e6675418..8e0207fa0 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGameHelper.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGameHelper.java @@ -426,15 +426,14 @@ private void DumpExtractResourceVersion(String systemVersionPath, String apkVers public void ExtractTDMGLSLShaderSource() { - final String destname = Q3EUtils.q3ei.datadir + "/darkmod"; - final String versionFile = destname + "/glslprogs/idtech4amm.version"; + Q3EPatchResourceManager manager = new Q3EPatchResourceManager(m_context); + final String versionFile = KStr.AppendPath(Q3EUtils.q3ei.datadir, "darkmod", "glslprogs/idtech4amm.version"); final String version = Q3EGlobals.TDM_GLSL_SHADER_VERSION; final String name = "The Dark Mod GLSL shader source"; - final String zip = "pak/darkmod/glprogs.pk4"; boolean overwrite = CheckExtractResourceOverwrite(versionFile, version, name); - if(ExtractZip(zip, destname, overwrite)) + if(manager.Fetch(Q3EGlobals.PatchResource.TDM_GLSL_SHADER, overwrite) != null) { if (overwrite) { @@ -447,15 +446,14 @@ public void ExtractTDMGLSLShaderSource() public void ExtractDOOM3BFGHLSLShaderSource() { - final String destname = Q3EUtils.q3ei.datadir + "/doom3bfg/base"; - final String versionFile = destname + "/renderprogs/idtech4amm.version"; + Q3EPatchResourceManager manager = new Q3EPatchResourceManager(m_context); + final String versionFile = KStr.AppendPath(Q3EUtils.q3ei.datadir, "doom3bfg/base", "renderprogs/idtech4amm.version"); final String version = Q3EGlobals.RBDOOM3BFG_HLSL_SHADER_VERSION; final String name = "RBDOOM 3 BFG HLSL shader source"; - final String zip = "pak/doom3bfg/renderprogs.pk4"; boolean overwrite = CheckExtractResourceOverwrite(versionFile, version, name); - if(ExtractZip(zip, destname, overwrite)) + if(manager.Fetch(Q3EGlobals.PatchResource.DOOM3BFG_HLSL_SHADER, overwrite) != null) { if (overwrite) { @@ -468,25 +466,14 @@ public void ExtractDOOM3BFGHLSLShaderSource() public void ExtractGZDOOMResource() { - final String destname = Q3EUtils.q3ei.datadir + "/gzdoom"; - final String versionFile = destname + "/idtech4amm.version"; + Q3EPatchResourceManager manager = new Q3EPatchResourceManager(m_context); + final String versionFile = KStr.AppendPath(Q3EUtils.q3ei.datadir, "gzdoom", "idtech4amm.version"); final String version = Q3EGlobals.GZDOOM_VERSION; final String name = "GZDOOM game resource"; - final String assetFolder = "pak/gzdoom"; - final String[] files = { - "brightmaps.pk3", - "game_support.pk3", - "game_widescreen_gfx.pk3", - "gzdoom.pk3", - "lights.pk3", - "soundfonts/gzdoom.sf2", - "fm_banks/GENMIDI.GS.wopl", - "fm_banks/gs-by-papiezak-and-sneakernets.wopn", - }; boolean overwrite = CheckExtractResourceOverwrite(versionFile, version, name); - if(ExtractCopy(assetFolder, destname, overwrite, files)) + if(manager.Fetch(Q3EGlobals.PatchResource.GZDOOM_RESOURCE, overwrite) != null) { if (overwrite) { diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGlobals.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGlobals.java index ddd0c613b..591998a77 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGlobals.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EGlobals.java @@ -209,6 +209,15 @@ public final class Q3EGlobals public static final String GAME_SUBDIR_ETW = "etw"; public static final String GAME_SUBDIR_REALRTCW = "realrtcw"; + public enum PatchResource + { + QUAKE4_SABOT, + DOOM3_RIVENSIN_ORIGIANL_LEVELS, + DOOM3BFG_HLSL_SHADER, + TDM_GLSL_SHADER, + GZDOOM_RESOURCE, + } + /* public static final String[] QUAKE4_MAPS = { "airdefense1", diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EInterface.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EInterface.java index e5671d404..f3b140f26 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EInterface.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EInterface.java @@ -303,6 +303,20 @@ private void SetupConfigFile() config_name = ConfigFileName(); } + public static String GetStandaloneDirectory(boolean standalone, String game) + { + String subdir = GetGameStandaloneDirectory(game); + if(standalone) + return subdir; + else if(Q3EGlobals.GAME_TDM.equals(game) + || Q3EGlobals.GAME_DOOM3BFG.equals(game) + || Q3EGlobals.GAME_GZDOOM.equals(game) + ) + return subdir; + else + return null; + } + private void SetupSubDir() { String subdir = GameSubDirectory(); @@ -821,6 +835,90 @@ else if(Q3EUtils.q3ei.isRealRTCW) return null; } + public static String GetGameModPreferenceKey(String name) + { + if(Q3EGlobals.GAME_QUAKE4.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q4_fs_game; + else if(Q3EGlobals.GAME_PREY.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_prey_fs_game; + else if(Q3EGlobals.GAME_QUAKE2.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q2_fs_game; + else if(Q3EGlobals.GAME_QUAKE3.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q3_fs_game; + else if(Q3EGlobals.GAME_RTCW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_rtcw_fs_game; + else if(Q3EGlobals.GAME_TDM.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_tdm_fs_game; + else if(Q3EGlobals.GAME_QUAKE1.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q1_fs_game; + else if(Q3EGlobals.GAME_DOOM3BFG.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_d3bfg_fs_game; + else if(Q3EGlobals.GAME_GZDOOM.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_gzdoom_fs_game; + else if(Q3EGlobals.GAME_ETW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_etw_fs_game; + else if(Q3EGlobals.GAME_REALRTCW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_realrtcw_fs_game; + else + return Q3EPreference.pref_harm_fs_game; + } + + public static String GetEnableModPreferenceKey(String name) + { + if(Q3EGlobals.GAME_QUAKE4.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q4_user_mod; + else if(Q3EGlobals.GAME_PREY.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_prey_user_mod; + else if(Q3EGlobals.GAME_QUAKE2.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q2_user_mod; + else if(Q3EGlobals.GAME_QUAKE3.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q3_user_mod; + else if(Q3EGlobals.GAME_RTCW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_rtcw_user_mod; + else if(Q3EGlobals.GAME_TDM.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_tdm_user_mod; + else if(Q3EGlobals.GAME_QUAKE1.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_q1_user_mod; + else if(Q3EGlobals.GAME_DOOM3BFG.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_d3bfg_user_mod; + else if(Q3EGlobals.GAME_GZDOOM.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_gzdoom_user_mod; + else if(Q3EGlobals.GAME_ETW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_etw_user_mod; + else if(Q3EGlobals.GAME_REALRTCW.equalsIgnoreCase(name)) + return Q3EPreference.pref_harm_realrtcw_user_mod; + else + return Q3EPreference.pref_harm_user_mod; + } + + public static String GetGameBaseDirectory(String name) + { + if(Q3EGlobals.GAME_PREY.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_PREY; + else if(Q3EGlobals.GAME_QUAKE4.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_QUAKE4; + else if(Q3EGlobals.GAME_QUAKE2.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_QUAKE2; + else if(Q3EGlobals.GAME_QUAKE3.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_QUAKE3; + else if(Q3EGlobals.GAME_RTCW.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_RTCW; + else if(Q3EGlobals.GAME_TDM.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_TDM; + else if(Q3EGlobals.GAME_QUAKE1.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_QUAKE1; + else if(Q3EGlobals.GAME_DOOM3BFG.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_DOOM3BFG; + else if(Q3EGlobals.GAME_GZDOOM.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_GZDOOM; + else if(Q3EGlobals.GAME_ETW.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_ETW; + else if(Q3EGlobals.GAME_REALRTCW.equalsIgnoreCase(name)) + return Q3EGlobals.GAME_BASE_REALRTCW; + else + return Q3EGlobals.GAME_BASE_DOOM3; + } + public void SetAppStoragePath(Context context) { Q3EUtils.q3ei.app_storage_path = Q3EUtils.GetAppStoragePath(context, null); diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResource.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResource.java new file mode 100644 index 000000000..8b18b30b5 --- /dev/null +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResource.java @@ -0,0 +1,105 @@ +package com.n0n3m4.q3e; + +import android.app.Activity; +import android.content.Context; +import android.util.Log; + +import com.n0n3m4.q3e.karin.KLog; +import com.n0n3m4.q3e.karin.KStr; + +import java.util.Arrays; + +public class Q3EPatchResource +{ + public static final int COPY_FILE_TO_FILE = 1; // copy assets/patch.pk4 -> dirname/zzz.pk4 + public static final int COPY_FILE_TO_DIR = 2; // copy assets/patch.pk4 -> dirname/ + public static final int COPY_DIR_FILES_TO_DIR = 3; // copy assets/ :: patch.pk4, other/other.pk4, ... -> dirname/ + public static final int EXTRACT_ZIP_TO_DIR = 4; // extract assets/patch.zip -> dirname/ + + public final Q3EGlobals.PatchResource type; + public final String name; + public final String version; + public final String game; + public final String mod; + public final int extract; + public final String assetPath; + public final String fsPath; + public final String[] assetFiles; + + public Q3EPatchResource(Q3EGlobals.PatchResource type, String name, String version, String game, String mod, int extract, String assetPath, String fsPath, String...assetFiles) + { + this.type = type; + this.name = name; + this.version = version; + this.game = game; + this.mod = mod; + this.extract = extract; + this.assetPath = assetPath; + this.fsPath = fsPath; + if(null != assetFiles) + { + this.assetFiles = new String[assetFiles.length]; + System.arraycopy(assetFiles, 0, this.assetFiles, 0, assetFiles.length); + } + else + this.assetFiles = null; + } + + public String Fetch(Context context, boolean overwrite, String...fsgame) + { + switch(extract) + { + case COPY_FILE_TO_FILE: + return CopyFileToFile(context, overwrite, fsgame); + case COPY_FILE_TO_DIR: + return CopyFileToDir(context, overwrite, fsgame); + case COPY_DIR_FILES_TO_DIR: + return CopyDirFilesToDir(context, overwrite, fsgame); + case EXTRACT_ZIP_TO_DIR: + return ExtractZipToDir(context, overwrite, fsgame); + default: + throw new RuntimeException("Unexcept extract type:" + extract); + } + } + + private String MakeOutPath(String...fsgame) + { + String path = Q3EInterface.GetStandaloneDirectory(Q3EUtils.q3ei.standalone, game); + if(null == fsPath) + path = KStr.AppendPath(path, null != fsgame ? fsgame[0] : null); + else if(fsPath.isEmpty()) + path = KStr.AppendPath(path, mod); + else + path = KStr.AppendPath(path, fsPath); + + return KStr.AppendPath(Q3EUtils.q3ei.datadir, path); + } + + private String CopyFileToFile(Context context, boolean overwrite, String...fsgame) + { + String toPath = MakeOutPath(fsgame); + KLog.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Copying file '%s' to file '%s'", assetPath, toPath); + return Q3EUtils.ExtractCopyFile(context, assetPath, toPath, overwrite) ? toPath : null; + } + + private String CopyFileToDir(Context context, boolean overwrite, String...fsgame) + { + String toPath = MakeOutPath(fsgame); + KLog.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Copying file '%s' to directory '%s/'", assetPath, toPath); + return Q3EUtils.ExtractCopyFile(context, assetPath, toPath + "/", overwrite) ? toPath : null; + } + + private String CopyDirFilesToDir(Context context, boolean overwrite, String...fsgame) + { + String toPath = MakeOutPath(fsgame); + KLog.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Copying directory '%s' files '%s' to directory '%s/'", assetPath, Arrays.toString(assetFiles), toPath); + return Q3EUtils.ExtractCopyDir(context, assetPath, toPath, overwrite, assetFiles) ? toPath : null; + } + + private String ExtractZipToDir(Context context, boolean overwrite, String...fsgame) + { + String toPath = MakeOutPath(fsgame); + KLog.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Extracting zip file '%s' to directory '%s/'", assetPath, toPath); + return Q3EUtils.ExtractZip(context, assetPath, toPath, overwrite) ? toPath : null; + } +} diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResourceManager.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResourceManager.java new file mode 100644 index 000000000..ae2830aa6 --- /dev/null +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EPatchResourceManager.java @@ -0,0 +1,116 @@ +package com.n0n3m4.q3e; + +import android.content.Context; + +import java.util.ArrayList; +import java.util.List; + +public class Q3EPatchResourceManager +{ + private Context context; + private final List resourceList = new ArrayList<>(); + + public Q3EPatchResourceManager(Context context) + { + SetContext(context); + Init(); + } + + public void SetContext(Context context) + { + if(null == context) + throw new RuntimeException("Q3EPatchResourceManager::Context is null"); + this.context = context; + } + + public List ResourceList() + { + return resourceList; + } + + private void Init() + { + Q3EPatchResource rsc; + + rsc = new Q3EPatchResource( + Q3EGlobals.PatchResource.QUAKE4_SABOT, + Q3ELang.tr(context, R.string.bot_q3_bot_support_in_mp_game), + "1", + Q3EGlobals.GAME_QUAKE4, + null, + Q3EPatchResource.COPY_FILE_TO_DIR, + "pak/q4base/sabot_a9.pk4", + null + ); + resourceList.add(rsc); + + rsc = new Q3EPatchResource( + Q3EGlobals.PatchResource.DOOM3_RIVENSIN_ORIGIANL_LEVELS, + Q3ELang.tr(context, R.string.rivensin_play_original_doom3_level), + "1", + Q3EGlobals.GAME_DOOM3, + "rivensin", + Q3EPatchResource.COPY_FILE_TO_DIR, + "pak/rivensin/play_original_doom3_level.pk4", + "" + ); + resourceList.add(rsc); + + rsc = new Q3EPatchResource( + Q3EGlobals.PatchResource.DOOM3BFG_HLSL_SHADER, + Q3ELang.tr(context, R.string.rbdoom3_bfg_hlsl_shader), + Q3EGlobals.RBDOOM3BFG_HLSL_SHADER_VERSION, + Q3EGlobals.GAME_DOOM3BFG, + null, + Q3EPatchResource.EXTRACT_ZIP_TO_DIR, + "pak/doom3bfg/renderprogs.pk4", + "base" + ); + resourceList.add(rsc); + + rsc = new Q3EPatchResource( + Q3EGlobals.PatchResource.TDM_GLSL_SHADER, + Q3ELang.tr(context, R.string.the_dark_mod_glsl_shader), + Q3EGlobals.TDM_GLSL_SHADER_VERSION, + Q3EGlobals.GAME_TDM, + null, + Q3EPatchResource.EXTRACT_ZIP_TO_DIR, + "pak/darkmod/glprogs.pk4", + "" + ); + resourceList.add(rsc); + + rsc = new Q3EPatchResource( + Q3EGlobals.PatchResource.GZDOOM_RESOURCE, + Q3ELang.tr(context, R.string.gzdoom_builtin_resource), + Q3EGlobals.GZDOOM_VERSION, + Q3EGlobals.GAME_GZDOOM, + null, + Q3EPatchResource.COPY_DIR_FILES_TO_DIR, + "pak/gzdoom", + "", + + "brightmaps.pk3", + "game_support.pk3", + "game_widescreen_gfx.pk3", + "gzdoom.pk3", + "lights.pk3", + "soundfonts/gzdoom.sf2", + "fm_banks/GENMIDI.GS.wopl", + "fm_banks/gs-by-papiezak-and-sneakernets.wopn" + ); + resourceList.add(rsc); + } + + public String Fetch(Q3EGlobals.PatchResource type, boolean overwrite, String...fsgame) + { + for(Q3EPatchResource rsc : resourceList) + { + if(rsc.type == type) + { + return rsc.Fetch(context, overwrite, fsgame); + } + } + throw new RuntimeException("Unexcept patch resource type: " + type); + } +} diff --git a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EUtils.java b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EUtils.java index a34249cdd..77f5e09cf 100644 --- a/Q3E/src/main/java/com/n0n3m4/q3e/Q3EUtils.java +++ b/Q3E/src/main/java/com/n0n3m4/q3e/Q3EUtils.java @@ -53,6 +53,7 @@ import java.io.Closeable; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; @@ -63,9 +64,13 @@ import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; public class Q3EUtils { @@ -876,4 +881,159 @@ public static String date_format(String format, Date...date) Date d = null != date && date.length > 0 && null != date[0] ? date[0] : new Date(); return new SimpleDateFormat(format).format(d); } + + public static long Write(String filePath, InputStream in, int...bufferSizeArg) throws RuntimeException + { + FileOutputStream fileoutputstream = null; + + try + { + fileoutputstream = new FileOutputStream(filePath); + return Q3EUtils.Copy(fileoutputstream, in, bufferSizeArg); + } + catch(FileNotFoundException e) + { + throw new RuntimeException(e); + } + finally + { + Q3EUtils.Close(fileoutputstream); + } + } + + public static boolean ExtractCopyFile(Context context, String assetFilePath, String systemFilePath, boolean overwrite) + { + InputStream bis = null; + + try + { + File srcFile = new File(assetFilePath); + String systemFolderPath; + String toFilePath; + if(systemFilePath.endsWith("/")) + { + systemFolderPath = systemFilePath.substring(0, systemFilePath.length() - 1); + toFilePath = systemFilePath + srcFile.getName(); + } + else + { + File f = new File(systemFilePath); + systemFolderPath = f.getParent(); + toFilePath = systemFilePath; + } + + Q3EUtils.mkdir(systemFolderPath, true); + + bis = context.getAssets().open(assetFilePath); + + File file = new File(toFilePath); + if(!overwrite && file.exists()) + return false; + + Q3EUtils.mkdir(file.getParent(), true); + + Log.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Copying " + assetFilePath + " to " + toFilePath); + Q3EUtils.Write(toFilePath, bis, 4096); + bis.close(); + bis = null; + return true; + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + finally + { + Q3EUtils.Close(bis); + } + } + + public static boolean ExtractCopyDir(Context context, String assetFolderPath, String systemFolderPath, boolean overwrite, String...assetPaths) + { + InputStream bis = null; + + try + { + Q3EUtils.mkdir(systemFolderPath, true); + + List fileList; + if(null == assetPaths) + { + String[] list = context.getAssets().list(assetFolderPath); + if(null == list) + fileList = new ArrayList<>(); + else + fileList = Arrays.asList(list); + } + else + fileList = Arrays.asList(assetPaths); + + for (String assetPath : fileList) + { + String sourcePath = assetFolderPath + "/" + assetPath; + String entryName = systemFolderPath + "/" + assetPath; + ExtractCopyFile(context, sourcePath, entryName, overwrite); + } + return true; + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + finally + { + Q3EUtils.Close(bis); + } + } + + public static boolean ExtractZip(Context context, String assetPath, String systemFolderPath, boolean overwrite) + { + InputStream bis = null; + ZipInputStream zipinputstream = null; + + try + { + bis = context.getAssets().open(assetPath); + zipinputstream = new ZipInputStream(bis); + + ZipEntry zipentry; + Q3EUtils.mkdir(systemFolderPath, true); + while ((zipentry = zipinputstream.getNextEntry()) != null) + { + String tmpname = zipentry.getName(); + + String toFilePath = systemFolderPath + "/" + tmpname; + toFilePath = toFilePath.replace('/', File.separatorChar); + toFilePath = toFilePath.replace('\\', File.separatorChar); + File file = new File(toFilePath); + + if (zipentry.isDirectory()) + { + if(!file.exists()) + Q3EUtils.mkdir(toFilePath, true); + continue; + } + + if(!overwrite && file.exists()) + continue; + + Log.i(Q3EGlobals.CONST_Q3E_LOG_TAG, "Extracting " + tmpname + " to " + systemFolderPath); + Q3EUtils.Write(toFilePath, zipinputstream, 4096); + zipinputstream.closeEntry(); + } + return true; + } + catch (Exception e) + { + e.printStackTrace(); + return false; + } + finally + { + Q3EUtils.Close(zipinputstream); + Q3EUtils.Close(bis); + } + } } diff --git a/Q3E/src/main/res/values-ru/strings.xml b/Q3E/src/main/res/values-ru/strings.xml index 8c1286d73..0f1516542 100644 --- a/Q3E/src/main/res/values-ru/strings.xml +++ b/Q3E/src/main/res/values-ru/strings.xml @@ -48,4 +48,10 @@ Копировать Button setting has changed! Can you save it? Exit + Боты Quake 4 (мод SABot-a9) + Файлы игры Quake4 в формате "aas" + Rivensin на оригинальных уровнях DOOM3 + RBDOOM3-BFG HLSL shader + The Dark Mod GLSL shader + GZDOOM built-in resource \ No newline at end of file diff --git a/Q3E/src/main/res/values-zh/strings.xml b/Q3E/src/main/res/values-zh/strings.xml index 0ad95b907..58e02f1b8 100644 --- a/Q3E/src/main/res/values-zh/strings.xml +++ b/Q3E/src/main/res/values-zh/strings.xml @@ -49,4 +49,10 @@ 按键配置已经被修改! 是否保存? 退出 复制 + 雷神之锤4 Bot(SABot-a9 mod) + 多人游戏地图aas文件 + Rivensin加载原毁灭战士3关卡 + RBDOOM3-BFG HLSL着色器 + The Dark Mod GLSL着色器 + GZDOOM内置资源 \ No newline at end of file diff --git a/Q3E/src/main/res/values/strings.xml b/Q3E/src/main/res/values/strings.xml index 729bafcfe..e7253dbb9 100644 --- a/Q3E/src/main/res/values/strings.xml +++ b/Q3E/src/main/res/values/strings.xml @@ -50,4 +50,10 @@ Button setting has changed! Can you save it? Exit Copy + Quake4 Bot(SABot-a9 mod) + Quake4 MP game map aas files + Rivensin play original DOOM3 level + RBDOOM3-BFG HLSL shader + The Dark Mod GLSL shader + GZDOOM built-in resource \ No newline at end of file diff --git a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java index 42aae9f39..af9cc6e62 100644 --- a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java +++ b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/GameLauncher.java @@ -614,6 +614,10 @@ else if (id == R.id.show_directory_helper) { OpenDirectoryHelper(); } + else if (id == R.id.launcher_tab1_patch_resource) + { + OpenResourceFileDialog(false); + } } }; @@ -798,6 +802,7 @@ public void InitQ3E(String game) InitUIDefaultLayout(q3ei); q3ei.default_path = default_gamedata; + q3ei.datadir = mPrefs.getString(Q3EPreference.pref_datapath, default_gamedata); //k add 20241113 q3ei.SetupDOOM3(); //k armv7-a only support neon now @@ -1404,6 +1409,7 @@ public boolean onEditorAction(TextView view, int id, KeyEvent ev) V.launcher_tab1_command_record.setOnClickListener(m_buttonClickListener); V.launcher_tab1_create_shortcut.setOnClickListener(m_buttonClickListener); V.show_directory_helper.setOnClickListener(m_buttonClickListener); + V.launcher_tab1_patch_resource.setOnClickListener(m_buttonClickListener); boolean userMod = mPrefs.getBoolean(Q3EUtils.q3ei.GetEnableModPreferenceKey(), false); V.fs_game_user.setChecked(userMod); @@ -1507,7 +1513,12 @@ public void afterTextChanged(Editable s) V.smoothjoy.setOnCheckedChangeListener(m_checkboxChangeListener); V.launcher_tab2_joystick_unfixed.setOnCheckedChangeListener(m_checkboxChangeListener); V.launcher_tab2_joystick_visible.setOnItemSelectedListener(m_itemSelectedListener); - V.edt_path.addTextChangedListener(new SavePreferenceTextWatcher(Q3EPreference.pref_datapath, default_gamedata)); + V.edt_path.addTextChangedListener(new SavePreferenceTextWatcher(Q3EPreference.pref_datapath, default_gamedata, new Runnable() { + @Override + public void run() { + Q3EUtils.q3ei.datadir = V.edt_path.getText().toString(); + } + })); V.edt_mouse.addTextChangedListener(new SavePreferenceTextWatcher(Q3EPreference.pref_eventdev, "/dev/input/event???")); V.rg_curpos.setOnCheckedChangeListener(m_groupCheckChangeListener); V.secfinglmb.setOnCheckedChangeListener(m_checkboxChangeListener); @@ -1853,7 +1864,7 @@ else if (itemId == R.id.main_menu_cvar_list) } else if (itemId == R.id.main_menu_extract_resource) { - OpenResourceFileDialog(); + OpenResourceFileDialog(true); return true; } else if (itemId == R.id.main_menu_save_settings) @@ -3007,12 +3018,14 @@ private void SetupCommandTextWatcher(boolean b) } } - private void OpenResourceFileDialog() + private void OpenResourceFileDialog(boolean all) { if (null == m_extractPatchResourceFunc) m_extractPatchResourceFunc = new ExtractPatchResourceFunc(this, CONST_RESULT_CODE_REQUEST_EXTRACT_PATCH_RESOURCE); Bundle bundle = new Bundle(); bundle.putString("path", V.edt_path.getText().toString()); + bundle.putString("game", Q3EUtils.q3ei.game); + bundle.putBoolean("all", all); m_extractPatchResourceFunc.Start(bundle); } @@ -3540,6 +3553,7 @@ private class ViewHolder public CheckBox find_dll; public EditText edt_harm_r_maxFps; public Button launcher_tab1_edit_cvar; + public Button launcher_tab1_patch_resource; public EditText edt_cmdline_temp; public CheckBox skip_intro; public Button launcher_tab1_game_mod_button; @@ -3658,6 +3672,7 @@ public void Setup() find_dll = findViewById(R.id.find_dll); edt_harm_r_maxFps = findViewById(R.id.edt_harm_r_maxFps); launcher_tab1_edit_cvar = findViewById(R.id.launcher_tab1_edit_cvar); + launcher_tab1_patch_resource = findViewById(R.id.launcher_tab1_patch_resource); edt_cmdline_temp = findViewById(R.id.edt_cmdline_temp); skip_intro = findViewById(R.id.skip_intro); launcher_tab1_game_mod_button = findViewById(R.id.launcher_tab1_game_mod_button); diff --git a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ExtractPatchResourceFunc.java b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ExtractPatchResourceFunc.java index d71f69df2..e999857bb 100644 --- a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ExtractPatchResourceFunc.java +++ b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/ExtractPatchResourceFunc.java @@ -2,14 +2,22 @@ import android.app.AlertDialog; import android.content.DialogInterface; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.PreferenceManager; import android.widget.Toast; import com.karin.idTech4Amm.R; import com.karin.idTech4Amm.lib.ContextUtility; import com.karin.idTech4Amm.lib.FileUtility; import com.n0n3m4.DIII4A.GameLauncher; +import com.n0n3m4.q3e.Q3EInterface; import com.n0n3m4.q3e.Q3ELang; +import com.n0n3m4.q3e.Q3EPatchResource; +import com.n0n3m4.q3e.Q3EPatchResourceManager; +import com.n0n3m4.q3e.Q3EPreference; +import com.n0n3m4.q3e.Q3EUtils; +import com.n0n3m4.q3e.karin.KStr; import java.io.File; import java.util.ArrayList; @@ -18,14 +26,10 @@ public final class ExtractPatchResourceFunc extends GameLauncherFunc { - private final String[] m_patchResources = { - // "glslprogs.pk4", - "q4base/sabot_a9.pk4", - "rivensin/play_original_doom3_level.pk4", - }; - private String m_path; - private List m_files; - private final int m_code; + private String m_path; + private final int m_code; + private boolean m_all; + private String m_game; public ExtractPatchResourceFunc(GameLauncher gameLauncher, int code) { @@ -35,10 +39,6 @@ public ExtractPatchResourceFunc(GameLauncher gameLauncher, int code) public void Reset() { - if(null != m_files) - m_files.clear(); - else - m_files = new ArrayList<>(); } public void Start(Bundle data) @@ -47,50 +47,92 @@ public void Start(Bundle data) Reset(); m_path = data.getString("path"); + m_all = data.getBoolean("all"); + m_game = data.getString("game"); + run(); + } + + + public void run() + { + Q3EPatchResourceManager manager = new Q3EPatchResourceManager(m_gameLauncher); + List resources = manager.ResourceList(); + List nameList = new ArrayList<>(); + List rscList = new ArrayList<>(); + String mod = GetGameMod(Q3EUtils.q3ei.game); + + for(Q3EPatchResource resource : resources) + { + if(!m_all) + { + if(!resource.game.equals(m_game)) + continue; + if(null != resource.mod && !resource.mod.equals(mod)) + continue; + } + nameList.add(resource.name); + rscList.add(resource); + } + // D3-format fonts don't need on longer - final String[] Names = { // Tr(R.string.opengles_shader), - Tr(R.string.bot_q3_bot_support_in_mp_game), - Tr(R.string.rivensin_play_original_doom3_level), - }; + //Tr(R.string.bot_q3_bot_support_in_mp_game), + //Tr(R.string.rivensin_play_original_doom3_level), AlertDialog.Builder builder = new AlertDialog.Builder(m_gameLauncher); builder.setTitle(R.string.game_patch_resource) - .setItems(Names, new DialogInterface.OnClickListener() { + .setItems(nameList.toArray(new CharSequence[0]), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int p) { - m_files.add(m_patchResources[p]); - ExtractPatchResource(); + ExtractPatchResource(rscList.get(p)); } }) .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.extract_all, new DialogInterface.OnClickListener() { + /*.setPositiveButton(R.string.extract_all, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int p) { m_files.addAll(Arrays.asList(m_patchResources)); ExtractPatchResource(); } - }) + })*/ .create() .show() ; } - private int ExtractPatchResource() + private boolean ExtractPatchResource(Q3EPatchResource resource) { - if(null == m_files || m_files.isEmpty()) - return -1; - int res = ContextUtility.CheckFilePermission(m_gameLauncher, m_code); if(res == ContextUtility.CHECK_PERMISSION_RESULT_REJECT) Toast_long(Tr(R.string.can_t_s_read_write_external_storage_permission_is_not_granted, Tr(R.string.access_file))); if(res != ContextUtility.CHECK_PERMISSION_RESULT_GRANTED) - return -1; + return false; - run(); - return m_files.size(); + String base = GetGameMod(resource.game); + String toPath = resource.Fetch(m_gameLauncher, true, base); + + if(null != toPath) + Toast_short(Tr(R.string.extract_path_resource_) + toPath); + else + Toast_short(Tr(R.string.extract_path_resource_) + Tr(R.string.fail)); + //run(); + return null != toPath; } - public void run() + private String GetGameMod(String game) + { + SharedPreferences preferences = SharedPreferences(); + boolean userMod = preferences.getBoolean(Q3EInterface.GetEnableModPreferenceKey(game), false); + String gamebase = Q3EInterface.GetGameBaseDirectory(game); + String mod = preferences.getString(Q3EInterface.GetGameModPreferenceKey(game), gamebase); + String base; + if(userMod) + base = KStr.IsEmpty(mod) ? gamebase : mod; + else + base = gamebase; + return base; + } + +/* public void run2() { int r = 0; String gamePath = m_path; @@ -108,5 +150,5 @@ public void run() r++; } Toast_short(Tr(R.string.extract_path_resource_) + r); - } + }*/ } diff --git a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/GameLauncherFunc.java b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/GameLauncherFunc.java index ded86dfcf..efbeb00c9 100644 --- a/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/GameLauncherFunc.java +++ b/idTech4Amm/src/main/java/com/n0n3m4/DIII4A/launcher/GameLauncherFunc.java @@ -1,8 +1,10 @@ package com.n0n3m4.DIII4A.launcher; import android.content.Context; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.Parcelable; +import android.preference.PreferenceManager; import android.widget.Toast; import com.n0n3m4.DIII4A.GameLauncher; @@ -123,6 +125,10 @@ public static T GetResultFromBundle(Bundle data) return null != data ? (T)data.get(CONST_RESULT_KEY) : null; } + protected SharedPreferences SharedPreferences() + { + return PreferenceManager.getDefaultSharedPreferences(m_gameLauncher); + } public Context getContext() { diff --git a/idTech4Amm/src/main/res/layout/launcher_tab1.xml b/idTech4Amm/src/main/res/layout/launcher_tab1.xml index 7b55c4230..6cc50c5f1 100644 --- a/idTech4Amm/src/main/res/layout/launcher_tab1.xml +++ b/idTech4Amm/src/main/res/layout/launcher_tab1.xml @@ -931,27 +931,41 @@ android:orientation="horizontal">