Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add A Clans implementation #54

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
64 changes: 32 additions & 32 deletions rustplus.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ message Vector4 {
}

message Half3 {
optional float x = 1;
optional float y = 2;
optional float z = 3;
optional uint32 x = 1;
optional uint32 y = 2;
optional uint32 z = 3;
}

message Color {
Expand All @@ -37,12 +37,12 @@ message Ray {
optional Vector3 direction = 2;
}

message ClanActionResult {
required int32 requestId = 1;
required int32 result = 2;
required bool hasClanInfo = 3;
optional ClanInfo clanInfo = 4;
}
// message ClanActionResult {
// required int32 requestId = 1;
// required int32 result = 2;
// required bool hasClanInfo = 3;
// optional ClanInfo clanInfo = 4;
// }

message ClanInfo {
required int64 clanId = 1;
Expand Down Expand Up @@ -89,29 +89,29 @@ message ClanInfo {
}
}

message ClanLog {
required int64 clanId = 1;
repeated ClanLog.Entry logEntries = 2;

message Entry {
required int64 timestamp = 1;
required string eventKey = 2;
optional string arg1 = 3;
optional string arg2 = 4;
optional string arg3 = 5;
optional string arg4 = 6;
}
}

message ClanInvitations {
repeated ClanInvitations.Invitation invitations = 1;

message Invitation {
required int64 clanId = 1;
required uint64 recruiter = 2;
required int64 timestamp = 3;
}
}
// message ClanLog {
// required int64 clanId = 1;
// repeated ClanLog.Entry logEntries = 2;
//
// message Entry {
// required int64 timestamp = 1;
// required string eventKey = 2;
// optional string arg1 = 3;
// optional string arg2 = 4;
// optional string arg3 = 5;
// optional string arg4 = 6;
// }
// }

// message ClanInvitations {
// repeated ClanInvitations.Invitation invitations = 1;
//
// message Invitation {
// required int64 clanId = 1;
// required uint64 recruiter = 2;
// required int64 timestamp = 3;
// }
// }

enum AppEntityType {
Switch = 1;
Expand Down
75 changes: 68 additions & 7 deletions rustplus/api/base_rust_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
TeamEvent,
ChatEvent,
ProtobufEvent,
ClanInfoEvent,
)
from ..utils import deprecated
from ..conversation import ConversationFactory
Expand Down Expand Up @@ -320,20 +321,20 @@ def command(
self.remote.command_handler.register_command(cmd_data)
return RegisteredListener(coro.__name__, cmd_data.coro)

def wrap_func(coro):
def wrap_func(coroutine: Union[RegisteredListener, Coroutine]):
if self.command_options is None:
raise CommandsNotEnabledError("Not enabled")

if isinstance(coro, RegisteredListener):
coro = coro.get_coro()
if isinstance(coroutine, RegisteredListener):
coroutine = coroutine.get_coro()

cmd_data = CommandData(
coro,
command_data = CommandData(
coroutine,
aliases,
alias_func,
)
self.remote.command_handler.register_command(cmd_data)
return RegisteredListener(coro.__name__, cmd_data.coro)
self.remote.command_handler.register_command(command_data)
return RegisteredListener(coroutine.__name__, coroutine)

return wrap_func

Expand Down Expand Up @@ -427,6 +428,21 @@ def protobuf_received(self, coro) -> RegisteredListener:
ProtobufEvent.handlers.register(listener, self.server_id)
return listener

def clan_info_event(self, coro) -> RegisteredListener:
"""
A Decorator to register an event listener for clan info being received on the websocket

:param coro: The coroutine to call when the command is called
:return: RegisteredListener - The listener object
"""

if isinstance(coro, RegisteredListener):
coro = coro.get_coro()

listener = RegisteredListener("clan_info_received", coro)
ClanInfoEvent.handlers.register(listener, self.server_id)
return listener

def remove_listener(self, listener) -> bool:
"""
This will remove a listener, command or event. Takes a RegisteredListener instance
Expand All @@ -453,6 +469,10 @@ def remove_listener(self, listener) -> bool:
ProtobufEvent.handlers.unregister(listener, self.server_id)
return True

if ClanInfoEvent.handlers.has(listener, self.server_id):
ClanInfoEvent.handlers.unregister(listener, self.server_id)
return True

return False

@staticmethod
Expand Down Expand Up @@ -635,3 +655,44 @@ async def get_camera_manager(self, cam_id: str) -> CameraManager:
:raises RequestError: If the camera is not found, or you cannot access it. See reason for more info
"""
raise NotImplementedError("Not Implemented")

async def get_clan_info(self) -> Union[RustClanInfo, None]:
"""
Gets the clan info from the server

:return RustClanInfo: The clan info. Will be None if not in a clan
"""
raise NotImplementedError("Not Implemented")

async def get_clan_chat(self) -> List[RustClanMessage]:
"""
Gets the clan chat from the server

:return List[RustClanMessage]: The clan chat messages
"""
raise NotImplementedError("Not Implemented")

async def send_clan_message(self, message: str) -> None:
"""
Sends a message to the clan chat

:param message: The message to send
"""
raise NotImplementedError("Not Implemented")

async def set_clan_motd(self, message: str) -> None:
"""
Sets the clan MOTD

:param message: The message to set
"""
raise NotImplementedError("Not Implemented")

async def get_nexus_player_token(self, app_key: str) -> str:
"""
Gets the Nexus Player Token for the server

:param app_key: The App Key for the server
:return str: The Nexus Player Token
"""
raise NotImplementedError("Not Implemented")
9 changes: 8 additions & 1 deletion rustplus/api/remote/events/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
from .registered_listener import RegisteredListener
from .events import EntityEvent, TeamEvent, ChatEvent, MarkerEvent, ProtobufEvent
from .events import (
EntityEvent,
TeamEvent,
ChatEvent,
MarkerEvent,
ProtobufEvent,
ClanInfoEvent,
)
from .event_loop_manager import EventLoopManager
from .event_handler import EventHandler
27 changes: 25 additions & 2 deletions rustplus/api/remote/events/event_handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import Set, Union

from ...structures import RustChatMessage, RustClanInfo
from ....utils import ServerID
from .events import EntityEvent, TeamEvent, ChatEvent, ProtobufEvent
from .events import EntityEvent, TeamEvent, ChatEvent, ProtobufEvent, ClanInfoEvent
from .registered_listener import RegisteredListener
from ..rustplus_proto import AppMessage

Expand Down Expand Up @@ -33,7 +34,29 @@ async def run_team_event(app_message: AppMessage, server_id: ServerID) -> None:
async def run_chat_event(app_message: AppMessage, server_id: ServerID) -> None:
handlers: Set[RegisteredListener] = ChatEvent.handlers.get_handlers(server_id)
for handler in handlers.copy():
await handler.get_coro()(ChatEvent(app_message))
message = RustChatMessage(app_message.broadcast.team_message.message)
await handler.get_coro()(ChatEvent(message, False, None))

@staticmethod
async def run_clan_chat_event(app_message: AppMessage, server_id: ServerID) -> None:
handlers: Set[RegisteredListener] = ChatEvent.handlers.get_handlers(server_id)
for handler in handlers.copy():
message = RustChatMessage(app_message.broadcast.clan_message.message)
await handler.get_coro()(
ChatEvent(message, True, app_message.broadcast.clan_message.clan_id)
)

@staticmethod
async def run_clan_info_event(app_message: AppMessage, server_id: ServerID) -> None:
handlers: Set[RegisteredListener] = ClanInfoEvent.handlers.get_handlers(
server_id
)
for handler in handlers.copy():
await handler.get_coro()(
ClanInfoEvent(
RustClanInfo(app_message.broadcast.clan_changed.clan_info)
)
)

@staticmethod
async def run_proto_event(byte_data: bytes, server_id: ServerID) -> None:
Expand Down
31 changes: 27 additions & 4 deletions rustplus/api/remote/events/events.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import List
from typing import List, Union

from ..rustplus_proto import AppMessage, AppEntityPayloadItem
from ...structures import RustChatMessage
from ...structures import RustChatMessage, RustClanInfo
from ...structures.rust_team_info import RustTeamInfo
from ...structures.rust_marker import RustMarker
from .handler_list import HandlerList, EntityHandlerList
Expand Down Expand Up @@ -45,13 +45,25 @@ def team_info(self) -> RustTeamInfo:
class ChatEvent:
handlers = HandlerList()

def __init__(self, app_message: AppMessage) -> None:
self._message = RustChatMessage(app_message.broadcast.team_message.message)
def __init__(
self, message: RustChatMessage, is_clan: bool, clan_id: Union[int, None]
) -> None:
self._message = message
self._is_clan = is_clan
self._clan_id = clan_id

@property
def message(self) -> RustChatMessage:
return self._message

@property
def is_clan(self) -> bool:
return self._is_clan

@property
def clan_id(self) -> Union[int, None]:
return self._clan_id


class EntityEvent:
handlers = EntityHandlerList()
Expand Down Expand Up @@ -124,3 +136,14 @@ def __init__(self, byte_data) -> None:
@property
def byte_data(self) -> bytes:
return self._byte_data


class ClanInfoEvent:
handlers = HandlerList()

def __init__(self, clan_info: RustClanInfo) -> None:
self._clan_info = clan_info

@property
def clan_info(self) -> RustClanInfo:
return self._clan_info
7 changes: 4 additions & 3 deletions rustplus/api/remote/rustplus_proto/rustplus.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 23 additions & 4 deletions rustplus/api/remote/rustws.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,10 @@ async def run(self) -> None:

try:
# This creates an asyncio task rather than awaiting the coroutine directly.
# This fixes the bug where if you called a BaseRustSocket#get... from within a RegisteredListener or callback,
# It would hang the websocket. This is because the websocket event loop would be stuck on the callback rather than polling the socket.
# This way, we can schedule the execution of all logic for this message, but continue polling the WS
# This fixes the bug where if you called a BaseRustSocket#get... from within a RegisteredListener or
# callback, It would hang the websocket. This is because the websocket event loop would be stuck on the
# callback rather than polling the socket. This way, we can schedule the execution of all logic for this
# message, but continue polling the WS
await self.run_coroutine_non_blocking(self.handle_message(app_message))
except Exception:
self.logger.exception(
Expand Down Expand Up @@ -276,6 +277,12 @@ async def handle_message(self, app_message: AppMessage) -> None:
# This means that the team of the current player has changed
await EventHandler.run_team_event(app_message, self.server_id)

elif self.is_clan_message(app_message):
await EventHandler.run_clan_chat_event(app_message, self.server_id)

elif self.is_clan_change_info(app_message):
await EventHandler.run_clan_info_event(app_message, self.server_id)

elif self.is_message(app_message):
# This means that a message has been sent to the team chat

Expand Down Expand Up @@ -346,6 +353,18 @@ def is_message(app_message: AppMessage) -> bool:
app_message.broadcast.team_message.message
)

@staticmethod
def is_clan_message(app_message: AppMessage) -> bool:
return betterproto.serialized_on_wire(
app_message.broadcast.clan_message.message
)

@staticmethod
def is_clan_change_info(app_message: AppMessage) -> bool:
return betterproto.serialized_on_wire(
app_message.broadcast.clan_changed.clan_info
)

@staticmethod
def is_camera_broadcast(app_message: AppMessage) -> bool:
return betterproto.serialized_on_wire(app_message.broadcast.camera_rays)
Expand Down Expand Up @@ -386,7 +405,7 @@ def error_present(message) -> bool:
"""
Checks message for error
"""
return message != ""
return message != "" and "clan" not in message

@staticmethod
async def run_coroutine_non_blocking(coroutine: Coroutine) -> Task:
Expand Down
Loading
Loading