Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
from core.aochat import client_packets
|
||||
from core.aochat import server_packets
|
||||
from core.conn import Conn
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
from core.lookup.character_service import CharacterService
|
||||
|
||||
|
||||
@instance()
|
||||
class BuddyService:
|
||||
BUDDY_LOGON_EVENT = "buddy_logon"
|
||||
BUDDY_LOGOFF_EVENT = "buddy_logoff"
|
||||
|
||||
def __init__(self):
|
||||
self.buddy_list = {}
|
||||
self.buddy_list_size = 0
|
||||
self.logger = Logger(__name__)
|
||||
|
||||
def inject(self, registry):
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.bot = registry.get_instance("bot")
|
||||
self.event_service = registry.get_instance("event_service")
|
||||
|
||||
def pre_start(self):
|
||||
self.bot.register_packet_handler(server_packets.BuddyAdded.id, self.handle_add)
|
||||
self.bot.register_packet_handler(server_packets.BuddyRemoved.id, self.handle_remove)
|
||||
self.bot.register_packet_handler(server_packets.LoginOK.id, self.handle_login_ok)
|
||||
self.event_service.register_event_type(self.BUDDY_LOGON_EVENT)
|
||||
self.event_service.register_event_type(self.BUDDY_LOGOFF_EVENT)
|
||||
|
||||
def handle_add(self, conn: Conn, packet):
|
||||
buddy = self.buddy_list[conn.id].get(packet.char_id, {"types": [], "conn_id": conn.id})
|
||||
buddy["online"] = packet.online
|
||||
self.buddy_list[conn.id][packet.char_id] = buddy
|
||||
|
||||
# verify that buddy does not exist on any other conn
|
||||
for conn_id, conn_buddy_list in self.buddy_list.items():
|
||||
if conn.id != conn_id:
|
||||
buddy = conn_buddy_list.get(packet.char_id, None)
|
||||
if buddy:
|
||||
if buddy["online"] is None:
|
||||
# remove from other conn list
|
||||
del conn_buddy_list[packet.char_id]
|
||||
else:
|
||||
# remove from this conn
|
||||
self.logger.warning(f"Removing char '{packet.char_id}' from conn '{conn.id}' "
|
||||
f"since it already exists on another conn")
|
||||
conn.send_packet(client_packets.BuddyRemove(packet.char_id))
|
||||
|
||||
if packet.online == 1:
|
||||
self.event_service.fire_event(self.BUDDY_LOGON_EVENT, packet)
|
||||
else:
|
||||
self.event_service.fire_event(self.BUDDY_LOGOFF_EVENT, packet)
|
||||
|
||||
def handle_remove(self, conn: Conn, packet):
|
||||
conn_buddy_list = self.buddy_list[conn.id]
|
||||
if packet.char_id in conn_buddy_list:
|
||||
if len(conn_buddy_list[packet.char_id]["types"]) > 0:
|
||||
self.logger.warning(f"Removing buddy {packet.char_id} that still has "
|
||||
f"types {conn_buddy_list[packet.char_id]['types']}")
|
||||
|
||||
del conn_buddy_list[packet.char_id]
|
||||
|
||||
def handle_login_ok(self, conn: Conn, _):
|
||||
self.buddy_list_size += 1000
|
||||
self.buddy_list[conn.id] = {}
|
||||
self.buddy_list[conn.id][conn.char_id] = {"online": True, "types": [], "conn_id": conn.id}
|
||||
|
||||
def add_buddy(self, char_id, _type):
|
||||
if not char_id:
|
||||
return False
|
||||
|
||||
# check if we are trying to add a conn as a buddy
|
||||
if self.is_conn_char_id(char_id):
|
||||
return False
|
||||
|
||||
buddy = self.get_buddy(char_id)
|
||||
if buddy:
|
||||
buddy["types"].append(_type)
|
||||
else:
|
||||
conn = self.get_conn_for_new_buddy()
|
||||
if conn.char_id != char_id:
|
||||
conn.send_packet(client_packets.BuddyAdd(char_id, "\1"))
|
||||
self.buddy_list[conn.id][char_id] = {"online": None, "types": [_type], "conn_id": conn.id}
|
||||
|
||||
return True
|
||||
|
||||
def is_conn_char_id(self, char_id):
|
||||
for _id, conn in self.bot.conns.items():
|
||||
if conn.char_id == char_id:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def remove_buddy(self, char_id, _type, force_remove=False):
|
||||
if char_id:
|
||||
buddy = self.get_buddy(char_id)
|
||||
if not buddy:
|
||||
return False
|
||||
|
||||
if _type in buddy["types"]:
|
||||
buddy["types"].remove(_type)
|
||||
|
||||
if len(buddy["types"]) == 0 or force_remove:
|
||||
if not self.is_conn_char_id(char_id):
|
||||
conn = self.bot.conns[buddy["conn_id"]]
|
||||
conn.send_packet(client_packets.BuddyRemove(char_id))
|
||||
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_buddy(self, char_id):
|
||||
for conn_id, conn_buddy_list in self.buddy_list.items():
|
||||
if char_id in conn_buddy_list:
|
||||
return conn_buddy_list[char_id]
|
||||
return None
|
||||
|
||||
def is_online(self, char_id):
|
||||
buddy = self.get_buddy(char_id)
|
||||
if buddy is None:
|
||||
return None
|
||||
else:
|
||||
return buddy.get("online", None)
|
||||
|
||||
def get_all_buddies(self):
|
||||
result = {}
|
||||
for conn_id, conn_buddy_list in self.buddy_list.items():
|
||||
for char_id, buddy in conn_buddy_list.items():
|
||||
result[char_id] = buddy
|
||||
|
||||
return result
|
||||
|
||||
def get_buddy_list_size(self):
|
||||
count = 0
|
||||
for conn_id, conn_buddy_list in self.buddy_list.items():
|
||||
count += len(conn_buddy_list)
|
||||
|
||||
return count
|
||||
|
||||
def get_conn_for_new_buddy(self):
|
||||
buddy_list_size = None
|
||||
_id = None
|
||||
for conn_id, conn_buddy_list in self.buddy_list.items():
|
||||
if buddy_list_size is None or len(conn_buddy_list) < buddy_list_size:
|
||||
buddy_list_size = len(conn_buddy_list)
|
||||
_id = conn_id
|
||||
|
||||
return self.bot.conns.get(_id, None)
|
||||
Reference in New Issue
Block a user