[Spoiler] FTL Profile/SavedGame Editor v27 (2018-01-12)

All your guides, strategy discussions, request for help on how to play go here. Please use [SPOILER] if relevant.
therunawaybros615
Posts: 51
Joined: Fri Oct 05, 2012 8:57 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby therunawaybros615 » Sat Jul 06, 2013 8:45 pm

Hello, everyone! Hey Vhati, remember the problems I had starting the editor? I fixed it, and if anyone else has any problems, go to this website. Jarfix fixes the .jar association on your PC.



Vhati, would you kindly list this website on your main post? http://johann.loefflmann.net/en/software/jarfix/

(If you get the reference, you get a cookie. :P)
Last edited by therunawaybros615 on Sat Jul 06, 2013 9:42 pm, edited 1 time in total.
I will bring PEACE! FREEDOM! JUSTICE! And SECURITY to my new empire! ~Anakin Skywalker
Steam Profile
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm
Contact:

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby iceburg333 » Sat Jul 06, 2013 9:40 pm

Hi runawaybros!
I had another question for Vhati, concerning:

Code: Select all

int headerAlpha = readInt(in)


From what I can tell, in is incremented as each stat/variable is read in SavedGameParser. So that means that the variables must be read in order and cannot be skipped. Is that correct? If so, and if I only want to read 2 variables from the file (ship blueprint and ship name), is it possible for me to skip further into the stream without reading the whole file?
Thanks again Vhati!
Vhati
Posts: 792
Joined: Thu Oct 25, 2012 12:01 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby Vhati » Sun Jul 07, 2013 1:37 am

therunawaybros615 wrote:Hello, everyone! Hey Vhati, remember the problems I had starting the editor? I fixed it
Glad to hear it. :)
I only stumbled across JarFix a couple pages ago. Linking it in the OP is a good idea.

As a matter of fact, I was also revising the launcher generator I wrote for you.
There was a place it overlooked when searching for Java on 64bit machines.

I'll PM you when that's ready, if you don't mind testing it out.
Last edited by Vhati on Sun Jul 07, 2013 4:05 am, edited 1 time in total.
Vhati
Posts: 792
Joined: Thu Oct 25, 2012 12:01 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby Vhati » Sun Jul 07, 2013 3:13 am

iceburg333 wrote:In my test class I have the code written:

Code: Select all

ShipSave ss2 = ShipSaveParser.readShipSavetest();

It's telling me that I "Cannot make a static reference to the non-static method readShipSavetest() from the type
ShipSaveParser". But why is ss2 static? Nothing in my test method is defined as static.
Since Java is primarily an object-oriented language, unless a method is explicitly "public static void foo() {...}", that method only exists as part of instantiated objects of the relevant class. In other words you either have to do the following...
iceburg333 wrote:

Code: Select all

ShipSaveParser parser = new ShipSaveParser();
ShipSaveParser.ShipSave ss2 = parser.readShipSave(testFile);;
Or declare the method "static" so that it becomes part of the class itself, rather than of objects.

You've got an extra semicolon up there, btw.

...

iceburg333 wrote:

Code: Select all

int headerAlpha = readInt(in)

From what I can tell, in is incremented as each stat/variable is read in SavedGameParser. So that means that the variables must be read in order and cannot be skipped. Is that correct?
Correct. InputStreams let you consume bytes from a source in the order they appear (some will allow limited buffering to repeat bytes that just passed to mimic backtracking). Streams will let you skip forward (read and ignore bytes) but...

iceburg333 wrote:if I only want to read 2 variables from the file (ship blueprint and ship name), is it possible for me to skip further into the stream without reading the whole file?
The continue.sav file format doesn't store data at absolute offsets.
Values take up varying amounts of bytes (for example, lists of more/fewer crew names, even the name strings have different lengths), and the next value just appears wherever the previous one ended, not at the Nth byte from the beginning.

So you have to read the whole file to know where anything is.
Just read the entire game state, then pick out what you're interested in...

Code: Select all

DataManager.init(new File("path/to/FTL/resources/"));

SavedGameParser parser = new SavedGameParser();
SavedGameState gameState = readSavedGame(new File("continue.sav"));
ShipState shipState = gameState.getPlayerShipState();
String shipName = shipState.getShipName();
String shipBlueprintID = shipState.getShipBlueprintId();
The DataManager's necessary because the only way to know how many doors to expect in the saved game (how many bytes to read before the next thing), is to have read the ship layout txt beforehand. And the only way to know the layout for a ship's blueprintId, is to have read the <shipBlueprint> xml for that blueprintId.

If you ever want to make your own custom DataManager (to add methods or something) you'd have to copy SavedGameParser.java and change "import net.blerf.ftl.parser.DataManager;" to your own class.
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm
Contact:

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby iceburg333 » Sun Jul 07, 2013 8:47 pm

Vhati wrote:Since Java is primarily an object-oriented language, unless a method is explicitly "public static void foo() {...}", that method only exists as part of instantiated objects of the relevant class. In other words you either have to do the following...

Code: Select all

ShipSaveParser parser = new ShipSaveParser();
ShipSaveParser.ShipSave ss2 = parser.readShipSave(testFile);;
Or declare the method "static" so that it becomes part of the class itself, rather than of objects.

You've got an extra semicolon up there, btw.

Thank you! It makes more sense now, static vs object.... I think I'm just now coming to grips with the theory behind it, though the idea of a 'new parser' still hurts my brain. :D
lol. Silly semicolons. Thanks. :)
...

Vhati wrote:Correct. InputStreams let you consume bytes from a source in the order they appear (some will allow limited buffering to repeat bytes that just passed to mimic backtracking). Streams will let you skip forward (read and ignore bytes) but...

The continue.sav file format doesn't store data at absolute offsets.
Values take up varying amounts of bytes (for example, lists of more/fewer crew names, even the name strings have different lengths), and the next value just appears wherever the previous one ended, not at the Nth byte from the beginning.

So you have to read the whole file to know where anything is.
Just read the entire game state, then pick out what you're interested in...

Thanks, that's what I was figuring, but I appreciate you getting back to me before I wracked my brain try to figure out if that was really the case. I'm getting better at combing through the code/looking at java source, but you still saved me at least an hour of pulling my hair out, if not three. :D
I only hesitated to read the whole file because I want to load multiple files (a save game selector, if you will) and I didn't want it to take a long time. Happily, all of the data I need is in that first section, so I shouldn't have to read too much code! :D

Vhati wrote:The DataManager's necessary because the only way to know how many doors to expect in the saved game (how many bytes to read before the next thing), is to have read the ship layout txt beforehand. And the only way to know the layout for a ship's blueprintId, is to have read the <shipBlueprint> xml for that blueprintId.


Wow, the more I look at this code, the more I think you and ComaToes did some beast work. Again, thank you for making it open source!
I'm certain that my program will require FTL Editor, so my ShipSaveParser class is modled after your SavedGameParser and calls classes from/extends your parser and datamanager, so I should be good just calling those functions. (and that bit is working, it's just pulling the wrong bytes since I cherry picked what data I wanted).

I'm going to start adapting my Parser to handle the input/output stream and test it, and I also spent a couple hours yesterday working to get github working, I'm going to keep doing that so I can share more code. However, in the meantime would you be willing to answer another question? (If I'm wearing you out, please let me know, it's just so nice to have a pro to answer questions.) :D

I'm working on making a savegame manager (calling it a space dock) where you see all of your ships (save files) and choose one to play with (board) while all the others are 'docked'. Your current ship is "continue.sav" while your others are named iteratively "continue_1.sav" etc. Everything is setting up nicely (I figured out a while loop to give the right name to docked ships), but I can't get a rename function to work! My code is this:

Code: Select all

public boolean boardShip(ShipSave ss1) {
      boolean success = false;
      File oldFile = ss1.getshipFilePath();
      File newFile = new File("continue.sav");
      if (!newFile.exists()) {
         //success = oldFile.renameTo(newFile);
         
         Path source = oldFile.toPath();
                try {
               Files.move(source, newFile.toPath());
            } catch (IOException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
            }
         }
         
      ss1.setshipFilePath(newFile);
      return success;
   }

When I run it I get an IO error like this:

Code: Select all

"java.nio.file.FileSystemException: continue_3.sav -> continue.sav: The process cannot access the file because it is being used by another process."

The commented out renameTo method also fails. My google searches tell me that my file is locked by my program and that I may need to lock the directory, but that doesn't make any sense. Would you be able to point me in the right direction?
Thanks again Vhati!
Ice
Targetstar
Posts: 37
Joined: Sun Sep 16, 2012 3:53 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby Targetstar » Sun Jul 07, 2013 11:09 pm

Dose this mod let you change the name of your crew during the game?
Vhati
Posts: 792
Joined: Thu Oct 25, 2012 12:01 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby Vhati » Mon Jul 08, 2013 2:21 am

iceburg333 wrote:I can't get a [savedgame file] rename function to work!

When I run it I get an IO error like this:

Code: Select all

"java.nio.file.FileSystemException: continue_3.sav -> continue.sav: The process cannot access the file because it is being used by another process."
A) Before moving, check that the destination isn't the same as the source.
B) You can't rename/delete the file if it's still got an open stream on it.

Usually any time you have a try/catch reading a stream, include a finally block that makes sure the stream gets closed. There are plenty of examples of that in the editor's source.
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm
Contact:

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby iceburg333 » Mon Jul 08, 2013 3:03 pm

Thanks for getting back so quickly!
Vhati wrote:A) Before moving, check that the destination isn't the same as the source.

It can't be that because I only try to save it

Code: Select all

if (!newFile.exists())
=/

Vhati wrote:B) You can't rename/delete the file if it's still got an open stream on it.

Usually any time you have a try/catch reading a stream, include a finally block that makes sure the stream gets closed. There are plenty of examples of that in the editor's source.


That's^ it! You were on the money! I had copied the finally close block for reading the files, but not for writing them, so when I created a new file to test on, I was keeping it write protected. I never would have thought of that! All of my tests are working now! Thank you!
Alright, I've got to make sure I'm properly incrementing the in/out streams and then I'm ready to work on my gui/main. I'll keep working on figuring out github too. =D

Targetstar wrote:Dose this mod let you change the name of your crew during the game?

Hey Targetstar, I saw your post while replying to Vhati. This isn't a mod so much as a standalone program, and I just opened it and was able to change the name, race, and a bunch of other stuff for my crew. Vhati and ComaToes have done a really good job with it, I recommend you download it and check it out. :)
Image
iceburg333
Posts: 67
Joined: Tue Jun 25, 2013 8:52 pm
Contact:

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby iceburg333 » Thu Jul 11, 2013 2:43 am

Hey Vhati!
I've got a working program and it's completely functional, I'm just trying to clean up / make the UI better. I have the UI show you each of your saves by showing you their name and beacons jumped to, as well as a button to board or dock that ship, and it works on saves. I've also added my code to github! I'd like to add a picture of the ship to the description, but I'm having trouble with the data manager. I get no compile errors, but on run time a null pointer exception is thrown.

Code: Select all

//      ShipBlueprint ship = DataManager.get().getShips()
//            .get(myShips[i].getPlayerShipBlueprintId());
//      ImageIcon shipPic = new ImageIcon("img/ship/" + ship.getGraphicsBaseName() + "_base.png");
//      JLabel lblShipID = new JLabel("", shipPic, JLabel.CENTER);
//      frmSpaceDock.getContentPane().add(lblShipID);
      
      for ( ShipBlueprint ship : DataManager.get().getPlayerShips() ) {
         ImageIcon shipPic = new ImageIcon("img/ship/" + ship.getGraphicsBaseName() + "_base.png");
         JLabel lblShipID = new JLabel("", shipPic, JLabel.CENTER);
         frmSpaceDock.getContentPane().add(lblShipID);
      }

Whether I comment the first or second block of code, both throw the null point exception. This is a generalized question and I realize my problem could be elsewhere in the code. It's all there on github, but I realize asking you to look through it would be asking you to do my job/possibly send you on a wild goose chase. I'm going to keep working on it, but thought I'd post just as an update / in case you might be able to point me in the right direction.
I copied a lot of the initialization code, so I have the user select the data.dat, but now that I think about it, it's not generating a config file. I'll look into that. :)

EDIT: I think I just got it to work, I wasn't writing a config file, so I think that was my problem. I'll update once I've got it ironed out, but I don't want to waste your time since I might have it. :D
Vhati
Posts: 792
Joined: Thu Oct 25, 2012 12:01 pm

Re: [Spoiler] FTL Editor v16 - Unlock ships, Edit SavedGames

Postby Vhati » Thu Jul 11, 2013 9:57 am

This'll pull the image out of resource.dat.

Code: Select all

private BufferedImage getResourceImage(String innerPath) {
  // If caching, you can get(innerPath) from a HashMap and return the pre-loaded pic.
  InputStream in = null;
  try {
    in = DataManager.get().getResourceInputStream(innerPath);
    BufferedImage result = ImageIO.read(in);
    return result;  // If caching, put result in the map before returning.
  }
  catch (IOException e) {
    log.error( "Failed to load resource image ("+ innerPath +")", e );
  }
  finally {
    try {if (in != null) in.close();}
    catch (IOException f) {}
  }
}


Code: Select all

// Set during init. Don't use the hard drive to buffer streams during ImageIO.read().
ImageIO.setUseCache(false);  // Small images don't need extra buffering.

// ...

BufferedImage baseImage = getResourceImage("img/ship/"+ ship.getGraphicsBaseName() +"_base.png");
JLabel lblShipID = new JLabel("", new ImageIcon(baseImage), JLabel.CENTER);
frmSpaceDock.getContentPane().add(lblShipID);


Tip: An ImageIcon that's constructed directly from a path-string caches the image... somewhere. In big apps, it can be inconvenient to later clear old images (link, more info). So I try to avoid that method.

ImageIO.read() doesn't do that. Each read() returns a unique image object that dies on its own when abandoned (When a cache is needed, a HashMap<String,BufferedImage> will suffice).
More relevant to your project, ImageIO can read a stream from DataManager.

Who is online

Users browsing this forum: No registered users and 23 guests