trainerbase 3.14.1__tar.gz → 3.16.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.
Files changed (33) hide show
  1. {trainerbase-3.14.1 → trainerbase-3.16.0}/PKG-INFO +1 -1
  2. {trainerbase-3.14.1 → trainerbase-3.16.0}/pyproject.toml +2 -2
  3. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/common/helpers.py +14 -1
  4. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/common/keyboard.py +2 -2
  5. trainerbase-3.16.0/trainerbase/common/rainbow.py +94 -0
  6. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/helpers.py +20 -3
  7. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/injections.py +3 -1
  8. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/misc.py +12 -10
  9. trainerbase-3.16.0/trainerbase/gui/rainbow.py +22 -0
  10. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/main.py +12 -5
  11. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/scriptengine.py +1 -0
  12. {trainerbase-3.14.1 → trainerbase-3.16.0}/LICENSE +0 -0
  13. {trainerbase-3.14.1 → trainerbase-3.16.0}/README.md +0 -0
  14. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/__init__.py +0 -0
  15. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/codeinjection.py +0 -0
  16. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/common/__init__.py +0 -0
  17. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/common/abc.py +0 -0
  18. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/common/teleport.py +0 -0
  19. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/config.py +0 -0
  20. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gameobject.py +0 -0
  21. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/__init__.py +0 -0
  22. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/objects.py +0 -0
  23. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/scripts.py +0 -0
  24. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/speedhack.py +0 -0
  25. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/teleport.py +0 -0
  26. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/gui/types.py +0 -0
  27. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/memory.py +0 -0
  28. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/process.py +0 -0
  29. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/speedhack.py +0 -0
  30. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase/tts.py +0 -0
  31. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase_vendor/FASM.EXE +0 -0
  32. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase_vendor/speedhack32.dll +0 -0
  33. {trainerbase-3.14.1 → trainerbase-3.16.0}/trainerbase_vendor/speedhack64.dll +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: trainerbase
3
- Version: 3.14.1
3
+ Version: 3.16.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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "trainerbase"
3
- version = "3.14.1"
3
+ version = "3.16.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.4.4"
20
+ ruff = "^0.4.10"
21
21
 
22
22
  [tool.ruff]
23
23
  src = ["trainerbase"]
@@ -1,7 +1,11 @@
1
- from collections.abc import Iterator, Sequence
1
+ from collections.abc import Callable, Iterator, Sequence
2
+ from contextlib import suppress
3
+ from functools import wraps
2
4
  from typing import overload
3
5
  from uuid import uuid4
4
6
 
7
+ from pymem.exception import MemoryReadError, MemoryWriteError
8
+
5
9
  from trainerbase.gameobject import AbstractReadableObject, GameObject
6
10
  from trainerbase.memory import POINTER_SIZE, Address, allocate, pm
7
11
 
@@ -119,3 +123,12 @@ def regenerate(
119
123
  ):
120
124
  if current_value.value < max_value.value:
121
125
  current_value.value += max(round(max_value.value * percent / 100), min_value)
126
+
127
+
128
+ def suppress_memory_exceptions[**P, T](callback: Callable[P, T]) -> Callable[P, T | None]:
129
+ @wraps(callback)
130
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> T | None:
131
+ with suppress(MemoryReadError, MemoryWriteError):
132
+ return callback(*args, **kwargs)
133
+
134
+ return wrapper
@@ -24,7 +24,7 @@ class SimpleSwitchable(Switchable):
24
24
 
25
25
  class SimpleHotkeyHandler(AbstractKeyboardHandler):
26
26
  def __init__(self, callback: Callable[[], None], hotkey: str):
27
- self._callback = callback
27
+ self.callback = callback
28
28
  self._hotkey = hotkey
29
29
 
30
30
  @property
@@ -34,7 +34,7 @@ class SimpleHotkeyHandler(AbstractKeyboardHandler):
34
34
 
35
35
  @override
36
36
  def handle(self):
37
- add_hotkey(self._hotkey, self._callback)
37
+ add_hotkey(self._hotkey, self.callback)
38
38
 
39
39
 
40
40
  class ReleaseHotkeySwitch(AbstractKeyboardHandler):
@@ -0,0 +1,94 @@
1
+ from collections.abc import Iterable, Iterator
2
+ from itertools import cycle
3
+
4
+ from dearpygui import dearpygui as dpg
5
+
6
+ from trainerbase.scriptengine import Script, rainbow_script_engine
7
+
8
+
9
+ type TagList = list[int | str]
10
+ type Color = tuple[int, int, int]
11
+ type Colors = Iterable[Color]
12
+
13
+
14
+ class GradientUpdater:
15
+ def __init__(self):
16
+ self.tags: TagList | None = None
17
+ self.colors: list[Color] | None = None
18
+ self.index_iter: Iterator[int] | None = None
19
+ self.initial_color: Color | None = None
20
+ self.initial_delta: tuple[int, int, int] | None = None
21
+ self.color_length: int | None = None
22
+
23
+ def __call__(self):
24
+ if self.tags is None or self.colors is None:
25
+ raise RuntimeError("Call setup(...)")
26
+
27
+ for tag, color in zip(self.tags, self.get_colors(len(self.tags))):
28
+ dpg.configure_item(tag, color=color)
29
+
30
+ def setup(
31
+ self,
32
+ *,
33
+ tags: TagList | None = None,
34
+ initial_color: Color | None = None,
35
+ initial_delta: tuple[int, int, int] | None = None,
36
+ color_length: int | None = None,
37
+ ) -> None:
38
+ if tags is not None:
39
+ self.tags = tags
40
+ self.colors = self.generate_colors(len(tags))
41
+ self.index_iter = cycle(range(len(self.colors)))
42
+
43
+ if initial_color is not None:
44
+ self.initial_color = initial_color
45
+
46
+ if initial_delta is not None:
47
+ self.initial_delta = initial_delta
48
+
49
+ if color_length is not None:
50
+ self.color_length = color_length
51
+
52
+ def generate_colors(self, length: int) -> list[Color]:
53
+ if self.initial_color is None or self.initial_delta is None or self.color_length is None:
54
+ raise RuntimeError("Call setup(...)")
55
+
56
+ red, green, blue = self.initial_color
57
+ delta_red, delta_green, delta_blue = self.initial_delta
58
+
59
+ colors = []
60
+
61
+ for _ in range(length // 2):
62
+ for _ in range(self.color_length):
63
+ colors.append((red, green, blue))
64
+
65
+ red, delta_red = self.next_color_channel_value(red, delta_red)
66
+ green, delta_green = self.next_color_channel_value(green, delta_green)
67
+ blue, delta_blue = self.next_color_channel_value(blue, delta_blue)
68
+
69
+ colors = colors + colors[::-1]
70
+
71
+ return colors
72
+
73
+ def get_colors(self, n: int) -> Colors:
74
+ if self.colors is None or self.index_iter is None:
75
+ raise RuntimeError("Call setup(...)")
76
+
77
+ index = next(self.index_iter)
78
+
79
+ colors = self.colors[index : index + n]
80
+
81
+ if len(colors) < n:
82
+ colors += self.colors[: n - len(colors)]
83
+
84
+ return colors
85
+
86
+ def next_color_channel_value(self, current: int, delta: int) -> tuple[int, int]:
87
+ if not (0 <= current + delta <= 255):
88
+ delta = -delta
89
+
90
+ return current + delta, delta
91
+
92
+
93
+ gradient_updater = GradientUpdater()
94
+ rainbow_script_engine.register_script(Script(gradient_updater, enabled=True))
@@ -3,6 +3,8 @@ from functools import wraps
3
3
 
4
4
  from dearpygui import dearpygui as dpg
5
5
 
6
+ from trainerbase.common.rainbow import Color, gradient_updater
7
+ from trainerbase.gui.rainbow import RainbowUI
6
8
  from trainerbase.gui.types import AbstractUIComponent
7
9
 
8
10
 
@@ -11,10 +13,17 @@ def add_components(*components: AbstractUIComponent):
11
13
  component.add_to_ui()
12
14
 
13
15
 
14
- def simple_trainerbase_menu(window_title: str, width: int, height: int):
15
- def menu_decorator(initializer: Callable):
16
+ def simple_trainerbase_menu(
17
+ window_title: str,
18
+ width: int,
19
+ height: int,
20
+ rainbow_initial_color: Color = (1, 255, 125),
21
+ rainbow_initial_delta: tuple[int, int, int] = (1, 1, 1),
22
+ rainbow_color_length: int = 3,
23
+ ):
24
+ def menu_decorator(initializer: Callable[[], None]):
16
25
  @wraps(initializer)
17
- def run_menu_wrapper(on_initialized: Callable):
26
+ def run_menu_wrapper(on_initialized: Callable[[], None]):
18
27
  dpg.create_context()
19
28
  dpg.create_viewport(
20
29
  title=window_title,
@@ -34,6 +43,14 @@ def simple_trainerbase_menu(window_title: str, width: int, height: int):
34
43
  horizontal_scrollbar=True,
35
44
  autosize=True,
36
45
  ):
46
+ gradient_updater.setup(
47
+ initial_color=rainbow_initial_color,
48
+ initial_delta=rainbow_initial_delta,
49
+ color_length=rainbow_color_length,
50
+ )
51
+
52
+ add_components(RainbowUI(width, gradient_updater))
53
+
37
54
  initializer()
38
55
 
39
56
  dpg.set_primary_window("menu", value=True)
@@ -1,3 +1,4 @@
1
+ from traceback import print_exc
1
2
  from typing import override
2
3
  from uuid import uuid4
3
4
 
@@ -41,8 +42,9 @@ class CodeInjectionUI(AbstractUIComponent):
41
42
 
42
43
  try:
43
44
  change_codeinjection_state()
44
- except (MemoryReadError, MemoryWriteError):
45
+ except (MemoryReadError, MemoryWriteError, ValueError):
45
46
  dpg.set_value(self.dpg_tag, not dpg.get_value(self.dpg_tag))
47
+ print_exc()
46
48
 
47
49
  def on_hotkey_press(self):
48
50
  dpg.set_value(self.dpg_tag, not dpg.get_value(self.dpg_tag))
@@ -1,9 +1,13 @@
1
1
  from typing import override
2
- from uuid import uuid4
3
2
 
4
3
  from dearpygui import dearpygui as dpg
5
4
 
6
- from trainerbase.common.keyboard import AbstractKeyboardHandler, ReleaseHotkeySwitch, ShortLongHotkeyPressSwitch
5
+ from trainerbase.common.keyboard import (
6
+ AbstractKeyboardHandler,
7
+ ReleaseHotkeySwitch,
8
+ ShortLongHotkeyPressSwitch,
9
+ SimpleHotkeyHandler,
10
+ )
7
11
  from trainerbase.gui.types import AbstractUIComponent
8
12
 
9
13
 
@@ -33,27 +37,25 @@ class TextUI(AbstractUIComponent):
33
37
 
34
38
 
35
39
  class HotkeyHandlerUI(AbstractUIComponent):
36
- DPG_TAG_PREFIX = "switch__"
37
-
38
40
  def __init__(
39
41
  self,
40
42
  handler: AbstractKeyboardHandler,
41
43
  label: str,
42
44
  ):
43
45
  self.handler = handler
44
- self.dpg_tag_press = f"{self.DPG_TAG_PREFIX}{uuid4()}_press"
45
- self.dpg_tag_hold = f"{self.DPG_TAG_PREFIX}{uuid4()}_hold"
46
46
  self.label = label
47
47
 
48
48
  @override
49
49
  def add_to_ui(self) -> None:
50
50
  match self.handler:
51
51
  case ShortLongHotkeyPressSwitch():
52
- dpg.add_text(f"Hold [{self.handler.hotkey}] Enable {self.label}", tag=self.dpg_tag_hold)
53
- dpg.add_text(f"Press [{self.handler.hotkey}] Toggle {self.label}", tag=self.dpg_tag_press)
52
+ dpg.add_text(f"Hold [{self.handler.hotkey}] Enable {self.label}")
53
+ dpg.add_text(f"Press [{self.handler.hotkey}] Toggle {self.label}")
54
54
  case ReleaseHotkeySwitch():
55
- dpg.add_text(f"[{self.handler.hotkey}] Toggle {self.label}", tag=self.dpg_tag_press)
55
+ dpg.add_text(f"[{self.handler.hotkey}] Toggle {self.label}")
56
+ case SimpleHotkeyHandler():
57
+ dpg.add_button(label=f"[{self.handler.hotkey}] {self.label}", callback=self.handler.callback)
56
58
  case _:
57
- dpg.add_text(f"[{self.handler.hotkey}] {self.label}", tag=self.dpg_tag_press)
59
+ dpg.add_text(f"[{self.handler.hotkey}] {self.label}")
58
60
 
59
61
  self.handler.handle()
@@ -0,0 +1,22 @@
1
+ from typing import override
2
+
3
+ from dearpygui import dearpygui as dpg
4
+
5
+ from trainerbase.common.rainbow import GradientUpdater
6
+ from trainerbase.gui.types import AbstractUIComponent
7
+
8
+
9
+ class RainbowUI(AbstractUIComponent):
10
+ def __init__(self, width: int, gradient_updater: GradientUpdater) -> None:
11
+ self.gradient_updater = gradient_updater
12
+ self.width = width
13
+
14
+ @override
15
+ def add_to_ui(self) -> None:
16
+ dpg.add_spacer()
17
+ dpg.add_spacer()
18
+ tags = [dpg.draw_line([-10.0 + i, 0.0], [1.0 + i, 0.0], thickness=2) for i in range(self.width)]
19
+
20
+ self.gradient_updater.setup(tags=tags)
21
+
22
+ return super().add_to_ui()
@@ -1,14 +1,18 @@
1
1
  from collections.abc import Callable
2
2
  from os import _exit as force_exit
3
- from sys import stderr
4
- from traceback import format_exc
3
+ from traceback import print_exc
5
4
  from typing import NoReturn
6
5
 
7
6
  from trainerbase.codeinjection import safely_eject_all_code_injections
8
7
  from trainerbase.gameobject import update_frozen_objects
9
8
  from trainerbase.gui.objects import update_displayed_objects
10
9
  from trainerbase.process import show_message_and_shutdown_if_process_exited
11
- from trainerbase.scriptengine import Script, process_healthcheck_script_engine, system_script_engine
10
+ from trainerbase.scriptengine import (
11
+ Script,
12
+ process_healthcheck_script_engine,
13
+ rainbow_script_engine,
14
+ system_script_engine,
15
+ )
12
16
  from trainerbase.speedhack import SpeedHack
13
17
 
14
18
 
@@ -20,6 +24,8 @@ def run( # pylint: disable=too-complex
20
24
  def on_shutdown() -> NoReturn:
21
25
  system_script_engine.stop()
22
26
  process_healthcheck_script_engine.stop()
27
+ rainbow_script_engine.stop()
28
+
23
29
  safely_eject_all_code_injections()
24
30
  SpeedHack.disable()
25
31
 
@@ -31,12 +37,13 @@ def run( # pylint: disable=too-complex
31
37
  def on_gui_initialized() -> None:
32
38
  system_script_engine.start()
33
39
  process_healthcheck_script_engine.start()
40
+ rainbow_script_engine.start()
34
41
 
35
42
  if on_gui_initialized_hook is not None:
36
43
  try:
37
44
  on_gui_initialized_hook()
38
45
  except Exception:
39
- print(format_exc(), file=stderr)
46
+ print_exc()
40
47
  on_shutdown()
41
48
 
42
49
  system_script_engine.register_script(Script(update_frozen_objects, enabled=True))
@@ -46,6 +53,6 @@ def run( # pylint: disable=too-complex
46
53
  try:
47
54
  run_gui(on_gui_initialized)
48
55
  except Exception:
49
- print(format_exc(), file=stderr)
56
+ print_exc()
50
57
 
51
58
  on_shutdown()
@@ -68,4 +68,5 @@ def enabled_by_default(script: Script) -> Script:
68
68
 
69
69
 
70
70
  system_script_engine = ScriptEngine()
71
+ rainbow_script_engine = ScriptEngine(delay=0.0025)
71
72
  process_healthcheck_script_engine = ScriptEngine(delay=3)
File without changes
File without changes