diff --git a/build.gradle b/build.gradle index cf1b553..6690eb9 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ apply plugin: 'java' apply plugin: 'application' apply plugin: 'idea' apply plugin: 'eclipse' +apply plugin: 'findbugs' repositories { mavenCentral() @@ -34,6 +35,7 @@ dependencies { compileOnly 'org.projectlombok:lombok:1.16.20' apt "org.projectlombok:lombok:1.16.20" + compileOnly 'com.google.code.findbugs:annotations:3.0.1' } sourceSets { diff --git a/src/lwjake2/client/CL.java b/src/lwjake2/client/CL.java index 05e3285..6866ae3 100644 --- a/src/lwjake2/client/CL.java +++ b/src/lwjake2/client/CL.java @@ -30,7 +30,8 @@ import lwjake2.qcommon.CM; import lwjake2.qcommon.Cbuf; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.MSG; import lwjake2.qcommon.Netchan; import lwjake2.qcommon.SZ; @@ -56,6 +57,8 @@ import java.nio.ByteOrder; */ @Slf4j public final class CL { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); + static int precache_check; // for autodownload of precache items static int precache_spawncount; @@ -159,10 +162,10 @@ public final class CL { // // open the demo file // - name = FS.Gamedir() + "/demos/" + Cmd.Argv(1) + ".dm2"; + name = fileSystem.getGamedir() + "/demos/" + Cmd.Argv(1) + ".dm2"; log.info("recording to {}", name); - FS.CreatePath(name); + fileSystem.createPath(name); Globals.cls.demofile = new RandomAccessFile(name, "rw"); if (Globals.cls.demofile == null) { log.error("ERROR: couldn't open."); @@ -973,8 +976,7 @@ public final class CL { // checking for skins in the model if (CL.precache_model == null) { - CL.precache_model = FS - .LoadFile(Globals.cl.configstrings[CL.precache_check]); + CL.precache_model = fileSystem.loadFile(Globals.cl.configstrings[CL.precache_check]); if (CL.precache_model == null) { CL.precache_model_skin = 0; CL.precache_check++; @@ -986,8 +988,6 @@ public final class CL { int header = bb.getInt(); if (header != qfiles.IDALIASHEADER) { - // not an alias model - FS.FreeFile(CL.precache_model); CL.precache_model = null; CL.precache_model_skin = 0; CL.precache_check++; @@ -1025,7 +1025,6 @@ public final class CL { CL.precache_model_skin++; } if (CL.precache_model != null) { - FS.FreeFile(CL.precache_model); CL.precache_model = null; } CL.precache_model_skin = 0; @@ -1408,7 +1407,7 @@ public final class CL { // if (Globals.cls.state == Defines.ca_uninitialized) // return; - path = FS.Gamedir() + "/config.cfg"; + path = fileSystem.getGamedir() + "/config.cfg"; f = Lib.fopen(path, "rw"); if (f == null) { log.warn("Couldn't write config.cfg."); @@ -1609,7 +1608,7 @@ public final class CL { InitLocal(); IN.Init(); - FS.ExecAutoexec(); + fileSystem.execAutoexec(); Cbuf.Execute(); } diff --git a/src/lwjake2/client/CL_ents.java b/src/lwjake2/client/CL_ents.java index b0b6f8a..a71fb5a 100644 --- a/src/lwjake2/client/CL_ents.java +++ b/src/lwjake2/client/CL_ents.java @@ -24,7 +24,8 @@ import lwjake2.game.entity_state_t; import lwjake2.game.player_state_t; import lwjake2.game.pmove_t; import lwjake2.qcommon.Com; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.MSG; import lwjake2.util.Math3D; @@ -40,6 +41,7 @@ import lwjake2.util.Math3D; * ========================================================================= */ public class CL_ents { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); static int bitcounts[] = new int[32]; /// just for protocol profiling @@ -815,7 +817,7 @@ public class CL_ents { * */ if ((renderfx & Defines.RF_SHELL_HALF_DAM) != 0) { - if (FS.Developer_searchpath(2) == 2) { + if (fileSystem.developer_searchpath(2) == 2) { // ditch the half damage shell if any of red, blue, or // double are on if ((renderfx & (Defines.RF_SHELL_RED | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE)) != 0) @@ -824,7 +826,7 @@ public class CL_ents { } if ((renderfx & Defines.RF_SHELL_DOUBLE) != 0) { - if (FS.Developer_searchpath(2) == 2) { + if (fileSystem.developer_searchpath(2) == 2) { // lose the yellow shell if we have a red, blue, or // green shell if ((renderfx & (Defines.RF_SHELL_RED | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_GREEN)) != 0) diff --git a/src/lwjake2/client/CL_parse.java b/src/lwjake2/client/CL_parse.java index 05d2546..8250d3f 100644 --- a/src/lwjake2/client/CL_parse.java +++ b/src/lwjake2/client/CL_parse.java @@ -27,7 +27,8 @@ import lwjake2.qcommon.CM; import lwjake2.qcommon.Cbuf; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.MSG; import lwjake2.qcommon.SZ; import lwjake2.render.model_t; @@ -43,6 +44,8 @@ import java.io.RandomAccessFile; */ @Slf4j public class CL_parse { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); + //// cl_parse.c -- parse a message received from the server public static String svc_strings[] = { "svc_bad", "svc_muzzleflash", @@ -56,7 +59,7 @@ public class CL_parse { // ============================================================================= public static String DownloadFileName(String fn) { - return FS.Gamedir() + "/" + fn; + return fileSystem.getGamedir() + "/" + fn; } /* @@ -74,7 +77,7 @@ public class CL_parse { return true; } - if (FS.FileLength(filename) > 0) { // it exists, no need to download + if (fileSystem.fileLength(filename) > 0) { // it exists, no need to download return true; } @@ -147,7 +150,7 @@ public class CL_parse { return; } - if (FS.LoadFile(filename) != null) { // it exists, no need to + if (fileSystem.loadFile(filename) != null) { // it exists, no need to // download Com.Printf("File already exists.\n"); return; @@ -221,7 +224,7 @@ public class CL_parse { if (Globals.cls.download == null) { String name = DownloadFileName(Globals.cls.downloadtempname).toLowerCase(); - FS.CreatePath(name); + fileSystem.createPath(name); Globals.cls.download = Lib.fopen(name, "rw"); if (Globals.cls.download == null) { @@ -320,10 +323,10 @@ public class CL_parse { // set gamedir if (str.length() > 0 - && (FS.fs_gamedirvar.string == null - || FS.fs_gamedirvar.string.length() == 0 || FS.fs_gamedirvar.string + && (fileSystem.getGamedirVar().string == null + || fileSystem.getGamedirVar().string.length() == 0 || fileSystem.getGamedirVar().string .equals(str)) - || (str.length() == 0 && (FS.fs_gamedirvar.string != null || FS.fs_gamedirvar.string + || (str.length() == 0 && (fileSystem.getGamedirVar().string != null || fileSystem.getGamedirVar().string .length() == 0))) Cvar.Set("game", str); diff --git a/src/lwjake2/client/Console.java b/src/lwjake2/client/Console.java index 6defe61..0719d5f 100644 --- a/src/lwjake2/client/Console.java +++ b/src/lwjake2/client/Console.java @@ -25,7 +25,8 @@ import lwjake2.game.Cmd; import lwjake2.qcommon.Cbuf; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.util.Lib; import lwjake2.util.Vargs; @@ -38,6 +39,7 @@ import java.util.Arrays; */ @Slf4j public final class Console extends Globals { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); public static Runnable ToggleConsole_f = new Runnable() { public void run() { SCR.EndLoadingPlaque(); // get rid of loading plaque @@ -93,10 +95,10 @@ public final class Console extends Globals { //Com_sprintf (name, sizeof(name), "%s/%s.txt", FS_Gamedir(), // Cmd_Argv(1)); - name = FS.Gamedir() + "/" + Cmd.Argv(1) + ".txt"; + name = fileSystem.getGamedir() + "/" + Cmd.Argv(1) + ".txt"; log.info("Dumped console text to {}", name); - FS.CreatePath(name); + fileSystem.createPath(name); f = Lib.fopen(name, "rw"); if (f == null) { log.error("ERROR: couldn't open."); diff --git a/src/lwjake2/client/Menu.java b/src/lwjake2/client/Menu.java index 723f31c..42210cb 100644 --- a/src/lwjake2/client/Menu.java +++ b/src/lwjake2/client/Menu.java @@ -24,7 +24,8 @@ import lwjake2.game.cvar_t; import lwjake2.qcommon.Cbuf; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.netadr_t; import lwjake2.sound.S; import lwjake2.sys.NET; @@ -33,6 +34,8 @@ import lwjake2.sys.Timer; import lwjake2.util.Lib; import lwjake2.util.Math3D; import lwjake2.util.QuakeFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.awt.Dimension; import java.io.RandomAccessFile; @@ -50,6 +53,8 @@ abstract class keyfunc_t { } public final class Menu extends Key { + private static final Logger logger = LoggerFactory.getLogger(Menu.class); + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); static int m_main_cursor; @@ -1885,9 +1890,6 @@ public final class Menu extends Key { public static String Credits_Key(int key) { switch (key) { case K_ESCAPE: - if (creditsBuffer != null) - //FS.FreeFile(creditsBuffer); - ; PopMenu(); break; } @@ -1906,7 +1908,7 @@ public final class Menu extends Key { int n; int isdeveloper = 0; - byte b[] = FS.LoadFile("credits"); + byte b[] = fileSystem.loadFile("credits"); if (b != null) { creditsBuffer = new String(b); @@ -1919,7 +1921,7 @@ public final class Menu extends Key { creditsIndex[n] = null; credits = creditsIndex; } else { - isdeveloper = FS.Developer_searchpath(1); + isdeveloper = fileSystem.developer_searchpath(1); if (isdeveloper == 1) // xatrix credits = xatcredits; @@ -2167,7 +2169,7 @@ public final class Menu extends Key { for (i = 0; i < MAX_SAVEGAMES; i++) { m_savestrings[i] = ""; - name = FS.Gamedir() + "/save/save" + i + "/server.ssv"; + name = fileSystem.getGamedir() + "/save/save" + i + "/server.ssv"; try { f = new QuakeFile(name, "r"); @@ -2589,7 +2591,7 @@ public final class Menu extends Key { // ===== // PGM // ROGUE GAMES - else if (FS.Developer_searchpath(2) == 2) { + else if (fileSystem.developer_searchpath(2) == 2) { if (s_rules_box.curvalue == 2) // tag { s_maxclients_field.statusbar = null; @@ -2635,7 +2637,7 @@ public final class Menu extends Key { // Cvar.SetValue ("coop", s_rules_box.curvalue ); // PGM - if ((s_rules_box.curvalue < 2) || (FS.Developer_searchpath(2) != 2)) { + if ((s_rules_box.curvalue < 2) || (fileSystem.developer_searchpath(2) != 2)) { Cvar.SetValue("deathmatch", 1 - (int) (s_rules_box.curvalue)); Cvar.SetValue("coop", s_rules_box.curvalue); Cvar.SetValue("gamerules", 0); @@ -2699,15 +2701,15 @@ public final class Menu extends Key { /* * * load the list of map names */ - mapsname = FS.Gamedir() + "/maps.lst"; + mapsname = fileSystem.getGamedir() + "/maps.lst"; // Check user dir first (default ~/.lwjake2) if ((fp = Lib.fopen(mapsname, "r")) == null) { // Check base dir first (baseq2 folder) - mapsname = FS.BaseGamedir() + "/maps.lst"; + mapsname = fileSystem.getBaseGamedir() + "/maps.lst"; if ((fp = Lib.fopen(mapsname, "r")) == null) { // Open the pak's maplist - buffer = FS.LoadFile("maps.lst"); + buffer = fileSystem.loadFile("maps.lst"); if (buffer == null) Com.Error(ERR_DROP, "couldn't find maps.lst\n"); } else { @@ -2755,7 +2757,7 @@ public final class Menu extends Key { fp = null; } else { - FS.FreeFile(buffer); + buffer = null; } /* @@ -2776,7 +2778,7 @@ public final class Menu extends Key { s_rules_box.name = "rules"; // PGM - rogue games only available with rogue DLL. - if (FS.Developer_searchpath(2) == 2) + if (fileSystem.developer_searchpath(2) == 2) s_rules_box.itemnames = dm_coop_names_rogue; else s_rules_box.itemnames = dm_coop_names; @@ -3059,7 +3061,7 @@ public final class Menu extends Key { // ======= // ROGUE - else if (FS.Developer_searchpath(2) == 2) { + else if (fileSystem.developer_searchpath(2) == 2) { if (f == s_no_mines_box) { bit = DF_NO_MINES; } else if (f == s_no_nukes_box) { @@ -3283,7 +3285,7 @@ public final class Menu extends Key { // ============ // ROGUE - if (FS.Developer_searchpath(2) == 2) { + if (fileSystem.developer_searchpath(2) == 2) { s_no_mines_box.type = MTYPE_SPINCONTROL; s_no_mines_box.x = 0; s_no_mines_box.y = y += 10; @@ -3354,7 +3356,7 @@ public final class Menu extends Key { // ======= // ROGUE - if (FS.Developer_searchpath(2) == 2) { + if (fileSystem.developer_searchpath(2) == 2) { Menu_AddItem(s_dmoptions_menu, s_no_mines_box); Menu_AddItem(s_dmoptions_menu, s_no_nukes_box); Menu_AddItem(s_dmoptions_menu, s_stack_double_box); @@ -3764,10 +3766,10 @@ public final class Menu extends Key { * * get a list of directories */ do { - path = FS.NextPath(path); + path = fileSystem.nextPath(path); findname = path + "/players/*.*"; - if ((dirnames = FS.ListFiles(findname, 0, SFF_SUBDIR)) != null) { + if ((dirnames = fileSystem.listFiles(findname, 0, SFF_SUBDIR)) != null) { ndirs = dirnames.length; break; } @@ -3807,7 +3809,7 @@ public final class Menu extends Key { // verify the existence of at least one pcx skin scratch = dirnames[i] + "/*.pcx"; - pcxnames = FS.ListFiles(scratch, 0, 0); + pcxnames = fileSystem.listFiles(scratch, 0, 0); npcxfiles = pcxnames.length; // count valid skins, which consist of a skin with a matching "_i" diff --git a/src/lwjake2/client/SCR.java b/src/lwjake2/client/SCR.java index 74796e7..0f9d1c1 100644 --- a/src/lwjake2/client/SCR.java +++ b/src/lwjake2/client/SCR.java @@ -23,12 +23,7 @@ import lwjake2.Defines; import lwjake2.Globals; import lwjake2.game.Cmd; import lwjake2.game.cvar_t; -import lwjake2.qcommon.Com; -import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; -import lwjake2.qcommon.MSG; -import lwjake2.qcommon.SZ; -import lwjake2.qcommon.qfiles; +import lwjake2.qcommon.*; import lwjake2.sound.S; import lwjake2.sys.Timer; import lwjake2.util.Lib; @@ -44,6 +39,7 @@ import java.util.Arrays; */ @Slf4j public final class SCR extends Globals { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); // cl_scrn.c -- master for refresh, status bar, console, chat, notify, etc static String[][] sb_nums = { @@ -1392,7 +1388,7 @@ public final class SCR extends Globals { qfiles.pcx_t pcx; // load the file - ByteBuffer raw = FS.LoadMappedFile(filename); + ByteBuffer raw = fileSystem.loadMappedFile(filename); if (raw == null) { VID.Printf(Defines.PRINT_DEVELOPER, "Bad pcx file " + filename @@ -1831,7 +1827,7 @@ public final class SCR extends Globals { } String name = "video/" + arg; - cl.cinematic_file = FS.LoadMappedFile(name); + cl.cinematic_file = fileSystem.loadMappedFile(name); if (cl.cinematic_file == null) { //Com.Error(ERR_DROP, "Cinematic " + name + " not found.\n"); FinishCinematic(); diff --git a/src/lwjake2/client/V.java b/src/lwjake2/client/V.java index bfb085b..eb7e82f 100644 --- a/src/lwjake2/client/V.java +++ b/src/lwjake2/client/V.java @@ -384,6 +384,7 @@ public final class V extends Globals { (int) cl.refdef.vieworg[1], (int) cl.refdef.vieworg[2], (int) cl.refdef.viewangles[YAW] + ); } }; diff --git a/src/lwjake2/game/Cmd.java b/src/lwjake2/game/Cmd.java index ce5b7f1..cac93d8 100644 --- a/src/lwjake2/game/Cmd.java +++ b/src/lwjake2/game/Cmd.java @@ -22,13 +22,7 @@ import lombok.extern.slf4j.Slf4j; import lwjake2.Defines; import lwjake2.Globals; import lwjake2.game.monsters.M_Player; -import lwjake2.qcommon.Cbuf; -import lwjake2.qcommon.Com; -import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; -import lwjake2.qcommon.MSG; -import lwjake2.qcommon.SZ; -import lwjake2.qcommon.cmd_function_t; +import lwjake2.qcommon.*; import lwjake2.server.SV_GAME; import lwjake2.util.Lib; @@ -41,6 +35,7 @@ import java.util.Vector; */ @Slf4j public final class Cmd { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); static Runnable List_f = new Runnable() { public void run() { cmd_function_t cmd = Cmd.cmd_functions; @@ -63,7 +58,7 @@ public final class Cmd { } byte[] f = null; - f = FS.LoadFile(Cmd.Argv(1)); + f = fileSystem.loadFile(Cmd.Argv(1)); if (f == null) { log.info("couldn't exec {}", Cmd.Argv(1)); return; @@ -71,8 +66,6 @@ public final class Cmd { log.info("execing {}", Cmd.Argv(1)); Cbuf.InsertText(new String(f)); - - FS.FreeFile(f); } }; @@ -386,7 +379,7 @@ public final class Cmd { /** * Cmd_ExecuteString * - * A complete command line has been parsed, so try to run it + * A complete command line has been parsed, so try to execute it * FIXME: lookupnoadd the token to speed search? */ public static void ExecuteString(String text) { @@ -396,7 +389,7 @@ public final class Cmd { TokenizeString(text.toCharArray(), true); - // run the command line + // execute the command line if (Argc() == 0) return; // no tokens diff --git a/src/lwjake2/qcommon/FS.java b/src/lwjake2/qcommon/BaseQ2FileSystem.java similarity index 78% rename from src/lwjake2/qcommon/FS.java rename to src/lwjake2/qcommon/BaseQ2FileSystem.java index 5d1f15f..7fcfd3f 100644 --- a/src/lwjake2/qcommon/FS.java +++ b/src/lwjake2/qcommon/BaseQ2FileSystem.java @@ -28,7 +28,6 @@ import lwjake2.sys.Sys; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -38,80 +37,81 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -/** - * FS - * +import static lwjake2.Defines.*; + +/* + * ================================================== + * + * QUAKE FILESYSTEM + * * @author cwei + * @author DmitriyMX + * @modify 2018-03-06 + * + * ================================================== */ + @Slf4j -public final class FS extends Globals { - /* - * ================================================== - * - * QUAKE FILESYSTEM - * - * ================================================== - */ +public class BaseQ2FileSystem implements FileSystem { + private static final BaseQ2FileSystem instance = new BaseQ2FileSystem(); + private static final int IDPAKHEADER = (('K' << 24) + ('C' << 16) + ('A' << 8) + 'P'); + private static final int MAX_FILES_IN_PACK = 4096; + // read in blocks of 64k + private static final int MAX_READ = 0x10000; - public static class packfile_t { + public static BaseQ2FileSystem getInstance() { + return instance; + } + + private BaseQ2FileSystem() {} + + private static class packfile_t { static final int SIZE = 64; - static final int NAME_SIZE = 56; - String name; // char name[56] - int filepos, filelen; - public String toString() { return name + " [ length: " + filelen + " pos: " + filepos + " ]"; } } - public static class pack_t { + private static class pack_t { String filename; - RandomAccessFile handle; - ByteBuffer backbuffer; - int numfiles; - Hashtable files; // with packfile_t entries } - public static String fs_gamedir; + private String fs_gamedir; - private static String fs_userdir; + private String fs_userdir; - public static cvar_t fs_basedir; + private cvar_t fs_basedir; - public static cvar_t fs_cddir; + private cvar_t fs_cddir; - public static cvar_t fs_gamedirvar; + private cvar_t fs_gamedirvar; - public static class filelink_t { + private static class filelink_t { String from; - int fromlength; - String to; } // with filelink_t entries - public static List fs_links = new LinkedList(); + private List fs_links = new LinkedList<>(); - public static class searchpath_t { + private static class searchpath_t { String filename; - pack_t pack; // only one of filename or pack will be used - searchpath_t next; } - public static searchpath_t fs_searchpaths; + private searchpath_t fs_searchpaths; // without gamedirs - public static searchpath_t fs_base_searchpaths; + private searchpath_t fs_base_searchpaths; /* * All of Quake's data access is through a hierchal file system, but the @@ -135,10 +135,11 @@ public final class FS extends Globals { /* * CreatePath - * + * * Creates any directories needed to store the given filename. */ - public static void CreatePath(String path) { + @Override + public void createPath(String path) { int index = path.lastIndexOf('/'); // -1 if not found and 0 means write to root if (index > 0) { @@ -149,32 +150,16 @@ public final class FS extends Globals { } } - /* - * FCloseFile - * - * For some reason, other dll's can't just call fclose() on files returned - * by FS_FOpenFile... - */ - public static void FCloseFile(RandomAccessFile file) throws IOException { - file.close(); - } - - public static void FCloseFile(InputStream stream) throws IOException { - stream.close(); - } - - public static int FileLength(String filename) { + @Override + public int fileLength(String filename) { searchpath_t search; String netpath; pack_t pak; - filelink_t link; file_from_pak = 0; // check for links first - for (Iterator it = fs_links.iterator(); it.hasNext();) { - link = it.next(); - + for (filelink_t link : fs_links) { if (filename.regionMatches(0, link.from, 0, link.fromlength)) { netpath = link.to + filename.substring(link.fromlength); File file = new File(netpath); @@ -226,28 +211,25 @@ public final class FS extends Globals { return -1; } - public static int file_from_pak = 0; + private int file_from_pak = 0; /* * FOpenFile - * + * * Finds the file in the search path. returns a RadomAccesFile. Used for * streaming data out of either a pak file or a seperate file. */ - public static RandomAccessFile FOpenFile(String filename) - throws IOException { + @Override + public RandomAccessFile FOpenFile(String filename) throws IOException { searchpath_t search; String netpath; pack_t pak; - filelink_t link; - File file = null; + File file; file_from_pak = 0; // check for links first - for (Iterator it = fs_links.iterator(); it.hasNext();) { - link = it.next(); - + for (filelink_t link : fs_links) { // if (!strncmp (filename, link->from, link->fromlength)) if (filename.regionMatches(0, link.from, 0, link.fromlength)) { netpath = link.to + filename.substring(link.fromlength); @@ -308,19 +290,16 @@ public final class FS extends Globals { return null; } - // read in blocks of 64k - public static final int MAX_READ = 0x10000; - /** * Read - * + * * Properly handles partial reads */ - public static void Read(byte[] buffer, int len, RandomAccessFile f) { - + @Override + public void read(byte[] buffer, int len, RandomAccessFile file) { int block, remaining; int offset = 0; - int read = 0; + int read; // read in chunks for progress bar remaining = len; @@ -328,15 +307,18 @@ public final class FS extends Globals { while (remaining != 0) { block = Math.min(remaining, MAX_READ); try { - read = f.read(buffer, offset, block); + read = file.read(buffer, offset, block); } catch (IOException e) { - Com.Error(Defines.ERR_FATAL, e.toString()); + log.error(e.toString()); + throw new RuntimeException("Look log file"); } if (read == 0) { - Com.Error(Defines.ERR_FATAL, "FS_Read: 0 bytes read"); + log.error("FS_Read: 0 bytes read"); + throw new RuntimeException("Look log file"); } else if (read == -1) { - Com.Error(Defines.ERR_FATAL, "FS_Read: -1 bytes read"); + log.error("FS_Read: -1 bytes read"); + throw new RuntimeException("Look log file"); } // // do some progress bar thing here... @@ -348,15 +330,16 @@ public final class FS extends Globals { /* * LoadFile - * + * * Filename are reletive to the quake search path a null buffer will just * return the file content as byte[] */ - public static byte[] LoadFile(String path) { + @Override + public byte[] loadFile(String path) { RandomAccessFile file; byte[] buf = null; - int len = 0; + int len; // TODO hack for bad strings (fuck \0) int index = path.indexOf('\0'); @@ -364,7 +347,7 @@ public final class FS extends Globals { path = path.substring(0, index); // look for it in the filesystem or pack files - len = FileLength(path); + len = fileLength(path); if (len < 1) return null; @@ -373,6 +356,7 @@ public final class FS extends Globals { file = FOpenFile(path); //Read(buf = new byte[len], len, h); buf = new byte[len]; + assert file != null; file.readFully(buf); file.close(); } catch (IOException e) { @@ -383,29 +367,27 @@ public final class FS extends Globals { /* * LoadMappedFile - * + * * Filename are reletive to the quake search path a null buffer will just * return the file content as ByteBuffer (memory mapped) */ - public static ByteBuffer LoadMappedFile(String filename) { + @Override + public ByteBuffer loadMappedFile(String filename) { searchpath_t search; String netpath; pack_t pak; - filelink_t link; - File file = null; + File file; - int fileLength = 0; + int fileLength; FileChannel channel = null; FileInputStream input = null; - ByteBuffer buffer = null; + ByteBuffer buffer; file_from_pak = 0; try { // check for links first - for (Iterator it = fs_links.iterator(); it.hasNext();) { - link = it.next(); - + for (filelink_t link : fs_links) { if (filename.regionMatches(0, link.from, 0, link.fromlength)) { netpath = link.to + filename.substring(link.fromlength); file = new File(netpath); @@ -477,66 +459,52 @@ public final class FS extends Globals { return buffer; } } - } catch (Exception e) { + } catch (Exception ignored) { } try { if (input != null) input.close(); else if (channel != null && channel.isOpen()) channel.close(); - } catch (IOException ioe) { + } catch (IOException ignored) { } return null; } - /* - * FreeFile - */ - public static void FreeFile(byte[] buffer) { - buffer = null; - } - - static final int IDPAKHEADER = (('K' << 24) + ('C' << 16) + ('A' << 8) + 'P'); - - static class dpackheader_t { + private static class dpackheader_t { int ident; // IDPAKHEADER - int dirofs; - int dirlen; } - static final int MAX_FILES_IN_PACK = 4096; - // buffer for C-Strings char[56] - static byte[] tmpText = new byte[packfile_t.NAME_SIZE]; + private byte[] tmpText = new byte[packfile_t.NAME_SIZE]; /* * LoadPackFile - * + * * Takes an explicit (not game tree related) path to a pak file. - * + * * Loads the header and directory, adding the files at the beginning of the * list so they override previous pack files. */ - static pack_t LoadPackFile(String packfile) { - + private pack_t loadPackFile(String packfile) { dpackheader_t header; Hashtable newfiles; RandomAccessFile file; - int numpackfiles = 0; - pack_t pack = null; + int numpackfiles; + pack_t pack; // unsigned checksum; // try { - file = new RandomAccessFile(packfile, "r"); - FileChannel fc = file.getChannel(); + file = new RandomAccessFile(packfile, "r"); + FileChannel fc = file.getChannel(); ByteBuffer packhandle = fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); packhandle.order(ByteOrder.LITTLE_ENDIAN); - + fc.close(); - - if (packhandle == null || packhandle.limit() < 1) + + if (packhandle.limit() < 1) return null; // header = new dpackheader_t(); @@ -553,12 +521,12 @@ public final class FS extends Globals { Com.Error(Defines.ERR_FATAL, packfile + " has " + numpackfiles + " files"); - newfiles = new Hashtable(numpackfiles); + newfiles = new Hashtable<>(numpackfiles); packhandle.position(header.dirofs); // parse the directory - packfile_t entry = null; + packfile_t entry; for (int i = 0; i < numpackfiles; i++) { packhandle.get(tmpText); @@ -577,7 +545,7 @@ public final class FS extends Globals { } pack = new pack_t(); - pack.filename = new String(packfile); + pack.filename = packfile; pack.handle = file; pack.numfiles = numpackfiles; pack.files = newfiles; @@ -589,23 +557,23 @@ public final class FS extends Globals { /* * AddGameDirectory - * + * * Sets fs_gamedir, adds the directory to the head of the path, then loads * and adds pak1.pak pak2.pak ... */ - static void AddGameDirectory(String dir) { + private void addGameDirectory(String dir) { int i; searchpath_t search; pack_t pak; String pakfile; - fs_gamedir = new String(dir); + fs_gamedir = dir; // // add the directory to the search path // ensure fs_userdir is first in searchpath search = new searchpath_t(); - search.filename = new String(dir); + search.filename = dir; if (fs_searchpaths != null) { search.next = fs_searchpaths.next; fs_searchpaths.next = search; @@ -621,7 +589,7 @@ public final class FS extends Globals { if (!(new File(pakfile).canRead())) continue; - pak = LoadPackFile(pakfile); + pak = loadPackFile(pakfile); if (pak == null) continue; @@ -639,7 +607,8 @@ public final class FS extends Globals { * Called to find where to write a file (demos, savegames, etc) * this is modified to /.lwjake2 */ - public static String Gamedir() { + @Override + public String getGamedir() { return (fs_userdir != null) ? fs_userdir : Globals.BASEDIRNAME; } @@ -648,14 +617,16 @@ public final class FS extends Globals { * * Called to find where to write a downloaded file */ - public static String BaseGamedir() { + @Override + public String getBaseGamedir() { return (fs_gamedir != null) ? fs_gamedir : Globals.BASEDIRNAME; } /* * ExecAutoexec */ - public static void ExecAutoexec() { + @Override + public void execAutoexec() { String dir = fs_userdir; String name; @@ -676,14 +647,14 @@ public final class FS extends Globals { /* * SetGamedir - * + * * Sets the gamedir and path to a different directory. */ - public static void SetGamedir(String dir) { + @Override + public void setGamedir(String dir) { searchpath_t next; - if (dir.indexOf("..") != -1 || dir.indexOf("/") != -1 - || dir.indexOf("\\") != -1 || dir.indexOf(":") != -1) { + if (dir.contains("..") || dir.contains("/") || dir.contains("\\") || dir.contains(":")) { log.warn("Gamedir should be a single filename, not a path"); return; } @@ -704,7 +675,6 @@ public final class FS extends Globals { fs_searchpaths.pack = null; } next = fs_searchpaths.next; - fs_searchpaths = null; fs_searchpaths = next; } @@ -722,9 +692,9 @@ public final class FS extends Globals { } else { Cvar.FullSet("gamedir", dir, CVAR_SERVERINFO | CVAR_NOSET); if (fs_cddir.string != null && fs_cddir.string.length() > 0) - AddGameDirectory(fs_cddir.string + '/' + dir); + addGameDirectory(fs_cddir.string + '/' + dir); - AddGameDirectory(fs_basedir.string + '/' + dir); + addGameDirectory(fs_basedir.string + '/' + dir); } } @@ -733,8 +703,8 @@ public final class FS extends Globals { * * Creates a filelink_t */ - public static void Link_f() { - filelink_t entry = null; + private void link_f() { + filelink_t entry; if (Cmd.Argc() != 3) { log.info("USAGE: link "); @@ -751,7 +721,7 @@ public final class FS extends Globals { it.remove(); return; } - entry.to = new String(Cmd.Argv(2)); + entry.to = Cmd.Argv(2); return; } } @@ -759,9 +729,9 @@ public final class FS extends Globals { // create a new link if the is not empty if (Cmd.Argv(2).length() > 0) { entry = new filelink_t(); - entry.from = new String(Cmd.Argv(1)); + entry.from = Cmd.Argv(1); entry.fromlength = entry.from.length(); - entry.to = new String(Cmd.Argv(2)); + entry.to = Cmd.Argv(2); fs_links.add(entry); } } @@ -769,7 +739,8 @@ public final class FS extends Globals { /* * ListFiles */ - public static String[] ListFiles(String findname, int musthave, int canthave) { + @Override + public String[] listFiles(String findname, int musthave, int canthave) { String[] list = new String[0]; File[] files = Sys.FindAll(findname, musthave, canthave); @@ -787,9 +758,9 @@ public final class FS extends Globals { /* * Dir_f */ - public static void Dir_f() { + private void dir_f() { String path = null; - String findname = null; + String findname; String wildcard = "*.*"; String[] dirnames; @@ -797,26 +768,21 @@ public final class FS extends Globals { wildcard = Cmd.Argv(1); } - while ((path = NextPath(path)) != null) { - String tmp = findname; - + while ((path = nextPath(path)) != null) { findname = path + '/' + wildcard; - if (tmp != null) - tmp.replaceAll("\\\\", "/"); - log.info("Directory of {}", findname); log.info("----"); - dirnames = ListFiles(findname, 0, 0); + dirnames = listFiles(findname, 0, 0); if (dirnames.length != 0) { - int index = 0; - for (int i = 0; i < dirnames.length; i++) { - if ((index = dirnames[i].lastIndexOf('/')) > 0) { - log.info(dirnames[i].substring(index + 1, dirnames[i].length())); + int index; + for (String dirname : dirnames) { + if ((index = dirname.lastIndexOf('/')) > 0) { + log.info(dirname.substring(index + 1, dirname.length())); } else { - log.info(dirnames[i]); + log.info(dirname); } } } @@ -827,10 +793,8 @@ public final class FS extends Globals { /* * Path_f */ - public static void Path_f() { - + private void path_f() { searchpath_t s; - filelink_t link; log.info("Current search path:"); for (s = fs_searchpaths; s != null; s = s.next) { @@ -843,18 +807,18 @@ public final class FS extends Globals { } log.info("Links:"); - for (Iterator it = fs_links.iterator(); it.hasNext();) { - link = it.next(); + for (filelink_t link : fs_links) { log.info("{} : {}", link.from, link.to); } } /* * NextPath - * + * * Allows enumerating all of the directories in the search path */ - public static String NextPath(String prevpath) { + @Override + public String nextPath(String prevpath) { searchpath_t s; String prev; @@ -866,7 +830,7 @@ public final class FS extends Globals { if (s.pack != null) continue; - if (prevpath == prev) + if (prevpath.equals(prev)) return s.filename; prev = s.filename; @@ -878,26 +842,15 @@ public final class FS extends Globals { /* * InitFilesystem */ - public static void InitFilesystem() { - Cmd.AddCommand("path", new Runnable() { - public void run() { - Path_f(); - } - }); - Cmd.AddCommand("link", new Runnable() { - public void run() { - Link_f(); - } - }); - Cmd.AddCommand("dir", new Runnable() { - public void run() { - Dir_f(); - } - }); + @Override + public void init() { + Cmd.AddCommand("path", this::path_f); + Cmd.AddCommand("link", this::link_f); + Cmd.AddCommand("dir", this::dir_f); fs_userdir = System.getProperty("user.home") + "/.lwjake2"; - FS.CreatePath(fs_userdir + "/"); - FS.AddGameDirectory(fs_userdir); + createPath(fs_userdir + "/"); + addGameDirectory(fs_userdir); // // basedir @@ -916,7 +869,7 @@ public final class FS extends Globals { // // start up with baseq2 by default // - AddGameDirectory(fs_basedir.string + '/' + Globals.BASEDIRNAME); + addGameDirectory(fs_basedir.string + '/' + Globals.BASEDIRNAME); // any set gamedirs will be freed up to here markBaseSearchPaths(); @@ -928,21 +881,27 @@ public final class FS extends Globals { /** * set baseq2 directory */ - static void setCDDir() { + @Override + public void setCDDir() { fs_cddir = Cvar.Get("cddir", "", CVAR_ARCHIVE); - if (fs_cddir.string.length() > 0) - AddGameDirectory(fs_cddir.string + '/' + Globals.BASEDIRNAME); + if (fs_cddir != null && fs_cddir.string.length() > 0) + addGameDirectory(fs_cddir.string + '/' + Globals.BASEDIRNAME); } - - /** Check for "+set game" override - Used to properly set gamedir */ - static void checkOverride() { - fs_gamedirvar = Cvar.Get("game", "", CVAR_LATCH | CVAR_SERVERINFO); - if (fs_gamedirvar.string.length() > 0) - SetGamedir(fs_gamedirvar.string); + /** + * Check for "+set game" override - Used to properly set gamedir + */ + @Override + public void checkOverride() { + fs_gamedirvar = Cvar.Get("game", "", CVAR_LATCH | CVAR_SERVERINFO); + + if (fs_gamedirvar != null && fs_gamedirvar.string.length() > 0) { + setGamedir(fs_gamedirvar.string); + } } - - static void markBaseSearchPaths() { + + @Override + public void markBaseSearchPaths() { // any set gamedirs will be freed up to here fs_base_searchpaths = fs_searchpaths; } @@ -951,21 +910,30 @@ public final class FS extends Globals { /* * Developer_searchpath */ - public static int Developer_searchpath(int who) { - + @Override + public int developer_searchpath(int who) { // PMM - warning removal // char *start; searchpath_t s; - for (s = fs_searchpaths; s != null; s = s.next) { - if (s.filename.indexOf("xatrix") != -1) + if (s.filename.contains("xatrix")) return 1; - if (s.filename.indexOf("rogue") != -1) + if (s.filename.contains("rogue")) return 2; } return 0; } + + @Override + public int getFileFromPak() { + return file_from_pak; + } + + @Override + public cvar_t getGamedirVar() { + return fs_gamedirvar; + } } \ No newline at end of file diff --git a/src/lwjake2/qcommon/CM.java b/src/lwjake2/qcommon/CM.java index 875ab25..8cbc237 100644 --- a/src/lwjake2/qcommon/CM.java +++ b/src/lwjake2/qcommon/CM.java @@ -37,6 +37,7 @@ import java.nio.IntBuffer; import java.util.Arrays; public class CM { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); public static class cnode_t { cplane_t plane; // ptr @@ -248,7 +249,7 @@ public class CM { // // load the file // - buf = FS.LoadFile(name); + buf = fileSystem.loadFile(name); if (buf == null) Com.Error(Defines.ERR_DROP, "Couldn't load " + name); @@ -283,8 +284,6 @@ public class CM { CMod_LoadAreaPortals(header.lumps[Defines.LUMP_AREAPORTALS]); CMod_LoadVisibility(header.lumps[Defines.LUMP_VISIBILITY]); CMod_LoadEntityString(header.lumps[Defines.LUMP_ENTITIES]); - - FS.FreeFile(buf); CM_InitBoxHull(); @@ -1787,7 +1786,7 @@ public class CM { byte buf[] = new byte[len]; - FS.Read(buf, len, f); + fileSystem.read(buf, len, f); ByteBuffer bb = ByteBuffer.wrap(buf); IntBuffer ib = bb.asIntBuffer(); diff --git a/src/lwjake2/qcommon/Cbuf.java b/src/lwjake2/qcommon/Cbuf.java index 54ddffd..fd43582 100644 --- a/src/lwjake2/qcommon/Cbuf.java +++ b/src/lwjake2/qcommon/Cbuf.java @@ -189,7 +189,7 @@ public final class Cbuf { } - // run the command line + // execute the command line int len = Lib.strlen(line); String cmd = new String(line, 0, len); diff --git a/src/lwjake2/qcommon/Cvar.java b/src/lwjake2/qcommon/Cvar.java index 7944334..3f13727 100644 --- a/src/lwjake2/qcommon/Cvar.java +++ b/src/lwjake2/qcommon/Cvar.java @@ -33,6 +33,7 @@ import java.util.Vector; * Cvar implements console variables. The original code is located in cvar.c */ public class Cvar extends Globals { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /** * @param var_name @@ -194,8 +195,8 @@ public class Cvar extends Globals { var.value = 0.0f; } if (var.name.equals("game")) { - FS.SetGamedir(var.string); - FS.ExecAutoexec(); + fileSystem.setGamedir(var.string); + fileSystem.execAutoexec(); } } return var; @@ -384,8 +385,8 @@ public class Cvar extends Globals { var.value = 0.0f; } if (var.name.equals("game")) { - FS.SetGamedir(var.string); - FS.ExecAutoexec(); + fileSystem.setGamedir(var.string); + fileSystem.execAutoexec(); } } } diff --git a/src/lwjake2/qcommon/FileSystem.java b/src/lwjake2/qcommon/FileSystem.java new file mode 100644 index 0000000..e46f8de --- /dev/null +++ b/src/lwjake2/qcommon/FileSystem.java @@ -0,0 +1,37 @@ +/* + * DmitriyMX + * 2018-03-06 + */ +package lwjake2.qcommon; + +import lwjake2.game.cvar_t; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; + +public interface FileSystem { + void init(); + byte[] loadFile(String path); + void read(byte[] buffer, int len, RandomAccessFile file); + void execAutoexec(); + void createPath(String path); + int fileLength(String filename); + String nextPath(String prevpath); + String[] listFiles(String findname, int musthave, int canthave); + + int developer_searchpath(int who); + cvar_t getGamedirVar(); + + void setGamedir(String dir); + String getGamedir(); + + String getBaseGamedir(); + + ByteBuffer loadMappedFile(String filename); + void setCDDir(); + void markBaseSearchPaths(); + void checkOverride(); + RandomAccessFile FOpenFile(String filename) throws IOException; + int getFileFromPak(); +} diff --git a/src/lwjake2/qcommon/Qcommon.java b/src/lwjake2/qcommon/Qcommon.java index caa84e1..299d59d 100644 --- a/src/lwjake2/qcommon/Qcommon.java +++ b/src/lwjake2/qcommon/Qcommon.java @@ -39,6 +39,7 @@ import java.io.IOException; */ @Slf4j public final class Qcommon extends Globals { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); public static final String BUILDSTRING = "Java " + System.getProperty("java.version");; public static final String CPUSTRING = System.getProperty("os.arch"); @@ -69,13 +70,13 @@ public final class Qcommon extends Globals { Cbuf.AddEarlyCommands(false); Cbuf.Execute(); - FS.InitFilesystem(); + fileSystem.init(); reconfigure(false); - FS.setCDDir(); // use cddir from config.cfg - FS.markBaseSearchPaths(); // mark the default search paths - FS.checkOverride(); + fileSystem.setCDDir(); // use cddir from config.cfg + fileSystem.markBaseSearchPaths(); // mark the default search paths + fileSystem.checkOverride(); reconfigure(true); // reload default.cfg and config.cfg diff --git a/src/lwjake2/render/DummyRenderer.java b/src/lwjake2/render/DummyRenderer.java index 2440752..72511eb 100644 --- a/src/lwjake2/render/DummyRenderer.java +++ b/src/lwjake2/render/DummyRenderer.java @@ -163,7 +163,7 @@ public class DummyRenderer implements refexport_t { } /* (non-Javadoc) - * @see jake2.client.refexport_t#updateScreen(jake2.qcommon.Runnable) + * @see jake2.client.refexport_t#updateScreen(java.lang.Runnable) */ public void updateScreen(Runnable callback) { callback.run(); diff --git a/src/lwjake2/render/lwjgl/Image.java b/src/lwjake2/render/lwjgl/Image.java index 0374fd7..ef4c20e 100644 --- a/src/lwjake2/render/lwjgl/Image.java +++ b/src/lwjake2/render/lwjgl/Image.java @@ -22,10 +22,7 @@ import lwjake2.Defines; import lwjake2.client.VID; import lwjake2.client.particle_t; import lwjake2.game.cvar_t; -import lwjake2.qcommon.Com; -import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; -import lwjake2.qcommon.qfiles; +import lwjake2.qcommon.*; import lwjake2.render.image_t; import lwjake2.util.Lib; import lwjake2.util.Vargs; @@ -51,6 +48,7 @@ import org.lwjgl.opengl.GL11; * @author cwei */ public abstract class Image extends Main { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); image_t draw_chars; @@ -450,7 +448,7 @@ public abstract class Image extends Main { // // load the file // - byte[] raw = FS.LoadFile(filename); + byte[] raw = fileSystem.loadFile(filename); if (raw == null) { VID.Printf(Defines.PRINT_DEVELOPER, "Bad pcx file " + filename + '\n'); @@ -547,7 +545,7 @@ public abstract class Image extends Main { // // load the file // - raw = FS.LoadFile(name); + raw = fileSystem.loadFile(name); if (raw == null) { @@ -1446,7 +1444,7 @@ public abstract class Image extends Main { image_t image = null; - byte[] raw = FS.LoadFile(name); + byte[] raw = fileSystem.loadFile(name); if (raw == null) { VID.Printf(Defines.PRINT_ALL, "GL_FindImage: can't load " + name + '\n'); return r_notexture; @@ -1630,7 +1628,7 @@ public abstract class Image extends Main { Draw_GetPalette(); if (qglColorTableEXT) { - gl_state.d_16to8table = FS.LoadFile("pics/16to8.dat"); + gl_state.d_16to8table = fileSystem.loadFile("pics/16to8.dat"); if (gl_state.d_16to8table == null) Com.Error(Defines.ERR_FATAL, "Couldn't load pics/16to8.pcx"); } diff --git a/src/lwjake2/render/lwjgl/Misc.java b/src/lwjake2/render/lwjgl/Misc.java index cd32bd7..c78e385 100644 --- a/src/lwjake2/render/lwjgl/Misc.java +++ b/src/lwjake2/render/lwjgl/Misc.java @@ -20,7 +20,7 @@ package lwjake2.render.lwjgl; import lwjake2.Defines; import lwjake2.client.VID; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.BaseQ2FileSystem; import java.io.File; import java.io.IOException; @@ -29,6 +29,7 @@ import java.nio.FloatBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; +import lwjake2.qcommon.FileSystem; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.ARBMultitexture; import org.lwjgl.opengl.EXTPointParameters; @@ -42,6 +43,7 @@ import org.lwjgl.opengl.GL12; * @author cwei */ public abstract class Misc extends Mesh { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /* ================== @@ -121,8 +123,8 @@ public abstract class Misc extends Mesh { ================== */ void GL_ScreenShot_f() { - StringBuffer sb = new StringBuffer(FS.Gamedir() + "/scrshot/jake00.tga"); - FS.CreatePath(sb.toString()); + StringBuffer sb = new StringBuffer(fileSystem.getGamedir() + "/scrshot/jake00.tga"); + fileSystem.createPath(sb.toString()); File file = new File(sb.toString()); // find a valid file name int i = 0; int offset = sb.length() - 6; diff --git a/src/lwjake2/render/lwjgl/Model.java b/src/lwjake2/render/lwjgl/Model.java index c1f01eb..4a7e410 100644 --- a/src/lwjake2/render/lwjgl/Model.java +++ b/src/lwjake2/render/lwjgl/Model.java @@ -24,7 +24,8 @@ import lwjake2.game.cplane_t; import lwjake2.game.cvar_t; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.lump_t; import lwjake2.qcommon.qfiles; import lwjake2.qcommon.texinfo_t; @@ -54,6 +55,7 @@ import org.lwjgl.BufferUtils; * @author cwei */ public abstract class Model extends Surf { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); // models.c -- model loading and caching @@ -271,7 +273,7 @@ public abstract class Model extends Surf { // // load the file // - fileBuffer = FS.LoadFile(name); + fileBuffer = fileSystem.loadFile(name); if (fileBuffer == null) { diff --git a/src/lwjake2/server/SV_CCMDS.java b/src/lwjake2/server/SV_CCMDS.java index fbbb684..9c8019d 100644 --- a/src/lwjake2/server/SV_CCMDS.java +++ b/src/lwjake2/server/SV_CCMDS.java @@ -30,7 +30,8 @@ import lwjake2.game.cvar_t; import lwjake2.qcommon.CM; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.MSG; import lwjake2.qcommon.Netchan; import lwjake2.qcommon.SZ; @@ -50,6 +51,7 @@ import java.util.Calendar; @Slf4j public class SV_CCMDS { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /* =============================================================================== @@ -176,13 +178,13 @@ public class SV_CCMDS { Com.DPrintf("SV_WipeSaveGame(" + savename + ")\n"); - name = FS.Gamedir() + "/save/" + savename + "/server.ssv"; + name = fileSystem.getGamedir() + "/save/" + savename + "/server.ssv"; remove(name); - name = FS.Gamedir() + "/save/" + savename + "/game.ssv"; + name = fileSystem.getGamedir() + "/save/" + savename + "/game.ssv"; remove(name); - name = FS.Gamedir() + "/save/" + savename + "/*.sav"; + name = fileSystem.getGamedir() + "/save/" + savename + "/*.sav"; File f = Sys.FindFirst(name, 0, 0); while (f != null) { @@ -191,7 +193,7 @@ public class SV_CCMDS { } Sys.FindClose(); - name = FS.Gamedir() + "/save/" + savename + "/*.sv2"; + name = fileSystem.getGamedir() + "/save/" + savename + "/*.sv2"; f = Sys.FindFirst(name, 0, 0); @@ -281,23 +283,23 @@ public class SV_CCMDS { SV_WipeSavegame(dst); // copy the savegame over - name = FS.Gamedir() + "/save/" + src + "/server.ssv"; - name2 = FS.Gamedir() + "/save/" + dst + "/server.ssv"; - FS.CreatePath(name2); + name = fileSystem.getGamedir() + "/save/" + src + "/server.ssv"; + name2 = fileSystem.getGamedir() + "/save/" + dst + "/server.ssv"; + fileSystem.createPath(name2); CopyFile(name, name2); - name = FS.Gamedir() + "/save/" + src + "/game.ssv"; - name2 = FS.Gamedir() + "/save/" + dst + "/game.ssv"; + name = fileSystem.getGamedir() + "/save/" + src + "/game.ssv"; + name2 = fileSystem.getGamedir() + "/save/" + dst + "/game.ssv"; CopyFile(name, name2); - String name1 = FS.Gamedir() + "/save/" + src + "/"; - name = FS.Gamedir() + "/save/" + src + "/*.sav"; + String name1 = fileSystem.getGamedir() + "/save/" + src + "/"; + name = fileSystem.getGamedir() + "/save/" + src + "/*.sav"; found = Sys.FindFirst(name, 0, 0); while (found != null) { name = name1 + found.getName(); - name2 = FS.Gamedir() + "/save/" + dst + "/" + found.getName(); + name2 = fileSystem.getGamedir() + "/save/" + dst + "/" + found.getName(); CopyFile(name, name2); @@ -324,7 +326,7 @@ public class SV_CCMDS { Com.DPrintf("SV_WriteLevelFile()\n"); - name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; + name = fileSystem.getGamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; try { f = new QuakeFile(name, "rw"); @@ -340,7 +342,7 @@ public class SV_CCMDS { e.printStackTrace(); } - name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; + name = fileSystem.getGamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; GameSave.WriteLevel(name); } /* @@ -356,7 +358,7 @@ public class SV_CCMDS { Com.DPrintf("SV_ReadLevelFile()\n"); - name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; + name = fileSystem.getGamedir() + "/save/current/" + SV_INIT.sv.name + ".sv2"; try { f = new QuakeFile(name, "r"); @@ -372,7 +374,7 @@ public class SV_CCMDS { e1.printStackTrace(); } - name = FS.Gamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; + name = fileSystem.getGamedir() + "/save/current/" + SV_INIT.sv.name + ".sav"; GameSave.ReadLevel(name); } /* @@ -389,7 +391,7 @@ public class SV_CCMDS { Com.DPrintf("SV_WriteServerFile(" + (autosave ? "true" : "false") + ")\n"); - filename = FS.Gamedir() + "/save/current/server.ssv"; + filename = fileSystem.getGamedir() + "/save/current/server.ssv"; try { f = new QuakeFile(filename, "rw"); @@ -442,7 +444,7 @@ public class SV_CCMDS { } // write game state - filename = FS.Gamedir() + "/save/current/game.ssv"; + filename = fileSystem.getGamedir() + "/save/current/game.ssv"; GameSave.WriteGame(filename, autosave); } /* @@ -460,7 +462,7 @@ public class SV_CCMDS { Com.DPrintf("SV_ReadServerFile()\n"); - filename = FS.Gamedir() + "/save/current/server.ssv"; + filename = fileSystem.getGamedir() + "/save/current/server.ssv"; f = new QuakeFile(filename, "r"); @@ -487,7 +489,7 @@ public class SV_CCMDS { SV_INIT.svs.mapcmd = mapcmd; // read game state - filename = FS.Gamedir() + "/save/current/game.ssv"; + filename = fileSystem.getGamedir() + "/save/current/game.ssv"; GameSave.ReadGame(filename); } catch (Exception e) { @@ -538,7 +540,7 @@ public class SV_CCMDS { Com.DPrintf("SV_GameMap(" + Cmd.Argv(1) + ")\n"); - FS.CreatePath(FS.Gamedir() + "/save/current/"); + fileSystem.createPath(fileSystem.getGamedir() + "/save/current/"); // check for clearing the current savegame map = Cmd.Argv(1); @@ -599,7 +601,7 @@ public class SV_CCMDS { map = Cmd.Argv(1); if (map.indexOf(".") < 0) { expanded = "maps/" + map + ".bsp"; - if (FS.LoadFile(expanded) == null) { + if (fileSystem.loadFile(expanded) == null) { Com.Printf("Can't find " + expanded + "\n"); return; @@ -644,7 +646,7 @@ public class SV_CCMDS { } // make sure the server.ssv file exists - name = FS.Gamedir() + "/save/" + Cmd.Argv(1) + "/server.ssv"; + name = fileSystem.getGamedir() + "/save/" + Cmd.Argv(1) + "/server.ssv"; try { f = new RandomAccessFile(name, "r"); } @@ -913,10 +915,10 @@ public class SV_CCMDS { // // open the demo file // - name = FS.Gamedir() + "/demos/" + Cmd.Argv(1) + ".dm2"; + name = fileSystem.getGamedir() + "/demos/" + Cmd.Argv(1) + ".dm2"; Com.Printf("recording to " + name + ".\n"); - FS.CreatePath(name); + fileSystem.createPath(name); try { SV_INIT.svs.demofile = new RandomAccessFile(name, "rw"); } diff --git a/src/lwjake2/server/SV_INIT.java b/src/lwjake2/server/SV_INIT.java index 613109b..fa1da8a 100644 --- a/src/lwjake2/server/SV_INIT.java +++ b/src/lwjake2/server/SV_INIT.java @@ -32,7 +32,8 @@ import lwjake2.qcommon.CM; import lwjake2.qcommon.Cbuf; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.MSG; import lwjake2.qcommon.PMove; import lwjake2.qcommon.SZ; @@ -45,6 +46,7 @@ import java.io.RandomAccessFile; @Slf4j public class SV_INIT { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /** * SV_FindIndex. */ @@ -134,7 +136,7 @@ public class SV_INIT { if (Cvar.VariableValue("deathmatch") != 0) return; - name = FS.Gamedir() + "/save/current/" + sv.name + ".sav"; + name = fileSystem.getGamedir() + "/save/current/" + sv.name + ".sav"; try { f = new RandomAccessFile(name, "r"); } diff --git a/src/lwjake2/server/SV_MAIN.java b/src/lwjake2/server/SV_MAIN.java index 69d1928..3755a51 100644 --- a/src/lwjake2/server/SV_MAIN.java +++ b/src/lwjake2/server/SV_MAIN.java @@ -29,7 +29,6 @@ import lwjake2.game.cvar_t; import lwjake2.game.edict_t; import lwjake2.qcommon.Com; import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; import lwjake2.qcommon.MSG; import lwjake2.qcommon.Netchan; import lwjake2.qcommon.SZ; @@ -116,7 +115,6 @@ public class SV_MAIN { } if (drop.download != null) { - FS.FreeFile(drop.download); drop.download = null; } diff --git a/src/lwjake2/server/SV_USER.java b/src/lwjake2/server/SV_USER.java index 61cef8c..2c1287e 100644 --- a/src/lwjake2/server/SV_USER.java +++ b/src/lwjake2/server/SV_USER.java @@ -27,17 +27,13 @@ import lwjake2.game.PlayerClient; import lwjake2.game.edict_t; import lwjake2.game.entity_state_t; import lwjake2.game.usercmd_t; -import lwjake2.qcommon.Cbuf; -import lwjake2.qcommon.Com; -import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; -import lwjake2.qcommon.MSG; -import lwjake2.qcommon.SZ; +import lwjake2.qcommon.*; import lwjake2.util.Lib; import java.io.IOException; public class SV_USER { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); static edict_t sv_player; @@ -120,7 +116,7 @@ public class SV_USER { name = "demos/" + SV_INIT.sv.name; try { - SV_INIT.sv.demofile = FS.FOpenFile(name); + SV_INIT.sv.demofile = fileSystem.FOpenFile(name); } catch (IOException e) { Com.Error(Defines.ERR_DROP, "Couldn't open " + name + "\n"); } @@ -365,7 +361,6 @@ public class SV_USER { if (SV_MAIN.sv_client.downloadcount != SV_MAIN.sv_client.downloadsize) return; - FS.FreeFile(SV_MAIN.sv_client.download); SV_MAIN.sv_client.download = null; } @@ -409,9 +404,9 @@ public class SV_USER { } if (SV_MAIN.sv_client.download != null) - FS.FreeFile(SV_MAIN.sv_client.download); + SV_MAIN.sv_client.download = null; - SV_MAIN.sv_client.download = FS.LoadFile(name); + SV_MAIN.sv_client.download = fileSystem.loadFile(name); // rst: this handles loading errors, no message yet visible if (SV_MAIN.sv_client.download == null) @@ -429,11 +424,10 @@ public class SV_USER { // came from a pak file, don't // allow // download ZOID - || (name.startsWith("maps/") && FS.file_from_pak != 0)) { + || (name.startsWith("maps/") && fileSystem.getFileFromPak() != 0)) { Com.DPrintf("Couldn't download " + name + " to " + SV_MAIN.sv_client.name + "\n"); if (SV_MAIN.sv_client.download != null) { - FS.FreeFile(SV_MAIN.sv_client.download); SV_MAIN.sv_client.download = null; } diff --git a/src/lwjake2/sound/WaveLoader.java b/src/lwjake2/sound/WaveLoader.java index 50e56ab..cca5b1d 100644 --- a/src/lwjake2/sound/WaveLoader.java +++ b/src/lwjake2/sound/WaveLoader.java @@ -20,14 +20,16 @@ package lwjake2.sound; import lombok.extern.slf4j.Slf4j; import lwjake2.Defines; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.Com; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; /** * SND_MEM */ @Slf4j public class WaveLoader { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /** * The ResampleSfx can squeeze and stretch samples to a default sample rate. * Since Joal and lwjgl sound drivers support this, we don't need it and the samples @@ -66,7 +68,7 @@ public class WaveLoader { else namebuffer = "sound/" + name; - byte[] data = FS.LoadFile(namebuffer); + byte[] data = fileSystem.loadFile(namebuffer); if (data == null) { Com.DPrintf("Couldn't load " + namebuffer + "\n"); diff --git a/src/lwjake2/sound/lwjgl/LWJGLSoundImpl.java b/src/lwjake2/sound/lwjgl/LWJGLSoundImpl.java index 473dec2..44eb8b7 100644 --- a/src/lwjake2/sound/lwjgl/LWJGLSoundImpl.java +++ b/src/lwjake2/sound/lwjgl/LWJGLSoundImpl.java @@ -25,9 +25,7 @@ import lwjake2.game.Cmd; import lwjake2.game.GameBase; import lwjake2.game.cvar_t; import lwjake2.game.entity_state_t; -import lwjake2.qcommon.Com; -import lwjake2.qcommon.Cvar; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.*; import lwjake2.sound.S; import lwjake2.sound.Sound; import lwjake2.sound.WaveLoader; @@ -57,6 +55,7 @@ import org.lwjgl.openal.OpenALException; */ @Slf4j public final class LWJGLSoundImpl implements Sound { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); static { S.register(new LWJGLSoundImpl()); }; @@ -379,14 +378,14 @@ public final class LWJGLSoundImpl implements Sound { // fall back strategies // // not found , so see if it exists - if (FS.FileLength(sexedFilename.substring(1)) > 0) { + if (fileSystem.fileLength(sexedFilename.substring(1)) > 0) { // yes, register it return RegisterSound(sexedFilename); } // try it with the female sound in the pak0.pak if (model.equalsIgnoreCase("female")) { String femaleFilename = "player/female/" + base.substring(1); - if (FS.FileLength("sound/" + femaleFilename) > 0) + if (fileSystem.fileLength("sound/" + femaleFilename) > 0) return AliasName(sexedFilename, femaleFilename); } // no chance, revert to the male sound in the pak0.pak diff --git a/src/lwjake2/util/Lib.java b/src/lwjake2/util/Lib.java index 5bba8b3..9ec91be 100644 --- a/src/lwjake2/util/Lib.java +++ b/src/lwjake2/util/Lib.java @@ -20,8 +20,9 @@ package lwjake2.util; import lombok.extern.slf4j.Slf4j; import lwjake2.Globals; +import lwjake2.qcommon.BaseQ2FileSystem; import lwjake2.qcommon.Com; -import lwjake2.qcommon.FS; +import lwjake2.qcommon.FileSystem; import java.io.File; import java.io.IOException; @@ -34,6 +35,7 @@ import java.nio.IntBuffer; @Slf4j public class Lib { + private static final FileSystem fileSystem = BaseQ2FileSystem.getInstance(); /** Converts a vector to a string. */ public static String vtos(float[] v) { return (int) v[0] + " " + (int) v[1] + " " + (int) v[2]; @@ -240,7 +242,7 @@ public class Lib { /** Like in libc */ public static String freadString(RandomAccessFile f, int len) { byte buffer[] = new byte[len]; - FS.Read(buffer, len, f); + fileSystem.read(buffer, len, f); return Lib.CtoJava(buffer); }