package com.narrowtux.fmm.model; import com.google.common.io.LittleEndianDataInputStream; import com.narrowtux.fmm.util.Util; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.image.Image; import java.io.*; import java.nio.file.Path; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class Save { private ObjectProperty<Path> path = new SimpleObjectProperty<>(); private StringProperty name = new SimpleStringProperty(); private ObjectProperty<Image> screenshot = new SimpleObjectProperty<>(); private ObservableList<Mod> mods = FXCollections.observableArrayList(); //TODO more properties like playtime and such public Save(Path path) { this.path.addListener((obj, ov, nv) -> { if (nv != null) { // set the filename String fileName = nv.getFileName().toString(); fileName = fileName.substring(0, fileName.indexOf('.')); name.set(fileName); mods.clear(); screenshot.set(null); try { ZipInputStream zip = new ZipInputStream(new FileInputStream(nv.toFile())); ZipEntry entry = null; while ((entry = zip.getNextEntry()) != null) { String zipEntryName = (new File(entry.getName()).getName()); if (zipEntryName.equals("level-init.dat")) { // read mods LittleEndianDataInputStream in = new LittleEndianDataInputStream(new BufferedInputStream(zip)); // skip 32 bytes and then look for "base" in.skip(32); in.mark(64); int bytes = 0; while (true) { char c = (char) in.readUnsignedByte(); bytes ++; if (c == 'b') { c = (char) in.readUnsignedByte(); bytes ++; if (c == 'a') { c = (char) in.readUnsignedByte(); bytes ++; if (c == 's') { c = (char) in.readUnsignedByte(); bytes ++; if (c == 'e') { in.reset(); break; } } } } } // word "base" was found bytes -= 12; if (in.skip(bytes) != bytes) { return; } int modSize = in.readInt(); for (int i = 0; i < modSize; i++) { String modName = Util.readString(in); short major = in.readShort(); short minor = in.readShort(); short build = in.readShort(); Version version = new Version(major, minor, build); Mod mod = Datastore.getInstance().getMod(modName, version); mods.add(mod); } break; } else if (zipEntryName.equals("preview.png")) { // read screenshot Image img = new Image(zip); this.screenshot.set(img); } if (mods.size() > 0 && this.screenshot.get() != null) { break; } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); this.path.set(path); } public Path getPath() { return path.get(); } public ObjectProperty<Path> pathProperty() { return path; } public void setPath(Path path) { this.path.set(path); } public String getName() { return name.get(); } public StringProperty nameProperty() { return name; } public void setName(String name) { this.name.set(name); } public Image getScreenshot() { return screenshot.get(); } public ObjectProperty<Image> screenshotProperty() { return screenshot; } public void setScreenshot(Image screenshot) { this.screenshot.set(screenshot); } public ObservableList<Mod> getMods() { return mods; } }