Begin port to 26.3: movement

This commit is contained in:
Tanner
2026-11-03 22:48:15 +00:00
parent 891f14b988
commit 59c76471f2
23 changed files with 30692 additions and 478 deletions
+102
View File
@@ -0,0 +1,102 @@
"""Entity and player-list updates for the 26.3 play protocol."""
from munch import Munch
from minecraft.networking.modern import (
AddEntityPacket, EntityPositionSyncPacket, MoveEntityPositionPacket,
MoveEntityPositionRotationPacket, MoveEntityRotationPacket,
PlayerInfoRemovePacket, PlayerInfoUpdatePacket, RemoveEntitiesPacket,
)
from mosfet.info import mobs
class ModernEntityManager:
def __init__(self, global_state):
self.g = global_state
self.g.mobs = self.g.get('mobs') or {}
self.g.players = self.g.get('players') or {}
self.g.objects = self.g.get('objects') or {}
self.g.player_names = self.g.get('player_names') or {}
register = self.g.connection.register_packet_listener
for packet_type, handler in (
(AddEntityPacket, self.handle_add_entity),
(RemoveEntitiesPacket, self.handle_remove_entities),
(MoveEntityPositionPacket, self.handle_move),
(MoveEntityPositionRotationPacket, self.handle_move),
(MoveEntityRotationPacket, self.handle_rotation),
(EntityPositionSyncPacket, self.handle_position_sync),
(PlayerInfoUpdatePacket, self.handle_player_info),
(PlayerInfoRemovePacket, self.handle_player_info_remove),
):
register(handler, packet_type)
def handle_add_entity(self, packet):
name = mobs.MOB_NAMES.get(packet.entity_type_id, 'unknown')
common = dict(entity_id=packet.entity_id, x=packet.x,
y=packet.y, z=packet.z)
if name == 'player':
player_uuid = str(packet.entity_uuid)
self.g.players[packet.entity_id] = Munch(
**common, player_uuid=player_uuid,
yaw=packet.yaw, pitch=packet.pitch)
elif name == 'item':
self.g.objects[packet.entity_id] = Munch(
**common, entity_uuid=str(packet.entity_uuid),
velocity_x=packet.velocity_x * 8000,
velocity_y=packet.velocity_y * 8000,
velocity_z=packet.velocity_z * 8000)
else:
self.g.mobs[packet.entity_id] = Munch(
**common, entity_uuid=str(packet.entity_uuid),
type=packet.entity_type_id, yaw=packet.yaw,
pitch=packet.pitch)
def _entity(self, entity_id):
for collection in (self.g.players, self.g.mobs, self.g.objects):
entity = collection.get(entity_id)
if entity is not None:
return entity
return None
def handle_move(self, packet):
entity = self._entity(packet.entity_id)
if entity is None:
return
entity.x += packet.delta_x
entity.y += packet.delta_y
entity.z += packet.delta_z
if hasattr(packet, 'yaw'):
entity.yaw = packet.yaw
entity.pitch = packet.pitch
def handle_rotation(self, packet):
entity = self._entity(packet.entity_id)
if entity is not None:
entity.yaw = packet.yaw
entity.pitch = packet.pitch
def handle_position_sync(self, packet):
entity = self._entity(packet.entity_id)
if entity is not None:
entity.x, entity.y, entity.z = packet.x, packet.y, packet.z
entity.yaw = packet.yaw
entity.pitch = packet.pitch
def handle_remove_entities(self, packet):
for entity_id in packet.entity_ids:
self.g.players.pop(entity_id, None)
self.g.mobs.pop(entity_id, None)
self.g.objects.pop(entity_id, None)
def handle_player_info(self, packet):
for profile_uuid, name in packet.entries:
if name:
uuid_text = str(profile_uuid)
self.g.player_names[uuid_text] = name
self.g.player_names[name] = profile_uuid
self.g.player_names[name.lower()] = profile_uuid
def handle_player_info_remove(self, packet):
removed = {str(uuid) for uuid in packet.uuids}
for key, value in list(self.g.player_names.items()):
if str(value) in removed or str(key) in removed:
del self.g.player_names[key]
+11 -30
View File
@@ -1,42 +1,23 @@
import os
from math import floor
import json
import time
from math import floor
from minecraft.networking.packets import clientbound, serverbound
from mosfet.protocol import packets
from mosfet.info import blocks, mcdata, mobs
from mosfet import utils
from mosfet.info import blocks
class DataManager:
def __init__(self, directory):
self.blocks = {}
self.blocks_states = {}
self.blocks_properties = {}
"""Compatibility facade over the checked-in Minecraft 26.3 data."""
def __init__(self, directory=None):
self.blocks = mcdata.mcd.blocks
self.blocks_states = dict(blocks.BLOCKS)
self.blocks_properties = dict(blocks.PROPS)
self.registries = {}
self.biomes = {}
self.entity_type = {}
if not os.path.isdir(directory):
raise FileNotFoundError("%s is not a valid directory")
if not os.path.isfile("%s/registries.json"%(directory)):
raise FileNotFoundError("%s is not a valid minecraft data directory")
with open("%s/blocks.json"%(directory)) as f:
blocks = json.loads(f.read())
for x in blocks:
for s in blocks[x]['states']:
self.blocks_states[s['id']] = x
self.blocks_properties[s['id']] = s.get('properties', {})
with open("%s/registries.json"%(directory)) as f:
registries = json.loads(f.read())
#for x in registries["minecraft:biome"]["entries"]:
# self.biomes[registries["minecraft:biome"]["entries"][x]["protocol_id"]] = x
for x in registries["minecraft:entity_type"]["entries"]:
self.entity_type[registries["minecraft:entity_type"]["entries"][x]["protocol_id"]] = x
self.entity_type = {
data['protocol_id']: name
for name, data in mobs.MOBS.items()
}
class ChunksManager:
+39
View File
@@ -0,0 +1,39 @@
"""Chat adapter for the Minecraft 26.3 play protocol."""
import time
from minecraft.networking.modern import (
ChatCommand, ClientboundPlayerChatPacket, ServerboundChatPacket, SystemChat,
)
class ModernChatManager:
def __init__(self, global_state):
self.g = global_state
self.handler = None
self.g.connection.register_packet_listener(
self.handle_player_chat, ClientboundPlayerChatPacket)
def set_handler(self, callback):
self.handler = callback
def handle_player_chat(self, packet):
sender = str(packet.sender)
text = '{}: {}'.format(sender, packet.message)
print('[chat] {}: {}'.format(sender, packet.message), flush=True)
if self.handler:
self.handler(('CHAT', sender, text))
def handle_system_chat(self, packet, message):
if self.handler:
self.handler(('SYSTEM', None, message))
def send(self, message):
if not message:
return
if message.startswith('/'):
self.g.connection.write_packet(
ChatCommand(command=message[1:]), force=True)
else:
packet = ServerboundChatPacket(
message=message, timestamp=int(time.time() * 1000))
self.g.connection.write_packet(packet, force=True)