Skip to content

Commit

Permalink
[#1] Working on multimod functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
DaloLorn committed Aug 23, 2021
1 parent a7290c7 commit f8e0d2f
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ModInstaller {
public static final String ENCOUNTERED_AN_EXCEPTION = "Encountered an exception: ";
public static final String PROTOCOL_GIT = "git://";
public static final String PROTOCOL_HTTPS = "https://";
public static final String NO_MOD_DESC = "No description could be found for this mod.";
public static final String NO_REPO_DESC = "No description could be found for this repository.";

private static Git repo;

Expand Down Expand Up @@ -204,7 +204,7 @@ public static String getDescription(@Nullable TextHandler errorHandler) {
var description = Utils.readGitFile(readmeLoader);
if (description != null)
return description;
else return NO_MOD_DESC;
else return NO_REPO_DESC;
} catch (Exception e) {
if(errorHandler != null)
errorHandler.handle(ENCOUNTERED_AN_EXCEPTION + e);
Expand Down Expand Up @@ -302,7 +302,7 @@ private static Modinfo findModinfo(
if(warningHandler != null)
warningHandler.handle("WARNING: Unable to discard repository metadata!\n\nTo improve loading times, it is recommended that you delete the installed mod's .git folder once installation is completed.");
}
return new Modinfo(inRoot, mod);
return new Modinfo(inRoot, mod, finder.getResult().toFile());
}
else {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package com.dalolorn.sr2modmanager.adapter.sr2utils;

import org.eclipse.jgit.lib.ObjectLoader;
import org.jetbrains.annotations.NotNull;

import java.io.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

public class DataReader {
public final String filename;
public final List<String> lines;

public boolean allowLines;
public boolean fullLine = false;
public boolean allowMultiline = true;
public boolean skipComments = true;
public boolean skipEmpty = true;

public boolean inMultiline = false;
public boolean squash = false;
public int indent;
public int lineIndex;
public String line;
public String key;
public String value;

public DataReader(@NotNull File file) throws IOException {
this(file, true);
}

public DataReader(@NotNull File file, boolean allowLines) throws IOException {
this.allowLines = allowLines;
filename = file.getName();

try (
var fileStream = new FileInputStream(file);
var fileReader = new BufferedReader(new InputStreamReader(fileStream))
) {
lines = fileReader.lines().collect(Collectors.toUnmodifiableList());
}
}

public DataReader(@NotNull ObjectLoader fileLoader, @NotNull String name) throws IOException {
this(fileLoader, name, true);
}

public DataReader(@NotNull ObjectLoader fileLoader, @NotNull String name, boolean allowLines) throws IOException {
this.allowLines = allowLines;
filename = name;

try (
var fileStream = fileLoader.openStream();
var fileReader = new BufferedReader(new InputStreamReader(fileStream))
) {
lines = fileReader.lines().map(str -> str+"\n").collect(Collectors.toUnmodifiableList());
}
}

public String position() {
return filename + " | Line " + lineIndex;
}

public boolean feed(String feedLine) {
line = feedLine;
return handle();
}

public boolean handle() {
// Handle multiline values
if(inMultiline) {
return handleMultilineValues();
}

// Cut off comments
cutOffComments();

// Get indent level
if (getIndentLevel()) return false;

// Detect comments
if(skipEmpty && line.isEmpty())
return false;

boolean isKeyValue = splitKeyValue(line);

if(!isKeyValue) {
if(allowLines) {
fullLine = true;
return true;
}
else {
return false;
}
}
else {
key = key.trim();
value = value.trim();
fullLine = false;

// Detect multiline blocks
if(allowMultiline && (value.equals("<<") || value.equals("<<|"))) {
squash = value.length() == 3;
value = "";
inMultiline = true;
return false;
}

return !key.isEmpty();
}
}

private boolean handleMultilineValues() {
line = line.trim();

if(line.length() > 1) {
if(line.charAt(line.length() - 1) == '\\')
line = line.substring(0, line.length() - 1);
else
line = squash ? " " : "\n";
}
else {
// Preserve empty lines in squash mode
line += squash ? "\n\n" : "\n";
}

if(line.startsWith(">>")) {
// Remove the last linebreak
if(value.length() > 0 && value.charAt(value.length() - 1) == '\n')
value = value.substring(0, value.length() - 1);
inMultiline = false;
return true;
}
else {
value += line;
return false;
}
}

private void cutOffComments() {
if(skipComments) {
int commentIndex = line.indexOf("//");
if(commentIndex != -1)
line = line.substring(0, commentIndex);
}
}

private boolean getIndentLevel() {
int pos = line.length() - line.stripLeading().length();
if(pos == 0) {
if(skipEmpty)
return true;
indent = 0;
}
else {
int rpos = line.substring(0, line.length() - line.stripTrailing().length()).length();
if(rpos != 0)
line = line.substring(pos, rpos - pos + 1);
indent = pos;
}
return false;
}

public boolean next() {
while(lineIndex < lines.size()) {
line = lines.get(lineIndex).trim();
lineIndex++;
if(handle())
return true;
}

return false;
}

public void reset() {
lineIndex = 0;
}

public boolean splitKeyValue(String input) {
return splitKeyValue(input, ':');
}

public boolean splitKeyValue(String input, char separator) {
int index = input.indexOf(separator);
if(index == -1)
return false;
key = input.substring(0, index);
value = input.substring(index+1);
return true;
}

public List<String> compilePattern(String pattern) {
pattern = pattern.toLowerCase(Locale.ROOT);
if(pattern.isEmpty())
return Collections.emptyList();

List<String> compiled = Arrays.asList(pattern.split("\\*"));
if(pattern.endsWith("*"))
compiled.add("");
return compiled;
}
}
68 changes: 67 additions & 1 deletion src/main/java/com/dalolorn/sr2modmanager/model/Modinfo.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,77 @@
package com.dalolorn.sr2modmanager.model;

import com.dalolorn.sr2modmanager.adapter.sr2utils.DataReader;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Modinfo {
private static final int CUR_COMPATIBILITY = 200;

public final boolean inRoot;
public final String folderName;

public Modinfo(boolean inRoot, String folderName) {
public String name;
public String description;
public String parentName;
public int version;
public int compatibility;
public boolean isBase;
public boolean listed;
public boolean forCurrentVersion;
public List<String> overrides = new ArrayList<>();
public List<List<String>> overridePatterns = new ArrayList<>();
public Map<Integer, String> fallbacks;

public Modinfo(boolean inRoot, String folderName, File file) throws IOException {
this.inRoot = inRoot;
this.folderName = folderName;
parse(new DataReader(file));
}

private void parse(DataReader file) {
String key;
String value;
while(file.next()) {
key = file.key;
value = file.value;
if(key.equalsIgnoreCase("Name")) {
name = value;
}
else if(key.equalsIgnoreCase("Description")) {
description = value;
}
else if(key.equalsIgnoreCase("Override")) {
overrides.add(value);
List<String> compiled = file.compilePattern(value);
overridePatterns.add(compiled);
}
else if(key.equalsIgnoreCase("Derives From")) {
if(value.equals("-"))
parentName = "";
else
parentName = value;
}
else if(key.equalsIgnoreCase("Base Mod")) {
isBase = Boolean.parseBoolean(value);
}
else if(key.equalsIgnoreCase("Listed")) {
listed = Boolean.parseBoolean(value);
}
else if(key.equalsIgnoreCase("Version")) {
version = Integer.parseInt(value);
}
else if(key.equalsIgnoreCase("Compatibility")) {
compatibility = Integer.parseInt(value);
forCurrentVersion = compatibility >= CUR_COMPATIBILITY;
}
else if(key.equalsIgnoreCase("Fallback")) {
file.splitKeyValue(value, '=');
fallbacks.put(Integer.parseInt(file.value), file.key);
}
}
}
}
1 change: 1 addition & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

exports com.dalolorn.sr2modmanager.adapter;
exports com.dalolorn.sr2modmanager.model;
exports com.dalolorn.sr2modmanager.adapter.sr2utils;
opens com.dalolorn.sr2modmanager.view;
opens com.dalolorn.sr2modmanager.adapter to com.google.gson;
}
22 changes: 11 additions & 11 deletions src/main/resources/com/dalolorn/sr2modmanager/view/MainFrame.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.dalolorn.sr2modmanager.view.MainController">
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.dalolorn.sr2modmanager.view.MainController">
<top>
<MenuBar>
<Menu mnemonicParsing="false" text="File">
<MenuItem mnemonicParsing="false" onAction="#openRepository" text="Open Mod Repository" fx:id="openRepositoryItem"/>
<MenuItem fx:id="openRepositoryItem" mnemonicParsing="false" onAction="#openRepository" text="Open Mod Repository" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" onAction="#close" text="Close"/>
<MenuItem mnemonicParsing="false" onAction="#close" text="Close" />
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<MenuItem mnemonicParsing="false" onAction="#deleteRepository" text="Delete Mod Repository" fx:id="deleteRepositoryItem" disable="true"/>
<MenuItem mnemonicParsing="false" onAction="#uninstallMod" text="Uninstall Mod" fx:id="uninstallModItem" disable="true"/>
<MenuItem fx:id="deleteRepositoryItem" disable="true" mnemonicParsing="false" onAction="#deleteRepository" text="Delete Mod Repository" />
<MenuItem fx:id="uninstallModItem" disable="true" mnemonicParsing="false" onAction="#uninstallMod" text="Uninstall Mod" />
</Menu>
<Menu mnemonicParsing="false" text="Options">
<MenuItem mnemonicParsing="false" onAction="#setSR2Path" text="Set SR2 Path" />
Expand All @@ -25,14 +25,14 @@
</top>
<center>
<TabPane fx:id="tabs">
<Tab text="Manage Mods" fx:id="modsTab">
<fx:include source="ModManager.fxml" fx:id="modsPane"/>
<Tab fx:id="modsTab" text="Manage Mods">
<fx:include fx:id="modsPane" source="ModManager.fxml" />
</Tab>
<Tab text="Install Mods" fx:id="installerTab">
<fx:include source="ModInstaller.fxml" fx:id="installerPane"/>
<Tab fx:id="installerTab" text="Install Mods">
<fx:include fx:id="installerPane" source="ModInstaller.fxml" />
</Tab>
<Tab text="Manage OpenSR" fx:id="osrTab">
<fx:include source="OpenSRManager.fxml" fx:id="osrPane"/>
<Tab fx:id="osrTab" text="Manage OpenSR">
<fx:include fx:id="osrPane" source="OpenSRManager.fxml" />
</Tab>
</TabPane>
</center>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.layout.*?>
<fx:root prefWidth="600.0" type="BorderPane" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.dalolorn.sr2modmanager.view.ModEntry">
<fx:root prefWidth="750.0" type="BorderPane" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.dalolorn.sr2modmanager.view.ModEntry">
<left>
<CheckBox fx:id="enabledToggle" mnemonicParsing="false" onAction="#toggleMod" text="CheckBox" BorderPane.alignment="CENTER">
<BorderPane.margin>
Expand Down
Loading

0 comments on commit f8e0d2f

Please sign in to comment.