[Save Manager] FTL Homeworld AE -v3.1

Distribute and discuss mods that are functional. Moderator - Grognak
User avatar
kartoFlane
Posts: 1488
Joined: Mon Jan 14, 2013 10:20 pm

Re: [Program] FTL SpaceDock

Postby kartoFlane » Wed Jul 24, 2013 11:25 pm

Well, I'm hardly a pro (Vhati's or shark's input would've been far more valuable), but I'm happy I was able to help :)

Regarding the launching issue; I've encountered that a month or two ago. It was a really tricky one.
The problem is: when you launch a new process, it is executed in the same working directory as the parent application that created the process.
So, when you execute FTLGame.exe that way, it executes the correct exe in FTL's installation, but it's working directory is set to Spacedock's directory -- so if the child process uses relative paths anywhere, they'll all resolve to [Spacedock path]/[relative path], and not [FTL installation path]/[relative path].

This causes FTL to spill its guts, since it can't find the .dat archives, and thus causes it to quit.

Also, I'd recommend against using waitFor() in this case -- it causes your application to stop working, only resuming once the child process has quit.

Another thing, though I'm not sure if I recall it correctly, is that processes created using exec() are child processes of the parent application, so if the parent quits, all children also quit. Don't trust me on that one, though.

Either way, here's a snippet of my code from my earlier project that executes FTL correctly:

Code: Select all

File ftl = new File(Main.ftlIntallPath.getAbsolutePath() + "/FTLGame.exe");
Main.logger.info(String.format("Running FTL... [%s]", ftl.getAbsolutePath()));
if (ftl.exists())
   try {
      ProcessBuilder builder = new ProcessBuilder(ftl.getAbsolutePath());
      builder.directory(ftl.getParentFile()); // this call corrects the working directory for the exe
      builder.start();
   } catch (IOException ex) {
      Main.logger.error("An exception occured while executing FTL.");
      ex.printStackTrace();
   }
else
   Main.logger.error("Could not find FTL executable.");


However, for the future I'd recommend making an extensive use of Google and Stack Overflow -- it is often said that roughly half of programming is googling for a solution, the other half is problem solving and actual coding... And coding accounts for the smaller part of that half :)
Superluminal2 - a ship editor for FTL
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm

Re: [Program] FTL SpaceDock

Postby iceburg333 » Thu Jul 25, 2013 1:40 am

kartoFlane wrote:Well, I'm hardly a pro (Vhati's or shark's input would've been far more valuable), but I'm happy I was able to help :)

Regarding the launching issue; I've encountered that a month or two ago. It was a really tricky one.
The problem is: when you launch a new process, it is executed in the same working directory as the parent application that created the process.
So, when you execute FTLGame.exe that way, it executes the correct exe in FTL's installation, but it's working directory is set to Spacedock's directory -- so if the child process uses relative paths anywhere, they'll all resolve to [Spacedock path]/[relative path], and not [FTL installation path]/[relative path].

This causes FTL to spill its guts, since it can't find the .dat archives, and thus causes it to quit.

Ah, that makes sense. Something was definitely going wrong.

kartoFlane wrote:Also, I'd recommend against using waitFor() in this case -- it causes your application to stop working, only resuming once the child process has quit.

Another thing, though I'm not sure if I recall it correctly, is that processes created using exec() are child processes of the parent application, so if the parent quits, all children also quit. Don't trust me on that one, though.

That makes sense too. I was trying the waitfor in case my program was terminating the exe in order to move forward, it was sort of a desperation attempt. And I'm okay with it terminating when FTL does, as this was just supposed to act as a mini-launcher or sorts. So you can pick your ship, press the game to play, and then afterwords hit refresh and then dock your ship and pick another. :)

kartoFlane wrote:Either way, here's a snippet of my code from my earlier project that executes FTL correctly:

Code: Select all

File ftl = new File(Main.ftlIntallPath.getAbsolutePath() + "/FTLGame.exe");
Main.logger.info(String.format("Running FTL... [%s]", ftl.getAbsolutePath()));
if (ftl.exists())
   try {
      ProcessBuilder builder = new ProcessBuilder(ftl.getAbsolutePath());
      builder.directory(ftl.getParentFile()); // this call corrects the working directory for the exe
      builder.start();
   } catch (IOException ex) {
      Main.logger.error("An exception occured while executing FTL.");
      ex.printStackTrace();
   }
else
   Main.logger.error("Could not find FTL executable.");


That code worked perfectly! Thank you so much for taking the time to post that. Man, so far working with FTL has been so refreshing. I'm used to banging my head against code for days when coding for Skyrim (it's debugger is entirely lacking/missing, it's very hard to find the root of your problems) and then to have people like you, Vhati, and Lologarithm help out so kindly like this, it's AWESOME. You say you're no pro, but you certainly have helped me a ton! =D

kartoFlane wrote:However, for the future I'd recommend making an extensive use of Google and Stack Overflow -- it is often said that roughly half of programming is googling for a solution, the other half is problem solving and actual coding... And coding accounts for the smaller part of that half :)

I have been! I think that probably 60-70% of my time at least is on google and stack flow. Every couple hours I just close google chrome all-together to clear out all of the tabs I have. I'm such a newb that I have few other options, but every now and again I come up with issues that I can't seem to find answers for (I looked at like 10+ stack overflow questions on getting an exe to run, but none touched on changing the directory of the builder.) But I definitely don't want to wear you guys out, so I'll try not to get greedy and bug you!!

Now that everything is working stupendously, I'll make sure to organize it better and remove dependancy, then release an update for spacedock, then keep working on the cargo bay version, and I'll try to keep github up to date.
Thanks again! =D
Ice

Ps. I didn't really think about your program's name until the other day while reading an article on IRL FTL drives, and then it hit me: "super" meaning higher/beyond and "luminal" meaning light. That's a sick name! =D
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm

Re: [Program] FTL SpaceDock

Postby iceburg333 » Thu Jul 25, 2013 4:34 pm

kartoFlane wrote:Also, as I was told by shark when I started, it might be a good idea to organize the code into relevant packages:

Code: Select all

org.iceburg.ftl.homeworld.core
   - FTLHomeworld
   - SaveGameParser
org.iceburg.ftl.homeworld.elements
   - Savegame
org.iceburg.ftl.homeworld.ui
   - SpaceDockUI
   - CargoBayUI


Will do. I did it and will upload to github after I post this.

kartoFlane wrote:It might also be a good idea to include relevant pieces of code from the Savegame Editor in your own project, to eliminate the confusing dependency. The code is open-source, so it's not a crime if you copy it.

I started to do this, but I think my code relies too heavily on the Editor. I'd have to copy 60% of their code over (their whole xml package, much of their data manager package, and their whole models package). Would you still recommend that? I'll write up some code to browse for the FTL Editor in the meantime, so at least it doesn't need to be in the same folder.

kartoFlane wrote:Also, since the savegame location cannot be changed AFAIK, you can just hardcode it into your program, so that the Spacedock doesn't have to be placed inside FTL's savegame directory. And even if the savegame location can be changed, you can prompt the user to point the program to it.

Well, that's about it - there are some other things I wanted to suggest, but figured I'd leave them to you to learn :)

Good idea. Lologarithm did much of this for me, but I updated it a bit so that you can now browse in game to a different save folder (in case you have multiple folders like me- a test folder and actual game folder).

kartoFlane wrote:I'd recommend making the ShipSave class into its own file, to make use of the object-oriented nature of Java.


I've moved ShipSave to it's own class in the ftl.homeworld.model package, and after a bit of fiddling (had to set them to static), I was able to get boardship and dockship into the ShipSave class. That makes sense to me, as we're just keeping our objects organized. :)

kartoFlane wrote:It looks like right now it only holds a reference to the savegame file itself - it's kind of a waste (you could use an ArrayList<File> for that), especially since you could have it contain the ship's image, button reference, data from within the save file (so you don't have to read it anew each time you need the info), as well as making it host the dockShip and boardShip functions (and all the other relevant methods I haven't spotted)


Alright, I'm struggling with this part. ShipSave extends SavedGameState, and so stores 7 bits of info (like beacons explored and name) as well as the file path of the actual save file. Are you saying that that's a waste and I should just store all of that info in an array? Also, things like the ship's image, button reference, etc, you're saying that it'd be better to move that within the save file, but I think that the only time it's read is when we're refreshing the panel (and we want stuff to be re-read to make sure we're accurate). Am I making sense/ missing something?
Thanks!
Ice
ps. I'll upload to github and then work on making the FTL Editor dependency more robust/not need the same folder location. :)
EDIT: Or maybe not, lol. I guess it's not a big deal to have FTL Homeworld in the same folder as FTL Editor, and that seems like the best option for now, as editing the manifest on the fly sounds like that would be too complicated. I'll keep googling it though.
User avatar
kartoFlane
Posts: 1488
Joined: Mon Jan 14, 2013 10:20 pm

Re: [Program] FTL SpaceDock

Postby kartoFlane » Thu Jul 25, 2013 6:32 pm

iceburg333 wrote:ShipSave extends SavedGameState

Oh, I've missed that bit. It's totally fine then.

iceburg333 wrote:Also, things like the ship's image, button reference, etc, you're saying that it'd be better to move that within the save file, but I think that the only time it's read is when we're refreshing the panel (and we want stuff to be re-read to make sure we're accurate). Am I making sense/ missing something?

Thing is, once you read the information, you have to store the data somewhere. What better place to do this than a class to which this data is directly related to?
I perused the code; the imageCache is good as it is, but the JButton[] could be changed to be a field of the ShipSave class:

Code: Select all

public class ShipSave extends SavedGameState {
   public File shipFilePath;
   public JButton boardButton;
   public String imageInnerPath; // to retrieve the image from imageCache
   ...

And this entire loop in SpaceDockUI.init():

Code: Select all

for (int i = 0; i < myShips.length; i++) {
   ...

Could instead be converted into ShipSave's constructor, so that each time you create a new instance of ShipSave, the button, label, and other related UI elements are also created.
It is nitpicky, because the code will work either way; however, thinking of code in an object-oriented way makes it much easier to organise, scale, work with and be understood by others.

Not sure if you've stumbled upon any OOP related resources or articles, but a good mental exercise is to break down a car into components:
On the highest level of abstraction, you have the Car class - what can you tell about a car when you first look at it? Color, brand, model, its plate number... But you can't really tell much about its other components without having a closer look. So, you come closer and examine the Engine - and take note of its own, specific properties (its own brand, model, type, efficiency, number of cylinders...), you look at the Tire(s) (brand, rubber, adhesion)...
Then you back away again, look at the car and remember that all those components are just parts that the Car references and makes use of.

Of course, you could store all of this information (or parts of it, depending on what you need for the project) in the Car class, but you'd end up with a lot of variables, arrays, maps, methods, and it'd all be a big mess to work with and keep track of. And then say you want to describe a three-wheeled car...

It's just a change in the mindset, but once you "get it", the code starts to organise itself in an eerily intuitive way, without you ever paying attention to it.

Also:

Code: Select all

public ShipSave[] myShips;

Arrays are good for some super-simple, one-time local stuff, or array-specific stuff, but they are clumsy to use. For storing references to objects that are used across the entire application, an ArrayList<ShipSave> would be much easier to use. It'd also allow you to get rid of the 50 saves limit, since ArrayList expands automatically as you add more entries to it.

Then, in conjunction with OO approach I talked about earlier you could get rid of the BoardListener and implement the button-press functionality in a neat way ("there must be a better way to do this!"):

Code: Select all

public class ShipSave extends SavedGameState {
   ...
   // constructor
   public ShipSave() {
      ...
      button = new JButton(...);
      // add it to the loopPanel, which now would have to be a public field in SpaceDockUI
      button.addListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (SpaceDockUI.currentShip != this) {
               SpaceDockUI.currentShip.dock();
               board(); // changes currentShip = this and button text to "Dock", etc...
            } else {
               dock(); // changes button text to "Board", etc...
            }
         }
      });
      ...
   }
   ...


iceburg333 wrote:I started to do this, but I think my code relies too heavily on the Editor. I'd have to copy 60% of their code over

Huh, that's a bit of a dependency indeed. I don't know, personally I'd probably copy it over anyway, simply treating it as a library the program uses (I used this approach with Superluminal, copying the entire datLib class from KuroSaru's DatManager). I'm not sure if it's a good practice, however. *shrug*

iceburg333 wrote:Ps. I didn't really think about your program's name until the other day while reading an article on IRL FTL drives, and then it hit me: "super" meaning higher/beyond and "luminal" meaning light. That's a sick name! =D

I still think it's cheesy as hell :P it was the working name I had for it, hoping I'd eventually come up with something better. Fast forward to the "release day", I went "fuck it, that's what it's going to be called", and just rolled with it.
Superluminal2 - a ship editor for FTL
ftlnvm
Posts: 1
Joined: Fri Jul 26, 2013 5:13 am

Re: [Program] FTL Homeworld

Postby ftlnvm » Fri Jul 26, 2013 5:24 am

Hi , i have two questions:

i have exactly followed your instructions of instalation (to not make mistakes), but i cant seem to make it work .

I downloaded the zip (in my regular download folder since there is no specific folder mentionned) then unpacked it (i only have winrar but it worked) then i added FTLProfile Editor.jar in the same folder (still my download folder). since i couldnt find any exe or anything in your unpacked mod, i launched profile editor, but i couldnt have the same window as in your screenshot. I also tried to launch directly the "notunpacked" jar and it stoped working (windows message)
What did i do wrong? i dont think i deviated from your instructions an inch .

Also, what am i suposed to do with stardock.jar?
UltraMantis
Posts: 2141
Joined: Thu Sep 20, 2012 3:17 pm

Re: [Program] FTL Homeworld

Postby UltraMantis » Fri Jul 26, 2013 9:53 am

You launch the .jar file. It's the Java equivalent of an .exe file. If you installed correctly which you probably did, and have Java installed the program will start. You may get asked wheter to trust the application or not as a security measure.
Report spam using the handy Report Button Mod.
Dimitriye98
Posts: 1
Joined: Sat Jul 27, 2013 10:01 am

Re: [Program] FTL Homeworld

Postby Dimitriye98 » Sat Jul 27, 2013 10:08 am

Ok, so I tried running this, and the jar failed to start. After running it from the command line I got the following error:

Code: Select all

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager
   at org.iceburg.ftl.homeworld.core.FTLHomeworld.<clinit>(FTLHomeworld.java:51)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.LogManager
   at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
   ... 1 more

Any idea what's wrong?
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm

Re: [Program] FTL Homeworld

Postby iceburg333 » Sat Jul 27, 2013 4:48 pm

Dimitriye98 wrote:Ok, so I tried running this, and the jar failed to start. After running it from the command line I got the following error:

Code: Select all

Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.LogManager

Any idea what's wrong?

Hey Dimitriye! I'm in the process of removing the FTL Editor dependency, and I'm having the same sort of troubles. First, try running the FTL Homeworld from the same folder location as the FTL Editor jar, if that doesn't work, then run the old Spacedock jar (download in the first post). If you have to run the old jar, then you need to run it from the save's profile. Sorry about that!

UltraMantis: Thanks once again for beating me to answering the question! You rock! :D
-------------------------------
KartoFlane:
Hey, I really appreciated your last message! I had to take my mother to the hospital yesterday, she broke her ankle, so I wasn't able to do much, but I'm working through your message today. I'll quote you/respond as I work through.

KartoFlane wrote:Huh, that's a bit of a dependency indeed. I don't know, personally I'd probably copy it over anyway, simply treating it as a library the program uses (I used this approach with Superluminal, copying the entire datLib class from KuroSaru's DatManager). I'm not sure if it's a good practice, however. *shrug*

Okay, I'm committed to this now. I've moved all of the packages over, but when I remove my project's dependence on FTL Editor.jar, I lose the dependencies that it depended on, mainly:

Code: Select all

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

I'm working on getting that dependency back, but it's frustrating. I'm not installing it correctly. >:0
I need to better understand maven, and I've asked Vhati about it on his thread. Until then I'll work on the OO approach and

Code: Select all

public class ShipSave extends SavedGameState {
   public File shipFilePath;
   public JButton boardButton;
   public String imageInnerPath; // to retrieve the image from imageCache

Once I've got more work done on it, I'll report back in. :D

EDIT:
-----------------------------
Man, what a frustrating day, lol.
So, I've commented out all of the log stuff, so that isn't giving me trouble now. Bad way to solve the problem, but at least I can keep going.
The car analogy was good/ makes sense/ helps me wrap my brain around this stuff. Thanks. :)

I love the idea of storing the button's in the current ship and not needing to use the button list. I've added the boardbtn to the ShipSave, but I'm not getting the results i'd like.

Code: Select all

public class ShipSave extends SavedGameState {
   ...
   // constructor
   public ShipSave() {
      ...
      button = new JButton(...);
      // add it to the loopPanel, which now would have to be a public field in SpaceDockUI
      button.addListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            if (SpaceDockUI.currentShip != this) {
               SpaceDockUI.currentShip.dock();
               board(); // changes currentShip = this and button text to "Dock", etc...
            } else {
               dock(); // changes button text to "Board", etc...
            }
         }
      });
      ...
   }
   ...

The problem is, in "if (SpaceDockUI.currentShip != this", this is an ActionListener and SpaceDockUI.getCurrentShip() doesn't work because of static reference: I need to access the current ship of a Specific SpaceDockUI...
If you can tell me how to get the ship from its child ActionListener, then I think I can figure out how to access the Specific SpaceDockUI that I need...

KartoFlane wrote:Also:

Code: Select all

public ShipSave[] myShips;


Arrays are good for some super-simple, one-time local stuff, or array-specific stuff, but they are clumsy to use. For storing references to objects that are used across the entire application, an ArrayList<ShipSave> would be much easier to use. It'd also allow you to get rid of the 50 saves limit, since ArrayList expands automatically as you add more entries to it.

I put the 50 save limit in only so that the dockship function didn't keep looking for a higher int to append to "Continue_" forever if something went wrong. It was more a safety feature than anything else. Should I remove it? What would be the advantage (for me) of making the Array into an Arraylist? The Array expands as is because on creation it sets itself to the number of save files, and I'm not creating any new ships right now (though maybe I'll have to change it later when you can build new ships).

(Github updated)
Image
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm

Re: [Program] FTL Homeworld

Postby iceburg333 » Sat Jul 27, 2013 7:40 pm

Dimitriye98 wrote:Ok, so I tried running this, and the jar failed to start. Any idea what's wrong?

Hey, I wanted to post to let you know I've updated the main thread. 1.2 Should be totally seperate from FTL Profile Editor. You *Should* be able to run FTL Homeworld from any directory without needing any other files. :D
User avatar
kartoFlane
Posts: 1488
Joined: Mon Jan 14, 2013 10:20 pm

Re: [Program] FTL Homeworld

Postby kartoFlane » Sat Jul 27, 2013 8:17 pm

iceburg333 wrote:The problem is, in "if (SpaceDockUI.currentShip != this"), this is an ActionListener

Well, there's a very simple way to work around that. And it only requires a single private variable, set to a certain object...
In case you couldn't figure it out, check this.

iceburg333 wrote:The Array expands as is because on creation it sets itself to the number of save files, and I'm not creating any new ships right now

Huh. True. Though I still think it's worth using an ArrayList instead, simply due to the ease of use.

iceburg333 wrote:I put the 50 save limit in only so that the dockship function didn't keep looking for a higher int to append to "Continue_" forever if something went wrong.

I see. To get around that and allow the program to parse all savegames, you could use File.listFiles() to get an array of all files in the directory. Then check if they contain "continue", and end with ".sav". Or just check for ".sav" extension, to get custom-named savegames too:

Code: Select all

File directory = (get the directory containing savegames)
for (File save : directory.listFiles()) {
   String name = save.getName();
   if (name.contains("continue") && name.endsWith(".sav")) {
      // do savegame-related stuff
   }
}
Superluminal2 - a ship editor for FTL