mirror of
https://github.com/ammaraskar/pyCraft.git
synced 2025-02-01 20:41:23 +01:00
Various improvements to utility types:
- Add operations for Vector. - Move some tests into test_utility_types.py. - Add tests for PositionAndLook and Vector.
This commit is contained in:
parent
61598eba75
commit
4b6feda1cb
@ -259,6 +259,7 @@ class UUID(Type):
|
||||
|
||||
|
||||
class Position(Type, Vector):
|
||||
"""3D position vectors with a specific, compact network representation."""
|
||||
__slots__ = ()
|
||||
|
||||
@staticmethod
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Minecraft data types that are used by packets, but don't have a specific
|
||||
network representation.
|
||||
"""
|
||||
from __future__ import division
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
@ -9,11 +10,43 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
"""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 Vector(namedtuple('BaseVector', ('x', 'y', 'z'))):
|
||||
"""An immutable type usually used to represent 3D spatial coordinates,
|
||||
supporting elementwise vector addition, subtraction, and negation; and
|
||||
scalar multiplication and (right) division.
|
||||
|
||||
NOTE: subclasses of 'Vector' should have '__slots__ = ()' to avoid the
|
||||
creation of a '__dict__' attribute, which would waste space.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
def __add__(self, other):
|
||||
return NotImplemented if not isinstance(other, Vector) else \
|
||||
type(self)(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
|
||||
def __sub__(self, other):
|
||||
return NotImplemented if not isinstance(other, Vector) else \
|
||||
type(self)(self.x - other.x, self.y - other.y, self.z - other.z)
|
||||
|
||||
def __neg__(self):
|
||||
return type(self)(-self.x, -self.y, -self.z)
|
||||
|
||||
def __mul__(self, other):
|
||||
return type(self)(self.x*other, self.y*other, self.z*other)
|
||||
|
||||
def __rmul__(self, other):
|
||||
return type(self)(other*self.x, other*self.y, other*self.z)
|
||||
|
||||
def __truediv__(self, other):
|
||||
return type(self)(self.x/other, self.y/other, self.z/other)
|
||||
|
||||
def __floordiv__(self, other):
|
||||
return type(self)(self.x//other, self.y//other, self.z//other)
|
||||
|
||||
__div__ = __floordiv__
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r)' % (type(self).__name__, self.x, self.y, self.z)
|
||||
|
||||
|
||||
class MutableRecord(object):
|
||||
@ -34,8 +67,12 @@ class MutableRecord(object):
|
||||
return type(self) is type(other) and \
|
||||
all(getattr(self, a) == getattr(other, a) for a in self.__slots__)
|
||||
|
||||
def __neq__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(getattr(self, a) for a in self.__slots__)
|
||||
values = tuple(getattr(self, a, None) for a in self.__slots__)
|
||||
return hash((type(self), values))
|
||||
|
||||
|
||||
class PositionAndLook(MutableRecord):
|
||||
|
@ -7,7 +7,7 @@ from random import choice
|
||||
from minecraft import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from minecraft.networking.connection import ConnectionContext
|
||||
from minecraft.networking.types import (
|
||||
VarInt, Enum, BitFieldEnum, Vector, PositionAndLook
|
||||
VarInt, Enum, Vector, PositionAndLook
|
||||
)
|
||||
from minecraft.networking.packets import (
|
||||
Packet, PacketBuffer, PacketListener, KeepAlivePacket, serverbound,
|
||||
@ -142,43 +142,6 @@ class PacketEnumTest(unittest.TestCase):
|
||||
'0x00 ExamplePacket(alpha=ZERO, beta=0, gamma=0)')
|
||||
|
||||
|
||||
class EnumTest(unittest.TestCase):
|
||||
def test_enum(self):
|
||||
class Example(Enum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
THREE = 3
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example.name_from_value, range(5))),
|
||||
[None, 'ONE', 'TWO', 'THREE', None])
|
||||
|
||||
|
||||
class BitFieldEnumTest(unittest.TestCase):
|
||||
def test_name_from_value(self):
|
||||
class Example1(BitFieldEnum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
FOUR = 4
|
||||
ALL = 7
|
||||
NONE = 0
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example1.name_from_value, range(9))),
|
||||
['NONE', 'ONE', 'TWO', 'ONE|TWO', 'FOUR',
|
||||
'ONE|FOUR', 'TWO|FOUR', 'ALL', None])
|
||||
|
||||
class Example2(BitFieldEnum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
FOUR = 4
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example2.name_from_value, range(9))),
|
||||
['0', 'ONE', 'TWO', 'ONE|TWO', 'FOUR',
|
||||
'ONE|FOUR', 'TWO|FOUR', 'ONE|TWO|FOUR', None])
|
||||
|
||||
|
||||
class TestReadWritePackets(unittest.TestCase):
|
||||
maxDiff = None
|
||||
|
||||
|
71
tests/test_utility_types.py
Normal file
71
tests/test_utility_types.py
Normal file
@ -0,0 +1,71 @@
|
||||
import unittest
|
||||
|
||||
from minecraft.networking.types import (
|
||||
Enum, BitFieldEnum, Vector, Position, PositionAndLook
|
||||
)
|
||||
|
||||
|
||||
class EnumTest(unittest.TestCase):
|
||||
def test_enum(self):
|
||||
class Example(Enum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
THREE = 3
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example.name_from_value, range(5))),
|
||||
[None, 'ONE', 'TWO', 'THREE', None])
|
||||
|
||||
|
||||
class BitFieldEnumTest(unittest.TestCase):
|
||||
def test_name_from_value(self):
|
||||
class Example1(BitFieldEnum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
FOUR = 4
|
||||
ALL = 7
|
||||
NONE = 0
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example1.name_from_value, range(9))),
|
||||
['NONE', 'ONE', 'TWO', 'ONE|TWO', 'FOUR',
|
||||
'ONE|FOUR', 'TWO|FOUR', 'ALL', None])
|
||||
|
||||
class Example2(BitFieldEnum):
|
||||
ONE = 1
|
||||
TWO = 2
|
||||
FOUR = 4
|
||||
|
||||
self.assertEqual(
|
||||
list(map(Example2.name_from_value, range(9))),
|
||||
['0', 'ONE', 'TWO', 'ONE|TWO', 'FOUR',
|
||||
'ONE|FOUR', 'TWO|FOUR', 'ONE|TWO|FOUR', None])
|
||||
|
||||
|
||||
class VectorTest(unittest.TestCase):
|
||||
def test_operators(self):
|
||||
self.assertEqual(Vector(1, -2, 0) + Vector(0, 1, 2), Vector(1, -1, 2))
|
||||
self.assertEqual(Vector(1, -2, 0) - Vector(0, 1, 2), Vector(1, -3, -2))
|
||||
self.assertEqual(-Vector(1, -2, 0), Vector(-1, 2, 0))
|
||||
self.assertEqual(Vector(1, -2, 0) * 2, Vector(2, -4, 0))
|
||||
self.assertEqual(2 * Vector(1, -2, 0), Vector(2, -4, 0))
|
||||
self.assertEqual(Vector(1, -2, 0) / 2, Vector(1/2, -2/2, 0/2))
|
||||
self.assertEqual(Vector(1, -2, 0) // 2, Vector(0, -1, 0))
|
||||
|
||||
def test_repr(self):
|
||||
self.assertEqual(str(Vector(1, 2, 3)), 'Vector(1, 2, 3)')
|
||||
self.assertEqual(str(Position(1, 2, 3)), 'Position(1, 2, 3)')
|
||||
|
||||
|
||||
class PositionAndLookTest(unittest.TestCase):
|
||||
""" This also tests the MutableRecord base type. """
|
||||
def test_properties(self):
|
||||
pos_look_1 = PositionAndLook(position=(1, 2, 3), look=(4, 5))
|
||||
pos_look_2 = PositionAndLook(x=1, y=2, z=3, yaw=4, pitch=5)
|
||||
string_repr = 'PositionAndLook(x=1, y=2, z=3, yaw=4, pitch=5)'
|
||||
|
||||
self.assertEqual(pos_look_1, pos_look_2)
|
||||
self.assertEqual(pos_look_1.position, pos_look_1.position)
|
||||
self.assertEqual(pos_look_1.look, pos_look_2.look)
|
||||
self.assertEqual(hash(pos_look_1), hash(pos_look_2))
|
||||
self.assertEqual(str(pos_look_1), string_repr)
|
Loading…
Reference in New Issue
Block a user