dev #1
@@ -1,3 +1,10 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/pygamecfg/__init__.py=utf-8
|
||||
encoding//src/pygamecfg/__main__.py=utf-8
|
||||
encoding//src/pygamecfg/common_ut.py=utf-8
|
||||
encoding//src/pygamecfg/core_gamecfg.py=utf-8
|
||||
encoding//src/pygamecfg/game_cod4.py=utf-8
|
||||
encoding//src/pygamecfg/game_ut2k4.py=utf-8
|
||||
encoding//src/pygamecfg/game_ut99.py=utf-8
|
||||
encoding//src/pygamecfg/tool_ini.py=utf-8
|
||||
encoding/<project>=UTF-8
|
||||
|
||||
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -341,7 +341,7 @@ pipeline {
|
||||
|'''.strip()
|
||||
|
|
||||
|import copier
|
||||
|copier.run_auto("./", "../_gitrepo",vcs_ref="HEAD",use_prereleases=True,defaults=True,cleanup_on_error=False)
|
||||
|copier.run_copy("./", "../_gitrepo",vcs_ref="HEAD",use_prereleases=True,defaults=True,cleanup_on_error=False)
|
||||
|
|
||||
|__EOWRAPPER__
|
||||
""".stripMargin())
|
||||
|
||||
40
README.md
40
README.md
@@ -8,46 +8,8 @@
|
||||
|
||||

|
||||
|
||||
# Python project template
|
||||
# pyGameCFG
|
||||
|
||||
A nice template to start blank python projets.
|
||||
|
||||
This template automate a lot of handy things and allow CI/CD automatic releases generation.
|
||||
|
||||
It is also collectings data to feed Jenkins build.
|
||||
|
||||
Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/{{repository}}/{{branch}}/latest/).
|
||||
|
||||
## Features
|
||||
|
||||
### Generic pipeline skeleton:
|
||||
- Prepare
|
||||
- GetCode
|
||||
- BuildPackage
|
||||
- Install
|
||||
- CheckCode
|
||||
- PlotMetrics
|
||||
- RunUnitTests
|
||||
- GenDOC
|
||||
- PostRelease
|
||||
|
||||
### CI/CD Environment
|
||||
- Jenkins
|
||||
- Gitea (with patch for dynamic Readme variables: https://chacha.ddns.net/gitea/chacha/GiteaMarkupVariable)
|
||||
- Docker
|
||||
- MkDocsWeb
|
||||
|
||||
### CI/CD Helper libs
|
||||
- VirtualEnv
|
||||
- Changelog generation based on commits
|
||||
- copier
|
||||
- pylint + pylint_json2html
|
||||
- mypy
|
||||
- unittest + xmlrunner + junitparser + junit2htmlreport
|
||||
- mkdocs
|
||||
|
||||
### Python project
|
||||
- Full .toml implementation
|
||||
- .whl automatic generation
|
||||
- dynamic versionning using git repository
|
||||
- embedded unit-test
|
||||
@@ -1,16 +1 @@
|
||||
# Usage
|
||||
|
||||
## Pulvinar dolor
|
||||
Donec dapibus est fermentum justo volutpat condimentum. Integer quis nunc neque. Donec dictum vehicula justo, in facilisis ex tincidunt in.
|
||||
Vivamus sollicitudin sem dui, id mollis orci facilisis ut. Proin sed pulvinar dolor. Donec volutpat commodo urna imperdiet pulvinar. Fusce eget aliquam risus.
|
||||
Vivamus viverra luctus ex, in finibus mi. Nullam elementum dapibus mollis. Ut suscipit volutpat ex, quis feugiat lacus consectetur eu.
|
||||
|
||||
## Condimentum faucibus
|
||||
Quisque auctor egestas sem, luctus suscipit ex maximus vitae. Duis facilisis augue et condimentum faucibus.
|
||||
Donec cursus, enim a sagittis egestas, lectus lorem eleifend libero, at tincidunt leo magna at libero.
|
||||
Nunc eros velit, suscipit luctus tempor vel, finibus et est. Curabitur efficitur pretium pulvinar.
|
||||
Donec urna lectus, vulputate quis turpis sed, placerat congue urna. Phasellus aliquet fermentum quam, non auctor elit porta nec. Morbi eu ligula at nisl ultricies condimentum vitae id ante.
|
||||
|
||||
## Aliquam lacinia
|
||||
In volutpat lorem ex, et fringilla nibh faucibus quis. Mauris et arcu elementum, auctor dui vitae, egestas arcu. Duis sit amet aliquam quam.
|
||||
Phasellus a odio turpis. Etiam tristique mi eu enim varius, eget facilisis est vestibulum. Aliquam lacinia nec purus sed luctus. Cras at laoreet erat.
|
||||
@@ -50,6 +50,7 @@ class doc_gen(helper_withresults_base):
|
||||
reference_path = doc_path / "reference"
|
||||
cls._reset_dir(reference_path)
|
||||
|
||||
# create one .md per python module
|
||||
for path in sorted((cls.project_rootdir_path / "src").rglob("*.py")):
|
||||
module_path = path.relative_to(cls.project_rootdir_path / "src").with_suffix("")
|
||||
doc_path = path.relative_to(cls.project_rootdir_path / "src").with_suffix(".md")
|
||||
@@ -57,14 +58,12 @@ class doc_gen(helper_withresults_base):
|
||||
|
||||
parts = list(module_path.parts)
|
||||
|
||||
if parts[-1] == "__init__":
|
||||
parts = parts[:-1]
|
||||
elif parts[-1] == "__main__":
|
||||
if parts[-1] in ("__init__", "__main__"):
|
||||
continue
|
||||
|
||||
cls._reset_dir(os.path.dirname(full_doc_path))
|
||||
cls._create_dir(full_doc_path.parent.resolve())
|
||||
with open(full_doc_path, "w+") as fd:
|
||||
identifier = "src." + ".".join(parts)
|
||||
identifier = ".".join(parts)
|
||||
print("::: " + identifier, file=fd)
|
||||
|
||||
cmdopts = [f"{sys.executable}", "-m", "mkdocs", "-v", "build", "--site-dir", str(site_path), "--clean"]
|
||||
@@ -93,6 +92,7 @@ class doc_gen(helper_withresults_base):
|
||||
with open(cls.project_rootdir_path / "mkdocs.yml", "w") as mkdocsCfgFile:
|
||||
mkdocsCfgFile.write(yaml.dump(mkdocsCfg, Dumper=Dumper, default_flow_style=False, sort_keys=False))
|
||||
|
||||
print(" !! start doc generation")
|
||||
res = cls.run_cmd(cmdopts)
|
||||
print(res.decode())
|
||||
print(" !! done")
|
||||
|
||||
@@ -11,6 +11,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
@@ -34,11 +35,17 @@ class helper_base(ABC):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _reset_dir(dirpath: Path):
|
||||
def _create_dir(dirpath: Path):
|
||||
dirpath = Path(dirpath)
|
||||
if not os.path.exists(dirpath):
|
||||
os.makedirs(dirpath)
|
||||
[f.unlink() for f in Path(dirpath).glob("*") if f.is_file()]
|
||||
|
||||
@staticmethod
|
||||
def _reset_dir(dirpath: Path):
|
||||
dirpath = Path(dirpath)
|
||||
if os.path.exists(dirpath):
|
||||
shutil.rmtree(dirpath)
|
||||
os.makedirs(dirpath)
|
||||
|
||||
@classmethod
|
||||
def reset_result_dir(cls):
|
||||
|
||||
@@ -63,7 +63,7 @@ class quality_check(helper_withresults_base):
|
||||
[
|
||||
"--load-plugins=pylint.extensions.mccabe",
|
||||
"--output-format=json,parseable",
|
||||
"--disable=invalid-name",
|
||||
"--disable=invalid-name,too-few-public-methods,too-many-arguments", # ignore
|
||||
"--ignore=_version.py",
|
||||
"--reports=y",
|
||||
"--score=yes",
|
||||
|
||||
41
mkdocs.yml
41
mkdocs.yml
@@ -1,19 +1,11 @@
|
||||
# pyChaChaDummyProject (c) by chacha
|
||||
#
|
||||
# pyChaChaDummyProject is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
docs_dir: docs
|
||||
site_name: 'pygamecfg'
|
||||
site_url: 'https://chacha.ddns.net/mkdocs-web/chacha/pygamecfg/latest/'
|
||||
site_description: 'A simple game config tool that provide bash API to read / write game config files (cod, ut ...)'
|
||||
site_author: 'chacha'
|
||||
repo_url: 'https://chacha.ddns.net/gitea/chacha/pygamecfg'
|
||||
site_name: pygamecfg
|
||||
site_url: https://chacha.ddns.net/mkdocs-web/chacha/pygamecfg/latest/
|
||||
site_description: A simple ini parser / factory
|
||||
site_author: chacha
|
||||
repo_url: https://chacha.ddns.net/gitea/chacha/pygamecfg
|
||||
use_directory_urls: false
|
||||
copyright: 'CC BY-NC-SA 4.0'
|
||||
copyright: CC BY-NC-SA 4.0
|
||||
theme:
|
||||
name: material
|
||||
features:
|
||||
@@ -22,11 +14,11 @@ theme:
|
||||
- navigation.tabs
|
||||
- navigation.tabs.sticky
|
||||
- navigation.footer
|
||||
- toc.integrate
|
||||
- navigation.path
|
||||
- navigation.top
|
||||
- navigation.section
|
||||
- content.code.annotate
|
||||
- navigation.prune
|
||||
- navigation.expand
|
||||
- toc.follow
|
||||
palette:
|
||||
- media: '(prefers-color-scheme: dark)'
|
||||
@@ -52,19 +44,30 @@ plugins:
|
||||
default_handler: python
|
||||
handlers:
|
||||
python:
|
||||
path:
|
||||
- src
|
||||
options:
|
||||
filters:
|
||||
- '!^_[^_]'
|
||||
inherited_members: true
|
||||
inherited_members: false
|
||||
show_if_no_docstring: true
|
||||
show_signature_annotations: true
|
||||
show_source: false
|
||||
show_category_heading: true
|
||||
group_by_category: true
|
||||
docstring_section_style: spacy
|
||||
show_root_full_path: false
|
||||
merge_init_into_class: true
|
||||
separate_signature: true
|
||||
heading_level: 2
|
||||
docstring_section_style: spacy
|
||||
show_root_toc_entry: false
|
||||
- with-pdf:
|
||||
cover_subtitle: User Manual
|
||||
cover_logo: C:\Users\chacha\git\pygamecfg\docs-static\Library.jpg
|
||||
verbose: false
|
||||
exclude_pages:
|
||||
- LICENSE
|
||||
output_path: C:\Users\chacha\git\pygamecfg\helpers-results\doc_gen\site\pdf\manual.pdf
|
||||
markdown_extensions:
|
||||
- def_list
|
||||
- tables
|
||||
@@ -115,4 +118,4 @@ markdown_extensions:
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
extra:
|
||||
branch: master
|
||||
repository: pygitversionhelper
|
||||
repository: pygamecfg
|
||||
|
||||
@@ -35,7 +35,8 @@ classifiers = [
|
||||
dependencies = [
|
||||
'importlib-metadata; python_version<"3.9"',
|
||||
'packaging',
|
||||
'pysimpleini>=0.3.1'
|
||||
'pysimpleini>=0.3.1',
|
||||
'typed-argument-parser==1.*'
|
||||
]
|
||||
dynamic = ["version"]
|
||||
|
||||
@@ -48,6 +49,7 @@ where = ["src"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"pygamecfg.data" = ["*.*"]
|
||||
"pysimpleini" = ["py.typed"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://chacha.ddns.net/gitea/chacha/pygamecfg"
|
||||
@@ -60,8 +62,8 @@ coverage-check = ["coverage>=7.0"]
|
||||
complexity-check = ["radon>=5.1"]
|
||||
quality-check = ["pylint>=2.15","pylint-json2html>=0.4","pandas>=1.5"]
|
||||
type-check = ["mypy[reports]>=0.99" ]
|
||||
doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5","mkdocs-pymdownx-material-extras", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin"]
|
||||
doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5","mkdocs-material-extensions","mkdocs-pymdownx-material-extras", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin","mkdocs-autorefs"]
|
||||
|
||||
#[project.scripts]
|
||||
#my-script = "my_package.module:function"
|
||||
# [project.scripts]
|
||||
# my-script = "my_package.module:function"
|
||||
|
||||
|
||||
68
pyproject.toml.bak
Normal file
68
pyproject.toml.bak
Normal file
@@ -0,0 +1,68 @@
|
||||
# pyChaChaDummyProject (c) by chacha
|
||||
#
|
||||
# pyChaChaDummyProject is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=63", "wheel", "setuptools_scm"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools_scm]
|
||||
version_scheme= "post-release"
|
||||
|
||||
[project]
|
||||
name = "pygamecfg"
|
||||
description = "A simple game config tool that provide bash API to read / write game config files (cod, ut ...)"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
keywords = ["chacha","chacha","template","pygamecfg"]
|
||||
license = { file = "LICENSE.md" }
|
||||
|
||||
authors = [
|
||||
{name="chacha",email="1000CHACHA0001@gmail.com"},
|
||||
]
|
||||
maintainers = [
|
||||
{name="chacha",email="1000CHACHA0001@gmail.com"},
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
]
|
||||
dependencies = [
|
||||
'importlib-metadata; python_version<"3.9"',
|
||||
'packaging',
|
||||
'pysimpleini>=0.3.1',
|
||||
'typed-argument-parser==1.*'
|
||||
]
|
||||
dynamic = ["version"]
|
||||
|
||||
[tool.setuptools]
|
||||
platforms = ["any"]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"pygamecfg.data" = ["*.*"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://chacha.ddns.net/gitea/chacha/pygamecfg"
|
||||
Documentation = "https://chacha.ddns.net/mkdocs-web/chacha/pygamecfg/master/latest/"
|
||||
Tracker = "https://chacha.ddns.net/gitea/chacha/pygamecfg/issues"
|
||||
|
||||
[project.optional-dependencies]
|
||||
test = ["junitparser>=2.8","junit2html>=30.1","xmlrunner>=1.7","mypy>=0.99" ]
|
||||
coverage-check = ["coverage>=7.0"]
|
||||
complexity-check = ["radon>=5.1"]
|
||||
quality-check = ["pylint>=2.15","pylint-json2html>=0.4","pandas>=1.5"]
|
||||
type-check = ["mypy[reports]>=0.99" ]
|
||||
doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5","mkdocs-material-extensions","mkdocs-pymdownx-material-extras", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin","mkdocs-autorefs"]
|
||||
|
||||
# [project.scripts]
|
||||
# my-script = "my_package.module:function"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# pygamecfg (c) by chacha
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pygamecfg is licensed under a
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
@@ -13,7 +16,6 @@ Main module __init__ file.
|
||||
from importlib.metadata import distribution, version, PackageNotFoundError
|
||||
import warnings
|
||||
|
||||
from .core import GameOptions_Factory
|
||||
|
||||
try: # pragma: no cover
|
||||
__version__ = version("pygamecfg")
|
||||
@@ -34,3 +36,9 @@ try: # pragma: no cover
|
||||
except PackageNotFoundError: # pragma: no cover
|
||||
warnings.warn('can not read dist.metadata["Name"], assuming local test context, setting it to <pygamecfg>')
|
||||
__Name__ = "pygamecfg"
|
||||
|
||||
from pygamecfg.core_gamecfg import GameOptions_Factory
|
||||
|
||||
from . import game_cod4
|
||||
from . import game_ut99
|
||||
from . import game_ut2k4
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# PySimpleINI (c) by chacha
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# PySimpleINI is licensed under a
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
@@ -10,52 +11,102 @@
|
||||
|
||||
"""CLI interface module"""
|
||||
from __future__ import annotations
|
||||
from typing import Literal, cast, Union
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import sys
|
||||
from tap import Tap
|
||||
|
||||
from . import __Summuary__, __Name__
|
||||
from . import GameOptions_Factory
|
||||
|
||||
parser = ArgumentParser(description=__Summuary__)
|
||||
parser.add_argument("-v", "--verbosity", action="count", default=0, help="increase output verbosity")
|
||||
|
||||
parser.add_argument("-b", "--basegamedir", help="set the game base dir", default="./")
|
||||
parser.add_argument("-c", "--configfile", help="set the default config file", default="")
|
||||
parser.add_argument("-g", "--game", help="the target game", choices=["ut99", "cod4"])
|
||||
subparsers = parser.add_subparsers(dest="command", help="command type", required=True)
|
||||
class pygamecfg_args_SetOption(Tap):
|
||||
"""SetOption CLI arg subparser"""
|
||||
|
||||
SetOption_subparser = subparsers.add_parser("SetOption", help="Set/Add a game config file option value (may need reboot)")
|
||||
SetOption_subparser.add_argument("option")
|
||||
SetOption_subparser.add_argument("value", nargs="?")
|
||||
option: str
|
||||
value: str = ""
|
||||
|
||||
def configure(self) -> None:
|
||||
self.add_argument("option")
|
||||
self.add_argument("value")
|
||||
|
||||
|
||||
RemOption_subparser = subparsers.add_parser("RemOption", help="Remove a game config file option, w or w/o value (may need reboot)")
|
||||
RemOption_subparser.add_argument("option")
|
||||
RemOption_subparser.add_argument("value", nargs="?")
|
||||
class pygamecfg_args_RemOption(Tap):
|
||||
"""RemOption CLI arg subparser"""
|
||||
|
||||
GetOption_subparser = subparsers.add_parser("GetOption", help="Get a game config file option value")
|
||||
GetOption_subparser.add_argument("option")
|
||||
option: str
|
||||
value: str = ""
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbosity:
|
||||
print("Using base game dir: {0}".format(args.basegamedir))
|
||||
print("Using config file: {0}".format(args.configfile))
|
||||
|
||||
if args.configfile == "":
|
||||
if args.game == "ut99":
|
||||
args.configfile = "./System/UnrealTournament.ini"
|
||||
elif args.game == "cod4":
|
||||
args.configfile = "./main/server.cfg"
|
||||
_GameOptions = GameOptions_Factory(args.game, args.basegamedir, args.configfile)
|
||||
def configure(self) -> None:
|
||||
self.add_argument("option")
|
||||
self.add_argument("value")
|
||||
|
||||
|
||||
if args.command == "SetOption":
|
||||
_GameOptions.set(args.option, args.value)
|
||||
elif args.command == "RemOption":
|
||||
_GameOptions.rem(args.option, args.value)
|
||||
elif args.command == "GetOption":
|
||||
res = _GameOptions.get(args.option)
|
||||
print(res)
|
||||
else:
|
||||
raise RuntimeError("Invalid argument")
|
||||
class pygamecfg_args_GetOption(Tap):
|
||||
"""GetOption CLI arg subparser"""
|
||||
|
||||
option: str
|
||||
|
||||
def configure(self) -> None:
|
||||
self.add_argument("option")
|
||||
|
||||
|
||||
class pygamecfg_args(Tap):
|
||||
"""Main CLI arg parser"""
|
||||
|
||||
verbosity: int = 0
|
||||
basegamedir: str = "./"
|
||||
configfile: str = ""
|
||||
game: Literal["ut99", "cod4", "ut2k4"]
|
||||
|
||||
def configure(self) -> None:
|
||||
self.add_argument("-v", "--verbosity", action="count", help="increase output verbosity")
|
||||
self.add_argument("-b", "--basegamedir", help="set the game base dir")
|
||||
self.add_argument("-c", "--configfile", help="set the default config file")
|
||||
self.add_argument("-g", "--game", help="the target game")
|
||||
self.add_subparsers(dest="command", help="command type", required=True)
|
||||
self.add_subparser("SetOption", pygamecfg_args_SetOption, help="Set/Add a game config file option value")
|
||||
self.add_subparser("RemOption", pygamecfg_args_RemOption, help="Remove a game config file option, w or w/o value")
|
||||
self.add_subparser("GetOption", pygamecfg_args_GetOption, help="Get a game config file option value")
|
||||
|
||||
def process_args(self) -> None:
|
||||
"""dynamically add self.command to avoid conflict with Tap/argparse while keep pylint happy"""
|
||||
self.command: Union[str, None] = cast(Union[str, None], self.command) # pylint: disable=attribute-defined-outside-init
|
||||
|
||||
|
||||
def fct_main(i_args: list[str]) -> None:
|
||||
"""CLI main function"""
|
||||
parser: pygamecfg_args = pygamecfg_args(prog=__Name__, description=__Summuary__)
|
||||
|
||||
args: pygamecfg_args = parser.parse_args(i_args)
|
||||
|
||||
if args.verbosity:
|
||||
print(f"Using base game dir: {args.basegamedir}")
|
||||
print(f"Using config file: {args.configfile}")
|
||||
|
||||
if args.configfile == "":
|
||||
if args.game == "ut99":
|
||||
args.configfile = "./System/UnrealTournament.ini"
|
||||
if args.game == "ut2k4":
|
||||
args.configfile = "./System/UT2004.ini"
|
||||
elif args.game == "cod4":
|
||||
args.configfile = "./main/server.cfg"
|
||||
|
||||
GameOptions = GameOptions_Factory(args.game, args.basegamedir, args.configfile)
|
||||
if args.command == "SetOption":
|
||||
GameOptions.set(
|
||||
cast(pygamecfg_args_SetOption, args).option, cast(pygamecfg_args_SetOption, args).value # pylint: disable=no-member
|
||||
)
|
||||
elif args.command == "RemOption":
|
||||
GameOptions.rem(
|
||||
cast(pygamecfg_args_RemOption, args).option, cast(pygamecfg_args_RemOption, args).value # pylint: disable=no-member
|
||||
)
|
||||
elif args.command == "GetOption":
|
||||
res = GameOptions.get(cast(pygamecfg_args_GetOption, args).option) # pylint: disable=no-member
|
||||
print(res)
|
||||
else:
|
||||
raise RuntimeError("Invalid argument")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
fct_main(sys.argv[1:])
|
||||
|
||||
72
src/pygamecfg/common_ut.py
Normal file
72
src/pygamecfg/common_ut.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
"""common UT functions"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
|
||||
from pysimpleini import PySimpleINI
|
||||
|
||||
from .core_gamecfg import GameOption, OptionType
|
||||
|
||||
|
||||
class GameOption_UT(GameOption):
|
||||
"""generic UT Option class"""
|
||||
|
||||
szGameType = ""
|
||||
TValueType = OptionType.OT_INVALID
|
||||
|
||||
szOptionName = ""
|
||||
szSectionName = ""
|
||||
szKeyName = ""
|
||||
bForceAdd: bool = False
|
||||
bRemovable: bool = False
|
||||
|
||||
cachedFile: Union[None, PySimpleINI] = None
|
||||
cachedFilePath: Union[None, Path] = None
|
||||
|
||||
Cls_PySimpleINI: type[PySimpleINI] = PySimpleINI
|
||||
|
||||
@classmethod
|
||||
def openFile(cls, filepath: Path) -> PySimpleINI:
|
||||
"""Open the file"""
|
||||
if (not cls.cachedFile) or (filepath != cls.cachedFilePath):
|
||||
cls.cachedFilePath = filepath
|
||||
cls.cachedFile = cls.Cls_PySimpleINI(filepath)
|
||||
return cls.cachedFile
|
||||
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: str) -> None:
|
||||
super().__init__(GameRootDir, ConfigFileRelPath)
|
||||
self.mainConfigFilePath: Path = Path(join(GameRootDir, ConfigFileRelPath))
|
||||
self.inifile = self.openFile(self.mainConfigFilePath)
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
self.format(value)
|
||||
self.inifile.setaddkeyvalue(self.szSectionName, self.szKeyName, self.szFormatedValue, self.bForceAdd)
|
||||
self.inifile.writefile()
|
||||
|
||||
def rem(self, value: Union[None, str]) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
if not self.bRemovable:
|
||||
raise RuntimeError("this options is not removable")
|
||||
self.inifile.delkey_ex(self.szSectionName, self.szKeyName, None, value)
|
||||
self.inifile.writefile()
|
||||
|
||||
def get(self) -> Union[str, list[str]]:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName not set")
|
||||
return self.inifile.getkeyvalue(self.szSectionName, self.szKeyName)
|
||||
@@ -1,97 +0,0 @@
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class OptionType(Enum):
|
||||
OT_INVALID = 0
|
||||
OT_STRING = 1
|
||||
OT_INTEGER = 2
|
||||
OT_BOOLEAN = 3
|
||||
OT_FLOAT = 4
|
||||
|
||||
|
||||
class GameOption(metaclass=ABCMeta):
|
||||
szGameType: str = ""
|
||||
szOptionName: str = ""
|
||||
TValueType: OptionType = OptionType.OT_INVALID
|
||||
szDefaultValue: str = ""
|
||||
szHelp: str = ""
|
||||
szFormatedValue: str = ""
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: Union[None, str] = None):
|
||||
self.GameRootDir = GameRootDir
|
||||
self.ConfigFileRelPath = ConfigFileRelPath
|
||||
|
||||
def format(self, value: Union[int, str, float]) -> None:
|
||||
if self.TValueType == OptionType.OT_STRING:
|
||||
self.szFormatedValue = str(value)
|
||||
elif self.TValueType == OptionType.OT_INTEGER:
|
||||
self.szFormatedValue = str(int(value))
|
||||
elif self.TValueType == OptionType.OT_BOOLEAN:
|
||||
try:
|
||||
intval = int(value)
|
||||
self.szFormatedValue = str(bool(intval))
|
||||
except:
|
||||
self.szFormatedValue = str(bool(1)) if value.lower() == "true" else str(bool(0))
|
||||
elif self.TValueType == OptionType.OT_FLOAT:
|
||||
self.szFormatedValue = str(float(value))
|
||||
else:
|
||||
raise RuntimeError("Invalid Option TValueType")
|
||||
|
||||
print("setting option <{0}> to: {1}".format(self.szOptionName, self.szFormatedValue))
|
||||
|
||||
@abstractmethod
|
||||
def set(self, value: str) -> None:
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
@abstractmethod
|
||||
def rem(self, value: Union[None, str]) -> None:
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
@abstractmethod
|
||||
def get(self) -> Union[None, str]:
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
|
||||
class GameOptions_Factory:
|
||||
ar_Options_cls = []
|
||||
|
||||
def __init__(self, szGameType: str, GameRootDir: str, ConfigFileRelPath: Union[None, str] = None) -> None:
|
||||
self.szGameType = szGameType
|
||||
self.ar_Options = []
|
||||
for Options_cls in self.ar_Options_cls:
|
||||
if Options_cls.szGameType == szGameType:
|
||||
self.ar_Options.append(Options_cls(GameRootDir, ConfigFileRelPath))
|
||||
|
||||
@classmethod
|
||||
def GameOptionRegister(cls, Option: GameOption) -> None:
|
||||
cls.ar_Options_cls.append(Option)
|
||||
|
||||
def set(self, OptionName: str, value: str) -> None:
|
||||
for _option in self.ar_Options:
|
||||
if _option.szOptionName == OptionName:
|
||||
_option.set(value)
|
||||
return
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
def rem(self, OptionName: str, value: Union[None, str]) -> None:
|
||||
for _option in self.ar_Options:
|
||||
if _option.szOptionName == OptionName:
|
||||
_option.rem(value)
|
||||
return
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
def get(self, OptionName: str) -> Union[None, str]:
|
||||
for _option in self.ar_Options:
|
||||
if _option.szOptionName == OptionName:
|
||||
return _option.get()
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
|
||||
def GameOptions_Factory_Register(cls):
|
||||
GameOptions_Factory.GameOptionRegister(cls)
|
||||
return cls
|
||||
154
src/pygamecfg/core_gamecfg.py
Normal file
154
src/pygamecfg/core_gamecfg.py
Normal file
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
""" Core file of pygamecfg
|
||||
contain generic management code for GameOption
|
||||
"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class OptionType(Enum):
|
||||
"""Supported option data type"""
|
||||
|
||||
OT_INVALID = 0
|
||||
OT_STRING = 1
|
||||
OT_INTEGER = 2
|
||||
OT_BOOLEAN = 3
|
||||
OT_FLOAT = 4
|
||||
|
||||
|
||||
class GameOption(metaclass=ABCMeta):
|
||||
"""Game option base type"""
|
||||
|
||||
szGameType: str = ""
|
||||
szOptionName: str = ""
|
||||
TValueType: OptionType = OptionType.OT_INVALID
|
||||
szDefaultValue: str = ""
|
||||
szHelp: str = ""
|
||||
szFormatedValue: str = ""
|
||||
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: Union[None, str] = None):
|
||||
"""GameOption constructor.
|
||||
|
||||
///warning
|
||||
This object does not aim to be created
|
||||
///
|
||||
|
||||
Args:
|
||||
GameRootDir: root dir of the game
|
||||
ConfigFileRelPath: path to the configfile (relative to rootdir)
|
||||
"""
|
||||
self.GameRootDir = GameRootDir
|
||||
self.ConfigFileRelPath = ConfigFileRelPath
|
||||
|
||||
def __enter__(self) -> GameOption:
|
||||
"""contextlib enter hook"""
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, exception_traceback) -> None:
|
||||
"""contextlib exit hook"""
|
||||
self.close()
|
||||
|
||||
def close(self) -> None:
|
||||
"""user-define close() function (for subclassing)"""
|
||||
|
||||
def format(self, value: Union[int, str, float]) -> None:
|
||||
"""standard function to format options before writing it to file (overloadable)"""
|
||||
|
||||
if self.TValueType == OptionType.OT_STRING:
|
||||
self.szFormatedValue = str(value)
|
||||
elif self.TValueType == OptionType.OT_INTEGER:
|
||||
self.szFormatedValue = str(int(value))
|
||||
elif self.TValueType == OptionType.OT_BOOLEAN:
|
||||
try:
|
||||
intval = int(value)
|
||||
self.szFormatedValue = str(bool(intval))
|
||||
except ValueError:
|
||||
self.szFormatedValue = str(True) if str(value).lower() == "true" else str(False)
|
||||
elif self.TValueType == OptionType.OT_FLOAT:
|
||||
self.szFormatedValue = str(float(value))
|
||||
else:
|
||||
raise RuntimeError("Invalid Option TValueType")
|
||||
|
||||
print(f"setting option <{self.szOptionName}> to: {self.szFormatedValue}")
|
||||
|
||||
@abstractmethod
|
||||
def set(self, value: str) -> None:
|
||||
"""generic set function"""
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
@abstractmethod
|
||||
def rem(self, value: Union[None, str]) -> None:
|
||||
"""generic rem function"""
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
@abstractmethod
|
||||
def get(self) -> Union[str, list[str]]:
|
||||
"""generic get function"""
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
|
||||
class GameOptions_Factory:
|
||||
"""factory that manage game options based on Game and the option itself"""
|
||||
|
||||
ar_Options_cls: list[type[GameOption]] = []
|
||||
ar_Options_cls_filtered: list[type[GameOption]] = []
|
||||
GameRootDir: str = "./"
|
||||
ConfigFileRelPath: str = ""
|
||||
|
||||
def __init__(self, szGameType: str, GameRootDir: str, ConfigFileRelPath: str) -> None:
|
||||
self.szGameType = szGameType
|
||||
self.GameRootDir = GameRootDir
|
||||
self.ConfigFileRelPath = ConfigFileRelPath
|
||||
for Options_cls in GameOptions_Factory.ar_Options_cls:
|
||||
if Options_cls.szGameType == szGameType:
|
||||
self.ar_Options_cls_filtered.append(Options_cls)
|
||||
|
||||
@classmethod
|
||||
def GameOptionRegister(cls, Option: type[GameOption]) -> None:
|
||||
"""interface option used by decorator to register option implementation classes"""
|
||||
GameOptions_Factory.ar_Options_cls.append(Option)
|
||||
|
||||
def set(self, OptionName: str, value: str) -> None:
|
||||
"""generic set function (API call)"""
|
||||
for _option in GameOptions_Factory.ar_Options_cls_filtered:
|
||||
if _option.szOptionName == OptionName:
|
||||
with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst:
|
||||
_optionInst.set(value)
|
||||
return
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
def rem(self, OptionName: str, value: Union[None, str]) -> None:
|
||||
"""generic rem function (API call)"""
|
||||
for _option in self.ar_Options_cls_filtered:
|
||||
if _option.szOptionName == OptionName:
|
||||
with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst:
|
||||
_optionInst.rem(value)
|
||||
return
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
def get(self, OptionName: str) -> Union[str, list[str]]:
|
||||
"""generic get function (API call)"""
|
||||
for _option in self.ar_Options_cls_filtered:
|
||||
if _option.szOptionName == OptionName:
|
||||
with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst:
|
||||
return _optionInst.get()
|
||||
raise RuntimeError("Option not found")
|
||||
|
||||
|
||||
def GameOptions_Factory_Register(cls: type[GameOption]) -> type[GameOption]:
|
||||
"""decorator to register game option concrete implementation"""
|
||||
GameOptions_Factory.GameOptionRegister(cls)
|
||||
return cls
|
||||
@@ -1,7 +0,0 @@
|
||||
# pygamecfg (c) by chacha
|
||||
#
|
||||
# pygamecfg is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
@@ -1,10 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
# pylint: disable=missing-class-docstring,missing-module-docstring,missing-function-docstring,duplicate-code
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
import re
|
||||
from os.path import join
|
||||
|
||||
from .core import GameOptions_Factory_Register, GameOption, OptionType
|
||||
from .core_gamecfg import GameOptions_Factory_Register, GameOption, OptionType
|
||||
|
||||
|
||||
class GameOption_COD4(GameOption):
|
||||
@@ -19,7 +31,10 @@ class GameOption_COD4(GameOption):
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: str) -> None:
|
||||
super().__init__(GameRootDir, ConfigFileRelPath)
|
||||
self.mainConfigFilePath = join(GameRootDir, ConfigFileRelPath)
|
||||
self.cfgfile = open(self.mainConfigFilePath, "r")
|
||||
self.cfgfile = open(self.mainConfigFilePath, "r", encoding="utf8") # pylint: disable=consider-using-with
|
||||
|
||||
def close(self) -> None:
|
||||
self.cfgfile.close()
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
if not self.szOptionName:
|
||||
@@ -31,7 +46,7 @@ class GameOption_COD4(GameOption):
|
||||
value = self.szPrefix + " " + self.szKeyName + " " + value
|
||||
|
||||
for line in self.cfgfile.readlines():
|
||||
if re.search(r"\s+" + self.szPrefix + r"\s+"):
|
||||
if re.search(r"\s+" + self.szPrefix + r"\s+", line):
|
||||
print(f"found: {line}")
|
||||
|
||||
def rem(self, value: Union[str, None] = None) -> None:
|
||||
@@ -54,11 +69,11 @@ class GameOption_COD4(GameOption):
|
||||
raise RuntimeError("Option not found in file")
|
||||
|
||||
self.cfgfile.close()
|
||||
with open(self.mainConfigFilePath, "w") as ofile:
|
||||
with open(self.mainConfigFilePath, "w", encoding="utf8") as ofile:
|
||||
ofile.write(newFile)
|
||||
self.cfgfile = open(self.mainConfigFilePath, "r")
|
||||
self.cfgfile = open(self.mainConfigFilePath, "r", encoding="utf8") # pylint: disable=consider-using-with
|
||||
|
||||
def get(self) -> Union[None, str]:
|
||||
def get(self) -> str:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName not set")
|
||||
|
||||
@@ -67,7 +82,7 @@ class GameOption_COD4(GameOption):
|
||||
else:
|
||||
regex = r"^\s*" + self.szPrefix + r"\s+" + self.szOptionName + r"\s*(?P<value>.*)"
|
||||
bfound = False
|
||||
res = None
|
||||
|
||||
for line in self.cfgfile.readlines():
|
||||
if result := re.search(regex, line):
|
||||
if bfound:
|
||||
@@ -1,75 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
|
||||
"""UT2k4 command set"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
from pysimpleini import PySimpleINI, KeyNotFoundError, SectionNotFoundError, Section, Key
|
||||
from os.path import join
|
||||
from pysimpleini import KeyNotFoundError
|
||||
|
||||
from .core import GameOptions_Factory_Register, GameOption, OptionType
|
||||
from .core_gamecfg import GameOptions_Factory_Register, OptionType
|
||||
from .tool_ini import PySimpleINI_GroupKeysInSection
|
||||
from .common_ut import GameOption_UT
|
||||
|
||||
|
||||
class ChaChaSimpleINI_UT2k4(PySimpleINI):
|
||||
def GroupKeysInSection(self, szSectionName: str, szKeyName: str) -> None:
|
||||
try:
|
||||
_section = self.getSection(szSectionName)
|
||||
if type(_section) is Section:
|
||||
ar_ServerPackages = _section.getKey(szKeyName)
|
||||
if isinstance(ar_ServerPackages, Key):
|
||||
ar_ServerPackages = [ar_ServerPackages]
|
||||
else: # array
|
||||
pass
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section.delKey(ServerPackages.name, None, ServerPackages.value)
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section.setAddKeyValue(ServerPackages.name, ServerPackages.value, True)
|
||||
except SectionNotFoundError:
|
||||
pass
|
||||
|
||||
def writeFile(self, bBeautify: bool = False) -> None:
|
||||
self.GroupKeysInSection("Engine.GameEngine", "ServerPackages")
|
||||
self.GroupKeysInSection("Engine.GameEngine", "ServerActors")
|
||||
self.GroupKeysInSection("Core.System", "Suppress")
|
||||
self.GroupKeysInSection("Core.System", "Paths")
|
||||
self.GroupKeysInSection("Editor.EditorEngine", "EditPackages")
|
||||
self.GroupKeysInSection("Editor.EditorEngine", "CutdownPackages")
|
||||
super().writeFile(bBeautify)
|
||||
class PySimpleINI_UT2k4(PySimpleINI_GroupKeysInSection):
|
||||
GroupRules = [
|
||||
("Engine.GameEngine", "ServerPackages"),
|
||||
("Engine.GameEngine", "ServerActors"),
|
||||
("Core.System", "Suppress"),
|
||||
("Core.System", "Paths"),
|
||||
("Core.System", "Paths"),
|
||||
("Editor.EditorEngine", "EditPackages"),
|
||||
("Editor.EditorEngine", "CutdownPackages"),
|
||||
]
|
||||
|
||||
|
||||
class GameOption_UT2k4(GameOption):
|
||||
class GameOption_UT2k4(GameOption_UT):
|
||||
szGameType = "ut2k4"
|
||||
TValueType = OptionType.OT_INVALID
|
||||
|
||||
szOptionName = ""
|
||||
szSectionName = ""
|
||||
szKeyName = ""
|
||||
bForceAdd: bool = False
|
||||
bRemovable: bool = False
|
||||
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: Union[None, str]) -> None:
|
||||
super().__init__(GameRootDir, ConfigFileRelPath)
|
||||
self.mainConfigFilePath = join(GameRootDir, ConfigFileRelPath)
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
self.format(value)
|
||||
self.inifile = ChaChaSimpleINI_UT2k4(self.mainConfigFilePath)
|
||||
self.inifile.setAddKeyValue(self.szSectionName, self.szKeyName, self.szFormatedValue, self.bForceAdd)
|
||||
self.inifile.writeFile()
|
||||
|
||||
def rem(self, value: Union[None, str]) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
if not self.bRemovable:
|
||||
raise RuntimeError("this options is not removable")
|
||||
self.inifile.delKeyEx(self.szSectionName, self.szKeyName, None, value)
|
||||
self.inifile.writeFile()
|
||||
|
||||
def get(self) -> Union[None, str]:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName not set")
|
||||
print("get option <{0}>".format(self.szOptionName))
|
||||
res = self.inifile.getKeyValue(self.szSectionName, self.szKeyName)
|
||||
return res
|
||||
Cls_PySimpleINI = PySimpleINI_UT2k4
|
||||
|
||||
|
||||
class GameOption_UT2k4_GenAdd(GameOption_UT2k4):
|
||||
@@ -156,10 +122,10 @@ class GameOption_UT2k4_HostName(GameOption_UT2k4):
|
||||
szDefaultValue = "ChaCha Test Server"
|
||||
szHelp = "Server's HostName"
|
||||
|
||||
def set(self, value: str):
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.GameReplicationInfo", "ShortName", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.GameReplicationInfo", "ShortName", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -201,12 +167,12 @@ class GameOption_UT2k4_HTTPDownloadServer(GameOption_UT2k4):
|
||||
szDefaultValue = "http://chacha.ddns.net/games/ut2k4"
|
||||
szHelp = "FastDL url"
|
||||
|
||||
def set(self, value: str):
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("IpDrv.HTTPDownload", "UseCompression", "True")
|
||||
self.inifile.delKey("IpDrv.HTTPDownload", "ProxyServerHost")
|
||||
self.inifile.delKey("IpDrv.HTTPDownload", "ProxyServerPort")
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("IpDrv.HTTPDownload", "UseCompression", "True")
|
||||
self.inifile.delkey("IpDrv.HTTPDownload", "ProxyServerHost")
|
||||
self.inifile.delkey("IpDrv.HTTPDownload", "ProxyServerPort")
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -238,10 +204,10 @@ class GameOption_UT2k4_NetServerMaxTickRate(GameOption_UT2k4):
|
||||
szDefaultValue = "60"
|
||||
szHelp = "Server Max TickRate"
|
||||
|
||||
def set(self, value: str):
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.DemoRecDrive", "NetServerMaxTickRate", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.DemoRecDrive", "NetServerMaxTickRate", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -253,10 +219,10 @@ class GameOption_UT2k4_LanServerMaxTickRate(GameOption_UT2k4):
|
||||
szDefaultValue = "60"
|
||||
szHelp = "Lan Server Max TickRate"
|
||||
|
||||
def set(self, value: str):
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.DemoRecDrive", "LanServerMaxTickRate", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.DemoRecDrive", "LanServerMaxTickRate", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -731,7 +697,7 @@ class GameOption_UT2k4_WebServer(GameOption_UT2k4):
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
if int(value) > 0:
|
||||
self.inifile.setAddKeyValue("UWeb.WebServer", "bEnabled", "True")
|
||||
self.inifile.setaddkeyvalue("UWeb.WebServer", "bEnabled", "True")
|
||||
else:
|
||||
self.inifile.setAddKeyValue("UWeb.WebServer", "bEnabled", "False")
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("UWeb.WebServer", "bEnabled", "False")
|
||||
self.inifile.writefile()
|
||||
@@ -1,75 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
# pylint: disable=missing-class-docstring,missing-function-docstring,duplicate-code
|
||||
"""UT99 command set"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
|
||||
from pysimpleini import PySimpleINI, KeyNotFoundError, SectionNotFoundError, Section, Key
|
||||
from os.path import join
|
||||
from pysimpleini import KeyNotFoundError, SectionNotFoundError
|
||||
|
||||
from .core import GameOptions_Factory_Register, GameOption, OptionType
|
||||
from .core_gamecfg import GameOptions_Factory_Register, OptionType
|
||||
from .tool_ini import PySimpleINI_GroupKeysInSection
|
||||
from .common_ut import GameOption_UT
|
||||
|
||||
|
||||
class PySimpleINI_UT99(PySimpleINI):
|
||||
def GroupKeysInSection(self, szSectionName: str, szKeyName: str) -> None:
|
||||
try:
|
||||
_section = self.getSection(szSectionName)
|
||||
if type(_section) is Section:
|
||||
ar_ServerPackages = _section.getKey(szKeyName)
|
||||
if isinstance(ar_ServerPackages, Key):
|
||||
ar_ServerPackages = [ar_ServerPackages]
|
||||
else: # array
|
||||
pass
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section.delKey(ServerPackages.name, None, ServerPackages.value)
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section.setAddKeyValue(ServerPackages.name, ServerPackages.value, True)
|
||||
except SectionNotFoundError:
|
||||
pass
|
||||
|
||||
def writeFile(self, bBeautify: bool = False) -> None:
|
||||
self.GroupKeysInSection("XC_Engine.XC_GameEngine", "ServerPackages")
|
||||
self.GroupKeysInSection("XC_Engine.XC_GameEngine", "ServerActors")
|
||||
self.GroupKeysInSection("Engine.GameEngine", "ServerPackages")
|
||||
self.GroupKeysInSection("Engine.GameEngine", "ServerActors")
|
||||
self.GroupKeysInSection("Core.System", "Suppress")
|
||||
self.GroupKeysInSection("Editor.EditorEngine", "EditPackages")
|
||||
super().writeFile(bBeautify)
|
||||
class PySimpleINI_UT99(PySimpleINI_GroupKeysInSection):
|
||||
GroupRules = [
|
||||
("XC_Engine.XC_GameEngine", "ServerPackages"),
|
||||
("XC_Engine.XC_GameEngine", "ServerActors"),
|
||||
("Engine.GameEngine", "ServerPackages"),
|
||||
("Engine.GameEngine", "ServerActors"),
|
||||
("Core.System", "Suppress"),
|
||||
("Editor.EditorEngine", "EditPackages"),
|
||||
]
|
||||
|
||||
|
||||
class GameOption_UT99(GameOption):
|
||||
class GameOption_UT99(GameOption_UT):
|
||||
szGameType = "ut99"
|
||||
TValueType = OptionType.OT_INVALID
|
||||
|
||||
szOptionName = ""
|
||||
szSectionName = ""
|
||||
szKeyName = ""
|
||||
bForceAdd: bool = False
|
||||
bRemovable: bool = False
|
||||
|
||||
def __init__(self, GameRootDir: str, ConfigFileRelPath: str) -> None:
|
||||
super().__init__(GameRootDir, ConfigFileRelPath)
|
||||
self.mainConfigFilePath = join(GameRootDir, ConfigFileRelPath)
|
||||
self.inifile = PySimpleINI_UT99(self.mainConfigFilePath)
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
self.format(value)
|
||||
self.inifile.setAddKeyValue(self.szSectionName, self.szKeyName, self.szFormatedValue, self.bForceAdd)
|
||||
self.inifile.writeFile()
|
||||
|
||||
def rem(self, value: Union[None, str]) -> None:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName is not set")
|
||||
if not self.bRemovable:
|
||||
raise RuntimeError("this options is not removable")
|
||||
self.inifile.delKeyEx(self.szSectionName, self.szKeyName, None, value)
|
||||
self.inifile.writeFile()
|
||||
|
||||
def get(self) -> Union[None, str]:
|
||||
if not self.szOptionName:
|
||||
raise RuntimeError("szOptionName not set")
|
||||
# print("get option <{0}>".format(self.szOptionName))
|
||||
res = self.inifile.getKeyValue(self.szSectionName, self.szKeyName)
|
||||
return res
|
||||
Cls_PySimpleINI = PySimpleINI_UT99
|
||||
|
||||
|
||||
class GameOption_UT99_GenAdd(GameOption_UT99):
|
||||
@@ -96,7 +61,7 @@ class GameOption_UT99_GenAdd__Engine(GameOption_UT99_GenAdd):
|
||||
prev = self.szSectionName
|
||||
|
||||
try:
|
||||
self.inifile.getSection("XC_Engine.XC_GameEngine")
|
||||
self.inifile.getsection("XC_Engine.XC_GameEngine")
|
||||
self.szSectionName = "XC_Engine.XC_GameEngine"
|
||||
super().set(value)
|
||||
except SectionNotFoundError:
|
||||
@@ -110,7 +75,7 @@ class GameOption_UT99_GenAdd__Engine(GameOption_UT99_GenAdd):
|
||||
prev = self.szSectionName
|
||||
|
||||
try:
|
||||
self.inifile.getSection("XC_Engine.XC_GameEngine")
|
||||
self.inifile.getsection("XC_Engine.XC_GameEngine")
|
||||
self.szSectionName = "XC_Engine.XC_GameEngine"
|
||||
super().rem(value)
|
||||
except SectionNotFoundError:
|
||||
@@ -175,8 +140,8 @@ class GameOption_UT99_HostName(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.GameReplicationInfo", "ShortName", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.GameReplicationInfo", "ShortName", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -240,8 +205,8 @@ class GameOption_UT99_AdminName(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("UTServerAdmin.UTServerAdmin", "AdminUsername", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("UTServerAdmin.UTServerAdmin", "AdminUsername", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -255,10 +220,10 @@ class GameOption_UT99_HTTPDownloadServer(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("IpDrv.HTTPDownload", "UseCompression", "True")
|
||||
self.inifile.delKey("IpDrv.HTTPDownload", "ProxyServerHost")
|
||||
self.inifile.delKey("IpDrv.HTTPDownload", "ProxyServerPort")
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("IpDrv.HTTPDownload", "UseCompression", "True")
|
||||
self.inifile.delkey("IpDrv.HTTPDownload", "ProxyServerHost")
|
||||
self.inifile.delkey("IpDrv.HTTPDownload", "ProxyServerPort")
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -292,8 +257,8 @@ class GameOption_UT99_NetServerMaxTickRate(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.DemoRecDriver", "NetServerMaxTickRate", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.DemoRecDriver", "NetServerMaxTickRate", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -307,8 +272,8 @@ class GameOption_UT99_LanServerMaxTickRate(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("Engine.DemoRecDriver", "LanServerMaxTickRate", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("Engine.DemoRecDriver", "LanServerMaxTickRate", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -322,8 +287,19 @@ class GameOption_UT99_AdminPassword(GameOption_UT99):
|
||||
|
||||
def set(self, value: str) -> None:
|
||||
super().set(value)
|
||||
self.inifile.setAddKeyValue("UTServerAdmin.UTServerAdmin", "AdminPassword", value)
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("UTServerAdmin.UTServerAdmin", "AdminPassword", value)
|
||||
self.inifile.writefile()
|
||||
|
||||
def get(self) -> Union[str, list[str]]:
|
||||
try:
|
||||
return super().get()
|
||||
except KeyNotFoundError:
|
||||
return self.inifile.getkeyvalue(
|
||||
"UTServerAdmin.UTServerAdmin",
|
||||
"AdminPassword",
|
||||
)
|
||||
|
||||
raise NotImplementedError("method not implemented")
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
@@ -448,15 +424,15 @@ class GameOption_UT99_WebServer(GameOption_UT99):
|
||||
def set(self, value: str) -> None:
|
||||
# fix ut99 v469c
|
||||
try:
|
||||
self.inifile.delKey("UWeb.WebServer", "Listenport")
|
||||
except:
|
||||
self.inifile.delkey("UWeb.WebServer", "Listenport")
|
||||
except KeyNotFoundError:
|
||||
pass
|
||||
super().set(value)
|
||||
if int(value) > 0:
|
||||
self.inifile.setAddKeyValue("UWeb.WebServer", "bEnabled", "True")
|
||||
self.inifile.setaddkeyvalue("UWeb.WebServer", "bEnabled", "True")
|
||||
else:
|
||||
self.inifile.setAddKeyValue("UWeb.WebServer", "bEnabled", "False")
|
||||
self.inifile.writeFile()
|
||||
self.inifile.setaddkeyvalue("UWeb.WebServer", "bEnabled", "False")
|
||||
self.inifile.writefile()
|
||||
|
||||
|
||||
@GameOptions_Factory_Register
|
||||
1
src/pygamecfg/py.typed
Normal file
1
src/pygamecfg/py.typed
Normal file
@@ -0,0 +1 @@
|
||||
# PlaceHolder
|
||||
44
src/pygamecfg/tool_ini.py
Normal file
44
src/pygamecfg/tool_ini.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyGameCFG(c) by chacha
|
||||
#
|
||||
# pyGameCFG is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
"""utility module that contain PySimpleINI based helpers"""
|
||||
from __future__ import annotations
|
||||
from typing import Union
|
||||
from pysimpleini import PySimpleINI, SectionNotFoundError, Key, Section
|
||||
|
||||
|
||||
class PySimpleINI_GroupKeysInSection(PySimpleINI):
|
||||
"""a class base on PySimpleINI that allow user to force some key to be group together in a section"""
|
||||
|
||||
GroupRules: list[tuple[str, str]] = []
|
||||
|
||||
def groupkeysinsection(self, szSectionName: str, szKeyName: str) -> None:
|
||||
"""internal function that actually group keys"""
|
||||
try:
|
||||
_section: list[Section] = self.getsection(szSectionName)
|
||||
if len(_section) == 1:
|
||||
ar_ServerPackages: Union[list[Key], Key] = _section[0].getkey(szKeyName)
|
||||
if isinstance(ar_ServerPackages, Key):
|
||||
ar_ServerPackages = [ar_ServerPackages]
|
||||
else: # array
|
||||
pass
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section[0].delkey(ServerPackages.getname(), None, ServerPackages.getvalue())
|
||||
for ServerPackages in ar_ServerPackages:
|
||||
_section[0].setaddkeyvalue(ServerPackages.getname(), ServerPackages.getvalue(), True)
|
||||
except SectionNotFoundError:
|
||||
pass
|
||||
|
||||
def writefile(self, bBeautify: bool = False, bWipeComments: bool = False) -> None:
|
||||
"""overload of the write function to call the group function before"""
|
||||
for GroupRule in self.GroupRules:
|
||||
self.groupkeysinsection(GroupRule[0], GroupRule[1])
|
||||
super().writefile(bBeautify, bWipeComments)
|
||||
520
test/data/UT99/System/UT99.ini
Normal file
520
test/data/UT99/System/UT99.ini
Normal file
@@ -0,0 +1,520 @@
|
||||
[URL]
|
||||
Protocol=unreal
|
||||
ProtocolDescription=Unreal Protocol
|
||||
Name=Player
|
||||
Map=Index.unr
|
||||
LocalMap=DM-Codex.unr
|
||||
Host=
|
||||
Portal=
|
||||
MapExt=unr
|
||||
SaveExt=usa
|
||||
Port=7777
|
||||
Class=Botpack.TMale1
|
||||
|
||||
[FirstRun]
|
||||
FirstRun=0
|
||||
|
||||
[PackageRemap]
|
||||
UnrealShare=UnrealI
|
||||
|
||||
[Engine.Engine]
|
||||
GameRenderDevice=SoftDrv.SoftwareRenderDevice
|
||||
AudioDevice=Galaxy.GalaxyAudioSubsystem
|
||||
NetworkDevice=IpDrv.TcpNetDriver
|
||||
DemoRecordingDevice=Engine.DemoRecDriver
|
||||
Console=UTMenu.UTConsole
|
||||
Language=int
|
||||
GameEngine=Engine.GameEngine
|
||||
EditorEngine=Editor.EditorEngine
|
||||
WindowedRenderDevice=SoftDrv.SoftwareRenderDevice
|
||||
RenderDevice=GlideDrv.GlideRenderDevice
|
||||
DefaultGame=Botpack.DeathMatchPlus
|
||||
DefaultServerGame=Botpack.DeathMatchPlus
|
||||
ViewportManager=WinDrv.WindowsClient
|
||||
Render=Render.Render
|
||||
Input=Engine.Input
|
||||
Canvas=Engine.Canvas
|
||||
|
||||
[Core.System]
|
||||
PurgeCacheDays=30
|
||||
SavePath=../Save
|
||||
CachePath=../Cache
|
||||
CacheExt=.uxx
|
||||
Paths=../System/*.u
|
||||
Paths=../Maps/*.unr
|
||||
Paths=../Textures/*.utx
|
||||
Paths=../Sounds/*.uax
|
||||
Paths=../Music/*.umx
|
||||
Suppress=DevLoad
|
||||
Suppress=DevSave
|
||||
Suppress=DevNetTraffic
|
||||
Suppress=DevGarbage
|
||||
Suppress=DevKill
|
||||
Suppress=DevReplace
|
||||
Suppress=DevSound
|
||||
Suppress=DevCompile
|
||||
Suppress=DevBind
|
||||
Suppress=DevBsp
|
||||
|
||||
[Engine.GameEngine]
|
||||
CacheSizeMegs=4
|
||||
UseSound=True
|
||||
ServerActors=IpDrv.UdpBeacon
|
||||
ServerActors=IpServer.UdpServerQuery
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=master0.gamespy.com MasterServerPort=27900
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=master.mplayer.com MasterServerPort=27900
|
||||
ServerActors=UWeb.WebServer
|
||||
ServerPackages=SoldierSkins
|
||||
ServerPackages=CommandoSkins
|
||||
ServerPackages=FCommandoSkins
|
||||
ServerPackages=SGirlSkins
|
||||
ServerPackages=BossSkins
|
||||
ServerPackages=Botpack
|
||||
|
||||
[WinDrv.WindowsClient]
|
||||
WindowedViewportX=640
|
||||
WindowedViewportY=480
|
||||
WindowedColorBits=16
|
||||
FullscreenViewportX=640
|
||||
FullscreenViewportY=480
|
||||
FullscreenColorBits=16
|
||||
Brightness=0.500000
|
||||
MipFactor=1.000000
|
||||
UseDirectDraw=True
|
||||
UseJoystick=False
|
||||
CaptureMouse=True
|
||||
StartupFullscreen=True
|
||||
CurvedSurfaces=False
|
||||
LowDetailTextures=False
|
||||
ScreenFlashes=True
|
||||
NoLighting=False
|
||||
SlowVideoBuffering=True
|
||||
DeadZoneXYZ=True
|
||||
DeadZoneRUV=False
|
||||
InvertVertical=False
|
||||
ScaleXYZ=1000.0
|
||||
ScaleRUV=2000.0
|
||||
MinDesiredFrameRate=30.0
|
||||
Decals=True
|
||||
NoDynamicLights=False
|
||||
|
||||
[XDrv.XClient]
|
||||
WindowedViewportX=640
|
||||
WindowedViewportY=480
|
||||
WindowedColorBits=16
|
||||
FullscreenViewportX=640
|
||||
FullscreenViewportY=480
|
||||
FullscreenColorBits=16
|
||||
Brightness=0.500000
|
||||
MipFactor=1.000000
|
||||
SlowVideoBuffering=False
|
||||
StartupFullscreen=True
|
||||
CurvedSurfaces=False
|
||||
CaptureMouse=True
|
||||
LowDetailTextures=False
|
||||
ScreenFlashes=True
|
||||
NoLighting=False
|
||||
DeadZoneXYZ=True
|
||||
DeadZoneRUV=False
|
||||
InvertVertical=False
|
||||
ScaleXYZ=1000.0
|
||||
ScaleRUV=2000.0
|
||||
MinDesiredFrameRate=30.0
|
||||
|
||||
[Engine.Player]
|
||||
ConfiguredInternetSpeed=2600
|
||||
ConfiguredLanSpeed=20000
|
||||
|
||||
[Audio.GenericAudioSubsystem]
|
||||
UseFilter=True
|
||||
UseSurround=False
|
||||
UseStereo=True
|
||||
UseCDMusic=False
|
||||
UseDigitalMusic=False
|
||||
UseSpatial=False
|
||||
UseReverb=False
|
||||
Use3dHardware=False
|
||||
LowSoundQuality=False
|
||||
ReverseStereo=False
|
||||
Latency=40
|
||||
OutputRate=22050Hz
|
||||
Channels=16
|
||||
MusicVolume=160
|
||||
SoundVolume=200
|
||||
AmbientFactor=0.7
|
||||
|
||||
[Galaxy.GalaxyAudioSubsystem]
|
||||
UseDirectSound=True
|
||||
UseFilter=True
|
||||
UseSurround=False
|
||||
UseStereo=True
|
||||
UseCDMusic=False
|
||||
UseDigitalMusic=True
|
||||
UseSpatial=False
|
||||
UseReverb=True
|
||||
Use3dHardware=False
|
||||
LowSoundQuality=False
|
||||
ReverseStereo=False
|
||||
Latency=40
|
||||
OutputRate=22050Hz
|
||||
EffectsChannels=16
|
||||
DopplerSpeed=9000.000000
|
||||
MusicVolume=160
|
||||
SoundVolume=200
|
||||
AmbientFactor=0.700000
|
||||
|
||||
[IpDrv.TcpNetDriver]
|
||||
AllowDownloads=True
|
||||
ConnectionTimeout=15.0
|
||||
InitialConnectTimeout=120.0
|
||||
AckTimeout=1.0
|
||||
KeepAliveTime=0.2
|
||||
MaxClientRate=20000
|
||||
MaxDownloadSize=0
|
||||
SimLatency=0
|
||||
RelevantTimeout=5.0
|
||||
SpawnPrioritySeconds=1.0
|
||||
ServerTravelPause=4.0
|
||||
NetServerMaxTickRate=20
|
||||
LanServerMaxTickRate=35
|
||||
DownloadManagers=IpDrv.HTTPDownload
|
||||
DownloadManagers=Engine.ChannelDownload
|
||||
|
||||
[IpDrv.HTTPDownload]
|
||||
RedirectToURL=http://uz.ut-files.com/
|
||||
ProxyServerHost=
|
||||
ProxyServerPort=3128
|
||||
UseCompression=True
|
||||
|
||||
[Engine.DemoRecDriver]
|
||||
DemoSpectatorClass=Botpack.CHSpectator
|
||||
MaxClientRate=25000
|
||||
ConnectionTimeout=15.0
|
||||
InitialConnectTimeout=500.0
|
||||
AckTimeout=1.0
|
||||
KeepAliveTime=1.0
|
||||
SimLatency=0
|
||||
RelevantTimeout=5.0
|
||||
SpawnPrioritySeconds=1.0
|
||||
ServerTravelPause=4.0
|
||||
NetServerMaxTickRate=60
|
||||
LanServerMaxTickRate=60
|
||||
|
||||
[Engine.GameReplicationInfo]
|
||||
ServerName=Alt Serv Name FULL
|
||||
ShortName=Alt Serv Name SHORT
|
||||
AdminName=TestAdminName
|
||||
AdminEmail=TestAdminName@test.com
|
||||
Region=0
|
||||
MOTDLine1=TestMOTDLine1
|
||||
MOTDLine2=TestMOTDLine2
|
||||
MOTDLine3=TestMOTDLine3
|
||||
MOTDLine4=TestMOTDLine4
|
||||
|
||||
[IpDrv.TcpipConnection]
|
||||
SimPacketLoss=0
|
||||
SimLatency=0
|
||||
|
||||
[IpServer.UdpServerQuery]
|
||||
DoUplink=True
|
||||
UpdateMinutes=1
|
||||
MasterServerAddress=unreal.epicgames.com
|
||||
MasterServerPort=27900
|
||||
Region=0
|
||||
|
||||
[IpDrv.UdpBeacon]
|
||||
DoBeacon=True
|
||||
BeaconTime=0.50
|
||||
BeaconTimeout=5.0
|
||||
BeaconProduct=ut
|
||||
|
||||
[SoftDrv.SoftwareRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=False
|
||||
Coronas=False
|
||||
HighDetailActors=False
|
||||
HighResTextureSmooth=True
|
||||
LowResTextureSmooth=False
|
||||
FastTranslucency=True
|
||||
|
||||
[GlideDrv.GlideRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailBias=-1.500000
|
||||
RefreshRate=60Hz
|
||||
DetailTextures=True
|
||||
FastUglyRefresh=False
|
||||
ScreenSmoothing=True
|
||||
Resolution=Default
|
||||
|
||||
[MetalDrv.MetalRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailTextures=False
|
||||
|
||||
[OpenGLDrv.OpenGLRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailTextures=True
|
||||
|
||||
[D3DDrv.D3DRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
UseMipmapping=True
|
||||
UseTrilinear=False
|
||||
UseMultitexture=True
|
||||
UsePageFlipping=True
|
||||
UsePalettes=True
|
||||
UseFullscreen=True
|
||||
UseGammaCorrection=True
|
||||
DetailTextures=False
|
||||
Use3dfx=False
|
||||
UseTripleBuffering=True
|
||||
UsePrecache=True
|
||||
Use32BitTextures=False
|
||||
|
||||
[SglDrv.SglRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=False
|
||||
Coronas=True
|
||||
HighDetailActors=False
|
||||
ColorDepth=16
|
||||
DetailTextures=False
|
||||
FastUglyRefresh=False
|
||||
TextureDetailBias=Near
|
||||
VertexLighting=False
|
||||
|
||||
[Editor.EditorEngine]
|
||||
UseSound=True
|
||||
CacheSizeMegs=6
|
||||
GridEnabled=True
|
||||
SnapVertices=True
|
||||
SnapDistance=10.000000
|
||||
GridSize=(X=16.000000,Y=16.000000,Z=16.000000)
|
||||
RotGridEnabled=True
|
||||
RotGridSize=(Pitch=1024,Yaw=1024,Roll=1024)
|
||||
GameCommandLine=-log
|
||||
FovAngleDegrees=90.000000
|
||||
GodMode=True
|
||||
AutoSave=False
|
||||
AutoSaveTimeMinutes=5
|
||||
AutoSaveIndex=6
|
||||
C_WorldBox=(R=0,G=0,B=107,A=0)
|
||||
C_GroundPlane=(R=0,G=0,B=63,A=0)
|
||||
C_GroundHighlight=(R=0,G=0,B=127,A=0)
|
||||
C_BrushWire=(R=255,G=63,B=63,A=0)
|
||||
C_Pivot=(R=0,G=255,B=0,A=0)
|
||||
C_Select=(R=0,G=0,B=127,A=0)
|
||||
C_AddWire=(R=127,G=127,B=255,A=0)
|
||||
C_SubtractWire=(R=255,G=192,B=63,A=0)
|
||||
C_GreyWire=(R=163,G=163,B=163,A=0)
|
||||
C_Invalid=(R=163,G=163,B=163,A=0)
|
||||
C_ActorWire=(R=127,G=63,B=0,A=0)
|
||||
C_ActorHiWire=(R=255,G=127,B=0,A=0)
|
||||
C_White=(R=255,G=255,B=255,A=0)
|
||||
C_SemiSolidWire=(R=127,G=255,B=0,A=0)
|
||||
C_NonSolidWire=(R=63,G=192,B=32,A=0)
|
||||
C_WireGridAxis=(R=119,G=119,B=119,A=0)
|
||||
C_ActorArrow=(R=163,G=0,B=0,A=0)
|
||||
C_ScaleBox=(R=151,G=67,B=11,A=0)
|
||||
C_ScaleBoxHi=(R=223,G=149,B=157,A=0)
|
||||
C_Mover=(R=255,G=0,B=255,A=0)
|
||||
C_OrthoBackground=(R=163,G=163,B=163,A=0)
|
||||
C_Current=(R=0,G=0,B=0,A=0)
|
||||
C_BrushVertex=(R=0,G=0,B=0,A=0)
|
||||
C_BrushSnap=(R=0,G=0,B=0,A=0)
|
||||
C_Black=(R=0,G=0,B=0,A=0)
|
||||
C_Mask=(R=0,G=0,B=0,A=0)
|
||||
C_WireBackground=(R=0,G=0,B=0,A=0)
|
||||
C_ZoneWire=(R=0,G=0,B=0,A=0)
|
||||
EditPackages=Core
|
||||
EditPackages=Engine
|
||||
EditPackages=Editor
|
||||
EditPackages=UWindow
|
||||
EditPackages=Fire
|
||||
EditPackages=IpDrv
|
||||
EditPackages=UWeb
|
||||
EditPackages=UBrowser
|
||||
EditPackages=UnrealShare
|
||||
EditPackages=UnrealI
|
||||
EditPackages=UMenu
|
||||
EditPackages=IpServer
|
||||
EditPackages=Botpack
|
||||
EditPackages=UTServerAdmin
|
||||
EditPackages=UTMenu
|
||||
EditPackages=UTBrowser
|
||||
|
||||
[UMenu.UnrealConsole]
|
||||
RootWindow=UMenu.UMenuRootWindow
|
||||
UWindowKey=IK_Esc
|
||||
ShowDesktop=True
|
||||
|
||||
[UMenu.UMenuMenuBar]
|
||||
ShowHelp=True
|
||||
GameUMenuDefault="UTMenu.UTGameMenu"
|
||||
MultiplayerUMenuDefault="UTMenu.UTMultiplayerMenu"
|
||||
OptionsUMenuDefault="UTMenu.UTOptionsMenu"
|
||||
|
||||
[Botpack.ChallengeBotInfo]
|
||||
Difficulty=1
|
||||
|
||||
[Botpack.DeathMatchPlus]
|
||||
bNoviceMode=True
|
||||
bHardCoreMode=True
|
||||
bUseTranslocator=False
|
||||
bCoopWeaponMode=False
|
||||
bForceRespawn=True
|
||||
TimeLimit=323
|
||||
FragLimit=321
|
||||
InitialBots=7
|
||||
MinPlayers=11
|
||||
bTournament=False
|
||||
|
||||
[Botpack.CTFGame]
|
||||
bUseTranslocator=True
|
||||
bCoopWeaponMode=True
|
||||
GoalTeamScore=3
|
||||
bForceRespawn=False
|
||||
TimeLimit=223
|
||||
|
||||
[Botpack.Domination]
|
||||
bDumbDown=True
|
||||
bUseTranslocator=True
|
||||
bCoopWeaponMode=True
|
||||
GoalTeamScore=100
|
||||
bForceRespawn=False
|
||||
TimeLimit=423
|
||||
|
||||
[Botpack.Assault]
|
||||
bUseTranslocator=False
|
||||
bCoopWeaponMode=True
|
||||
bForceRespawn=True
|
||||
TimeLimit=123
|
||||
|
||||
[Botpack.TeamGamePlus]
|
||||
bBalanceTeams=True
|
||||
GoalTeamScore=30
|
||||
bPlayersBalanceTeams=True
|
||||
MaxTeamSize=4
|
||||
|
||||
[Engine.GameInfo]
|
||||
bLowGore=False
|
||||
bVeryLowGore=False
|
||||
MaxSpectators=1
|
||||
MaxPlayers=4
|
||||
ServerLogName=server.log
|
||||
bWorldLog=True
|
||||
bBatchLocal=False
|
||||
DemoBuild=0
|
||||
DemoHasTuts=0
|
||||
PlayerViewDelay=1.000000
|
||||
PlayerSpeechDelay=0.300000
|
||||
PlayerTauntDelay=2.000000
|
||||
bLogAdminActions=False
|
||||
LoginDelaySeconds=0.000000
|
||||
MaxLoginAttempts=0
|
||||
ActionToTake=DO_Nothing
|
||||
IPPolicies[0]=ACCEPT,*
|
||||
IPPolicies[1]=
|
||||
GamePassword=TestPwd
|
||||
|
||||
[UnrealShare.UnrealGameOptionsMenu]
|
||||
bCanModifyGore=True
|
||||
|
||||
[UBrowser.UBrowserMainClientWindow]
|
||||
LANTabName=UBrowserLAN
|
||||
ServerListNames[0]=UBrowserUT
|
||||
ServerListNames[1]=UBrowserLAN
|
||||
ServerListNames[2]=UBrowserPopulated
|
||||
ServerListNames[3]=UBrowserDeathmatch
|
||||
ServerListNames[4]=UBrowserTeamGames
|
||||
ServerListNames[5]=UBrowserCTF
|
||||
ServerListNames[6]=UBrowserDOM
|
||||
ServerListNames[7]=UBrowserAS
|
||||
ServerListNames[8]=UBrowserLMS
|
||||
ServerListNames[9]=UBrowserAll
|
||||
ServerListNames[10]=None
|
||||
ServerListNames[11]=None
|
||||
ServerListNames[12]=None
|
||||
ServerListNames[13]=None
|
||||
ServerListNames[14]=None
|
||||
ServerListNames[15]=None
|
||||
ServerListNames[16]=None
|
||||
ServerListNames[17]=None
|
||||
ServerListNames[18]=None
|
||||
ServerListNames[19]=None
|
||||
|
||||
[UBrowserUT]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserLAN]
|
||||
ListFactories[0]=UBrowser.UBrowserLocalFact,BeaconProduct=ut
|
||||
URLAppend=?LAN
|
||||
AutoRefreshTime=10
|
||||
bNoAutoSort=True
|
||||
|
||||
[UBrowserPopulated]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,MinPlayers=1,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserDeathmatch]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=DeathMatchPlus,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserTeamGames]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=TeamGamePlus,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserCTF]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=CTFGame,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserDOM]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=Domination,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserAS]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=Assault,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserLMS]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=LastManStanding,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserAll]
|
||||
ListFactories[0]=UBrowser.UBrowserGSpyFact,MasterServerAddress=unreal.epicgames.com,MasterServerTCPPort=28900,Region=0,GameName=ut
|
||||
ListFactories[1]=UBrowser.UBrowserGSpyFact,MasterServerAddress=master0.gamespy.com,MasterServerTCPPort=28900,Region=0,GameName=ut
|
||||
bHidden=True
|
||||
bFallbackFactories=True
|
||||
|
||||
[UTMenu.UTMultiplayerMenu]
|
||||
OnlineServices[0]=LOCALIZE,MPlayer
|
||||
OnlineServices[1]=LOCALIZE,Heat
|
||||
OnlineServices[2]=LOCALIZE,WON
|
||||
|
||||
[UWeb.WebServer]
|
||||
Applications[0]=UTServerAdmin.UTServerAdmin
|
||||
ApplicationPaths[0]=/ServerAdmin
|
||||
Applications[1]=UTServerAdmin.UTImageServer
|
||||
ApplicationPaths[1]=/images
|
||||
DefaultApplication=0
|
||||
bEnabled=True
|
||||
ListenPort=9999
|
||||
MaxConnections=30
|
||||
|
||||
[UBrowser.UBrowserHTTPClient]
|
||||
ProxyServerAddress=
|
||||
ProxyServerPort=
|
||||
|
||||
[UTServerAdmin.UTServerAdmin]
|
||||
AdminUsername=TestAdminUser
|
||||
AdminPassword=TestAdminPwd
|
||||
|
||||
520
test/data/UT99/System/UnrealTournament.ini
Normal file
520
test/data/UT99/System/UnrealTournament.ini
Normal file
@@ -0,0 +1,520 @@
|
||||
[URL]
|
||||
Protocol=unreal
|
||||
ProtocolDescription=Unreal Protocol
|
||||
Name=Player
|
||||
Map=Index.unr
|
||||
LocalMap=DM-Codex.unr
|
||||
Host=
|
||||
Portal=
|
||||
MapExt=unr
|
||||
SaveExt=usa
|
||||
Port=7777
|
||||
Class=Botpack.TMale1
|
||||
|
||||
[FirstRun]
|
||||
FirstRun=0
|
||||
|
||||
[PackageRemap]
|
||||
UnrealShare=UnrealI
|
||||
|
||||
[Engine.Engine]
|
||||
GameRenderDevice=SoftDrv.SoftwareRenderDevice
|
||||
AudioDevice=Galaxy.GalaxyAudioSubsystem
|
||||
NetworkDevice=IpDrv.TcpNetDriver
|
||||
DemoRecordingDevice=Engine.DemoRecDriver
|
||||
Console=UTMenu.UTConsole
|
||||
Language=int
|
||||
GameEngine=Engine.GameEngine
|
||||
EditorEngine=Editor.EditorEngine
|
||||
WindowedRenderDevice=SoftDrv.SoftwareRenderDevice
|
||||
RenderDevice=GlideDrv.GlideRenderDevice
|
||||
DefaultGame=Botpack.DeathMatchPlus
|
||||
DefaultServerGame=Botpack.DeathMatchPlus
|
||||
ViewportManager=WinDrv.WindowsClient
|
||||
Render=Render.Render
|
||||
Input=Engine.Input
|
||||
Canvas=Engine.Canvas
|
||||
|
||||
[Core.System]
|
||||
PurgeCacheDays=30
|
||||
SavePath=../Save
|
||||
CachePath=../Cache
|
||||
CacheExt=.uxx
|
||||
Paths=../System/*.u
|
||||
Paths=../Maps/*.unr
|
||||
Paths=../Textures/*.utx
|
||||
Paths=../Sounds/*.uax
|
||||
Paths=../Music/*.umx
|
||||
Suppress=DevLoad
|
||||
Suppress=DevSave
|
||||
Suppress=DevNetTraffic
|
||||
Suppress=DevGarbage
|
||||
Suppress=DevKill
|
||||
Suppress=DevReplace
|
||||
Suppress=DevSound
|
||||
Suppress=DevCompile
|
||||
Suppress=DevBind
|
||||
Suppress=DevBsp
|
||||
|
||||
[Engine.GameEngine]
|
||||
CacheSizeMegs=4
|
||||
UseSound=True
|
||||
ServerActors=IpDrv.UdpBeacon
|
||||
ServerActors=IpServer.UdpServerQuery
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=master0.gamespy.com MasterServerPort=27900
|
||||
ServerActors=IpServer.UdpServerUplink MasterServerAddress=master.mplayer.com MasterServerPort=27900
|
||||
ServerActors=UWeb.WebServer
|
||||
ServerPackages=SoldierSkins
|
||||
ServerPackages=CommandoSkins
|
||||
ServerPackages=FCommandoSkins
|
||||
ServerPackages=SGirlSkins
|
||||
ServerPackages=BossSkins
|
||||
ServerPackages=Botpack
|
||||
|
||||
[WinDrv.WindowsClient]
|
||||
WindowedViewportX=640
|
||||
WindowedViewportY=480
|
||||
WindowedColorBits=16
|
||||
FullscreenViewportX=640
|
||||
FullscreenViewportY=480
|
||||
FullscreenColorBits=16
|
||||
Brightness=0.500000
|
||||
MipFactor=1.000000
|
||||
UseDirectDraw=True
|
||||
UseJoystick=False
|
||||
CaptureMouse=True
|
||||
StartupFullscreen=True
|
||||
CurvedSurfaces=False
|
||||
LowDetailTextures=False
|
||||
ScreenFlashes=True
|
||||
NoLighting=False
|
||||
SlowVideoBuffering=True
|
||||
DeadZoneXYZ=True
|
||||
DeadZoneRUV=False
|
||||
InvertVertical=False
|
||||
ScaleXYZ=1000.0
|
||||
ScaleRUV=2000.0
|
||||
MinDesiredFrameRate=30.0
|
||||
Decals=True
|
||||
NoDynamicLights=False
|
||||
|
||||
[XDrv.XClient]
|
||||
WindowedViewportX=640
|
||||
WindowedViewportY=480
|
||||
WindowedColorBits=16
|
||||
FullscreenViewportX=640
|
||||
FullscreenViewportY=480
|
||||
FullscreenColorBits=16
|
||||
Brightness=0.500000
|
||||
MipFactor=1.000000
|
||||
SlowVideoBuffering=False
|
||||
StartupFullscreen=True
|
||||
CurvedSurfaces=False
|
||||
CaptureMouse=True
|
||||
LowDetailTextures=False
|
||||
ScreenFlashes=True
|
||||
NoLighting=False
|
||||
DeadZoneXYZ=True
|
||||
DeadZoneRUV=False
|
||||
InvertVertical=False
|
||||
ScaleXYZ=1000.0
|
||||
ScaleRUV=2000.0
|
||||
MinDesiredFrameRate=30.0
|
||||
|
||||
[Engine.Player]
|
||||
ConfiguredInternetSpeed=2600
|
||||
ConfiguredLanSpeed=20000
|
||||
|
||||
[Audio.GenericAudioSubsystem]
|
||||
UseFilter=True
|
||||
UseSurround=False
|
||||
UseStereo=True
|
||||
UseCDMusic=False
|
||||
UseDigitalMusic=False
|
||||
UseSpatial=False
|
||||
UseReverb=False
|
||||
Use3dHardware=False
|
||||
LowSoundQuality=False
|
||||
ReverseStereo=False
|
||||
Latency=40
|
||||
OutputRate=22050Hz
|
||||
Channels=16
|
||||
MusicVolume=160
|
||||
SoundVolume=200
|
||||
AmbientFactor=0.7
|
||||
|
||||
[Galaxy.GalaxyAudioSubsystem]
|
||||
UseDirectSound=True
|
||||
UseFilter=True
|
||||
UseSurround=False
|
||||
UseStereo=True
|
||||
UseCDMusic=False
|
||||
UseDigitalMusic=True
|
||||
UseSpatial=False
|
||||
UseReverb=True
|
||||
Use3dHardware=False
|
||||
LowSoundQuality=False
|
||||
ReverseStereo=False
|
||||
Latency=40
|
||||
OutputRate=22050Hz
|
||||
EffectsChannels=16
|
||||
DopplerSpeed=9000.000000
|
||||
MusicVolume=160
|
||||
SoundVolume=200
|
||||
AmbientFactor=0.700000
|
||||
|
||||
[IpDrv.TcpNetDriver]
|
||||
AllowDownloads=True
|
||||
ConnectionTimeout=15.0
|
||||
InitialConnectTimeout=120.0
|
||||
AckTimeout=1.0
|
||||
KeepAliveTime=0.2
|
||||
MaxClientRate=20000
|
||||
MaxDownloadSize=0
|
||||
SimLatency=0
|
||||
RelevantTimeout=5.0
|
||||
SpawnPrioritySeconds=1.0
|
||||
ServerTravelPause=4.0
|
||||
NetServerMaxTickRate=20
|
||||
LanServerMaxTickRate=35
|
||||
DownloadManagers=IpDrv.HTTPDownload
|
||||
DownloadManagers=Engine.ChannelDownload
|
||||
|
||||
[IpDrv.HTTPDownload]
|
||||
RedirectToURL=http://uz.ut-files.com/
|
||||
ProxyServerHost=
|
||||
ProxyServerPort=3128
|
||||
UseCompression=True
|
||||
|
||||
[Engine.DemoRecDriver]
|
||||
DemoSpectatorClass=Botpack.CHSpectator
|
||||
MaxClientRate=25000
|
||||
ConnectionTimeout=15.0
|
||||
InitialConnectTimeout=500.0
|
||||
AckTimeout=1.0
|
||||
KeepAliveTime=1.0
|
||||
SimLatency=0
|
||||
RelevantTimeout=5.0
|
||||
SpawnPrioritySeconds=1.0
|
||||
ServerTravelPause=4.0
|
||||
NetServerMaxTickRate=60
|
||||
LanServerMaxTickRate=60
|
||||
|
||||
[Engine.GameReplicationInfo]
|
||||
ServerName=Test Server Name FULL
|
||||
ShortName=Test Server Name SHORT
|
||||
AdminName=TestAdminName
|
||||
AdminEmail=TestAdminName@test.com
|
||||
Region=0
|
||||
MOTDLine1=TestMOTDLine1
|
||||
MOTDLine2=TestMOTDLine2
|
||||
MOTDLine3=TestMOTDLine3
|
||||
MOTDLine4=TestMOTDLine4
|
||||
|
||||
[IpDrv.TcpipConnection]
|
||||
SimPacketLoss=0
|
||||
SimLatency=0
|
||||
|
||||
[IpServer.UdpServerQuery]
|
||||
DoUplink=True
|
||||
UpdateMinutes=1
|
||||
MasterServerAddress=unreal.epicgames.com
|
||||
MasterServerPort=27900
|
||||
Region=0
|
||||
|
||||
[IpDrv.UdpBeacon]
|
||||
DoBeacon=True
|
||||
BeaconTime=0.50
|
||||
BeaconTimeout=5.0
|
||||
BeaconProduct=ut
|
||||
|
||||
[SoftDrv.SoftwareRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=False
|
||||
Coronas=False
|
||||
HighDetailActors=False
|
||||
HighResTextureSmooth=True
|
||||
LowResTextureSmooth=False
|
||||
FastTranslucency=True
|
||||
|
||||
[GlideDrv.GlideRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailBias=-1.500000
|
||||
RefreshRate=60Hz
|
||||
DetailTextures=True
|
||||
FastUglyRefresh=False
|
||||
ScreenSmoothing=True
|
||||
Resolution=Default
|
||||
|
||||
[MetalDrv.MetalRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=True
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailTextures=False
|
||||
|
||||
[OpenGLDrv.OpenGLRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
DetailTextures=True
|
||||
|
||||
[D3DDrv.D3DRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=True
|
||||
Coronas=True
|
||||
HighDetailActors=True
|
||||
UseMipmapping=True
|
||||
UseTrilinear=False
|
||||
UseMultitexture=True
|
||||
UsePageFlipping=True
|
||||
UsePalettes=True
|
||||
UseFullscreen=True
|
||||
UseGammaCorrection=True
|
||||
DetailTextures=False
|
||||
Use3dfx=False
|
||||
UseTripleBuffering=True
|
||||
UsePrecache=True
|
||||
Use32BitTextures=False
|
||||
|
||||
[SglDrv.SglRenderDevice]
|
||||
Translucency=True
|
||||
VolumetricLighting=False
|
||||
ShinySurfaces=False
|
||||
Coronas=True
|
||||
HighDetailActors=False
|
||||
ColorDepth=16
|
||||
DetailTextures=False
|
||||
FastUglyRefresh=False
|
||||
TextureDetailBias=Near
|
||||
VertexLighting=False
|
||||
|
||||
[Editor.EditorEngine]
|
||||
UseSound=True
|
||||
CacheSizeMegs=6
|
||||
GridEnabled=True
|
||||
SnapVertices=True
|
||||
SnapDistance=10.000000
|
||||
GridSize=(X=16.000000,Y=16.000000,Z=16.000000)
|
||||
RotGridEnabled=True
|
||||
RotGridSize=(Pitch=1024,Yaw=1024,Roll=1024)
|
||||
GameCommandLine=-log
|
||||
FovAngleDegrees=90.000000
|
||||
GodMode=True
|
||||
AutoSave=False
|
||||
AutoSaveTimeMinutes=5
|
||||
AutoSaveIndex=6
|
||||
C_WorldBox=(R=0,G=0,B=107,A=0)
|
||||
C_GroundPlane=(R=0,G=0,B=63,A=0)
|
||||
C_GroundHighlight=(R=0,G=0,B=127,A=0)
|
||||
C_BrushWire=(R=255,G=63,B=63,A=0)
|
||||
C_Pivot=(R=0,G=255,B=0,A=0)
|
||||
C_Select=(R=0,G=0,B=127,A=0)
|
||||
C_AddWire=(R=127,G=127,B=255,A=0)
|
||||
C_SubtractWire=(R=255,G=192,B=63,A=0)
|
||||
C_GreyWire=(R=163,G=163,B=163,A=0)
|
||||
C_Invalid=(R=163,G=163,B=163,A=0)
|
||||
C_ActorWire=(R=127,G=63,B=0,A=0)
|
||||
C_ActorHiWire=(R=255,G=127,B=0,A=0)
|
||||
C_White=(R=255,G=255,B=255,A=0)
|
||||
C_SemiSolidWire=(R=127,G=255,B=0,A=0)
|
||||
C_NonSolidWire=(R=63,G=192,B=32,A=0)
|
||||
C_WireGridAxis=(R=119,G=119,B=119,A=0)
|
||||
C_ActorArrow=(R=163,G=0,B=0,A=0)
|
||||
C_ScaleBox=(R=151,G=67,B=11,A=0)
|
||||
C_ScaleBoxHi=(R=223,G=149,B=157,A=0)
|
||||
C_Mover=(R=255,G=0,B=255,A=0)
|
||||
C_OrthoBackground=(R=163,G=163,B=163,A=0)
|
||||
C_Current=(R=0,G=0,B=0,A=0)
|
||||
C_BrushVertex=(R=0,G=0,B=0,A=0)
|
||||
C_BrushSnap=(R=0,G=0,B=0,A=0)
|
||||
C_Black=(R=0,G=0,B=0,A=0)
|
||||
C_Mask=(R=0,G=0,B=0,A=0)
|
||||
C_WireBackground=(R=0,G=0,B=0,A=0)
|
||||
C_ZoneWire=(R=0,G=0,B=0,A=0)
|
||||
EditPackages=Core
|
||||
EditPackages=Engine
|
||||
EditPackages=Editor
|
||||
EditPackages=UWindow
|
||||
EditPackages=Fire
|
||||
EditPackages=IpDrv
|
||||
EditPackages=UWeb
|
||||
EditPackages=UBrowser
|
||||
EditPackages=UnrealShare
|
||||
EditPackages=UnrealI
|
||||
EditPackages=UMenu
|
||||
EditPackages=IpServer
|
||||
EditPackages=Botpack
|
||||
EditPackages=UTServerAdmin
|
||||
EditPackages=UTMenu
|
||||
EditPackages=UTBrowser
|
||||
|
||||
[UMenu.UnrealConsole]
|
||||
RootWindow=UMenu.UMenuRootWindow
|
||||
UWindowKey=IK_Esc
|
||||
ShowDesktop=True
|
||||
|
||||
[UMenu.UMenuMenuBar]
|
||||
ShowHelp=True
|
||||
GameUMenuDefault="UTMenu.UTGameMenu"
|
||||
MultiplayerUMenuDefault="UTMenu.UTMultiplayerMenu"
|
||||
OptionsUMenuDefault="UTMenu.UTOptionsMenu"
|
||||
|
||||
[Botpack.ChallengeBotInfo]
|
||||
Difficulty=1
|
||||
|
||||
[Botpack.DeathMatchPlus]
|
||||
bNoviceMode=True
|
||||
bHardCoreMode=True
|
||||
bUseTranslocator=False
|
||||
bCoopWeaponMode=False
|
||||
bForceRespawn=True
|
||||
TimeLimit=323
|
||||
FragLimit=321
|
||||
InitialBots=7
|
||||
MinPlayers=11
|
||||
bTournament=False
|
||||
|
||||
[Botpack.CTFGame]
|
||||
bUseTranslocator=True
|
||||
bCoopWeaponMode=True
|
||||
GoalTeamScore=3
|
||||
bForceRespawn=False
|
||||
TimeLimit=223
|
||||
|
||||
[Botpack.Domination]
|
||||
bDumbDown=True
|
||||
bUseTranslocator=True
|
||||
bCoopWeaponMode=True
|
||||
GoalTeamScore=100
|
||||
bForceRespawn=False
|
||||
TimeLimit=423
|
||||
|
||||
[Botpack.Assault]
|
||||
bUseTranslocator=False
|
||||
bCoopWeaponMode=True
|
||||
bForceRespawn=True
|
||||
TimeLimit=123
|
||||
|
||||
[Botpack.TeamGamePlus]
|
||||
bBalanceTeams=True
|
||||
GoalTeamScore=30
|
||||
bPlayersBalanceTeams=True
|
||||
MaxTeamSize=4
|
||||
|
||||
[Engine.GameInfo]
|
||||
bLowGore=False
|
||||
bVeryLowGore=False
|
||||
MaxSpectators=1
|
||||
MaxPlayers=4
|
||||
ServerLogName=server.log
|
||||
bWorldLog=True
|
||||
bBatchLocal=False
|
||||
DemoBuild=0
|
||||
DemoHasTuts=0
|
||||
PlayerViewDelay=1.000000
|
||||
PlayerSpeechDelay=0.300000
|
||||
PlayerTauntDelay=2.000000
|
||||
bLogAdminActions=False
|
||||
LoginDelaySeconds=0.000000
|
||||
MaxLoginAttempts=0
|
||||
ActionToTake=DO_Nothing
|
||||
IPPolicies[0]=ACCEPT,*
|
||||
IPPolicies[1]=
|
||||
GamePassword=TestPwd
|
||||
|
||||
[UnrealShare.UnrealGameOptionsMenu]
|
||||
bCanModifyGore=True
|
||||
|
||||
[UBrowser.UBrowserMainClientWindow]
|
||||
LANTabName=UBrowserLAN
|
||||
ServerListNames[0]=UBrowserUT
|
||||
ServerListNames[1]=UBrowserLAN
|
||||
ServerListNames[2]=UBrowserPopulated
|
||||
ServerListNames[3]=UBrowserDeathmatch
|
||||
ServerListNames[4]=UBrowserTeamGames
|
||||
ServerListNames[5]=UBrowserCTF
|
||||
ServerListNames[6]=UBrowserDOM
|
||||
ServerListNames[7]=UBrowserAS
|
||||
ServerListNames[8]=UBrowserLMS
|
||||
ServerListNames[9]=UBrowserAll
|
||||
ServerListNames[10]=None
|
||||
ServerListNames[11]=None
|
||||
ServerListNames[12]=None
|
||||
ServerListNames[13]=None
|
||||
ServerListNames[14]=None
|
||||
ServerListNames[15]=None
|
||||
ServerListNames[16]=None
|
||||
ServerListNames[17]=None
|
||||
ServerListNames[18]=None
|
||||
ServerListNames[19]=None
|
||||
|
||||
[UBrowserUT]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserLAN]
|
||||
ListFactories[0]=UBrowser.UBrowserLocalFact,BeaconProduct=ut
|
||||
URLAppend=?LAN
|
||||
AutoRefreshTime=10
|
||||
bNoAutoSort=True
|
||||
|
||||
[UBrowserPopulated]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,MinPlayers=1,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserDeathmatch]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=DeathMatchPlus,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserTeamGames]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=TeamGamePlus,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserCTF]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=CTFGame,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserDOM]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=Domination,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserAS]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=Assault,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserLMS]
|
||||
ListFactories[0]=UBrowser.UBrowserSubsetFact,SupersetTag=UBrowserAll,GameType=LastManStanding,bCompatibleServersOnly=True
|
||||
|
||||
[UBrowserAll]
|
||||
ListFactories[0]=UBrowser.UBrowserGSpyFact,MasterServerAddress=unreal.epicgames.com,MasterServerTCPPort=28900,Region=0,GameName=ut
|
||||
ListFactories[1]=UBrowser.UBrowserGSpyFact,MasterServerAddress=master0.gamespy.com,MasterServerTCPPort=28900,Region=0,GameName=ut
|
||||
bHidden=True
|
||||
bFallbackFactories=True
|
||||
|
||||
[UTMenu.UTMultiplayerMenu]
|
||||
OnlineServices[0]=LOCALIZE,MPlayer
|
||||
OnlineServices[1]=LOCALIZE,Heat
|
||||
OnlineServices[2]=LOCALIZE,WON
|
||||
|
||||
[UWeb.WebServer]
|
||||
Applications[0]=UTServerAdmin.UTServerAdmin
|
||||
ApplicationPaths[0]=/ServerAdmin
|
||||
Applications[1]=UTServerAdmin.UTImageServer
|
||||
ApplicationPaths[1]=/images
|
||||
DefaultApplication=0
|
||||
bEnabled=True
|
||||
ListenPort=9999
|
||||
MaxConnections=30
|
||||
|
||||
[UBrowser.UBrowserHTTPClient]
|
||||
ProxyServerAddress=
|
||||
ProxyServerPort=
|
||||
|
||||
[UTServerAdmin.UTServerAdmin]
|
||||
AdminUsername=TestAdminUser
|
||||
AdminPassword=TestAdminPwd
|
||||
|
||||
30
test/test_gen.py
Normal file
30
test/test_gen.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# pygamecfg (c) by chacha
|
||||
#
|
||||
# pygamecfg is licensed under a
|
||||
# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
#
|
||||
# You should have received a copy of the license along with this
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
|
||||
from src import pygamecfg
|
||||
from src.pygamecfg.__main__ import fct_main
|
||||
|
||||
|
||||
class Testtest_gen(unittest.TestCase):
|
||||
def test_version(self):
|
||||
self.assertNotEqual(pygamecfg.__version__, "?.?.?")
|
||||
|
||||
def test_normal_help(self):
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
fct_main(["-h"])
|
||||
|
||||
def test_defect_nogame(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
fct_main(["GetOption", "test"])
|
||||
self.assertIn("pygamecfg: error: the following arguments are required: -g/--game", capted_stderr.getvalue())
|
||||
self.assertIn("", capted_stdout.getvalue())
|
||||
@@ -7,26 +7,303 @@
|
||||
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout,redirect_stderr
|
||||
|
||||
print(__name__)
|
||||
print(__package__)
|
||||
from os import linesep
|
||||
from io import StringIO
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
|
||||
from src import pygamecfg
|
||||
from src.pygamecfg.__main__ import fct_main
|
||||
|
||||
class Testtest_module(unittest.TestCase):
|
||||
def test_version(self):
|
||||
self.assertNotEqual(pygamecfg.__version__,"?.?.?")
|
||||
|
||||
def test_test_module(self):
|
||||
|
||||
class Testtest_ut99(unittest.TestCase):
|
||||
def test_normal_ServerPackages(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
self.assertEqual(pygamecfg.test_function(41),42)
|
||||
|
||||
self.assertEqual(len(capted_stderr.getvalue()),0)
|
||||
self.assertEqual(capted_stdout.getvalue().strip(),"Hello world !")
|
||||
self.assertEqual(len(capted_stderr.getvalue()),0)
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "ServerPackages"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual(
|
||||
"['SoldierSkins', 'CommandoSkins', 'FCommandoSkins', 'SGirlSkins', 'BossSkins', 'Botpack']\n", capted_stdout.getvalue()
|
||||
)
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_ServerActors(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "ServerActors"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual(
|
||||
"['IpDrv.UdpBeacon', 'IpServer.UdpServerQuery', 'IpServer.UdpServerUplink MasterServerAddress=unreal.epicgames.com MasterServerPort=27900', 'IpServer.UdpServerUplink MasterServerAddress=master0.gamespy.com MasterServerPort=27900', 'IpServer.UdpServerUplink MasterServerAddress=master.mplayer.com MasterServerPort=27900', 'UWeb.WebServer']\n",
|
||||
capted_stdout.getvalue(),
|
||||
)
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
|
||||
def test_normal_Port(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "Port"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("7777\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_Map(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "Map"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("Index.unr\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_GameType(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "GameType"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("Botpack.DeathMatchPlus\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_HostName(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "HostName"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("Test Server Name FULL\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MOTD(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MOTD"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestMOTDLine1\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MOTD2(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MOTD2"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestMOTDLine2\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MOTD3(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MOTD3"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestMOTDLine3\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MOTD4(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MOTD4"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestMOTDLine4\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AdminEmail(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AdminEmail"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestAdminName@test.com\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AdminName(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AdminName"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestAdminName\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_HTTPDownloadServer(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "HTTPDownloadServer"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("http://uz.ut-files.com/\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MaxClientRate(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MaxClientRate"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("20000\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_NetServerMaxTickRate(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "NetServerMaxTickRate"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("20\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_LanServerMaxTickRate(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "LanServerMaxTickRate"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("35\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AdminPassword(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AdminPassword"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestAdminPwd\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_GamePassword(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "GamePassword"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("TestPwd\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MaxPlayers(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MaxPlayers"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("4\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MaxSpectators(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MaxSpectators"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("1\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AS_TimeLimit(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AS_TimeLimit"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("123\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DOM_TimeLimit(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DOM_TimeLimit"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("423\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_CTF_TimeLimit(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "CTF_TimeLimit"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("223\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DM_TimeLimit(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DM_TimeLimit"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("323\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_GoalTeamScore(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "GoalTeamScore"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("30\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MaxTeamSize(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MaxTeamSize"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("4\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DM_FragLimit(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DM_FragLimit"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("321\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_ServerLogName(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "ServerLogName"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("server.log\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_WebServer(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "WebServer"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("9999\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_TournamentMode(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "TournamentMode"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("False\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_InitialBots(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "InitialBots"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("7\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_MinPlayers(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "MinPlayers"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("11\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AS_UseTranslocator(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AS_UseTranslocator"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("True\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_CTF_UseTranslocator(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "CTF_UseTranslocator"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("True\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DM_UseTranslocator(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DM_UseTranslocator"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("False\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DOM_UseTranslocator(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DOM_UseTranslocator"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("True\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_CTF_ForceRespawn(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "CTF_ForceRespawn"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("False\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DM_ForceRespawn(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DM_ForceRespawn"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("True\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_DOM_ForceRespawn(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "DOM_ForceRespawn"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("False\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_AS_ForceRespawn(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "GetOption", "AS_ForceRespawn"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("True\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
def test_normal_customcfgfile_HostName(self):
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr:
|
||||
fct_main(["-g", "ut99", "-b", "test/data/UT99", "-c", "System/UT99.ini", "GetOption", "HostName"])
|
||||
# /!\ add '\n' at the end of the string cause Python terminal newline is always this, regardless Windows / Linux os.linesep
|
||||
self.assertEqual("Alt Serv Name FULL\n", capted_stdout.getvalue())
|
||||
self.assertEqual("", capted_stderr.getvalue())
|
||||
|
||||
Reference in New Issue
Block a user