Begin port to 26.3: movement
This commit is contained in:
@@ -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
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user