100 lines
3.6 KiB
Python
100 lines
3.6 KiB
Python
import threading
|
|
import time
|
|
|
|
from core.aochat import server_packets
|
|
from core.aochat.client_packets import CharacterLookup
|
|
from core.decorators import instance
|
|
|
|
|
|
@instance()
|
|
class CharacterService:
|
|
def __init__(self):
|
|
self.name_to_id = {}
|
|
self.id_to_name = {}
|
|
self.waiting_for_response = set()
|
|
self.notify_on_receive = {}
|
|
|
|
def inject(self, registry):
|
|
self.bot = registry.get_instance("bot")
|
|
self.db = registry.get_instance("db")
|
|
|
|
def pre_start(self):
|
|
self.bot.register_packet_handler(server_packets.CharacterLookup.id, self.update)
|
|
self.bot.register_packet_handler(server_packets.CharacterName.id, self.update)
|
|
|
|
def start(self):
|
|
self.db.shared.exec("CREATE TABLE IF NOT EXISTS `all_orgs` (`org_id` INT(11) NOT NULL, "
|
|
"`org_name` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci', "
|
|
"`member_count` INT(11) NULL DEFAULT NULL, "
|
|
"`faction` VARCHAR(16) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci', "
|
|
"`last_seen` INT(11) NOT NULL, "
|
|
"PRIMARY KEY (`org_id`) USING BTREE, "
|
|
"INDEX `org_name` (`org_name`) USING BTREE)")
|
|
self.db.create_view("all_orgs")
|
|
|
|
def _wait_for_char_id(self, char_name):
|
|
# char_name must be .capitalize()'ed
|
|
|
|
packet = self.bot.iterate(1)
|
|
while packet and char_name not in self.name_to_id:
|
|
packet = self.bot.iterate(1)
|
|
|
|
return self.name_to_id.get(char_name, None)
|
|
|
|
# FeatureFlags.THREADING
|
|
def _wait_for_char_id_threading(self, char_name):
|
|
# char_name must be .capitalize()'ed
|
|
|
|
event = self.notify_on_receive.get(char_name, None)
|
|
if event is None:
|
|
event = threading.Event()
|
|
self.notify_on_receive[char_name] = event
|
|
|
|
if char_name not in self.name_to_id:
|
|
event.wait(10)
|
|
|
|
return self.name_to_id.get(char_name, None)
|
|
|
|
def resolve_char_to_id(self, char):
|
|
if isinstance(char, int):
|
|
return char
|
|
elif char.isdigit():
|
|
return int(char)
|
|
else:
|
|
char_name = char.capitalize()
|
|
if char_name in self.name_to_id:
|
|
return self.name_to_id[char_name]
|
|
else:
|
|
self._send_lookup_if_needed(char_name)
|
|
return self._wait_for_char_id(char_name)
|
|
|
|
def resolve_char_to_name(self, char, default=None):
|
|
if isinstance(char, int) or char.isdigit():
|
|
char_name = self.get_char_name(char)
|
|
return char_name if char_name else default
|
|
else:
|
|
return char
|
|
|
|
def get_char_name(self, char_id):
|
|
return self.id_to_name.get(char_id, None)
|
|
|
|
def update(self, conn, packet):
|
|
self.waiting_for_response.discard(packet.name)
|
|
|
|
if packet.char_id == 4294967295:
|
|
self.name_to_id[packet.name] = None
|
|
else:
|
|
self.id_to_name[packet.char_id] = packet.name
|
|
self.name_to_id[packet.name] = packet.char_id
|
|
# self._update_name_history(packet.name, packet.char_id)
|
|
|
|
def _update_name_history(self, char_name, char_id):
|
|
params = [char_name, char_id, int(time.time())]
|
|
self.db.exec("INSERT IGNORE INTO name_history (name, char_id, created_at) VALUES (?, ?, ?)", params)
|
|
|
|
def _send_lookup_if_needed(self, char_name):
|
|
# char_name must be .capitalize()'ed
|
|
if char_name not in self.name_to_id and char_name not in self.waiting_for_response:
|
|
self.waiting_for_response.add(char_name)
|
|
self.bot.send_packet(CharacterLookup(char_name))
|