mirror of
https://github.com/solero/houdini.git
synced 2024-11-21 13:07:21 +00:00
Improve stamps end screen (#101)
* properly handle players exiting cardjitsu water * make end screens only show stamps from current session * add card-jitsu end game screen * fix oversight with how water players get removed * fix card jitsu fire stamp awards * change session stamps to use redis
This commit is contained in:
parent
f6f9f39c22
commit
e23a7ecf2e
@ -78,30 +78,34 @@ async def handle_get_game_over(p, score: int):
|
||||
if p.room.id == 996:
|
||||
return
|
||||
|
||||
if p.room.game and not p.waddle and not p.table:
|
||||
# card-jitsus except snow have special handling
|
||||
card_jitsu_rooms = [995, 998, 997]
|
||||
is_card_jitsu = p.room.id in card_jitsu_rooms
|
||||
|
||||
# Waddle minigames don't normally need the end screen
|
||||
if p.waddle and not is_card_jitsu:
|
||||
return
|
||||
|
||||
if p.room.game and not p.table:
|
||||
coins_earned = determine_coins_earned(p, score)
|
||||
if await determine_coins_overdose(p, coins_earned):
|
||||
return await cheat_ban(p, p.id, comment='Coins overdose')
|
||||
|
||||
collected_stamps_string, total_collected_stamps, total_game_stamps, total_stamps = '', 0, 0, 0
|
||||
if not is_card_jitsu:
|
||||
if await determine_coins_overdose(p, coins_earned):
|
||||
return await cheat_ban(p, p.id, comment="Coins overdose")
|
||||
|
||||
stamp_info = "", 0, 0, 0
|
||||
|
||||
if p.room.stamp_group:
|
||||
game_stamps = [stamp for stamp in p.server.stamps.values() if stamp.group_id == p.room.stamp_group]
|
||||
collected_stamps = [stamp for stamp in game_stamps if stamp.id in p.stamps]
|
||||
|
||||
total_stamps = len([stamp for stamp in p.stamps.values() if p.server.stamps[stamp.stamp_id].group_id])
|
||||
total_collected_stamps = len(collected_stamps)
|
||||
total_game_stamps = len(game_stamps)
|
||||
collected_stamps_string = '|'.join(str(stamp.id) for stamp in collected_stamps)
|
||||
|
||||
if total_collected_stamps == total_game_stamps:
|
||||
stamp_info = await p.get_game_end_stamps_info(True)
|
||||
# has all stamps in game
|
||||
if stamp_info[1] == stamp_info[2]:
|
||||
coins_earned *= 2
|
||||
|
||||
await p.update(coins=min(p.coins + coins_earned, p.server.config.max_coins)).apply()
|
||||
await p.send_xt('zo', p.coins,
|
||||
collected_stamps_string,
|
||||
total_collected_stamps,
|
||||
total_game_stamps,
|
||||
total_stamps)
|
||||
if not is_card_jitsu:
|
||||
await p.update(
|
||||
coins=min(p.coins + coins_earned, p.server.config.max_coins)
|
||||
).apply()
|
||||
await p.send_xt("zo", p.coins, *stamp_info)
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('ggd', ext='z'), client=ClientType.Vanilla)
|
||||
@ -146,3 +150,10 @@ async def handle_game_complete(p, medals: int):
|
||||
medals = min(6, medals)
|
||||
await p.update(career_medals=p.career_medals + medals,
|
||||
agent_medals=p.agent_medals + medals).apply()
|
||||
|
||||
|
||||
@handlers.disconnected
|
||||
@handlers.player_attribute(joined_world=True)
|
||||
async def clear_stamp_sessions(p):
|
||||
"""When disconnected, clear stamps in case any were obtained and not properly handled"""
|
||||
await p.clear_stamps_session()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import itertools
|
||||
import math
|
||||
import random
|
||||
import enum
|
||||
from collections import Counter
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Union
|
||||
@ -10,6 +11,19 @@ from houdini.data.ninja import Card
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.penguin import Penguin
|
||||
|
||||
class CardStamp(enum.IntEnum):
|
||||
"""ID of Card-Jitsu stamps"""
|
||||
GRASSHOPPER = 230
|
||||
ELEMENTAL_WIN = 242
|
||||
FINE_STUDENT = 232
|
||||
FLAWLESS_VICTORY = 238
|
||||
ONE_ELEMENT = 244
|
||||
TRUE_NINJA = 234
|
||||
MATCH_MASTER = 240
|
||||
NINJA_MASTER = 236
|
||||
SENSEI_CARD = 246
|
||||
FULL_DOJO = 248
|
||||
|
||||
|
||||
@dataclass
|
||||
class Played:
|
||||
@ -44,7 +58,12 @@ class CardJitsuLogic(IWaddle):
|
||||
|
||||
ItemAwards = [4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 104]
|
||||
PostcardAwards = {0: 177, 4: 178, 8: 179}
|
||||
StampAwards = {0: 230, 4: 232, 8: 234, 9: 236}
|
||||
StampAwards = {
|
||||
0: CardStamp.GRASSHOPPER,
|
||||
4: CardStamp.FINE_STUDENT,
|
||||
8: CardStamp.TRUE_NINJA,
|
||||
9: CardStamp.NINJA_MASTER,
|
||||
}
|
||||
StampGroupId = 38
|
||||
|
||||
def __init__(self, waddle):
|
||||
@ -235,7 +254,7 @@ async def ninja_rank_up(p, ranks=1):
|
||||
if rank in CardJitsuLogic.PostcardAwards:
|
||||
await p.add_inbox(p.server.postcards[CardJitsuLogic.PostcardAwards[rank]])
|
||||
if rank in CardJitsuLogic.StampAwards:
|
||||
await p.add_stamp(p.server.stamps[CardJitsuLogic.StampAwards[rank]])
|
||||
await p.add_card_jitsu_stamp(CardJitsuLogic.StampAwards[rank])
|
||||
await p.update(ninja_rank=p.ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
@ -266,20 +285,10 @@ async def ninja_progress(p, won=False):
|
||||
await ninja_rank_up(p)
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
|
||||
async def ninja_stamps_earned(p):
|
||||
game_stamps = [stamp for stamp in p.server.stamps.values() if stamp.group_id == p.room.stamp_group]
|
||||
collected_stamps = [stamp for stamp in game_stamps if stamp.id in p.stamps]
|
||||
total_collected_stamps = len(collected_stamps)
|
||||
total_game_stamps = len(game_stamps)
|
||||
collected_stamps_string = '|'.join(str(stamp.id) for stamp in collected_stamps)
|
||||
await p.send_xt('cjsi', collected_stamps_string, total_collected_stamps, total_game_stamps)
|
||||
|
||||
|
||||
async def ninja_win(winner, loser):
|
||||
await ninja_progress(winner.penguin, won=True)
|
||||
await ninja_progress(loser.penguin, won=False)
|
||||
await ninja_stamps_earned(winner.penguin)
|
||||
await ninja_stamps_earned(loser.penguin)
|
||||
await winner.penguin.waddle.remove_penguin(winner.penguin)
|
||||
await loser.penguin.waddle.remove_penguin(loser.penguin)
|
||||
|
||||
@ -304,6 +313,8 @@ async def handle_update_game(p):
|
||||
@handlers.handler(XTPacket('lz', ext='z'))
|
||||
@handlers.waddle(CardJitsuLogic, CardJitsuMatLogic, SenseiLogic)
|
||||
async def handle_leave_game(p):
|
||||
# sending stamp info fixes the game taking a bit to close when quitting
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
seat_id = p.waddle.get_seat_id(p)
|
||||
await p.waddle.send_xt('cz', p.safe_name, f=lambda penguin: penguin is not p)
|
||||
await p.waddle.send_xt('lz', seat_id, f=lambda penguin: penguin is not p)
|
||||
@ -357,9 +368,8 @@ async def handle_send_pick(p, action: str, card_id: int):
|
||||
winner_seat_id = p.waddle.get_round_winner()
|
||||
|
||||
if me.chosen.card.id == 256 or opponent.chosen.card.id == 256:
|
||||
stamp = p.server.stamps[246]
|
||||
await me.penguin.add_stamp(stamp, notify=True)
|
||||
await opponent.penguin.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
await opponent.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
|
||||
if me.chosen.card.power_id and me.chosen.card.power_id in CardJitsuLogic.OnPlayed:
|
||||
await p.waddle.send_xt('zm', 'power', seat_id, opponent_seat_id, me.chosen.card.power_id)
|
||||
@ -383,19 +393,18 @@ async def handle_send_pick(p, action: str, card_id: int):
|
||||
if winning_cards:
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id, *(card.id for card in winning_cards))
|
||||
|
||||
stamp = p.server.stamps[[244, 242][win_method]]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
stamp = [CardStamp.ONE_ELEMENT, CardStamp.ELEMENTAL_WIN][win_method]
|
||||
await winner.penguin.add_card_jitsu_stamp(stamp)
|
||||
if all(not cards for cards in loser.bank.values()):
|
||||
stamp = p.server.stamps[238]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(
|
||||
CardStamp.FLAWLESS_VICTORY
|
||||
)
|
||||
if sum(1 for cards in winner.bank.values() for _ in cards) >= 9:
|
||||
stamp = p.server.stamps[248]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(CardStamp.FULL_DOJO)
|
||||
|
||||
await winner.penguin.update(ninja_matches_won=winner.penguin.ninja_matches_won+1).apply()
|
||||
if winner.penguin.ninja_matches_won == 25:
|
||||
stamp = p.server.stamps[240]
|
||||
await winner.penguin.add_stamp(stamp, notify=True)
|
||||
await winner.penguin.add_card_jitsu_stamp(CardStamp.MATCH_MASTER)
|
||||
|
||||
await ninja_win(winner, loser)
|
||||
else:
|
||||
@ -493,8 +502,7 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
winner_seat_id = p.waddle.get_round_winner()
|
||||
|
||||
if me.chosen.card.id == 256 or sensei.chosen.card.id == 256:
|
||||
stamp = p.server.stamps[246]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.SENSEI_CARD)
|
||||
|
||||
if me.chosen.card.power_id and me.chosen.card.power_id in CardJitsuLogic.OnPlayed:
|
||||
await p.send_xt('zm', 'power', 1, 0, me.chosen.card.power_id)
|
||||
@ -518,21 +526,17 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id, *(card.id for card in winning_cards))
|
||||
|
||||
if winner == me:
|
||||
stamp = p.server.stamps[[244, 242][win_method]]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
stamp = [CardStamp.ONE_ELEMENT, CardStamp.ELEMENTAL_WIN][win_method]
|
||||
await me.penguin.add_card_jitsu_stamp(stamp)
|
||||
if all(not cards for cards in sensei.bank.values()):
|
||||
stamp = p.server.stamps[238]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.FLAWLESS_VICTORY)
|
||||
if sum(1 for cards in me.bank.values() for _ in cards) >= 9:
|
||||
stamp = p.server.stamps[248]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.FULL_DOJO)
|
||||
|
||||
await p.update(ninja_matches_won=p.ninja_matches_won + 1).apply()
|
||||
if p.ninja_matches_won == 25:
|
||||
stamp = p.server.stamps[240]
|
||||
await p.add_stamp(stamp, notify=True)
|
||||
await me.penguin.add_card_jitsu_stamp(CardStamp.MATCH_MASTER)
|
||||
|
||||
await ninja_stamps_earned(p)
|
||||
can_rank_up = await ninja_rank_up(p)
|
||||
if can_rank_up:
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
@ -548,7 +552,6 @@ async def handle_send_sensei_pick(p, action: str, card_id: int):
|
||||
if can_rank_up:
|
||||
await p.send_xt('cza', p.ninja_rank)
|
||||
await p.waddle.send_xt('czo', 0, winner_seat_id)
|
||||
await ninja_stamps_earned(p)
|
||||
|
||||
await p.send_xt('zm', 'judge', winner_seat_id)
|
||||
me.chosen = None
|
||||
|
@ -2,6 +2,7 @@ import asyncio
|
||||
import itertools
|
||||
import math
|
||||
import random
|
||||
import enum
|
||||
from collections import Counter
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Union
|
||||
@ -9,9 +10,18 @@ from typing import List, Union
|
||||
from houdini import IWaddle, handlers
|
||||
from houdini.data.ninja import Card
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.handlers.games.ninja.card import ninja_stamps_earned
|
||||
from houdini.penguin import Penguin
|
||||
|
||||
class FireStamp(enum.IntEnum):
|
||||
"""IDs of Card-Jitsu Fire stamps"""
|
||||
WARM_UP = 252
|
||||
SCORE_FIRE = 254
|
||||
FIRE_MIDWAY = 256
|
||||
STRONG_DEFENCE = 260
|
||||
FIRE_SUIT = 262
|
||||
FIRE_NINJA = 264
|
||||
MAX_ENERGY = 266
|
||||
FIRE_EXPERT = 268
|
||||
|
||||
@dataclass
|
||||
class FireNinja:
|
||||
@ -37,7 +47,7 @@ class CardJitsuFireLogic(IWaddle):
|
||||
AutoBattleTimeout = 22
|
||||
|
||||
ItemAwards = [6025, 4120, 2013, 1086, 3032]
|
||||
StampAwards = {2: 256, 4: 262}
|
||||
StampAwards = {1: FireStamp.FIRE_MIDWAY, 3: FireStamp.FIRE_SUIT}
|
||||
|
||||
def __init__(self, waddle):
|
||||
super().__init__(waddle)
|
||||
@ -524,7 +534,7 @@ async def fire_ninja_rank_up(p, ranks=1):
|
||||
for rank in range(p.fire_ninja_rank, p.fire_ninja_rank+ranks):
|
||||
await p.add_inventory(p.server.items[CardJitsuFireLogic.ItemAwards[rank]], notify=False)
|
||||
if rank in CardJitsuFireLogic.StampAwards:
|
||||
await p.add_stamp(p.server.stamps[CardJitsuFireLogic.StampAwards[rank]])
|
||||
await p.add_card_jitsu_stamp(CardJitsuFireLogic.StampAwards[rank])
|
||||
await p.update(
|
||||
fire_ninja_rank=p.fire_ninja_rank + ranks
|
||||
).apply()
|
||||
@ -567,18 +577,18 @@ async def end_game_stamps(ninja, finish_position):
|
||||
if finish_position == 1:
|
||||
await ninja.penguin.update(fire_matches_won=ninja.penguin.fire_matches_won + 1).apply()
|
||||
if ninja.penguin.fire_matches_won >= 10:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[252])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.WARM_UP)
|
||||
if ninja.penguin.fire_matches_won >= 50:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[268])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.FIRE_EXPERT)
|
||||
if ninja.energy >= 6:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[260])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.STRONG_DEFENCE)
|
||||
if type(ninja.penguin.waddle) == FireSenseiLogic:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[264])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.FIRE_NINJA)
|
||||
|
||||
if ninja.energy_won >= 1:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[254])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.SCORE_FIRE)
|
||||
if ninja.energy_won >= 3:
|
||||
await ninja.penguin.add_stamp(ninja.penguin.server.stamps[266])
|
||||
await ninja.penguin.add_card_jitsu_stamp(FireStamp.MAX_ENERGY)
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('gz', ext='z'))
|
||||
@ -665,5 +675,5 @@ async def handle_info_ready_sync(p):
|
||||
|
||||
@handlers.handler(XTPacket('lz', ext='z'))
|
||||
@handlers.player_in_room(CardJitsuFireLogic.room_id)
|
||||
async def handle_leave_game(p):
|
||||
await ninja_stamps_earned(p)
|
||||
async def handle_leave_game(p: Penguin):
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
|
@ -12,6 +12,17 @@ from houdini.handlers import XTPacket
|
||||
from houdini.penguin import Penguin
|
||||
from houdini.data.ninja import Card
|
||||
|
||||
class WaterStamp(enum.IntEnum):
|
||||
"IDs of Card-Jitsu Water stamps"
|
||||
GONG = 270
|
||||
WATERY_FALL = 274
|
||||
WATER_EXPERT = 276
|
||||
WATER_MIDWAY = 278
|
||||
WATER_SUIT = 282
|
||||
WATER_NINJA = 284
|
||||
TWO_CLOSE = 286
|
||||
SKIPPING_STONES = 288
|
||||
|
||||
|
||||
@dataclass
|
||||
class WaterCard:
|
||||
@ -252,6 +263,13 @@ class WaterPlayer:
|
||||
cleared: int = 0
|
||||
"""Number of stones cleared in the match"""
|
||||
|
||||
left: bool = False
|
||||
"""
|
||||
Whether the player has left the game
|
||||
|
||||
Penguins remain in the board even if the player leaves
|
||||
"""
|
||||
|
||||
def get_card(self, hand_id: int) -> WaterCard:
|
||||
"""Get the card given its hand ID"""
|
||||
return next((card for card in self.hand.cards if card.hand_id == hand_id), None)
|
||||
@ -407,7 +425,11 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
ITEM_AWARDS = [6026, 4121, 2025, 1087, 3032]
|
||||
"""All the items gained from ranking, indexed by their rank"""
|
||||
|
||||
STAMP_AWARDS = {1: 278, 3: 282, 4: 284}
|
||||
STAMP_AWARDS = {
|
||||
1: WaterStamp.WATER_MIDWAY,
|
||||
3: WaterStamp.WATER_SUIT,
|
||||
4: WaterStamp.WATER_NINJA,
|
||||
}
|
||||
"""Map rank and the stamp you gain from LEAVING the rank"""
|
||||
|
||||
board_cycle_handler: WaterCycleHandler
|
||||
@ -469,6 +491,13 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
# original)
|
||||
self.board = Board(columns=5 if len(waddle.penguins) <= 2 else 7)
|
||||
|
||||
async def remove_penguin(self, p: Penguin):
|
||||
player = self.get_player_by_penguin(p)
|
||||
# this may run twice for the same player
|
||||
if player is not None:
|
||||
self.players[player.seat_id].left = True
|
||||
await super().remove_penguin(p)
|
||||
|
||||
async def send_zm(self, *args):
|
||||
"""Send a "zm" packet, used for various commands, to the clients"""
|
||||
await self.send_xt("zm", "&".join(map(str, args)))
|
||||
@ -477,9 +506,11 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
"""Send a "zm" packet, used for various commands, to a specific client"""
|
||||
await player.penguin.send_xt("zm", "&".join(map(str, args)))
|
||||
|
||||
def get_player_by_penguin(self, penguin: Penguin) -> WaterPlayer:
|
||||
def get_player_by_penguin(self, penguin: Penguin) -> Union[WaterPlayer, None]:
|
||||
"""Get the player instance associated with a penguin"""
|
||||
return next(player for player in self.players if player.penguin == penguin)
|
||||
return next(
|
||||
(player for player in self.players if player.penguin == penguin), None
|
||||
)
|
||||
|
||||
def get_card_generator(self, p: Penguin) -> Generator[WaterCard, None, None]:
|
||||
"""Get a generator for a player's cards"""
|
||||
@ -634,15 +665,12 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
).apply()
|
||||
|
||||
if winner.penguin.water_matches_won >= 100:
|
||||
# Water Expert stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[276])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.WATER_EXPERT)
|
||||
|
||||
# Gong! stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[270])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.GONG)
|
||||
|
||||
if winner.two_close >= 2:
|
||||
# Two Close stamp
|
||||
await winner.penguin.add_stamp(winner.penguin.server.stamps[286])
|
||||
await winner.penguin.add_card_jitsu_stamp(WaterStamp.TWO_CLOSE)
|
||||
|
||||
# iterate over all players that drowned from the last place order
|
||||
for row in self.board.rows:
|
||||
@ -650,7 +678,7 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
break
|
||||
players_in_row = self.get_players_in_row(row)
|
||||
for player in players_in_row:
|
||||
if isinstance(player, WaterSensei):
|
||||
if isinstance(player, WaterSensei) or player.left:
|
||||
continue
|
||||
|
||||
# because winner has already been removed
|
||||
@ -684,7 +712,7 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
p.server.items[cls.ITEM_AWARDS[rank]], cost=0, notify=False
|
||||
)
|
||||
if rank in cls.STAMP_AWARDS:
|
||||
await p.add_stamp(p.server.stamps[cls.STAMP_AWARDS[rank]])
|
||||
await p.add_card_jitsu_stamp(cls.STAMP_AWARDS[rank])
|
||||
|
||||
await p.update(water_ninja_rank=p.water_ninja_rank + ranks).apply()
|
||||
return True
|
||||
@ -700,20 +728,28 @@ class CardJitsuWaterLogic(IWaddle):
|
||||
players_in_row = self.get_players_in_row(drop_row)
|
||||
position = len(self.players)
|
||||
for player in players_in_row:
|
||||
if player.penguin is not None:
|
||||
if not player.left:
|
||||
# Watery Fall stamp
|
||||
await player.penguin.add_stamp(player.penguin.server.stamps[274])
|
||||
|
||||
|
||||
await player.penguin.add_card_jitsu_stamp(WaterStamp.WATERY_FALL)
|
||||
|
||||
# CMD_PLAYER_KILL, meant for players who lose from falling
|
||||
player_kill_data = []
|
||||
for player in players_in_row:
|
||||
amulet = await self.update_player_progress(
|
||||
player, fell=True, position=position
|
||||
)
|
||||
amulet = None
|
||||
if not player.left:
|
||||
amulet = await self.update_player_progress(
|
||||
player, fell=True, position=position
|
||||
)
|
||||
else:
|
||||
amulet = Amulet(None, False)
|
||||
player_kill_data.append(
|
||||
f"pk&{player.seat_id}&{position}&{amulet.serialize()}&false"
|
||||
)
|
||||
|
||||
|
||||
await self.send_zm(":".join(player_kill_data))
|
||||
|
||||
# for Two Close stamp
|
||||
@ -985,12 +1021,15 @@ def get_water_rank_threshold(rank):
|
||||
async def handle_get_game(p: Penguin):
|
||||
"""Handle the client entering the game"""
|
||||
seat_id = p.waddle.get_seat_id(p)
|
||||
player = p.waddle.get_player_by_penguin(p)
|
||||
player: WaterPlayer = p.waddle.get_player_by_penguin(p)
|
||||
|
||||
# needs to send these or the client dies
|
||||
await p.send_xt("gz")
|
||||
await p.send_xt("jz")
|
||||
|
||||
# needed to fix client taking a bit to exit game
|
||||
await p.send_card_jitsu_stamp_info()
|
||||
|
||||
# CMD_PLAYER_INDEX
|
||||
await p.waddle.send_zm_client(player, "po", seat_id)
|
||||
|
||||
@ -1109,8 +1148,7 @@ async def handle_throw_card(p: Penguin, *, cell_id: str):
|
||||
)
|
||||
|
||||
if player.cleared >= 28:
|
||||
# Skipping Stones stamp
|
||||
await player.penguin.add_stamp(player.penguin.server.stamps[288])
|
||||
await p.add_card_jitsu_stamp(WaterStamp.SKIPPING_STONES)
|
||||
|
||||
# CMD_PLAYER_THROW
|
||||
await p.waddle.send_zm(
|
||||
|
@ -244,6 +244,8 @@ class Penguin(Spheniscidae, penguin.Penguin):
|
||||
if stamp.id in self.stamps:
|
||||
return False
|
||||
|
||||
await self.server.redis.set(self.get_recent_stamp_key(stamp.id), 1)
|
||||
|
||||
await self.stamps.insert(stamp_id=stamp.id)
|
||||
|
||||
if notify:
|
||||
@ -254,6 +256,10 @@ class Penguin(Spheniscidae, penguin.Penguin):
|
||||
|
||||
return True
|
||||
|
||||
def get_recent_stamp_key(self, stamp_id):
|
||||
"""Get redis key that locates the session recency of a stamp"""
|
||||
return f'{self.id}.{stamp_id}.recentstamp'
|
||||
|
||||
async def add_inbox(self, postcard, sender_name="sys", sender_id=None, details=""):
|
||||
penguin_postcard = await PenguinPostcard.create(penguin_id=self.id, sender_id=sender_id,
|
||||
postcard_id=postcard.id, details=details)
|
||||
@ -380,7 +386,90 @@ class Penguin(Spheniscidae, penguin.Penguin):
|
||||
|
||||
self.logger.info(f'{self.username} updated their background to \'{item.name}\' ' if item else
|
||||
f'{self.username} removed their background item')
|
||||
|
||||
async def send_card_jitsu_stamp_info(self):
|
||||
"""
|
||||
Send information the client requires to properly display the stamp end screen
|
||||
"""
|
||||
stamp_info = await self.get_game_end_stamps_info(False)
|
||||
await self.send_xt("cjsi", *stamp_info)
|
||||
|
||||
async def add_card_jitsu_stamp(self, stamp_id):
|
||||
"""Correct way of adding a card-jitsu (Regular, Fire, Water) stamp"""
|
||||
await self.add_stamp(self.server.stamps[stamp_id])
|
||||
await self.send_card_jitsu_stamp_info()
|
||||
|
||||
async def get_game_end_stamps_info(
|
||||
self, clear_session: bool
|
||||
) -> tuple[str, int, int, int]:
|
||||
"""
|
||||
Get the info of the stamps at the end of a game that the client requires
|
||||
|
||||
If clear_session is True, the stamps will be marked off and will no longer
|
||||
show up as new stamps at the end of minigames
|
||||
"""
|
||||
(
|
||||
collected_game_stamps_string,
|
||||
total_collected_game_stamps,
|
||||
total_game_stamps,
|
||||
total_stamps,
|
||||
) = ("", 0, 0, 0)
|
||||
|
||||
game_stamps = [
|
||||
stamp
|
||||
for stamp in self.server.stamps.values()
|
||||
if stamp.group_id == self.room.stamp_group
|
||||
]
|
||||
|
||||
game_stamps_ids = [stamp.id for stamp in game_stamps]
|
||||
|
||||
recently_collected_game_stamps = []
|
||||
|
||||
for stamp in self.stamps.values():
|
||||
if stamp.stamp_id in game_stamps_ids:
|
||||
is_recent = await self.server.redis.get(
|
||||
self.get_recent_stamp_key(stamp.stamp_id)
|
||||
)
|
||||
if is_recent:
|
||||
recently_collected_game_stamps.append(stamp)
|
||||
|
||||
collected_game_stamps = [
|
||||
stamp for stamp in game_stamps if (stamp.id in self.stamps and stamp)
|
||||
]
|
||||
|
||||
collected_game_stamps_string = "|".join(
|
||||
str(stamp.stamp_id) for stamp in recently_collected_game_stamps
|
||||
)
|
||||
|
||||
total_collected_game_stamps = len(collected_game_stamps)
|
||||
|
||||
total_game_stamps = len(game_stamps)
|
||||
|
||||
total_stamps = len(
|
||||
[
|
||||
stamp
|
||||
for stamp in self.stamps.values()
|
||||
if self.server.stamps[stamp.stamp_id].group_id
|
||||
]
|
||||
)
|
||||
|
||||
if clear_session:
|
||||
await self.clear_stamps_session()
|
||||
|
||||
return (
|
||||
collected_game_stamps_string,
|
||||
total_collected_game_stamps,
|
||||
total_game_stamps,
|
||||
total_stamps,
|
||||
)
|
||||
|
||||
async def clear_stamps_session(self):
|
||||
"""
|
||||
Exits a game session and unmarks all stamps since we are no longer in their session
|
||||
"""
|
||||
async for key in self.server.redis.scan_iter(self.get_recent_stamp_key("*")):
|
||||
await self.server.redis.delete(key)
|
||||
|
||||
def __repr__(self):
|
||||
if self.id is not None:
|
||||
return f'<Penguin ID=\'{self.id}\' Username=\'{self.username}\'>'
|
||||
|
Loading…
Reference in New Issue
Block a user