Skip to content

Commit

Permalink
Merge pull request #341 from osuTitanic/dev
Browse files Browse the repository at this point in the history
Add command threading, peppy message handler & code cleanup
  • Loading branch information
Lekuruu authored May 21, 2024
2 parents 1227c50 + eca8220 commit de1b346
Show file tree
Hide file tree
Showing 23 changed files with 352 additions and 301 deletions.
2 changes: 1 addition & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from . import server
from . import events
from . import common
from . import jobs
from . import tasks
161 changes: 88 additions & 73 deletions app/clients/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from . import DefaultRequestPacket as RequestPacket

from ..common.database.objects import DBBeatmap, DBScore
from ..common.database.repositories import wrapper
from ..objects.multiplayer import Match
from ..objects.channel import Channel
from ..objects.player import Player
Expand Down Expand Up @@ -55,25 +56,23 @@ def wrapper(func) -> Callable:

return wrapper

@wrapper.exception_wrapper()
def resolve_channel(channel_name: str, player: Player) -> Optional[Channel]:
try:
if channel_name == '#spectator':
# Select spectator chat
return (
player.spectating.spectator_chat
if player.spectating else
player.spectator_chat
)
if channel_name == '#spectator':
# Select spectator chat
return (
player.spectating.spectator_chat
if player.spectating else
player.spectator_chat
)

elif channel_name == '#multiplayer':
# Select multiplayer chat
return player.match.chat
elif channel_name == '#multiplayer':
# Select multiplayer chat
return player.match.chat

# Resolve channel by name
if channel := session.channels.by_name(channel_name):
return channel
except AttributeError:
return
# Resolve channel by name
if channel := session.channels.by_name(channel_name):
return channel

@register(RequestPacket.PONG)
def pong(player: Player):
Expand All @@ -89,10 +88,16 @@ def receive_updates(player: Player, filter: PresenceFilter):
player.filter = filter

if filter.value <= 0:
# Client set filter to "None"
# No players will be sent
return

players = session.players if filter == PresenceFilter.All else \
player.online_friends
# Account for player filter
players = (
session.players
if filter == PresenceFilter.All
else player.online_friends
)

player.enqueue_players(players, stats_only=True)

Expand Down Expand Up @@ -206,6 +211,11 @@ def send_message(player: Player, message: bMessage):

@register(RequestPacket.SEND_PRIVATE_MESSAGE)
def send_private_message(sender: Player, message: bMessage):
if message.target == 'peppy':
# This could be an internal osu! anti-cheat message
officer.call(f'{sender.name} tried to message peppy: "{message.content}"')
return

if not (target := session.players.by_name(message.target)):
sender.revoke_channel(message.target)
return
Expand Down Expand Up @@ -290,7 +300,7 @@ def send_private_message(sender: Player, message: bMessage):
messages.create(
sender.name,
target.name,
message.content
message.content[:512]
)

sender.update_activity()
Expand All @@ -311,17 +321,18 @@ def away_message(player: Player, message: bMessage):
is_private=True
)
)
else:
player.away_message = None
player.enqueue_message(
bMessage(
session.bot_player.name,
'You are no longer marked as being away',
session.bot_player.name,
session.bot_player.id,
is_private=True
)
return

player.away_message = None
player.enqueue_message(
bMessage(
session.bot_player.name,
'You are no longer marked as being away',
session.bot_player.name,
session.bot_player.id,
is_private=True
)
)

@register(RequestPacket.ADD_FRIEND)
def add_friend(player: Player, target_id: int):
Expand Down Expand Up @@ -377,9 +388,7 @@ def beatmap_info(player: Player, info: bBeatmapInfoRequest, ignore_limit: bool =
if total_maps <= 0:
return

player.logger.info(
f'Got {total_maps} beatmap requests'
)
player.logger.info(f'Got {total_maps} beatmap requests')

# Fetch all matching beatmaps from database
with session.database.managed_session() as s:
Expand Down Expand Up @@ -420,14 +429,19 @@ def beatmap_info(player: Player, info: bBeatmapInfoRequest, ignore_limit: bool =
map_infos: List[bBeatmapInfo] = []

for index, beatmap in maps:
if beatmap.status <= -3:
# Not submitted
continue

ranked = {
-2: 0, # Graveyard: Pending
-1: 0, # WIP: Pending
0: 0, # Pending: Pending
1: 1, # Ranked: Ranked
2: 2, # Approved: Approved
3: 2, # Qualified: Approved
4: 2, # Loved: Approved
-3: -1, # Not submitted
-2: 0, # Graveyard: Pending
-1: 0, # WIP: Pending
0: 0, # Pending: Pending
1: 1, # Ranked: Ranked
2: 2, # Approved: Approved
3: 2, # Qualified: Approved
4: 2, # Loved: Approved
}[beatmap.status]

# Get personal best in every mode for this beatmap
Expand All @@ -454,12 +468,12 @@ def beatmap_info(player: Player, info: bBeatmapInfoRequest, ignore_limit: bool =
index,
beatmap.id,
beatmap.set_id,
beatmap.set_id, # thread_id
beatmap.set_id, # ThreadId
ranked,
grades[0], # standard
grades[2], # fruits
grades[1], # taiko
grades[3], # mania
grades[0], # Standard
grades[2], # Fruits
grades[1], # Taiko
grades[3], # Mania
beatmap.md5
)
)
Expand Down Expand Up @@ -489,7 +503,6 @@ def start_spectating(player: Player, player_id: int):

if (player.spectating or player in target.spectators) and not player.is_tourney_client:
stop_spectating(player)
# TODO: return here?

player.logger.info(f'Started spectating "{target.name}".')
player.spectating = target
Expand Down Expand Up @@ -585,7 +598,6 @@ def invite(player: Player, target_id: int):
return

# TODO: Check invite spams

target.enqueue_invite(
bMessage(
player.name,
Expand Down Expand Up @@ -747,10 +759,11 @@ def leave_match(player: Player):
slot = player.match.get_slot(player)
assert slot is not None

if slot.status == SlotStatus.Locked:
status = SlotStatus.Locked
else:
status = SlotStatus.Open
status = (
SlotStatus.Locked
if slot.status == SlotStatus.Locked
else SlotStatus.Open
)

slot.reset(status)

Expand All @@ -776,12 +789,12 @@ def leave_match(player: Player):
player.match.beatmap_name = player.match.previous_beatmap_name

if all(slot.empty for slot in player.match.slots):
# No players in match anymore -> Disband match
player.enqueue_match_disband(player.match.id)

for p in session.players.in_lobby:
p.enqueue_match_disband(player.match.id)

# Match is empty
session.matches.remove(player.match)
player.match.starting = None

Expand All @@ -800,25 +813,26 @@ def leave_match(player: Player):
events.create(match_id, type=EventType.Disband)

player.match.logger.info('Match was disbanded.')
else:
if player is player.match.host:
# Player was host, transfer to next player
for slot in player.match.slots:
if slot.status.value & SlotStatus.HasPlayer.value:
player.match.host = slot.player
player.match.host.enqueue_match_transferhost()

events.create(
player.match.db_match.id,
type=EventType.Host,
data={
'previous': {'id': player.id, 'name': player.name},
'new': {'id': player.match.host.id, 'name': player.match.host.name}
}
)
player.match = None
return

player.match.update()
if player is player.match.host:
# Player was host, transfer to next player
for slot in player.match.slots:
if slot.status.value & SlotStatus.HasPlayer.value:
player.match.host = slot.player
player.match.host.enqueue_match_transferhost()

events.create(
player.match.db_match.id,
type=EventType.Host,
data={
'previous': {'id': player.id, 'name': player.name},
'new': {'id': player.match.host.id, 'name': player.match.host.name}
}
)

player.match.update()
player.match = None

@register(RequestPacket.MATCH_CHANGE_SLOT)
Expand Down Expand Up @@ -905,7 +919,7 @@ def change_mods(player: Player, mods: Mods):

if player.match.freemod:
if player is player.match.host:
# Onky keep SpeedMods
# Only keep SpeedMods
player.match.mods = mods & Mods.SpeedMods

# There is a bug, where DT and NC are enabled at the same time
Expand Down Expand Up @@ -1007,10 +1021,11 @@ def lock(player: Player, slot_id: int):
if slot.has_player:
player.match.kick_player(slot.player)

if slot.status == SlotStatus.Locked:
slot.status = SlotStatus.Open
else:
slot.status = SlotStatus.Locked
slot.status = (
SlotStatus.Open
if slot.status == SlotStatus.Locked
else SlotStatus.Locked
)

player.match.update()

Expand Down
8 changes: 8 additions & 0 deletions app/clients/versions/b20121223/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ def wrapper(func) -> Callable:
@register(RequestPacket.SEND_MESSAGE)
def message(stream: StreamIn):
return Reader(stream).read_message()

@register(RequestPacket.SEND_PRIVATE_MESSAGE)
def private_message(stream: StreamIn):
return Reader(stream).read_message()

@register(RequestPacket.SET_AWAY_MESSAGE)
def away_message(stream: StreamIn):
return Reader(stream).read_message()
18 changes: 18 additions & 0 deletions app/clients/versions/b20121223/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,21 @@ def message(message: bMessage):
writer = Writer()
writer.write_message(message)
return writer.stream.get()

@register(ResponsePacket.TARGET_IS_SILENCED)
def target_silenced(msg: bMessage):
writer = Writer()
writer.write_message(msg)
return writer.stream.get()

@register(ResponsePacket.USER_DM_BLOCKED)
def dm_blocked(msg: bMessage):
writer = Writer()
writer.write_message(msg)
return writer.stream.get()

@register(ResponsePacket.INVITE)
def match_invite(msg: bMessage):
writer = Writer()
writer.write_message(msg)
return writer.stream.get()
1 change: 1 addition & 0 deletions app/clients/versions/b388/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def beatmap_info_reply(reply: bBeatmapInfoReply):
for info in reply.beatmaps:
# Approved status does not exist
info.ranked = {
-1: -1,
0: 0,
1: 1,
2: 1
Expand Down
Loading

0 comments on commit de1b346

Please sign in to comment.