423 lines
16 KiB
Java
423 lines
16 KiB
Java
/*
|
|
* Auto-CreamAPI
|
|
* Copyright (C) 2020 Jeddunk
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with this program. If not, see
|
|
* <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import com.jfoenix.controls.*;
|
|
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
|
|
import javafx.beans.value.ChangeListener;
|
|
import javafx.collections.FXCollections;
|
|
import javafx.concurrent.Service;
|
|
import javafx.concurrent.Task;
|
|
import javafx.fxml.FXML;
|
|
import javafx.scene.control.Alert;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.Tooltip;
|
|
import javafx.scene.paint.Color;
|
|
import javafx.stage.FileChooser;
|
|
import org.apache.commons.codec.digest.DigestUtils;
|
|
import org.apache.commons.configuration2.ex.ConfigurationException;
|
|
import org.jsoup.HttpStatusException;
|
|
import pojo.App;
|
|
import util.CreamApiConfig;
|
|
import util.CreamApiDllHandler;
|
|
import util.SteamAppsListCache;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.nio.file.StandardCopyOption;
|
|
import java.util.Map;
|
|
import java.util.NoSuchElementException;
|
|
import java.util.Objects;
|
|
|
|
public class Controller {
|
|
|
|
private static final String REGEX = "(?<steamApiDll>steam_api(?:64)?.dll)$";
|
|
public Label creamApiDllApplied;
|
|
public Label creamApiConfigExists;
|
|
public FontAwesomeIconView creamApiDllAppliedIcon;
|
|
public FontAwesomeIconView creamApiConfigExistsIcon;
|
|
private CreamApiDllHandler handler = null;
|
|
private boolean is64Bit;
|
|
private boolean isSameFile;
|
|
|
|
{
|
|
try {
|
|
handler = CreamApiDllHandler.getInstance();
|
|
} catch (IOException e) {
|
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
|
alert.setTitle("CreamAPI DLLs missing!");
|
|
alert.setHeaderText("CreamAPI DLL files can't be found!");
|
|
alert.setContentText("Please download CreamAPI and extract the non-log " +
|
|
"version in the same folder as Auto-CreamAPI!\nThe program will now close.");
|
|
alert.showAndWait();
|
|
System.exit(10);
|
|
}
|
|
}
|
|
|
|
private final CreamApiConfig config = CreamApiConfig.getInstance();
|
|
private final SteamAppsListCache cache = new SteamAppsListCache();
|
|
@FXML
|
|
public Label state_label;
|
|
@FXML
|
|
public JFXTextField path_textfield;
|
|
@FXML
|
|
public JFXTextField appId_textfield;
|
|
@FXML
|
|
public JFXTextField game_name_textfield;
|
|
@FXML
|
|
public JFXComboBox<String> language_combobox;
|
|
@FXML
|
|
public JFXTextArea dlc_textarea;
|
|
@FXML
|
|
public JFXCheckBox extra_protection_checkbox;
|
|
@FXML
|
|
public JFXCheckBox offline_checkbox;
|
|
@FXML
|
|
public JFXCheckBox unlock_all_checkbox;
|
|
@FXML
|
|
public JFXButton reset_button;
|
|
@FXML
|
|
public JFXButton save_button;
|
|
@FXML
|
|
public JFXButton getAppId_button;
|
|
@FXML
|
|
public JFXButton path_button;
|
|
@FXML
|
|
public JFXButton retrieveDlcList_button;
|
|
private String steamApiPathString;
|
|
|
|
public Controller() {
|
|
}
|
|
|
|
@FXML
|
|
public void initialize() {
|
|
appId_textfield.textProperty().addListener(appIdChangesGameName());
|
|
//retrieveDlcList_button.setDisable(true); // WIP
|
|
generate_tooltips();
|
|
fix_dlc_textarea_prompt_text();
|
|
reset(true);
|
|
}
|
|
|
|
private void read() {
|
|
language_combobox.setItems(FXCollections.observableArrayList(config.getLanguages()));
|
|
language_combobox.getSelectionModel().select(config.getLanguage());
|
|
appId_textfield.setText(config.getAppId().toString());
|
|
dlc_textarea.setText(config.getDlcListAsString());
|
|
game_name_textfield.setText(cache.getGame(config.getAppId()).getName());
|
|
extra_protection_checkbox.setSelected(config.getExtraProtection());
|
|
offline_checkbox.setSelected(config.getForceOffline());
|
|
unlock_all_checkbox.setSelected(config.getUnlockAll());
|
|
unlockAll_disableDlcTextArea();
|
|
}
|
|
|
|
private void emptyFields() {
|
|
creamApiDllAppliedIcon.setGlyphName("TIMES");
|
|
creamApiConfigExistsIcon.setGlyphName("TIMES");
|
|
appId_textfield.setText("");
|
|
dlc_textarea.setText("");
|
|
game_name_textfield.setText("");
|
|
extra_protection_checkbox.setSelected(false);
|
|
offline_checkbox.setSelected(false);
|
|
unlock_all_checkbox.setSelected(false);
|
|
unlockAll_disableDlcTextArea();
|
|
}
|
|
|
|
private void fix_dlc_textarea_prompt_text() {
|
|
dlc_textarea.setPromptText("List of DLC...\r0000 = DLC Name");
|
|
}
|
|
|
|
private void generate_tooltips() {
|
|
Tooltip extra_protection_tooltip = new Tooltip("\"extra protection\"");
|
|
extra_protection_checkbox.setTooltip(extra_protection_tooltip);
|
|
Tooltip.install(extra_protection_checkbox, extra_protection_tooltip);
|
|
}
|
|
|
|
private ChangeListener<String> appIdChangesGameName() {
|
|
return (observable, oldValue, newValue) -> {
|
|
int appId;
|
|
try {
|
|
appId = Integer.parseInt(newValue);
|
|
final App game = cache.getGame(appId);
|
|
if (game != null) {
|
|
game_name_textfield.setText(game.getName());
|
|
} else {
|
|
game_name_textfield.setText("");
|
|
}
|
|
} catch (NumberFormatException e) {
|
|
game_name_textfield.setText("");
|
|
}
|
|
};
|
|
}
|
|
|
|
private void reset(boolean silent) {
|
|
if (silent) {
|
|
state_label.setText("");
|
|
} else {
|
|
state_label.setText("Resetting fields...");
|
|
}
|
|
try {
|
|
config.read();
|
|
read();
|
|
if (!silent) {
|
|
state_label.setText("Successfully reset all fields!");
|
|
}
|
|
} catch (NoSuchElementException e) {
|
|
System.err.println("Error reading cream_api.ini! " +
|
|
"This can be ignored if setting up CreamAPI for the first time.");
|
|
} catch (NullPointerException e) {
|
|
System.err.println("Can't fill out fields, no configuration file set!");
|
|
if (!silent) {
|
|
state_label.setText("Could not reset fields, no configuration file set!");
|
|
}
|
|
}
|
|
updateIndicators();
|
|
}
|
|
|
|
private void updateIndicators() {
|
|
Color colorSuccess = Color.web("#43A047");
|
|
Color colorFailure = Color.web("#E53935");
|
|
try {
|
|
is64Bit = false;
|
|
if (!steamApiPathString.isEmpty()) {
|
|
Path dllPath = Paths.get(steamApiPathString);
|
|
if (dllPath.endsWith("steam_api64.dll")) {
|
|
is64Bit = true;
|
|
}
|
|
InputStream is = Files.newInputStream(dllPath);
|
|
String md5 = DigestUtils.md5Hex(is);
|
|
isSameFile = Objects.equals(md5, handler.getDllMd5(is64Bit));
|
|
if (isSameFile) {
|
|
creamApiDllApplied.setTextFill(colorSuccess);
|
|
creamApiDllAppliedIcon.setFill(colorSuccess);
|
|
creamApiDllAppliedIcon.setGlyphName("CHECK");
|
|
} else {
|
|
creamApiDllApplied.setTextFill(colorFailure);
|
|
creamApiDllAppliedIcon.setFill(colorFailure);
|
|
creamApiDllAppliedIcon.setGlyphName("TIMES");
|
|
}
|
|
Path configPath = Paths.get(config.getPath());
|
|
if (Files.exists(configPath) && Files.size(configPath) > 0L) {
|
|
creamApiConfigExists.setTextFill(colorSuccess);
|
|
creamApiConfigExistsIcon.setFill(colorSuccess);
|
|
creamApiConfigExistsIcon.setGlyphName("CHECK");
|
|
} else {
|
|
creamApiConfigExists.setTextFill(colorFailure);
|
|
creamApiConfigExistsIcon.setFill(colorFailure);
|
|
creamApiConfigExistsIcon.setGlyphName("TIMES");
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
System.err.println("Error! Resetting visual indicators!");
|
|
creamApiDllApplied.setTextFill(colorFailure);
|
|
creamApiDllAppliedIcon.setFill(colorFailure);
|
|
creamApiDllAppliedIcon.setGlyphName("TIMES");
|
|
creamApiConfigExists.setTextFill(colorFailure);
|
|
creamApiConfigExistsIcon.setFill(colorFailure);
|
|
creamApiConfigExistsIcon.setGlyphName("TIMES");
|
|
}
|
|
}
|
|
|
|
public void save() {
|
|
Service<Void> s = new Service<Void>() {
|
|
@Override
|
|
protected Task<Void> createTask() {
|
|
return new Task<Void>() {
|
|
@Override
|
|
protected Void call() {
|
|
try {
|
|
setUpCreamApi();
|
|
config.setDlcListFromString(dlc_textarea.getText());
|
|
config.setAppId(Integer.parseInt(appId_textfield.getText()));
|
|
config.setExtraProtection(extra_protection_checkbox.isSelected());
|
|
config.setForceOffline(offline_checkbox.isSelected());
|
|
config.setUnlockAll(unlock_all_checkbox.isSelected());
|
|
config.setLanguage(language_combobox.getValue());
|
|
config.sync();
|
|
} catch (IOException | ConfigurationException e) {
|
|
e.printStackTrace();
|
|
cancel();
|
|
} catch (NullPointerException e) {
|
|
System.err.println("No configuration file set!");
|
|
cancel();
|
|
}
|
|
updateIndicators();
|
|
return null;
|
|
}
|
|
};
|
|
}
|
|
};
|
|
s.setOnRunning(event -> {
|
|
setDisableAllButtons(true);
|
|
state_label.setText("Saving...");
|
|
});
|
|
s.setOnSucceeded(event -> {
|
|
setDisableAllButtons(false);
|
|
state_label.setText("Saved successfully!");
|
|
});
|
|
s.setOnCancelled(event -> {
|
|
setDisableAllButtons(false);
|
|
state_label.setText("Could not save configuration file!");
|
|
});
|
|
s.start();
|
|
}
|
|
|
|
public void getAppId() {
|
|
final App game = cache.findGame(game_name_textfield.getText());
|
|
if (game == null) {
|
|
appId_textfield.setText("-1");
|
|
} else {
|
|
appId_textfield.setText(String.valueOf(game.getAppId()));
|
|
}
|
|
}
|
|
|
|
public void unlockAll_disableDlcTextArea() {
|
|
dlc_textarea.setDisable(unlock_all_checkbox.isSelected());
|
|
retrieveDlcList_button.setDisable(unlock_all_checkbox.isSelected());
|
|
}
|
|
|
|
/**
|
|
* Gets DLC from both the Steam Store and SteamDB, since the latter has a (weird) limit of 64(?) DLCs. SteamDB
|
|
* also lists DLC not available for purchase.
|
|
*/
|
|
public void getDlcList() {
|
|
Service<Void> s = new Service<Void>() {
|
|
@Override
|
|
protected Task<Void> createTask() {
|
|
return new Task<Void>() {
|
|
@Override
|
|
protected Void call() {
|
|
try {
|
|
Map<Number, String> collect = cache.getDlcMap(appId_textfield.getText());
|
|
StringBuilder sb = new StringBuilder();
|
|
collect.forEach((k, v) -> sb.append(k).append("=").append(v).append("\n"));
|
|
dlc_textarea.setText(sb.toString());
|
|
} catch (HttpStatusException e) {
|
|
if (e.getStatusCode() == 404) {
|
|
System.err.println("App ID empty or not found! (HTTP Status Code: 404)");
|
|
} else {
|
|
// e.printStackTrace();
|
|
System.err.println("STATUS CODE: " + e.getStatusCode());
|
|
}
|
|
cancel();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
cancel();
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
}
|
|
};
|
|
s.setOnRunning(event -> {
|
|
setDisableAllButtons(true);
|
|
state_label.setText("Getting list of DLCs...");
|
|
});
|
|
s.setOnSucceeded(event -> {
|
|
setDisableAllButtons(false);
|
|
state_label.setText("Got list of DLCs successfully!");
|
|
});
|
|
s.setOnCancelled(event -> {
|
|
setDisableAllButtons(false);
|
|
state_label.setText("Could not get list of DLCs!");
|
|
});
|
|
s.start();
|
|
}
|
|
|
|
public void openFileChooser() {
|
|
FileChooser chooser = new FileChooser();
|
|
chooser.setTitle("Choose steam_api(64).dll...");
|
|
FileChooser.ExtensionFilter filter =
|
|
new FileChooser.ExtensionFilter("steam_api(64).dll",
|
|
"steam_api.dll", "steam_api64.dll");
|
|
chooser.getExtensionFilters().add(filter);
|
|
final File file = chooser.showOpenDialog(path_button.getScene().getWindow());
|
|
try {
|
|
config.setConfig(file.getParent() + "\\cream_api.ini");
|
|
} catch (ConfigurationException | IOException e) {
|
|
e.printStackTrace();
|
|
} catch (NullPointerException e) {
|
|
System.err.println("Could not set config file location! Did you cancel the file chooser?");
|
|
}
|
|
path_textfield.setText(file.getParent());
|
|
steamApiPathString = file.getAbsolutePath();
|
|
emptyFields();
|
|
reset(true);
|
|
state_label.setText("Ready.");
|
|
}
|
|
|
|
/**
|
|
* check if creamapi version of dll is there, if not, rename original to steam_api(64)_o.dll and copy
|
|
* creamapi dll to the path. also looks for alternative steam dll (which means it patches both 64 and 32 bit
|
|
* dlls at once if found)
|
|
*
|
|
* @throws IOException If file is missing or not accessible/modifiable.
|
|
*/
|
|
private void setUpCreamApi() throws IOException {
|
|
Path path = Paths.get(steamApiPathString);
|
|
copyDllFile(path, isSameFile);
|
|
findAdditionalDll(path);
|
|
}
|
|
|
|
private void findAdditionalDll(Path path) throws IOException {
|
|
String secondDllString = is64Bit ? "\\steam_api.dll" : "\\steam_api64.dll";
|
|
Path dir = path.getParent();
|
|
Path secondDll = Paths.get(dir.toString() + secondDllString);
|
|
if (Files.exists(secondDll)) {
|
|
System.out.println("Alternative DLL found!");
|
|
InputStream is = Files.newInputStream(secondDll);
|
|
String md5 = DigestUtils.md5Hex(is);
|
|
boolean isSameFile1 = Objects.equals(md5, handler.getDllMd5(!is64Bit));
|
|
copyDllFile(secondDll, isSameFile1);
|
|
}
|
|
}
|
|
|
|
private void copyDllFile(Path path, boolean isSameFile) throws IOException {
|
|
if (!isSameFile) {
|
|
String pathOrigString = steamApiPathString;
|
|
pathOrigString =
|
|
pathOrigString
|
|
.replaceFirst(REGEX, is64Bit ? "steam_api64_o.dll" : "steam_api_o.dll");
|
|
Path pathOrig = Paths.get(pathOrigString);
|
|
if (!Files.exists(pathOrig)) {
|
|
Files.move(path, pathOrig);
|
|
} else {
|
|
String pathBakString = steamApiPathString;
|
|
pathBakString =
|
|
pathBakString
|
|
.replaceFirst(REGEX, is64Bit ? "steam_api64.dll.backup" : "steam_api.dll.backup");
|
|
Path pathBak = Paths.get(pathBakString);
|
|
Files.move(path, pathBak, StandardCopyOption.REPLACE_EXISTING);
|
|
}
|
|
//Files.deleteIfExists(path);
|
|
Files.copy(handler.getDllPath(is64Bit), path);
|
|
}
|
|
}
|
|
|
|
private void setDisableAllButtons(boolean b) {
|
|
reset_button.setDisable(b);
|
|
save_button.setDisable(b);
|
|
getAppId_button.setDisable(b);
|
|
path_button.setDisable(b);
|
|
retrieveDlcList_button.setDisable(b);
|
|
}
|
|
|
|
public void resetFromButton() {
|
|
reset(false);
|
|
}
|
|
}
|