import json
# src.sealmc... if you clone this repo
from src.sealmc.fkrystal.pythonmc import PythonMC
from src.sealmc.fkrystal.pythonmc.packet import Packet
from src.sealmc.fkrystal.pythonmc.handler import PacketHandler
from src.sealmc.fkrystal.pythonmc.mctypes import MinecraftTypes
# or if you install with pip or uv...
from sealmc.fkrystal.pythonmc import PythonMC
from sealmc.fkrystal.pythonmc.packet import Packet
from sealmc.fkrystal.pythonmc.handler import PacketHandler
from sealmc.fkrystal.pythonmc.mctypes import MinecraftTypes
# ==========================================
# Add your packet structure
# ==========================================
# https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshaking
class HandshakePacket(Packet):
def __init__(self, ver=0, addr="", port=25565, state=1):
super().__init__()
self.ver = ver
self.addr = addr
self.state = state
@classmethod
def _decode_body(cls, stream):
return cls(MinecraftTypes.read_varint(stream), MinecraftTypes.read_string(stream), MinecraftTypes.read_ushort(stream), MinecraftTypes.read_varint(stream))
def __repr__(self): return f"<Handshake Protocol={self.ver} Intent={self.state}>"
# https://minecraft.wiki/w/Java_Edition_protocol/Packets#Login
class LoginStartPacket(Packet):
def __init__(self, name=""):
super().__init__()
self.name = name
@classmethod
def _decode_body(cls, stream):
return cls(MinecraftTypes.read_string(stream))
class LoginDisconnectPacket(Packet):
def __init__(self, text):
super().__init__()
self.text = text
def encode(self):
data = {"text": self.text, "color": "red"}
return MinecraftTypes.write_string(json.dumps(data))
# https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
class StatusRequestPacket(Packet):
# ID 0x00 in State 1
def __init__(self): super().__init__()
@classmethod
def _decode_body(cls, stream): return cls()
class PingPacket(Packet):
# ID 0x01 in State 1
def __init__(self, payload=0):
super().__init__()
self.payload = payload
@classmethod
def _decode_body(cls, stream): return cls(MinecraftTypes.read_long(stream))
def encode(self): return MinecraftTypes.write_long(self.payload)
class StatusResponsePacket(Packet):
# We only send this, never receive it
def __init__(self, json_dict):
super().__init__()
self.data = json.dumps(json_dict)
def encode(self): return MinecraftTypes.write_string(self.data)
# ==========================================
# Packet Handler
# ==========================================
class MyHandshakeHandler(PacketHandler):
def handle_0x00(self, p: HandshakePacket):
print(f"Handshake from {p.addr} -> Requesting State {p.state}")
print(f"[DEBUG]", p)
self.conn.switch_state(p.state)
return self.server.get_handler_for_state(p.state, self.conn)
class MyLoginHandler(PacketHandler):
def handle_0x00(self, p: LoginStartPacket):
print(f"Login Attempt: {p.name}")
# Kick them using our custom packet
self.conn.send_packet(LoginDisconnectPacket(f"Welcome {p.name} (Login test)"))
return self
class MyTransferHandler(PacketHandler):
def handle_0x00(self, p: LoginStartPacket):
print(f"Transfer Attempt: {p.name}")
# Kick them using our custom packet
self.conn.send_packet(LoginDisconnectPacket(f"Welcome {p.name} (Transfer test)"))
return self
class MyStatusHandler(PacketHandler):
def handle_0x00(self, p: StatusRequestPacket):
# 1. Received Request -> Send JSON Response
status = {
"version": {"name": "PythonMC", "protocol": 47},
"players": {"max": 100, "online": 1},
"description": {"text": "Powered by Python!"}
}
self.conn.send_packet(StatusResponsePacket(status))
return self
def handle_0x01(self, p: PingPacket):
# 2. Received Ping -> Send Pong
print(f"Ping: {p.payload}")
self.conn.send_packet(PingPacket(p.payload))
return self
app = PythonMC(port=25565)
# Register Packets (State, ID, Class)
app.register_packet(0, 0x00, HandshakePacket)
app.register_packet(1, 0x00, StatusRequestPacket)
app.register_packet(1, 0x01, PingPacket)
app.register_packet(2, 0x00, LoginStartPacket)
app.register_packet(3, 0x00, LoginStartPacket)
# Register Logic Handlers
app.set_handshake_state_handler(0, MyHandshakeHandler)
app.set_handshake_state_handler(1, MyStatusHandler)
app.set_handshake_state_handler(2, MyLoginHandler)
app.set_handshake_state_handler(3, MyTransferHandler)
if __name__ == "__main__":
app.run()-
Notifications
You must be signed in to change notification settings - Fork 0
A simple framework for simulating Minecraft: Java Edition server protocol.
License
thenoppy12/PythonMC
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
About
A simple framework for simulating Minecraft: Java Edition server protocol.