Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion server/client_changearea.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,12 @@ def post_area_changed(
msg += f'You note this about the area: `{area_description}`.'
client.send_ooc(msg)


if client.followedby and not ignore_followers:
for c in client.followedby:
c.follow_area(area)

for c in area.clients:
if c == client:
continue
if c.packet_handler.USES_2d0d0_CHARACTER_PACKETS:
c.refresh_visible_char_list()
113 changes: 72 additions & 41 deletions server/client_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,11 +978,20 @@ def change_character(self, char_id: int, force: bool = False,
.format(self.id, old_char, self.char_folder, self.area.id),
is_zstaff=target_area, in_hub=target_area.hub)

self.send_command_dict('PV', {
'client_id': self.id,
'char_id_tag': 'CID',
'char_id': self.char_id,
})
if self.packet_handler.USES_2d0d0_CHARACTER_PACKETS:
if has_char_after:
self.send_command_dict('character', {
'char_name': new_char,
})
else:
self.send_command_dict('spectator', dict())

else:
self.send_command_dict('PV', {
'client_id': self.id,
'char_id_tag': 'CID',
'char_id': self.char_id,
})
self.publisher.publish('client_change_character', {
'old_char_id': old_char_id,
'old_char_name': old_char,
Expand Down Expand Up @@ -1741,40 +1750,56 @@ def prepare_area_info(self, current_area: AreaManager.Area, area_id: int,
return info

def refresh_char_list(self):
char_list = [0] * len(self.hub.character_manager.get_characters())
unusable_ids = self.area.get_chars_unusable(allow_restricted=self.is_staff())
# Remove sneaked players from unusable if needed so that they don't appear as taken
# Their characters will not be able to be reused, but at least that's one less clue
# about their presence.
if not self.is_staff():
unusable_ids -= {c.char_id for c in self.area.clients if not c.is_visible}

for x in unusable_ids:
char_list[x] = -1

if self.has_participant_character():
char_list[self.char_id] = 0 # Self is always available
self.send_command_dict('CharsCheck', {
'chars_status_ao2_list': char_list,
})
if self.packet_handler.USES_2d0d0_CHARACTER_PACKETS:
for c in self.area.clients:
char_name = c.get_char_name()
self.send_command_dict('roster_slot', {
'char_name': char_name,
'char_count': 1,
})
else:
char_list = [0] * len(self.hub.character_manager.get_characters())
unusable_ids = self.area.get_chars_unusable(allow_restricted=self.is_staff())
# Remove sneaked players from unusable if needed so that they don't appear as taken
# Their characters will not be able to be reused, but at least that's one less clue
# about their presence.
if not self.is_staff():
unusable_ids -= {c.char_id for c in self.area.clients if not c.is_visible}

for x in unusable_ids:
char_list[x] = -1

if self.has_participant_character():
char_list[self.char_id] = 0 # Self is always available
self.send_command_dict('CharsCheck', {
'chars_status_ao2_list': char_list,
})

def refresh_visible_char_list(self):
char_list = [0] * len(self.hub.character_manager.get_characters())
unusable_ids = {c.char_id for c in self.get_visible_clients(self.area)
if c.has_participant_character()}
if not self.is_staff():
unusable_ids |= {self.hub.character_manager.get_character_id_by_name(name)
for name in self.area.restricted_chars}

for x in unusable_ids:
char_list[x] = -1

# Self is always available
if self.has_participant_character():
char_list[self.char_id] = 0
self.send_command_dict('CharsCheck', {
'chars_status_ao2_list': char_list,
})
if self.packet_handler.USES_2d0d0_CHARACTER_PACKETS:
for c in self.get_visible_clients(self.area):
char_name = c.get_char_name()
self.send_command_dict('roster_slot', {
'char_name': char_name,
'char_count': 1,
})
else:
char_list = [0] * len(self.hub.character_manager.get_characters())
unusable_ids = {c.char_id for c in self.get_visible_clients(self.area)
if c.has_participant_character()}
if not self.is_staff():
unusable_ids |= {self.hub.character_manager.get_character_id_by_name(name)
for name in self.area.restricted_chars}

for x in unusable_ids:
char_list[x] = -1

# Self is always available
if self.has_participant_character():
char_list[self.char_id] = 0
self.send_command_dict('CharsCheck', {
'chars_status_ao2_list': char_list,
})

def send_done(self):
self.refresh_visible_char_list()
Expand All @@ -1785,10 +1810,16 @@ def send_done(self):
self.send_command_dict('DONE', dict())

def char_select(self):
# By running the change_character code, all checks and actions for switching to
# spectator are made
self.change_character(-1)
self.send_done()
if self.packet_handler.USES_2d0d0_CHARACTER_PACKETS:
# TODO: WARNING.
# This code currently does not do everything the "else" currently does
# Proceed with caution.
self.send_command_dict('SELECT_CHARACTER', dict())
else:
# By running the change_character code, all checks and actions for switching to
# spectator are made
self.change_character(-1)
self.send_done()

def get_party(self, tc=False):
if not self.party:
Expand Down
28 changes: 28 additions & 0 deletions server/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __eq__(self, other):
ALLOWS_INVISIBLE_BLANKPOSTS = True
REPLACES_BASE_OPUS_FOR_MP3 = False
ALLOWS_CHAR_LIST_RELOAD = True
USES_2d0d0_CHARACTER_PACKETS = False

DECRYPTOR_OUTBOUND = [
('key', 34), # 0
Expand Down Expand Up @@ -338,6 +339,33 @@ def __eq__(self, other):
]


class ClientDRO2d0d0(DefaultDROProtocol):
VERSION_TO_SEND = [2, 0, 0]
USES_2d0d0_CHARACTER_PACKETS = True

SELECT_CHARACTER_OUTBOUND = [
]

SPECTATOR_INBOUND = [
]

SPECTATOR_OUTBOUND = [
]

ROSTER_SLOT_OUTBOUND = [
('char_name', ''), # 0
('char_count', 0), # 1
]

CHARACTER_INBOUND = [
('char_name', ArgType.STR), # 0
]

CHARACTER_OUTBOUND = [
('char_name', ''), # 0
]


class ClientDRO1d2d2(DefaultDROProtocol):
VERSION_TO_SEND = [1, 2, 2]

Expand Down
32 changes: 29 additions & 3 deletions server/network/ao_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@ def check_client_version():

if software == 'DRO':
if release >= 2:
# DRO 2???
# Placeholder
client.packet_handler = clients.ClientDRO1d2d2()
client.packet_handler = clients.ClientDRO2d0d0()
elif release >= 1:
if major >= 2:
if minor >= 2:
Expand Down Expand Up @@ -941,6 +939,7 @@ def net_cmd_charscheck(client: ClientManager.Client, pargs: Dict[str, Any]):

client.refresh_visible_char_list()


def net_cmd_fs(client: ClientManager.Client, pargs: Dict[str, Any]):
"""
Files set.
Expand All @@ -956,3 +955,30 @@ def net_cmd_pw(self, _):
# Well, not empty, there are these comments which makes it not empty
# but not code is run.
return


def net_cmd_spectator(client: ClientManager.Client, pargs: Dict[str, Any]):
"""
Request to change to spectator.
"""

net_cmd_cc(client, {
'client_id': client.id,
'char_id': -1,
'client_hdid': client.hdid,
})


def net_cmd_character(client: ClientManager.Client, pargs: Dict[str, Any]):
"""
Request to change to a particular character.
"""

char_name = pargs['char_name']
new_id = client.hub.character_manager.get_character_id_by_name(char_name)

net_cmd_cc(client, {
'client_id': client.id,
'char_id': new_id,
'client_hdid': client.hdid,
})
4 changes: 4 additions & 0 deletions server/network/ao_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,4 +333,8 @@ def data_send(self, command: str, *args: List):
needs_auth=True), # character availability request
'FS': _command(function=ao_commands.net_cmd_fs,
needs_auth=True), # set files
'spectator': _command(function=ao_commands.net_cmd_spectator,
needs_auth=True), # change to spectator
'character': _command(function=ao_commands.net_cmd_character,
needs_auth=True), # change to character
}