Possible to setup custom saved game and installation directory.

This commit is contained in:
Khopa 2020-06-05 14:21:42 +02:00
parent ce70242c35
commit b219b2a71b
13 changed files with 402 additions and 176 deletions

View File

@ -1,3 +1,18 @@
#2.0 RC 7
##Features/Improvements :
* **[Units/Factions]** Added P-47D-30 for factions allies_1944
* **[Mission Generator]** CAP flights have been slightly reworked
* **[Mission Generator]** Add PP points for JF-17 on STRIKE missions
* **[Mission Generator]** Add ST point for F-14B on STRIKE missions
* **[Mission Generator]** Flights with client slots will never be delayed
* **[Mission Generator]** AI units can start from parking
##Fixed issues :
* **[Mission Generator]** When playing as RED the activation trigger would not be properly generated
* **[Mission Generator]** Changed "strike" payload for Su-24M
* **[Mission Generator]** FW-190A8 is now properly considered as flyable
#2.0 RC 6
Saves file from RC5 are not compatible with the new version.

View File

@ -21,5 +21,6 @@ class Settings:
perf_artillery = True
perf_moving_units = True
perf_infantry = True
perf_ai_parking_start = True

View File

@ -48,6 +48,7 @@ CAP_CAPABLE = [
P_51D_30_NA,
P_51D,
P_47D_30,
SpitfireLFMkIXCW,
SpitfireLFMkIX,
@ -106,6 +107,7 @@ CAS_CAPABLE = [
P_51D_30_NA,
P_51D,
P_47D_30,
A_20G,
SpitfireLFMkIXCW,
@ -169,6 +171,7 @@ STRIKE_CAPABLE = [
P_51D_30_NA,
P_51D,
P_47D_30,
A_20G,
SpitfireLFMkIXCW,

View File

@ -4,6 +4,7 @@ import sys
from shutil import copyfile
import dcs
from PySide2 import QtWidgets
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QSplashScreen
from dcs import installation
@ -11,12 +12,22 @@ from dcs import installation
from qt_ui import uiconstants
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.QLiberationWindow import QLiberationWindow
from userdata import persistency, logging as logging_module
from qt_ui.windows.preferences.QLiberationFirstStartWindow import QLiberationFirstStartWindow
from userdata import persistency, logging as logging_module, liberation_install
if __name__ == "__main__":
persistency.setup(installation.get_dcs_saved_games_directory())
app = QApplication(sys.argv)
css = ""
with open("./resources/stylesheets/style.css") as stylesheet:
app.setStyleSheet(stylesheet.read())
# Logging setup
VERSION_STRING = "2.0RC6"
logging_module.setup_version_string(VERSION_STRING)
# Inject custom payload in pydcs framework
custom_payloads = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..\\resources\\customized_payloads")
if os.path.exists(custom_payloads):
dcs.planes.FlyingType.payload_dirs.append(custom_payloads)
@ -27,11 +38,14 @@ if __name__ == "__main__":
if os.path.exists(custom_payloads):
dcs.planes.FlyingType.payload_dirs.append(custom_payloads)
VERSION_STRING = "2.0RC6"
logging_module.setup_version_string(VERSION_STRING)
logging.info("Using {} as userdata folder".format(persistency.base_path()))
app = QApplication(sys.argv)
first_start = liberation_install.init()
if first_start:
window = QLiberationFirstStartWindow()
window.exec_()
logging.info("Using {} as 'Saved Game Folder'".format(persistency.base_path()))
logging.info("Using {} as 'DCS installation folder'".format(liberation_install.get_dcs_install_directory()))
# Splash screen setup
pixmap = QPixmap("./resources/ui/splash_screen.png")
@ -44,24 +58,28 @@ if __name__ == "__main__":
uiconstants.load_aircraft_icons()
uiconstants.load_vehicle_icons()
css = ""
with open("./resources/stylesheets/style.css") as stylesheet:
css = stylesheet.read()
# Replace DCS Mission scripting file to allow DCS Liberation to work
print("Replace : " + installation.get_dcs_install_directory() + os.path.sep + "Scripts/MissionScripting.lua")
copyfile("./resources/scripts/MissionScripting.lua", installation.get_dcs_install_directory() + os.path.sep + "Scripts/MissionScripting.lua")
app.processEvents()
try:
liberation_install.replace_mission_scripting_file()
except:
error_dialog = QtWidgets.QErrorMessage()
error_dialog.setWindowTitle("Wrong DCS installation directory.")
error_dialog.showMessage("Unable to modify Mission Scripting file. Possible issues with rights. Try running as admin, or please perform the modification of the MissionScripting file manually.")
error_dialog.exec_()
# Apply CSS (need works)
app.setStyleSheet(css)
GameUpdateSignal()
# Start window
window = QLiberationWindow()
window.showMaximized()
splash.finish(window)
sys.exit(app.exec_())
qt_execution_code = app.exec_()
# Restore Mission Scripting file
logging.info("QT App terminated with status code : " + str(qt_execution_code))
logging.info("Attempt to restore original mission scripting file")
liberation_install.restore_original_mission_scripting()
sys.exit(qt_execution_code)

View File

@ -8,12 +8,12 @@ from game.event import UnitsDeliveryEvent, FrontlineAttackEvent
from theater.theatergroundobject import CATEGORY_MAP
URLS : Dict[str, str] = {
"Manual": "https://github.com/shdwp/dcs_liberation/wiki/Manual",
"Manual": "https://github.com/khopa/dcs_liberation/wiki",
"Troubleshooting": "https://github.com/shdwp/dcs_liberation/wiki/Troubleshooting",
"Modding": "https://github.com/shdwp/dcs_liberation/wiki/Modding-tutorial",
"Repository": "https://github.com/shdwp/dcs_liberation",
"Repository": "https://github.com/khopa/dcs_liberation",
"ForumThread": "https://forums.eagle.ru/showthread.php?t=214834",
"Issues": "https://github.com/shdwp/dcs_liberation/issues"
"Issues": "https://github.com/khopa/dcs_liberation/issues"
}
LABELS_OPTIONS = ["Full", "Abbreviated", "Dot Only", "Off"]

View File

@ -1,10 +1,9 @@
import sys
import webbrowser
from PySide2 import QtGui
from PySide2.QtCore import Qt
from PySide2.QtGui import QIcon
from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \
from PySide2.QtWidgets import QWidget, QVBoxLayout, QMainWindow, QAction, QMessageBox, QDesktopWidget, \
QSplitter
import qt_ui.uiconstants as CONST
@ -12,10 +11,12 @@ from game import Game
from qt_ui.uiconstants import URLS
from qt_ui.widgets.QTopPanel import QTopPanel
from qt_ui.widgets.map.QLiberationMap import QLiberationMap
from qt_ui.windows.preferences import QLiberationPreferences
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal, DebriefingSignal
from qt_ui.windows.QDebriefingWindow import QDebriefingWindow
from qt_ui.windows.QNewGameWizard import NewGameWizard
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
from qt_ui.windows.preferences.QLiberationPreferencesWindow import QLiberationPreferencesWindow
from userdata import persistency
@ -79,6 +80,10 @@ class QLiberationWindow(QMainWindow):
self.showAboutDialogAction.setIcon(QIcon.fromTheme("help-about"))
self.showAboutDialogAction.triggered.connect(self.showAboutDialog)
self.showLiberationPrefDialogAction = QAction("Preferences", self)
self.showLiberationPrefDialogAction.setIcon(QIcon.fromTheme("help-about"))
self.showLiberationPrefDialogAction.triggered.connect(self.showLiberationDialog)
def initToolbar(self):
self.tool_bar = self.addToolBar("File")
self.tool_bar.addAction(self.newGameAction)
@ -92,17 +97,21 @@ class QLiberationWindow(QMainWindow):
file_menu.addAction(self.newGameAction)
#file_menu.addAction(QIcon(CONST.ICONS["Open"]), "Open") # TODO : implement
file_menu.addAction(self.saveGameAction)
file_menu.addSeparator()
file_menu.addAction(self.showLiberationPrefDialogAction)
file_menu.addSeparator()
#file_menu.addAction("Save As") # TODO : implement
#file_menu.addAction("Close Current Game", lambda: self.closeGame()) # Not working
file_menu.addAction("Exit" , lambda: self.exit())
help_menu = self.menu.addMenu("Help")
#help_menu.addAction("Online Manual", lambda: webbrowser.open_new_tab(URLS["Manual"]))
help_menu.addAction("Online Manual", lambda: webbrowser.open_new_tab(URLS["Manual"]))
help_menu.addAction("Discord", lambda: webbrowser.open_new_tab("https://" + "discord.gg" + "/" + "bKrt" + "rkJ"))
#help_menu.addAction("Troubleshooting Guide", lambda: webbrowser.open_new_tab(URLS["Troubleshooting"]))
#help_menu.addAction("Modding Guide", lambda: webbrowser.open_new_tab(URLS["Modding"]))
#help_menu.addSeparator() ----> Note from Khopa : I disable these links since it's not up to date for this branch
help_menu.addAction("Contribute", lambda: webbrowser.open_new_tab(URLS["Repository"]))
#help_menu.addAction("Contribute", lambda: webbrowser.open_new_tab(URLS["Repository"]))
help_menu.addAction("Forum Thread", lambda: webbrowser.open_new_tab(URLS["ForumThread"]))
help_menu.addAction("Report an issue", lambda: webbrowser.open_new_tab(URLS["Issues"]))
help_menu.addSeparator()
@ -192,6 +201,10 @@ class QLiberationWindow(QMainWindow):
print(about.textFormat())
about.exec_()
def showLiberationDialog(self):
self.subwindow = QLiberationPreferencesWindow()
self.subwindow.show()
def onDebriefing(self, debrief: DebriefingSignal):
print("On Debriefing")
self.debriefing = QDebriefingWindow(debrief.debriefing, debrief.gameEvent, debrief.game)

View File

@ -0,0 +1,80 @@
from PySide2.QtGui import QIcon, Qt
from PySide2.QtWidgets import QDialog, QVBoxLayout, QPushButton, QHBoxLayout, QPlainTextEdit, QTextEdit
from qt_ui.windows.preferences.QLiberationPreferences import QLiberationPreferences
class QLiberationFirstStartWindow(QDialog):
def __init__(self):
super(QLiberationFirstStartWindow, self).__init__()
self.setModal(True)
self.setWindowTitle("First start configuration")
self.setMinimumSize(500, 200)
self.setWindowIcon(QIcon("./resources/icon.png"))
self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.Dialog | Qt.WindowTitleHint)
self.setWindowModality(Qt.WindowModal)
self.preferences = QLiberationPreferences()
WARN_TEXT = """
<strong>Welcome to DCS Liberation !</strong>
<br/><br>
<strong>Please take 30 seconds to read this :</strong>
<p>DCS Liberation will modify this file in your DCS installation directory :</p>
<br/>
<strong>&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua</strong><br/>
<p>
This will disable some security limits of the DCS World Lua scripting environment, in order to allow communication between DCS World and DCS Liberation.
However, the modification of this file could potentially grant access to your filesystem to malicious DCS mission files.
</p>
<p>So, you should not join untrusted servers or open untrusted mission files within DCS world while DCS Liberation is running.</p>
<p>
DCS Liberation will restore your original MissionScripting file when it close.
</p>
<p>
However, should DCS Liberation encounter an unexpected crash (which should not happen), the MissionScripting file might not be restored.
If that occurs, you can use the backup file saved in the DCS Liberation directory there :
</p>
<br/>
<strong>./resources/scripts/MissionScripting.original.lua</strong><br/>
<p>Then copy it in your DCS installation directory to replace this file :</p>
<br/>
<strong>&lt;dcs_installation_directory&gt;/Scripts/MissionScripting.lua</strong><br/>
<p>As you click on the button below, the file will be replaced in your DCS installation directory.</p>
<br/><br/>
<strong>Thank you for reading !</strong>
"""
self.warning_text = QTextEdit(WARN_TEXT)
self.warning_text.setReadOnly(True)
self.apply_button = QPushButton("I have read everything and I Accept")
self.apply_button.clicked.connect(lambda : self.apply())
self.initUI()
def initUI(self):
layout = QVBoxLayout()
layout.addWidget(self.preferences)
layout.addWidget(self.warning_text)
layout.addStretch()
apply_btn_layout = QHBoxLayout()
apply_btn_layout.addStretch()
apply_btn_layout.addWidget(self.apply_button)
layout.addLayout(apply_btn_layout)
self.setLayout(layout)
def apply(self):
print("Applying changes")
if self.preferences.apply():
self.close()

View File

@ -0,0 +1,93 @@
import os
from PySide2 import QtWidgets
from PySide2.QtGui import Qt
from PySide2.QtWidgets import QFrame, QLineEdit, QGridLayout, QVBoxLayout, QLabel, QPushButton, \
QFileDialog, QMessageBox, QDialog
from userdata import liberation_install
class QLiberationPreferences(QFrame):
def __init__(self):
super(QLiberationPreferences, self).__init__()
self.saved_game_dir = ""
self.dcs_install_dir = ""
self.dcs_install_dir = liberation_install.get_dcs_install_directory()
self.saved_game_dir = liberation_install.get_saved_game_dir()
self.edit_dcs_install_dir = QLineEdit(self.dcs_install_dir)
self.edit_saved_game_dir = QLineEdit(self.saved_game_dir)
self.edit_dcs_install_dir.setMinimumWidth(300)
self.edit_saved_game_dir.setMinimumWidth(300)
self.browse_saved_game = QPushButton("Browse...")
self.browse_saved_game.clicked.connect(self.on_browse_saved_games)
self.browse_install_dir = QPushButton("Browse...")
self.browse_install_dir.clicked.connect(self.on_browse_installation_dir)
self.initUi()
def initUi(self):
main_layout = QVBoxLayout()
layout = QGridLayout()
layout.addWidget(QLabel("<strong>DCS saved game directory:</strong>"), 0, 0, alignment=Qt.AlignLeft)
layout.addWidget(self.edit_saved_game_dir, 1, 0, alignment=Qt.AlignRight)
layout.addWidget(self.browse_saved_game, 1, 1, alignment=Qt.AlignRight)
layout.addWidget(QLabel("<strong>DCS installation directory:</strong>"), 2, 0, alignment=Qt.AlignLeft)
layout.addWidget(self.edit_dcs_install_dir, 3, 0, alignment=Qt.AlignRight)
layout.addWidget(self.browse_install_dir, 3, 1, alignment=Qt.AlignRight)
main_layout.addLayout(layout)
main_layout.addStretch()
self.setLayout(main_layout)
def on_browse_saved_games(self):
saved_game_dir = str(QFileDialog.getExistingDirectory(self, "Select DCS Saved Game Directory"))
if saved_game_dir:
self.saved_game_dir = saved_game_dir
self.edit_saved_game_dir.setText(saved_game_dir)
def on_browse_installation_dir(self):
install_dir = str(QFileDialog.getExistingDirectory(self, "Select DCS Installation Directory"))
if install_dir:
self.dcs_install_dir = install_dir
self.edit_dcs_install_dir.setText(install_dir)
def apply(self):
print("Applying changes")
self.saved_game_dir = self.edit_saved_game_dir.text()
self.dcs_install_dir = self.edit_dcs_install_dir.text()
if not os.path.isdir(self.saved_game_dir):
error_dialog = QMessageBox.critical(self, "Wrong DCS Saved Games directory.",
self.saved_game_dir + " is not a valid directory",
QMessageBox.StandardButton.Ok)
error_dialog.exec_()
return False
if not os.path.isdir(self.dcs_install_dir):
error_dialog = QMessageBox.critical(self, "Wrong DCS installation directory.",
self.dcs_install_dir + " is not a valid directory",
QMessageBox.StandardButton.Ok)
error_dialog.exec_()
return False
if not os.path.isdir(os.path.join(self.dcs_install_dir, "Scripts")) and os.path.isfile(os.path.join(self.dcs_install_dir, "bin", "DCS.exe")):
error_dialog = QMessageBox.critical(self, "Wrong DCS installation directory.",
self.dcs_install_dir + " is not a valid DCS installation directory",
QMessageBox.StandardButton.Ok)
error_dialog.exec_()
return False
liberation_install.setup(self.saved_game_dir, self.dcs_install_dir)
liberation_install.save_config()
return True

View File

@ -0,0 +1,37 @@
from PySide2.QtGui import QIcon, Qt
from PySide2.QtWidgets import QDialog, QVBoxLayout, QPushButton, QHBoxLayout
from qt_ui.windows.preferences.QLiberationPreferences import QLiberationPreferences
class QLiberationPreferencesWindow(QDialog):
def __init__(self):
super(QLiberationPreferencesWindow, self).__init__()
self.setModal(True)
self.setWindowTitle("Preferences")
self.setMinimumSize(300, 200)
self.setWindowIcon(QIcon("./resources/icon.png"))
self.preferences = QLiberationPreferences()
self.apply_button = QPushButton("Apply")
self.apply_button.clicked.connect(lambda : self.apply())
self.initUI()
def initUI(self):
layout = QVBoxLayout()
layout.addWidget(self.preferences)
layout.addStretch()
apply_btn_layout = QHBoxLayout()
apply_btn_layout.addStretch()
apply_btn_layout.addWidget(self.apply_button)
layout.addLayout(apply_btn_layout)
self.setLayout(layout)
def apply(self):
if self.preferences.apply():
print("Closing")
self.close()
else:
print("Not Closing")

View File

@ -98,11 +98,11 @@ class QSettingsWindow(QDialog):
self.enemyAASkill.currentIndexChanged.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0)
self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1)
self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1, Qt.AlignRight)
self.difficultyLayout.addWidget(QLabel("Enemy skill"), 1, 0)
self.difficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1)
self.difficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1, Qt.AlignRight)
self.difficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0)
self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1)
self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight)
self.difficultyLabel = QComboBox()
[self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS]
@ -110,13 +110,13 @@ class QSettingsWindow(QDialog):
self.difficultyLabel.currentIndexChanged.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("In Game Labels"), 3, 0)
self.difficultyLayout.addWidget(self.difficultyLabel, 3, 1)
self.difficultyLayout.addWidget(self.difficultyLabel, 3, 1, Qt.AlignRight)
self.noNightMission = QCheckBox()
self.noNightMission.setChecked(self.game.settings.night_disabled)
self.noNightMission.toggled.connect(self.applySettings)
self.difficultyLayout.addWidget(QLabel("No night missions"), 4, 0)
self.difficultyLayout.addWidget(self.noNightMission, 4, 1)
self.difficultyLayout.addWidget(self.noNightMission, 4, 1, Qt.AlignRight)
def initGeneratorLayout(self):
@ -135,7 +135,7 @@ class QSettingsWindow(QDialog):
self.supercarrier.toggled.connect(self.applySettings)
self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
self.gameplayLayout.addWidget(self.supercarrier, 0, 1)
self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
self.performance = QGroupBox("Performance")
self.performanceLayout = QGridLayout();
@ -162,16 +162,22 @@ class QSettingsWindow(QDialog):
self.infantry.setChecked(self.game.settings.perf_infantry)
self.infantry.toggled.connect(self.applySettings)
self.ai_parking_start = QCheckBox()
self.ai_parking_start.setChecked(self.game.settings.perf_ai_parking_start)
self.ai_parking_start.toggled.connect(self.applySettings)
self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
self.performanceLayout.addWidget(self.smoke, 0, 1)
self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
self.performanceLayout.addWidget(self.red_alert, 1, 1)
self.performanceLayout.addWidget(self.red_alert, 1, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("Artillery strikes"), 2, 0)
self.performanceLayout.addWidget(self.arti, 2, 1)
self.performanceLayout.addWidget(self.arti, 2, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("Moving ground units"), 3, 0)
self.performanceLayout.addWidget(self.moving_units, 3, 1)
self.performanceLayout.addWidget(self.moving_units, 3, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("Generate infantry squads along vehicles"), 4, 0)
self.performanceLayout.addWidget(self.infantry, 4, 1)
self.performanceLayout.addWidget(self.infantry, 4, 1, alignment=Qt.AlignRight)
self.performanceLayout.addWidget(QLabel("AI planes parking start (AI starts in flight if disabled)"), 5, 0)
self.performanceLayout.addWidget(self.ai_parking_start, 5, 1, alignment=Qt.AlignRight)
self.generatorLayout.addWidget(self.gameplay)
self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
@ -230,6 +236,7 @@ class QSettingsWindow(QDialog):
self.game.settings.perf_artillery = self.arti.isChecked()
self.game.settings.perf_moving_units = self.moving_units.isChecked()
self.game.settings.perf_infantry = self.infantry.isChecked()
self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked()
GameUpdateSignal.get_instance().updateGame(self.game)

View File

@ -1,132 +0,0 @@
"""
This utility classes provides methods to check players installed DCS environment.
TODO : add method 'is_using_open_beta', 'is_using_stable'
TODO : [NICE to have] add method to check list of installed DCS modules (could be done either through window registry, or through filesystem analysis)
"""
import winreg
import os
def is_using_dcs_steam_edition():
"""
Check if DCS World : Steam Edition version is installed on this computer
:return True if DCS Steam edition is installed,
-1 if DCS Steam Edition is registered in Steam apps but not installed,
False if never installed in Steam
"""
try:
# Note : Steam App ID for DCS World is 223750
dcs_steam_app_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam\\Apps\\223750")
installed = winreg.QueryValueEx(dcs_steam_app_key, "Installed")
winreg.CloseKey(dcs_steam_app_key)
if installed[0] == 1:
return True
else:
return False
except FileNotFoundError as fnfe:
return False
def is_using_dcs_standalone_edition():
"""
Check if DCS World standalone edition is installed on this computer
:return True if Standalone is installed, False if it is not
"""
try:
dcs_path_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Eagle Dynamics\\DCS World")
winreg.CloseKey(dcs_path_key)
return True
except FileNotFoundError as fnfe:
return False
def _find_steam_directory():
"""
Get the Steam install directory for this computer from registry
:return Steam installation path
"""
try:
steam_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Valve\\Steam")
path = winreg.QueryValueEx(steam_key, "SteamPath")[0]
winreg.CloseKey(steam_key)
return path
except FileNotFoundError as fnfe:
print(fnfe)
return ""
def _get_steam_library_folders():
"""
Get the installation directory for Steam games
:return List of Steam library folders where games can be installed
"""
try:
steam_dir = _find_steam_directory()
"""
For reference here is what the vdf file is supposed to look like :
"LibraryFolders"
{
"TimeNextStatsReport" "1561832478"
"ContentStatsID" "-158337411110787451"
"1" "D:\\Games\\Steam"
"2" "E:\\Steam"
}
"""
vdf_file_location = steam_dir + os.path.sep + "steamapps" + os.path.sep + "libraryfolders.vdf"
with open(vdf_file_location) as adf_file:
paths = [l.split("\"")[3] for l in adf_file.readlines()[1:] if ':\\\\' in l]
return paths
except Exception as e:
print(e)
return []
def _find_steam_dcs_directory():
"""
Find the DCS install directory for DCS World Steam Edition
:return: Install directory as string, empty string if not found
"""
for library_folder in _get_steam_library_folders():
folder = library_folder + os.path.sep + "steamapps" + os.path.sep + "common" + os.path.sep + "DCSWorld"
if os.path.isdir(folder):
return folder + os.path.sep
return ""
def get_dcs_install_directory():
"""
Get the DCS World install directory for this computer
:return DCS World install directory
"""
if is_using_dcs_standalone_edition():
try:
dcs_path_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Eagle Dynamics\\DCS World")
path = winreg.QueryValueEx(dcs_path_key, "Path")
dcs_dir = path[0] + os.path.sep
winreg.CloseKey(dcs_path_key)
return dcs_dir
except Exception as e:
print("Couldn't detect DCS World installation folder")
return ""
elif is_using_dcs_steam_edition():
return _find_steam_dcs_directory()
else:
print("Couldn't detect any installed DCS World version")
def get_dcs_saved_games_directory():
"""
Get the save game directory for DCS World
:return: Save game directory as string
"""
return os.path.join(os.path.expanduser("~"), "Saved Games", "DCS")
if __name__ == "__main__":
print("Using STEAM Edition : " + str(is_using_dcs_steam_edition()))
print("Using Standalone Edition : " + str(is_using_dcs_standalone_edition()))
print("DCS Installation directory : " + get_dcs_install_directory())
print("DCS saved games directory : " + get_dcs_saved_games_directory())

View File

@ -0,0 +1,99 @@
import json
import os
from shutil import copyfile
import dcs
from userdata import persistency
global __dcs_saved_game_directory
global __dcs_installation_directory
PREFERENCES_FILE_PATH = "liberation_preferences.json"
def init():
global __dcs_saved_game_directory
global __dcs_installation_directory
if os.path.isfile(PREFERENCES_FILE_PATH):
try:
with(open(PREFERENCES_FILE_PATH)) as prefs:
pref_data = json.loads(prefs.read())
__dcs_saved_game_directory = pref_data["saved_game_dir"]
__dcs_installation_directory = pref_data["dcs_install_dir"]
is_first_start = False
except:
__dcs_saved_game_directory = ""
__dcs_installation_directory = ""
is_first_start = True
else:
try:
__dcs_saved_game_directory = dcs.installation.get_dcs_saved_games_directory()
if os.path.exists(__dcs_saved_game_directory + ".openbeta"):
__dcs_saved_game_directory = dcs.installation.get_dcs_saved_games_directory() + ".openbeta"
except:
__dcs_saved_game_directory = ""
try:
__dcs_installation_directory = dcs.installation.get_dcs_install_directory()
except:
__dcs_installation_directory = ""
is_first_start = True
persistency.setup(__dcs_saved_game_directory)
return is_first_start
def setup(saved_game_dir, install_dir):
global __dcs_saved_game_directory
global __dcs_installation_directory
__dcs_saved_game_directory = saved_game_dir
__dcs_installation_directory = install_dir
persistency.setup(__dcs_saved_game_directory)
def save_config():
global __dcs_saved_game_directory
global __dcs_installation_directory
pref_data = {"saved_game_dir": __dcs_saved_game_directory,
"dcs_install_dir": __dcs_installation_directory}
with(open(PREFERENCES_FILE_PATH, "w")) as prefs:
prefs.write(json.dumps(pref_data))
def get_dcs_install_directory():
global __dcs_installation_directory
return __dcs_installation_directory
def get_saved_game_dir():
global __dcs_saved_game_directory
return __dcs_saved_game_directory
def replace_mission_scripting_file():
install_dir = get_dcs_install_directory()
mission_scripting_path = os.path.join(install_dir, "Scripts", "MissionScripting.lua")
liberation_scripting_path = "./resources/scripts/MissionScripting.lua"
backup_scripting_path = "./resources/scripts/MissionScripting.original.lua"
if os.path.isfile(mission_scripting_path):
with open(mission_scripting_path, "r") as ms:
current_file_content = ms.read()
with open(liberation_scripting_path, "r") as libe_ms:
liberation_file_content = libe_ms.read()
# Save original file
if current_file_content != liberation_file_content:
copyfile(mission_scripting_path, backup_scripting_path)
# Replace DCS file
copyfile(liberation_scripting_path, mission_scripting_path)
def restore_original_mission_scripting():
install_dir = get_dcs_install_directory()
mission_scripting_path = os.path.join(install_dir, "Scripts", "MissionScripting.lua")
backup_scripting_path = "./resources/scripts/MissionScripting.original.lua"
if os.path.isfile(backup_scripting_path) and os.path.isfile(mission_scripting_path):
copyfile(backup_scripting_path, mission_scripting_path)

View File

@ -2,9 +2,6 @@ import logging
import os
import pickle
import shutil
import sys
from dcs import installation
_dcs_saved_game_folder = None # type: str
@ -17,12 +14,7 @@ def setup(user_folder: str):
def base_path() -> str:
global _dcs_saved_game_folder
assert _dcs_saved_game_folder
openbeta_path = _dcs_saved_game_folder + ".openbeta"
if os.path.exists(openbeta_path):
return openbeta_path # For standalone openbeta users
else:
return _dcs_saved_game_folder # For standalone stable users & steam users (any branch)
return _dcs_saved_game_folder
def _save_file() -> str: