More packets

This commit is contained in:
Casey 2023-08-26 12:33:31 +03:00
parent f2155a631d
commit 69a00c1a2b
Signed by: hkc
GPG Key ID: F0F6CFE11CDB0960
13 changed files with 138 additions and 45 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ __pycache__/
venv/
state
packets.txt
packets*.txt

View File

@ -9,9 +9,15 @@ MAX_SIZE = 0x400000
async def main(args):
async def main(args: list[str]):
loop = asyncio.get_running_loop()
server = await asyncio.start_server(BTAProxy(args[0], 25565, loop).handle_client, "localhost", 25565)
port: int = 25565
if len(args) >= 2:
port = int(args[1])
server = await asyncio.start_server(BTAProxy(args[0], port, loop).handle_client, "localhost", 25565)
print("listening on", str.join(", ", [str(s.getsockname()) for s in server.sockets]))
print("forwarding to", args[0], port)
async with server:
await server.serve_forever()

View File

@ -15,6 +15,8 @@ class AsyncDataInputStream:
async def read_bytes(self, n: int) -> bytes:
if len(self._buffer) < n:
self._last = (await self._queue.get())
if not self._last:
raise EOFError('empty packet was received')
self._buffer += self._last
out, self._buffer = self._buffer[:n], self._buffer[n:]
return out
@ -76,7 +78,7 @@ class AsyncDataInputStream:
try:
return (await self.read_bytes(size)).decode('utf-8')
except Exception as e:
raise ValueError(f'failed reading string of size {size} in {last}') from e
raise ValueError(f'failed reading string of size {size} in {last!r}') from e
class SyncDataInputStream:
def __init__(self, buffer: bytes):
@ -98,7 +100,7 @@ class SyncDataInputStream:
def read(self) -> int:
if self._cursor >= len(self._buffer):
raise EOFError(f'stream overread in {self._buffer} at {self._cursor}')
raise EOFError(f'stream overread in {self._buffer!r} at {self._cursor}')
self._cursor += 1
return self._buffer[self._cursor - 1]

View File

@ -5,16 +5,22 @@ import time
from bta_proxy.datainputstream import AsyncDataInputStream
from bta_proxy.packets import *
async def inspect_client(queue: Queue, addr: tuple[str, int]):
dis = AsyncDataInputStream(queue)
last_time = time.time()
with open("packets-%s-%d-client.txt" % addr, "w") as f:
while True:
try:
pkt = await Packet.read_packet(dis)
except EOFError:
break
now = time.time()
delta = now - last_time
last_time = now
print(f"{delta*1000:+8.1f}ms {pkt}", file=f)
match pkt.packet_id:
case Packet10Flying.packet_id:
continue
@ -32,12 +38,19 @@ async def inspect_client(queue: Queue, addr: tuple[str, int]):
async def inspect_server(queue: Queue, addr: tuple[str, int]):
dis = AsyncDataInputStream(queue)
last_time = time.time()
with open("packets-%s-%d-server.txt" % addr, "w") as f:
while True:
try:
pkt = await Packet.read_packet(dis)
except EOFError:
break
now = time.time()
delta = now - last_time
last_time = now
print(f"{delta*1000:+8.1f}ms {pkt}", file=f)
match pkt.packet_id:
case Packet50PreChunk.packet_id:
continue

View File

@ -56,5 +56,12 @@ from .packet132setmobspawner import Packet132SetMobSpawner
from .packet39attachentity import Packet39AttachEntity
from .packet35entitynickname import Packet35EntityNickname
from .packet52multiblockchange import Packet52MultiBlockChange
from .packet20statistic import Packet20Statistic
from .packet200statistic import Packet200Statistic
from .packet0keepalive import Packet0KeepAlive
from .packet106transaction import Packet106Transaction
from .packet20namedentityspawn import Packet20NamedEntitySpawn
from .packet107updatecreativeinventory import Packet107UpdateCreativeInventory
from .packet22collect import Packet22Collect
from .packet9respawn import Packet9Respawn
from .packet60explosion import Packet60Explosion
from .packet60explosion import Packet60Explosion

View File

@ -47,9 +47,11 @@ class Packet:
):
match datatype:
case "list", sizekey, *args:
args = args[0] if len(args) == 1 else tuple(args)
length = sizekey if isinstance(try_int(sizekey), int) else fields[sizekey]
return [
await Packet.read_field(stream, args, fields)
for _ in range(fields[sizekey])
for _ in range(length)
]
case "uint":
return await stream.read_uint()
@ -98,8 +100,8 @@ class Packet:
case "itemstack":
return await ItemStack.read_from(stream)
case "itemstack", length_or_key:
if isinstance(length_or_key, int):
items: list[Optional[ItemStack]] = []
if isinstance(length_or_key, int):
for _ in range(length_or_key):
if (item_id := await stream.read_short()) >= 0:
count = await stream.read()
@ -115,7 +117,6 @@ class Packet:
raise KeyError(
f"failed to find {length_or_key} in {fields} to read number of itemstacks"
)
items: list[Optional[ItemStack]] = []
for _ in range(fields[length_or_key]):
if (item_id := await stream.read_short()) >= 0:
count = await stream.read()

View File

@ -0,0 +1,9 @@
from .base import Packet
class Packet106Transaction(Packet, packet_id=106):
__slots__ = ('window_id', 'action_id', 'flag')
FIELDS = [
('window_id', 'ubyte'),
('action_id', 'short'),
('flag', 'bool'),
]

View File

@ -0,0 +1,9 @@
from .base import Packet
class Packet107UpdateCreativeInventory(Packet, packet_id=107):
__slots__ = ('window_id', 'page', 'text')
FIELDS = [
('window_id', 'ubyte'),
('page', 'int'),
('text', 'str'),
]

View File

@ -1,6 +1,6 @@
from .base import Packet
class Packet20Statistic(Packet, packet_id=20):
class Packet200Statistic(Packet, packet_id=200):
__slots__ = ('field_27052_a', 'field_27051')
FIELDS = [
('field_27052_a', 'int'),

View File

@ -0,0 +1,16 @@
from .base import Packet
class Packet20NamedEntitySpawn(Packet, packet_id=20):
__slots__ = ('entity_id', 'name', 'x', 'y', 'z', 'yaw', 'pitch', 'item', 'name', 'color')
FIELDS = [
('entity_id', 'int'),
('name', 'str'),
('x', 'int'),
('y', 'int'),
('z', 'int'),
('yaw', 'byte'),
('pitch', 'byte'),
('item', 'short'),
('name', 'str'),
('color', 'ubyte'),
]

View File

@ -0,0 +1,8 @@
from .base import Packet
class Packet22Collect(Packet, packet_id=22):
__slots__ = ('collected', 'collector')
FIELDS = [
('collected', 'int'),
('collector', 'int'),
]

View File

@ -0,0 +1,13 @@
from .base import Packet
class Packet60Explosion(Packet, packet_id=60):
__slots__ = ('x', 'y', 'z', 'size', 'destroyed_len', 'rel_destroyed', 'is_cannonball')
FIELDS = [
('x', 'double'),
('y', 'double'),
('z', 'double'),
('size', 'float'),
('destroyed_len', 'int'),
('rel_destroyed', ('list', 'destroyed_len', 'list', 3, 'byte')),
('is_cannonball', 'bool'),
]

View File

@ -0,0 +1,8 @@
from .base import Packet
class Packet9Respawn(Packet, packet_id=9):
__slots__ = ('dimension', 'world_type')
FIELDS = [
('dimension', 'byte'),
('world_type', 'byte'),
]