Merge branch 'main' into feat/multiplayer-api
This commit is contained in:
@@ -582,6 +582,7 @@ async def process_score(
|
|||||||
session: AsyncSession,
|
session: AsyncSession,
|
||||||
redis: Redis,
|
redis: Redis,
|
||||||
) -> Score:
|
) -> Score:
|
||||||
|
can_get_pp = info.passed and ranked and mods_can_get_pp(info.ruleset_id, info.mods)
|
||||||
score = Score(
|
score = Score(
|
||||||
accuracy=info.accuracy,
|
accuracy=info.accuracy,
|
||||||
max_combo=info.max_combo,
|
max_combo=info.max_combo,
|
||||||
@@ -611,7 +612,7 @@ async def process_score(
|
|||||||
nlarge_tick_hit=info.statistics.get(HitResult.LARGE_TICK_HIT, 0),
|
nlarge_tick_hit=info.statistics.get(HitResult.LARGE_TICK_HIT, 0),
|
||||||
nslider_tail_hit=info.statistics.get(HitResult.SLIDER_TAIL_HIT, 0),
|
nslider_tail_hit=info.statistics.get(HitResult.SLIDER_TAIL_HIT, 0),
|
||||||
)
|
)
|
||||||
if info.passed and ranked and mods_can_get_pp(info.ruleset_id, info.mods):
|
if can_get_pp:
|
||||||
beatmap_raw = await fetcher.get_or_fetch_beatmap_raw(redis, beatmap_id)
|
beatmap_raw = await fetcher.get_or_fetch_beatmap_raw(redis, beatmap_id)
|
||||||
pp = await asyncio.get_event_loop().run_in_executor(
|
pp = await asyncio.get_event_loop().run_in_executor(
|
||||||
None, calculate_pp, score, beatmap_raw
|
None, calculate_pp, score, beatmap_raw
|
||||||
@@ -621,7 +622,7 @@ async def process_score(
|
|||||||
user_id = user.id
|
user_id = user.id
|
||||||
await session.commit()
|
await session.commit()
|
||||||
await session.refresh(score)
|
await session.refresh(score)
|
||||||
if score.passed and ranked:
|
if can_get_pp:
|
||||||
previous_pp_best = await get_user_best_pp_in_beatmap(
|
previous_pp_best = await get_user_best_pp_in_beatmap(
|
||||||
session, beatmap_id, user_id, score.gamemode
|
session, beatmap_id, user_id, score.gamemode
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -241,39 +241,63 @@ class SpectatorHub(Hub[StoreClientState]):
|
|||||||
user_id = int(client.connection_id)
|
user_id = int(client.connection_id)
|
||||||
store = self.get_or_create_state(client)
|
store = self.get_or_create_state(client)
|
||||||
score = store.score
|
score = store.score
|
||||||
|
assert store.beatmap_status is not None
|
||||||
|
assert store.state is not None
|
||||||
|
assert store.score is not None
|
||||||
if not score or not store.score_token:
|
if not score or not store.score_token:
|
||||||
return
|
return
|
||||||
|
if (
|
||||||
|
BeatmapRankStatus.PENDING < store.beatmap_status <= BeatmapRankStatus.LOVED
|
||||||
|
) and any(
|
||||||
|
k.is_hit() and v > 0 for k, v in store.score.score_info.statistics.items()
|
||||||
|
):
|
||||||
|
await self._process_score(store, client)
|
||||||
|
store.state = None
|
||||||
|
store.beatmap_status = None
|
||||||
|
store.checksum = None
|
||||||
|
store.ruleset_id = None
|
||||||
|
store.score_token = None
|
||||||
|
store.score = None
|
||||||
|
await self._end_session(user_id, state)
|
||||||
|
|
||||||
assert store.beatmap_status is not None
|
async def _process_score(self, store: StoreClientState, client: Client) -> None:
|
||||||
|
user_id = int(client.connection_id)
|
||||||
async def _save_replay():
|
assert store.state is not None
|
||||||
assert store.checksum is not None
|
assert store.score_token is not None
|
||||||
assert store.ruleset_id is not None
|
assert store.checksum is not None
|
||||||
assert store.state is not None
|
assert store.ruleset_id is not None
|
||||||
assert store.score is not None
|
assert store.score is not None
|
||||||
async with AsyncSession(engine) as session:
|
async with AsyncSession(engine) as session:
|
||||||
async with session:
|
async with session:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
score_record = None
|
score_record = None
|
||||||
while time.time() - start_time < READ_SCORE_TIMEOUT:
|
while time.time() - start_time < READ_SCORE_TIMEOUT:
|
||||||
sub_query = select(ScoreToken.score_id).where(
|
sub_query = select(ScoreToken.score_id).where(
|
||||||
ScoreToken.id == store.score_token,
|
ScoreToken.id == store.score_token,
|
||||||
|
)
|
||||||
|
result = await session.exec(
|
||||||
|
select(Score)
|
||||||
|
.options(joinedload(Score.beatmap)) # pyright: ignore[reportArgumentType]
|
||||||
|
.where(
|
||||||
|
Score.id == sub_query,
|
||||||
|
Score.user_id == user_id,
|
||||||
)
|
)
|
||||||
result = await session.exec(
|
)
|
||||||
select(Score)
|
score_record = result.first()
|
||||||
.options(joinedload(Score.beatmap)) # pyright: ignore[reportArgumentType]
|
if score_record:
|
||||||
.where(
|
break
|
||||||
Score.id == sub_query,
|
if not score_record:
|
||||||
Score.user_id == user_id,
|
return
|
||||||
)
|
if not score_record.passed:
|
||||||
)
|
return
|
||||||
score_record = result.first()
|
await self.call_noblock(
|
||||||
if score_record:
|
client,
|
||||||
break
|
"UserScoreProcessed",
|
||||||
if not score_record:
|
user_id,
|
||||||
return
|
score_record.id,
|
||||||
if not score_record.passed:
|
)
|
||||||
return
|
# save replay
|
||||||
|
if store.state.state == SpectatedUserState.Passed:
|
||||||
score_record.has_replay = True
|
score_record.has_replay = True
|
||||||
await session.commit()
|
await session.commit()
|
||||||
await session.refresh(score_record)
|
await session.refresh(score_record)
|
||||||
@@ -282,32 +306,11 @@ class SpectatorHub(Hub[StoreClientState]):
|
|||||||
md5=store.checksum,
|
md5=store.checksum,
|
||||||
username=store.score.score_info.user.name,
|
username=store.score.score_info.user.name,
|
||||||
score=score_record,
|
score=score_record,
|
||||||
statistics=score.score_info.statistics,
|
statistics=store.score.score_info.statistics,
|
||||||
maximum_statistics=score.score_info.maximum_statistics,
|
maximum_statistics=store.score.score_info.maximum_statistics,
|
||||||
frames=score.replay_frames,
|
frames=store.score.replay_frames,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
BeatmapRankStatus.PENDING
|
|
||||||
< store.beatmap_status
|
|
||||||
<= BeatmapRankStatus.LOVED
|
|
||||||
)
|
|
||||||
and any(
|
|
||||||
k.is_hit() and v > 0 for k, v in score.score_info.statistics.items()
|
|
||||||
)
|
|
||||||
and state.state != SpectatedUserState.Failed
|
|
||||||
):
|
|
||||||
# save replay
|
|
||||||
await _save_replay()
|
|
||||||
store.state = None
|
|
||||||
store.beatmap_status = None
|
|
||||||
store.checksum = None
|
|
||||||
store.ruleset_id = None
|
|
||||||
store.score_token = None
|
|
||||||
store.score = None
|
|
||||||
await self._end_session(user_id, state)
|
|
||||||
|
|
||||||
async def _end_session(self, user_id: int, state: SpectatorState) -> None:
|
async def _end_session(self, user_id: int, state: SpectatorState) -> None:
|
||||||
if state.state == SpectatedUserState.Playing:
|
if state.state == SpectatedUserState.Playing:
|
||||||
state.state = SpectatedUserState.Quit
|
state.state = SpectatedUserState.Quit
|
||||||
|
|||||||
Reference in New Issue
Block a user