trainerbase 3.16.2__tar.gz → 4.0.0__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-3.16.2 → trainerbase-4.0.0}/PKG-INFO +3 -2
- {trainerbase-3.16.2 → trainerbase-4.0.0}/pyproject.toml +4 -3
- trainerbase-4.0.0/trainerbase/common/abc.py +18 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/common/keyboard.py +1 -15
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/common/rainbow.py +5 -1
- trainerbase-4.0.0/trainerbase/common/tapper.py +56 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/common/teleport.py +2 -2
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gameobject.py +1 -1
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/scripts.py +3 -3
- trainerbase-4.0.0/trainerbase/gui/tapper.py +71 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/main.py +6 -6
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/memory.py +18 -6
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/process.py +6 -13
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/scriptengine.py +35 -13
- {trainerbase-3.16.2 → trainerbase-4.0.0}/LICENSE +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/README.md +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/__init__.py +0 -0
- {trainerbase-3.16.2/trainerbase/common → trainerbase-4.0.0/trainerbase}/abc.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/codeinjection.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/common/__init__.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/common/helpers.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/config.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/__init__.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/helpers.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/injections.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/misc.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/objects.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/rainbow.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/speedhack.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/teleport.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/gui/types.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/speedhack.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase/tts.py +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase_vendor/FASM.EXE +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase_vendor/speedhack32.dll +0 -0
- {trainerbase-3.16.2 → trainerbase-4.0.0}/trainerbase_vendor/speedhack64.dll +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: trainerbase
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Framework for creating game trainers/mods
|
|
5
5
|
Home-page: https://gitlab.com/python-trainers/trainer-base
|
|
6
6
|
License: MIT
|
|
@@ -12,10 +12,11 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Requires-Dist: dearpygui (>=1.11.1,<2.0.0)
|
|
14
14
|
Requires-Dist: keyboard (>=0.13.5,<0.14.0)
|
|
15
|
+
Requires-Dist: mouse (>=0.7.1,<0.8.0)
|
|
15
16
|
Requires-Dist: psutil (>=6.0.0,<7.0.0)
|
|
16
17
|
Requires-Dist: pyinjector (>=1.3.0,<2.0.0)
|
|
17
18
|
Requires-Dist: pymem (>=1.13.1,<2.0.0)
|
|
18
|
-
Requires-Dist: pyttsx3 (>=2.
|
|
19
|
+
Requires-Dist: pyttsx3 (>=2.98,<3.0)
|
|
19
20
|
Project-URL: Repository, https://gitlab.com/python-trainers/trainer-base
|
|
20
21
|
Description-Content-Type: text/markdown
|
|
21
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "trainerbase"
|
|
3
|
-
version = "
|
|
3
|
+
version = "4.0.0"
|
|
4
4
|
description = "Framework for creating game trainers/mods"
|
|
5
5
|
authors = ["v01d <v01d@v01d.ru>", "doomayka <zd@doomayka.ru>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -17,7 +17,7 @@ include = [
|
|
|
17
17
|
]
|
|
18
18
|
|
|
19
19
|
[tool.poetry.group.dev.dependencies]
|
|
20
|
-
ruff = "^0.
|
|
20
|
+
ruff = "^0.6.8"
|
|
21
21
|
|
|
22
22
|
[tool.ruff]
|
|
23
23
|
src = ["trainerbase"]
|
|
@@ -51,9 +51,10 @@ python = "^3.12"
|
|
|
51
51
|
pymem = "^1.13.1"
|
|
52
52
|
dearpygui = "^1.11.1"
|
|
53
53
|
keyboard = "^0.13.5"
|
|
54
|
-
pyttsx3 = "^2.
|
|
54
|
+
pyttsx3 = "^2.98"
|
|
55
55
|
pyinjector = "^1.3.0"
|
|
56
56
|
psutil = "^6.0.0"
|
|
57
|
+
mouse = "^0.7.1"
|
|
57
58
|
|
|
58
59
|
[build-system]
|
|
59
60
|
requires = ["poetry-core"]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import override
|
|
3
|
+
|
|
4
|
+
from trainerbase.abc import Switchable
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SimpleSwitchable(Switchable):
|
|
8
|
+
def __init__(self, on_enabled: Callable[[], None], on_disabled: Callable[[], None]):
|
|
9
|
+
self._on_enabled = on_enabled
|
|
10
|
+
self._on_disabled = on_disabled
|
|
11
|
+
|
|
12
|
+
@override
|
|
13
|
+
def enable(self):
|
|
14
|
+
self._on_enabled()
|
|
15
|
+
|
|
16
|
+
@override
|
|
17
|
+
def disable(self):
|
|
18
|
+
self._on_disabled()
|
|
@@ -4,24 +4,10 @@ from typing import override
|
|
|
4
4
|
|
|
5
5
|
from keyboard import add_hotkey, on_press_key, on_release_key
|
|
6
6
|
|
|
7
|
-
from trainerbase.
|
|
7
|
+
from trainerbase.abc import AbstractKeyboardHandler, Switchable
|
|
8
8
|
from trainerbase.gameobject import GameBool
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class SimpleSwitchable(Switchable):
|
|
12
|
-
def __init__(self, on_enabled: Callable[[], None], on_disabled: Callable[[], None]):
|
|
13
|
-
self._on_enabled = on_enabled
|
|
14
|
-
self._on_disabled = on_disabled
|
|
15
|
-
|
|
16
|
-
@override
|
|
17
|
-
def enable(self):
|
|
18
|
-
self._on_enabled()
|
|
19
|
-
|
|
20
|
-
@override
|
|
21
|
-
def disable(self):
|
|
22
|
-
self._on_disabled()
|
|
23
|
-
|
|
24
|
-
|
|
25
11
|
class SimpleHotkeyHandler(AbstractKeyboardHandler):
|
|
26
12
|
def __init__(self, callback: Callable[[], None], hotkey: str):
|
|
27
13
|
self.callback = callback
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
from collections.abc import Iterable, Iterator
|
|
2
2
|
from itertools import cycle
|
|
3
|
+
from typing import override
|
|
3
4
|
|
|
4
5
|
from dearpygui import dearpygui as dpg
|
|
5
6
|
|
|
7
|
+
from trainerbase.scriptengine import AbstractBaseScript
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
type TagList = list[int | str]
|
|
8
11
|
type Color = tuple[int, int, int]
|
|
9
12
|
type Colors = Iterable[Color]
|
|
10
13
|
|
|
11
14
|
|
|
12
|
-
class GradientUpdater:
|
|
15
|
+
class GradientUpdater(AbstractBaseScript):
|
|
13
16
|
def __init__(self):
|
|
14
17
|
self.tags: TagList | None = None
|
|
15
18
|
self.colors: list[Color] | None = None
|
|
@@ -18,6 +21,7 @@ class GradientUpdater:
|
|
|
18
21
|
self.initial_delta: tuple[int, int, int] | None = None
|
|
19
22
|
self.color_length: int | None = None
|
|
20
23
|
|
|
24
|
+
@override
|
|
21
25
|
def __call__(self):
|
|
22
26
|
if self.tags is None or self.colors is None:
|
|
23
27
|
raise RuntimeError("Call setup(...)")
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from enum import StrEnum, auto
|
|
3
|
+
from functools import partial
|
|
4
|
+
from typing import assert_never, override
|
|
5
|
+
|
|
6
|
+
from keyboard import send
|
|
7
|
+
from mouse import click
|
|
8
|
+
|
|
9
|
+
from trainerbase.abc import Switchable
|
|
10
|
+
from trainerbase.scriptengine import ScriptEngine
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TappingDevice(StrEnum):
|
|
14
|
+
MOUSE = auto()
|
|
15
|
+
KEYBOARD = auto()
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def function(self) -> Callable[[str], None]:
|
|
19
|
+
match self:
|
|
20
|
+
case self.MOUSE:
|
|
21
|
+
return click
|
|
22
|
+
case self.KEYBOARD:
|
|
23
|
+
return send
|
|
24
|
+
case _:
|
|
25
|
+
assert_never(self)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Tapper(Switchable):
|
|
29
|
+
def __init__(self, default_delay: float, tap_button: str = "left", device: TappingDevice = TappingDevice.MOUSE):
|
|
30
|
+
self._delay = default_delay
|
|
31
|
+
self.tapper_script_engine: ScriptEngine | None = None
|
|
32
|
+
self.tapper_function = partial(device.function, tap_button)
|
|
33
|
+
|
|
34
|
+
@override
|
|
35
|
+
def enable(self):
|
|
36
|
+
self.disable()
|
|
37
|
+
|
|
38
|
+
self.tapper_script_engine = ScriptEngine(self._delay)
|
|
39
|
+
self.tapper_script_engine.simple_script(self.tapper_function, enabled=True)
|
|
40
|
+
self.tapper_script_engine.start()
|
|
41
|
+
|
|
42
|
+
@override
|
|
43
|
+
def disable(self):
|
|
44
|
+
if self.tapper_script_engine is not None:
|
|
45
|
+
self.tapper_script_engine.stop()
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def delay(self):
|
|
49
|
+
return self._delay
|
|
50
|
+
|
|
51
|
+
@delay.setter
|
|
52
|
+
def delay(self, new_delay: float):
|
|
53
|
+
if self.tapper_script_engine is not None:
|
|
54
|
+
self.tapper_script_engine.delay = new_delay
|
|
55
|
+
|
|
56
|
+
self._delay = new_delay
|
|
@@ -8,7 +8,7 @@ from pymem.exception import MemoryReadError
|
|
|
8
8
|
|
|
9
9
|
from trainerbase.common.helpers import Number
|
|
10
10
|
from trainerbase.gameobject import GameObject
|
|
11
|
-
from trainerbase.scriptengine import
|
|
11
|
+
from trainerbase.scriptengine import system_script_engine
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
type Coords[T: (int, float)] = tuple[T, T, T]
|
|
@@ -74,7 +74,7 @@ class Teleport:
|
|
|
74
74
|
self.movement_vector = Vector3(0, 0, 0)
|
|
75
75
|
self.minimal_movement_vector_length = minimal_movement_vector_length
|
|
76
76
|
|
|
77
|
-
system_script_engine.
|
|
77
|
+
system_script_engine.simple_script(self.update_movement_vector, enabled=True)
|
|
78
78
|
|
|
79
79
|
def set_coords(self, x: Number, y: Number, z: Number = 100) -> None:
|
|
80
80
|
self.player_x.value = x
|
|
@@ -6,7 +6,7 @@ from typing import ClassVar, Self, cast, override
|
|
|
6
6
|
|
|
7
7
|
from pymem.exception import MemoryWriteError
|
|
8
8
|
|
|
9
|
-
from trainerbase.
|
|
9
|
+
from trainerbase.abc import Switchable
|
|
10
10
|
from trainerbase.memory import ConvertibleToAddress, ensure_address, pm
|
|
11
11
|
|
|
12
12
|
|
|
@@ -5,16 +5,16 @@ from dearpygui import dearpygui as dpg
|
|
|
5
5
|
from keyboard import add_hotkey
|
|
6
6
|
|
|
7
7
|
from trainerbase.gui.types import AbstractUIComponent
|
|
8
|
-
from trainerbase.scriptengine import
|
|
8
|
+
from trainerbase.scriptengine import AbstractBaseScript
|
|
9
9
|
from trainerbase.tts import say
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class ScriptUI(AbstractUIComponent):
|
|
12
|
+
class ScriptUI[T: AbstractBaseScript](AbstractUIComponent):
|
|
13
13
|
DPG_TAG_PREFIX = "script__"
|
|
14
14
|
|
|
15
15
|
def __init__(
|
|
16
16
|
self,
|
|
17
|
-
script:
|
|
17
|
+
script: T,
|
|
18
18
|
label: str,
|
|
19
19
|
hotkey: str | None = None,
|
|
20
20
|
*,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from typing import override
|
|
2
|
+
|
|
3
|
+
from dearpygui import dearpygui as dpg
|
|
4
|
+
|
|
5
|
+
from trainerbase.common.keyboard import ReleaseHotkeySwitch
|
|
6
|
+
from trainerbase.common.tapper import Tapper
|
|
7
|
+
from trainerbase.gui.helpers import add_components
|
|
8
|
+
from trainerbase.gui.misc import HotkeyHandlerUI
|
|
9
|
+
from trainerbase.gui.types import AbstractUIComponent
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TapperUI(AbstractUIComponent):
|
|
13
|
+
DPG_TAG_TAPPER_DELAY_INPUT = "tag_tapper_delay_input"
|
|
14
|
+
DPG_TAG_TAPPER_PRESET_INPUT = "tag_tapper_preset_input"
|
|
15
|
+
|
|
16
|
+
PRESETS: tuple[float, ...] = (0.05, 0.15, 0.25, 0.3, 0.5, 0.7, 1, 2, 5, 10)
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
tapper: Tapper | None = None,
|
|
21
|
+
key: str = "PageUp",
|
|
22
|
+
default_delay: float = 0.15,
|
|
23
|
+
):
|
|
24
|
+
if tapper is None:
|
|
25
|
+
self.tapper = Tapper(default_delay)
|
|
26
|
+
self.default_delay = default_delay
|
|
27
|
+
else:
|
|
28
|
+
self.tapper = tapper
|
|
29
|
+
self.default_delay = tapper.delay
|
|
30
|
+
|
|
31
|
+
self.key = key
|
|
32
|
+
|
|
33
|
+
@override
|
|
34
|
+
def add_to_ui(self) -> None:
|
|
35
|
+
add_components(HotkeyHandlerUI(ReleaseHotkeySwitch(self.tapper, self.key), "Tapper"))
|
|
36
|
+
|
|
37
|
+
dpg.add_input_double(
|
|
38
|
+
tag=self.DPG_TAG_TAPPER_DELAY_INPUT,
|
|
39
|
+
label="Tapper Delay",
|
|
40
|
+
min_value=0.0,
|
|
41
|
+
max_value=60.0,
|
|
42
|
+
default_value=self.default_delay,
|
|
43
|
+
min_clamped=True,
|
|
44
|
+
max_clamped=True,
|
|
45
|
+
callback=self.on_delay_change,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
dpg.add_slider_int(
|
|
49
|
+
tag=self.DPG_TAG_TAPPER_PRESET_INPUT,
|
|
50
|
+
label="Preset",
|
|
51
|
+
min_value=0,
|
|
52
|
+
max_value=len(self.PRESETS) - 1,
|
|
53
|
+
clamped=True,
|
|
54
|
+
default_value=self.get_closest_preset_index(self.default_delay),
|
|
55
|
+
callback=self.on_preset_change,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def on_preset_change(self):
|
|
59
|
+
new_delay = self.PRESETS[dpg.get_value(self.DPG_TAG_TAPPER_PRESET_INPUT)]
|
|
60
|
+
self.tapper.delay = new_delay
|
|
61
|
+
dpg.set_value(self.DPG_TAG_TAPPER_DELAY_INPUT, new_delay)
|
|
62
|
+
|
|
63
|
+
def on_delay_change(self):
|
|
64
|
+
new_delay = dpg.get_value(self.DPG_TAG_TAPPER_DELAY_INPUT)
|
|
65
|
+
closest_preset_index = self.get_closest_preset_index(new_delay)
|
|
66
|
+
self.tapper.delay = new_delay
|
|
67
|
+
dpg.set_value(self.DPG_TAG_TAPPER_PRESET_INPUT, closest_preset_index)
|
|
68
|
+
|
|
69
|
+
def get_closest_preset_index(self, delay: float) -> int:
|
|
70
|
+
closest_preset = min(self.PRESETS, key=lambda preset: abs(preset - delay))
|
|
71
|
+
return self.PRESETS.index(closest_preset)
|
|
@@ -7,9 +7,9 @@ from trainerbase.codeinjection import safely_eject_all_code_injections
|
|
|
7
7
|
from trainerbase.common.rainbow import gradient_updater
|
|
8
8
|
from trainerbase.gameobject import update_frozen_objects
|
|
9
9
|
from trainerbase.gui.objects import update_displayed_objects
|
|
10
|
-
from trainerbase.process import
|
|
10
|
+
from trainerbase.process import shutdown_if_process_exited
|
|
11
11
|
from trainerbase.scriptengine import (
|
|
12
|
-
|
|
12
|
+
enabled_by_default,
|
|
13
13
|
process_healthcheck_script_engine,
|
|
14
14
|
rainbow_script_engine,
|
|
15
15
|
system_script_engine,
|
|
@@ -50,10 +50,10 @@ def run( # pylint: disable=too-complex
|
|
|
50
50
|
print_exc()
|
|
51
51
|
on_shutdown()
|
|
52
52
|
|
|
53
|
-
system_script_engine.
|
|
54
|
-
system_script_engine.
|
|
55
|
-
process_healthcheck_script_engine.
|
|
56
|
-
rainbow_script_engine.register_script(
|
|
53
|
+
system_script_engine.simple_script(update_frozen_objects, enabled=True)
|
|
54
|
+
system_script_engine.simple_script(update_displayed_objects, enabled=True)
|
|
55
|
+
process_healthcheck_script_engine.simple_script(shutdown_if_process_exited, enabled=True)
|
|
56
|
+
rainbow_script_engine.register_script(enabled_by_default(gradient_updater))
|
|
57
57
|
|
|
58
58
|
try:
|
|
59
59
|
run_gui(on_gui_initialized, on_shutdown)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from functools import partial
|
|
4
|
+
from itertools import count
|
|
5
|
+
from time import sleep
|
|
4
6
|
from types import MappingProxyType
|
|
5
7
|
from typing import Final, Self, assert_never, cast, override
|
|
6
8
|
|
|
@@ -170,14 +172,24 @@ def allocate(size: int = POINTER_SIZE, count: int = 1) -> int:
|
|
|
170
172
|
return pm.allocate(size * count)
|
|
171
173
|
|
|
172
174
|
|
|
173
|
-
def get_module_address(module_name: str) -> int:
|
|
175
|
+
def get_module_address(module_name: str, *, delay: float = 2, retry_limit: int | None = 4) -> int:
|
|
174
176
|
"""
|
|
175
|
-
Returns
|
|
177
|
+
Returns module address.
|
|
178
|
+
Raises RuntimeError if the address was not found and retry_limit is reached.
|
|
179
|
+
|
|
180
|
+
Set retry_limit to None or negative value if you need infinite retry cycle.
|
|
181
|
+
Set retry_limit to 0 if you want to disable retries.
|
|
176
182
|
"""
|
|
177
183
|
|
|
178
|
-
|
|
184
|
+
for try_counter in count():
|
|
185
|
+
module_info = module_from_name(pm.process_handle, module_name)
|
|
186
|
+
|
|
187
|
+
if module_info is not None:
|
|
188
|
+
return module_info.lpBaseOfDll
|
|
189
|
+
|
|
190
|
+
if try_counter == retry_limit:
|
|
191
|
+
raise RuntimeError(f"Failed to find module: {module_name}, tried {try_counter + 1} time(s).")
|
|
179
192
|
|
|
180
|
-
|
|
181
|
-
return 0
|
|
193
|
+
sleep(delay)
|
|
182
194
|
|
|
183
|
-
|
|
195
|
+
raise RuntimeError("This code must be unreachable!")
|
|
@@ -3,11 +3,9 @@ from itertools import cycle
|
|
|
3
3
|
from os import _exit as force_exit
|
|
4
4
|
from typing import cast
|
|
5
5
|
|
|
6
|
-
from psutil import pid_exists
|
|
6
|
+
from psutil import Process, pid_exists
|
|
7
7
|
from pymem import Pymem
|
|
8
8
|
from pymem.exception import ProcessNotFound
|
|
9
|
-
from win32api import MessageBox
|
|
10
|
-
from win32con import MB_ICONERROR, MB_OK
|
|
11
9
|
|
|
12
10
|
from trainerbase.config import pymem_config
|
|
13
11
|
|
|
@@ -38,18 +36,13 @@ def attach_to_process() -> Pymem:
|
|
|
38
36
|
force_exit(0)
|
|
39
37
|
|
|
40
38
|
|
|
41
|
-
def
|
|
42
|
-
if pid_exists(cast(int, _pm.process_id)):
|
|
43
|
-
|
|
39
|
+
def shutdown_if_process_exited():
|
|
40
|
+
if not pid_exists(cast(int, _pm.process_id)):
|
|
41
|
+
force_exit(0)
|
|
44
42
|
|
|
45
|
-
MessageBox(
|
|
46
|
-
None,
|
|
47
|
-
"Shut down trainer?",
|
|
48
|
-
"Process Exited!",
|
|
49
|
-
MB_ICONERROR | MB_OK,
|
|
50
|
-
)
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
def kill_game_process():
|
|
45
|
+
Process(_pm.process_id).kill()
|
|
53
46
|
|
|
54
47
|
|
|
55
48
|
_pm = attach_to_process()
|
|
@@ -1,22 +1,46 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
1
2
|
from collections.abc import Callable
|
|
2
3
|
from contextlib import suppress
|
|
3
4
|
from sys import stderr
|
|
4
5
|
from threading import Thread
|
|
5
6
|
from time import sleep
|
|
7
|
+
from typing import Any, override
|
|
6
8
|
|
|
7
9
|
from pymem.exception import MemoryReadError, MemoryWriteError
|
|
8
10
|
|
|
11
|
+
from trainerbase.abc import Switchable
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
|
|
14
|
+
class AbstractBaseScript(Switchable, ABC):
|
|
15
|
+
enabled: bool = False
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def __call__(self) -> Any:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def __repr__(self):
|
|
22
|
+
return f"<{self.__class__.__name__}: enabled={self.enabled}>"
|
|
23
|
+
|
|
24
|
+
@override
|
|
25
|
+
def enable(self):
|
|
26
|
+
self.enabled = True
|
|
27
|
+
|
|
28
|
+
@override
|
|
29
|
+
def disable(self):
|
|
30
|
+
self.enabled = False
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SimpleScript(AbstractBaseScript):
|
|
34
|
+
def __init__(self, callback: Callable[[], None], *, enabled: bool = False):
|
|
35
|
+
self._callback = callback
|
|
13
36
|
self.enabled = enabled
|
|
14
37
|
|
|
15
38
|
def __repr__(self):
|
|
16
|
-
return f"<Script {getattr(self.
|
|
39
|
+
return f"<Script {getattr(self._callback, "__name__", "Anon function-based script")}: enabled={self.enabled}>"
|
|
17
40
|
|
|
41
|
+
@override
|
|
18
42
|
def __call__(self):
|
|
19
|
-
|
|
43
|
+
self._callback()
|
|
20
44
|
|
|
21
45
|
|
|
22
46
|
class ScriptEngine:
|
|
@@ -24,7 +48,7 @@ class ScriptEngine:
|
|
|
24
48
|
self.delay = delay
|
|
25
49
|
self.should_run = False
|
|
26
50
|
self.thread = Thread(target=self.script_loop)
|
|
27
|
-
self.scripts: list[
|
|
51
|
+
self.scripts: list[AbstractBaseScript] = []
|
|
28
52
|
|
|
29
53
|
def __repr__(self):
|
|
30
54
|
return f"<ScriptEngine delay={self.delay} should_run={self.should_run} scripts={len(self.scripts)}>"
|
|
@@ -55,18 +79,16 @@ class ScriptEngine:
|
|
|
55
79
|
|
|
56
80
|
sleep(self.delay)
|
|
57
81
|
|
|
58
|
-
def register_script(self, script:
|
|
82
|
+
def register_script[T: AbstractBaseScript](self, script: T) -> T:
|
|
59
83
|
self.scripts.append(script)
|
|
60
84
|
return script
|
|
61
85
|
|
|
62
|
-
def simple_script(self, executor: Callable) ->
|
|
63
|
-
|
|
64
|
-
self.register_script(script)
|
|
65
|
-
return script
|
|
86
|
+
def simple_script(self, executor: Callable[[], None], *, enabled: bool = False) -> AbstractBaseScript:
|
|
87
|
+
return self.register_script(SimpleScript(executor, enabled=enabled))
|
|
66
88
|
|
|
67
89
|
|
|
68
|
-
def enabled_by_default(script:
|
|
69
|
-
script.
|
|
90
|
+
def enabled_by_default[T: AbstractBaseScript](script: T) -> T:
|
|
91
|
+
script.enable()
|
|
70
92
|
return script
|
|
71
93
|
|
|
72
94
|
|
|
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
|