Beispiel #1
0
	def trySetSecondaryLoggingPath(self, newLogFilePath):
		# type: (str) -> None
		"""
		Specify the secondary path for the log file.
		The current log file will be copied to the newLogFilePath.
		Any additional writes will go to both the existing log file and the new one.
		:param newLogFilePath: the path where the new log file will be created (and updated)
		:return: None
		"""
		# If new log file path is the same as current one, don't do anything
		if self.secondaryLogFilePath is not None:
			if os.path.normpath(self.secondaryLogFilePath) == os.path.normpath(newLogFilePath):
				return

		try:
			common.makeDirsExistOK(os.path.dirname(newLogFilePath))
			shutil.copy(self.logPath, newLogFilePath)

			if self.secondaryLogFile is not None:
				fileToClose = self.secondaryLogFile
				self.secondaryLogFile = None
				fileToClose.close()
				print("Closed log file at: [{}]".format(newLogFilePath))

			self.secondaryLogFile = io.open(newLogFilePath, "a", encoding='UTF-8')
			self.secondaryLogFilePath = newLogFilePath
			print("Successfully created secondary log file at: [{}]".format(newLogFilePath))
		except Exception as e:
			print("Couldn't create secondary log at: [{}] Error: {}".format(newLogFilePath, e))
Beispiel #2
0
	def __init__(self, logPath):
		self.logPath = logPath
		self.terminal = sys.stdout
		common.makeDirsExistOK(os.path.dirname(logPath))
		self.logFile = io.open(logPath, "a", encoding='UTF-8')
		self.secondaryLogFile = None
		self.secondaryLogFilePath = None
		self.callbacks = {}
		self.queue = queue.Queue(maxsize=100000)
Beispiel #3
0
def mainUmineko(conf):
    # type: (installConfiguration.FullInstallConfiguration) -> None
    logger.getGlobalLogger().trySetSecondaryLoggingPath(
        os.path.join(conf.installPath, common.Globals.LOG_BASENAME))

    isQuestionArcs = 'question' in conf.subModConfig.modName.lower()

    print("CONFIGURATION:")
    print("Install path", conf.installPath)
    print("Mod Option", conf.subModConfig.modName)
    print("Sub Option", conf.subModConfig.subModName)
    print("Is Question Arcs", isQuestionArcs)
    print("Is Windows", common.Globals.IS_WINDOWS)
    print("Is Linux", common.Globals.IS_LINUX)
    print("Is Mac", common.Globals.IS_MAC)

    ####################################### VALIDATE AND PREPARE FOLDERS ###############################################
    # do a quick verification that the directory is correct before starting installer
    if not os.path.isfile(os.path.join(conf.installPath, "arc.nsa")):
        raise Exception(
            "ERROR - wrong game path. Installation Stopped.\n"
            "There is no 'arc.nsa' in the game folder. Are you sure the correct game folder was selected?"
        )

    for filename in os.listdir(conf.installPath):
        # Stop the user installing the mod on pirated versions of the game.
        # Use SHA256 hash of the lowercase filename to avoid listing the website names in our source code.
        if hashlib.sha256(filename.lower().encode('utf-8')).hexdigest() in [
                '2c02ec6f6de9281a68975257a477e8f994affe4eeaaf18b0b56b4047885461e0',
                '4fae41c555fe50034065e59ce33a643c1d93ee846221ecc5756f00e039035076',
        ]:
            raise Exception(
                "\nInstall Failed - The {} mod is not compatible with the pirated version of the game\n"
                "(Detected file [{}]) Please install the latest Steam or Mangagamer release."
                .format(conf.subModConfig.modName, filename))

        # Stop the user installing the mod on the old/original Japanese game.
        # This probably means the user placed a fake identifier (eg the game exe) in the old game's folder.
        if filename == 'snow.dll':
            raise Exception(
                "\nInstall Failed - The {} mod is not compatible with the old/original Japanese game.\n"
                "(Detected [{}]) Please install the latest Steam or Mangagamer release."
                .format(conf.subModConfig.modName, filename))

    # Create aliases for the temp directories, and ensure they exist beforehand
    downloadTempDir = conf.subModConfig.modName + " Downloads"

    if os.path.isdir(downloadTempDir):
        print(
            "Information: Temp directories already exist - continued or overwritten install"
        )

    common.makeDirsExistOK(downloadTempDir)

    ######################################## Query and Download Files ##################################################
    fileVersionManager = fileVersionManagement.VersionManager(
        subMod=conf.subModConfig,
        modFileList=conf.buildFileListSorted(),
        localVersionFolder=conf.installPath)

    filesRequiringUpdate = fileVersionManager.getFilesRequiringUpdate()
    print("Perform Full Install: {}".format(
        fileVersionManager.fullUpdateRequired()))
    downloaderAndExtractor = common.DownloaderAndExtractor(
        filesRequiringUpdate,
        downloadTempDir,
        conf.installPath,
        downloadProgressAmount=45,
        extractionProgressAmount=45)
    downloaderAndExtractor.buildDownloadAndExtractionList()

    parser = installConfiguration.ModOptionParser(conf)

    for opt in parser.downloadAndExtractOptionsByPriority:
        downloaderAndExtractor.addItemManually(
            url=opt.url,
            extractionDir=os.path.join(conf.installPath,
                                       opt.relativeExtractionPath),
        )

    downloaderAndExtractor.printPreview()

    # Delete all non-checksummed files from the download folder, if they exist
    print("Removing non-checksummed downloads:")
    deleteExtractablesFromFolder(
        downloadTempDir,
        [x for x in downloaderAndExtractor.extractList if not x.fromMetaLink])

    downloaderAndExtractor.download()

    # Treat the install as "started" once the "download" stage is complete
    fileVersionManager.saveVersionInstallStarted()

    ###################### Backup/clear the .exe and script files, and old graphics ####################################
    backupOrRemoveFiles(conf.installPath)

    if fileVersionManager.fullUpdateRequired():
        # Remove old graphics from a previous installation, as they can conflict with the voice-only patch
        graphicsPathsToDelete = [
            os.path.join(conf.installPath, x) for x in ['big', 'bmp', 'en']
        ]

        for folderPath in graphicsPathsToDelete:
            if os.path.exists(folderPath):
                print("Deleting {}".format(folderPath))
                try:
                    shutil.rmtree(folderPath)
                except:
                    print("WARNING: failed to remove folder {}".format(
                        folderPath))

    ######################################## Extract Archives ##########################################################
    downloaderAndExtractor.extract()

    ############################################# FIX .ARC FILE NAMING #################################################
    # Steam release has arc files labeled arc.nsa, arc1.nsa, arc2.nsa, arc3.nsa.
    # Mangagamer release has only one arc file labeled arc.nsa
    # Generate dummy arc1-arc3 nsa files if they don't already exist, so the game can find the arc4.nsa that we provide
    for i in range(1, 4):
        nsaPath = os.path.join(conf.installPath, 'arc{}.nsa'.format(i))
        if not os.path.exists(nsaPath):
            print(
                ".nsa archive check: Generating dummy [{}] as it does not already exist (Mangagamer)"
                .format(nsaPath))
            with open(nsaPath, 'wb') as dummyNSAFile:
                dummyNSAFile.write(bytes([0, 0, 0, 0, 0, 6]))
        else:
            print(".nsa archive check: [{}] already exists (Steam)".format(
                nsaPath))

    #################################### MAKE EXECUTABLE, WRITE HELPER SCRIPTS #########################################
    gameBaseName = "Umineko5to8"
    if isQuestionArcs:
        gameBaseName = "Umineko1to4"

    if common.Globals.IS_MAC:
        print("Un-quarantining game executable")
        subprocess.call([
            "xattr", "-d", "com.apple.quarantine",
            os.path.join(conf.installPath, gameBaseName + ".app")
        ])

    print("Creating debug mode batch files")
    # write batch file to let users launch game in debug mode
    with open(os.path.join(conf.installPath, gameBaseName + "_DebugMode.bat"),
              'w') as f:
        f.writelines([gameBaseName + ".exe --debug\n", "pause"])

    #make the following files executable, if they exist
    makeExecutableList = [
        os.path.join(conf.installPath, "Umineko1to4"),
        os.path.join(conf.installPath,
                     "Umineko1to4.app/Contents/MacOS/umineko4"),
        os.path.join(conf.installPath, "Umineko5to8"),
        os.path.join(conf.installPath,
                     "Umineko5to8.app/Contents/MacOS/umineko8")
    ]

    print("Making executables ... executable")
    for exePath in makeExecutableList:
        if os.path.exists(exePath):
            common.makeExecutable(exePath)

    # Patched game uses mysav folder, which Steam can't see so can't get incompatible saves by accident.
    # Add batch file which reverses this behaviour by making a linked folder from (saves->mysav)
    print("Creating EnableSteamSync.bat")
    with open(os.path.join(conf.installPath, "EnableSteamSync.bat"), 'w') as f:
        f.write("""
if exist saves (
    ren saves backup-saves
    mklink /J saves mysav
) else (
    mklink /J saves mysav
)
pause
""")

    # For now, don't copy save data

    steamGridExtractor.extractSteamGrid()
    fileVersionManager.saveVersionInstallFinished()

    if not parser.keepDownloads:
        print("Removing temporary downloads:")
        deleteExtractablesFromFolder(downloadTempDir,
                                     downloaderAndExtractor.extractList)

    commandLineParser.printSeventhModStatusUpdate(
        100, "Umineko install script completed!")
Beispiel #4
0
def main(conf):
    # type: (installConfiguration.FullInstallConfiguration) -> None
    logger.getGlobalLogger().trySetSecondaryLoggingPath(
        os.path.join(conf.installPath, common.Globals.LOG_BASENAME))

    print("CONFIGURATION:")
    print("Install path", conf.installPath)
    print("Mod Option", conf.subModConfig.modName)
    print("Sub Option", conf.subModConfig.subModName)
    print("Is Windows", common.Globals.IS_WINDOWS)
    print("Is Linux", common.Globals.IS_LINUX)
    print("Is Mac", common.Globals.IS_MAC)

    if not common.Globals.IS_WINDOWS:
        raise Exception(
            "Error: Umineko Hane Mod (onscripter version) is not supported on Mac or Linux!"
        )

    ####################################### VALIDATE AND PREPARE FOLDERS ###############################################
    # do a quick verification that the directory is correct before starting installer
    if not os.path.isfile(os.path.join(conf.installPath, "arc.nsa")):
        raise Exception(
            "ERROR - wrong game path. Installation Stopped.\n"
            "There is no 'arc.nsa' in the game folder. Are you sure the correct game folder was selected?"
        )

    # Create aliases for the temp directories, and ensure they exist beforehand
    downloadTempDir = conf.subModConfig.modName + " Downloads"

    if os.path.isdir(downloadTempDir):
        print(
            "Information: Temp directories already exist - continued or overwritten install"
        )

    common.makeDirsExistOK(downloadTempDir)

    ######################################## DOWNLOAD, BACKUP, THEN EXTRACT ############################################
    fileVersionManager = fileVersionManagement.VersionManager(
        subMod=conf.subModConfig,
        modFileList=conf.buildFileListSorted(),
        localVersionFolder=conf.installPath)

    filesRequiringUpdate = fileVersionManager.getFilesRequiringUpdate()
    conf.subModConfig.printEnabledOptions()
    downloaderAndExtractor = common.DownloaderAndExtractor(
        filesRequiringUpdate,
        downloadTempDir,
        conf.installPath,
        downloadProgressAmount=45,
        extractionProgressAmount=45)
    downloaderAndExtractor.buildDownloadAndExtractionList()

    parser = installConfiguration.ModOptionParser(conf)

    for opt in parser.downloadAndExtractOptionsByPriority:
        downloaderAndExtractor.addItemManually(
            url=opt.url,
            extractionDir=os.path.join(conf.installPath,
                                       opt.relativeExtractionPath),
        )

    downloaderAndExtractor.printPreview()

    # Download files
    # Delete all non-checksummed files from the download folder, if they exist
    for extractableItem in downloaderAndExtractor.extractList:
        extractableItemPath = os.path.join(downloadTempDir,
                                           extractableItem.filename)
        if not extractableItem.fromMetaLink and os.path.exists(
                extractableItemPath):
            print("Removing existing non-checksummed download: [{}]".format(
                extractableItemPath))
            os.remove(extractableItemPath)

    downloaderAndExtractor.download()

    # Extract files
    fileVersionManager.saveVersionInstallStarted()
    downloaderAndExtractor.extract()

    fileVersionManager.saveVersionInstallFinished()
    commandLineParser.printSeventhModStatusUpdate(
        100, "Umineko Hane install script completed!")