diff --git a/module/gamefree/bytearray.pyi b/module/gamefree/bytearray.pyi index f4900a450..efb2f516e 100644 --- a/module/gamefree/bytearray.pyi +++ b/module/gamefree/bytearray.pyi @@ -17,6 +17,12 @@ class ByteArray: def writeUInt(self, data: ctypes.c_uint) -> ByteArray: ... + def writeUInt8(self, data: ctypes.c_uint8) -> ByteArray: + ... + + def writeUInt16(self, data: ctypes.c_uint16) -> ByteArray: + ... + def writeLong(self, data: ctypes.c_long) -> ByteArray: ... diff --git a/module/gamefree/bytearray/ByteArray.cpp b/module/gamefree/bytearray/ByteArray.cpp index d386d7dcd..0506d40ac 100644 --- a/module/gamefree/bytearray/ByteArray.cpp +++ b/module/gamefree/bytearray/ByteArray.cpp @@ -21,6 +21,14 @@ void ByteArray::writeUInt(unsigned int data) { writeNumber(data); } +void ByteArray::writeUInt8(unsigned _int8 data) { + writeNumber(data); +} + +void ByteArray::writeUInt16(unsigned _int16 data) { + writeNumber(data); +} + void ByteArray::writeLong(long data) { writeNumber(data); } diff --git a/module/gamefree/bytearray/ByteArray.hpp b/module/gamefree/bytearray/ByteArray.hpp index 07e920ea6..fd4a64ad5 100644 --- a/module/gamefree/bytearray/ByteArray.hpp +++ b/module/gamefree/bytearray/ByteArray.hpp @@ -25,6 +25,10 @@ public: void writeUInt(unsigned int data); + void writeUInt8(unsigned _int8 data); + + void writeUInt16(unsigned _int16 data); + void writeLong(long data); void writeLongLong(long long data); diff --git a/module/gamefree/bytearray/PyByteArray.cpp b/module/gamefree/bytearray/PyByteArray.cpp index 27a396d10..424167a66 100644 --- a/module/gamefree/bytearray/PyByteArray.cpp +++ b/module/gamefree/bytearray/PyByteArray.cpp @@ -20,6 +20,16 @@ PyByteArray& PyByteArray::writeUInt(unsigned int data) { return *this; } +PyByteArray& PyByteArray::writeUInt8(unsigned _int8 data) { + m_data.writeUInt8(data); + return *this; +} + +PyByteArray& PyByteArray::writeUInt16(unsigned _int16 data) { + m_data.writeUInt16(data); + return *this; +} + PyByteArray& PyByteArray::writeLong(long data) { m_data.writeLong(data); return *this; diff --git a/module/gamefree/bytearray/PyByteArray.hpp b/module/gamefree/bytearray/PyByteArray.hpp index cda4a28b6..ddfa8f8cb 100644 --- a/module/gamefree/bytearray/PyByteArray.hpp +++ b/module/gamefree/bytearray/PyByteArray.hpp @@ -15,6 +15,10 @@ public: PyByteArray& writeUInt(unsigned int data); + PyByteArray& writeUInt8(unsigned _int8 data); + + PyByteArray& writeUInt16(unsigned _int16 data); + PyByteArray& writeLong(long data); PyByteArray& writeLongLong(long long data); diff --git a/module/gamefree/bytearray/module.cpp b/module/gamefree/bytearray/module.cpp index ca10a30d3..d5ba7d5c1 100644 --- a/module/gamefree/bytearray/module.cpp +++ b/module/gamefree/bytearray/module.cpp @@ -11,6 +11,8 @@ PYBIND11_MODULE(bytearray, m) { .def("writeUChar", &PyByteArray::writeUChar) .def("writeInt", &PyByteArray::writeInt) .def("writeUInt", &PyByteArray::writeUInt) + .def("writeUInt8", &PyByteArray::writeUInt8) + .def("writeUInt16", &PyByteArray::writeUInt16) .def("writeLong", &PyByteArray::writeLong) .def("writeLongLong", &PyByteArray::writeLongLong) .def("writeULong", &PyByteArray::writeULong) diff --git a/module/gamefree/gamedata.py b/module/gamefree/gamedata.py new file mode 100644 index 000000000..fe04b2694 --- /dev/null +++ b/module/gamefree/gamedata.py @@ -0,0 +1,16 @@ +class AzurLaneGameDataManager: + instance = None + + def __init__(self): + ... + + @staticmethod + def get_instance() -> "AzurLaneGameDataManager": + if AzurLaneGameDataManager.instance is None: + AzurLaneGameDataManager.instance = AzurLaneGameDataManager() + return AzurLaneGameDataManager.instance + + +class AzurLaneGameData: + def __init__(self): + self.game_data = AzurLaneGameDataManager.get_instance() diff --git a/module/gamefree/netpkg.py b/module/gamefree/netpkg.py new file mode 100644 index 000000000..174334cf3 --- /dev/null +++ b/module/gamefree/netpkg.py @@ -0,0 +1,37 @@ +import threading + +from google.protobuf import message +import module.gamefree.bytearray as ba + +class AzurLaneNetworkEndPackage: + ... + + +class AzurLaneNetworkPackage: + + def __init__(self, id, proto_message: message.Message): + self.event = threading.Event() + self.proto_message = proto_message + self.id = id + self.returned_data: bytes = None + + def pack(self) -> bytes: + buffer = ba.ByteArray() + + serialized = self.proto_message.SerializeToString() + serialized_len = len(serialized) + if serialized_len == 0: + buffer.writeUInt16(6) + else: + buffer.writeUInt16(5 + serialized_len) + + buffer.writeUInt8(0) + buffer.writeUInt16(self.id) + buffer.writeUInt16(0) + buffer.writeString(serialized) + + return buffer.toBytes() + + +class HeartBeatPackage: + ... \ No newline at end of file diff --git a/module/gamefree/network.py b/module/gamefree/network.py new file mode 100644 index 000000000..18199b3bb --- /dev/null +++ b/module/gamefree/network.py @@ -0,0 +1,93 @@ +import socket +import threading +import time +from queue import Queue +from module.gamefree.netpkg import * +from module.logger import logger + + +class AzurLaneNetworkClient: + instance = None + + def __init__(self): + self.task_queue = Queue() + self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.worker: threading.Thread = None + self.heartbeater: threading.Thread = None + self.heartbeat_thread_event = threading.Event() + + def __del__(self): + self.stop_work() + + def connect(self, addr, port): + self.server_socket.connect((addr, port)) + + def transfer(self, pkg: AzurLaneNetworkPackage) -> bytes: + self.server_socket.send(pkg.pack()) + buffer = ba.ByteArray() + while 1: + returned_data = self.server_socket.recv(1024) + if returned_data == 0: + break + buffer.writeBytes(returned_data) + return buffer.toBytes() + + def start_heartbeat(self): + if self.heartbeater is not None: + if self.heartbeater.is_alive(): + return + self.heartbeater = threading.Thread(target=self.work_thread) + self.heartbeater.start() + + def start_work(self): + if self.worker is not None: + if self.worker.is_alive(): + return + self.worker = threading.Thread(target=self.work_thread) + self.worker.start() + + def stop_work(self): + self.heartbeat_thread_event.set() + self.task_queue.queue.clear() + self.task_queue.put(AzurLaneNetworkEndPackage()) + + def work_thread(self): + while 1: + pkg = self.task_queue.get() + if isinstance(pkg, AzurLaneNetworkEndPackage): + break + elif isinstance(pkg, AzurLaneNetworkPackage): + data = self.transfer(pkg) + pkg.returned_data = data + pkg.event.set() + else: + logger.warning(f"Unknown net package class: {type(pkg).__name__}") + + def heartbeat_thread(self): + while 1: + if self.heartbeat_thread_event.is_set(): + break + self.task_queue.put(HeartBeatPackage()) + if self.heartbeat_thread_event.is_set(): + break + time.sleep(1) + + def queue_package(self, pkg): + self.task_queue.put(pkg) + + @staticmethod + def get_instance() -> "AzurLaneNetworkClient": + if AzurLaneNetworkClient.instance is None: + AzurLaneNetworkClient.instance = AzurLaneNetworkClient() + return AzurLaneNetworkClient.instance + + +class AzurLaneNetwork: + def __init__(self): + self.client = AzurLaneNetworkClient.get_instance() + + def send(self, pkg: AzurLaneNetworkPackage) -> bytes: + self.client.queue_package(pkg) + pkg.event.wait() + return pkg.returned_data +