Skip to content

Commit

Permalink
The packet for the current version of Server List Ping are now build …
Browse files Browse the repository at this point in the history
…using BasePacket class
  • Loading branch information
Lucino772 committed Apr 26, 2021
1 parent e16effb commit 883434d
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 107 deletions.
Empty file.
17 changes: 17 additions & 0 deletions mojang/api/net/slp/packets/current.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from ...common.packet import BasePacket
from ...common.types import *
from .types import *

class SLPCurrentHandshakePacket(BasePacket):
packet_id: int = VarInt(default=0x00)
proto_version: int = VarInt()
server_address: str = String()
server_port: int = BigEndianShort(signed=False)
next_state: int = VarInt()

class SLPCurrentRequestPacket(BasePacket):
packet_id: int = VarInt(default=0x00)

class SLPCurrentResponsePacket(BasePacket):
packet_id: int = VarInt()
response: dict = JSONString()
11 changes: 11 additions & 0 deletions mojang/api/net/slp/packets/ping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from ...common.packet import BasePacket
from ...common.types import *
from .types import *

class SLPPingPacket(BasePacket):
packet_id: int = VarInt(default=0x01)
payload: int = BigEndianInt64()

class SLPPongPacket(BasePacket):
packet_id: int = VarInt()
payload: int = BigEndianInt64()
93 changes: 93 additions & 0 deletions mojang/api/net/slp/packets/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from typing import IO
import struct
import json
from ...common.types import Type, BigEndianShort

## VarTypes ##
class VarType(Type):
_python_type = int

def __new__(cls, default=0, **kwargs):
return super().__new__(cls, default=default, **kwargs)

def __init_subclass__(cls, nbytes: int):
cls.__nbytes = nbytes

def check_value(self, value: int):
if not isinstance(value, int):
raise TypeError('Wrong type, got `{}` expect `int`'.format(type(value).__name__))

@property
def size(self):
return self.__nbytes

def read(self, buffer: IO):
val = 0

for i in range(self.__nbytes):
byte = buffer.read(1)
if len(byte) == 0:
break

val |= (ord(byte) & 0x7f) << (7*i)

if ord(byte) & 0x80 == 0:
break

return val

def write(self, value: int, buffer: IO):
while True:
byte = value & 0x7f
value >>= 7

if value > 0:
byte |= 0x80

buffer.write(struct.pack('B', byte))

if value == 0:
break


class VarInt(VarType, nbytes=5):
pass

class VarLong(VarType, nbytes=10):
pass

## Other ##
class String(Type):
_python_type = str

def __new__(cls, default='', encoding='utf-8', **kwargs):
obj = super().__new__(cls, default=default, **kwargs)
obj.__encoding = encoding
return obj

@property
def encoding(self):
return self.__encoding

def check_value(self, value: str):
if not isinstance(value, str):
raise TypeError('Wrong type, got `{}` expect `str`'.format(type(value).__name__))

def read(self, buffer: IO):
length = VarInt().read(buffer)
return buffer.read(length).decode(self.__encoding)

def write(self, value: str, buffer: IO):
self.check_value(value)
VarInt().write(len(value), buffer)
buffer.write(value.encode(self.__encoding))

class JSONString(String):
_python_type = dict

def read(self, buffer: IO):
return json.loads(super().read(buffer))

def write(self, value: dict, buffer: IO):
text = json.dumps(value)
super().write(text, buffer)
82 changes: 35 additions & 47 deletions mojang/api/net/slp/slp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,47 @@
import struct
import time

from .utils import *

from .packets.types import VarInt
from .packets.current import SLPCurrentHandshakePacket, SLPCurrentRequestPacket, SLPCurrentResponsePacket
from .packets.ping import SLPPingPacket, SLPPongPacket

def _slp_current(sock: socket.socket, hostname='localhost', port=25565):
## Prepare and send handshake
buffer = io.BytesIO()
_write_varint(0x00, buffer)
_write_varint(0x00, buffer)
_write_string(hostname, buffer)
_write_short(port,buffer)
_write_varint(0x01,buffer)

with sock.makefile('wb') as fp:
_write_varint(len(buffer.getvalue()), fp)
fp.write(buffer.getvalue())

## Receive server info
buffer = io.BytesIO()
_write_varint(0x00, buffer)

with sock.makefile('wb') as fp:
_write_varint(len(buffer.getvalue()), fp)
fp.write(buffer.getvalue())

with sock.makefile('rb') as fp:
packet_length = _read_varint(fp)
packet_id = _read_varint(fp)
data = json.loads(_read_string(fp))

## Ping
buffer = io.BytesIO()
_write_varint(0x01, buffer)
_write_long(int(time.time() * 1000), buffer)

with sock.makefile('wb') as fp:
_write_varint(len(buffer.getvalue()), fp)
fp.write(buffer.getvalue())

with sock.makefile('rb') as fp:
packet_length = _read_varint(fp)
packet_id = _read_varint(fp)
itime = _read_long(fp)
# Send handshake
packet = SLPCurrentHandshakePacket(proto_version=0, server_address=hostname, server_port=port, next_state=0x01)
with sock.makefile('wb') as buffer:
VarInt().write(len(packet.data), buffer)
packet.write(buffer)

ping = int(time.time() * 1000) - itime
# Send request
packet = SLPCurrentRequestPacket()
with sock.makefile('wb') as buffer:
VarInt().write(len(packet.data), buffer)
packet.write(buffer)

# Receive response
with sock.makefile('rb') as buffer:
length = VarInt().read(buffer)
rpacket = SLPCurrentResponsePacket.from_bytes(buffer.read(length))

# Ping-Pong
packet = SLPPingPacket(payload=int(time.time() * 1000))
with sock.makefile('wb') as buffer:
VarInt().write(len(packet.data), buffer)
packet.write(buffer)

with sock.makefile('rb') as buffer:
length = VarInt().read(buffer)
pong_packet = SLPPongPacket.from_bytes(buffer.read(length))

return {
'protocol_version': data['version']['protocol'],
'version': data['version']['name'],
'motd': data['description']['text'],
'protocol_version': int(rpacket.response['version']['protocol']),
'version': rpacket.response['version']['name'],
'motd': rpacket.response['description']['text'],
'players': {
'count': (data['players']['online'], data['players']['max']),
'list': data['players'].get('sample', []),
'count': (int(rpacket.response['players']['online']), int(rpacket.response['players']['max'])),
'list': rpacket.response['players'].get('sample', [])
},
'ping': ping
'ping': int(time.time() * 1000) - pong_packet.payload
}

def _slp_1_6(sock: socket.socket, hostname='localhost', port=25565):
Expand Down
60 changes: 0 additions & 60 deletions mojang/api/net/slp/utils.py

This file was deleted.

0 comments on commit 883434d

Please sign in to comment.