character creation partial, misread char select data
This commit is contained in:
parent
285abf1985
commit
6207766662
12
__init__.py
12
__init__.py
|
@ -1,7 +1,15 @@
|
|||
__all__ = "Character", "ClientBase", "Client", "Helpers", "Packet", "iPacket", "oPacket"
|
||||
__all__ = "Character", "ClientBase", "Client", "Helpers", "Packet", "iPacket", "oPacket", "NAMES"
|
||||
|
||||
from .character import Character
|
||||
from .client_base import ClientBase
|
||||
from .client import Client
|
||||
from .packet import Packet, iPacket, oPacket
|
||||
from .packet_helper import Helpers
|
||||
from .packet_helper import Helpers
|
||||
|
||||
NAMES = []
|
||||
|
||||
with open("clb/.names", "r") as f:
|
||||
NAMES.extend([l.rstrip("\n") for l in f.readlines()])
|
||||
|
||||
with open("clb/.words", "r") as f:
|
||||
NAMES.extend([l.rstrip("\n") for l in f.readlines()])
|
||||
|
|
88
client.py
88
client.py
|
@ -1,5 +1,5 @@
|
|||
from random import randint
|
||||
from asyncio import sleep
|
||||
from random import choice, randint
|
||||
from asyncio import sleep, Event, Queue
|
||||
|
||||
from rich import print
|
||||
|
||||
|
@ -12,7 +12,7 @@ from .packet_helper import Helpers
|
|||
|
||||
class Client(ClientBase):
|
||||
|
||||
def __init__(self, loop=None, username=None, password=None):
|
||||
def __init__(self, names=None, loop=None, username=None, password=None):
|
||||
super().__init__(loop)
|
||||
self._username = username
|
||||
self._password = password
|
||||
|
@ -22,6 +22,10 @@ class Client(ClientBase):
|
|||
self._channel_count = 0
|
||||
self._channel_id = 0
|
||||
self._characters = []
|
||||
self._can_login = Event()
|
||||
self._NAMES = names
|
||||
|
||||
self._char_name = ""
|
||||
|
||||
async def begin(self):
|
||||
while self._loop.is_running() and self._sock.fileno():
|
||||
|
@ -48,8 +52,12 @@ class Client(ClientBase):
|
|||
await self.send_packet(opkt)
|
||||
|
||||
@packet_handler(RecvOps.LOGIN_STATUS)
|
||||
async def login_second(self, ipkt: iPacket):
|
||||
ipkt.decode_byte()
|
||||
async def login_first(self, ipkt: iPacket):
|
||||
r1 = ipkt.decode_byte()
|
||||
if r1 != 0:
|
||||
print(f"Login Response code: {r1}")
|
||||
return
|
||||
|
||||
ipkt.decode_byte()
|
||||
ipkt.decode_int()
|
||||
self._account_id = ipkt.decode_int()
|
||||
|
@ -73,6 +81,10 @@ class Client(ClientBase):
|
|||
|
||||
await self.send_packet(oPacket(SendOps.SERVERLIST_REQUEST))
|
||||
|
||||
@packet_handler(RecvOps.LOGIN_SECOND)
|
||||
async def login_second(self, ipkt: iPacket):
|
||||
self._can_login.set()
|
||||
|
||||
@packet_handler(RecvOps.SERVERLIST)
|
||||
async def serverlist(self, ipkt: iPacket):
|
||||
if (world_id := ipkt.decode_byte()) == 0xFF:
|
||||
|
@ -82,7 +94,6 @@ class Client(ClientBase):
|
|||
# self.schedule_action(SendOps.CHARLIST_REQUEST, 3.0)
|
||||
return
|
||||
|
||||
|
||||
world_name = ipkt.decode_string()
|
||||
world_flag = ipkt.decode_byte()
|
||||
event_message = ipkt.decode_string()
|
||||
|
@ -107,6 +118,7 @@ class Client(ClientBase):
|
|||
w_id = ipkt.decode_byte()
|
||||
ch_id = ipkt.decode_short()
|
||||
self._worlds[w_id]["load"] += load
|
||||
self._worlds[w_id]["channels"][ch_id] = {}
|
||||
self._worlds[w_id]["channels"][ch_id]["load"] = load
|
||||
self._worlds[w_id]["channels"][ch_id]["name"] = ch_name
|
||||
|
||||
|
@ -133,13 +145,36 @@ class Client(ClientBase):
|
|||
@packet_handler(RecvOps.CHARLIST)
|
||||
async def char_list(self, ipkt: iPacket):
|
||||
self._characters = Helpers.character_entries(ipkt)
|
||||
await self._can_login.wait()
|
||||
|
||||
if not self._characters: # create char
|
||||
...
|
||||
await self.check_name()
|
||||
else: # login to char
|
||||
...
|
||||
|
||||
print(self._characters)
|
||||
|
||||
@packet_handler(RecvOps.ADD_NEW_CHAR_ENTRY)
|
||||
async def add_new_char(self, ipkt: iPacket):
|
||||
success = ipkt.decode_byte() == 0
|
||||
print(f"Response to character creation: {success}")
|
||||
if not success:
|
||||
return
|
||||
|
||||
self._characters.append(Helpers.character_entry(ipkt))
|
||||
print(self._characters)
|
||||
|
||||
@packet_handler(RecvOps.CHAR_NAME_RESPONSE)
|
||||
async def char_name_resp(self, ipkt: iPacket):
|
||||
name = ipkt.decode_string()
|
||||
taken = ipkt.decode_byte() == 1
|
||||
print(taken, name)
|
||||
if taken:
|
||||
await self.check_name()
|
||||
else:
|
||||
self._char_name = name
|
||||
await self.create_char()
|
||||
|
||||
async def do_login(self):
|
||||
opkt = oPacket(SendOps.LOGIN_PASSWORD)
|
||||
opkt.encode_string(self._username)
|
||||
|
@ -150,8 +185,45 @@ class Client(ClientBase):
|
|||
async def request_char_list(self):
|
||||
opkt = oPacket(SendOps.CHARLIST_REQUEST)
|
||||
opkt.encode_byte(2)
|
||||
self._channel_id = randint(0, self._channel_count - 1)
|
||||
self._channel_id = randint(0, self._channel_count - 1) + 1
|
||||
opkt.encode_byte(self._world_id)
|
||||
opkt.encode_short(self._channel_id)
|
||||
|
||||
await self.send_packet(opkt)
|
||||
|
||||
async def check_name(self):
|
||||
opkt = oPacket(SendOps.CHECK_CHAR_NAME)
|
||||
opkt.encode_string(choice(self._NAMES))
|
||||
await self.send_packet(opkt)
|
||||
|
||||
async def create_char(self):
|
||||
opkt = oPacket(SendOps.CREATE_CHAR)
|
||||
opkt.encode_string(self._char_name)
|
||||
job = 1
|
||||
opkt.encode_int(job) # job
|
||||
opkt.encode_short(0) # dual blade
|
||||
opkt.encode_byte(0) # gender
|
||||
opkt.encode_byte(1) # skin color
|
||||
opkt.encode_byte(8)
|
||||
faces = [20000, 20001, 20002]
|
||||
hairs = [30030, 30020, 30000]
|
||||
hair_colors = [0, 2, 3, 7]
|
||||
eye_colors = [0, 1, 2, 3]
|
||||
shirts = [1040002, 1040006, 1040010]
|
||||
ds_marks = [1012277, 1012278, 1012279, 1012280]
|
||||
shorts = [1060002, 1060006]
|
||||
shoes = [1072001, 1072005, 1072037, 1072038]
|
||||
weapons = [1302000, 1322005, 1312004]
|
||||
opkt.encode_int(choice(faces)) # face
|
||||
opkt.encode_int(choice(hairs)) # hair
|
||||
if job not in [5, 6]:
|
||||
opkt.encode_int(choice(hair_colors)) # hair color
|
||||
opkt.encode_int(choice(eye_colors)) # eye color
|
||||
if job == 6:
|
||||
opkt.encode_int(choice(ds_marks))
|
||||
|
||||
opkt.encode_int(choice(shirts))
|
||||
opkt.encode_int(choice(shorts))
|
||||
opkt.encode_int(choice(shoes))
|
||||
opkt.encode_int(choice(weapons))
|
||||
await self.send_packet(opkt)
|
|
@ -70,7 +70,6 @@ class ClientBase:
|
|||
async def _sock_recv(self):
|
||||
# 51.222.56.169
|
||||
await self._ready.wait()
|
||||
self._recv_size = -1
|
||||
|
||||
while self._loop.is_running():
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from .character import Character
|
||||
from .packet import iPacket
|
||||
from .packet import iPacket, oPacket
|
||||
|
||||
|
||||
class Helpers:
|
||||
|
@ -9,7 +9,7 @@ class Helpers:
|
|||
chars = []
|
||||
ipkt.decode_byte()
|
||||
for i in range(ipkt.decode_byte()):
|
||||
chars.append(Character.fill(Helpers.character_entry(ipkt, view_all)))
|
||||
chars.append(Helpers.character_entry(ipkt, view_all))
|
||||
return chars
|
||||
|
||||
@staticmethod
|
||||
|
@ -23,14 +23,12 @@ class Helpers:
|
|||
|
||||
rank = {}
|
||||
if ranked := ipkt.decode_byte():
|
||||
rank |= {
|
||||
"rank": ipkt.decode_int(),
|
||||
"rank_move": ipkt.decode_int(),
|
||||
"job_rank": ipkt.decode_int(),
|
||||
"job_rank_move": ipkt.decode_int()
|
||||
}
|
||||
rank["rank"] = ipkt.decode_int()
|
||||
rank["rank_move"] = ipkt.decode_int()
|
||||
rank["job_rank"] = ipkt.decode_int()
|
||||
rank["job_rank_move"] = ipkt.decode_int()
|
||||
|
||||
return stats | look_useful | rank
|
||||
return Character.fill(stats | look_useful | rank)
|
||||
|
||||
@staticmethod
|
||||
def character_stats(ipkt: iPacket):
|
||||
|
@ -114,4 +112,4 @@ class Helpers:
|
|||
if marking := ipkt.decode_int():
|
||||
look["demon_marking"] = marking
|
||||
|
||||
return look
|
||||
return look
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pycryptodome==3.14.1
|
||||
Pygments==2.11.2
|
||||
rich==12.0.0
|
||||
rich==12.0.0
|
||||
attrs==21.4.0
|
68
tools.py
68
tools.py
|
@ -1,6 +1,3 @@
|
|||
from asyncio import sleep
|
||||
|
||||
from dataclasses import dataclass, is_dataclass
|
||||
from random import randint
|
||||
|
||||
|
||||
|
@ -50,76 +47,11 @@ def get(iterable, **attrs):
|
|||
return find(predicate, iterable)
|
||||
|
||||
|
||||
def filter_out_to(func, iters, out):
|
||||
new = []
|
||||
|
||||
for item in iters:
|
||||
if func(item):
|
||||
new.append(item)
|
||||
else:
|
||||
out.append(item)
|
||||
|
||||
return new
|
||||
|
||||
|
||||
def first_or_default(list_, f):
|
||||
return next((val for val in list_ if f(val)), None)
|
||||
|
||||
|
||||
def fix_dict_keys(dict_):
|
||||
copy = dict(dict_)
|
||||
|
||||
for key, value in copy.items():
|
||||
if key.isdigit():
|
||||
value = dict_.pop(key)
|
||||
key = int(key)
|
||||
|
||||
if isinstance(value, dict):
|
||||
dict_[key] = fix_dict_keys(value)
|
||||
|
||||
else:
|
||||
dict_[key] = value
|
||||
|
||||
return dict_
|
||||
|
||||
|
||||
def to_string(bytes_):
|
||||
return " ".join([
|
||||
bytes_.hex()[i:i + 2].upper() for i in range(0, len(bytes_.hex()), 2)
|
||||
])
|
||||
|
||||
|
||||
async def wakeup():
|
||||
while True:
|
||||
await sleep(0.01)
|
||||
|
||||
|
||||
def nested_dataclass(*args, **kwargs):
|
||||
|
||||
def wrapper(cls):
|
||||
cls = dataclass(cls, **kwargs)
|
||||
original_init = cls.__init__
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
for name, value in kwargs.items():
|
||||
field_type = cls.__annotations__.get(name, None)
|
||||
|
||||
if is_dataclass(field_type) and isinstance(value, dict):
|
||||
new_obj = field_type(**value)
|
||||
kwargs[name] = new_obj
|
||||
|
||||
original_init(self, *args, **kwargs)
|
||||
|
||||
cls.__init__ = __init__
|
||||
return cls
|
||||
|
||||
return wrapper(args[0]) if args else wrapper
|
||||
|
||||
|
||||
class Manager(list):
|
||||
|
||||
def get(self, search):
|
||||
return first_or_default(self, search)
|
||||
|
||||
def first_or_default(self, func):
|
||||
return next((val for val in self if func(val)), None)
|
||||
|
|
Loading…
Reference in New Issue