diff --git a/Builder/builder.py b/Builder/builder.py new file mode 100644 index 0000000..4c909d1 --- /dev/null +++ b/Builder/builder.py @@ -0,0 +1,27 @@ +import zipfile +import yaml +import os + +def getconfig(): + try: + with open('./config.yaml', 'r') as confFile: + conf = yaml.full_load(confFile) + except FileNotFoundError: + print('File not found') + return conf + +def zipOutput(): + with zipfile.ZipFile('SSE.zip', 'w', + compression=zipfile.ZIP_DEFLATED, + compresslevel=9) as zipArch: + zipArch.write('SSE.exe') + + +conf = getconfig() +paramsStr = '--' + ' --'.join(conf['params']) +plugins = conf['plugins'] +icon = conf['main']['icon'] + +if __name__ == '__main__': + os.system(f'nuitka {paramsStr} --plugin-enable={plugins} --windows-icon-from-ico={icon} ../SSE.py') + zipOutput() \ No newline at end of file diff --git a/Builder/config.yaml b/Builder/config.yaml new file mode 100644 index 0000000..d135b3e --- /dev/null +++ b/Builder/config.yaml @@ -0,0 +1,13 @@ +main: + version: '0.0.1.0' + author: 'intervision' + authorlink: 'https://github.com/intervisionlord' + icon: '../imgs/SSE_Icon.png' + +plugins: qt-plugins + +params: + - windows-disable-console + - onefile + - standalone + - remove-output \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..19f98ab --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +
+ +
+ +# Stationeers Save Editor +## Описание +Позволяет редактировать некоторые параметры сохранения игры. + +На данный момент можно поменять название игрового мира, кол-во дней с момента начала игры и возможность использования исследований. + +### Версия 0.0.1.0 + +## Интерфейс +
+ +
\ No newline at end of file diff --git a/SSE.py b/SSE.py new file mode 100644 index 0000000..5ff56f5 --- /dev/null +++ b/SSE.py @@ -0,0 +1,68 @@ +from datetime import datetime +from PyQt5.QtGui import QIcon +from PyQt5.QtWidgets import QApplication, QMessageBox, QMainWindow +import xml.etree.ElementTree as ET +from shutil import copytree +import time +import sys +import gui +from os import environ, path, listdir + +class MainForm(QMainWindow, gui.Ui_mainWindow): + def __init__(self): + super().__init__() + self.setupUi(self) + self.setWindowIcon(QIcon('imgs/SSE_icon.png')) + self.savesLabel.setText(self.getPaths()[0]) + self.savesCombo.currentIndexChanged.connect(self.saveChangeSig) + self.saveButton.clicked.connect(self.rewriteSave) + + def getPaths(self): + self.myDocsPath = environ.get('USERPROFILE') + self.savesPath = f'{self.myDocsPath}\\Documents\\My Games\\Stationeers\\saves' + self.savesFile = f'{self.savesPath}\\{self.savesCombo.currentText()}\\world.xml' + return self.savesPath, self.savesFile + + + def getXMLRoot(self): + xmlTree = ET.parse(self.savesFile) + rootNode = xmlTree.getroot() + return xmlTree, rootNode + + def saveChangeSig(self): + self.dateModifLabel.setText(time.ctime(path.getmtime(self.getPaths()[1]))) + rootNode = self.getXMLRoot()[1] + for element in rootNode: + if str(element.tag) == 'ResearchKey': + self.researchCombo.setCurrentText(element.text) + elif str(element.tag) == 'DaysPast': + self.daysPastText.setText(element.text) + elif str(element.tag) == 'WorldName': + self.worldNameText.setText(element.text) + + def rewriteSave(self): + xmlTree = self.getXMLRoot()[0] + xmlTree.find('.//ResearchKey').text = self.researchCombo.currentText() + xmlTree.find('.//DaysPast').text = self.daysPastText.text() + dateformat = '%Y_%m_%d_%H_%M_%S' + if self.backupCheck.isChecked(): + copytree(f'{self.getPaths()[0]}\\{self.savesCombo.currentText()}', + f'{self.getPaths()[0]}\\{self.savesCombo.currentText()}_{datetime.now().strftime(dateformat)}') + xmlTree.write(f'{self.savesFile}') + msgbox('Save File modified!') + +def msgbox(mText): + mBox = QMessageBox() + mBox.setWindowTitle('Info') + mBox.setText(mText) + mBox.setIcon(QMessageBox.Information) + popupWindow = mBox.exec_() + +if __name__ == '__main__': + app = QApplication(sys.argv) + form = MainForm() + form.show() + for i in (listdir(form.savesPath)): + if path.isdir(f'{form.savesPath}\\{i}'): + form.savesCombo.addItem(str(i)) + app.exec() \ No newline at end of file diff --git a/UI/main.ui b/UI/main.ui new file mode 100644 index 0000000..ae9b431 --- /dev/null +++ b/UI/main.ui @@ -0,0 +1,305 @@ + + + mainWindow + + + + 0 + 0 + 320 + 248 + + + + + 320 + 248 + + + + + 600 + 248 + + + + Stationeers Save Editor + + + + + + + + + + 50 + false + false + + + + Qt::LeftToRight + + + Save Info + + + Qt::AlignCenter + + + false + + + false + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + + + + + + 50 + false + false + true + + + + Qt::LeftToRight + + + false + + + Save Parameters + + + Qt::AlignCenter + + + false + + + + QLayout::SetDefaultConstraint + + + + + + + + + World Name + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 80 + 20 + + + + + + + + + + + + Days Past + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 80 + 20 + + + + + + + + + + + + Research + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + ResearchOff + + + + ResearchOff + + + + + ResearchOn + + + + + + + + + + + + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + + + + TextLabel + + + + + + + + + + + + Save file + + + + + + + Backup Original Save + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..cf88b8a --- /dev/null +++ b/gui.py @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'UI/main.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_mainWindow(object): + def setupUi(self, mainWindow): + mainWindow.setObjectName("mainWindow") + mainWindow.resize(320, 248) + mainWindow.setMinimumSize(QtCore.QSize(320, 248)) + mainWindow.setMaximumSize(QtCore.QSize(600, 248)) + self.centralwidget = QtWidgets.QWidget(mainWindow) + self.centralwidget.setObjectName("centralwidget") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.centralwidget) + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.verticalLayout_MAIN = QtWidgets.QVBoxLayout() + self.verticalLayout_MAIN.setObjectName("verticalLayout_MAIN") + self.saveInfoGroup = QtWidgets.QGroupBox(self.centralwidget) + font = QtGui.QFont() + font.setBold(False) + font.setItalic(False) + font.setWeight(50) + self.saveInfoGroup.setFont(font) + self.saveInfoGroup.setLayoutDirection(QtCore.Qt.LeftToRight) + self.saveInfoGroup.setAlignment(QtCore.Qt.AlignCenter) + self.saveInfoGroup.setFlat(False) + self.saveInfoGroup.setCheckable(False) + self.saveInfoGroup.setObjectName("saveInfoGroup") + self.gridLayout = QtWidgets.QGridLayout(self.saveInfoGroup) + self.gridLayout.setObjectName("gridLayout") + self.dateModifLabel = QtWidgets.QLabel(self.saveInfoGroup) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dateModifLabel.sizePolicy().hasHeightForWidth()) + self.dateModifLabel.setSizePolicy(sizePolicy) + self.dateModifLabel.setObjectName("dateModifLabel") + self.gridLayout.addWidget(self.dateModifLabel, 1, 1, 1, 1) + self.savesCombo = QtWidgets.QComboBox(self.saveInfoGroup) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.savesCombo.sizePolicy().hasHeightForWidth()) + self.savesCombo.setSizePolicy(sizePolicy) + self.savesCombo.setMaximumSize(QtCore.QSize(100, 16777215)) + self.savesCombo.setObjectName("savesCombo") + self.gridLayout.addWidget(self.savesCombo, 1, 0, 1, 1) + self.saveParamsGroup = QtWidgets.QGroupBox(self.saveInfoGroup) + font = QtGui.QFont() + font.setBold(False) + font.setWeight(50) + font.setStrikeOut(False) + font.setKerning(True) + self.saveParamsGroup.setFont(font) + self.saveParamsGroup.setLayoutDirection(QtCore.Qt.LeftToRight) + self.saveParamsGroup.setAutoFillBackground(False) + self.saveParamsGroup.setAlignment(QtCore.Qt.AlignCenter) + self.saveParamsGroup.setFlat(False) + self.saveParamsGroup.setObjectName("saveParamsGroup") + self.gridLayout_2 = QtWidgets.QGridLayout(self.saveParamsGroup) + self.gridLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) + self.gridLayout_2.setObjectName("gridLayout_2") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.worldNameLabel = QtWidgets.QLabel(self.saveParamsGroup) + self.worldNameLabel.setObjectName("worldNameLabel") + self.horizontalLayout_3.addWidget(self.worldNameLabel) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem) + self.worldNameText = QtWidgets.QLineEdit(self.saveParamsGroup) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.worldNameText.sizePolicy().hasHeightForWidth()) + self.worldNameText.setSizePolicy(sizePolicy) + self.worldNameText.setMaximumSize(QtCore.QSize(80, 20)) + self.worldNameText.setObjectName("worldNameText") + self.horizontalLayout_3.addWidget(self.worldNameText) + self.verticalLayout.addLayout(self.horizontalLayout_3) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.daysPastLabel = QtWidgets.QLabel(self.saveParamsGroup) + self.daysPastLabel.setObjectName("daysPastLabel") + self.horizontalLayout_2.addWidget(self.daysPastLabel) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem1) + self.daysPastText = QtWidgets.QLineEdit(self.saveParamsGroup) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.daysPastText.sizePolicy().hasHeightForWidth()) + self.daysPastText.setSizePolicy(sizePolicy) + self.daysPastText.setMaximumSize(QtCore.QSize(80, 20)) + self.daysPastText.setObjectName("daysPastText") + self.horizontalLayout_2.addWidget(self.daysPastText) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.researchLabel = QtWidgets.QLabel(self.saveParamsGroup) + self.researchLabel.setObjectName("researchLabel") + self.horizontalLayout.addWidget(self.researchLabel) + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem2) + self.researchCombo = QtWidgets.QComboBox(self.saveParamsGroup) + self.researchCombo.setEditable(False) + self.researchCombo.setObjectName("researchCombo") + self.researchCombo.addItem("") + self.researchCombo.addItem("") + self.horizontalLayout.addWidget(self.researchCombo) + self.verticalLayout.addLayout(self.horizontalLayout) + self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1) + self.gridLayout.addWidget(self.saveParamsGroup, 3, 0, 1, 2) + self.savesLabel = QtWidgets.QLabel(self.saveInfoGroup) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.savesLabel.sizePolicy().hasHeightForWidth()) + self.savesLabel.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("MS Shell Dlg 2") + self.savesLabel.setFont(font) + self.savesLabel.setObjectName("savesLabel") + self.gridLayout.addWidget(self.savesLabel, 0, 0, 1, 2) + self.verticalLayout_MAIN.addWidget(self.saveInfoGroup) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.saveButton = QtWidgets.QPushButton(self.centralwidget) + self.saveButton.setObjectName("saveButton") + self.horizontalLayout_4.addWidget(self.saveButton) + self.backupCheck = QtWidgets.QCheckBox(self.centralwidget) + self.backupCheck.setObjectName("backupCheck") + self.horizontalLayout_4.addWidget(self.backupCheck) + self.verticalLayout_MAIN.addLayout(self.horizontalLayout_4) + spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_MAIN.addItem(spacerItem3) + self.horizontalLayout_5.addLayout(self.verticalLayout_MAIN) + mainWindow.setCentralWidget(self.centralwidget) + + self.retranslateUi(mainWindow) + QtCore.QMetaObject.connectSlotsByName(mainWindow) + + def retranslateUi(self, mainWindow): + _translate = QtCore.QCoreApplication.translate + mainWindow.setWindowTitle(_translate("mainWindow", "Stationeers Save Editor")) + self.saveInfoGroup.setTitle(_translate("mainWindow", "Save Info")) + self.dateModifLabel.setText(_translate("mainWindow", "TextLabel")) + self.saveParamsGroup.setTitle(_translate("mainWindow", "Save Parameters")) + self.worldNameLabel.setText(_translate("mainWindow", "World Name")) + self.daysPastLabel.setText(_translate("mainWindow", "Days Past")) + self.researchLabel.setText(_translate("mainWindow", "Research")) + self.researchCombo.setCurrentText(_translate("mainWindow", "ResearchOff")) + self.researchCombo.setItemText(0, _translate("mainWindow", "ResearchOff")) + self.researchCombo.setItemText(1, _translate("mainWindow", "ResearchOn")) + self.savesLabel.setText(_translate("mainWindow", "TextLabel")) + self.saveButton.setText(_translate("mainWindow", "Save file")) + self.backupCheck.setText(_translate("mainWindow", "Backup Original Save")) diff --git a/imgs/SSE_Icon.png b/imgs/SSE_Icon.png new file mode 100644 index 0000000..d7c1cf8 Binary files /dev/null and b/imgs/SSE_Icon.png differ