Cross-client buddy handlers

This commit is contained in:
Ben 2019-08-19 02:29:43 +01:00
parent c84bf9114a
commit 9098ae50a1
4 changed files with 233 additions and 2 deletions

View File

@ -20,6 +20,8 @@ class Room(db.Model):
super().__init__(*args, **kwargs)
self.penguins = []
self.igloo = False
self.tables = {}
self.waddles = {}

View File

@ -0,0 +1,193 @@
from houdini import handlers
from houdini.handlers import XTPacket
from houdini.handlers.play.navigation import handle_join_room
from houdini.data.penguin import Penguin
from houdini.data.buddy import BuddyList, BuddyRequest
from houdini import ClientType
async def update_player_presence(p):
for buddy_id in p.data.buddies.keys():
if buddy_id in p.server.penguins_by_id:
buddy = p.server.penguins_by_id[buddy_id]
await p.send_xt('bon', buddy.data.id, p.server.server_config['Id'], buddy.room.id)
await buddy.send_xt('bon', p.data.id, p.server.server_config['Id'], p.room.id)
for character_id in p.data.character_buddies.keys():
if character_id in p.server.penguins_by_character_id:
character = p.server.penguins_by_character_id[character_id]
await p.send_xt('caon', character_id, p.server.server_config['Id'], character.room.id)
if p.data.character is not None:
for penguin in p.server.penguins_by_id.values():
if p.data.character in penguin.data.character_buddies:
await penguin.send_xt('caon', p.data.character, p.server.server_config['Id'], p.room.id)
@handlers.handler(XTPacket('j', 'jr'), after=handle_join_room, client=ClientType.Vanilla)
async def handle_send_room_presence(p):
await update_player_presence(p)
@handlers.handler(XTPacket('b', 'gb'), client=ClientType.Vanilla)
@handlers.allow_once
async def handle_get_buddies(p):
buddies_query = BuddyList.load(parent=Penguin.on(Penguin.id == BuddyList.buddy_id)).where(
BuddyList.penguin_id == p.data.id)
request_query = BuddyRequest.load(parent=Penguin.on(Penguin.id == BuddyRequest.requester_id)).where(
BuddyRequest.penguin_id == p.data.id)
buddies = []
best_buddies = []
characters = []
best_characters = []
async with p.server.db.transaction():
buddy_list = buddies_query.gino.iterate()
buddy_requests = request_query.gino.iterate()
async for buddy in buddy_list:
buddy_presence = int(buddy.buddy_id in p.server.penguins_by_id)
buddies.append(f'{buddy.buddy_id}|{buddy.parent.nickname}|{buddy_presence}')
if buddy.best_buddy:
best_buddies.append(str(buddy.buddy_id))
for character in p.data.character_buddies.values():
character_presence = int(character.character_id in p.server.penguins_by_character_id)
characters.append(f'{character.character_id}|{character_presence}')
if character.best_buddy:
best_characters.append(str(character.character_id))
requests = [f'{request.requester_id}|{request.parent.nickname}' async for request in buddy_requests]
best_friend_count = len(best_buddies) + len(best_characters)
notification_aware = int(best_friend_count >= 1)
best_friends_enabled = int((len(buddies) + len(characters)) >= 6)
await p.send_xt('gs', best_friend_count, notification_aware, int(p.data.active), best_friends_enabled)
await p.send_xt('gb', *buddies)
await p.send_xt('pr', *requests)
await p.send_xt('gc', *characters)
if best_friends_enabled:
await p.send_xt('gbf', *best_buddies)
await p.send_xt('gbc', *best_characters)
await update_player_presence(p)
@handlers.handler(XTPacket('b', 'gb'), client=ClientType.Legacy)
@handlers.allow_once
async def handle_get_buddies_legacy(p):
buddies_query = BuddyList.load(parent=Penguin.on(Penguin.id == BuddyList.buddy_id)).where(
BuddyList.penguin_id == p.data.id)
buddies = []
async with p.server.db.transaction():
buddy_list = buddies_query.gino.iterate()
async for buddy in buddy_list:
buddy_presence = int(buddy.buddy_id in p.server.penguins_by_id)
buddies.append(f'{buddy.buddy_id}|{buddy.parent.nickname}|{buddy_presence}')
await p.send_xt('gb', *buddies)
await update_player_presence(p)
@handlers.handler(XTPacket('b', 'bf'), client=ClientType.Legacy)
async def handle_find_buddy(p, buddy_id: int):
if buddy_id in p.data.buddies and buddy_id in p.server.penguins_by_id:
buddy = p.server.penguins_by_id[buddy_id]
await p.send_xt('bf', buddy.room.id)
@handlers.handler(XTPacket('b', 'br'))
@handlers.cooldown(.5)
async def handle_buddy_request(p, buddy_id: int):
if buddy_id not in p.data.buddies:
if buddy_id in p.server.penguins_by_id:
buddy = p.server.penguins_by_id[buddy_id]
if buddy.client_type == ClientType.Vanilla and p.data.id not in buddy.data.buddy_requests:
await buddy.data.buddy_requests.set(p.data.id)
elif p.data.id not in buddy.buddy_requests:
buddy.buddy_requests.add(p.data.id)
else:
return
await buddy.send_xt('br', p.data.id, p.data.nickname)
else:
await BuddyRequest.create(penguin_id=buddy_id, requester_id=p.data.id)
@handlers.handler(XTPacket('b', 'ba'))
async def handle_buddy_accept(p, buddy_id: int):
if buddy_id in p.data.buddy_requests:
await p.data.buddy_requests.delete(buddy_id)
elif buddy_id in p.buddy_requests:
p.buddy_requests.remove(buddy_id)
else:
return
await p.data.buddies.set(buddy_id)
if buddy_id in p.server.penguins_by_id:
buddy = p.server.penguins_by_id[buddy_id]
await buddy.data.buddies.set(p.data.id)
await buddy.send_xt('ba', p.data.id, p.data.nickname, 1)
await p.send_xt('ba', buddy.data.id, buddy.data.nickname, 1)
if p.client_type == ClientType.Vanilla:
await p.send_xt('bon', buddy.data.id, p.server.server_config['Id'], buddy.room.id)
if buddy.client_type == ClientType.Vanilla:
await buddy.send_xt('bon', p.data.id, p.server.server_config['Id'], p.room.id)
else:
await BuddyList.create(penguin_id=buddy_id, buddy_id=p.data.id)
nickname = await Penguin.select('nickname').where(Penguin.id == buddy_id).gino.scalar()
await p.send_xt('ba', buddy_id, nickname, 0)
@handlers.handler(XTPacket('b', 'rb'))
async def handle_buddy_remove(p, buddy_id: int):
if buddy_id in p.data.buddies:
await p.data.buddies.delete(buddy_id)
await p.send_xt('rb', buddy_id)
if buddy_id in p.server.penguins_by_id:
buddy = p.server.penguins_by_id[buddy_id]
await buddy.send_xt('rb', p.data.id)
await buddy.data.buddies.delete(p.data.id)
else:
await BuddyList.delete.where((BuddyList.penguin_id == buddy_id) &
(BuddyList.buddy_id == p.data.id)).gino.status()
@handlers.handler(XTPacket('b', 'cr'), client=ClientType.Vanilla)
async def handle_character_request(p, character_id: int):
if character_id in p.server.characters and character_id not in p.data.character_buddies:
character = p.server.characters[character_id]
await p.data.character_buddies.set(character_id)
await p.send_xt('cr', character_id, 0)
await p.send_xt('caon', character_id, p.server.server_config['Id'], p.room.id)
@handlers.handler(XTPacket('b', 'rr'), client=ClientType.Vanilla)
async def handle_buddy_reject(p, buddy_id: int):
await p.data.buddy_requests.delete(buddy_id)
@handlers.handler(XTPacket('b', 'tbf'), client=ClientType.Vanilla)
async def handle_toggle_best_friend(p, buddy_id: int):
if buddy_id in p.data.buddies:
buddy_record = p.data.buddies[buddy_id]
await buddy_record.update(best_buddy=not buddy_record.best_buddy).apply()
@handlers.handler(XTPacket('b', 'tbc'), client=ClientType.Vanilla)
async def handle_toggle_best_character(p, character_id: int):
if character_id in p.data.character_buddies:
character_buddy_record = p.data.character_buddies[character_id]
await character_buddy_record.update(best_buddy=not character_buddy_record.best_buddy).apply()

View File

@ -3,6 +3,7 @@ from houdini.handlers import XTPacket
from houdini.data.penguin import Penguin
from aiocache import cached
import random
def get_player_string_key(_, p, player_id):
@ -83,6 +84,27 @@ async def handle_get_player_by_name(p, player_name: str):
await p.send_xt('pbn')
@handlers.handler(XTPacket('u', 'smi'), client=ClientType.Vanilla)
@handlers.cooldown(10)
async def handle_send_mascot_invite(p, num_invites: int, character_id: int):
if character_id in p.server.characters and p.data.character is not None:
for _ in range(min(num_invites, len(p.server.penguins_by_id))):
player = random.choice(list(p.server.penguins_by_id.values()))
await player.send_xt('smi', character_id)
@handlers.handler(XTPacket('u', 'bf'), client=ClientType.Vanilla)
async def handle_find_player(p, player_id: int):
if player_id in p.server.penguins_by_id:
player = p.server.penguins_by_id[player_id]
room_id = player.room.id
room_type = 'igloo' if player.room.igloo else 'invalid'
room_owner = player.room.penguin_id if player.room.igloo else -1
else:
room_id, room_type, room_owner = -1, 'invalid', -1
await p.send_xt('bf', room_id, room_type, room_owner)
@handlers.handler(XTPacket('u', 'pbsms'), client=ClientType.Vanilla)
async def handle_pbsm_start(p):
await p.send_xt('pbsms')

View File

@ -6,8 +6,9 @@ from houdini.spheniscidae import Spheniscidae
class Penguin(Spheniscidae):
__slots__ = ['x', 'y', 'frame', 'toy', 'room', 'waddle', 'table',
'login_key', 'member', 'membership_days', 'avatar',
'walking_puffle', 'permissions', 'active_quests']
'data', 'muted', 'login_key', 'member', 'membership_days',
'avatar', 'walking_puffle', 'permissions', 'active_quests',
'buddy_requests']
def __init__(self, *args):
super().__init__(*args)
@ -32,6 +33,8 @@ class Penguin(Spheniscidae):
self.active_quests = None
self.buddy_requests = set()
@property
def party_state(self):
return str()
@ -301,6 +304,17 @@ class Penguin(Spheniscidae):
del self.server.penguins_by_id[self.data.id]
del self.server.penguins_by_username[self.data.username]
if self.data.character is not None:
del self.server.penguins_by_character_id[self.data.character]
for penguin in self.server.penguins_by_id.values():
if self.data.character in penguin.data.character_buddies:
await penguin.send_xt('caof', self.data.character)
for buddy_id in self.data.buddies:
if buddy_id in self.server.penguins_by_id:
await self.server.penguins_by_id[buddy_id].send_xt('bof', self.data.id)
await self.server.redis.hincrby('population', self.server.server_config['Id'], -1)
await super()._client_disconnected()