Skip to content

Commit

Permalink
Misc. additions
Browse files Browse the repository at this point in the history
  • Loading branch information
thetestgame committed Nov 11, 2024
1 parent 4912209 commit a89d516
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 9 deletions.
27 changes: 19 additions & 8 deletions panda3d_astron/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
"""
This module contains the AstronClientRepository class, which is a subclass of the ClientRepositoryBase class
from the Panda3D direct.distributed module. This class is used to implement the client-side of the Astron
distributed networking system. It is used to communicate with an Astron ClientAgent instance, which is the
server-side of the Astron distributed networking system.
"""

from direct.directnotify import DirectNotifyGlobal
from direct.distributed.ClientRepositoryBase import ClientRepositoryBase
from direct.distributed.PyDatagram import PyDatagram
Expand All @@ -8,6 +15,7 @@
from direct.distributed import DoInterestManager as interest_mgr

from panda3d_astron import msgtypes
from panda3d_toolbox import runtime

# --------------------------------------------------------------------------------------------------------------------------------------------------------------------- #
# Panda3D ClientRepositoryBase implementation for implementing Astron clients
Expand Down Expand Up @@ -36,7 +44,8 @@ class AstronClientRepository(ClientRepositoryBase):

def __init__(self, *args, **kwargs):
ClientRepositoryBase.__init__(self, *args, **kwargs)
base.finalExitCallbacks.append(self.shutdown)
runtime.base.finalExitCallbacks.append(self.shutdown)

self.message_handlers = {
msgtypes.CLIENT_HELLO_RESP: self.handleHelloResp,
msgtypes.CLIENT_EJECT: self.handleEject,
Expand Down Expand Up @@ -82,7 +91,7 @@ def handleHelloResp(self, di: PyDatagramIterator) -> None:
Handles the CLIENT_HELLO_RESP packet sent by the Client Agent to the client when the client's CLIENT_HELLO is accepted.
"""

messenger.send("CLIENT_HELLO_RESP", [])
runtime.messenger.send("CLIENT_HELLO_RESP", [])

def handleEject(self, di: PyDatagramIterator) -> None:
"""
Expand All @@ -91,7 +100,8 @@ def handleEject(self, di: PyDatagramIterator) -> None:

error_code = di.get_uint16()
reason = di.get_string()
messenger.send("CLIENT_EJECT", [error_code, reason])

runtime.messenger.send("CLIENT_EJECT", [error_code, reason])

def handleEnterObjectRequired(self, di: PyDatagramIterator) -> None:
"""
Expand Down Expand Up @@ -209,7 +219,8 @@ def handleObjectLeaving(self, di):
dist_obj = self.doId2do.get(do_id)
dist_obj.delete()
self.deleteObject(do_id)
messenger.send("CLIENT_OBJECT_LEAVING", [do_id])

runtime.messenger.send("CLIENT_OBJECT_LEAVING", [do_id])

def handleAddInterest(self, di):
"""
Expand All @@ -220,7 +231,7 @@ def handleAddInterest(self, di):
parent_id = di.get_uint32()
zone_id = di.get_uint32()

messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id])
runtime.messenger.send("CLIENT_ADD_INTEREST", [context, interest_id, parent_id, zone_id])
self.addInternalInterestHandle(context, interest_id, parent_id, [zone_id])

def handleAddInterestMultiple(self, di):
Expand All @@ -232,7 +243,7 @@ def handleAddInterestMultiple(self, di):
parent_id = di.get_uint32()
zone_ids = [di.get_uint32() for i in range(0, di.get_uint16())]

messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids])
runtime.messenger.send("CLIENT_ADD_INTEREST_MULTIPLE", [context, interest_id, parent_id, zone_ids])
self.addInternalInterestHandle(context, interest_id, parent_id, zone_ids)

def addInternalInterestHandle(self, context, interest_id, parent_id, zone_ids) -> None:
Expand All @@ -257,7 +268,7 @@ def handleRemoveInterest(self, di):

context = di.get_uint32()
interest_id = di.get_uint16()
messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id])
runtime.messenger.send("CLIENT_REMOVE_INTEREST", [context, interest_id])

def deleteObject(self, doId):
"""
Expand Down Expand Up @@ -384,7 +395,7 @@ def lostConnection(self):
"""
"""

messenger.send("LOST_CONNECTION")
runtime.messenger.send("LOST_CONNECTION")

def disconnect(self):
"""
Expand Down
77 changes: 76 additions & 1 deletion panda3d_astron/interfaces/clientagent.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,68 @@ def set_client_state_established(self, clientChannel: int) -> None:

setClientStateEstablished = set_client_state_established

def set_client_id(self, clientChannel: int, clientId: int) -> None:
"""
Changes the sender used to represent this client. This is useful if application/game components need to identify the avatar/account a given message came from:
by changing the sender channel to include this information, the server can easily determine the account ID of a client that sends a field update.
Note: This also results in the CA opening the new channel, if it isn't open already.
"""

dg = PyDatagram()
dg.addServerHeader(clientChannel, self.air.ourChannel, msgtypes.CLIENTAGENT_SET_CLIENT_ID)
dg.add_uint64(clientId)

self.air.send(dg)

setClientId = set_client_id

def set_client_account_id(self, clientChannel: int, accountId: int) -> None:
"""
Changes the client id associated with the client channel to reflect the account the client is authenticated with. This is useful if application/game components need to identify the account a given message came from.
by changing the sender channel to include this information, the server can easily determine the account ID of a client that sends a field update.
Note: This also results in the CA opening the new channel, if it isn't open already.
"""

dg = PyDatagram()
dg.addServerHeader(clientChannel, self.air.ourChannel, msgtypes.CLIENTAGENT_SET_ACCOUNT_ID)
dg.add_uint64(accountId << 32)

self.air.send(dg)

setAccountId = set_client_account_id

def set_client_avatar_id(self, clientChannel: int, avatarId: int) -> None:
"""
Changes the client id associated with the client channel to reflect the avatar the client is authenticated with. This is useful if application/game components need to identify the avatar a given message came from.
by changing the sender channel to include this information, the server can easily determine the avatar ID of a client that sends a field update.
Note: This also results in the CA opening the new channel, if it isn't open already.
"""

dg = PyDatagram()
dg.addServerHeader(clientChannel, self.air.ourChannel, msgtypes.CLIENTAGENT_SET_AVATAR_ID)
dg.add_uint64(clientChannel << 32 | avatarId)

self.air.send(dg)

setAvatarId = set_client_avatar_id

def remove_client_avatar_id(self, clientChannel: int) -> None:
"""
Changes the client id associated with the client channel to reflect the avatar the client is authenticated with. This is useful if application/game components need to identify the avatar a given message came from.
by changing the sender channel to include this information, the server can easily determine the account ID of a client that sends a field update.
"""

dg = PyDatagram()
dg.addServerHeader(clientChannel, self.air.ourChannel, msgtypes.CLIENTAGENT_SET_AVATAR_ID)
dg.add_uint64(clientChannel << 32)

self.air.send(dg)

removeAvatarId = remove_client_avatar_id

def send_client_datagram(self, clientChannel: int, datagram: object) -> None:
"""
Send a raw datagram down the pipe to the client. This is useful for sending app/game-specific messages to the client, debugging, etc.
Expand Down Expand Up @@ -451,4 +513,17 @@ def handle_client_agent_interest_done_resp(self, di: PyDatagramIterator) -> None
try:
self.__callbacks[ctx](client_channel, interest_id)
finally:
del self.__callbacks[ctx]
del self.__callbacks[ctx]

def send_system_message(self, message: str, clientChannel: int = 10) -> None:
"""
Sends a CLIENT_SYSTEM_MESSAGE to the given client channel.
"""

dg = PyDatagram()
dg.addServerHeader(clientChannel, self.air.ourChannel, msgtypes.CLIENTAGENT_SEND_SYSTEM_MESSAGE)
dg.add_string(message)

self.send_client_datagram(clientChannel, dg)

sendSystemMessage = send_system_message
38 changes: 38 additions & 0 deletions panda3d_astron/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,44 @@ def clear_post_remove(self) -> None:

clearPostRemove = clear_post_remove

def get_account_id_from_channel(self, channel: int) -> int:
"""
Get the account ID of the client connected to the specified channel.
"""

return (channel >> 32) & 0xFFFFFFFF

getAccountIdFromChannel = get_account_id_from_channel

def get_avatar_id_from_channel(self, channel: int) -> int:
"""
Get the avatar ID of the client connected to the specified channel.
"""

return channel & 0xFFFFFFFF

getAvatarIdFromChannel = get_avatar_id_from_channel

def get_account_id_from_sender(self) -> int:
"""
Get the account ID of the sender of the current message. This only works if the
client agent set_client_account_id was called previously.
"""

return self.get_account_id_from_channel(self.getMsgSender())

getAccountIdFromSender = get_account_id_from_sender

def get_avatar_id_from_sender(self) -> int:
"""
Get the avatar ID of the sender of the current message. This only works if the
client agent set_client_id was called previously.
"""

return self.get_avatar_id_from_channel(self.getMsgSender())

getAvatarIdFromSender = get_avatar_id_from_sender

def handle_datagram(self, di: object) -> None:
"""
Handle a datagram received from the Message Director.
Expand Down

0 comments on commit a89d516

Please sign in to comment.