From 2558076a5234657eb8e59235a3417659f40a5265 Mon Sep 17 00:00:00 2001 From: Gabor Bata Date: Fri, 29 Sep 2023 13:09:45 +0200 Subject: [PATCH] Fixed loading alternate configurations * Fix writing alternate config files i.e. when -config argument is used Previously the default.cfg is truncated to empty file in that case, and the alternate config file is not updated. * Add classic Doom key controls configuration support (classic.cfg) Classic Doom key controls are using the arrow keys instead of WASD. Added mapping to arrow keys in vanilla key behavior mode. * Fix/suppress some compile warnings, remove deprecated API usage Removed deprecated API calls to make sure Mocha Doom will compile with future Java versions. --- classic.cfg | 43 ++++++++++++++++++++++ src/awt/EventBase.java | 2 + src/doom/ConfigBase.java | 50 ++++++++++++++++++++++--- src/doom/ConfigManager.java | 8 +++- src/doom/DoomMain.java | 63 +++++++++++++++++--------------- src/doom/DoomStatus.java | 4 +- src/mochadoom/Loggers.java | 1 + src/rr/SimpleTextureManager.java | 2 +- src/utils/C2JUtils.java | 25 +++++++------ src/w/DoomIO.java | 4 +- src/w/WadLoader.java | 18 +++++---- 11 files changed, 159 insertions(+), 61 deletions(-) create mode 100644 classic.cfg diff --git a/classic.cfg b/classic.cfg new file mode 100644 index 00000000..293c99de --- /dev/null +++ b/classic.cfg @@ -0,0 +1,43 @@ +mouse_sensitivity 5 +sfx_volume 8 +music_volume 8 +show_messages 1 +key_right 77 +key_left 75 +key_up 72 +key_down 80 +key_strafeleft 51 +key_straferight 52 +key_fire 29 +key_use 57 +key_strafe 56 +key_speed 54 +use_mouse 0 +mouseb_fire 0 +mouseb_strafe 1 +mouseb_forward 2 +use_joystick 0 +joyb_fire 0 +joyb_strafe 1 +joyb_use 3 +joyb_speed 2 +screenblocks 10 +detaillevel 0 +snd_channels 8 +snd_musicdevice 3 +snd_sfxdevice 3 +snd_sbport 0 +snd_sbirq 0 +snd_sbdma 0 +snd_mport 0 +usegamma 0 +chatmacro0 "No" +chatmacro1 "I'm ready to kick butt!" +chatmacro2 "I'm OK." +chatmacro3 "I'm not looking too good!" +chatmacro4 "Help!" +chatmacro5 "You suck!" +chatmacro6 "Next time, scumbag..." +chatmacro7 "Come here!" +chatmacro8 "I'll take care of it." +chatmacro9 "Yes" diff --git a/src/awt/EventBase.java b/src/awt/EventBase.java index 489fcc0b..e2fd4150 100644 --- a/src/awt/EventBase.java +++ b/src/awt/EventBase.java @@ -60,6 +60,7 @@ static & EventBase> Optional findById(H[] values, int e @SafeVarargs static & EventBase> Relation[] Relate(H src, H... dests) { + @SuppressWarnings("unchecked") final IntFunction[]> arrayer = Relation[]::new; return Arrays.stream(dests) .map(dest -> new Relation<>(src, dest)) @@ -166,6 +167,7 @@ public KeyStateInterest( final class KeyStateHolder & EventBase> { private final Set holdingSet; private final LinkedHashSet> keyInterests; + @SuppressWarnings("unchecked") private final IntFunction[]> generator = KeyStateInterest[]::new; public KeyStateHolder() { diff --git a/src/doom/ConfigBase.java b/src/doom/ConfigBase.java index 06e61290..d3d75904 100644 --- a/src/doom/ConfigBase.java +++ b/src/doom/ConfigBase.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.Optional; import m.Settings; import utils.OSValidator; @@ -63,19 +64,30 @@ public static class Files { public final Comparator comparator; public final String fileName; + // flags that configuration is provided by the -config argument + public final boolean alternate; + public boolean changed = true; - private String[] paths; - + public Files(String fileName) { - this(fileName, Comparator.comparing(Enum::name, String::compareTo)); + this(fileName, false); + } + + public Files(String fileName, boolean alternate) { + this(fileName, Comparator.comparing(Enum::name, String::compareTo), alternate); } public Files(String fileName, Comparator comparator) { + this(fileName, comparator, false); + } + + public Files(String fileName, Comparator comparator, boolean alternate) { this.fileName = fileName; this.comparator = comparator; + this.alternate = alternate; } - + public Optional firstValidPathIO() { return Arrays.stream(getPaths()) .map(ResourceIO::new) @@ -86,7 +98,33 @@ public Optional firstValidPathIO() { public ResourceIO workDirIO() { return new ResourceIO(getFolder() + fileName); } - + + @Override + public int hashCode() { + int hash = 7; + hash = 53 * hash + Objects.hashCode(this.fileName); + hash = 53 * hash + (this.alternate ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Files other = (Files) obj; + if (this.alternate != other.alternate) { + return false; + } + return Objects.equals(this.fileName, other.fileName); + } + /** * Get file / paths combinations * @@ -146,7 +184,7 @@ public static List getFiles() { */ if (!Engine.getCVM() .with(CommandVariable.CONFIG, 0, (String[] fileNames) -> - Arrays.stream(fileNames).map(Files::new).forEach(ret::add)) + Arrays.stream(fileNames).map(fileName -> new Files(fileName, true)).forEach(ret::add)) /** * If there is no such argument, load default.cfg (or .doomrc) and mochadoom.cfg diff --git a/src/doom/ConfigManager.java b/src/doom/ConfigManager.java index 34b3082e..7f713602 100644 --- a/src/doom/ConfigManager.java +++ b/src/doom/ConfigManager.java @@ -188,11 +188,17 @@ public T getValue(final Settings setting, final Class valueType) { public void SaveDefaults() { SETTINGS_MAP.forEach((file, settings) -> { + // skip writing settings which are not part of the loaded config files, + // this helps to not overwrite default.cfg with empty content in case we're using the -config argument + if (!this.configFiles.contains(file)) { + return; + } + // do not write unless there is changes if (!file.changed) { return; } - + // choose existing config file or create one in current working directory final ResourceIO rio = file.firstValidPathIO().orElseGet(file::workDirIO); final Iterator it = settings.stream().sorted(file.comparator).iterator(); diff --git a/src/doom/DoomMain.java b/src/doom/DoomMain.java index a93b8074..e32a3e6e 100644 --- a/src/doom/DoomMain.java +++ b/src/doom/DoomMain.java @@ -30,6 +30,7 @@ import f.EndLevel; import f.Finale; import f.Wiper; +import g.Signals; import static g.Signals.ScanCode.*; import hu.HU; import i.DiskDrawer; @@ -1289,21 +1290,7 @@ public boolean Responder(event_t ev) { ev.withKey(sc -> { gamekeydown[sc.ordinal()] = true; if (vanillaKeyBehavior) { - switch(sc) { - case SC_LSHIFT: - case SC_RSHIFT: - gamekeydown[SC_RSHIFT.ordinal()] = gamekeydown[SC_LSHIFT.ordinal()] = true; - break; - case SC_LCTRL: - case SC_RCTRL: - gamekeydown[SC_RCTRL.ordinal()] = gamekeydown[SC_LCTRL.ordinal()] = true; - break; - case SC_LALT: - case SC_RALT: - gamekeydown[SC_RALT.ordinal()] = gamekeydown[SC_LALT.ordinal()] = true; - break; - default: break; - } + handleVanillaKeys(sc, true); } }); return true; // eat key down events @@ -1318,21 +1305,7 @@ public boolean Responder(event_t ev) { ev.withKey(sc -> { gamekeydown[sc.ordinal()] = false; if (vanillaKeyBehavior) { - switch(sc) { - case SC_LSHIFT: - case SC_RSHIFT: - gamekeydown[SC_RSHIFT.ordinal()] = gamekeydown[SC_LSHIFT.ordinal()] = false; - break; - case SC_LCTRL: - case SC_RCTRL: - gamekeydown[SC_RCTRL.ordinal()] = gamekeydown[SC_LCTRL.ordinal()] = false; - break; - case SC_LALT: - case SC_RALT: - gamekeydown[SC_RALT.ordinal()] = gamekeydown[SC_LALT.ordinal()] = false; - break; - default: break; - } + handleVanillaKeys(sc, false); } }); return false; // always let key up events filter down @@ -1368,6 +1341,36 @@ public boolean Responder(event_t ev) { return false; } + private void handleVanillaKeys(Signals.ScanCode sc, boolean keyDown) { + switch(sc) { + case SC_LSHIFT: + case SC_RSHIFT: + gamekeydown[SC_RSHIFT.ordinal()] = gamekeydown[SC_LSHIFT.ordinal()] = keyDown; + break; + case SC_LCTRL: + case SC_RCTRL: + gamekeydown[SC_RCTRL.ordinal()] = gamekeydown[SC_LCTRL.ordinal()] = keyDown; + break; + case SC_LALT: + case SC_RALT: + gamekeydown[SC_RALT.ordinal()] = gamekeydown[SC_LALT.ordinal()] = keyDown; + break; + case SC_UP: + gamekeydown[SC_NUMKEY8.ordinal()] = keyDown; + break; + case SC_DOWN: + gamekeydown[SC_NUMKEY2.ordinal()] = keyDown; + break; + case SC_LEFT: + gamekeydown[SC_NUMKEY4.ordinal()] = keyDown; + break; + case SC_RIGHT: + gamekeydown[SC_NUMKEY6.ordinal()] = keyDown; + break; + default: break; + } + } + private final String turbomessage="is turbo!"; /** diff --git a/src/doom/DoomStatus.java b/src/doom/DoomStatus.java index 178c23de..3b51323f 100644 --- a/src/doom/DoomStatus.java +++ b/src/doom/DoomStatus.java @@ -390,8 +390,8 @@ public void setPaused(boolean paused) { protected byte[] savebuffer; /* TODO Proper reconfigurable controls. Defaults hardcoded for now. T3h h4x, d00d. */ - public int key_right = SC_NUMKEY6.ordinal(); - public int key_left = SC_NUMKEY4.ordinal(); + public int key_right = SC_RIGHT.ordinal(); + public int key_left = SC_LEFT.ordinal(); public int key_up = SC_W.ordinal(); public int key_down = SC_S.ordinal(); public int key_strafeleft = SC_A.ordinal(); diff --git a/src/mochadoom/Loggers.java b/src/mochadoom/Loggers.java index 5bc945be..3466910b 100644 --- a/src/mochadoom/Loggers.java +++ b/src/mochadoom/Loggers.java @@ -82,6 +82,7 @@ public static & EventBase lastHandler = handler; + @SuppressWarnings("unchecked") final IntFunction[]> arrayGenerator = EventBase[]::new; final EventBase[] depends = actionStateHolder .cooperations(handler, RelationType.DEPEND) diff --git a/src/rr/SimpleTextureManager.java b/src/rr/SimpleTextureManager.java index 2d7ab17a..467d799a 100644 --- a/src/rr/SimpleTextureManager.java +++ b/src/rr/SimpleTextureManager.java @@ -239,7 +239,7 @@ public void InitTextures () throws IOException mtexture.unpack(maptex[texset]); // MAES: the HashTable only needs to know the correct names. - TextureCache.put(mtexture.name.toUpperCase(), new Integer(i)); + TextureCache.put(mtexture.name.toUpperCase(), Integer.valueOf(i)); // We don't need to manually copy trivial fields. textures[i]=new texture_t(); diff --git a/src/utils/C2JUtils.java b/src/utils/C2JUtils.java index 8509c295..4b816c5f 100644 --- a/src/utils/C2JUtils.java +++ b/src/utils/C2JUtils.java @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; @@ -167,9 +168,9 @@ public static String nullTerminatedString(char[] s) { public static void initArrayOfObjects(T[] os, Class c) { try { for (int i = 0; i < os.length; i++) { - os[i] = c.newInstance(); + os[i] = c.getDeclaredConstructor().newInstance(); } - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); System.err.println("Failure to allocate " + os.length + " objects of class" + c.getName() + "!"); @@ -192,9 +193,9 @@ public static void initArrayOfObjects(T[] os) { Class c = (Class) os.getClass().getComponentType(); try { for (int i = 0; i < os.length; i++) { - os[i] = c.newInstance(); + os[i] = c.getDeclaredConstructor().newInstance(); } - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); System.err.println("Failure to allocate " + os.length + " objects of class " + c.getName() + "!"); @@ -229,9 +230,9 @@ public static T[] createArrayOfObjects(Class c, int num) { try { for (int i = 0; i < os.length; i++) { - os[i] = c.newInstance(); + os[i] = c.getDeclaredConstructor().newInstance(); } - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); System.err.println("Failure to instantiate " + os.length + " objects of class " + c.getName() + "!"); System.exit(-1); @@ -264,9 +265,9 @@ public static T[] createArrayOfObjects(T instance, int num) { try { for (int i = 0; i < os.length; i++) { - os[i] = c.newInstance(); + os[i] = c.getDeclaredConstructor().newInstance(); } - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); System.err.println("Failure to instantiate " + os.length + " objects of class " + c.getName() + "!"); @@ -294,9 +295,9 @@ public static void initArrayOfObjects(T[] os, int startpos, int endpos) { Class c = (Class) os.getClass().getComponentType(); try { for (int i = startpos; i < endpos; i++) { - os[i] = c.newInstance(); + os[i] = c.getDeclaredConstructor().newInstance(); } - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); System.err.println("Failure to allocate " + os.length + " objects of class " + c.getName() + "!"); @@ -708,9 +709,9 @@ public static T[] resize(T[] oldarray, int newsize) { T cls; try { - cls = (T) oldarray.getClass().getComponentType().newInstance(); + cls = (T) oldarray.getClass().getComponentType().getDeclaredConstructor().newInstance(); return resize(cls, oldarray, newsize); - } catch (IllegalAccessException | InstantiationException e) { + } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) { System.err.println("Cannot autodetect type in resizeArray.\n"); return null; } diff --git a/src/w/DoomIO.java b/src/w/DoomIO.java index a3c48639..57756fd0 100644 --- a/src/w/DoomIO.java +++ b/src/w/DoomIO.java @@ -242,7 +242,7 @@ public static void readObjectArrayWithReflection(DataInputStream dis,IReadableDo Class c=s.getClass().getComponentType(); for (int i=0;i(); wadfiles = new ArrayList<>(); this.I = new DummySystem(); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + CloseAllHandles(); + })); } - //// FIELDS /** Location of each lump on disk. */ @@ -773,7 +776,7 @@ public T CacheLumpNum(int lump, int tag, Class what) { // In case of sequential reads of similar objects, use // CacheLumpNumIntoArray instead. thebuffer.rewind(); - lumpcache[lump] = (CacheableDoomObject) what.newInstance(); + lumpcache[lump] = (CacheableDoomObject) what.getDeclaredConstructor().newInstance(); lumpcache[lump].unpack(thebuffer); // Track it for freeing @@ -1152,7 +1155,7 @@ protected void InitLumpHash() { // in any chain, observing pwad ordering rules. killough for (int i = 0; i < numlumps; i++) { // hash function: - doomhash.put(lumpinfo[i].name.toUpperCase(), new Integer(i)); + doomhash.put(lumpinfo[i].name.toUpperCase(), Integer.valueOf(i)); } } @@ -1235,10 +1238,11 @@ public void CloseAllHandles(){ } - @Override - public void finalize(){ - CloseAllHandles(); - } + // TODO: finalize is deprecated - CloseAllHandles() call is moved to shutdown hook + //@Override + //public void finalize(){ + // CloseAllHandles(); + //} public static final int ns_global=0; public static final int ns_flats=1;