Exemple #1
0
    def tail_file(self, remove_offset: bool = True) -> Iterable:
        log_file = get_server_path(self.config.server_log)
        offset_file = get_server_path(".log_offset")
        if remove_offset:
            self.delete_offset()

        return Pygtail(log_file, offset_file=offset_file)
Exemple #2
0
    def install(
        self,
        force: bool,
        beta: bool,
        old: bool,
        enable: bool,
        minecraft_version: str,
        *args,
        **kwargs,
    ) -> int:
        """ installs a specific version of Minecraft """

        latest, versions = self._get_minecraft_versions(beta, old)

        if minecraft_version is None:
            minecraft_version = latest
        elif minecraft_version not in versions:
            raise click.BadParameter(
                "could not find minecraft version",
                self.context,
                get_param_obj(self.context, "minecraft_version"),
            )

        self.logger.debug("minecraft version:")
        self.logger.debug(versions[minecraft_version])

        jar_dir = get_server_path("jars")
        jar_file = f"minecraft_server.{minecraft_version}.jar"
        jar_path = os.path.join(jar_dir, jar_file)
        if os.path.isdir(jar_dir):
            if os.path.isfile(jar_path):
                if force:
                    os.remove(jar_path)
                else:
                    raise click.BadParameter(
                        f"minecraft v{minecraft_version} already installed",
                        self.context,
                        get_param_obj(self.context, "minecraft_version"),
                    )
        else:
            os.makedirs(jar_dir)

        self.logger.info(f"downloading v{minecraft_version}...")
        version = get_json(versions[minecraft_version]["url"])
        download_file(
            version["downloads"]["server"]["url"],
            jar_path,
            sha1=version["downloads"]["server"]["sha1"],
        )

        self.logger.success(f"minecraft v{minecraft_version} installed")

        link_path = get_server_path(self.config.server_jar)
        if not os.path.isfile(link_path) or enable:
            return self.invoke(
                self.enable,
                minecraft_version=minecraft_version,
            )
        return STATUS_SUCCESS
    def _check_steam_for_update(self, app_id: str, branch: str):
        manifest_file = get_server_path(
            ["steamapps", f"appmanifest_{app_id}.acf"])

        if not os.path.isfile(manifest_file):
            self.logger.debug("No local manifet")
            return True

        manifest = None
        with open(manifest_file, "r") as f:
            manifest = acf.load(f)

        stdout = self.run_command(
            (f"{self.config.steamcmd_path} +app_info_update 1 "
             f"+app_info_print {app_id} +quit"),
            redirect_output=True,
        )
        index = stdout.find(f'"{app_id}"')
        app_info = acf.loads(stdout[index:])

        try:
            current_buildid = app_info[app_id]["depots"]["branches"][branch][
                "buildid"]
        except KeyError:
            self.logger.debug("Failed to parse remote manifest")
            return True

        self.logger.debug(f"current: {manifest['AppState']['buildid']}")
        self.logger.debug(f"latest: {current_buildid}")
        return manifest["AppState"]["buildid"] != current_buildid
Exemple #4
0
def get_logger() -> logging.getLoggerClass():
    logging.setLoggerClass(ClickLogger)
    logger = logging.getLogger("gs_manager")

    if not logger.hasHandlers():
        logger.setLevel(logging.DEBUG)
        log_dir = get_server_path("logs")
        if not os.path.isdir(log_dir):
            os.mkdir(log_dir)

        log_path = os.path.join(log_dir, "gs_manager.log")
        log_file = None

        try:
            log_file = open(log_path, "a")
        except PermissionError:
            log_file = open(os.devnull, "w")

        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        handler = logging.StreamHandler(log_file)
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.propagate = False
        logger.click_debug = click.get_current_context().params["debug"]
    return logger
Exemple #5
0
    def start(
        self,
        no_verify: bool,
        foreground: bool,
        accept_eula: bool,
        add_property: List[Dict[str, str]],
        remove_property: List[str],
        *args,
        **kwargs,
    ) -> int:
        """ starts Minecraft server """

        if add_property or remove_property:
            for prop in add_property:
                self.config.mc.update(prop)

            for prop in remove_property:
                del self.config.mc[prop]

            self.config.save_mc()

        if accept_eula:
            eula_path = get_server_path("eula.txt")
            with open(eula_path, "w") as f:
                f.write("eula=true")

        return self.invoke(
            super().start,
            no_verify=no_verify,
            foreground=foreground,
        )
Exemple #6
0
    def restore(self, list_backups: bool, num: int, backup_num: int, *args,
                **kwargs) -> int:
        """ edits a server file with your default editor """

        backup_folder = os.path.join(self.config.backup_location, "backups")
        restore_folder = os.path.join(self.config.backup_location, "restore")
        backups = []

        if os.path.isdir(backup_folder):
            for backup in os.listdir(backup_folder):
                if backup.startswith(self.backup_name):
                    backups.append(backup)
            backups = sorted(backups)

        if list_backups:
            if num >= 0:
                backups = backups[:num]

            for index, backup in enumerate(backups):
                self.logger.info(f"{index:2}: {backup}")
            return STATUS_SUCCESS

        if backup_num > len(backups):
            self.logger.error(f"Backup {backup_num} does not exist")
            return STATUS_FAILED

        if self.is_running():
            self.logger.error(f"{self.server_name} is still running")
            return STATUS_FAILED

        self.logger.info("Cleaning up previous restore...")
        for old_backup in os.listdir(self.config.backup_location):
            if old_backup.endswith(".tar.gz"):
                os.remove(os.path.join(self.config.backup_location,
                                       old_backup))

        if os.path.isdir(restore_folder):
            rmtree(restore_folder)
        os.mkdir(restore_folder)

        self.logger.info("Extacting backup...")
        backup_file = os.path.join(self.config.backup_location,
                                   backups[backup_num])
        copyfile(os.path.join(backup_folder, backups[backup_num]), backup_file)

        with tarfile.open(backup_file) as tar:
            tar.extractall(path=restore_folder)

        config_file = os.path.join(restore_folder, DEFAULT_CONFIG)
        if os.path.isfile(config_file):
            os.remove(config_file)

        self.logger.info("Restoring backup...")
        copy_tree(
            os.path.join(restore_folder, self.config.backup_directory),
            get_server_path(self.config.backup_directory),
            preserve_times=1,
        )
        return STATUS_SUCCESS
Exemple #7
0
    def save_starbound(self) -> None:
        config_path = get_server_path(["storage", "starbound_server.config"])

        with open(config_path, "w") as config_file:
            json.dump(self.starbound, config_file, indent=4, sort_keys=True)

        self._starbound_config = None
        self.starbound
    def _was_running_from_disk(self):
        was_running = False

        start_servers = get_server_path(".start_servers")
        if os.path.exists(start_servers):
            with open(start_servers, "r") as f:
                was_running = f.read().strip().split(",")
            os.remove(start_servers)

        return was_running
Exemple #9
0
    def save_mc(self) -> None:
        property_path = get_server_path("server.properties")
        server_property_string = ""
        for key, value in self.mc.items():
            server_property_string += f"{key}={value}\n"
        with open(property_path, "w") as f:
            f.write(server_property_string)

        self._mc_config = None
        self.mc
    def validate(value) -> str:
        # do not validate file paths inside of service dir if context is
        # not active yet
        try:
            click.get_current_context()
        except RuntimeError:
            return value

        if not os.path.isdir(get_server_path(value)):
            raise ValueError(f"{value} does not exist")

        return value
Exemple #11
0
    def backup(self, *args, **kwargs) -> int:
        """ edits a server file with your default editor """

        backup_folder = os.path.join(self.config.backup_location, "backups")
        timestamp = (datetime.now().isoformat(timespec="minutes").replace(
            ":", "-"))
        backup_file = f"{self.backup_name}_{timestamp}.tar.gz"

        os.makedirs(backup_folder, exist_ok=True)

        if self._command_exists("save_command"):
            self.logger.info(f"Saving servers...")
            current_instance = self.config.instance_name
            multi_instance = self.config.multi_instance
            self.set_instance(None, False)
            self.invoke(
                self.command,
                command_string=self.config.save_command,
                do_print=False,
                parallel=True,
                current_instance="@all",
            )
            self.set_instance(current_instance, multi_instance)

        self.logger.info(f"Making server backup ({backup_file})...")
        with tarfile.open(os.path.join(backup_folder, backup_file),
                          "w:gz") as tar:
            tar.add(
                get_server_path(self.config.backup_directory),
                arcname=self.config.backup_directory,
            )
            tar.add(self.config.config_path, arcname=DEFAULT_CONFIG)
            for path in self.config.backup_extra_paths:
                if os.path.exists(path):
                    tar.add(path, os.path.basename(path))
                else:
                    self.logger.warning(f"{path} does not exist")

        old_backups = []
        now = time.time()
        for backup in os.listdir(backup_folder):
            abs_path = os.path.join(backup_folder, backup)
            if os.stat(abs_path).st_mtime < now - 7 * 86400:
                old_backups.append(abs_path)

        if len(old_backups) > 0:
            self.logger.info(f"Deleting {len(old_backups)} old backups...")

            for backup in old_backups:
                os.remove(backup)

        return STATUS_SUCCESS
Exemple #12
0
    def enable(self, force: bool, minecraft_version: str, *args,
               **kwargs) -> int:
        """ enables a specific version of Minecraft """

        if self.is_running():
            self.logger.error(f"{self.server_name} is still running")
            return STATUS_FAILED

        jar_dir = get_server_path("jars")
        jar_file = f"minecraft_server.{minecraft_version}.jar"
        jar_path = os.path.join(jar_dir, jar_file)
        link_path = get_server_path(self.config.server_jar)

        if not os.path.isfile(jar_path):
            raise click.BadParameter(
                f"minecraft v{minecraft_version} is not installed",
                self.context,
                get_param_obj(self.context, "minecraft_version"),
            )

        if not (os.path.islink(link_path) or force
                or not os.path.isfile(link_path)):
            raise click.ClickException(
                f"{self.config.server_jar} is not a symbolic link, "
                "use -f to override")

        if os.path.isfile(link_path):
            if os.path.realpath(link_path) == jar_path:
                raise click.BadParameter(
                    f"minecraft v{minecraft_version} already enabled",
                    self.context,
                    get_param_obj(self.context, "minecraft_version"),
                )
            os.remove(link_path)

        self.run_command(f"ln -s {jar_path} {link_path}")

        self.logger.success(f"minecraft v{minecraft_version} enabled")
        return STATUS_SUCCESS
Exemple #13
0
    def versions(self, beta: bool, old: bool, installed: bool, num: int, *args,
                 **kwargs) -> int:
        """ lists versions of Minecraft """

        jar_dir = get_server_path("jars")
        installed_versions = []
        for root, dirs, files in os.walk(jar_dir):
            for filename in files:
                if filename.endswith(".jar"):
                    parts = filename.split(".")
                    installed_versions.append(".".join(parts[1:-1]))

        if installed:
            if num > 0:
                installed_versions = installed_versions[:num]

            for version in installed_versions:
                self.logger.info(f"{version} (installed)")
        else:
            latest, versions = self._get_minecraft_versions(beta, old)
            display_versions = []
            if old:
                display_versions = [
                    v["id"] for v in versions.values()
                    if v["type"].startswith("old_")
                ]
            elif beta:
                display_versions = [
                    v["id"] for v in versions.values()
                    if v["type"].startswith("snapshot")
                ]
            else:
                display_versions = versions.keys()

            if num > 0:
                display_versions = display_versions[:num]

            for version in display_versions:
                extra = ""
                if version == latest:
                    extra = "(latest)"

                if version in installed_versions:
                    if extra == "":
                        extra = "(installed)"
                    else:
                        extra = "(latest,installed)"
                self.logger.info(f"{version} {extra}")

        return STATUS_SUCCESS
Exemple #14
0
    def edit(self, force: bool, edit_path: str, *args, **kwargs) -> int:
        """ edits a server file with your default editor """

        if not force and self.is_running():
            self.logger.warning(f"{self.server_name} is still running")
            return STATUS_PARTIAL_FAIL

        file_path = get_server_path(edit_path)
        editor = os.environ.get("EDITOR") or "vim"

        self.run_command(
            f"{editor} {file_path}",
            redirect_output=False,
        )
        return STATUS_SUCCESS
    def _stop_servers(self, was_running, reason: Optional[str] = None):
        current_instance = self.config.instance_name
        multi_instance = self.config.multi_instance

        if reason is None:
            reason = "Updates found"

        if self._command_exists("say_command"):
            self.logger.info("notifying users...")
            self.set_instance(None, False)
            self.invoke(
                self.say,
                command_string=f"{reason}. Server restarting in 5 minutes",
                do_print=False,
                parallel=True,
                current_instances=f"@each:{','.join(was_running)}",
            )
            self._wait(300 - self.config.pre_stop)

        if self._command_exists("save_command"):
            self.logger.info("saving servers...")
            self.set_instance(None, False)
            self.invoke(
                self.command,
                command_string=self.config.save_command,
                do_print=False,
                parallel=True,
                current_instances=f"@each:{','.join(was_running)}",
            )

        self.set_instance(None, False)
        self.invoke(
            self.stop,
            force=False,
            reason="New updates found.",
            verb="restarting",
            parallel=True,
            current_instances=f"@each:{','.join(was_running)}",
        )

        self.set_instance(current_instance, multi_instance)

        with open(get_server_path(".start_servers"), "w") as f:
            if isinstance(was_running, bool):
                f.write("default")
            else:
                f.write(",".join(was_running))
Exemple #16
0
    def starbound(self) -> dict:
        if self._starbound_config is None:
            self._starbound_config = {}

            config_path = get_server_path(
                ["storage", "starbound_server.config"])
            if not os.path.isfile(config_path):
                self.logger.warn("could not find starbound_server.config for "
                                 "Starbound server")
                return {}

            with open(config_path) as config_file:
                self._starbound_config = json.load(config_file)

            self._update_config()

        return self._starbound_config
Exemple #17
0
    def mc(self) -> Dict[str, str]:
        if self._mc_config is None:
            self._mc_config = {}

            config_path = get_server_path("server.properties")
            if not os.path.isfile(config_path):
                raise click.ClickException(
                    "could not find server.properties for Minecraft server")

            lines = []
            with open(config_path) as config_file:
                for line in config_file:
                    if not line.startswith("#"):
                        lines.append(line)

            self._mc_config = KeyValuePairsType.validate(lines)

        return self._mc_config
    def start_command(self) -> str:
        if self._start_command is None:
            config_args = _make_command_args(self.ark_config)

            server_command = get_server_path(
                ["ShooterGame", "Binaries", "Linux", "ShooterGameServer"])

            command = ("{} {} -server -servergamelog -log "
                       "-servergamelogincludetribelogs").format(
                           server_command,
                           config_args,
                       )

            if "automanagedmods" in command:
                raise click.BadParameter(
                    "-automanagedmods option is not supported")
            self._start_command = command

        return self._start_command
    def install(
        self,
        allow_run: bool,
        force: bool,
        stop: bool,
        restart: bool,
        app_id: Optional[int] = None,
        *args,
        **kwargs,
    ) -> int:
        """ installs/validates/updates the ARK server """

        status = self.invoke(
            super().install,
            app_id=app_id,
            allow_run=allow_run,
            force=force,
            stop=stop,
            restart=restart,
        )

        self.logger.debug("super status: {}".format(status))

        if status == STATUS_SUCCESS:
            steamcmd_dir = get_server_path(
                ["Engine", "Binaries", "ThirdParty", "SteamCMD", "Linux"])
            steamcmd_path = os.path.join(steamcmd_dir, "steamcmd.sh")

            if not os.path.isdir(steamcmd_dir):
                os.makedirs(steamcmd_dir, exist_ok=True)

            if not os.path.isfile(steamcmd_path):
                self.logger.info("installing Steam locally for ARK...")
                old_path = os.getcwd()
                os.chdir(steamcmd_dir)
                filename = download_file(STEAM_DOWNLOAD_URL)
                self.run_command("tar -xf {}".format(filename))
                os.remove(os.path.join(steamcmd_dir, filename))
                self.run_command("{} +quit".format(steamcmd_path))
                os.chdir(old_path)
                self.logger.success("Steam installed successfully")

        return status
Exemple #20
0
    def start(
        self,
        no_verify: bool,
        foreground: bool,
        start_command: Optional[str] = None,
        *args,
        **kwargs,
    ) -> int:
        """ starts gameserver """

        if self.is_running():
            self.logger.warning(f"{self.server_name} is already running")
            return STATUS_PARTIAL_FAIL

        self._delete_pid_file()
        self.logger.info(f"starting {self.server_name}...", nl=False)

        command = start_command or self.config.start_command
        popen_kwargs = {}
        if self.config.spawn_process and not foreground:
            log_file_path = get_server_path(
                ["logs", f"{self.backup_name}.log"])

            command = f"nohup {command}"
            popen_kwargs = {
                "return_process": True,
                "redirect_output": False,
                "stdin": DEVNULL,
                "stderr": STDOUT,
                "stdout": PIPE,
                "start_new_session": True,
            }
        elif foreground:
            popen_kwargs = {
                "redirect_output": False,
            }

        try:
            response = self.run_command(
                command,
                cwd=get_server_path(self.config.start_directory),
                **popen_kwargs,
            )
        except CalledProcessError:
            self.logger.error("unexpected error from server")

        if foreground:
            return

        if self.config.spawn_process:
            self.run_command(
                f"cat > {log_file_path}",
                return_process=True,
                redirect_output=False,
                stdin=response.stdout,
                stderr=DEVNULL,
                stdout=DEVNULL,
            )

        if self.config.wait_start > 0:
            time.sleep(self.config.wait_start)

        self._find_pid()
        if no_verify:
            return STATUS_SUCCESS
        return self._startup_check()
    def workshop_download(
        self,
        allow_run: bool,
        force: bool,
        stop: bool,
        restart: bool,
        *args,
        **kwargs,
    ) -> int:
        """ downloads Steam workshop items """

        was_running = False
        if not force:
            needs_update = self._check_steam_for_update(
                str(self.config.workshop_id), "public")
            if not needs_update:
                self.logger.success(
                    f"{self.config.workshop_id} is already on latest version")
                self._start_servers(restart, was_running)
                return STATUS_SUCCESS

        if not allow_run:
            was_running = self.is_running(check_all=True)
            if was_running:
                if not (restart or stop):
                    self.logger.warning(
                        f"at least once instance of {self.config.app_id} "
                        "is still running")
                    return STATUS_PARTIAL_FAIL
                self._stop_servers(was_running,
                                   reason="Updates found for workshop app")

        status = self.invoke(
            self.install,
            app_id=self.config.workshop_id,
            allow_run=True,
            force=force,
        )

        if not status == STATUS_SUCCESS:
            return status

        if len(self.config.workshop_items) == 0:
            self.logger.warning("\nno workshop items selected for install")
            return STATUS_PARTIAL_FAIL

        mods_to_update = []
        manifest_file = get_server_path([
            "steamapps",
            "workshop",
            f"appworkshop_{self.config.workshop_id}.acf",
        ], )

        if not force and os.path.isfile(manifest_file):
            manifest = None
            with open(manifest_file, "r") as f:
                manifest = acf.load(f)

            self.logger.info("checking for updates for workshop items...")
            with click.progressbar(self.config.workshop_items) as bar:
                for workshop_item in bar:
                    workshop_item = str(workshop_item)
                    if (workshop_item not in manifest["AppWorkshop"]
                        ["WorkshopItemsInstalled"]):
                        mods_to_update.append(workshop_item)
                        continue

                    last_update_time = int(
                        manifest["AppWorkshop"]["WorkshopItemsInstalled"]
                        [workshop_item]["timeupdated"])

                    try:
                        latest_metadata = self._get_published_file(
                            workshop_item)
                    except requests.HTTPError:
                        self.logger.error(
                            "\ncould not query Steam for updates")
                        return STATUS_FAILED

                    newest_update_time = int(
                        latest_metadata["response"]["publishedfiledetails"][0]
                        ["time_updated"])

                    if last_update_time < newest_update_time:
                        mods_to_update.append(workshop_item)
        else:
            mods_to_update = self.config.workshop_items

        if len(mods_to_update) == 0:
            self.logger.success("all workshop items already up to date")
            self._start_servers(restart, was_running)
            return STATUS_SUCCESS

        self.logger.info("downloading workshop items...")
        with click.progressbar(mods_to_update) as bar:
            for workshop_item in bar:
                try:
                    self.run_command(
                        (f"{self.config.steamcmd_path} "
                         f"{self._steam_login()} +force_install_dir "
                         f"{self.config.server_path} "
                         "+workshop_download_item "
                         f"{self.config.workshop_id} {workshop_item} +quit"))
                except CalledProcessError:
                    self.logger.error("\nfailed to validate workshop items")
                    return STATUS_FAILED

        self.logger.success("\nvalidated workshop items")
        self._start_servers(restart, was_running)
        return STATUS_SUCCESS
    def workshop_download(
        self,
        allow_run: bool,
        force: bool,
        stop: bool,
        restart: bool,
        *args,
        **kwargs,
    ) -> int:
        """ downloads and installs ARK mods """

        status = self.invoke(
            super().workshop_download,
            allow_run=True,
            force=force,
            stop=stop,
            restart=False,
        )

        self.logger.debug("super status: {}".format(status))

        if status == STATUS_SUCCESS:
            mod_path = get_server_path(["ShooterGame", "Content", "Mods"])
            base_src_dir = get_server_path([
                "steamapps",
                "workshop",
                "content",
                str(self.config.workshop_id),
            ])

            mods_to_update = []
            manifest_file = get_server_path([
                "steamapps",
                "workshop",
                f"appworkshop_{self.config.workshop_id}.acf",
            ])

            if not force and os.path.isfile(manifest_file):
                manifest = None
                with open(manifest_file, "r") as f:
                    manifest = acf.load(f)

                    for workshop_item in self.config.workshop_items:
                        workshop_item = str(workshop_item)
                        mod_dir = os.path.join(mod_path, str(workshop_item))
                        mod_file = os.path.join(mod_path,
                                                "{}.mod".format(workshop_item))

                        if not os.path.isfile(mod_file) or (
                                workshop_item not in manifest["AppWorkshop"]
                            ["WorkshopItemsInstalled"]):
                            mods_to_update.append(workshop_item)
                            continue

                        last_update_time = int(
                            manifest["AppWorkshop"]["WorkshopItemsInstalled"]
                            [workshop_item]["timeupdated"])
                        last_extract_time = os.path.getctime(mod_file)

                        if last_update_time > last_extract_time:
                            mods_to_update.append(workshop_item)
            else:
                mods_to_update = self.config.workshop_items

            mods_to_update = self.str_mods(mods_to_update)
            if len(mods_to_update) == 0:
                was_running = self.is_running("@any")
                # automatically check for any servers shutdown by install
                if not was_running:
                    self._start_servers(restart, was_running)
                return STATUS_SUCCESS

            self.logger.info(
                f"{len(mods_to_update)} mod(s) need to be extracted: "
                f"{','.join(mods_to_update)}")

            was_running = self.is_running("@any")
            if was_running:
                if not (restart or stop):
                    self.logger.warning(
                        (f"at least once instance of {self.config.app_id}"
                         " is still running"))
                    return STATUS_PARTIAL_FAIL
                self._stop_servers(
                    was_running,
                    reason=(f"Updates found for {len(mods_to_update)} "
                            f"mod(s): {','.join(mods_to_update)}"),
                )

            self.logger.info("extracting mods...")
            with click.progressbar(mods_to_update) as bar:
                for workshop_item in bar:
                    src_dir = os.path.join(base_src_dir, str(workshop_item))
                    branch_dir = os.path.join(
                        src_dir,
                        "{}NoEditor".format(self.config.workshop_branch),
                    )
                    mod_dir = os.path.join(mod_path, str(workshop_item))
                    mod_file = os.path.join(mod_path,
                                            "{}.mod".format(workshop_item))

                    if not os.path.isdir(src_dir):
                        self.logger.error(
                            "could not find workshop item: {}".format(
                                self.config.workshop_id))
                        return STATUS_FAILED
                    elif os.path.isdir(branch_dir):
                        src_dir = branch_dir

                    if os.path.isdir(mod_dir):
                        self.logger.debug(
                            "removing old mod_dir of {}...".format(
                                workshop_item))
                        shutil.rmtree(mod_dir)
                    if os.path.isfile(mod_file):
                        self.logger.debug(
                            "removing old mod_file of {}...".format(
                                workshop_item))
                        os.remove(mod_file)

                    self.logger.debug("copying {}...".format(workshop_item))
                    shutil.copytree(src_dir, mod_dir)

                    if not self._create_mod_file(mod_dir, mod_file,
                                                 workshop_item):
                        self.logger.error(
                            "could not create .mod file for {}".format(
                                workshop_item))
                        return STATUS_FAILED

                    if not self._extract_files(mod_dir):
                        return STATUS_FAILED
            self.logger.success("workshop items successfully installed")

        if status == STATUS_SUCCESS:
            self._start_servers(restart, was_running)
        return status
Exemple #23
0
 def _get_pid_file_path(self) -> str:
     return get_server_path(self._get_pid_filename())
Exemple #24
0
 def delete_offset(self):
     offset_file = get_server_path(".log_offset")
     if os.path.isfile(offset_file):
         os.remove(offset_file)