rustplus 6.0.11__tar.gz → 6.1.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 (124) hide show
  1. {rustplus-6.0.11/rustplus.egg-info → rustplus-6.1.0}/PKG-INFO +3 -1
  2. {rustplus-6.0.11 → rustplus-6.1.0}/README.md +2 -0
  3. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/__init__.py +10 -2
  4. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/__init__.py +1 -0
  5. rustplus-6.1.0/rustplus/annotations/clan_event.py +21 -0
  6. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/events/__init__.py +1 -0
  7. rustplus-6.1.0/rustplus/events/chat_event.py +27 -0
  8. rustplus-6.1.0/rustplus/events/clan_info_event.py +13 -0
  9. rustplus-6.1.0/rustplus/remote/camera/camera_constants.py +32 -0
  10. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/camera/camera_manager.py +4 -4
  11. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/camera/camera_parser.py +86 -3
  12. rustplus-6.1.0/rustplus/remote/nexus/__init__.py +1 -0
  13. rustplus-6.1.0/rustplus/remote/nexus/nexus_interface.py +45 -0
  14. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/websocket/ws.py +39 -25
  15. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/rust_api.py +106 -8
  16. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/__init__.py +2 -1
  17. rustplus-6.1.0/rustplus/structs/clans/__init__.py +2 -0
  18. rustplus-6.1.0/rustplus/structs/clans/rust_clan_info.py +247 -0
  19. rustplus-6.1.0/rustplus/structs/clans/rust_clan_message.py +30 -0
  20. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_chat_message.py +8 -3
  21. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_info.py +19 -1
  22. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_marker.py +9 -0
  23. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/util.py +6 -0
  24. {rustplus-6.0.11 → rustplus-6.1.0/rustplus.egg-info}/PKG-INFO +3 -1
  25. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus.egg-info/SOURCES.txt +7 -0
  26. rustplus-6.0.11/rustplus/events/chat_event.py +0 -13
  27. rustplus-6.0.11/rustplus/remote/camera/camera_constants.py +0 -35
  28. {rustplus-6.0.11 → rustplus-6.1.0}/LICENSE +0 -0
  29. {rustplus-6.0.11 → rustplus-6.1.0}/MANIFEST.in +0 -0
  30. {rustplus-6.0.11 → rustplus-6.1.0}/requirements.txt +0 -0
  31. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/chat_event.py +0 -0
  32. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/command.py +0 -0
  33. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/entity_event.py +0 -0
  34. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/protobuf_event.py +0 -0
  35. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/annotations/team_event.py +0 -0
  36. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/commands/__init__.py +0 -0
  37. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/commands/chat_command.py +0 -0
  38. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/commands/chat_command_data.py +0 -0
  39. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/commands/command_options.py +0 -0
  40. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/events/entity_event.py +0 -0
  41. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/events/protobuf_event.py +0 -0
  42. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/events/team_event.py +0 -0
  43. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/exceptions/__init__.py +0 -0
  44. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/exceptions/exceptions.py +0 -0
  45. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/__init__.py +0 -0
  46. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/airfield.png +0 -0
  47. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/arctic_base.png +0 -0
  48. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/bandit.png +0 -0
  49. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/barn.png +0 -0
  50. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/cargo.png +0 -0
  51. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/chinook.png +0 -0
  52. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/chinook_blades.png +0 -0
  53. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/crate.png +0 -0
  54. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/desert_base.png +0 -0
  55. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/dome.png +0 -0
  56. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/excavator.png +0 -0
  57. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/explosion.png +0 -0
  58. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/ferryterminal.png +0 -0
  59. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/fishing.png +0 -0
  60. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/harbour.png +0 -0
  61. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/icon.png +0 -0
  62. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/jungle_ziggurat.png +0 -0
  63. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/junkyard.png +0 -0
  64. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/large_oil_rig.png +0 -0
  65. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/launchsite.png +0 -0
  66. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/lighthouse.png +0 -0
  67. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/military_tunnels.png +0 -0
  68. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/mining_outpost.png +0 -0
  69. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/mining_quarry_hqm.png +0 -0
  70. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/mining_quarry_stone.png +0 -0
  71. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/mining_quarry_sulfur.png +0 -0
  72. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/missile_silo.png +0 -0
  73. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/outpost.png +0 -0
  74. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/oxums.png +0 -0
  75. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/patrol.png +0 -0
  76. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/power_plant.png +0 -0
  77. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/radtown.png +0 -0
  78. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/satellite.png +0 -0
  79. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/sewer.png +0 -0
  80. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/small_oil_rig.png +0 -0
  81. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/stables.png +0 -0
  82. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/supermarket.png +0 -0
  83. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/swamp.png +0 -0
  84. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/train.png +0 -0
  85. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/train_yard.png +0 -0
  86. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/underwater_lab.png +0 -0
  87. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/vending_machine.png +0 -0
  88. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/icons/water_treatment.png +0 -0
  89. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/identification/__init__.py +0 -0
  90. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/identification/handler_list.py +0 -0
  91. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/identification/registered_listener.py +0 -0
  92. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/identification/server_details.py +0 -0
  93. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/__init__.py +0 -0
  94. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/camera/__init__.py +0 -0
  95. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/camera/structures.py +0 -0
  96. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/fcm/__init__.py +0 -0
  97. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/fcm/fcm_listener.py +0 -0
  98. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/proxy/__init__.py +0 -0
  99. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/proxy/proxy_value_grabber.py +0 -0
  100. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/ratelimiter/__init__.py +0 -0
  101. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/rustplus_proto/__init__.py +0 -0
  102. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/rustplus_proto/rustplus.py +0 -0
  103. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/remote/websocket/__init__.py +0 -0
  104. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_contents.py +0 -0
  105. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_entity_info.py +0 -0
  106. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_error.py +0 -0
  107. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_item.py +0 -0
  108. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_map.py +0 -0
  109. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_team_info.py +0 -0
  110. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/rust_time.py +0 -0
  111. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/structs/serialization.py +0 -0
  112. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/__init__.py +0 -0
  113. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/deprecated.py +0 -0
  114. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/emojis.py +0 -0
  115. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/fonts/PermanentMarker.ttf +0 -0
  116. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/fonts/__init__.py +0 -0
  117. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/grab_items.py +0 -0
  118. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/utils.py +0 -0
  119. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus/utils/yielding_event.py +0 -0
  120. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus.egg-info/dependency_links.txt +0 -0
  121. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus.egg-info/requires.txt +0 -0
  122. {rustplus-6.0.11 → rustplus-6.1.0}/rustplus.egg-info/top_level.txt +0 -0
  123. {rustplus-6.0.11 → rustplus-6.1.0}/setup.cfg +0 -0
  124. {rustplus-6.0.11 → rustplus-6.1.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rustplus
3
- Version: 6.0.11
3
+ Version: 6.1.0
4
4
  Summary: A python wrapper for the Rust Plus API
5
5
  Home-page: https://github.com/olijeffers0n/rustplus
6
6
  Author: olijeffers0n
@@ -60,6 +60,8 @@ pip install rustplus
60
60
  - Getting the time
61
61
  - Using Smart Devices
62
62
  - Camera Handling
63
+ - Interacting with clans
64
+ - Getting nexus information
63
65
 
64
66
  # For information on all the above methods, see the [Wiki](https://rplus.ollieee.xyz)
65
67
 
@@ -29,6 +29,8 @@ pip install rustplus
29
29
  - Getting the time
30
30
  - Using Smart Devices
31
31
  - Camera Handling
32
+ - Interacting with clans
33
+ - Getting nexus information
32
34
 
33
35
  # For information on all the above methods, see the [Wiki](https://rplus.ollieee.xyz)
34
36
 
@@ -4,9 +4,17 @@ RustPlus, An API wrapper for interfacing with the Rust+ App API
4
4
 
5
5
  from .rust_api import RustSocket
6
6
  from .identification import ServerDetails
7
- from .annotations import Command, ChatEvent, ProtobufEvent, TeamEvent, EntityEvent
7
+ from .annotations import (
8
+ Command,
9
+ ChatEvent,
10
+ ProtobufEvent,
11
+ TeamEvent,
12
+ EntityEvent,
13
+ ClanEvent,
14
+ )
8
15
  from .remote.fcm import FCMListener
9
16
  from .remote.camera import MovementControls, CameraMovementOptions
17
+ from .remote.nexus import NexusInterface, Realm
10
18
  from .commands import CommandOptions, ChatCommand
11
19
  from .events import ChatEventPayload, TeamEventPayload, EntityEventPayload
12
20
  from .utils import convert_event_type_to_name, Emoji, convert_coordinates
@@ -14,5 +22,5 @@ from .structs import RustError, RustMarker, Vector
14
22
 
15
23
  __name__ = "rustplus"
16
24
  __author__ = "olijeffers0n"
17
- __version__ = "6.0.11"
25
+ __version__ = "6.1.0"
18
26
  __support__ = "Discord: https://discord.gg/nQqJe8qvP8"
@@ -3,3 +3,4 @@ from .entity_event import EntityEvent
3
3
  from .chat_event import ChatEvent
4
4
  from .team_event import TeamEvent
5
5
  from .protobuf_event import ProtobufEvent
6
+ from .clan_event import ClanEvent
@@ -0,0 +1,21 @@
1
+ from typing import Callable
2
+
3
+ from .. import ServerDetails
4
+ from ..identification import RegisteredListener
5
+ from ..events import ClanInfoEventPayload as ClanInfoEventManager
6
+
7
+
8
+ def ClanEvent(server_details: ServerDetails) -> Callable:
9
+
10
+ def wrapper(func) -> RegisteredListener:
11
+
12
+ if isinstance(func, RegisteredListener):
13
+ func = func.get_coro()
14
+
15
+ listener = RegisteredListener(func.__name__, func)
16
+
17
+ ClanInfoEventManager.HANDLER_LIST.register(listener, server_details)
18
+
19
+ return listener
20
+
21
+ return wrapper
@@ -2,3 +2,4 @@ from .chat_event import ChatEventPayload
2
2
  from .entity_event import EntityEventPayload
3
3
  from .team_event import TeamEventPayload
4
4
  from .protobuf_event import ProtobufEventPayload
5
+ from .clan_info_event import ClanInfoEventPayload
@@ -0,0 +1,27 @@
1
+ from rustplus.identification.handler_list import HandlerList
2
+ from ..structs import RustChatMessage
3
+
4
+ from typing import Union
5
+
6
+
7
+ class ChatEventPayload:
8
+ HANDLER_LIST = HandlerList()
9
+
10
+ def __init__(
11
+ self, message: RustChatMessage, is_clan: bool, clan_id: Union[int, None]
12
+ ) -> None:
13
+ self._message = message
14
+ self._is_clan = is_clan
15
+ self._clan_id = clan_id
16
+
17
+ @property
18
+ def message(self) -> RustChatMessage:
19
+ return self._message
20
+
21
+ @property
22
+ def is_clan(self) -> bool:
23
+ return self._is_clan
24
+
25
+ @property
26
+ def clan_id(self) -> Union[int, None]:
27
+ return self._clan_id
@@ -0,0 +1,13 @@
1
+ from rustplus.identification.handler_list import HandlerList
2
+ from ..structs import RustClanInfo
3
+
4
+
5
+ class ClanInfoEventPayload:
6
+ HANDLER_LIST = HandlerList()
7
+
8
+ def __init__(self, clan_info: RustClanInfo) -> None:
9
+ self._clan_info = clan_info
10
+
11
+ @property
12
+ def clan_info(self) -> RustClanInfo:
13
+ return self._clan_info
@@ -0,0 +1,32 @@
1
+ class MovementControls:
2
+ """
3
+ Possible inputs for the camera movement.
4
+ """
5
+
6
+ FORWARD = 2
7
+ BACKWARD = 4
8
+ LEFT = 8
9
+ RIGHT = 16
10
+ JUMP = 32
11
+ DUCK = 64
12
+ SPRINT = 128
13
+ USE = 256
14
+ FIRE_PRIMARY = 1024
15
+ FIRE_SECONDARY = 2048
16
+ RELOAD = 8192
17
+ FIRE_THIRD = 134217728
18
+
19
+
20
+ class CameraMovementOptions:
21
+ """
22
+ Indicate which camera controls are active for the camera.
23
+
24
+ """
25
+
26
+ NONE = 0
27
+ MOVEMENT = 1
28
+ MOUSE = 2
29
+ SPRINT_AND_DUCK = 4
30
+ FIRE = 8
31
+ RELOAD = 16
32
+ CROSSHAIR = 32
@@ -58,8 +58,8 @@ class CameraManager:
58
58
  async def _create_frame(
59
59
  self,
60
60
  render_entities: bool = True,
61
- entity_render_distance: float = float("inf"),
62
- max_entity_amount: int = float("inf"),
61
+ entity_render_distance: float | int = float("inf"),
62
+ max_entity_amount: float | int = float("inf"),
63
63
  ) -> Union[Image.Image, None]:
64
64
  if self._last_packets is None:
65
65
  return None
@@ -95,8 +95,8 @@ class CameraManager:
95
95
  async def get_frame(
96
96
  self,
97
97
  render_entities: bool = True,
98
- entity_render_distance: float = float("inf"),
99
- max_entity_amount: int = float("inf"),
98
+ entity_render_distance: float | int = float("inf"),
99
+ max_entity_amount: float | int = float("inf"),
100
100
  ) -> Union[Image.Image, None]:
101
101
  return await self._create_frame(
102
102
  render_entities, entity_render_distance, max_entity_amount
@@ -7,7 +7,6 @@ import numpy as np
7
7
  from scipy.spatial import ConvexHull
8
8
  from PIL import Image, ImageDraw, ImageFont
9
9
 
10
- from .camera_constants import LOOKUP_CONSTANTS
11
10
  from .structures import Entity, Vector3
12
11
 
13
12
  SCIENTIST_COLOUR = "#3098f2"
@@ -44,6 +43,8 @@ class Parser:
44
43
  self.entities = []
45
44
  self.last_fov = 0
46
45
 
46
+ self.lookup_constants = self._generate_lookup_constants(self.width, self.height)
47
+
47
48
  def reset_output(self) -> None:
48
49
  self.colour_output = np.full(
49
50
  (self.width * self.scale_factor, self.height * self.scale_factor, 3),
@@ -53,6 +54,42 @@ class Parser:
53
54
  (self.width * self.scale_factor, self.height * self.scale_factor)
54
55
  )
55
56
 
57
+ @staticmethod
58
+ def _generate_lookup_constants(width: int, height: int) -> List[int]:
59
+ instance_count = width * height
60
+
61
+ sample_position_buffer = [0] * (instance_count * 2)
62
+
63
+ buffer_index = 0
64
+
65
+ for y in range(height):
66
+ for x in range(width):
67
+ sample_position_buffer[buffer_index] = RNGSource.int32(x)
68
+ buffer_index += 1
69
+
70
+ sample_position_buffer[buffer_index] = RNGSource.int32(y)
71
+ buffer_index += 1
72
+
73
+ rng = RNGSource(1337)
74
+
75
+ for current_position in range(instance_count - 1, 0, -1):
76
+ current_index = 2 * current_position
77
+ random_position = 2 * rng.next_int(current_position + 1)
78
+
79
+ current_x = sample_position_buffer[current_index]
80
+ current_y = sample_position_buffer[current_index + 1]
81
+
82
+ random_x = sample_position_buffer[random_position]
83
+ random_y = sample_position_buffer[random_position + 1]
84
+
85
+ sample_position_buffer[random_position] = current_x
86
+ sample_position_buffer[random_position + 1] = current_y
87
+
88
+ sample_position_buffer[current_index] = random_x
89
+ sample_position_buffer[current_index + 1] = random_y
90
+
91
+ return sample_position_buffer
92
+
56
93
  def handle_camera_ray_data(self, data) -> None:
57
94
  if data is None:
58
95
  return
@@ -90,9 +127,11 @@ class Parser:
90
127
  alignment = ray[1]
91
128
  material = ray[2]
92
129
 
93
- index1 = LOOKUP_CONSTANTS[self._sample_offset]
130
+ index1 = self.lookup_constants[self._sample_offset]
94
131
  self._sample_offset += 1
95
- index2 = int(LOOKUP_CONSTANTS[self._sample_offset] * self.width + index1)
132
+ index2 = int(
133
+ self.lookup_constants[self._sample_offset] * self.width + index1
134
+ )
96
135
  self._sample_offset += 1
97
136
 
98
137
  x = (index2 % self.width) * self.scale_factor
@@ -786,3 +825,47 @@ class MathUtils:
786
825
 
787
826
  # Return the vertices that correspond to the non-zero indices
788
827
  return np.array(list(zip(x, y)))
828
+
829
+
830
+ class RNGSource:
831
+ def __init__(self, seed):
832
+ self.state = self.int32(seed)
833
+ self.next_state()
834
+
835
+ def next_int(self, e):
836
+ t = self.int32((self.next_state() * self.int32(e)) / 4294967295)
837
+
838
+ if t < 0:
839
+ t = e + t - 1
840
+
841
+ return self.int32(t)
842
+
843
+ def next_state(self):
844
+ e = self.state
845
+ t = e
846
+
847
+ e = self.int32(e ^ self.int32(e << 13))
848
+ e = self.int32(e ^ (self.uint32(e) >> 17))
849
+ e = self.int32(e ^ self.int32(e << 5))
850
+
851
+ self.state = e
852
+
853
+ return self.clamp(t)
854
+
855
+ @staticmethod
856
+ def clamp(e):
857
+ return e if e >= 0 else 4294967295 + e - 1
858
+
859
+ @staticmethod
860
+ def int32(value):
861
+ value = int(value)
862
+ value &= 0xFFFFFFFF
863
+
864
+ if value >= 0x80000000:
865
+ value -= 0x100000000
866
+
867
+ return value
868
+
869
+ @staticmethod
870
+ def uint32(value):
871
+ return value & 0xFFFFFFFF
@@ -0,0 +1 @@
1
+ from .nexus_interface import NexusInterface, Realm
@@ -0,0 +1,45 @@
1
+ from typing import Any
2
+
3
+ import requests
4
+ import enum
5
+
6
+
7
+ class Realm(enum.Enum):
8
+ Development = 0
9
+ Staging = 1
10
+ Production = 2
11
+
12
+
13
+ class NexusInterface:
14
+ def __init__(self, endpoint: str):
15
+ self.session = requests.Session()
16
+ self.endpoint = endpoint
17
+
18
+ def get_all_nexus(self, public_key: str, realm: Realm) -> Any | None:
19
+
20
+ res = self.session.get(
21
+ f"{self.endpoint}?publicKey={public_key}&realm={realm.value}"
22
+ )
23
+
24
+ if res.status_code == 200:
25
+ return res.json()
26
+
27
+ return None
28
+
29
+ def get_nexus_info(self, nexus_id: int) -> Any | None:
30
+
31
+ res = self.session.get(f"{self.endpoint}/{nexus_id}")
32
+
33
+ if res.status_code == 200:
34
+ return res.json()
35
+
36
+ return None
37
+
38
+ def get_nexus_map(self, nexus_id: int) -> Any | None:
39
+
40
+ res = self.session.get(f"{self.endpoint}/{nexus_id}/map")
41
+
42
+ if res.status_code == 200:
43
+ return res.content
44
+
45
+ return None
@@ -19,9 +19,10 @@ from ...events import (
19
19
  TeamEventPayload,
20
20
  ChatEventPayload,
21
21
  )
22
+ from ...events.clan_info_event import ClanInfoEventPayload
22
23
  from ...exceptions import RequestError
23
24
  from ...identification import ServerDetails, RegisteredListener
24
- from ...structs import RustChatMessage, RustTeamInfo
25
+ from ...structs import RustChatMessage, RustTeamInfo, RustClanInfo
25
26
  from ...utils import YieldingEvent, convert_time
26
27
  from ...utils.utils import error_present
27
28
 
@@ -274,14 +275,40 @@ class RustWebsocket:
274
275
  for handler in handlers:
275
276
  await handler.get_coro()(team_event)
276
277
 
277
- elif self.is_message(app_message):
278
+ elif self.is_clan_broadcast(app_message):
279
+ # Clan Event
280
+ if self.debug:
281
+ self.logger.info(f"Running Clan Event: {app_message}")
282
+
283
+ # This means that the clan of the current player has changed
284
+ handlers = ClanInfoEventPayload.HANDLER_LIST.get_handlers(
285
+ self.server_details
286
+ )
287
+ clan_event = ClanInfoEventPayload(
288
+ RustClanInfo(app_message.broadcast.clan_changed.clan_info)
289
+ )
290
+ for handler in handlers:
291
+ await handler.get_coro()(clan_event)
292
+
293
+ elif self.is_message(app_message) or self.is_clan_message(app_message):
278
294
  # Chat message event
295
+
296
+ is_clan = self.is_clan_message(app_message)
297
+
279
298
  if self.debug:
280
- self.logger.info(f"Running Chat Event: {app_message}")
299
+ self.logger.info(
300
+ f"Running Chat Event: {app_message}, is_clan={is_clan}"
301
+ )
281
302
 
282
303
  handlers = ChatEventPayload.HANDLER_LIST.get_handlers(self.server_details)
283
304
  chat_event = ChatEventPayload(
284
- RustChatMessage(app_message.broadcast.team_message.message)
305
+ RustChatMessage(
306
+ app_message.broadcast.clan_message.message
307
+ if is_clan
308
+ else app_message.broadcast.team_message.message
309
+ ),
310
+ is_clan,
311
+ app_message.broadcast.clan_message.clan_id if is_clan else None,
285
312
  )
286
313
  for handler in handlers:
287
314
  await handler.get_coro()(chat_event)
@@ -321,6 +348,12 @@ class RustWebsocket:
321
348
  app_message.broadcast.team_message.message
322
349
  )
323
350
 
351
+ @staticmethod
352
+ def is_clan_message(app_message: AppMessage) -> bool:
353
+ return betterproto.serialized_on_wire(
354
+ app_message.broadcast.clan_message.message
355
+ )
356
+
324
357
  @staticmethod
325
358
  def is_camera_broadcast(app_message: AppMessage) -> bool:
326
359
  return betterproto.serialized_on_wire(app_message.broadcast.camera_rays)
@@ -334,27 +367,8 @@ class RustWebsocket:
334
367
  return betterproto.serialized_on_wire(app_message.broadcast.team_changed)
335
368
 
336
369
  @staticmethod
337
- def get_proto_cost(app_request: AppRequest) -> int:
338
- """
339
- Gets the cost of an AppRequest
340
- """
341
- costs = [
342
- (app_request.get_time, 1),
343
- (app_request.send_team_message, 2),
344
- (app_request.get_info, 1),
345
- (app_request.get_team_chat, 1),
346
- (app_request.get_team_info, 1),
347
- (app_request.get_map_markers, 1),
348
- (app_request.get_map, 5),
349
- (app_request.set_entity_value, 1),
350
- (app_request.get_entity_info, 1),
351
- (app_request.promote_to_leader, 1),
352
- ]
353
- for request, cost in costs:
354
- if betterproto.serialized_on_wire(request):
355
- return cost
356
-
357
- raise ValueError()
370
+ def is_clan_broadcast(app_message: AppMessage) -> bool:
371
+ return betterproto.serialized_on_wire(app_message.broadcast.clan_changed)
358
372
 
359
373
  @staticmethod
360
374
  async def run_coroutine_non_blocking(coroutine: Coroutine) -> Task:
@@ -19,6 +19,7 @@ from .remote.rustplus_proto import (
19
19
  AppCameraSubscribe,
20
20
  AppMapMonument,
21
21
  AppFlag,
22
+ AppGetNexusAuth,
22
23
  )
23
24
  from .remote.websocket import RustWebsocket
24
25
  from .structs import (
@@ -31,6 +32,9 @@ from .structs import (
31
32
  RustEntityInfo,
32
33
  RustContents,
33
34
  RustItem,
35
+ RustClanInfo,
36
+ RustClanMessage,
37
+ RustAuthDetails,
34
38
  )
35
39
  from .structs.rust_error import RustError
36
40
  from .utils import (
@@ -61,13 +65,16 @@ class RustSocket:
61
65
  self.command_options = command_options
62
66
  self.logger = logging.getLogger("rustplus.py")
63
67
 
64
- console_handler = logging.StreamHandler()
65
- console_handler.setLevel(logging.DEBUG)
66
- console_handler.setFormatter(
67
- logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
68
- )
69
- self.logger.addHandler(console_handler)
70
- self.logger.setLevel(logging.DEBUG)
68
+ if not self.logger.handlers:
69
+ console_handler = logging.StreamHandler()
70
+ console_handler.setLevel(logging.DEBUG)
71
+ console_handler.setFormatter(
72
+ logging.Formatter(
73
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
74
+ )
75
+ )
76
+ self.logger.addHandler(console_handler)
77
+ self.logger.setLevel(logging.DEBUG)
71
78
 
72
79
  self.ws = RustWebsocket(
73
80
  self.server_details,
@@ -337,7 +344,7 @@ class RustSocket:
337
344
 
338
345
  for marker in map_markers:
339
346
  if add_events:
340
- if marker.type in [2, 4, 5, 6, 8]:
347
+ if marker.type in RustMarker.Events:
341
348
  icon = convert_marker(int(marker.type), marker.rotation)
342
349
  if marker.type == 6:
343
350
  x, y = marker.x, marker.y
@@ -563,3 +570,94 @@ class RustSocket:
563
570
  return RustError("get_camera_manager", response.response.error.error)
564
571
 
565
572
  return CameraManager(self, cam_id, response.response.camera_subscribe_info)
573
+
574
+ async def get_clan_info(self) -> Union[RustClanInfo, RustError]:
575
+ """
576
+ Gets the clan information for the player's current clan.
577
+
578
+ :return RustClanInfo: The clan information
579
+ """
580
+ packet = await self._generate_request(tokens=1)
581
+ packet.get_clan_info = AppEmpty()
582
+ response = await self.ws.send_and_get(packet)
583
+
584
+ if response is None:
585
+ return RustError("get_clan_info", "No response received")
586
+
587
+ if error_present(response):
588
+ return RustError("get_clan_info", response.response.error.error)
589
+
590
+ return RustClanInfo(response.response.clan_info.clan_info)
591
+
592
+ async def get_clan_chat(self) -> Union[List[RustClanMessage], RustError]:
593
+ """
594
+ Gets the clan chat for the player's current clan.
595
+
596
+ :return List[RustClanMessage]: The clan chat
597
+ """
598
+ packet = await self._generate_request(tokens=1)
599
+ packet.get_clan_chat = AppEmpty()
600
+ response = await self.ws.send_and_get(packet)
601
+
602
+ if response is None:
603
+ return RustError("get_clan_chat", "No response received")
604
+
605
+ if error_present(response):
606
+ return RustError("get_clan_chat", response.response.error.error)
607
+
608
+ return [
609
+ RustClanMessage(message) for message in response.response.clan_chat.messages
610
+ ]
611
+
612
+ async def send_clan_message(self, message: str) -> None:
613
+ """
614
+ Sends a message to the in-game clan chat
615
+
616
+ :param message: The string message to send
617
+ """
618
+
619
+ packet = await self._generate_request(tokens=2)
620
+ send_message = AppSendMessage()
621
+ send_message.message = message
622
+ packet.send_clan_message = send_message
623
+
624
+ await self.ws.send_message(packet, True)
625
+
626
+ async def set_clan_motd(self, message: str) -> None:
627
+ """
628
+ Sets the clan's message of the day
629
+
630
+ :param message: The string message to set as the clan's message of the day
631
+ """
632
+
633
+ packet = await self._generate_request()
634
+ send_message = AppSendMessage()
635
+ send_message.message = message
636
+ packet.set_clan_motd = send_message
637
+
638
+ await self.ws.send_message(packet, True)
639
+
640
+ async def get_nexus_auth(self, app_key: str) -> Union[RustAuthDetails, RustError]:
641
+ """
642
+ Gets the auth for a server. Does not require that the player token of this RustSocket is set correctly.
643
+
644
+ :param app_key: The app key to use. I do not know how you would get this currently, without owning the server.
645
+ """
646
+
647
+ packet = await self._generate_request()
648
+ send_message = AppGetNexusAuth()
649
+ send_message.app_key = app_key
650
+ packet.get_nexus_auth = send_message
651
+
652
+ response = await self.ws.send_and_get(packet)
653
+
654
+ if response is None:
655
+ return RustError("get_nexus_auth", "No response received")
656
+
657
+ if error_present(response):
658
+ return RustError("get_nexus_auth", response.response.error.error)
659
+
660
+ return RustAuthDetails(
661
+ response.response.nexus_auth.server_id,
662
+ response.response.nexus_auth.player_token,
663
+ )
@@ -7,5 +7,6 @@ from .rust_team_info import RustTeamInfo, RustTeamMember, RustTeamNote
7
7
  from .rust_entity_info import RustEntityInfo
8
8
  from .rust_contents import RustContents
9
9
  from .rust_item import RustItem
10
- from .util import Vector
10
+ from .util import Vector, RustAuthDetails
11
11
  from .rust_error import RustError
12
+ from .clans import *
@@ -0,0 +1,2 @@
1
+ from .rust_clan_message import RustClanMessage
2
+ from .rust_clan_info import RustClanInfo