trainerbase 4.4.1__tar.gz → 4.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {trainerbase-4.4.1 → trainerbase-4.5.1}/PKG-INFO +3 -2
- {trainerbase-4.4.1 → trainerbase-4.5.1}/pyproject.toml +4 -3
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/codeinjection.py +2 -1
- trainerbase-4.5.1/trainerbase/config.py +56 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/teleport.py +38 -6
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/logger.py +3 -6
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/process.py +7 -7
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/speedhack.py +4 -3
- trainerbase-4.4.1/trainerbase/config.py +0 -29
- {trainerbase-4.4.1 → trainerbase-4.5.1}/.gitignore +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/LICENSE +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/README.md +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/__init__.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/abc.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/__init__.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/abc.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/helpers.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/keyboard.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/rainbow.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/tapper.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/common/teleport.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gameobject.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/__init__.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/helpers.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/injections.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/misc.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/objects.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/rainbow.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/scripts.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/speedhack.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/tapper.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/gui/types.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/main.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/memory.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/py.typed +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/scriptengine.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase/tts.py +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase_vendor/FASM.EXE +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase_vendor/speedhack32.dll +0 -0
- {trainerbase-4.4.1 → trainerbase-4.5.1}/trainerbase_vendor/speedhack64.dll +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trainerbase
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.5.1
|
|
4
4
|
Summary: Framework for creating game trainers/mods
|
|
5
5
|
Project-URL: Homepage, https://gitlab.com/python-trainers/
|
|
6
6
|
Project-URL: Repository, https://gitlab.com/python-trainers/trainer-base
|
|
@@ -13,7 +13,8 @@ Requires-Python: >=3.13
|
|
|
13
13
|
Requires-Dist: dearpygui>=2.0.0
|
|
14
14
|
Requires-Dist: keyboard>=0.13.5
|
|
15
15
|
Requires-Dist: mouse>=0.7.1
|
|
16
|
-
Requires-Dist: psutil>=
|
|
16
|
+
Requires-Dist: psutil>=7.0.0
|
|
17
|
+
Requires-Dist: pydantic>=2.10.6
|
|
17
18
|
Requires-Dist: pyinjector>=1.3.0
|
|
18
19
|
Requires-Dist: pymem>=1.14.0
|
|
19
20
|
Requires-Dist: pyttsx3>=2.98
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "trainerbase"
|
|
3
|
-
version = "4.
|
|
3
|
+
version = "4.5.1"
|
|
4
4
|
description = "Framework for creating game trainers/mods"
|
|
5
5
|
license = "MIT"
|
|
6
6
|
authors = [
|
|
@@ -13,7 +13,8 @@ dependencies = [
|
|
|
13
13
|
"dearpygui>=2.0.0",
|
|
14
14
|
"keyboard>=0.13.5",
|
|
15
15
|
"mouse>=0.7.1",
|
|
16
|
-
"psutil>=
|
|
16
|
+
"psutil>=7.0.0",
|
|
17
|
+
"pydantic>=2.10.6",
|
|
17
18
|
"pyinjector>=1.3.0",
|
|
18
19
|
"pymem>=1.14.0",
|
|
19
20
|
"pyttsx3>=2.98",
|
|
@@ -73,5 +74,5 @@ build-backend = "hatchling.build"
|
|
|
73
74
|
|
|
74
75
|
[dependency-groups]
|
|
75
76
|
dev = [
|
|
76
|
-
"ruff>=0.
|
|
77
|
+
"ruff>=0.9.7",
|
|
77
78
|
]
|
|
@@ -8,12 +8,13 @@ from typing import ClassVar, Final, Self, override
|
|
|
8
8
|
|
|
9
9
|
from pymem.exception import MemoryWriteError
|
|
10
10
|
|
|
11
|
+
from trainerbase.config import config
|
|
11
12
|
from trainerbase.logger import logger
|
|
12
13
|
from trainerbase.memory import ARCH, ConvertibleToAddress, allocate, ensure_address
|
|
13
14
|
from trainerbase.process import pm
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
FASM_EXECUTABLE_PATH: Final[Path] =
|
|
17
|
+
FASM_EXECUTABLE_PATH: Final[Path] = config.vendor.folder / "FASM.EXE"
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
type Code = bytes | str
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from tomllib import load as load_toml
|
|
3
|
+
from typing import Any, Final
|
|
4
|
+
|
|
5
|
+
from pydantic import AliasChoices, BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
CONFIG_FILE: Final[Path] = Path("./trainerbase.toml")
|
|
9
|
+
|
|
10
|
+
DEFAULT_VENDOR_FOLDER_PATHS: Final[list[Path]] = [
|
|
11
|
+
Path(__file__).resolve().parent.parent / "trainerbase_vendor",
|
|
12
|
+
Path().resolve() / "trainerbase_vendor",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Process(BaseModel):
|
|
17
|
+
names: list[str] = Field(alias=AliasChoices("names", "process_names"))
|
|
18
|
+
exact_match: bool = True
|
|
19
|
+
ignore_case: bool = False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SpeedhackConfig(BaseModel):
|
|
23
|
+
offset_x64: int = 0x47098
|
|
24
|
+
offset_x32: int = 0x40058
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Vendor(BaseModel):
|
|
28
|
+
extra_search_paths: list[Path] | None = None
|
|
29
|
+
speedhack: SpeedhackConfig = SpeedhackConfig()
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def folder(self) -> Path:
|
|
33
|
+
search_paths = DEFAULT_VENDOR_FOLDER_PATHS.copy()
|
|
34
|
+
|
|
35
|
+
if self.extra_search_paths is not None:
|
|
36
|
+
search_paths.extend(self.extra_search_paths)
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
path = next(filter(Path.is_dir, search_paths))
|
|
40
|
+
except StopIteration as e:
|
|
41
|
+
raise ValueError("Failed to find Trainer Base vendor folder") from e
|
|
42
|
+
|
|
43
|
+
return path.resolve()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Config(BaseModel):
|
|
47
|
+
process: Process = Field(alias=AliasChoices("process", "pymem"))
|
|
48
|
+
vendor: Vendor | None = Vendor()
|
|
49
|
+
logging: dict[str, Any] | None = None # Must be managed by logging.dictConfig
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
with CONFIG_FILE.resolve().open("rb") as trainerbase_toml:
|
|
53
|
+
trainerbase_config = load_toml(trainerbase_toml)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
config = Config.model_validate(trainerbase_config)
|
|
@@ -16,6 +16,9 @@ from trainerbase.tts import say
|
|
|
16
16
|
class TeleportUI(AbstractUIComponent):
|
|
17
17
|
DPG_TAG_TELEPORT_LABELS = "__teleport_labels"
|
|
18
18
|
DPG_TAG_TELEPORT_LABEL_FILTER_INPUT = "__dpg_tag_teleport_label_filter_input"
|
|
19
|
+
POSITION_ID_MANUAL_PRIMARY = "__position_id_manual_primary"
|
|
20
|
+
POSITION_ID_MANUAL_SECONDARY = "__position_id_manual_secondary"
|
|
21
|
+
POSITION_ID_BEFORE_DASH = "__position_id_before_dash"
|
|
19
22
|
|
|
20
23
|
def __init__(
|
|
21
24
|
self,
|
|
@@ -24,6 +27,7 @@ class TeleportUI(AbstractUIComponent):
|
|
|
24
27
|
hotkey_set_saved_position: str | None = "Home",
|
|
25
28
|
hotkey_dash: str | None = "End",
|
|
26
29
|
hotkey_secondary_position_modifier: str = "Shift",
|
|
30
|
+
hotkey_dash_rollback: str = "Shift+End",
|
|
27
31
|
*,
|
|
28
32
|
tts_on_hotkey: bool = True,
|
|
29
33
|
):
|
|
@@ -32,6 +36,7 @@ class TeleportUI(AbstractUIComponent):
|
|
|
32
36
|
self.hotkey_set_saved_position = hotkey_set_saved_position
|
|
33
37
|
self.hotkey_secondary_position_modifier = hotkey_secondary_position_modifier
|
|
34
38
|
self.hotkey_dash = hotkey_dash
|
|
39
|
+
self.hotkey_dash_rollback = hotkey_dash_rollback
|
|
35
40
|
self.tts_on_hotkey = tts_on_hotkey
|
|
36
41
|
|
|
37
42
|
@override
|
|
@@ -69,10 +74,19 @@ class TeleportUI(AbstractUIComponent):
|
|
|
69
74
|
|
|
70
75
|
@suppress_memory_exceptions
|
|
71
76
|
def on_hotkey_dash_press(self):
|
|
77
|
+
self.tp.save_position(self.POSITION_ID_BEFORE_DASH)
|
|
72
78
|
self.tp.dash()
|
|
79
|
+
|
|
73
80
|
if self.tts_on_hotkey:
|
|
74
81
|
say("Dash!")
|
|
75
82
|
|
|
83
|
+
@suppress_memory_exceptions
|
|
84
|
+
def on_hotkey_dash_rollback_press(self):
|
|
85
|
+
self.tp.restore_saved_position(self.POSITION_ID_BEFORE_DASH)
|
|
86
|
+
|
|
87
|
+
if self.tts_on_hotkey:
|
|
88
|
+
say("Dash Rollback!")
|
|
89
|
+
|
|
76
90
|
@suppress_memory_exceptions
|
|
77
91
|
def on_goto_label(self):
|
|
78
92
|
self.tp.goto(dpg.get_value(self.DPG_TAG_TELEPORT_LABELS))
|
|
@@ -81,8 +95,14 @@ class TeleportUI(AbstractUIComponent):
|
|
|
81
95
|
if self.hotkey_save_position is None or self.hotkey_set_saved_position is None:
|
|
82
96
|
return
|
|
83
97
|
|
|
84
|
-
add_hotkey(
|
|
85
|
-
|
|
98
|
+
add_hotkey(
|
|
99
|
+
self.hotkey_save_position,
|
|
100
|
+
partial(self.on_hotkey_save_position_press, self.POSITION_ID_MANUAL_PRIMARY),
|
|
101
|
+
)
|
|
102
|
+
add_hotkey(
|
|
103
|
+
self.hotkey_set_saved_position,
|
|
104
|
+
partial(self.on_hotkey_set_saved_position_press, self.POSITION_ID_MANUAL_PRIMARY),
|
|
105
|
+
)
|
|
86
106
|
|
|
87
107
|
hotkey_secondary_position_hint = ""
|
|
88
108
|
if self.hotkey_secondary_position_modifier:
|
|
@@ -91,8 +111,14 @@ class TeleportUI(AbstractUIComponent):
|
|
|
91
111
|
f"{self.hotkey_secondary_position_modifier} + {self.hotkey_set_saved_position}"
|
|
92
112
|
)
|
|
93
113
|
hotkey_secondary_position_hint = f"[{self.hotkey_secondary_position_modifier} +] "
|
|
94
|
-
add_hotkey(
|
|
95
|
-
|
|
114
|
+
add_hotkey(
|
|
115
|
+
hotkey_save_secondary_position,
|
|
116
|
+
partial(self.on_hotkey_save_position_press, self.POSITION_ID_MANUAL_SECONDARY),
|
|
117
|
+
)
|
|
118
|
+
add_hotkey(
|
|
119
|
+
hotkey_set_secondary_saved_position,
|
|
120
|
+
partial(self.on_hotkey_set_saved_position_press, self.POSITION_ID_MANUAL_SECONDARY),
|
|
121
|
+
)
|
|
96
122
|
|
|
97
123
|
dpg.add_text(f"[{hotkey_secondary_position_hint}{self.hotkey_save_position}] Save Position")
|
|
98
124
|
dpg.add_text(f"[{hotkey_secondary_position_hint}{self.hotkey_set_saved_position}] Restore Position")
|
|
@@ -101,9 +127,15 @@ class TeleportUI(AbstractUIComponent):
|
|
|
101
127
|
if self.hotkey_dash is None:
|
|
102
128
|
return
|
|
103
129
|
|
|
104
|
-
|
|
130
|
+
with dpg.group(horizontal=True):
|
|
131
|
+
add_hotkey(self.hotkey_dash, self.on_hotkey_dash_press)
|
|
132
|
+
dpg.add_text(f"[{self.hotkey_dash}] Dash")
|
|
133
|
+
|
|
134
|
+
if self.hotkey_dash_rollback is None:
|
|
135
|
+
return
|
|
105
136
|
|
|
106
|
-
|
|
137
|
+
add_hotkey(self.hotkey_dash_rollback, self.on_hotkey_dash_rollback_press)
|
|
138
|
+
dpg.add_text(f"/ [{self.hotkey_dash_rollback}] Dash Rollback")
|
|
107
139
|
|
|
108
140
|
def _tp_add_labels_if_needed(self):
|
|
109
141
|
if not self.tp.labels:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from logging import ERROR, getLogger
|
|
2
2
|
from logging.config import dictConfig
|
|
3
3
|
|
|
4
|
-
from trainerbase.config import CONFIG_FILE,
|
|
4
|
+
from trainerbase.config import CONFIG_FILE, config
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
if
|
|
7
|
+
if config.logging is None:
|
|
8
8
|
logging_config = {
|
|
9
9
|
"version": 1,
|
|
10
10
|
"disable_existing_loggers": True,
|
|
@@ -28,9 +28,9 @@ if logging_config is None:
|
|
|
28
28
|
}
|
|
29
29
|
using_default_config = True
|
|
30
30
|
else:
|
|
31
|
+
logging_config = config.logging
|
|
31
32
|
using_default_config = False
|
|
32
33
|
|
|
33
|
-
|
|
34
34
|
dictConfig(logging_config)
|
|
35
35
|
getLogger("comtypes").setLevel(ERROR)
|
|
36
36
|
|
|
@@ -38,6 +38,3 @@ logger = getLogger("TrainerBase")
|
|
|
38
38
|
|
|
39
39
|
if using_default_config:
|
|
40
40
|
logger.debug(f"No logging config in {CONFIG_FILE}! Using default one.")
|
|
41
|
-
|
|
42
|
-
for warning_message in config_warnings:
|
|
43
|
-
logger.warning(warning_message)
|
|
@@ -9,7 +9,7 @@ from psutil import Process, pid_exists, process_iter
|
|
|
9
9
|
from pymem import Pymem
|
|
10
10
|
from pymem.exception import ProcessError
|
|
11
11
|
|
|
12
|
-
from trainerbase.config import
|
|
12
|
+
from trainerbase.config import config
|
|
13
13
|
from trainerbase.logger import logger
|
|
14
14
|
|
|
15
15
|
|
|
@@ -70,15 +70,15 @@ def ensure_main_module_is_initialized(pm: Pymem) -> int:
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
def attach_to_process() -> Pymem:
|
|
73
|
-
|
|
74
|
-
exact_match = process_config["exact_match"]
|
|
75
|
-
ignore_case = process_config["ignore_case"]
|
|
76
|
-
|
|
77
|
-
if not process_names:
|
|
73
|
+
if not config.process.names:
|
|
78
74
|
raise ValueError("Empty process name list")
|
|
79
75
|
|
|
80
76
|
with suppress(KeyboardInterrupt):
|
|
81
|
-
pid = get_target_pid(
|
|
77
|
+
pid = get_target_pid(
|
|
78
|
+
config.process.names,
|
|
79
|
+
exact_match=config.process.exact_match,
|
|
80
|
+
ignore_case=config.process.ignore_case,
|
|
81
|
+
)
|
|
82
82
|
|
|
83
83
|
pm = Pymem(pid)
|
|
84
84
|
ensure_main_module_is_initialized(pm)
|
|
@@ -5,16 +5,17 @@ from typing import Final, Self, cast
|
|
|
5
5
|
from pyinjector import inject
|
|
6
6
|
from pymem.exception import MemoryWriteError
|
|
7
7
|
|
|
8
|
+
from trainerbase.config import config
|
|
8
9
|
from trainerbase.gameobject import GameDouble
|
|
9
10
|
from trainerbase.memory import ARCH, get_module_address
|
|
10
11
|
from trainerbase.process import pm
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
SPEEDHACK_DLL_MODULE_NAME: Final[str] = f"speedhack{ARCH}.dll"
|
|
14
|
-
SPEEDHACK_DLL_PATH: Final[Path] =
|
|
15
|
-
|
|
15
|
+
SPEEDHACK_DLL_PATH: Final[Path] = config.vendor.folder / SPEEDHACK_DLL_MODULE_NAME
|
|
16
|
+
SPEED_MODIFIER_OFFSET: Final[int] = (
|
|
17
|
+
config.vendor.speedhack.offset_x32 if ARCH == 32 else config.vendor.speedhack.offset_x64
|
|
16
18
|
)
|
|
17
|
-
SPEED_MODIFIER_OFFSET: Final[int] = 0x40058 if ARCH == 32 else 0x47098
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class SpeedHack:
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from tomllib import load as load_toml
|
|
3
|
-
from typing import Final
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
CONFIG_FILE: Final[Path] = Path("./trainerbase.toml")
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
with CONFIG_FILE.resolve().open("rb") as trainerbase_toml:
|
|
10
|
-
trainerbase_config = load_toml(trainerbase_toml)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
config_warnings = []
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
try:
|
|
17
|
-
process_config = trainerbase_config["process"]
|
|
18
|
-
except KeyError:
|
|
19
|
-
# Legacy section support
|
|
20
|
-
process_config = trainerbase_config["pymem"]
|
|
21
|
-
process_config["names"] = process_config["process_names"]
|
|
22
|
-
del trainerbase_config["pymem"]
|
|
23
|
-
|
|
24
|
-
config_warnings.append(
|
|
25
|
-
"Deprecated config! Use [process] section with field `names` instead of [pymem] with `process_names`"
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
logging_config = trainerbase_config.get("logging")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|