Divide minecraft.networking.types into multiple modules.

This commit is contained in:
joo 2018-06-20 09:54:17 +01:00
parent 201e075591
commit 61598eba75
4 changed files with 150 additions and 108 deletions

View File

@ -0,0 +1,3 @@
from .basic import * # noqa: F401, F403
from .enum import * # noqa: F401, F403
from .utility import * # noqa: F401, F403

View File

@ -5,45 +5,16 @@ These definitions and methods are used by the packet definitions
from __future__ import division
import struct
import uuid
from collections import namedtuple
from .utility import Vector
# NOTE: subclasses of 'Vector' should have '__slots__ = ()' to avoid the
# creation of a '__dict__' attribute, which would waste space.
Vector = namedtuple('Vector', ('x', 'y', 'z'))
class MutableRecord(object):
__slots__ = ()
def __init__(self, **kwds):
for attr, value in kwds.items():
setattr(self, attr, value)
def __repr__(self):
return '%s(%s)' % (type(self).__name__, ', '.join(
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
def __eq__(self, other):
return type(self) is type(other) and \
all(getattr(self, a) == getattr(other, a) for a in self.__slots__)
def __hash__(self):
return hash(getattr(self, a) for a in self.__slots__)
class PositionAndLook(MutableRecord):
__slots__ = 'x', 'y', 'z', 'yaw', 'pitch'
# Access the fields 'x', 'y', 'z' as a Vector.
def position(self, position):
self.x, self.y, self.z = position
position = property(lambda self: Vector(self.x, self.y, self.z), position)
# Access the fields 'yaw', 'pitch' as a tuple.
def look(self, look):
self.yaw, self.pitch = look
look = property(lambda self: (self.yaw, self.pitch), look)
__all__ = (
'Type', 'Boolean', 'UnsignedByte', 'Byte', 'Short', 'UnsignedShort',
'Integer', 'FixedPointInteger', 'VarInt', 'Long', 'UnsignedLong', 'Float',
'Double', 'ShortPrefixedByteArray', 'VarIntPrefixedByteArray',
'TrailingByteArray', 'String', 'UUID', 'Position',
)
class Type(object):
@ -58,9 +29,6 @@ class Type(object):
raise NotImplementedError("Base data type not serializable")
# =========================================================
class Boolean(Type):
@staticmethod
def read(file_object):
@ -317,71 +285,3 @@ class Position(Type, Vector):
x, y, z = position
value = ((x & 0x3FFFFFF) << 38) | ((y & 0xFFF) << 26) | (z & 0x3FFFFFF)
UnsignedLong.send(value, socket)
class Enum(object):
@classmethod
def name_from_value(cls, value):
for name, name_value in cls.__dict__.items():
if name.isupper() and name_value == value:
return name
class BitFieldEnum(Enum):
@classmethod
def name_from_value(cls, value):
if not isinstance(value, int):
return
ret_names = []
ret_value = 0
for cls_name, cls_value in sorted(
[(n, v) for (n, v) in cls.__dict__.items()
if isinstance(v, int) and n.isupper() and v | value == value],
reverse=True, key=lambda p: p[1]
):
if ret_value | cls_value != ret_value or cls_value == value:
ret_names.append(cls_name)
ret_value |= cls_value
if ret_value == value:
return '|'.join(reversed(ret_names)) if ret_names else '0'
# Designation of one of a player's hands, in absolute terms.
class AbsoluteHand(Enum):
LEFT = 0
RIGHT = 1
# Designation of one a player's hands, relative to a choice of main/off hand.
class RelativeHand(Enum):
MAIN = 0
OFF = 1
# Designation of one of a block's 6 faces.
class BlockFace(Enum):
BOTTOM = 0 # -Y
TOP = 1 # +Y
NORTH = 2 # -Z
SOUTH = 3 # +Z
WEST = 4 # -X
EAST = 5 # +X
# A dict mapping Position tuples to the corresponding BlockFace values.
# When accessing this dict, plain tuples also match. For example:
# >>> BlockFace.from_vector[0, 0, -1] == BlockFace.NORTH
# True
from_vector = {
Position(0, -1, 0): BOTTOM,
Position(0, +1, 0): TOP,
Position(0, 0, -1): NORTH,
Position(0, 0, +1): SOUTH,
Position(-1, 0, 0): WEST,
Position(+1, 0, 0): EAST,
}
# A dict mapping BlockFace values to unit Position tuples.
# This is the inverse mapping of face_by_position. For example:
# >>> BlockFace.to_vector[BlockFace.NORTH]
# Position(x=0, y=0, z=-1)
to_vector = {fce: pos for (pos, fce) in from_vector.items()}

View File

@ -0,0 +1,84 @@
"""Types for enumerations of values occurring in packets, including operations
for working with these values.
The values in an enum are given as class attributes with UPPERCASE names.
These classes are usually not supposed to be instantiated, but sometimes an
instantiatable class may subclass Enum to provide class enum attributes in
addition to other functionality.
"""
from .utility import Vector
__all__ = (
'Enum', 'BitFieldEnum', 'AbsoluteHand', 'RelativeHand', 'BlockFace',
)
class Enum(object):
# Return a human-readable string representation of an enum value.
@classmethod
def name_from_value(cls, value):
for name, name_value in cls.__dict__.items():
if name.isupper() and name_value == value:
return name
class BitFieldEnum(Enum):
@classmethod
def name_from_value(cls, value):
if not isinstance(value, int):
return
ret_names = []
ret_value = 0
for cls_name, cls_value in sorted(
[(n, v) for (n, v) in cls.__dict__.items()
if isinstance(v, int) and n.isupper() and v | value == value],
reverse=True, key=lambda p: p[1]
):
if ret_value | cls_value != ret_value or cls_value == value:
ret_names.append(cls_name)
ret_value |= cls_value
if ret_value == value:
return '|'.join(reversed(ret_names)) if ret_names else '0'
# Designation of one of a player's hands, in absolute terms.
class AbsoluteHand(Enum):
LEFT = 0
RIGHT = 1
# Designation of one a player's hands, relative to a choice of main/off hand.
class RelativeHand(Enum):
MAIN = 0
OFF = 1
# Designation of one of a block's 6 faces.
class BlockFace(Enum):
BOTTOM = 0 # -Y
TOP = 1 # +Y
NORTH = 2 # -Z
SOUTH = 3 # +Z
WEST = 4 # -X
EAST = 5 # +X
# A dict mapping Vector tuples to the corresponding BlockFace values.
# When accessing this dict, plain tuples also match. For example:
# >>> BlockFace.from_vector[0, 0, -1] == BlockFace.NORTH
# True
from_vector = {
Vector(0, -1, 0): BOTTOM,
Vector(0, +1, 0): TOP,
Vector(0, 0, -1): NORTH,
Vector(0, 0, +1): SOUTH,
Vector(-1, 0, 0): WEST,
Vector(+1, 0, 0): EAST,
}
# A dict mapping BlockFace values to unit Position tuples.
# This is the inverse mapping of face_by_position. For example:
# >>> BlockFace.to_vector[BlockFace.NORTH]
# Position(x=0, y=0, z=-1)
to_vector = {fce: pos for (pos, fce) in from_vector.items()}

View File

@ -0,0 +1,55 @@
"""Minecraft data types that are used by packets, but don't have a specific
network representation.
"""
from collections import namedtuple
__all__ = (
'Vector', 'MutableRecord', 'PositionAndLook',
)
"""An immutable type usually used to represent 3D spatial coordinates.
NOTE: subclasses of 'Vector' should have '__slots__ = ()' to avoid the
creation of a '__dict__' attribute, which would waste space.
"""
Vector = namedtuple('Vector', ('x', 'y', 'z'))
class MutableRecord(object):
"""An abstract base class providing namedtuple-like repr(), ==, and hash()
implementations for types containing mutable fields given by __slots__.
"""
__slots__ = ()
def __init__(self, **kwds):
for attr, value in kwds.items():
setattr(self, attr, value)
def __repr__(self):
return '%s(%s)' % (type(self).__name__, ', '.join(
'%s=%r' % (a, getattr(self, a)) for a in self.__slots__))
def __eq__(self, other):
return type(self) is type(other) and \
all(getattr(self, a) == getattr(other, a) for a in self.__slots__)
def __hash__(self):
return hash(getattr(self, a) for a in self.__slots__)
class PositionAndLook(MutableRecord):
"""A mutable record containing 3 spatial position coordinates
and 2 rotational coordinates for a look direction.
"""
__slots__ = 'x', 'y', 'z', 'yaw', 'pitch'
# Access the fields 'x', 'y', 'z' as a Vector.
def position(self, position):
self.x, self.y, self.z = position
position = property(lambda self: Vector(self.x, self.y, self.z), position)
# Access the fields 'yaw', 'pitch' as a tuple.
def look(self, look):
self.yaw, self.pitch = look
look = property(lambda self: (self.yaw, self.pitch), look)