mirror of
https://github.com/solero/houdini.git
synced 2025-04-26 00:26:31 +00:00
251 lines
8.4 KiB
Python
251 lines
8.4 KiB
Python
from houdini import handlers
|
|
from houdini.converters import SeparatorConverter
|
|
from houdini.handlers import XTPacket
|
|
from houdini.data.penguin import Penguin
|
|
from houdini.constants import ClientType
|
|
|
|
from aiocache import cached
|
|
from datetime import datetime
|
|
import random
|
|
import asyncio
|
|
import time
|
|
|
|
|
|
def get_player_string_key(_, p, player_id):
|
|
return f'player.{player_id}'
|
|
|
|
|
|
def get_mascot_string_key(_, p, mascot_id):
|
|
return f'mascot.{mascot_id}'
|
|
|
|
|
|
@cached(alias='default', key_builder=get_player_string_key)
|
|
async def get_player_string(p, penguin_id: int):
|
|
if penguin_id in p.server.penguins_by_id:
|
|
return await p.server.penguins_by_id[penguin_id].string
|
|
else:
|
|
player_data = await Penguin.get(penguin_id)
|
|
string = await p.server.anonymous_penguin_string_compiler.compile(player_data)
|
|
return string
|
|
|
|
|
|
@cached(alias='default', key_builder=get_mascot_string_key)
|
|
async def get_mascot_string(p, mascot_id: int):
|
|
if mascot_id in p.server.penguins_by_character_id:
|
|
return await p.server.penguins_by_character_id[mascot_id].string
|
|
else:
|
|
player_data = await Penguin.query.where(Penguin.character == mascot_id).gino.first()
|
|
string = await p.server.anonymous_penguin_string_compiler.compile(player_data)
|
|
return string
|
|
|
|
|
|
async def server_heartbeat(server):
|
|
while True:
|
|
timer = time.time()
|
|
await asyncio.sleep(61)
|
|
for penguin in server.penguins_by_id.values():
|
|
if penguin.heartbeat < timer:
|
|
await penguin.close()
|
|
|
|
|
|
async def server_egg_timer(server):
|
|
while True:
|
|
await asyncio.sleep(60)
|
|
for p in server.penguins_by_id.values():
|
|
if p.timer_active:
|
|
p.egg_timer_minutes -= 1
|
|
if p.is_vanilla_client:
|
|
minutes_until_timer_end = datetime.combine(datetime.today(), p.timer_end) - datetime.now()
|
|
minutes_until_timer_end = minutes_until_timer_end.total_seconds() // 60
|
|
|
|
if minutes_until_timer_end <= p.egg_timer_minutes + 1:
|
|
if p.egg_timer_minutes == 7:
|
|
await p.send_error(915, p.egg_timer_minutes, p.timer_start, p.timer_end)
|
|
elif p.egg_timer_minutes == 5:
|
|
await p.send_error(915, p.egg_timer_minutes, p.timer_start, p.timer_end)
|
|
else:
|
|
if p.egg_timer_minutes == 7:
|
|
await p.send_error(914, p.egg_timer_minutes, p.timer_total)
|
|
elif p.egg_timer_minutes == 5:
|
|
await p.send_error(914, p.egg_timer_minutes, p.timer_total)
|
|
|
|
await p.send_xt('uet', max(0, p.egg_timer_minutes))
|
|
if p.egg_timer_minutes < 0:
|
|
await p.send_error_and_disconnect(916, p.timer_start, p.timer_end)
|
|
else:
|
|
if p.egg_timer_minutes < 0:
|
|
await p.send_error_and_disconnect(910)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'h'))
|
|
@handlers.cooldown(59)
|
|
async def handle_heartbeat(p):
|
|
p.heartbeat = time.time()
|
|
await p.send_xt('h')
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'gp'))
|
|
@handlers.cooldown(1)
|
|
async def handle_get_player(p, penguin_id: int):
|
|
await p.send_xt('gp', await get_player_string(p, penguin_id))
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'gmo'), client=ClientType.Vanilla)
|
|
@handlers.cooldown(1)
|
|
async def handle_get_mascot(p, mascot_id: int):
|
|
await p.send_xt('gmo', await get_mascot_string(p, mascot_id))
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbi'), client=ClientType.Vanilla)
|
|
@handlers.cooldown(1)
|
|
async def handle_get_player_by_id(p, penguin_id: int):
|
|
await p.send_xt('pbi', penguin_id)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbs'), client=ClientType.Vanilla)
|
|
@handlers.cooldown(1)
|
|
async def handle_get_player_by_swid(p, penguin_id: int):
|
|
if penguin_id in p.server.penguins_by_id:
|
|
nickname = p.server.penguins_by_id[penguin_id].safe_nick
|
|
else:
|
|
nickname = await Penguin.select('nickname').where(Penguin.id == penguin_id).gino.scalar()
|
|
await p.send_xt('pbs', penguin_id, penguin_id, nickname)
|
|
|
|
|
|
_id_converter = SeparatorConverter(separator=',', mapper=int)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbsu'), client=ClientType.Vanilla)
|
|
@handlers.cooldown(1)
|
|
async def handle_get_player_username_by_swid(p, ids: _id_converter):
|
|
ids = list(ids)
|
|
query = Penguin.select('id', 'nickname').where(Penguin.id.in_(ids))
|
|
async with p.server.db.transaction():
|
|
nicknames = {
|
|
pid: nickname async for pid, nickname in query.gino.iterate()}
|
|
|
|
await p.send_xt('pbsu', ','.join(nicknames[pid] for pid in ids))
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'gabcms'))
|
|
async def handle_get_ab_test_data(p):
|
|
pass
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'rpfi'))
|
|
async def handle_send_refresh_player_friend_info(p):
|
|
pass
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbn'), client=ClientType.Vanilla)
|
|
@handlers.cooldown(1)
|
|
async def handle_get_player_by_name(p, player_name: str):
|
|
player_name = player_name.lower()
|
|
if player_name in p.server.penguins_by_username:
|
|
player = p.server.penguins_by_username[player_name]
|
|
await p.send_xt('pbn', player.id, player.id, player.safe_name)
|
|
else:
|
|
result = await Penguin.select('id', 'nickname').where(
|
|
Penguin.username == player_name).gino.first()
|
|
if result is not None:
|
|
player_id, nickname = result
|
|
await p.send_xt('pbn', player_id, player_id, nickname)
|
|
else:
|
|
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.character is not None:
|
|
players = random.sample(list(p.server.penguins_by_id.values()), min(num_invites, len(p.server.penguins_by_id)))
|
|
for player in players:
|
|
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 = 'backyard' if player.room.backyard else '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', 'gbffl'))
|
|
async def handle_get_best_friends(p):
|
|
await p.send_xt('gbffl', ','.join((str(buddy.buddy_id) for buddy in p.buddies.values() if buddy.best_buddy)))
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbsms'), client=ClientType.Vanilla)
|
|
async def handle_pbsm_start(p):
|
|
await p.send_xt('pbsms')
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbsm'), client=ClientType.Vanilla)
|
|
async def handle_get_player_ids(p, ids: str):
|
|
await p.send_xt('pbsm', ids)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'pbsmf'), client=ClientType.Vanilla)
|
|
async def handle_pbsm_finish(p):
|
|
await p.send_xt('pbsmf')
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'sp'))
|
|
async def handle_set_player_position(p, x: int, y: int):
|
|
p.x, p.y = x, y
|
|
p.frame = 1
|
|
p.toy = None
|
|
await p.room.send_xt('sp', p.id, x, y)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'sf'))
|
|
@handlers.cooldown(.5)
|
|
async def handle_set_player_frame(p, frame: int):
|
|
p.frame = frame
|
|
await p.room.send_xt('sf', p.id, frame)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'sb'))
|
|
@handlers.cooldown(1)
|
|
async def handle_send_throw_ball(p, x: int, y: int):
|
|
await p.room.send_xt('sb', p.id, x, y)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'se'))
|
|
@handlers.cooldown(1)
|
|
async def handle_send_emote(p, emote: int):
|
|
await p.room.send_xt('se', p.id, emote)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'sa'))
|
|
@handlers.cooldown(1)
|
|
async def handle_send_action(p, action: int):
|
|
await p.room.send_xt('sa', p.id, action)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'followpath'))
|
|
@handlers.cooldown(1)
|
|
async def handle_follow_path(p, path: int):
|
|
await p.room.send_xt('followpath', p.id, path)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'ss'))
|
|
async def handle_send_safe_message(p, message_id: int):
|
|
await p.room.send_xt('ss', p.id, message_id)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'sma'))
|
|
async def handle_send_mascot_message(p, message_id: int):
|
|
if p.character:
|
|
await p.room.send_xt('sma', p.id, message_id)
|
|
|
|
|
|
@handlers.handler(XTPacket('u', 'glr'))
|
|
async def handle_get_last_revision(p):
|
|
await p.send_xt('glr', 'houdini')
|