diff --git a/houdini.sql b/houdini.sql index 918ee02..b282a12 100644 --- a/houdini.sql +++ b/houdini.sql @@ -1465,6 +1465,7 @@ CREATE TABLE penguin_stamp ( penguin_id INT NOT NULL, stamp_id INT NOT NULL, recent BOOLEAN NOT NULL DEFAULT TRUE, + in_game_session BOOLEAN NOT NULL DEFAULT TRUE, PRIMARY KEY (penguin_id, stamp_id), CONSTRAINT stamp_ibfk_1 FOREIGN KEY (penguin_id) REFERENCES penguin (id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT stamp_ibfk_2 FOREIGN KEY (stamp_id) REFERENCES stamp (id) ON DELETE CASCADE ON UPDATE CASCADE @@ -1476,6 +1477,7 @@ COMMENT ON COLUMN penguin_stamp.penguin_id IS 'Stamp penguin ID'; COMMENT ON COLUMN penguin_stamp.stamp_id IS 'Stamp ID'; COMMENT ON COLUMN penguin_stamp.recent IS 'Is recently earned?'; COMMENT ON COLUMN penguin_stamp.recent IS 'Is recently earned?'; +COMMENT ON COLUMN penguin_stamp.in_game_session IS 'Still in the minigame session it was earned'; DROP TABLE IF EXISTS penguin_membership; CREATE TABLE penguin_membership ( diff --git a/houdini/data/stamp.py b/houdini/data/stamp.py index 00147a0..fed9fde 100644 --- a/houdini/data/stamp.py +++ b/houdini/data/stamp.py @@ -54,6 +54,7 @@ class PenguinStamp(db.Model): stamp_id = db.Column(db.ForeignKey('stamp.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True, nullable=False) recent = db.Column(db.Boolean, nullable=False, server_default=db.text("true")) + in_game_session = db.Column(db.Boolean, nullable=False, server_default=db.text("true")) class StampCollection(AbstractDataCollection): diff --git a/houdini/handlers/games/__init__.py b/houdini/handlers/games/__init__.py index ae181b0..3d6acc7 100644 --- a/houdini/handlers/games/__init__.py +++ b/houdini/handlers/games/__init__.py @@ -80,28 +80,15 @@ async def handle_get_game_over(p, score: int): if p.room.game and not p.waddle 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') + stamp_info = "", 0, 0, 0 - collected_stamps_string, total_collected_stamps, total_game_stamps, total_stamps = '', 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) + await p.send_xt("zo", p.coins, *stamp_info) @handlers.handler(XTPacket('ggd', ext='z'), client=ClientType.Vanilla) @@ -146,3 +133,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() diff --git a/houdini/penguin.py b/houdini/penguin.py index f3ccb67..45392c5 100644 --- a/houdini/penguin.py +++ b/houdini/penguin.py @@ -380,7 +380,74 @@ 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 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 = [ + stamp + for stamp in self.stamps.values() + if (stamp.in_game_session and stamp.stamp_id in game_stamps_ids) + ] + + 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 + """ + stamps = [stamp for stamp in self.stamps.values() if stamp.in_game_session] + for stamp in stamps: + await stamp.update(in_game_session=False).apply() + def __repr__(self): if self.id is not None: return f''