Skip to content

Commit

Permalink
Merge branch 'devel'
Browse files Browse the repository at this point in the history
  • Loading branch information
Argent77 committed Jan 23, 2021
2 parents 09a928c + a8d84af commit 5263258
Show file tree
Hide file tree
Showing 38 changed files with 1,132 additions and 759 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Java CI with Apache Ant

on:
push:
branches: [ devel, master ]
pull_request:
branches: [ devel, master ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Ant
run: ant -noinput -buildfile build.xml
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
NearInfinity.jar
jar/NearInfinity.jar
*.class
/bin
/build
/.settings
.vscode/launch.json
57 changes: 53 additions & 4 deletions src/org/infinity/NearInfinity.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
Expand Down Expand Up @@ -339,6 +342,21 @@ protected Void doInBackground() throws Exception
{
Profile.openGame(keyFile, BrowserMenuBar.getInstance().getBookmarkName(keyFile), forcedGame);

// making sure vital game resources are accessible
Path tlkFile = Profile.getProperty(Profile.Key.GET_GAME_DIALOG_FILE);
try {
checkFileAccess(tlkFile);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(NearInfinity.this,
String.format("Unable to open the game \"%s\".\n" +
"The file \"%s\" is locked by another process.",
Profile.getProperty(Profile.Key.GET_GAME_TITLE),
tlkFile.getFileName().toString()),
"Near Infinity Error", JOptionPane.ERROR_MESSAGE);
System.exit(10);
}

advanceProgress("Initializing GUI...");
BrowserMenuBar.getInstance().gameLoaded(Profile.Game.Unknown, null);
CreMapCache.reset();
Expand Down Expand Up @@ -727,11 +745,28 @@ public void openGame(Path keyFile)
blocker.setBlocked(true);
try {
Profile.Game oldGame = Profile.getGame();
String oldFile = Profile.getChitinKey().toString();
Path oldKeyFile = Profile.getChitinKey();
ChildFrame.closeWindows();
clearCache(false);
EffectFactory.init();
EffectFactory.reset();
Profile.openGame(keyFile, BrowserMenuBar.getInstance().getBookmarkName(keyFile));

// making sure vital game resources are accessible
Path tlkPath = Profile.getProperty(Profile.Key.GET_GAME_DIALOG_FILE);
try {
checkFileAccess(tlkPath);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(NearInfinity.this,
String.format("The file \"%s\" of the game \"%s\"\n" +
"is locked by another process. Reverting to the previous game.",
tlkPath.getFileName().toString(),
Profile.getProperty(Profile.Key.GET_GAME_TITLE)),
"Near Infinity Error", JOptionPane.ERROR_MESSAGE);
openGame(oldKeyFile);
return;
}

CreMapCache.reset();
removeViewable();
ResourceTreeModel treemodel = ResourceFactory.getResourceTreeModel();
Expand All @@ -741,7 +776,7 @@ public void openGame(Path keyFile)
Profile.getProperty(Profile.Key.GET_GAME_TITLE),
Profile.getGameRoot(), treemodel.size());
statusBar.setMessage(msg);
BrowserMenuBar.getInstance().gameLoaded(oldGame, oldFile);
BrowserMenuBar.getInstance().gameLoaded(oldGame, oldKeyFile.toString());
tree.setModel(treemodel);
containerpanel.removeAll();
containerpanel.revalidate();
Expand Down Expand Up @@ -793,11 +828,13 @@ public void refreshGame()
if (removeViewable()) {
ChildFrame.closeWindows();
ResourceTreeModel treemodel = ResourceFactory.getResourceTreeModel();
updateWindowTitle();
updateLauncher();
final String msg = String.format(STATUSBAR_TEXT_FMT,
Profile.getProperty(Profile.Key.GET_GAME_TITLE),
Profile.getGameRoot(), treemodel.size());
statusBar.setMessage(msg);
statusBar.invalidate();
BrowserMenuBar.getInstance().gameLoaded(null, null);
tree.setModel(treemodel);
containerpanel.removeAll();
Expand Down Expand Up @@ -978,7 +1015,7 @@ private static boolean reloadFactory(boolean refreshOnly)
clearCache(refreshOnly);
Path keyFile = refreshOnly ? Profile.getChitinKey() : findKeyfile();
if (keyFile != null) {
EffectFactory.init();
EffectFactory.reset();
retVal = Profile.openGame(keyFile, BrowserMenuBar.getInstance().getBookmarkName(keyFile));
if (retVal) {
CreMapCache.reset();
Expand Down Expand Up @@ -1182,6 +1219,18 @@ private boolean launchGameBinary(Path binPath)
return retVal;
}

/**
* Checks read access of the specified file.
* @param path The file path to check.
* @throws IOException if specified path could not be opened for reading.
*/
private void checkFileAccess(Path path) throws IOException
{
if (path != null) {
try (FileChannel ch = FileChannel.open(path, StandardOpenOption.READ)) { }
}
}

// -------------------------- INNER CLASSES --------------------------

private static final class ConsoleStream extends PrintStream
Expand Down
4 changes: 3 additions & 1 deletion src/org/infinity/gui/BrowserMenuBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@

public final class BrowserMenuBar extends JMenuBar implements KeyEventDispatcher
{
public static final String VERSION = "v2.1-20200901";
public static final String VERSION = "v2.1-20210123";
public static final LookAndFeelInfo DEFAULT_LOOKFEEL =
new LookAndFeelInfo("Metal", "javax.swing.plaf.metal.MetalLookAndFeel");

Expand Down Expand Up @@ -3312,12 +3312,14 @@ private void displayAbout()
// List of contributors (sorted alphabetically)
final String[] contributors = {
"Argent77",
"Bubb",
"devSin",
"Fredrik Lindgren (aka Wisp)",
"FredSRichardson",
"Mingun",
"Taimon",
"Valerio Bigiani (aka The Bigg)",
"winterheart",
};
// More contributors, in separate block
final String[] contributorsMisc = {
Expand Down
107 changes: 46 additions & 61 deletions src/org/infinity/gui/StructViewer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2019 Jon Olav Hauglid
// Copyright (C) 2001 - 2020 Jon Olav Hauglid
// See LICENSE.txt for license information

package org.infinity.gui;
Expand Down Expand Up @@ -83,7 +83,7 @@
import org.infinity.resource.AbstractStruct;
import org.infinity.resource.AddRemovable;
import org.infinity.resource.Closeable;
import org.infinity.resource.HasAddRemovable;
import org.infinity.resource.HasChildStructs;
import org.infinity.resource.HasViewerTabs;
import org.infinity.resource.Profile;
import org.infinity.resource.Resource;
Expand Down Expand Up @@ -178,7 +178,6 @@ public final class StructViewer extends JPanel implements ListSelectionListener,
private final StructTable table = new StructTable();
private final HashMap<Integer, StructEntry> entryMap = new HashMap<>();
private final HashMap<Viewable, ViewFrame> viewMap = new HashMap<>();
private AddRemovable emptyTypes[];
private JMenuItem miFindAttribute, miFindReferences, miFindStateReferences, miFindRefToItem;
private Editable editable;
private JTabbedPane tabbedPane;
Expand Down Expand Up @@ -355,26 +354,27 @@ else if (fieldColors.containsKey(field.getClass())) // consider only referenced
lowerpanel.addComponentListener(this);
cards.show(lowerpanel, CARD_EMPTY);

if (struct instanceof HasAddRemovable && !struct.getFields().isEmpty()) {
if (struct instanceof HasChildStructs && !struct.getFields().isEmpty()) {
try {
emptyTypes = ((HasAddRemovable)struct).getAddRemovables();
final AddRemovable[] prototypes = ((HasChildStructs)struct).getPrototypes();
if (prototypes.length > 0) {
final JMenuItem menuItems[] = new JMenuItem[prototypes.length];
for (int i = 0; i < prototypes.length; i++) {
final AddRemovable proto = prototypes[i];
final JMenuItem menu = new JMenuItem(proto.getName());
menu.putClientProperty("prototype", proto);
menuItems[i] = menu;
}
ButtonPopupMenu bpmAdd = (ButtonPopupMenu)buttonPanel.addControl(ButtonPanel.Control.ADD);
bpmAdd.setMenuItems(menuItems);
bpmAdd.addItemListener(this);
JButton bRemove = (JButton)buttonPanel.addControl(ButtonPanel.Control.REMOVE);
bRemove.setEnabled(false);
bRemove.addActionListener(this);
}
} catch (Exception e) {
e.printStackTrace();
}
if (emptyTypes == null)
emptyTypes = new AddRemovable[0];
JMenuItem menuItems[] = new JMenuItem[emptyTypes.length];
for (int i = 0; i < menuItems.length; i++) {
menuItems[i] = new JMenuItem(emptyTypes[i].getName());
}
if (emptyTypes.length > 0) {
ButtonPopupMenu bpmAdd = (ButtonPopupMenu)buttonPanel.addControl(ButtonPanel.Control.ADD);
bpmAdd.setMenuItems(menuItems);
bpmAdd.addItemListener(this);
JButton bRemove = (JButton)buttonPanel.addControl(ButtonPanel.Control.REMOVE);
bRemove.setEnabled(false);
bRemove.addActionListener(this);
}
}

ButtonPopupMenu bpmFind = (ButtonPopupMenu)buttonPanel.addControl(ButtonPanel.Control.FIND_MENU);
Expand Down Expand Up @@ -504,7 +504,7 @@ public void actionPerformed(ActionEvent event)
Viewable selected = (Viewable)table.getModel().getValueAt(min, 1);
createViewFrame(getTopLevelAncestor(), selected);
} else if (buttonPanel.getControlByType(ButtonPanel.Control.REMOVE) == event.getSource()) {
if (!(struct instanceof HasAddRemovable)) {
if (!(struct instanceof HasChildStructs)) {
return;
}
Window wnd = SwingUtilities.getWindowAncestor(this);
Expand All @@ -518,9 +518,7 @@ public void actionPerformed(ActionEvent event)
Object entry = table.getModel().getValueAt(rows[i], 1);
if (entry instanceof AddRemovable) {
try {
if (((HasAddRemovable)struct).confirmRemoveEntry((AddRemovable)entry)) {
struct.removeDatatype((AddRemovable)entry, true);
}
struct.removeDatatype((AddRemovable)entry, true);
} catch (Exception e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -651,48 +649,35 @@ public void stateChanged(ChangeEvent event)
@Override
public void itemStateChanged(ItemEvent event)
{
if (event.getSource() instanceof ButtonPopupMenu &&
buttonPanel.getControlPosition((JComponent)event.getSource()) >= 0) {
if (buttonPanel.getControlByType(ButtonPanel.Control.ADD) == event.getSource()) {
if (!(struct instanceof HasAddRemovable)) {
return;
}
ButtonPopupMenu bpmAdd = (ButtonPopupMenu)event.getSource();
JMenuItem item = bpmAdd.getSelectedItem();
AddRemovable toadd = null;
for (final AddRemovable emptyType : emptyTypes) {
if (emptyType != null && emptyType.getName().equals(item.getText())) {
toadd = emptyType;
break;
}
}
try {
toadd = ((HasAddRemovable)struct).confirmAddEntry(toadd);
if (toadd != null) {
toadd = (AddRemovable)toadd.clone();
}
} catch (Exception e) {
e.printStackTrace();
return;
final Object src = event.getSource();
if (src == buttonPanel.getControlByType(ButtonPanel.Control.ADD) && struct instanceof HasChildStructs) {
final JMenuItem item = ((ButtonPopupMenu)src).getSelectedItem();
AddRemovable toadd = (AddRemovable)item.getClientProperty("prototype");
try {
toadd = ((HasChildStructs)struct).confirmAddEntry(toadd);
if (toadd != null) {
toadd = (AddRemovable)toadd.clone();
}
int index = struct.addDatatype(toadd);
table.getSelectionModel().setSelectionInterval(index, index);
table.scrollRectToVisible(table.getCellRect(index, 1, true));
} else if (buttonPanel.getControlByType(ButtonPanel.Control.FIND_MENU) == event.getSource()) {
ButtonPopupMenu bpmFind = (ButtonPopupMenu)event.getSource();
JMenuItem item = bpmFind.getSelectedItem();
if (item == miFindAttribute) {
new AttributeSearcher(struct, (StructEntry)table.getValueAt(table.getSelectedRow(), 1),
getTopLevelAncestor());
} else if (item == miFindReferences) {
struct.searchReferences(getTopLevelAncestor());
} else if (item == miFindStateReferences) {
State state = (State)table.getValueAt(table.getSelectedRow(), 1);
new DialogStateReferenceSearcher(struct.getResourceEntry(), state, getTopLevelAncestor());
} else if (item == miFindRefToItem) {
new DialogItemRefSearcher((DlgResource) struct, table.getValueAt(table.getSelectedRow(), 1),
getTopLevelAncestor());
}
} catch (Exception e) {
e.printStackTrace();
}
} else
if (src == buttonPanel.getControlByType(ButtonPanel.Control.FIND_MENU)) {
final JMenuItem item = ((ButtonPopupMenu)src).getSelectedItem();
if (item == miFindAttribute) {
new AttributeSearcher(struct, (StructEntry)table.getValueAt(table.getSelectedRow(), 1),
getTopLevelAncestor());
} else if (item == miFindReferences) {
struct.searchReferences(getTopLevelAncestor());
} else if (item == miFindStateReferences) {
State state = (State)table.getValueAt(table.getSelectedRow(), 1);
new DialogStateReferenceSearcher(struct.getResourceEntry(), state, getTopLevelAncestor());
} else if (item == miFindRefToItem) {
new DialogItemRefSearcher((DlgResource) struct, table.getValueAt(table.getSelectedRow(), 1),
getTopLevelAncestor());
}
}
}
Expand Down
24 changes: 14 additions & 10 deletions src/org/infinity/resource/AbstractStruct.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,24 @@ private static void adjustEntryOffsets(AbstractStruct superStruct, AbstractStruc

private static void adjustSectionOffsets(AbstractStruct superStruct, AddRemovable datatype, int amount)
{
boolean sectionMatch = false;
for (final StructEntry e : superStruct.fields) {
if (e instanceof SectionOffset) {
final SectionOffset so = (SectionOffset)e;
if (so.getValue() + superStruct.getExtraOffset() > datatype.getOffset()) {
so.incValue(amount);
}
else if (so.getValue() + superStruct.getExtraOffset() == datatype.getOffset()) {
sectionMatch |= so.getSection().equals(datatype.getClass());
if (amount > 0 &&
!(so.getSection().equals(datatype.getClass()) ||
(Profile.getEngine() == Profile.Engine.IWD2 && superStruct instanceof CreResource) ||
((superStruct instanceof ItmResource || superStruct instanceof SplResource) && !sectionMatch))) {
so.incValue(amount);
if (amount > 0) {
if (superStruct instanceof ItmResource || superStruct instanceof SplResource) {
// ensure that effect structures are added after ability structures
if (datatype instanceof AbstractAbility && so.getSection().equals(Effect.class)) {
so.incValue(amount);
}
}
else if (!(so.getSection().equals(datatype.getClass()) ||
(Profile.getEngine() == Profile.Engine.IWD2 && superStruct instanceof CreResource))) {
so.incValue(amount);
}
}
}
}
Expand All @@ -155,7 +159,7 @@ protected AbstractStruct(ResourceEntry entry) throws Exception
name = entry.getResourceName();
ByteBuffer bb = entry.getResourceBuffer();
endoffset = read(bb, 0);
if (this instanceof HasAddRemovable && !fields.isEmpty()) {// Is this enough?
if (this instanceof HasChildStructs && !fields.isEmpty()) {// Is this enough?
Collections.sort(fields); // This way we can writeField out in the order in list - sorted by offset
fixHoles((ByteBuffer)bb.position(0));
initAddStructMaps();
Expand All @@ -182,7 +186,7 @@ protected AbstractStruct(AbstractStruct superStruct, String name, ByteBuffer buf
{
this(superStruct, name, startoffset, listSize);
endoffset = read(buffer, startoffset);
if (this instanceof HasAddRemovable) {
if (this instanceof HasChildStructs) {
if (!(this instanceof Actor)) { // Is this enough?
Collections.sort(fields); // This way we can writeField out in the order in list - sorted by offset
}
Expand Down Expand Up @@ -912,7 +916,7 @@ public List<AddRemovable> removeAllRemoveables()

public void removeDatatype(AddRemovable removedEntry, boolean removeRecurse)
{
if (removeRecurse && removedEntry instanceof HasAddRemovable) { // Recusivly removeTableLine substructures first
if (removeRecurse && removedEntry instanceof HasChildStructs) { // Recusivly removeTableLine substructures first
AbstractStruct removedStruct = (AbstractStruct)removedEntry;
for (int i = 0; i < removedStruct.fields.size(); i++) {
final StructEntry o = removedStruct.fields.get(i);
Expand Down
Loading

0 comments on commit 5263258

Please sign in to comment.